背景:
http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_03.html
昨天做测试的时候遇到一个问题,做好的SWF在Flash AS3中调试通过,但是发布到html中之后就无法得到数据了。查了一些资料之后找到了解决办法。这里感谢 剑心 提供帮助,以及同事若水三千提供Java代码及日志记录。
1、问题描述
将flash发布为html格式后,加载页面后,swf无法与服务器进行socket通信。Flash端显示的错误为:
securityErrorHandler信息: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"]
在服务器端显示的信息是由客户端尝试进行连接,但是无法接受数据。接受的数据显示为空。
本日志由 flyinweb 于 2009-09-14 16:42:21 发表到 WEB应用开发 中,目前已经被浏览 632 次,评论 0 次;
作者添加了以下标签: crossdomain,flex;
首页只显示了部分日志内容,要查看日志的全部内容请阅读全文;
操作系统:Linux
安装及配置eaccelerator-0.9.5加速PHP-5.2.1
Comet is a programming technique that enables web servers to send data to the client without having any need for the client to request it. This technique will produce more responsive applications than classic AJAX. In classic AJAX applications, web browser (client) cannot be notified in real time that the server data model has changed. The user must create a request (for example by clicking on a link) or a periodic AJAX request must happen in order to get new data fro the server.
I will now explain how to implement Comet with PHP programming language. I will demonstrate it on two demos which uses two techniques: the first one is based on hidden ”<iframe>” and the second one is based on classic AJAX non-returning request. The first demo will simply show the server date in real time on the clients and the second demo will display a mini-chat.
About SendEmail
SendEmail is a lightweight, command line SMTP email client. If you have the need to send email from a command line, this free program is perfect: simple to use and feature rich. It was designed to be used in bash scripts, batch files, Perl programs and web sites, but is quite adaptable and will likely meet your requirements. SendEmail is written in Perl and is unique in that it requires NO MODULES. It has an intuitive and flexible set of command-line options, making it very easy to learn and use.
[Supported Platforms: Linux, BSD, OS X, Windows 98, Windows NT, Windows 2000, & Windows XP]
Download
提交页面
- <html>
- <body>
- <script language="javascript">
- var oXMLDoc = new ActiveXObject("Microsoft.XMLDOM"); //创建'MSXML'对象
- oXMLDoc.async = true;
- var theUniqueID= 0;
- var iTimerID=null; //这个变量是作定时器的ID
- //让数据提交的同时执行显示进度条的函数
- function UploadData()
- {
- theUniqueID = (new Date()).getTime() % 1000000000;
- // 清除原始数据
- PercentDone.style.width = "0%";
- ElapsedTime.innerHTML = "";
- TimeLeft.innerHTML = "";
- SizeCompleted.innerHTML = "";
- TotalSize.innerHTML = "";
- TransferRate.innerHTML = "";
- document.myform.action = "demo.asp?ProgressID=" + theUniqueID; //处理上传数据的程序
- //将提交的数据放在一个名字是upload隐藏的iframe里面处理,这样提交的页面就不会跳转到处理数据的页
- document.myform.target="upload"
- document.myform.submit(); //提交表单
- ProgressBar(); //开始执行反映上传情况的函数
- }
- function ProgressBar()
- {
- sURL = "Progress_Xml.asp?ProgressID=" + theUniqueID + "&temp="+Math.random(); //获取上传状态数据的地址
- oXMLDoc.onreadystatechange = Function( "fnLoadComplete();" );
- oXMLDoc.load( sURL );
- }
- function fnLoadComplete()
- {
- var iReadyState;
- try
- {
- iReadyState = oXMLDoc.readyState;
- }
- catch(e)
- {
- return;
- }
- if( iReadyState != 4 ) return;
- if( oXMLDoc == null || oXMLDoc.xml == "" )
- {
- window.status = 'Xml load fault';
- return;
- }
- var oRoot = oXMLDoc.documentElement; //获取返回xml数据的根节点
- if(oRoot != null)
- {
- if (oRoot.selectSingleNode("ErrorMessage") == null)
- {
- var readyState = oRoot.selectSingleNode("ReadyState").text;
- // 如果还没初始化完成,继续
- if ( readyState == "uninitialized" )
- {
- iTimerID = setTimeout("ProgressBar()", 1000);
- }
- // 上传进行中
- else if ( readyState == "loading" ) //文件上传结束就取消定时器
- {
- bar1.style.display = 'block'; //让显示上传进度显示的层的可见
- PercentDone.style.width = oRoot.selectSingleNode("Percentage").text; //设置进度条的百分比例
- //根据返回的数据在客户端显示
- ElapsedTime.innerHTML = oRoot.selectSingleNode("ElapsedTime").text; //显示剩余时间
- TimeLeft.innerHTML = oRoot.selectSingleNode("TimeLeft").text; //显示剩余时间
- SizeCompleted.innerHTML = oRoot.selectSingleNode("SizeCompleted").text; //已上传数据大小
- TotalSize.innerHTML = oRoot.selectSingleNode("TotalSize").text; //总大小
- TransferRate.innerHTML=oRoot.selectSingleNode("TransferRate").text; //传输速率
- //这里设定时间间隔是0.5秒,你也可以根据你的情况修改获取数据时间间隔
- iTimerID = setTimeout("ProgressBar()", 100);
- }
- // 上传结束
- else if ( readyState == "loaded" )
- {
- PercentDone.style.width = "100%"; //设置进度条的百分比例
- if (iTimerID != null)
- clearTimeout(iTimerID)
- iTimerID = null;
- alert("上传结束,服务器处理中...");
- }
- // 上传结束
- else
- {
- PercentDone.style.width = "100%"; //设置进度条的百分比例
- if (iTimerID != null)
- clearTimeout(iTimerID)
- iTimerID = null;
- alert("上传结束");
- }
- }
- else
- {
- alert(oRoot.selectSingleNode("ErrorMessage").text);
- upload.location.href = "about:blank";
- }
- }
- }
- function CacelUpload()
- {
- upload.location.href = "about:blank";
- if (iTimerID != null)
- clearTimeout(iTimerID)
- iTimerID = null;
- bar1.style.display = '';
- }
- </script>
- <base target="_blank">
- <form name="myform" method="post" action="demo.asp" enctype="multipart/form-data" target="upload">
- <h2>Asp无组件上传带进度条 </h2>
- <HR>
- 上传测试:<BR>
- <input type="file" name="filefield1">(请上传小于10MB的文件)<br>
- <input type="button" value="上传" onclick="UploadData()">
- <input type="button" value="取消上传" onclick="CacelUpload()"><br>
- <div id=bar1 style="display:">
- <table border="0" width="100%">
- <tr>
- <td><b>传送:</b></td>
- </tr>
- <tr bgcolor="#999999">
- <td>
- <table border="0" width="" cellspacing="1" bgcolor="#0033FF" id="PercentDone">
- <tr>
- <td> </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td>
- <table border="0" cellpadding="0" cellspacing="0">
- <tr><td>总 大 小: </td><td id="TotalSize"></td></tr>
- <tr><td>已经上传: </td><td id="SizeCompleted"></td></tr>
- <tr><td>平均速率:</td><td id="TransferRate"></td></tr>
- <tr><td>使用时间:</td><td id="ElapsedTime"></td></tr>
- <tr><td>剩余时间:</td><td id="TimeLeft"></td></tr>
- </table>
- </td>
- </tr>
- </table>
- </div>
- <iframe name="upload" style="width:100%"></iframe>
- </form>
- </body>
- </html>
demo.asp
- <!-- #include file="Upload.asp" -->
- <%
- Server.ScriptTimeout = 9999
- set Upload = new DoteyUpload
- Upload.MaxTotalBytes = 10 *1024 *1024 ' 最大10MB
- Upload.ProgressID = Request.QueryString("ProgressID")
- Upload.Upload() '上传演示,不保存到硬盘
- If Request.TotalBytes > 10 *1024 *1024 Then
- Response.Write "不要上传超过10MB的文件"
- Response.End
- End If
- if Upload.ErrMsg <> "" then
- Response.Write(Upload.ErrMsg)
- Response.End()
- end if
- if Upload.Files.Count > 0 then
- Items = Upload.Files.Items
- end if
- Response.Write("您已上传 " & Upload.Files.Count & " 个文件到: " & path & "<hr>")
- for each File in Upload.Files.Items
- Response.Write("文件名: " & File.FileName & "<br>")
- Response.Write("文件大小: " & File.FileSize/1024 & " KB<br>")
- Response.Write("文件类型: " & File.FileType & "<br>")
- Response.Write("客户端路径: " & File.FilePath & "<br>")
- Response.Write("<hr>")
- next
- Response.Write("<br>")
- %>
upload.asp
- <%
- '-----------------------------------------------------
- ' 描述: Asp无组件上传带进度条
- ' 作者: 宝玉(www.webuc.net)
- ' 链接: www.pspsoft.com, www.cnforums.net, blog.joycode.com, www.cnblogs.com, www.51js.com
- ' 版本: 1.0 Beta
- ' 版权: 本作品可免费使用,但是请勿移除版权信息
- ' 推荐: asp.net上传组件(http://www.upload4asp.net/)
- '-----------------------------------------------------
- Dim DoteyUpload_SourceData
- Class DoteyUpload
- Public Files
- Public Form
- Public MaxTotalBytes
- Public Version
- Public ProgressID
- Public ErrMsg
- Private BytesRead
- Private ChunkReadSize
- Private Info
- Private Progress
- Private UploadProgressInfo
- Private CrLf
- Private Sub Class_Initialize()
- Set Files = Server.CreateObject("Scripting.Dictionary") ' 上传文件集合
- Set Form = Server.CreateObject("Scripting.Dictionary") ' 表单集合
- UploadProgressInfo = "DoteyUploadProgressInfo" ' Application的Key
- MaxTotalBytes = 1 *1024 *1024 *1024 ' 默认最大1G
- ChunkReadSize = 64 * 1024 ' 分块大小64K
- CrLf = Chr(13) & Chr(10) ' 换行
- Set DoteyUpload_SourceData = Server.CreateObject("ADODB.Stream")
- DoteyUpload_SourceData.Type = 1 ' 二进制流
- DoteyUpload_SourceData.Open
- Version = "1.0 Beta" ' 版本
- ErrMsg = "" ' 错误信息
- Set Progress = New ProgressInfo
- End Sub
- ' 将文件根据其文件名统一保存在某路径下
- Public Sub SaveTo(path)
- Upload() ' 上传
- if right(path,1) <> "/" then path = path & "/"
- ' 遍历所有已上传文件
- For Each fileItem In Files.Items
- fileItem.SaveAs path & fileItem.FileName
- Next
- ' 保存结束后更新进度信息
- Progress.ReadyState = "complete" '上传结束
- UpdateProgressInfo progressID
- End Sub
- ' 分析上传的数据,并保存到相应集合中
- Public Sub Upload ()
- Dim TotalBytes, Boundary
- TotalBytes = Request.TotalBytes ' 总大小
- If TotalBytes < 1 Then
- Raise("无数据传入")
- Exit Sub
- End If
- If TotalBytes > MaxTotalBytes Then
- Raise("您当前上传大小为" & TotalBytes/1000 & " K,最大允许为" & MaxTotalBytes/1024 & "K")
- Exit Sub
- End If
- Boundary = GetBoundary()
- If IsNull(Boundary) Then
- Raise("如果form中没有包括multipart/form-data上传是无效的")
- Exit Sub ''如果form中没有包括multipart/form-data上传是无效的
- End If
- Boundary = StringToBinary(Boundary)
- Progress.ReadyState = "loading" '开始上传
- Progress.TotalBytes = TotalBytes
- UpdateProgressInfo progressID
- Dim DataPart, PartSize
- BytesRead = 0
- '循环分块读取
- Do While BytesRead < TotalBytes
- '分块读取
- PartSize = ChunkReadSize
- if PartSize + BytesRead > TotalBytes Then PartSize = TotalBytes - BytesRead
- DataPart = Request.BinaryRead(PartSize)
- BytesRead = BytesRead + PartSize
- DoteyUpload_SourceData.Write DataPart
- Progress.UploadedBytes = BytesRead
- Progress.LastActivity = Now()
- ' 更新进度信息
- UpdateProgressInfo progressID
- Loop
- ' 上传结束后更新进度信息
- Progress.ReadyState = "loaded" '上传结束
- UpdateProgressInfo progressID
- Dim Binary
- DoteyUpload_SourceData.Position = 0
- Binary = DoteyUpload_SourceData.Read
- Dim BoundaryStart, BoundaryEnd, PosEndOfHeader, IsBoundaryEnd
- Dim Header, bFieldContent
- Dim FieldName
- Dim File
- Dim TwoCharsAfterEndBoundary
- BoundaryStart = InStrB(Binary, Boundary)
- BoundaryEnd = InStrB(BoundaryStart + LenB(Boundary), Binary, Boundary, 0)
- Do While (BoundaryStart > 0 And BoundaryEnd > 0 And Not IsBoundaryEnd)
- ' 获取表单头的结束位置
- PosEndOfHeader = InStrB(BoundaryStart + LenB(Boundary), Binary, StringToBinary(vbCrLf + vbCrLf))
- ' 分离表单头信息,类似于:
- ' Content-Disposition: form-data; name="file1"; filename="G:\homepage.txt"
- ' Content-Type: text/plain
- Header = BinaryToString(MidB(Binary, BoundaryStart + LenB(Boundary) + 2, PosEndOfHeader - BoundaryStart - LenB(Boundary) - 2))
- ' 分离表单内容
- bFieldContent = MidB(Binary, (PosEndOfHeader + 4), BoundaryEnd - (PosEndOfHeader + 4) - 2)
- FieldName = GetFieldName(Header)
- ' 如果是附件
- If InStr (Header,"filename=""") > 0 Then
- Set File = New FileInfo
- ' 获取文件相关信息
- Dim clientPath
- clientPath = GetFileName(Header)
- File.FileName = GetFileNameByPath(clientPath)
- File.FileExt = GetFileExt(clientPath)
- File.FilePath = clientPath
- File.FileType = GetFileType(Header)
- File.FileStart = PosEndOfHeader + 3
- File.FileSize = BoundaryEnd - (PosEndOfHeader + 4) - 2
- File.FormName = FieldName
- ' 如果该文件不为空并不存在该表单项保存之
- If Not Files.Exists(FieldName) And File.FileSize > 0 Then
- Files.Add FieldName, File
- End If
- '表单数据
- Else
- ' 允许同名表单
- If Form.Exists(FieldName) Then
- Form(FieldName) = Form(FieldName) & "," & BinaryToString(bFieldContent)
- Else
- Form.Add FieldName, BinaryToString(bFieldContent)
- End If
- End If
- ' 是否结束位置
- TwoCharsAfterEndBoundary = BinaryToString(MidB(Binary, BoundaryEnd + LenB(Boundary), 2))
- IsBoundaryEnd = TwoCharsAfterEndBoundary = "--"
- If Not IsBoundaryEnd Then ' 如果不是结尾, 继续读取下一块
- BoundaryStart = BoundaryEnd
- BoundaryEnd = InStrB(BoundaryStart + LenB(Boundary), Binary, Boundary)
- End If
- Loop
- ' 解析文件结束后更新进度信息
- Progress.UploadedBytes = TotalBytes
- Progress.ReadyState = "interactive" '解析文件结束
- UpdateProgressInfo progressID
- End Sub
- '异常信息
- Private Sub Raise(Message)
- ErrMsg = ErrMsg & "[" & Now & "]" & Message & "<BR>"
- Progress.ErrorMessage = Message
- UpdateProgressInfo ProgressID
- 'call Err.Raise(vbObjectError, "DoteyUpload", Message)
- End Sub
- ' 取边界值
- Private Function GetBoundary()
- Dim ContentType, ctArray, bArray
- ContentType = Request.ServerVariables("HTTP_CONTENT_TYPE")
- ctArray = Split(ContentType, ";")
- If Trim(ctArray(0)) = "multipart/form-data" Then
- bArray = Split(Trim(ctArray(1)), "=")
- GetBoundary = "--" & Trim(bArray(1))
- Else '如果form中没有包括multipart/form-data上传是无效的
- GetBoundary = null
- Raise("如果form中没有包括multipart/form-data上传是无效的")
- End If
- End Function
- ' 将二进制流转化成文本
- Private Function BinaryToString(xBinary)
- Dim Binary
- if vartype(xBinary) = 8 then Binary = MultiByteToBinary(xBinary) else Binary = xBinary
- Dim RS, LBinary
- Const adLongVarChar = 201
- Set RS = CreateObject("ADODB.Recordset")
- LBinary = LenB(Binary)
- if LBinary>0 then
- RS.Fields.Append "mBinary", adLongVarChar, LBinary
- RS.Open
- RS.AddNew
- RS("mBinary").AppendChunk Binary
- RS.Update
- BinaryToString = RS("mBinary")
- Else
- BinaryToString = ""
- End If
- End Function
- Function MultiByteToBinary(MultiByte)
- Dim RS, LMultiByte, Binary
- Const adLongVarBinary = 205
- Set RS = CreateObject("ADODB.Recordset")
- LMultiByte = LenB(MultiByte)
- if LMultiByte>0 then
- RS.Fields.Append "mBinary", adLongVarBinary, LMultiByte
- RS.Open
- RS.AddNew
- RS("mBinary").AppendChunk MultiByte & ChrB(0)
- RS.Update
- Binary = RS("mBinary").GetChunk(LMultiByte)
- End If
- MultiByteToBinary = Binary
- End Function
- ' 字符串到二进制
- Function StringToBinary(String)
- Dim I, B
- For I=1 to len(String)
- B = B & ChrB(Asc(Mid(String,I,1)))
- Next
- StringToBinary = B
- End Function
- '返回表单名
- Private Function GetFieldName(infoStr)
- Dim sPos, EndPos
- sPos = InStr(infoStr, "name=")
- EndPos = InStr(sPos + 6, infoStr, Chr(34) & ";")
- If EndPos = 0 Then
- EndPos = inStr(sPos + 6, infoStr, Chr(34))
- End If
- GetFieldName = Mid(infoStr, sPos + 6, endPos - _
- (sPos + 6))
- End Function
- '返回文件名
- Private Function GetFileName(infoStr)
- Dim sPos, EndPos
- sPos = InStr(infoStr, "filename=")
- EndPos = InStr(infoStr, Chr(34) & CrLf)
- GetFileName = Mid(infoStr, sPos + 10, EndPos - _
- (sPos + 10))
- End Function
- '返回文件的 MIME type
- Private Function GetFileType(infoStr)
- sPos = InStr(infoStr, "Content-Type: ")
- GetFileType = Mid(infoStr, sPos + 14)
- End Function
- '根据路径获取文件名
- Private Function GetFileNameByPath(FullPath)
- Dim pos
- pos = 0
- FullPath = Replace(FullPath, "/", "\")
- pos = InStrRev(FullPath, "\") + 1
- If (pos > 0) Then
- GetFileNameByPath = Mid(FullPath, pos)
- Else
- GetFileNameByPath = FullPath
- End If
- End Function
- '根据路径获取扩展名
- Private Function GetFileExt(FullPath)
- Dim pos
- pos = InStrRev(FullPath,".")
- if pos>0 then GetFileExt = Mid(FullPath, Pos)
- End Function
- ' 更新进度信息
- ' 进度信息保存在Application中的ADODB.Recordset对象中
- Private Sub UpdateProgressInfo(progressID)
- Const adTypeText = 2, adDate = 7, adUnsignedInt = 19, adVarChar = 200
- If (progressID <> "" And IsNumeric(progressID)) Then
- Application.Lock()
- if IsEmpty(Application(UploadProgressInfo)) Then
- Set Info = Server.CreateObject("ADODB.Recordset")
- Set Application(UploadProgressInfo) = Info
- Info.Fields.Append "ProgressID", adUnsignedInt
- Info.Fields.Append "StartTime", adDate
- Info.Fields.Append "LastActivity", adDate
- Info.Fields.Append "TotalBytes", adUnsignedInt
- Info.Fields.Append "UploadedBytes", adUnsignedInt
- Info.Fields.Append "ReadyState", adVarChar, 128
- Info.Fields.Append "ErrorMessage", adVarChar, 4000
- Info.Open
- Info("ProgressID").Properties("Optimize") = true
- Info.AddNew
- Else
- Set Info = Application(UploadProgressInfo)
- If Not Info.Eof Then
- Info.MoveFirst()
- Info.Find "ProgressID = " & progressID
- End If
- If (Info.EOF) Then
- Info.AddNew
- End If
- End If
- Info("ProgressID") = clng(progressID)
- Info("StartTime") = Progress.StartTime
- Info("LastActivity") = Now()
- Info("TotalBytes") = Progress.TotalBytes
- Info("UploadedBytes") = Progress.UploadedBytes
- Info("ReadyState") = Progress.ReadyState
- Info("ErrorMessage") = Progress.ErrorMessage
- Info.Update
- Application.UnLock
- End IF
- End Sub
- ' 根据上传ID获取进度信息
- Public Function GetProgressInfo(progressID)
- Dim pi, Infos
- Set pi = New ProgressInfo
- If Not IsEmpty(Application(UploadProgressInfo)) Then
- Set Infos = Application(UploadProgressInfo)
- If Not Infos.Eof Then
- Infos.MoveFirst
- Infos.Find "ProgressID = " & progressID
- If Not Infos.EOF Then
- pi.StartTime = Infos("StartTime")
- pi.LastActivity = Infos("LastActivity")
- pi.TotalBytes = clng(Infos("TotalBytes"))
- pi.UploadedBytes = clng(Infos("UploadedBytes"))
- pi.ReadyState = Trim(Infos("ReadyState"))
- pi.ErrorMessage = Trim(Infos("ErrorMessage"))
- Set GetProgressInfo = pi
- End If
- End If
- End If
- Set GetProgressInfo = pi
- End Function
- ' 移除指定的进度信息
- Private Sub RemoveProgressInfo(progressID)
- If Not IsEmpty(Application(UploadProgressInfo)) Then
- Application.Lock
- Set Info = Application(UploadProgressInfo)
- If Not Info.Eof Then
- Info.MoveFirst
- Info.Find "ProgressID = " & progressID
- If Not Info.EOF Then
- Info.Delete
- End If
- End If
- ' 如果没有记录了, 直接释放, 避免'800a0bcd'错误
- If Info.RecordCount = 0 Then
- Info.Close
- Application.Contents.Remove UploadProgressInfo
- End If
- Application.UnLock
- End If
- End Sub
- ' 移除指定的进度信息
- Private Sub RemoveOldProgressInfo(progressID)
- If Not IsEmpty(Application(UploadProgressInfo)) Then
- Dim L
- Application.Lock
- Set Info = Application(UploadProgressInfo)
- Info.MoveFirst
- Do
- L = Info("LastActivity").Value
- If IsEmpty(L) Then
- Info.Delete()
- ElseIf DateDiff("d", Now(), L) > 30 Then
- Info.Delete()
- End If
- Info.MoveNext()
- Loop Until Info.EOF
- ' 如果没有记录了, 直接释放, 避免'800a0bcd'错误
- If Info.RecordCount = 0 Then
- Info.Close
- Application.Contents.Remove UploadProgressInfo
- End If
- Application.UnLock
- End If
- End Sub
- End Class
- '---------------------------------------------------
- ' 进度信息 类
- '---------------------------------------------------
- Class ProgressInfo
- Public UploadedBytes
- Public TotalBytes
- Public StartTime
- Public LastActivity
- Public ReadyState
- Public ErrorMessage
- Private Sub Class_Initialize()
- UploadedBytes = 0 ' 已上传大小
- TotalBytes = 0 ' 总大小
- StartTime = Now() ' 开始时间
- LastActivity = Now() ' 最后更新时间
- ReadyState = "uninitialized" ' uninitialized,loading,loaded,interactive,complete
- ErrorMessage = ""
- End Sub
- ' 总大小
- Public Property Get TotalSize
- TotalSize = FormatNumber(TotalBytes / 1024, 0, 0, 0, -1) & " K"
- End Property
- ' 已上传大小
- Public Property Get SizeCompleted
- SizeCompleted = FormatNumber(UploadedBytes / 1024, 0, 0, 0, -1) & " K"
- End Property
- ' 已上传秒数
- Public Property Get ElapsedSeconds
- ElapsedSeconds = DateDiff("s", StartTime, Now())
- End Property
- ' 已上传时间
- Public Property Get ElapsedTime
- If ElapsedSeconds > 3600 then
- ElapsedTime = ElapsedSeconds \ 3600 & " 时 " & (ElapsedSeconds mod 3600) \ 60 & " 分 " & ElapsedSeconds mod 60 & " 秒"
- ElseIf ElapsedSeconds > 60 then
- ElapsedTime = ElapsedSeconds \ 60 & " 分 " & ElapsedSeconds mod 60 & " 秒"
- else
- ElapsedTime = ElapsedSeconds mod 60 & " 秒"
- End If
- End Property
- ' 传输速率
- Public Property Get TransferRate
- If ElapsedSeconds > 0 Then
- TransferRate = FormatNumber(UploadedBytes / 1024 / ElapsedSeconds, 2, 0, 0, -1) & " K/秒"
- Else
- TransferRate = "0 K/秒"
- End If
- End Property
- ' 完成百分比
- Public Property Get Percentage
- If TotalBytes > 0 Then
- Percentage = fix(UploadedBytes / TotalBytes * 100) & "%"
- Else
- Percentage = "0%"
- End If
- End Property
- ' 估计剩余时间
- Public Property Get TimeLeft
- If UploadedBytes > 0 Then
- SecondsLeft = fix(ElapsedSeconds * (TotalBytes / UploadedBytes - 1))
- If SecondsLeft > 3600 then
- TimeLeft = SecondsLeft \ 3600 & " 时 " & (SecondsLeft mod 3600) \ 60 & " 分 " & SecondsLeft mod 60 & " 秒"
- ElseIf SecondsLeft > 60 then
- TimeLeft = SecondsLeft \ 60 & " 分 " & SecondsLeft mod 60 & " 秒"
- else
- TimeLeft = SecondsLeft mod 60 & " 秒"
- End If
- Else
- TimeLeft = "未知"
- End If
- End Property
- End Class
- '---------------------------------------------------
- ' 文件信息 类
- '---------------------------------------------------
- Class FileInfo
- Dim FormName, FileName, FilePath, FileSize, FileType, FileStart, FileExt, NewFileName
- Private Sub Class_Initialize
- FileName = "" ' 文件名
- FilePath = "" ' 客户端路径
- FileSize = 0 ' 文件大小
- FileStart= 0 ' 文件开始位置
- FormName = "" ' 表单名
- FileType = "" ' 文件Content Type
- FileExt = "" ' 文件扩展名
- NewFileName = "" '上传后文件名
- End Sub
- Public Function Save()
- SaveAs(FileName)
- End Function
- ' 保存文件
- Public Function SaveAs(fullpath)
- Dim dr
- SaveAs = false
- If trim(fullpath) = "" Or FileStart = 0 Or FileName = "" Or right(fullpath,1) = "/" Then Exit Function
- NewFileName = GetFileNameByPath(fullpath)
- Set dr = CreateObject("Adodb.Stream")
- dr.Mode = 3
- dr.Type = 1
- dr.Open
- DoteyUpload_SourceData.position = FileStart
- DoteyUpload_SourceData.copyto dr, FileSize
- dr.SaveToFile MapPath(FullPath), 2
- dr.Close
- set dr = nothing
- SaveAs = true
- End function
- ' 取服务器端路径
- Private Function MapPath(Path)
- If InStr(1, Path, ":") > 0 Or Left(Path, 2) = "\\" Then
- MapPath = Path
- Else
- MapPath = Server.MapPath(Path)
- End If
- End function
- '根据路径获取文件名
- Private Function GetFileNameByPath(FullPath)
- Dim pos
- pos = 0
- FullPath = Replace(FullPath, "/", "\")
- pos = InStrRev(FullPath, "\") + 1
- If (pos > 0) Then
- GetFileNameByPath = Mid(FullPath, pos)
- Else
- GetFileNameByPath = FullPath
- End If
- End Function
- End Class
- %>
问题:用dw做了一个下拉菜单,但是碰到form的列表项就跑到下面去了,请帮忙解决,请看问题图示如下:
解决方案:由于层与下拉框之间的优先级是:下拉框 > 层,因此在显示的时候,会因为优先级的次序而会出现如上问题。(如果几个元素都是层的话,我们可以通过层的 z-index 属性来设置)解决办法就是:给层中放一个优先级比下拉框更高的元素(iframe),从而解决此问题!具体解决代码如下:
- <div id="menu" style="position:absolute; visibility:hidden; top:20px; left:20px; width:100px; height:200px; background-color:#6699cc;">
- <table>
- <tr><td>item 1</td></tr>
- <tr><td>item 2</td></tr>
- <tr><td>item 3</td></tr>
- <tr><td>item 4</td></tr>
- <tr><td>item 5</td></tr>
- </table>
- <iframe src="javascript:false" style="position:absolute; visibility:inherit; top:0px; left:0px; width:100px; height:200px; z-index:-1; filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';"></iframe>
- </div>
- <a href="#" onclick="document.getElementById('menu').style.visibility='visible'">menu</a>
- <form>
- <select><option>A form selection list</option></select>
- </form>
使用 JavaScript 构建下拉菜单
发布日期: 12/6/2004 | 更新日期: 12/6/2004
Jon Spivey
MVP
适用于:
Microsoft FrontPage
摘要:学习如何使用 FrontPage、JavaScript 和层叠样式表为 Web 页构建下拉菜单。
简介
很多 Web 站点都采用某种形式的下拉菜单。下拉菜单可以设计用于访问子菜单,而这些子菜单进而可以访问其他子菜单。通过使用下拉菜单,可以为最深层次的站点提供具有针对性的导航结构。尽管在大多数 JavaScript 站点上都有用于这种菜单类型的免费脚本,但完成的菜单通常并不是非常吸引人,并且不能在所有的浏览器中运行。在本文中,我将讨论如何使用短短的几行 JavaScript 和一个层叠样式表来构建吸引人且符合下列所有条件的下拉菜单:
• 跨浏览器兼容。该脚本会在所有的版本 4 和更高版本的浏览器中运行。
• 可自定义的内容。该脚本允许在下拉菜单中放入链接、文本和图像的任意组合。
• 高效率脚本编写。构成这个菜单的脚本的大小小于 2 KB。
可以下载名为 FrontPage 2002 Sample Dropdown menu.zip 的压缩文件,以便您可以在遵循本文所述并构建自己的菜单时使用。FrontPage 2002 Sample Dropdown menu.zip 包含图像、脚本、doctype 声明(这样,我们可以根据 WWW 联合会阐明的 HTML 4.01 规范来正确地验证该文档)、两个层叠样式表以及一个 Default.htm 页面。要开始构建自己的下拉菜单,请将该压缩文件的内容进行解压缩,并将该文件导入 Microsoft FrontPage Web 站点,然后将图像(.gif 文件)移动到名为 images 的子文件夹中。
添加菜单按钮
在 images 文件夹中,您将找到用于创建四个菜单按钮的图像。每个按钮都具有三种状态:默认状态、当指针移动到按钮上时出现的悬停状态以及指示当前页面的按下状态。还有一个徽标 (Logo.gif) 和一个背景图像 (Bg.gif);这两个都是我在自己的站点上用于设计页面的图像。我们将插入 Logo.gif,而使用附加的层叠样式表来应用 Bg.gif。随着对该过程的逐步熟悉,您会希望创建并插入自己的图像。为了帮助我们正确地定位一切内容,我还将名为 Shim.gif 的透明 GIF 包括在其中。
由于要将徽标和菜单按钮定位在表格中,因此让我们从将表格添加到页面来开始。
要将表格添加到页面:
1. 打开 Default.htm。光标的放置位置无关紧要,因为我们稍后将会定位该表格。
2. 在 Table 菜单上,指向 Insert,然后单击 Table。
3. 选择下列设置:带有设置的 Insert Table 对话框
要将图像添加到表格:
1. 将光标放在第一个单元格中。
2. 在 Insert 菜单上,指向 Picture,然后单击 From File。
3. 浏览到 images 文件夹,然后选择 Shim.gif。
4. 单击 Insert。
要设置图片属性:
1. 右键单击该图像,然后单击 Picture Properties。
2. 选择 Specify size,然后清除 Keep aspect ratio。
3. 将宽度设置为 40 像素、高度设置为 49 像素。
要设置单元格属性:
1. 右键单击该单元格,然后单击 Cell Properties。
2. 选择 Specify width。
3. 将宽度设置为 40 像素。
我们希望徽标出现在下一个单元格中,但需要徽标跨越四列。
要使一个单元格跨越多列:
1. 单击第一行的第二个单元格。
2. 在 Table 菜单上,指向 Select,然后单击 Cell。
3. 按住 CTRL 按钮,然后单击该行中接下来的三个单元格。
4. 右键单击任意突出显示的单元格,然后单击 Merge Cells。
现在,将徽标插入到刚创建的跨列单元格中。然后,将 Shim.gif 插入到最后一个单元格中,将其宽度设置为 24 像素、高度设置为 49 像素。
将上述步骤作为指导,移动到第二行,将 Shim.gif 插入到第一个单元格中,并将其宽度设置为 40 像素、高度设置为 26 像素。现在,将这些按钮本身添加到第二行。将 Oneout.gif 插入到第二个单元格,将 Twoout.gif 插入到第三个单元格,将 Threeout.gif 插入到第四个单元格,将 Fourout.gif 插入到第五个单元格。要完成该表格,请将 Shim.gif 插入到最后一个单元格,并将其宽度设置为 24 像素、高度设置为 26 像素。
添加链接
现在,我们可以将链接添加到菜单。并不是所有链接都将处于活动状态。我们将为 Logo.gif 和 Shim.gif 使用静态超级链接以触发菜单功能所必需的脚本。
要添加链接:
1. 在第一行的第二个单元格中,右键单击 Logo.gif,然后单击 Hyperlink。
2. 在 Address 文本框中,键入 javascript:;,然后单击 OK。
3. 在第二行的第一个单元格中,右键单击 Shim.gif,然后单击 Hyperlink。
4. 在 Address 文本框中,键入 javascript:;,然后单击 OK。
5. 对于四个菜单按钮(Oneout.gif、Twoout.gif、Threeout.gif 和 Fourout.gif)中的每一个,右键单击该图像,然后单击 Hyperlink。
6. 在 Address 文本框中,键入您要链接的页面的 URL,然后单击 OK。
7. 在最后一行的最后一个单元格中,右键单击 Shim.gif,然后单击 Hyperlink。
8. 在 Address 框中,键入 javascript:;,然后单击 OK。
定位表格
表格虽然已经完成,但我们仍需要将其定位到页面的左上角。过去,通过使用正文标记中的边距属性将页面边距设置为零,我们可以实现这一操作。但是,在 HTML 4.01 规范中边距属性被否决,因此我们将使用绝对位置将菜单定位到页面的左上角。
要定位表格:
1. 右键单击工具栏上的任意位置,然后单击 Positioning 显示“Positioning”工具栏。
2. 单击表格内部。
3. 在 Table 菜单上,指向 Select,然后单击 Table。
4. 在“Positioning”工具栏上,单击最左端的 Position Absolutely 图标,然后输入以下设置:图 2. 带有设置的 Positioning 工具栏
注 我已经删除了默认高度设置;它是不必要的,而且可能会在一些浏览器中引起问题。
5. 保存页面。
6. 要在浏览器中预览该页面,请在 File 菜单上,单击 Preview in Browser。注意菜单表格位于页面的左上角。
添加下拉菜单
现在,让我们从第一个菜单按钮开始来构建菜单的下拉部分 - 子菜单。使用以下设置将表格添加到页面:带有设置的 Insert Table 对话框
表格的放置位置无关紧要,因为我们会稍后对其进行定位。我们需要将某些链接添加到菜单中以便正确地对其进行测试。在第一个表格行中键入 Link One,在第二个表格行中键入 Link Two,依次类推,直到键入 Link Four。在最后一行中,键入几行文本。要使我们能够使用层叠样式表设置最后一个单元格中的文本的样式,该文本需要位于<P>标记中。
Some interesting text or an image, or both, might go here.
现在,我们已经创建了子菜单表格,需要将其直接定位在第一个菜单按钮下。
要定位子菜单表格:
1. 单击表格内部。
2. 在 Table 菜单上,指向 Select,然后单击 Table。
3. 在“Positioning”工具栏上,单击 Position Absolutely,然后输入以下设置: 带有设置的 Positioning 工具栏
这会直接将子菜单定位在第一个按钮正下方。FrontPage 会自动将 DIV 元素添加到表格中以便正确对其进行定位。使用层叠样式表,我们将类属性应用到该 DIV 元素。切换到 HTML 视图并找到刚添加的 DIV 元素的代码。我为子菜单创建的类属性称为 drop,因此,让我们添加 class="drop" 以将 drop 类属性分配给 DIV 元素:
- <div style="position: absolute; top: 75px; left: 44px; width: 175px; z-index: 10" class="drop">
显示和隐藏菜单
现在,该到智能部分了。当我们将指针移动到第一个按钮的上方时,我们需要使该菜单可见,而当我们移开指针时,需要它再次隐藏。同时,当指针悬停在菜单上时,菜单按钮图像应该更改为悬停状态 (Oneover.gif),当指针离开菜单时返回默认状态。要确保当指针移开菜单时,该菜单处于隐藏状态,我们将在该菜单后添加一个稍微大一些的透明 GIF。当用户将指针移开菜单时,透明 GIF 将触发脚本并隐藏菜单。
在页面上的任意位置插入 Shim.gif(我们将在稍后对其进行定位)。该 Shim.gif 需要比菜单大,因此将宽度设置为 224 像素、高度设置为 250 像素。
要将 Shim.gif 定位在第一个菜单下:
• 单击该图像。
• 在“Positioning”工具栏上,单击 Position Absolutely,然后输入以下设置: 带有设置的 Positioning 工具栏
• 因为我们需要在用户将指针移动到该图像上时运行某个脚本,所以右键单击该图像,单击 Hyperlink,然后在 Address 框中键入 javascript:;。
现在,切换到 HTML 视图并找到该图像的 HTML。FrontPage 已经应用了 SPAN 标记,但我们希望使用 DIV 元素。DIV 元素是块级元素,它可以包含其他块级元素,例如,P、H1 和 TABLE 元素。SPAN 元素是一个内联元素,不能包含块级元素。我们要使用块级元素,因此将 SPAN 元素更改为 DIV 元素以便以下列代码结束:
添加事件处理程序
在构建菜单后,我们需要将事件处理程序添加到已经创建的链接上。我们可以编写两个函数,一个用于显示子菜单,一个用于隐藏它,但是这样做会浪费时间。如果一个函数可以完成这两项工作,效率会更高。我们称这个函数为 showHide。这样,如果我们要显示某个特定子菜单,我们就传入想要显示的子菜单的编号。例如,showHide('1') 将显示第一个子菜单。如果要隐藏当前打开的子菜单,不管它是哪个子菜单,那么我们在不使用参数的情况下调用该函数,例如 showHide()。
让我们将事件处理程序添加到第一个菜单按钮。触发时,它将会显示按钮的子菜单。在 FrontPage 中,单击第一个菜单按钮,然后切换到 HTML 视图。该图像需要一个名称,以便我们可以使用脚本引用它。
在 image 标记中,添加一个 name 属性(这个图像的名称为“trig1”)。我们还需要将 onmouseover 事件处理程序添加到该按钮。完成后的代码将类似于如下所示:
- <a HREF="default1.asp" onmouseover="showHide('1')">
- <img alt="" src="images/oneout.gif" name="trig1" border="0" width="124" height="26">
- </a>
注 这就是我们的第一个子菜单,或者子菜单 1。showHide 参数为 1,图像名为 trig1,我们正在查看图像 Oneout.gif。
- <a href="javascript:;" onmouseover="showHide()">
- <img src="images/Shim.gif" width="220px" height="300px" border=0>
- </a>
在浏览器中预览页面。当指针移动到按钮上时,子菜单将会显示。
要添加事件处理程序以隐藏子菜单,请在 HTML 中找到透明 GIF 的 HTML。添加 onmouseover 事件处理程序以调用不带参数的 showHide:
- HYPERLINK "javascript:;" for(i=0;i<aLayers.length;i++){
- if(document.layers)document.layers[aLayers[i]].visibility='hide';
- else if(document.getElementById)
- document.getElementById(aLayers[i]).style.visibility='hidden';
- else if(document.all)document.all(aLayers[i]).style.visibility='hidden';
- }
向上移动两行,我们将看到 Logo.gif 的 HTML。我们需要当用户将指针移动到 Logo.gif 上时隐藏该菜单,因此将 onmouseover 事件处理程序添加到链接:
- <a href="javascript:;" onmouseover="showHide()"><img border="0"
- src="images/logo.gif" width="516" height="49"></a>
现在,向上移动四行,我们将会发现处理菜单表格的 DIV 元素的 HTML。该 DIV 元素应该为 id 属性指定 "top":
- <div style="position: absolute; top: 0px; left: 0px; width: 580px;" id="top">
现在,找到刚创建的下拉菜单的 HTML。我们需要将该 DIV 元素的 z 索引设置为 hidden,并为其指定一个 id 属性值 "sub1",这样代码会类似于如下所示:
- <div style="position: absolute; top: 75px; left: 44px; width: 175px; z-index: 10; visibility: hidden" id="sub1" class="drop">
最后,向下滚动到我们刚才添加的 Shim.gif 的 HTML。该 DIV 元素也需要隐藏,并且应该将 id 属性值设置为 "close1"。该元素也需要一个 onmouseover 事件处理程序,用来通知脚本在用户将指针移动到其上时隐藏菜单。
要在浏览器中预览页面,在“文件”菜单上,单击“在浏览器中预览”。将指针移动到菜单按钮上,然后将其移开菜单按钮。正如您所见,现在已具备了一个正常工作的下拉菜单。
添加更多菜单
正如前面所见,每个菜单都包括三个部分:触发子菜单的按钮图像、包含子菜单的 DIV 元素和隐藏子菜单的关闭 DIV 元素。
您可以在一个页面上按喜好创建多个子菜单。但是,要使用本文中包括的脚本,遵循我所使用的菜单部分的命名顺序非常最重要。菜单按钮必须按顺序进行命名:trig1、trig2、trig3 等等。子菜单必须包含 id sub1、sub2、sub3 等等。并且关闭 DIV 元素必须将 id 属性值设置为 close1、close2、close3 等等。
记住这个命名顺序,遵循上述步骤创建第二、第三和第四个按钮的菜单。下面是您应该使用的设置的总结。每个子菜单和关闭 DIV 元素都需要准确地出现在相关联的菜单按钮下面。所有 DIV 元素的顶端位置都是 75px。对于左侧位置,我已经在页面上移动每个子菜单,直到它准确位于菜单按钮下。注意子菜单需要定位到准确的像素十分重要。关闭 DIV 元素的左侧位置无需准确到像素,因为每个关闭 DIV 元素都比相关联的菜单大。
菜单 1 菜单 2 菜单 3 菜单 4
图像名 trig1 trig2 trig3 trig4
菜单 Div ID sub1 sub2 sub3 sub4
菜单 Div 顶端位置 75px 75px 75px 75px
菜单 Div 左侧位置 44px 174px 305px 436px
关闭 Div ID close1 close2 close3 close4
关闭 Div 顶端位置 75px 75px 75px 75px
关闭 Div 左侧位置 10px 154px 258px 378px
将事件处理程序添加到第二、第三和第四个子菜单中。为了多样化,您可以尝试添加不同长度的子菜单。还可以将图像或任意多的文本添加到子菜单中。只需要记住每个菜单的命名规则即可:trig1 用于图像、sub1 用于菜单 DIV 元素以及 close1 用于包含透明 GIF 的 DIV 元素。还要记住透明 GIF 必须比该菜单大。
有了能正常工作的菜单后,让我们来看一下代码。
脚本
该脚本的功能存在于函数 showHide()。让我们看一下 showHide() 函数的代码:
- function showHide(){
- var a = showHide.arguments;
- if(a.length>0) a = new Array('sub'+a[0], 'close'+a[0],a[0]);
- if(!document.layerSet){
- if(a.length > 0){aLayers = new Array();for(i=0; i 0){for(i=0; i< +?.src?);> a[2] else{document.images[?trig?+a[2]].src="eval('over'" +?.src?);} c="eval('over'" if(document.layers){document.layers[?top?].document.images[?trig?+a[2]].sr ;} if(document.layers)document.layers[aLayers[i]].visibility="show">
我们需要做的首要事情就是指派传递到变量(在此例中为 a)的参数(如果有)。我们可以使用一行代码来完成:
- var a = showHide.arguments;
我们的变量“a”将根据数组为空(如果没有任何参数传递到函数)或为零。第一个元素“a[0]”将包含传入的参数(基于子菜单最终数量,为 1、2、3 等等)。因此,我们将需要测试“a”变量的长度。如果它大于 0,我们需要构建一个稍后会在脚本中使用的数组。以下代码测试我们的“a”变量的长度并构建包含两个 DIV 元素以及传递到函数的参数的数组。
- if(a.length>0) a = new Array('sub'+a[0], 'close'+a[0],a[0]);
因此,如果将参数“1”传递到函数,“a”将是包含元素 sub1、close1 和 1 的新数组。
我们需要一种方法来确定这是否是第一次在页面上调用该函数,以便确定是否存在需要关闭的任何打开的 DIV 元素。
如果确实是第一次调用该脚本,则脚本将构建包含两个 DIV 元素(只要这两个元素已经打开,我们就要关闭它们)的数组。我会使用变量“document.layerSet”来确定该函数是否是第一次进行调用。如果我们只使用一个简单的设置为 true 或 flase 的变量(例如,“layerSet=true”),则它不会在两次调用该函数之间保留其值。通过以格式“document.variableName”使用变量,该变量将在两次调用函数之间保留它的值。
您可能会认为“document.layerSet”是指文档对象的 layerSet 属性,同样,“document.bgColor”是指文档对象的 bgColor 属性。在此例中,情况并非如此。不存在文档对象的 layerSet 属性。它只是我为变量选择的名称。我也可以简单地选择“document.jonsVariable”。当我们以这种方式使用变量时,必须选择不是文档对象属性的变量名称。您可能会发现这种技术在很多脚本中都非常有用。
第一次调用该脚本时,“document.layerSet”将设置为 false,因为我们尚未为它设置值,并且它并不是文档对象的有效属性。确定“document.layerSet”是否为 false 的快速方法就是编写 if(!document.layerSet)。如果它为 false,我们需要构建一个数组(我称其为“aLayers”)以保存我们要打开菜单的 ID:
- if(!document.layerSet){
- if(a.length > 0){
- aLayers = new Array();
- for(i=0; i< } document.layerSet="true;">
在调用脚本后,“document.layerSet”将设置为真,这样该代码将只运行一次。
如果不是第一次调用该函数,将会打开当前在页面上可见的包含两个 DIV 元素 — 子菜单 (subx) 和关闭 DIV (closex)— 的数组 (aLayers)。
要隐藏这些 DIV 元素并将菜单按钮图像切换回到其默认状态,我们需要找到当前打开菜单的索引 (x)。索引是 aLayers 的第一个元素的第四个字符,因此我们可以使用以下代码找到它:
- theIndex = aLayers[0].charAt(3);
变量 theIndex 将存储我们要查找的编号,而 aLayers 将在其数组中保存当前打开的 DIV 元素的编号。方法 charAt(3) 将跳过前三个字符并将第四个字符的值分配给 theIndex。
您将会想起我们的图像遵循命名顺序 trig1、trig2、trig3 等等。运行上述代码段后,我们可以通过利用 'trig'+theIndex 引用当前打开的图像来查找其名称。通常情况下,我们可以使用“document.images['ImageName']”来处理页面上的图像。
在除 Netscape 4.0 的任意浏览器中,都可以使用“document.images['trig'+theIndex]”来调用该图像。但 Netscape 4.0 使用非 DIV 元素的层,因此我们需要添加该调用的“document.layers['top']”以便使其对 Netscape 4.0 有意义。结果是:
- document.layers['top'].document.images['trig'theIndex]
我们可以编写特定代码以适应 Netscape 4.0,并确保对跨浏览器兼容的菜单图像的引用。因为 Netscape 4.0 是唯一包含 document.layers 集合的浏览器,所以 if(document.layers) 是测试浏览器是否为 Netscape 4.0 的快速简单的方法。在建立对图像的引用后,我们可以使用 'out' + theIndex + '.src' 将图像源 (src) 转换回其默认状态:
- if(document.layers){hideImage
- =document.layers['top'].document.images['trig'+theIndex];}
- else{hideImage = document.images['trig'+theIndex];}
- hideImage.src = eval('out' + theIndex + '.src');
在转换菜单图像后,我们需要隐藏当前打开的子菜单。打开的菜单存储在“aLayers”中,因此我们将循环“aLayers”并隐藏 DIV 元素。利用脚本处理已定位的 DIV 元素有三种不同的方法。对于 Netscape 4.0,方法是 document.layers['NameOfDiv']。对于 Microsoft Internet Explorer 4.x,方法是 document.all('NameOfDiv')。对于浏览器版本 5 和更高版本,方法是 document.getElementById('NameOfDiv')。因此我们可以依次通过“aLayers”以确定所有三种可能性,并且对于 Netscape 4.0 将两层的可见性设置为“hide”,对于所有其他浏览器设置为“hidden”。
- for(i=0;i< if(document.layers)document.layers[aLayers[i]].visibility="hide" }>
此时,所有菜单图像都处于其默认状态,并且所有子菜单都处于隐藏状态。如果我们调用不带参数的函数,换言之,如果我们将指针从一个子菜单上移开,同时又不移动到另一个子菜单上,那么就不会有任何其他操作。
但是,如果我们调用带参数的函数(即,如果我们将指针移动到另一个子菜单上),那么我们需要显示选定的子菜单并将菜单按钮转换到其悬停状态。当然,我们还需要使用 aLayers 在显示上添加两个 DIV 元素 — subx 和 closex—,这样我们可以在下一次调用该函数时隐藏它们。脚本的其余部分是使用与前面相同的方法来确定 theIndex 并对 Netscape 4.0 进行测试,它将如下所示:
- if(a.length > 0){
- for(i=0; i< a[2] else{document.images[?trig?+a[2]].src="eval('over'" +?.src?);} c="eval('over'" if(document.layers){document.layers[?top?].document.images[?trig?+a[2]].sr ;} if(document.layers)document.layers[aLayers[i]].visibility="show" }} +?.src?); aLayers[i]="a[i];">
脚本将继续以这种方式运行,直到用户关闭浏览器窗口。
两个样式表
让我们查看一下样式表如何工作以及它们实现的内容。我们需要确保页面可以显示在所有浏览器中,包括 Netscape 4.0。我们使用两个样式表来实现这一目的:一个用于 Netscape 4.0 的基本样式表和一个用于最新浏览器版本的样式表。将样式表链接到页面的通常的语法是:
- <link rel="stylesheet" type="text/css" href="stylesheet.css">
所有版本 4.0 和更高版本的浏览器都支持该语法。将样式表链接到页面的另一个方法是 @import 命令:
- <style type="text/css">
- @import url(stylesheet.css);
- </style>
Netscape 4.0 不支持 @import 命令并将其完全完全忽略。因此,如果我具有一个用于 Netscape 4.0 浏览器的样式表和另一个用于版本 5.0 和更高版本浏览器的样式表,我可以对两个样式表使用以下代码:
- <link rel="stylesheet" type="text/css" href="old.css">
- <style type="text/css">@import url('v5.css');</style>
使用这种格式,就不再需要浏览器检测。
现在,让我们看一下样式表本身。我们从设置 标记的样式开始。我想要背景图像 (Bg.gif) 在 x 方向中重复(即在 x-y 轴上交叉,但不在同一平面上)。我们还需要定位菜单的左上角,这样我们添加到页面的任何内容会正确地定位于该菜单下面。因此,我们设置顶端边距为 100 像素。所有其他边距设置为 0 像素。
- body {
- background-image: url('/images/bg.gif');
- background-repeat: repeat-x;
- margin-top:100px;
- margin-right: 0px;
- margin-bottom: 0px;
- margin-left: 0px;
- }
现在,我们为下拉菜单本身定义一个类属性 (drop)。drop 类属性定义在以下几个代码段中:“.drop”用于常规属性;“.drop td”用于处理表格单元格的表现形式;“.drop a”和“.drop a:hover”用于处理链接的表现形式。
- .drop {
- border: 1px none #666666;
- padding-top: 10px;
- background-color: #FFFFFF;
- layer-background-color: #ffffff;
- }
- .drop td {
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-size: 12px;
- }
- .drop a {
- color: #99CCCC;
- text-decoration: none;
- font-size: 14px;
- padding-left: 11px;
- padding-top: 2px;
- padding-bottom: 2px;
- }
- .drop a:hover {
- color: #FFFFFF;
- background-color: #99CCCC;
- }
当然,设置页面样式的方式并没有对错之分,因此尝试自己的颜色和字体以得到想要的外观。有关层叠样式表的详细信息(包括类、特性、属性和值),请参阅 Using Cascading Style Sheets on Your Web Site。
灵活性的优势
我所介绍的技术的优势在于我们将具有一个可以运行在所有当前浏览器中的精简脚本。更重要的是,该技术非常灵活。在掌握该技术后,您将能够设计和构建自己的下拉菜单。还可以使用该技术来构建垂直的弹出菜单。您无需接触构建该菜单的 JavaScript,但确实需要学习层叠样式表。我已经为该演示使用了一些非常简单的样式。通过修改层叠样式表,您可以使自己的菜单更有趣、更吸引人。
本日志由 flyinweb 于 2009-06-19 23:39:24 发表到 WEB应用开发 中,目前已经被浏览 240 次,评论 0 次;
作者添加了以下标签: JavaScript,下拉菜单;
MicrosoftVBscript运行时错误(0x000A0005) 无效的过程调用或参数
MicrosoftVBscript运行时错误(0x000A0005) 无效的过程调用或参数
MicrosoftVBscript运行时错误(0x000A0006) 溢出
MicrosoftVBscript运行时错误(0x000A0007) 内存不够
MicrosoftVBscript运行时错误(0x000A0009) 下标越界
MicrosoftVBscript运行时错误(0x000A000A) 该数组为定长的或临时被锁定
MicrosoftVBscript运行时错误(0x000A000B) 被零除
MicrosoftVBscript运行时错误(0x000A000D) 类型不匹配
MicrosoftVBscript运行时错误(0x000A000E) 字符串空间不够
MicrosoftVBscript运行时错误(0x000A0011) 不能执行所需的操作
MicrosoftVBscript运行时错误(0x000A001C) 堆栈溢出
MicrosoftVBscript运行时错误(0x000A0023) 未定义过程或函数
MicrosoftVBscript运行时错误(0x000A0030) 加载 DLL 时出错
MicrosoftVBscript运行时错误(0x000A0033) 内部错误
MicrosoftVBscript运行时错误(0x000A0034) 错误的文件名或号码
MicrosoftVBscript运行时错误(0x000A0035) 文件未找到
MicrosoftVBscript运行时错误(0x000A0036) 错误的文件模式
MicrosoftVBscript运行时错误(0x000A0037) 文件已经打开
MicrosoftVBscript运行时错误(0x000A0039) 设备 I/O 错误
MicrosoftVBscript运行时错误(0x000A003A) 文件已存在
MicrosoftVBscript运行时错误(0x000A003D) 磁盘已满
MicrosoftVBscript运行时错误(0x000A003E) 输入超出了文件尾
MicrosoftVBscript运行时错误(0x000A0043) 文件过多
MicrosoftVBscript运行时错误(0x000A0044) 设备不可用
MicrosoftVBscript运行时错误(0x000A0046) 没有权限
MicrosoftVBscript运行时错误(0x000A0047) 磁盘没有准备好
MicrosoftVBscript运行时错误(0x000A004A) 重命名时不能带有其他驱动器符号
MicrosoftVBscript运行时错误(0x000A004B) 路径/文件访问错误
MicrosoftVBscript运行时错误(0x000A004C) 路径未找到
MicrosoftVBscript运行时错误(0x000A005B) 对象变量未设置
MicrosoftVBscript运行时错误(0x000A005C) For 循环未初始化
MicrosoftVBscript运行时错误(0x000A005E) 无效使用 Null
MicrosoftVBscript运行时错误(0x000A0142) 不能创建必要的临时文件
MicrosoftVBscript运行时错误(0x000A01A8) 缺少对象
MicrosoftVBscript运行时错误(0x000A01AD) ActiveX 部件不能创建对象
MicrosoftVBscript运行时错误(0x000A01AE) 类不支持 Automation 操作
MicrosoftVBscript运行时错误(0x000A01B0) Automation 操作中文件名或类名未找到
MicrosoftVBscript运行时错误(0x000A01B6) 对象不支持此属性或方法
MicrosoftVBscript运行时错误(0x000A01B8) Automation 操作错误
MicrosoftVBscript运行时错误(0x000A01BD) 对象不支持此操作
MicrosoftVBscript运行时错误(0x000A01BE) 对象不支持已命名参数
MicrosoftVBscript运行时错误(0x000A01BF) 对象不支持当前区域设置选项
MicrosoftVBscript运行时错误(0x000A01C0) 未找到已命名参数
MicrosoftVBscript运行时错误(0x000A01C1) 参数是必选项
MicrosoftVBscript运行时错误(0x000A01C2) 错误的参数个数或无效的参数属性值
MicrosoftVBscript运行时错误(0x000A01C3) 对象不是一个集合
MicrosoftVBscript运行时错误(0x000A01C5) 未找到指定的 DLL 函数
MicrosoftVBscript运行时错误(0x000A01C7) 代码资源锁定错误
MicrosoftVBscript运行时错误(0x000A01C9) 此键已与该集合的一个元素关联
MicrosoftVBscript运行时错误(0x000A01CA) 变量使用了一个 VBScript 中不支持的 Automation 类型
MicrosoftVBscript运行时错误(0x000A01CE) 远程服务器不存在或不可用
MicrosoftVBscript运行时错误(0x000A01E1) 无效图片
MicrosoftVBscript运行时错误(0x000A01F4) 变量未定义
MicrosoftVBscript运行时错误(0x000A01F5) 非法赋值
MicrosoftVBscript运行时错误(0x000A01F6) 对象不能安全用 Script 编程
MicrosoftVBscript运行时错误(0x000A01F7) 对象不能安全初始化
MicrosoftVBscript运行时错误(0x000A01F8) 对象不能安全创建
MicrosoftVBscript运行时错误(0x000A01F9) 无效的或无资格的引用
MicrosoftVBscript运行时错误(0x000A01FA) 类没有被定义
MicrosoftVBscript运行时错误(0x000A01FB) 出现一个意外错误
MicrosoftVBscript运行时错误(0x000A03E9) 内存不够
MicrosoftVBscript运行时错误(0x000A03EA) 语法错误
MicrosoftVBscript运行时错误(0x000A03EB) 缺少 ':'
MicrosoftVBscript运行时错误(0x000A03ED) 缺少 '('
MicrosoftVBscript运行时错误(0x000A03EE) 缺少 ')'
MicrosoftVBscript运行时错误(0x000A03EF) 缺少 ']'
MicrosoftVBscript运行时错误(0x000A03F2) 缺少标识符
MicrosoftVBscript运行时错误(0x000A03F3) 缺少 '='
MicrosoftVBscript运行时错误(0x000A03F4) 缺少 'If'
MicrosoftVBscript运行时错误(0x000A03F5) 缺少 'To'
MicrosoftVBscript运行时错误(0x000A03F6) 缺少 'End'
MicrosoftVBscript运行时错误(0x000A03F7) 缺少 'Function'
MicrosoftVBscript运行时错误(0x000A03F8) 缺少 'Sub'
MicrosoftVBscript运行时错误(0x000A03F9) 缺少 'Then'
MicrosoftVBscript运行时错误(0x000A03FA) 缺少 'Wend'
MicrosoftVBscript运行时错误(0x000A03FB) 缺少 'Loop'
MicrosoftVBscript运行时错误(0x000A03FC) 缺少 'Next'
MicrosoftVBscript运行时错误(0x000A03FD) 缺少 'Case'
MicrosoftVBscript运行时错误(0x000A03FE) 缺少 'Select'
MicrosoftVBscript运行时错误(0x000A03FF) 缺少表达式
MicrosoftVBscript运行时错误(0x000A0400) 缺少语句
MicrosoftVBscript运行时错误(0x000A0401) 语句未结束
MicrosoftVBscript运行时错误(0x000A0402) 缺少整型常数
MicrosoftVBscript运行时错误(0x000A0403) 缺少 'While' 或 'Until'
MicrosoftVBscript运行时错误(0x000A0404) 缺少 'While' 和 'Until'或语句未结束
MicrosoftVBscript运行时错误(0x000A0405) 缺少 'With'
MicrosoftVBscript运行时错误(0x000A0406) 标识符过长
MicrosoftVBscript运行时错误(0x000A0407) 无效数字
MicrosoftVBscript运行时错误(0x000A0408) 无效字符
MicrosoftVBscript运行时错误(0x000A0409) 未结束的字符串常量
MicrosoftVBscript运行时错误(0x000A040A) 注释未结束
MicrosoftVBscript运行时错误(0x000A040D) 无效使用 'Me' 关键字
MicrosoftVBscript运行时错误(0x000A040E) 'loop' 语句缺少 'do'
MicrosoftVBscript运行时错误(0x000A040F) 无效的 'exit' 语句
MicrosoftVBscript运行时错误(0x000A0410) 循环控制变量 'for' 无效
MicrosoftVBscript运行时错误(0x000A0411) 名称重定义
MicrosoftVBscript运行时错误(0x000A0412) 必须是行中的第一个语句
MicrosoftVBscript运行时错误(0x000A0413) 不能为 non-ByVal 参数赋值
MicrosoftVBscript运行时错误(0x000A0414) 调用子程序时不能使用括号
MicrosoftVBscript运行时错误(0x000A0415) 缺少文字常数
MicrosoftVBscript运行时错误(0x000A0416) 缺少 'In'
MicrosoftVBscript运行时错误(0x000A0417) 缺少 'Class'
MicrosoftVBscript运行时错误(0x000A0418) 必须在一个类的内部定义
MicrosoftVBscript运行时错误(0x000A0419) 在属性声明中缺少 Let , Set 或 Get
MicrosoftVBscript运行时错误(0x000A041A) 缺少 'Property'
MicrosoftVBscript运行时错误(0x000A041B) 在所有属性的规范中,变量的数目必须一致
MicrosoftVBscript运行时错误(0x000A041C) 在一个类中不允许有多个缺省的属性/方法
MicrosoftVBscript运行时错误(0x000A041D) 类的初始化或终止程序没有变量
MicrosoftVBscript运行时错误(0x000A041E) 属性的 set 或 let 必须至少有一个变量
MicrosoftVBscript运行时错误(0x000A041F) 错误的 'Next'
MicrosoftVBscript运行时错误(0x000A0420) 'Default' 只能在 'Property' , 'Function' 或 'Sub' 中指定
MicrosoftVBscript运行时错误(0x000A0421) 指定 'Default' 时必须同时指定 'Public'
MicrosoftVBscript运行时错误(0x000A0422) 只能在 Property Get 中指定 'Default'
MicrosoftVBscript运行时错误(0x000A1000) Microsoft VBScript 编译器错误
MicrosoftVBscript运行时错误(0x000A1001) Microsoft VBScript 运行时错误
MicrosoftVBscript运行时错误(0x000A1398) 缺少正则表达式对象
MicrosoftVBscript运行时错误(0x000A1399) 正则表达式语法错误
MicrosoftVBscript运行时错误(0x000A139A) 错误的数量词
MicrosoftVBscript运行时错误(0x000A139B) 正则表达式中缺少 ']'
MicrosoftVBscript运行时错误(0x000A139C) 正则表达式中缺少 ')'
MicrosoftVBscript运行时错误(0x000A139D) 字符集越界
本日志由 flyinweb 于 2009-06-19 23:22:36 发表到 WEB应用开发 中,目前已经被浏览 215 次,评论 0 次;
作者添加了以下标签: VBScript 运行时错误;
To: jconsole不能打开,大概两种可能: 1 没有启用独占模式,如O
两个实例分别放在不同的 datadir 里面,会方便很多
今天遇到了“Cleanup failed to process the following paths:-
谢谢分享.有帮助.
根据inotify + rsync的思路,现在有了个c++版本的同步程序,只需指
真是有耐心呀。我做了个pdf 文件 在上面的网站可以下载