JavaScript代码在IE和Firefox间的区别

1. HTML 对象的 id 作为对象名的问题

  IE:HTML 对象的 ID 可以作为 document 的下属对象变量名直接使用

  FF:不支持

  解决方法:使用document.getElementById替代document.all

  2. 如果控件只有name,没有id, 用getElementById时:

  IE:可以找到对象

  FF:返回NULL

  解决方法:所有控件必须设置ID属性

  3. Evel:

  IE:支持,利用 eval(idName) 可以取得 id 为 idName 的 HTML 对象

  FF:不支持。

  解决方法:统一使用getElementById(idName) 代替 eval(idName)。

  4. Event:

  IE:用全局对象window.event

  FF:event只能在事件发生的现场使用,在调用函数时传入event对象

  解决方法:使用之前做一下浏览器类型判断,各用各的。

  5. 对象名称中美元符号‘$’改为使用下划线‘_’

  6. 集合类对象问题

  IE:可以使用()或[]获取集合类对象

  FF:只能使用[]获取集合类对象

  现有代码中存在许多,不能在 FF 下运行

  解决方法:统一使用[]获取集合类对象。document.form.item(“itemName”) 这样的语句改为document.form.elements[“elementName”]

  7. 变量名与某 HTML 对象 id 相同的问题

  IE:不能使用与 HTML 对象 id 相同的变量名

  FF:可以使用

  解决方法:在声明变量时,一律加上 var ,以避免歧义,这样在 IE 中亦可正常运行。

  此外,最好不要取与 HTML 对象 id 相同的变量名,以减少错误。

  8. Event定位问题

  IE:支持event.x 和event.y

  FF:支持event.pageX和event.pageY

  解决方法,统一使用event.clientX和event.clientY,但是在FF中event.clientX 与 event.pageX 有微妙的差别(当整个页面有滚动条的时候),不过大多数时候是等效的。如果要完全一样,可以判断浏览器类型后对应使用。

  9. 父结点的问题

  IE:parentElement parentElement.children

  FF:parentNode parentNode.childNodes

  childNodes的下标的含义在IE和FF中不同,FF使用DOM规范,childNodes中会插入空白文本节点。一般可以通过node.getElementsByTagName()来回避这个问题。

  当html中节点缺失时,IE和FF对parentNode的解释不同,例如

 


 <form> 
<table
  <input/> 
</table> 
</form>

 

  IE:input.parentNode的值为空节点

  FF:input.parentNode的值为form

  FF中节点没有removeNode方法,必须使用如下方法 node.parentNode.removeChild(node)

  10. const 问题

  现有问题:

  IE:不支持 const 关键字。如 const constVar = 32; 在IE中这是语法错误。

  FF:支持

  解决方法:不使用 const ,以 var 代替。

  11. body 对象

  IE:在body标签完全被读入之后才存在

  FF:在body标签没有被浏览器完全读入之前就存在

  12. 自定义属性问题

  IE:可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性

  FF:只能使用getAttribute()获取自定义属性.

  解决方法:统一通过getAttribute()获取自定义属性

  13. event.srcElement问题

  IE:even.srcElement

  FF:even.target

  解决方法:使用时判断浏览器类型,各用各的。

  14. 模态和非模态窗口

  IE:支持模态和非模态窗口

  FF:不支持

  解决方法:直接使用window.open(pageURL,name,parameters)方式打开新窗口。如果需要将子窗口中的参数传递回父窗口,可以在子窗口中使用window.opener来访问父窗口。

  15. innerText

  IE:innerText

  FF:textContent

  16. 类似 obj.style.height = imgObj.height 的语句

  IE:有效

  FF:无效

  解决方法:统一使用obj.style.height = imgObj.height + ‘px’;

 

javascript关闭窗口(兼容firefox,IE)

javascript关闭窗口,可以用下面简单的代码:

<a href="javascript:self.close()">关闭窗口</a>  

我在IE7下测试通过,但是firefox3.0却不行。

难道firefox不支持在href中直接写JavaScript?于是改成下面的样子:

<a href="javascript:alert('Hello World')">弹出窗口</a>  

这次IE7和firefox下测试都通过。那就不是href中直接写JavaScript的原因了。

继续测试firefox怎么关闭自身窗口

改成了如下代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"    
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
<script type="text/javascript">  
<!--   
function windowClose(){   
//self.close();   
window.close();   
}   
//-->  
</script>  
<title>js测试</title>  
</head>  
<a href="javascript:self.close()">关闭窗口</a><br />  
<a href="javascript:alert('Hello World')">弹出窗口</a><br />    
<a href="#" onclick="windowClose()">js函数关闭窗口</a>  
<body>  
</body>  
</html>  

还是不能关闭窗口。难道firefox不支持window的close属性?

那window对象的close方法能不能关闭open方法打开的窗口呢?

写下面两个html文件放在同一个文件夹下

<script type="text/javascript">   
<!--   
function openWindow(){   
window.open("new.html","newWindow","width=200,height=100,toolbar=no");   
}   
//-->   
</script>   
<a href="#" onclick="openWindow()">open函数打开新窗口</a><br />   
<a href="new.html" target="_blank">超级链接在新窗口中打开新页面</a><br />   
<a href="new.html" target="_parent">超级链接在父窗口中打开新页面</a>  
<a href="javascript:window.close()">关闭窗口</a>   
<a href="javascript:self.close()">关闭窗口</a> 

用open方法和在”_blank”打开的可以在新窗口中关闭,而在”_parent”中打开的在firefox中还是关闭不

因此在firefox里用window的close方法时要注意他和IE不同的地方:在父窗口打开的页面是不能用close

方法关闭的。

然后去google搜了一下:之所以window.close在firefox不能使用,是因为firefox默认不能关闭用户打

开的网页,我们可以这样设置firefox:

打开firefox,在地址栏输入about:config

找到dom.allow_scripts_to_close_windows这项并改为true。

现在知道为什么了吧。那篇文章还有一段不错的内容,摘录如下:

众所周知,在javascript中window.close()是用来关闭窗口的,而且ie和firefox都是支持的。为了实现

用户对浏览器的绝对控制,ie中用close关闭非open打开的窗口时会弹出一个对话框询问用户。有时候我

们不希望再这样哆嗦,但是怎么去掉这个框呢,用下面的代码就可以了

<script language="javascript" type="text/javascript">    
  
function closeWindow() {    
  
window.open('','_parent','');    
  
window.close();    
  
}    
  
</script>    
<a href="javascript:closeWindow();">Close Window</a>  

firebug调试

Javascript的调试利器:Firebug使用详解
Posted 星期日, 12/09/2007 – 02:09 by ppkosd

Javascript 的调试,是开发Web应用尤其是AJAX应用很重要的一环,目前对Javascript进行调试的工具很多,我比较喜欢使用的是Firebug。 Firebug是Joe Hewitt开发的一套与Firefox集成在一起的功能强大的web开发工具,可以实时编辑、调试和监测任何页面的CSS、HTML和 JavaScript。
本文主要是为初学者介绍一下Firebug的基本功能与如何使用Firebug。由于本人水平与能力有限,在文章中的可能会有很多错误与遗漏,希望大家能谅解和指正!

<!–[if !supportLists]–>1、 <!–[endif]–>安装
Firebug是与Firefox集成的,所以我们首先要安装的事 Firefox浏览器。安装好浏览器后,打开浏览器,选择菜单栏上的“工具”菜单,选择“附加软件”,在弹出窗口中点击右下角的“获取扩展”链接。在打开的页面的search输入框中输入“firebug”。等搜索结果出来后点击Firbug链接(图1-1红色圈住部分)进入Firebug的下载安装页面。

<!–[if !vml]–><!–[endif]–>
图1-1

在页面中点击Install Now(图1-2)按钮。

<!–[if !vml]–><!–[endif]–>
图1-2

在弹出窗口(图1-3)中等待3秒后单击“立即安装”按钮。

<!–[if !vml]–><!–[endif]–>
图1-3

等待安装完成后会单击窗口(图1-4)中的“重启 Firefox”按钮重新启动Firefox。

<!–[if !vml]–><!–[endif]–>
图1-4

当Firefox重启完后我们可以在状态栏最右边发现一个灰色圆形图标(<!–[if !vml]–><!–[endif]–>),这就表示Firebug已经安装好了。灰色图标表示Firebug未开启对当前网站的编辑、调试和监测功能。而绿色(<!–[if !vml]–><!–[endif]–>)则表示Firebug已开启对当前网站进行编辑、调试和监测的功能。而红色图标(<!–[if !vml]–><!–[endif]–>)表示已开启对当前网站进行编辑、调试和监测的功能,而且检查到当前页面有错误,当前图标表示有5个错误。

<!–[if !supportLists]–>2、 <!–[endif]–>开启或关闭Firebug
单击Firebug的图标或者按F12键你会发现页面窗口被分成了两部分,上半部分是浏览的页面,下半部分则是Firebug的控制窗口(图2-1)。如果你不喜欢这样,可以按CTRL+F12或在前面操作后单击右上角的上箭头按钮,弹出一个新窗口作为Firebug的控制窗口。

<!–[if !vml]–><!–[endif]–>
图2-1

从图2-1中我们可以看到,因为我们开启Firebug的编辑、调试和监测功能,所以目前只有两个可以选择的链接:“Enable Firebug”与“Enable Firebug for this web site”。如果你想对所有的网站进行编辑、调试和检测,你可以点击“Enable Firebug”开启Firebug,则以后无论浏览任何网站,Firebug都处于活动状态,随时可以进行编辑、调试和检测。不过一般的习惯我们只是对自己开发的网站进行编辑、调试和检测,所以我们只单击“Enable Firebug for this web site”开启Firebug就行了。
开启Firebug窗口(图2-2)后,我们可以看到窗口主要有两个区域,一个是功能区,一个是信息区。选择功能区第二行的不同标签,信息区的显示会有不同,Options的选项也会不同,搜索框的搜索方式也会不同。

<!–[if !vml]–><!–[endif]–>
图2-2

要关闭Firebug控制窗口单击功能区最右边的关闭图标或按F12键就行了。如果要关闭Firebug的编辑、调试和监测功能,则需要单击功能区最左边的臭虫图标,打开主菜单,选择“Disable Firebug”或“Disable Firebug for xxxxx”。

<!–[if !supportLists]–>3、 <!–[endif]–>Firebug主菜单

单击功能区最左边的臭虫图标可打开主菜单(图3-1),其主要功能描述请看表1。

<!–[if !vml]–><!–[endif]–>
图3-1

菜单选项

说明
Disable Firebug
关闭/开启Firebug对所有网页的编辑、调试和检测功能
Disable Firebug for xxxxx

关闭/开启Firebug对xxxxx网站的编辑、调试和检测功能
Allowed Sites

设置允许编辑、调试和检测的网站
Text Size:Increase text size

增大信息区域显示文本的字号
Text Size:Decrease text size

减少信息区域显示文本的字号
Text Size:Normal text size

信息区域以正常字体显示
Options:Always Open in New Window

设置Firebug控制窗口永远在新窗口打开
Show Preview tooltips

设置是否显示预览提示。
Shade Box Model

当前查看状态为HTML,鼠标在HTML element标签上移动时,页面会相应在当前标签显示位置显示一个边框表示该标签范围。这个选项的作用是设置是否用不同颜色背景表示标签范围。
Firebug Website..

打开Firebug主页。
Documentation..

打开Firebug文档页。
Discussion Group

打开Firebug讨论组。
Contribute

打开捐助Firebug 页面。
表1

<!–[if !supportLists]–>4、 <!–[endif]–>控制台(Console)
单击功能区第二栏的“Console”标签可切换到控制台(图4-1)。控制台的作用是显示各种错误信息(可在Options里定义),显示脚本代码中内嵌的控制台调试信息,通过命令行对脚本进行调试,通过单击Profile对脚本进行性能测试。 控制台分两个区域,一个是信息区,一个是命令行,通过Options菜单的“Larger Command Line”可改变命令行位置。

<!–[if !vml]–><!–[endif]–>
图4-1

    Options菜单的选项请看表2。

菜单选项

说明
Show JavaScript Errors 显示脚本错误。
Show JavaScript Warnings

显示脚本警告。
Show CSS Errors

显示CSS错误。
Show XML Errors

显示XML错误。
Show XMLHttpRequests

显示XMLHttpRequests。
Larger Command Line

将命令行显示从控制窗口底部移动右边,扩大输入区域。
表2

单击“Clear”按钮可清除控制台的控制信息。

<!–[if !supportLists]–>5、 <!–[endif]–>页面源代码查看功能
单击功能区第二栏的“HTML”标签可切换到源代码查看功能(图5-1)。虽然Firefox也提供了查看页面源代码的功能,但它显示的只是页面文件本身的源代码,通过脚本输出的HTML源码是看不到。而Firebug则是所见即所得,是最终的源代码。

<!–[if !vml]–><!–[endif]–>
图5-1

我们来看一个例子,文件源代码如下:

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>
<html>
<head>
<title>简单的例子</title>
       <meta http-equiv=”content-type” content=”text/html; charset=utf-8″>
       <style>
              #div1{background:red;width:100px;height:100px;}
              #div2{background:blue;width:100px;height:100px;margin:10px;padding:10px;border:5px solid black;color:white;}
              #div3{background:yellow;width:50px;height:50px;margin-left:25px;}
       </style>
</head>
<body scroll=”no”>
<div id=”div1″>方块一</div>
<div id=”div2″>方块二</div>
<script>
    document.getElementById(‘div1′).innerHTML+='<div id=”div3″>方块三</div>’;
</script>
</body>
</html>
 
在例子中我们通过JavaScript在“div1”中加入了“div3”,在Firefox中查看源代码你是看不到“div1”中包含有代码“<div id=”div3″>方块三</div>”的,但是Firebug中我们是可以看见的(图5-2选中部分)。

<!–[if !vml]–><!–[endif]–>
图5-2

从图5-1中我们可以看到,信息区被分成了两个部分,左边是显示源代码,右边是一个功能区,可以从这里查看到HTML Element中的CSS定义、布局情况和DOM结构。
从图5-2中我们可以看到,源代码按DOM结构分层次显示的,通过层次折叠功能,我们就可以很方便分析代码。在功能区的第一行还根据你的选择,清晰的按子、父、根列出了当前源代码的层次(图5-2红色部分),单击各部分,则会即刻转到该部分的源代码。

<!–[if !vml]–><!–[endif]–>
图5-3

在源代码上移动鼠标,页面就会出现一个半透明的方块,指示当前鼠标所指源代码的显示区域,当选择。在图5-4中,鼠标正指向“div1”,而在页面中“div1”的显示区域上被一个半透明的方块遮盖了。
<!–[if !vml]–><!–[endif]–>
图5-4
如果你把“Inspect”按钮按下,功能正好相反,在页面中移动鼠标,则当前显示区域的源代码会被加亮显示出来。在图5-5中,我们可以看到鼠标指针正指向“方块二”,而在源代码中可以看到,“方块二”的源代码“<div id=”div2″>方块二</div>”已被加亮显示(红色部分)。如果你单击某个显示区域,则该区域的源代码会被选中。

<!–[if !vml]–><!–[endif]–>
图5-5
是不是很方便?方便是方便,但是我的源代码很多,而且有些区域在页面中不方便鼠标指定,怎么办?没关系,我们还有一个厉害武器,搜索功能。譬如我们知道某个HTML Element的ID是“div2”,但在层层叠叠的源代码中不好找,在页面中鼠标也很难找到,那我们就在功能区的搜索框中输入“div2”,再看看源代码区域,“div2”被加亮显示出来了(图5-6红色部分)。在这个简单的例子可能看不出很好的效果,大家可以尝试一下把“div1”先折叠起来,然后在搜索框输入“div3”,你可以看到“div1”会自动展开,并将“div3”加亮显示,如果还觉得不够理想,可以找一个源代码比较多的例子测试一下。
<!–[if !vml]–><!–[endif]–>
图5-6

除了通过按下“Inspect”按钮,单击显示区域选择源代码,我们还可以通过单击源代码中的HTML标记(开始或结束标记都可以)来选择。我们尝试一下把鼠标移动到HTML标记,会发现鼠标指针变成了手的形状,这说明我们可以通过单击选择该源代码。选择源代码后,我们就可以通过右边的功能区查看、编辑和调试它的CSS定义和盒子模型(CSS盒子模型请参阅相关说明,这里就不再赘述了),还有一个很好的功能就是当外部编辑器修改了源代码(没有删除该源代码,只是修改),我们在浏览器重新加载页面后,选择的源代码不会改变,我们可以很方便的观察源代码的变化与效果。
有没有经常为调试某个页面效果在源代码编辑器和浏览器之间切换,一次又一次的刷新而感到懊恼?有了Firebug你就不用再懊恼了。你可以直接在源代码中进行编辑,然后查看效果。如果只是修改已经存在的属性,例如要修改“div2”的内部文本,则直接将鼠标移动到文本上面,等鼠标指针换成“I”,单击即可进行编辑了。其它已存在的属性和属性值也可以这样直接进行编辑。如果要为某 Element添加属性,请将鼠标移动到该Element上,等光标变为“I”的时候,单击鼠标右键,从菜单中选择“New Attribute..”,在显示的编辑框中输入你要添加的属性名称就可以了。
<!–[if !vml]–><!–[endif]–>
图5-7

<!–[if !vml]–><!–[endif]–>
图5-8
我们尝试一下为“div2”增加一个“onclick”属性,单击的结果是将 “div2”的显示文本修改为“单击”。把光标移动到“div2”上,然后单击鼠标右键,选择“New Attribute..”(图5-7),在编辑框中输入“onclick”,最后按一下回车键(图5-8),出现属性值输入框后,输入 “this.innerHTML=’单击’”,回车后我们可以继续添加下一个属性,这次测试不需要,所以按ESC结束我们的输入。我们来检验一下修改结果,单击页面“div2”的区域(图5-9),“div2”的显示文本已修改为“单击”了,而源代码也改变了。有没有发现,“div2”被加亮显示了?这又是Firebug的一个功能。只要我们通过页面中的操作修改了Element的属性,Firebug就会在源代码中通过加亮的方式指示当前操作修改那些属性值。譬如我们单击某个链接修改了一个iframe里的src,那么这个src的属性值就会被加亮显示。又譬如我们单击某个链接修改了一个image里的图像,那么它的src属性值也会被加亮显示。我们可以通过Options菜单里的“Highlight Changes”设置是否加亮显示改变。而“Expand Changes”则是设置被改变的源代码折叠起来看不见时展开让它可见。而“Scroll Changes into view”则是源代码很多,被改变的源代码不在可视区域时,将被改变的源代码滚动到可视区域。
<!–[if !vml]–><!–[endif]–>
图5-9

有时候我们不单是要增加一两个属性,而是要做更多的修改,这怎么办呢?很简单,选择你要更改Element,然后单击功能区第一行的“Edit”按钮或者直接将鼠标移动到要修改的Element上,单击鼠标右键,选择“Edit HTML..”,这时候,源代码区域将切换到编辑状态,你可以随意的修改你选择的源代码了。我们尝试修改一下“div2”,将被修改显示文本修改回“方块二”,我们选择“div2”,然后单击“Edit”按钮(图5-10),将显示文本修改回“方块二”,然后再次单击“Edit”按钮退出编辑状态,如果要放弃修改,可以按ESC键退出。因为是所见即所得的,所以我们在修改的时候,页面会同时刷新显示。
<!–[if !vml]–><!–[endif]–>
图5-10
如果要修改Element的CSS定义怎么办?很简单,选择该Element,然后在右边的窗口选择“Style”标签,这里显示的就是当前Element的CSS定义了。我们在这里可以对CSS定义进行添加、编辑、删除、禁止等操作。我们尝试一下把“div2”的背景色禁止了看看。将鼠标移动到“background”这行(图5-11),我们可以看到在这行的最右边会有一个灰色的禁止图标,只要单击这个禁止图标,就可以禁止了这个CSS属性了。我们单击这个图标看看效果,页面中的“div2”已经变成白色背景了,而禁止图标也变成红色,而文本会则变成灰色(图5-12),这说明已经禁止了“background”了。当然了,这个操作也可以通过鼠标右键的“Disable XXXXX”来实现(XXXXX表示当前选择的CSS属性)。我们再次单击禁止图标,恢复“background”属性。我们这次要把 “background”的颜色由蓝色(blue)修改为绿色(green)。我们把鼠标移动到“background”属性值“blue”上(图 5-13)。怎么会出现一个蓝色背景的方框?这是Firebug提供背景预览功能,让我们很直观的知道当前背景是什么。如果背景是图片的话,显示的将是背景图片的缩略图。继续我们的操作,单击属性值,在出现的编辑框中将“blue”修改为“green”。好了,背景已经修改为绿色了。现在的显示文本是左对齐的,我想让它居中对齐,这需要在CSS里加一个“text-align”的属性,值为“center”。请在CSS上单击鼠标右键,在菜单中选择 “New Property..”,在编辑框中输入“te”,Firebug已通过自动完成功能帮我们输入“text-align”了(图5-14),按Tab键或回车,在属性值中我们输入“c”,Firebug再次帮我们自动完成了“center”(图5-15),按Tab键或回车完成输入,如果不需要继续输入新属性,按ESC或单击鼠标取消输入。文本“方块二”现在已经居中显示了。如果忘记了某个属性值有那些选项怎么办?不要紧,在输入属性值的时候可以通过上、下箭头选择我们需要的属性值。
在“Style”标签里我们可以选择“Options”菜单里的“Show Computed Style”查看浏览器默认的风格定义。

<!–[if !vml]–><!–[endif]–>
图5-11

<!–[if !vml]–><!–[endif]–>
图5-12

<!–[if !vml]–><!–[endif]–>
图5-13

<!–[if !vml]–><!–[endif]–>

<!–[if !vml]–><!–[endif]–>
图5-14

图5-15
页面设计中,我们有时候最头疼的是什么?是盒子模型!为了调整一个Element的 margin、border、padding和相对位置,我们往往需要花很多工夫去修改源代码,然后刷新页面查看效果。有了Firebug,你就可以轻松应对了。我们将右边的区域切换到“Layout”标签(图5-16),你会看到一个盒子模型,里面从外到里通过不同的线和颜色划分出了offset、 margin、border、padding和内容五个区域,里面4个区域在每个边上都有1个数值,表示该方向上的调整值。我们先在左边选择 “div2”,然后把鼠标分别移动到“Layout”里的不同区域(图5-17),然后留意一下页面,页面在顶部多了一条水平标尺,在左边多一条垂直标尺,而4条实线指示出了当前鼠标指示的区域实际位置,通过与标尺的交点可以知道该区域离页面显示区域左上角的偏移量(单位是px),当然我们也可以通过 layout中的数字计算出这些偏移量。在图中,我们还可以看到,在内容区域的外面还有3个不同颜色的区域,它们从里到外用不同颜色表示了 padding、border、margin的位置和偏移量。只要将鼠标移动到不同区域,页面中的4条实线也会改变位置,指示出页面中相应的区域。我们还可以通过修改Layout中的数值,对显示效果进行调整。例如我们要将“div2”的内容显示区域扩大到200×200,将鼠标移动最左边的100上,光标变成“I”后,单击鼠标,然后在输入框中输入200,按回车可继续修改高度值,输入200,回车后完成修改。页面中的“div2”区域已经扩展到 200×200了,而源代码也增加了“style=”width: 200px; height: 200px;””(图5-18)。我们切换标签到“Style”,会发现多了“element.style {height:200px;width:200px;}”(图 5-19),而CSS定义里面的高度和宽度都划了横线,表示不起作用了,“element.style”表示直接定义在Element源代码上的CSS属性。有时候某些Element会有相同的属性,也有自己特殊的属性,而特殊的属性想写在Element的源代码上,就可以在Style里单击鼠标右键选择 “Edit Element Style..”进行添加。如果有兴趣的话,大家可以尝试修改“Layout”里的其它属性值,看看页面的变化,这里我就不再一一说明了。
    如果不想在页面中显示标尺和4条实线,可以不选择“Options”菜单里的“Show Rules and Guides”。

<!–[if !vml]–><!–[endif]–>
图5-16

<!–[if !vml]–><!–[endif]–>
图5-17

<!–[if !vml]–><!–[endif]–>
图5-18

<!–[if !vml]–><!–[endif]–>
图5-19

在源代码显示区域我们还可以通过鼠标右键复制源代码和显示内容,这里就不一一说明了。 DOM的说明请看查看DOM结构一节,两者是一样的。在源代码区域中如果觉得源代码显示太密,可以将“Options”菜单里的“Show White Space”选项打开,每个源代码块之间会用空白行隔离。如果要查看源代码的注释内容,请将“Options”菜单里的“Show Comments”选项打开。
这里要提醒大家一下,在HTML里调试出正确的源代码和CSS后,别忘记将源代码和CSS的修改结果复制到你的源代码文件中,不然你的调试结果在页面刷新后会付之东流。切记!切记!

<!–[if !supportLists]–>6、 <!–[endif]–>查看CSS定义
将功能区第二行的标签切换到“CSS”,在这里我们可以查看页面中所有的CSS定义,包括链接的CSS文件。通过功能区的文件选择按钮可以选择不同的含有CSS的文件(图6-1红色圈住部分)。

<!–[if !vml]–><!–[endif]–>
图6-1

CSS的定义的编辑这里就不再说明了,这个可以参考HTML的“Style”操作。
“Edit”按钮功能和HTML的“Edit”功能类似。

<!–[if !supportLists]–>7、 <!–[endif]–>脚本调试
将功能区第二行的标签切换到“Script”,在这里我们可以对页面中所有的脚本进行调试,包括链接的脚本。和CSS一样,可以通过文件选择按钮选择不同的脚本文件。
如果要在脚本中设置一个断点,可以单击行号旁边的空白区域,这时会出现一个红色的点表示在这里设置了断点(图7-1),当脚本运行到此会停止运行,等待你的操作。在右边的小窗口将标签切换到“Breakpoints”可以查看我们设置的所有断点(图7-2),单击左上角的checkbox可以让断点不起作用,如果要删除断点可以单击右上角的删除图标。通过“Options”菜单的 “Disable All Breakpoints”可暂时禁止所有断点,而“Remove All Breakpoints”可删除所有断点。在断点标记的红点上单击右键还可以设置断点条件,在符合条件的时候才会停止脚本的执行。
<!–[if !vml]–><!–[endif]–>
图7-1

<!–[if !vml]–><!–[endif]–>
图7-2

下面我们来尝试一下断点的功能。首先在测试页脚本里增加一个test的函数,函数的主要操作是运行一个1000次的循环,将循环的参数值显示在“div2”里:

    function test(){
            for(var i=0;i<1000;i++){
                   document.getElementById(‘div2’).innerHTML=i;
            }
        }
 
    在“div2”里增加一个“onclick”属性,单击后执行test:

<div id=”div2″ onclick=’test()’>方块二</div>
 
刷新页面,然后在“for(var i=0;i<1000;i++){”这行上设置一个断点,并设置条件为“i=100”(图7-3),然后单击“div2”开始执行函数test。

<!–[if !vml]–><!–[endif]–>
图7-3

当脚本停下来后,我们将鼠标移动到变量“i”上,这时会出现一个小方框,里面有一个数值,这就是变量“i“的当前值(图7-4)。在脚本调试的时候,你可以通过这个方法很方便的了解到当前变量的值。你还可以通过右边窗口的“Watch”标签查看到“i”的值(图7-5)。
<!–[if !vml]–><!–[endif]–>
图7-4

<!–[if !vml]–><!–[endif]–>
图7-5
在“Watch”标签窗口我们可以通过“Options”菜单选择查看用户自定义属性(Show User-defined Properties)、用户自定义函数(Show User-defined Functions)、DOM属性(Show DOM Properties)、DOM函数(Show DOM Functions)和DOM常数(Show DOM Constants)。我们还可以通过单击“New watch expression…”(图7-6淡黄色背景部分)加入自己想跟踪的内容。例如我们想跟踪一下“div2”的显示内容,就可以单击“New watch expression…”,加入“document.getElementById(‘div2’).innerHTML”,输入中可通过TAB键自动完成关键字的输入(图7-7)。如果不想跟踪了,可单击最右边的删除图标取消跟踪。
<!–[if !vml]–><!–[endif]–>
图7-6

<!–[if !vml]–><!–[endif]–>
图7-7

脚本在断点停止后,我们就可以利用搜索框旁的4个跟踪按钮进行代码跟踪了(图 7-7)。第一按钮是继续运行程序,不再执行跟踪,快捷键是F8。第二个按钮是单步执行方式,每次执行一条语句,该方式在遇到函数调用时不进入调用函数内部进行跟踪,快捷键是F10。第三个按钮也是单步执行方式,每次执行一条语句,但它遇到函数调用时会进入调用函数内部进行跟踪,快捷键是F11。当你进入调用函数内,想马上跳出来时,可以单击第四个按钮,该按钮没有快捷键。
搜索框的作用和HTML源代码查看是一样的,不过有一个不同,就是输入“#n”(n≥1),可以直接跳到脚本的第n行。
当执行脚本在“console”标签内显示一个错误,而错误的提示行左边出现一个暗红色的圆点时(图7-8),我们可以单击改红点在该行设置一个断点。

<!–[if !vml]–><!–[endif]–>
图7-8
我们可以通过“Script”标签的“Options”菜单的“Break on All Errors”选项设置每当脚本发生错误时就中断脚本,进入调试状态。
有时候一个函数随机出现错误,你不可能每次调用都去跟踪一次,而产生错误的原因很可能是传递的参数错误,这时你可以通过跟踪函数调用的功能去检查每次调用函数时的参数情况。操作在函数脚本内单击鼠标右键,在菜单中选择“Log Calls to xxxxx”(xxxxx为函数名),然后可在“console”标签中可查看函数调用情况。

<!–[if !supportLists]–>8、 <!–[endif]–>查看DOM结构
将功能区第二行的标签切换到“DOM”可俺层次查看整个页面的DOM结构。通过 “Options”菜单可自定义选择查看用户自定义属性(Show User-defined Properties)、用户自定义函数(Show User-defined Functions)、DOM属性(Show DOM Properties)、DOM函数(Show DOM Functions)或DOM常数(Show DOM Constants)等内容。
通过双击你可以修改DOM里面的属性值。

<!–[if !supportLists]–>9、 <!–[endif]–>查看网络状况
作为开发人员,是否会经常听到老板或客户抱怨页面下载太慢了?于是你就怀疑是否脚本太多了?忘记压缩图片了?服务器太慢了?网络太慢?确实是头疼的事情。有了Firebug,你就可以很容易的对这个问题进行分析和判断了。请将 Firebug的当前标签切换到“Net”(图9-1)。

<!–[if !vml]–><!–[endif]–>
图9-1

<!–[if !vml]–><!–[endif]–>
图9-2

从图中我们可以看到,页面中每一个下载文件都用一个灰色条表示它相对其它文件是从什么时候开始下载的,下载时间是多少。在底部我们看到页面发送了多少个请求,下载总量是多少,有多少是有缓存的,下载总共花费了多少时间等信息。
如果只想了解某一样文件的下载情况,你可以单击功能区第一栏的文件分类按钮过滤文件(图9-2红色圈住区域1)。
将鼠标在文件中移动,如果是图片,我们可以看到图片的缩略图(图9-2红色圈住区域3)。
如果显示为红色的文件名,则表示该文件在服务器中不存在,不能下载,这样你就要检查一下文件的路径是否正确或者是否上传了该文件(图9-2红色圈住区域2)。
我们可以展开某个文件,查看它的HTTP头信息和返回结果的信息。如果请求的是一个动态页面或XMLHttpRequest,则还可以查看提交的变量。通过查看提交的变量和返回信息,我们可以很方便的调试程序是否正确提交了需要的变量和返回了正确的数据。例如从图36中,我们可以看到向“topics-remote.php”发送了一个请求,提交的参数有“_dc”、 “callback”、“limit”和“start”四个,值分别为“1188637444000”、“stcCallback1001”、“25”与 “0”,从这里我们可以很方便的知道我们脚本操作提交的参数是否正确。切换到“Response”页可以看到返回的结果(图9-3),在这里你可以对返回结果进行检查。如果你感觉在这里查看结果很乱,你可以单击鼠标右键,在弹出菜单中选择“Copy Response body”复制结果到编辑器查看,你还可以选择“Open in New Tab”打开一个新标签浏览。

<!–[if !vml]–><!–[endif]–>
图9-3

通过右键菜单你可以复制文件地址(Copy Location)、HTTP请求头信息(Copy Request Headers)和HTTP响应头信息(Copy Response Headers)。
如果不想使用该功能,可以选择Options菜单的“Disable Network Monitoring”关闭该功能。

<!–[if !supportLists]–>10、              <!–[endif]–>命令行调试
在“Console”标签了有一个命令行工具,我们可以在这里运行一些脚本对页面进行调试。
我们在命令行中输入“document.getElementById(‘div2’).innerHTML”看看效果(图10-1),别忘了用TAB键实现快速输入关键字。在信息区显示了当前“div2”的显示内容。

<!–[if !vml]–><!–[endif]–>
图10-1

要输入“document.getElementById”是不是觉得很麻烦?这里有一个简单的办法,用“$”符号代替“document.getElementById”,我们再在命令行中输入“$(‘div2’).innerHTML”,然后看看结果,是一样(图10-2)。

<!–[if !vml]–><!–[endif]–>
图10-2

当你通过“Inspect”锁定了一些HTML Element时,你可以通过“$1”来访问最后一个Element,依次类推,我们可以通过“$n”(n>1)访问依次倒序访问锁定的Element。
我们来实践一下,刷新一下测试页面,然后按下“Inspect”按钮,鼠标单击“方块二”,然后在按下“Inspect”按钮,单击“方块一”。将firebug窗口切换回“Console”标签,然后输入“$1”,回车后再输入 “$2”,查看一下结果(图10-3),正是我们用锁定过的Element。

<!–[if !vml]–><!–[endif]–>
图10-3

在命令行还可以通过“$$(HTML 标记)”返回一个Element数组。我们在测试页输入“$$(‘div’)”看看(图10-4)。我们再输入“$$(‘div’)[0]”看看(图10-5)。是不是很便于我们对HTML进行调试。

<!–[if !vml]–><!–[endif]–>
图10-4
<!–[if !vml]–><!–[endif]–>
图10-5

命令行的所有特殊函数请看表3:

命令
说明
$(id)

通过id返回Element。
$$(selector)

通过CSS选择器返回Element数组。
$x(xpath)

通过xpath表达式返回Element数组。
dir(object)

列出对象的所有属性,和在DOM标签页查看该对象的是一样的。
dirxml(node)

列出节点的HTML或XML的源代码树,和在HTML标签页查看改节点一样。
cd(window)

默认情况下,命令行相关的是顶层window对象,使用该命令可切换到frame里的window独享。
clear()

清空信息显示区,和单击按钮Clear功能一样。
inspect(object[, tabName])

监视一个对象。tabName表示在那个标签页对该对象进行监视,可选值为“html”、“css”、“script”和“dom”。
keys(object)

返回由对象的属性名组成的数组。
values(object)

返回由对象的属性值组成的数组。
debug(fn)

在函数的第一行增加一个断点。
undebug(fn)

移除在函数第一行的断点。
monitor(fn)

跟踪函数fn的调用。
unmonitor(fn)

不跟踪函数fn的调用。
monitorEvents(object[, types])

跟踪对象的事件。Types的可选值为“composition”、 “contextmenu”、 “drag”、 “focus”,、“form”、“key”、 “load”、“mouse”、“mutation”、“paint”、“scroll”、“text”、“ui”和“xul”。
unmonitorEvents(object[, types])

不跟踪对象的事件。Types的可选值为“composition”、 “contextmenu”、 “drag”、 “focus”,、“form”、“key”、 “load”、“mouse”、“mutation”、“paint”、“scroll”、“text”、“ui”和“xul”。
profile([title])

开始对脚本进行性能测试,可选参数title将作为测试结果的标题。
profileEnd()

结束脚本性能测试。
表3

命令行有命令记忆功能,可通过上、下箭头键选择已经输入过的命令。

<!–[if !supportLists]–>11、              <!–[endif]–>在脚本文件中加入调试命令
有没有对脚本调试中经常需要alert感到厌烦?有了Firebug,你就可以放下alert了,因为Firebug有功能比alert更强大的console.log。
先让我们来认识一下console.log,在测试文件脚本区域我们输入一下代码:

console.log(‘Hello’);
 
   刷新一下页面,将firebug切换到“console”标签看看(图11-1),在信息区显示出了我们要输出的信息“Hello”。当然了,单凭这个就说console.log有点夸大,我们修改一下test函数,把 “document.getElementById(‘div2’).innerHTML=i;”修改为:

console.log(‘当前的参数是:%d’,i);
<!–[if !vml]–><!–[endif]–>
图11-1
 
   刷新页面后看看结果(图11-2)。是不是挺不错的?console.log可以象c语言的printf一样实现格式化输出。我们再在脚本区加入一个语句:

console.log(2,4,window,test,document);
 

<!–[if !vml]–><!–[endif]–>
图11-2
 
刷新页面后看看结果(图11-3)。console.log可以连续输出多个对象,而且如果对象是DOM、函数,还可以直接点击去到该对象。

<!–[if !vml]–><!–[endif]–>
图11-3
 
如果你觉得console.log输出的文本太单调,不能表示出不同的信息,那么你可以通过console.debug、 console.info、 console.warn和console.error来代替console.log,这些函数分别会用不同的背景颜色和文字颜色来显示信息。
我们来看看测试一下这些函数的输出,在脚本中加入:

     console.debug(‘This is console.debug!’);
     console.info(‘This is console.info!’);
     console.warn(‘This is console.warn!’);
     console.error(‘This is console.error!’);
 
   刷新页面看看结果(图11-4)。

<!–[if !vml]–><!–[endif]–>
图11-4
 
有时候,为了更清楚方便的查看输出信息,我们可能需要将一些调试信息进行分组输出,那么可以使用console.group来对信息进行分组,在组信息输出完成后用console.groupEnd结束分组。我们测试一下把刚才的4个输出作为一个分组输出,修改代码为:

     console.group(‘开始分组:’);
     console.debug(‘This is console.debug!’);
     console.info(‘This is console.info!’);
     console.warn(‘This is console.warn!’);
     console.error(‘This is console.error!’);
     console.groupEnd();
 
刷新页面看看结果(图11-5)。在console.group中,我们还可以加入一个组标题“开始分组:”。如果需要,我们还可以通过嵌套的方式,在组内再分组。

<!–[if !vml]–><!–[endif]–>
图11-5
 
有时候,我们需要写一个for循环列出一个对象的所有属性或者某个HTML Element下的所有节点,有了firebug后,我们不需要再写这个for循环了,我们只需要使用console.dir(object)或 console.dirxml(element)就可以了。
在测试页中加入代码测试一下:

     console.dir(document.getElementById(‘div1’));
     console.dirxml(document.getElementById(‘div1’));
 
    结果请看图11-6和图11-7。

<!–[if !vml]–><!–[endif]–>
图11-6
<!–[if !vml]–><!–[endif]–>
图11-7
 
是否想知道代码的运行速度?很简单,使用console.time和console.timeEnd就可以。
修改一下test函数的代码,测试一下运行1000次循环需要多少时间:

     function test(){
            console.time(‘test’);
            for(var i=0;i<1000;i++){
                   document.getElementById(‘div2’).innerHTML=i;
                   //console.log(‘当前的参数是:%d’,i);
            }
            console.timeEnd(‘test’);
        }
 
刷新页面,单击“方块二”,看看结果(图11-8)。在这里要注意的是console.time和console.timeEnd里的参数要一致才会有正确的输出,而该参数就是信息的标题。

<!–[if !vml]–><!–[endif]–>
图11-8
 
是否想知道某个函数是从哪里调用的?console..trace可帮助我们进行追踪。在test函数的结尾加入:

            console.trace();
 
刷新页面,单击“方块二”,看看结果(图11-9)。结果显示是在坐标(97,187)的鼠标单击事件执行了test函数,而调用的脚本是在simple.html文件里的第1行。因为是在HTML里面的事件调用了test 函数,所以显示的行号是第1行。如果是脚本,则会显示调用脚本的行号,通过单击可以直接去到调用行。

<!–[if !vml]–><!–[endif]–>
图11-9
 
如果想在脚本某个位置设置断点,可以在脚本中输入“debugger”作为一行。当脚本执行到这一行时会停止执行等待用户操作,这时候可以通过切换到“Script”标签对脚本进行调试。
    Firebug还有其它的一些调试函数,这里就不一一做介绍,有兴趣可以自己测试。表4是所有函数的列表:
函数
说明
console.log(object[, object, …])
向控制台输出一个信息。可以输入多个参数,输出将已空格分隔各参数输出。
第一参数可以包含格式化文本,例如:
console.log(‘这里有%d个%s’,count,apple);
字符串格式:
%s :字符串。
%d, %i:数字。
%f: 浮点数。
%o -超链接对象。
console.debug(object[, object, …])

向控制台输出一个信息,信息包含一个超链接链接到输出位置。
console.info(object[, object, …])

向控制台输出一个带信息图标和背景颜色的信息,信息包含一个超链接链接到输出位置。
console.warn(object[, object, …])

向控制台输出一个带警告图标和背景颜色的信息,信息包含一个超链接链接到输出位置。
console.error(object[, object, …])

向控制台输出一个带错误图标和背景颜色的信息,信息包含一个超链接链接到输出位置。
console.assert(expression[, object, …])

测试一个表示是否为true,如果为false,提交一个例外信息到控制台。
console.dir(object)

列出对象的所有属性。
console.dirxml(node)

列出HTML或XML Element的XML源树。
console.trace()

输出堆栈的调用入口。
console.group(object[, object, …])

将信息分组再输出到控制台。通过console.groupEnd()结束分组。
console.groupEnd()

结束分组输出。
console.time(name)

创建一个名称为name的计时器,计算代码的执行时间,调用console.timeEnd(name)停止计时器并输出执行时间。
console.timeEnd(name)

停止名称为name的计时器并输出执行时间。
console.profile([title])

开始对脚本进行性能测试,title为测试标题。
console.profileEnd()

结束性能测试。
console.count([title])

计算代码的执行次数。titile作为输出标题。
表4

<!–[if !supportLists]–>12、              <!–[endif]–>在IE中使用Firebug
Firebug是Firefox的一个扩展,但是我习惯在IE中调试我的页面怎么办?如果在页面脚本中加入console.log()将调试信息写到Friebug,在IE中肯定是提示错误的,怎么办?不用担心,Frirebug提供了 Frirbug Lite脚本,可以插入页面中模仿Firebug控制台。
我们可以从一下地址下载firebug lite:
http://www.getfirebug.com/releases/firebuglite1.0-b1.zip

然后在页面中加入:

<script language=”javascript” type=”text/javascript” src=”/路径/firebug.js”></script>
 
    如果你不想在IE中模仿Friebug控制台,只是不希望console.log()脚本出现错误信息,那么在页面中加入一下语句:

<script language=”javascript” type=”text/javascript” src=”/路径/firebugx.js”></script>
 
如果你不想安装Firebug Lite,只是想避免脚本错误,那么可以在脚本中加入以下语句:

if (!window.console || !console.firebug)
{
    var names = [“log”, “debug”, “info”, “warn”, “error”, “assert”, “dir”, “dirxml”,
    “group”, “groupEnd”, “time”, “timeEnd”, “count”, “trace”, “profile”, “profileEnd”];

    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {}
}
 
我们将firebug.js加入到测试页面中,然后打开IE,加载页面。页面加载完成后,我们按下F12键就可以打开控制台了。每次页面刷新后,你都要按F12键打开控制台,是不是很烦?如果不想那么,就在html标签中加入“debug=’true’”,例如:

<html debug=”true”>
 
   在Friebug Lite中也有命令行,但是功能没那么强。

<!–[if !supportLists]–>13、 <!–[endif]–>快捷键和鼠标操作
全局操作
打开Firebug窗口

F12
关闭Firebug窗口

F12
在新窗口打开Firebug

Ctrl+F12
往前切换标签

Ctrl+`
将光标移到命令行

Ctrl+Shift+L
将光标移到搜索框

Ctrl+Shift+K
进入Inspect模式

Ctrl+Shift+C
进行JavaScript性能测试

Ctrl+Shift+P
重新执行最后一条命令行命令

Ctrl+Shift+E
HTML标签
编辑属性

单击属性名或值
编辑文本节点

单击文本
编辑Element

双击Element标记
移到路径里的下一个节点

Ctrl+.
移到路径里的上一个节点

Ctrl+,
HTML编辑
完成编辑

Return
取消编辑

Esc
移到下一个区域

Tab
移到上一个区域

Shift+Tab
HTML Inspect 模式
取消Inspect

Esc
Inspect 父节点

Ctrl+Up
Inspect 子节点

Ctrl+Down
Script标签
继续运行

F5
 

Ctrl+/
单步执行(Step Over)

F10
 

Ctrl+’
单步执行(Step Into)

F11
 

Ctrl+;
退出函数(Step Out)

Shift+F11
 

Ctrl+Shift+;
设置断点

单击行号
禁止断点

在行号上Shift+Click
编辑断点条件

在行号上Right-Click
运行到当前行

在行号上Middle-Click
 

在行号上Ctrl+Click
移到堆栈中的下一个函数

Ctrl+.
移到堆栈中的上一个函数

Ctrl+,
将焦点切换到Scripts菜单

Ctrl+Space
将焦点切换到Watch编辑

Ctrl+Shift+N
DOM 标签
编辑属性

双击在空白
移到路径中下一个对象

Ctrl+.
移到路径中上一个对象

Ctrl+,
DOM 和Watch编辑
结束编辑

Return
取消编辑

Esc
自动完成下一个属性

Tab
自动完成上一个属性

Shift+Tab
CSS标签
编辑属性

单击属性
插入新属性

双击空白处
移动焦点到Style Sheets菜单

Ctrl+Space
CSS编辑
完成编辑

Return
取消编辑

Esc
移到下一个区域

Tab
移到上一个区域

Shift+Tab
按步长1增加数值

Up
按步长1减少数值

Down
按步长10增加数值

Page Up
按步长10减少数值

Page Down
自动完成下一个关键字

Up
自动完成上一个关键字

Down
Layout标签
编辑值

单击值
Layout编辑
完成编辑

Return
取消编辑

Esc
移到下一个区域

Tab
移到上一个区域

Shift+Tab
按步长1增加数值

Up
按步长1减少数值

Down
按步长10增加数值

Page Up
按步长10减少数值

Page Down
自动完成下一个关键字

Up
自动完成上一个关键字

Down
命令行 (小)
自动完成上一个属性

Tab
自动完成下一个属性

Shift+Tab
执行

Return
Inspect结果

Shift+Return
打开结果鼠标右键菜单

Ctrl+Return
命令行 (大)
执行

Ctrl+Return

<!–[if !supportLists]–>13、              <!–[endif]–>总结
真是意想不到,Firebug居然有那么多好功能居然是我不知道。通过写本篇文章,才认真的了解和学习了一次Firebug,越学越感觉到它的威力。不过我学的也只是皮毛,还有更多的功能和技巧需要在平时的使用中慢慢积累,因此这篇文章只是一个简单的介绍,还有很多东西是没有涉及到的,而且因为我本身水平与能力有限,所以文中会有很多错误与遗漏,希望大家能多多谅解与指正!多谢!

例子最终源代码:
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>
<html debug=’true’>
<head>
  <title>简单的例子</title>
    <meta http-equiv=”content-type” content=”text/html; charset=utf-8″>
    <style>
        #div1{background:red;width:100px;height:100px;}
        #div2{background:blue;width:100px;height:100px;margin:10px;padding:10px;border:5px solid black;color:white;}
        #div3{background:yellow;width:50px;height:50px;margin-left:25px;}
    </style>
<script language=”javascript” type=”text/javascript” src=”firebug/firebug.js”></script>
</head>
<body scroll=”no”>
  <div id=”div1″>方块一</div>
  <div id=”div2″ onclick=’test()’>方块二</div>
  <script>
      document.getElementById(‘div1′).innerHTML+='<div id=”div3″>方块三</div>’;
/*      console.log(‘Hello’);
      console.log(2,4,window,test,document);
      console.group(‘开始分组:’);
      console.debug(‘This is console.debug!’);
      console.info(‘This is console.info!’);
      console.warn(‘This is console.warn!’);
      console.error(‘This is console.error!’);
      console.groupEnd();*/
//      console.dir(document.getElementById(‘div1’));
//      console.dirxml(document.getElementById(‘div1’));
     
      function test(){
          console.time(‘test’);
          for(var i=0;i<1000;i++){
              document.getElementById(‘div2’).innerHTML=i;
              //console.log(‘当前的参数是:%d’,i);
          }
          console.timeEnd(‘test’);
          console.trace();
      } 
     

Javascript的调试利器:Firebug使用详解

<!– start node.tpl.php –>

 Javascript 的调试,是开发Web应用尤其是AJAX应用很重要的一环,目前对Javascript进行调试的工具很多,我比较喜欢使用的是Firebug。 Firebug是Joe Hewitt开发的一套与Firefox集成在一起的功能强大的web开发工具,可以实时编辑、调试和监测任何页面的CSS、HTML和 JavaScript。

本文主要是为初学者介绍一下Firebug的基本功能与如何使用Firebug。由于本人水平与能力有限,在文章中的可能会有很多错误与遗漏,希望大家能谅解和指正!
 
<!–[if !supportLists]–>1、 <!–[endif]–>安装
Firebug是与Firefox集成的,所以我们首先要安装的事 Firefox浏览器。安装好浏览器后,打开浏览器,选择菜单栏上的“工具”菜单,选择“附加软件”,在弹出窗口中点击右下角的“获取扩展”链接。在打开的页面的search输入框中输入“firebug”。等搜索结果出来后点击Firbug链接(图1-1红色圈住部分)进入Firebug的下载安装页面。
 
<!–[if !vml]–><!–[endif]–>
图1-1
 
在页面中点击Install Now(图1-2)按钮。
 
<!–[if !vml]–><!–[endif]–>
图1-2
 
在弹出窗口(图1-3)中等待3秒后单击“立即安装”按钮。
 
<!–[if !vml]–><!–[endif]–>
图1-3
 
等待安装完成后会单击窗口(图1-4)中的“重启 Firefox”按钮重新启动Firefox。
 
<!–[if !vml]–><!–[endif]–>
图1-4
 
当Firefox重启完后我们可以在状态栏最右边发现一个灰色圆形图标(<!–[if !vml]–><!–[endif]–>),这就表示Firebug已经安装好了。灰色图标表示Firebug未开启对当前网站的编辑、调试和监测功能。而绿色(<!–[if !vml]–><!–[endif]–>)则表示Firebug已开启对当前网站进行编辑、调试和监测的功能。而红色图标(<!–[if !vml]–><!–[endif]–>)表示已开启对当前网站进行编辑、调试和监测的功能,而且检查到当前页面有错误,当前图标表示有5个错误。
 
<!–[if !supportLists]–>2、 <!–[endif]–>开启或关闭Firebug
单击Firebug的图标或者按F12键你会发现页面窗口被分成了两部分,上半部分是浏览的页面,下半部分则是Firebug的控制窗口(图2-1)。如果你不喜欢这样,可以按CTRL+F12或在前面操作后单击右上角的上箭头按钮,弹出一个新窗口作为Firebug的控制窗口。
 
<!–[if !vml]–><!–[endif]–>
图2-1
 
从图2-1中我们可以看到,因为我们开启Firebug的编辑、调试和监测功能,所以目前只有两个可以选择的链接:“Enable Firebug”与“Enable Firebug for this web site”。如果你想对所有的网站进行编辑、调试和检测,你可以点击“Enable Firebug”开启Firebug,则以后无论浏览任何网站,Firebug都处于活动状态,随时可以进行编辑、调试和检测。不过一般的习惯我们只是对自己开发的网站进行编辑、调试和检测,所以我们只单击“Enable Firebug for this web site”开启Firebug就行了。
开启Firebug窗口(图2-2)后,我们可以看到窗口主要有两个区域,一个是功能区,一个是信息区。选择功能区第二行的不同标签,信息区的显示会有不同,Options的选项也会不同,搜索框的搜索方式也会不同。
 
<!–[if !vml]–><!–[endif]–>
图2-2
 
要关闭Firebug控制窗口单击功能区最右边的关闭图标或按F12键就行了。如果要关闭Firebug的编辑、调试和监测功能,则需要单击功能区最左边的臭虫图标,打开主菜单,选择“Disable Firebug”或“Disable Firebug for xxxxx”。
 
<!–[if !supportLists]–>3、 <!–[endif]–>Firebug主菜单
 
单击功能区最左边的臭虫图标可打开主菜单(图3-1),其主要功能描述请看表1。
 
<!–[if !vml]–><!–[endif]–>
图3-1
 
菜单选项
说明
Disable Firebug
关闭/开启Firebug对所有网页的编辑、调试和检测功能
Disable Firebug for xxxxx
关闭/开启Firebug对xxxxx网站的编辑、调试和检测功能
Allowed Sites
设置允许编辑、调试和检测的网站
Text Size:Increase text size
增大信息区域显示文本的字号
Text Size:Decrease text size
减少信息区域显示文本的字号
Text Size:Normal text size
信息区域以正常字体显示
Options:Always Open in New Window
设置Firebug控制窗口永远在新窗口打开
Show Preview tooltips
设置是否显示预览提示。
Shade Box Model
当前查看状态为HTML,鼠标在HTML element标签上移动时,页面会相应在当前标签显示位置显示一个边框表示该标签范围。这个选项的作用是设置是否用不同颜色背景表示标签范围。
Firebug Website..

css统一设置input样式(区分input类型)

1.用css的expression判断表达式

    input

    {

        background-color:expression(this.type==”text” ‘#FFC’:”);

    }

优点:简单

缺点:expression判断表达式FireFox是不支持的。致命的是只能区分出一个(例如例子中就只能区分出text文本框),不要试图设置多个,下面的会将上面的覆盖掉

2.用css中的type选择器

    input[type=”text”]

    {

        background-color:#FFC;

    }

   

    input[type=”password”]

    {

        background-image:url(BG.gif);

    }

优点:简单,明了,可以分区出各个input控件形态。

缺点:type选择器,IE6之前的对web标准支持的不太好的浏览器不能支持

3.用javascript脚本实现

<script language=javascript>

switch(type)

{

    case ‘text’:

    style.backgroundColor=”red”;

    break;

    case ‘password’:

    style.backgroundImage=”url(BG.gif)”;

    break;

    case ‘submit’:

    style.backgroundColor=”blue”;

    style.color=”white”;

    break;

}

</script>

优点:可以分区出各个input控件形态。

缺点:在js没有起作用之前,各个input还是原始状态,然后突然“变帅”会让你的页面很奇怪。较致命的是FireFox不支持

4.用Skin设置

Skin文件参考代码:

<asp:TextBox runat=”server” style=”background-color:#FFC “></asp:TextBox>

<asp:Button runat=”server” style=”background-color:red”></asp:Button>

注意里面的样式是用style加上的,而不是用cssClass,道理很简单,如果用cssClass,前面的再用cssClass就会覆盖这个cssClass。导致失败。当然,skin不能单独使用,还要配合css样式表。

优点:可以分区出各个控件形态(注意:skin只能对服务器端控件使用,所以现在已经不是单纯的input标签了,虽然这些服务器端控件“打到”前台的时候仍然是input控件)。

缺点:只能对服务器端控件使用。

CSS兼容IE/Firefox要点

首先我们说说firefox和IE对CSS的宽度显示有什么不同: 
  其实CSS ’width’ 指的是标准CSS中所指的width的宽度,在firefox中的宽度就是这个宽度。它只包含容器中内容的宽度。而Internet Explorer ’width’则是指整个容器的宽度,包括内容,padding ,border。 
Firefox中:容器占的宽度=内容宽度+padding宽度+border宽度 
IE中:内容宽度=您定义的容器宽度(Internet Explorer ’width’)-padding宽度-border宽度 

  所以,如果IE中定义 width:120px;padding:5px 的话,所显示的宽度就是120px. 
  即padding:5px是在width里面。 
  而Firefox中,上面这个定义,显示宽度就是 125 px; 
  所以,我们就必须这样定义 
   

width:115px !important;width:120px;padding:5px;

 

  必须注意的是, !important; 一定要在前面。  

CSS 兼容要点:
DOCTYPE 影响 CSS 处理 
FF: div 设置 margin-left, margin-right 为 auto 时已经居中, IE 不行
FF: body 设置 text-align 时, div 需要设置 margin: auto(主要是 margin-left,margin-right) 方可居中
FF: 设置 padding 后, div 会增加 height 和 width, 但 IE 不会, 故需要用 !important 多设一个 height 和 width
FF: 支持 !important, IE 则忽略, 可用 !important 为 FF 特别设置样式
div 的垂直居中问题: vertical-align:middle; 将行距增加到和整个DIV一样高 line-height:200px; 然后插入文字,就垂直居中了。缺点是要控制内容不要换行
cursor: pointer 可以同时在 IE FF 中显示游标手指状, hand 仅 IE 可以
FF: 链接加边框和背景色,需设置 display: block, 同时设置 float: left 保证不换行。参照 menubar, 给 a 和 menubar 设置高度是为了避免底边显示错位, 若不设 height, 可以在 menubar 中插入一个空格

XHTML+CSS兼容性解决方案小集
  使用XHTML+CSS构架好处不少,但也确实存在一些问题,不论是因为使用不熟练还是思路不清晰,我就先把一些我遇到的问题写在下面,省的大家四处找^^
在mozilla firefox和IE中的BOX模型解释不一致导致相差2px解决方法:
div{margin:30px!important;margin:28px;}注意这两个margin的顺序一定不能写反,据阿捷的说法!important这个属性IE不能识别,但别的浏览器可以识别。所以在IE下其实解释成这样:
div{maring:30px;margin:28px}重复定义的话按照最后一个来执行,所以不可以只写margin:XXpx!important; 
IE5 和IE6的BOX解释不一致IE5下div{width:300px;margin:0 10px 0 10px;}div的宽度会被解释为300px-10px(右填充)-10px(左填充)最终div的宽度为280px,而在IE6和其他浏览器上宽度则 是以300px+10px(右填充)+10px(左填充)=320px来计算的。这时我们可以做如下修改
div{width:300px!important;width /**/:340px;margin:0 10px 0 10px},关于这个/**/是什么我也不太明白,只知道IE5和firefox都支持但IE6不支持,如果有人理解的话,请告诉我一声,谢了!:) 
ul标签在Mozilla中默认是有padding值的,而在IE中只有margin有值所以先定义
ul{margin:0;padding:0;}就能解决大部分问题
关于脚本,在xhtml1.1中不支持language属性,只需要把代码改为
<script type=”text/javascript”>就可以了
margin加倍的问题
  设置为float的div在ie下设置的margin会加倍。这是一个ie6都存在的bug。
  解决方案是在这个div里面加上display:inline;
例如:
<#div id=”imfloat”></#div>
  相应的css为

#IamFloat{
float:left;
margin:5px;/*IE下理解为10px*/
display:inline;/*IE下再理解为5px*/}

用js直接读取Rss新闻的两种方法

在这里我主要是用了两种方法:

第一种是直接用js来访问,这种方法的优点是简单,但缺点是不能在firefox上使用

第二种是用prototype进行实现,当然对ie和firefox就都能满足了

但不论你是用哪种方法,都会面临一个问题:

由于客户端浏览器的安全设置问题,从客户端JavaScript脚本中用XMLHttpRequest直接访问第三方的网址是被禁止的。

最简单的方法就是在自己的服务器上添加一个代理,客户端脚本先把请求发送给代理,代理转发请求,把响应发回给客户端脚本。

所以,我们先在自己的服务器上添加一个代理

/**
 * 
 */
package com.sech.web.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

/**
 * 
 * <p>
 * Copyright: Copyright (c) 2009
 * </p>
 * 
 * @author sech
 * 
 * @version 1.0
 */
public class RssRead extends HttpServlet {
	/**
	 * 
	 */
	private static final long serialVersionUID = 4431127246599359389L;
	private static int READ_BUFFER_SIZE = 1024;

	/**
	 * 
	 */
	public RssRead() {
		// TODO Auto-generated constructor stub
	}

	public void init() throws ServletException {
	}

	// Process the HTTP Get request
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String urlString = request.getParameter("url");		
		writeResponse(response, urlString);
	}

	private void writeResponse(HttpServletResponse response, String urlString)
			throws ServletException {
		try {
			URL url = new URL(urlString);
			URLConnection urlConnection = url.openConnection();
			response.setContentType(urlConnection.getContentType());
			InputStream ins = urlConnection.getInputStream();
			OutputStream outs = response.getOutputStream();
			byte[] buffer = new byte[READ_BUFFER_SIZE];
			int bytesRead = 0;
			while ((bytesRead = ins.read(buffer, 0, READ_BUFFER_SIZE)) != -1) {
				outs.write(buffer, 0, bytesRead);
			}
			outs.flush();
			outs.close();
			ins.close();
		} catch (Exception e) {
			try {
				response.sendError(
						HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e
								.getMessage());
			} catch (IOException ioe) {
				throw new ServletException(ioe);
			}
		}
	}

	// Process the HTTP Post request
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

	// Clean up resources
	public void destroy() {
	}
}
然后再在web.xml中配置下:
<servlet>
    <servlet-name>rssread</servlet-name>
    <servlet-class>com.sech.web.servlet.RssRead</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>rssread</servlet-name>
    <url-pattern>/rssread</url-pattern>
  </servlet-mapping>

这样我们就可以直接访问:http://localhost/rssread 了

既然已经建立了服务器代理,那下面我们就进行js的编写.
第一种:
function get_news(servername)
{
	var URL,i;
	var s_wz,e_wz,str,htmlText;
	htmlText = "";
	URL = servername+"rssread url=http://news.sohu.com/rss/shehui.xml";	
	var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
	xmlDoc.async=false;
	xmlDoc.load(URL);
	nodes = xmlDoc.documentElement.childNodes;
	var ItemN = xmlDoc.getElementsByTagName("item");
	for(i=0;i<7;i++)
	{
		TextTitle = ItemN[i].selectSingleNode("title").text;//获取title内容
		TextLink = ItemN[i].selectSingleNode("link").text;//获取link内容
		//Textdescription = ItemN[0].selectSingleNode("description").text;
		//s_wz = Textdescription.indexOf("src='");
		//e_wz = Textdescription.indexOf("'",s_wz+5);
		//Imgurl = Textdescription.slice(s_wz+5,e_wz);
		htmlText = htmlText + "<LI><a href='"+TextLink+"' target=_blank>"+TextTitle+"</a></LI>"
	}
	return htmlText;

}
 html的调用:
<DIV class=textDiv id="news">
<UL>
<script  language="JavaScript">    
  document.writeln(sendRequest('http://localhost/'))
  </script>   
</UL>
</DIV>
 第二种方法:
var SendRequestAjax = Class.create();

SendRequestAjax.prototype ={ 
 
	initialize: function(servername) { 
		   this.servername = servername;
  },
  
	sendRequest:function(){	
    var url =this.servername+"rssread url=http://news.sohu.com/rss/shehui.xml";
    var pars = ""; 
    var myAjax = new Ajax.Request(url, {method: 'get', parameters: pars, onComplete: this.sendRequestCompleted.bind(this)});
},   

sendRequestCompleted:function(res){ 	 
    var results= res.responseXML; 
    var title = null; 
    var item = null; 
    var link = null; 
    var htmlText="";   
    var items = results.getElementsByTagName("item");     
    for(var i = 0; i <  7; i++) { 
        item = items[i]; 
        link=items[i].getElementsByTagName("link")[0].firstChild.nodeValue; 
        title = items[i].getElementsByTagName("title")[0].firstChild.nodeValue; 
        
        htmlText = htmlText + "<LI><a href='"+link+"' target=_blank>"+title+"</a></LI>"
    }    
    $("news").innerHTML="<UL>"+htmlText+"</UL>";    
}
}; 
function sendRequest(servername) { 
    var oSendRequestAjax = new SendRequestAjax(servername);
    oSendRequestAjax.sendRequest();        
}  
 html代码:
<script type="text/javascript" src="js/prototype.js"></script>
<DIV class=textDiv id="news">
<script  language="JavaScript">    
  (sendRequest('http://localhost/'))
  </script>   
</DIV>

 OK.这样两种方法就都搞定了.

javascript实现java中的Map(高效)[转]

javascript实现java中的Map,代码是在国外的一个网站上看到的(http://stackoverflow.com/questions/368280/javascript-hashmap-equivalent
),自己稍作了修改,之前也看到过有人用2个数组实现了Map,但是我感觉效率比较低,现在这个我感觉效率还可以,自己做了下测试,代码如下:

Map.js

Java代码 复制代码
  1. function Map(linkItems) {    
  2.     
    this
    .current = undefined; 
      
  3.     
    this
    ._size = 
    0
    ;    
  4.     
    if
    (linkItems === 
    false
    ){   
  5.         
    this
    .disableLinking();    
  6.     }    
  7. }   
  8. /**
     
  9.  * 获取当前map
     
  10.  * @return 当前对象
     
  11.  */
      
  12. Map.noop = function() {    
  13.     
    return
     
    this
    ;    
  14. };    
  15. /**
     
  16.  * 非法操作
     
  17.  * @return
     
  18.  */
      
  19. Map.illegal = function() {    
  20.     
    throw
     
    new
     Error(
    “非法操作,Map已经被禁用”
    );    
  21. };    
  22. /**
     
  23.  * 
     
  24.  * @param obj
     
  25.  * @param foreignKeys
     
  26.  * @return
     
  27.  */
      
  28. Map.from = function(obj, foreignKeys) {    
  29.     var map = 
    new
     Map; 
      
  30.     
    for
    (var prop in obj) { 
      
  31.         
    if
    (foreignKeys || obj.hasOwnProperty(prop)){
      
  32.             map.put(prop, obj[prop]);    
  33.         }    
  34.     }    
  35.     
    return
     map; 
      
  36. };    
  37. /**
     
  38.  * 禁用map
     
  39.  * @return
     
  40.  */
      
  41. Map.prototype.disableLinking = function() {    
  42.     
    this
    .link = Map.noop; 
      
  43.     
    this
    .unlink = Map.noop; 
      
  44.     
    this
    .disableLinking = Map.noop; 
      
  45.     
    this
    .next = Map.illegal; 
      
  46.     
    this
    .key = Map.illegal; 
      
  47.     
    this
    .value = Map.illegal; 
      
  48.     
    this
    .clear = Map.illegal; 
      
  49.     
    return
     
    this
    ;    
  50. };    
  51. /**
     
  52.  * 返回hash值 例如:number 123
     
  53.  * @param value key/value
     
  54.  * @return
     
  55.  */
      
  56. Map.prototype.hash = function(value) {    
  57.     
    return
     (typeof value) + 
    ‘ ‘
     + (value 
    instanceof
     Object   (value.__hash || (value.__hash = ++arguments.callee.current)) : value.toString()); 
      
  58. };    
  59. /**
     
  60.  * 返回map的长度
     
  61.  * @return
     
  62.  */
      
  63. Map.prototype.size = function() {    
  64.     
    return
     
    this
    ._size;   
  65. };    
  66.   
  67. Map.prototype.hash.current = 
    0
    ;    
  68. /**
     
  69.  * 通过key获取value
     
  70.  * @param key
     
  71.  * @return
     
  72.  */
      
  73. Map.prototype.get = function(key) {    
  74.     var item = 
    this
    [
    this
    .hash(key)];    
  75.     
    return
     item === undefined   undefined : item.value; 
      
  76. };    
  77. /**
     
  78.  * 向map中添加数据
     
  79.  * @param key 键
     
  80.  * @param value 值
     
  81.  * @return
     
  82.  */
      
  83. Map.prototype.put = function(key, value) {    
  84.     var hash = 
    this
    .hash(key);    
  85.     
    if
    (
    this
    [hash] === undefined) {    
  86.         var item = { key : key, value : value };    
  87.         
    this
    [hash] = item; 
      
  88.         
    this
    .link(item); 
      
  89.         ++
    this
    ._size; 
      
  90.     }
    else
    {
      
  91.         
    this
    [hash].value = value;   
  92.     }    
  93.     
    return
     
    this
    ;    
  94. };    
  95. /**
     
  96.  * 通过key删除数据
     
  97.  * @param key
     
  98.  * @return
     
  99.  */
      
  100. Map.prototype.remove = function(key) {    
  101.     var hash = 
    this
    .hash(key);    
  102.     var item = 
    this
    [hash]; 
      
  103.     
    if
    (item !== undefined) { 
      
  104.         —
    this
    ._size; 
      
  105.         
    this
    .unlink(item); 
      
  106.         delete 
    this
    [hash]; 
      
  107.     }    
  108.     
    return
     
    this
    ;    
  109. };    
  110. /**
     
  111.  * 清除map
     
  112.  * @return
     
  113.  */
      
  114. Map.prototype.clear = function() {    
  115.     
    while
    (
    this
    ._size){   
  116.         
    this
    .remove(
    this
    .key());    
  117.     }    
  118.     
    return
     
    this
    ;    
  119. };    
  120. /**
     
  121.  * 处理队列
     
  122.  * @param item
     
  123.  * @return
     
  124.  */
      
  125. Map.prototype.link = function(item) {    
  126.     
    if
    (
    this
    ._size == 
    0
    ) {    
  127.         item.prev = item;    
  128.         item.next = item;    
  129.         
    this
    .current = item; 
      
  130.     }
    else
     { 
      
  131.         item.prev = 
    this
    .current.prev;    
  132.         item.prev.next = item;    
  133.         item.next = 
    this
    .current;    
  134.         
    this
    .current.prev = item;   
  135.     }    
  136. };    
  137. Map.prototype.unlink = function(item) {    
  138.     
    if
    (
    this
    ._size == 
    0
    ){    
  139.         
    this
    .current = undefined;   
  140.     }
    else
     { 
      
  141.         item.prev.next = item.next;    
  142.         item.next.prev = item.prev;    
  143.         
    if
    (item === 
    this
    .current){   
  144.             
    this
    .current = item.next;    
  145.         }    
  146.     }    
  147. };    
  148. /**
     
  149.  * 获取下一个
     
  150.  * @return
     
  151.  */
      
  152. Map.prototype.next = function() {    
  153.     
    this
    .current = 
    this
    .current.next;    
  154.     
    return
     
    this
    ;   
  155. };    
  156. /**
     
  157.  * 获取key
     
  158.  * @return
     
  159.  */
      
  160. Map.prototype.key = function() {    
  161.     
    return
     
    this
    .current.key;    
  162. };    
  163. /**
     
  164.  * 获取value
     
  165.  * @return
     
  166.  */
      
  167. Map.prototype.value = function() {    
  168.     
    return
     
    this
    .current.value;    
  169. };   
function Map(linkItems) { 
    this.current = undefined; 
    this._size = 0; 
    if(linkItems === false){
    	this.disableLinking(); 
    } 
}
/**
 * 获取当前map
 * @return 当前对象
 */
Map.noop = function() { 
    return this; 
}; 
/**
 * 非法操作
 * @return
 */
Map.illegal = function() { 
    throw new Error("非法操作,Map已经被禁用"); 
}; 
/**
 * 
 * @param obj
 * @param foreignKeys
 * @return
 */
Map.from = function(obj, foreignKeys) { 
    var map = new Map; 
    for(var prop in obj) { 
        if(foreignKeys || obj.hasOwnProperty(prop)){
        	map.put(prop, obj[prop]); 
        } 
    } 
    return map; 
}; 
/**
 * 禁用map
 * @return
 */
Map.prototype.disableLinking = function() { 
    this.link = Map.noop; 
    this.unlink = Map.noop; 
    this.disableLinking = Map.noop; 
    this.next = Map.illegal; 
    this.key = Map.illegal; 
    this.value = Map.illegal; 
    this.clear = Map.illegal; 
    return this; 
}; 
/**
 * 返回hash值 例如:number 123
 * @param value key/value
 * @return
 */
Map.prototype.hash = function(value) { 
    return (typeof value) + ' ' + (value instanceof Object   (value.__hash || (value.__hash = ++arguments.callee.current)) : value.toString()); 
}; 
/**
 * 返回map的长度
 * @return
 */
Map.prototype.size = function() { 
    return this._size;
}; 

Map.prototype.hash.current = 0; 
/**
 * 通过key获取value
 * @param key
 * @return
 */
Map.prototype.get = function(key) { 
    var item = this[this.hash(key)]; 
    return item === undefined   undefined : item.value; 
}; 
/**
 * 向map中添加数据
 * @param key 键
 * @param value 值
 * @return
 */
Map.prototype.put = function(key, value) { 
    var hash = this.hash(key); 
    if(this[hash] === undefined) { 
        var item = { key : key, value : value }; 
        this[hash] = item; 
        this.link(item); 
        ++this._size; 
    }else{
    	this[hash].value = value;
    } 
    return this; 
}; 
/**
 * 通过key删除数据
 * @param key
 * @return
 */
Map.prototype.remove = function(key) { 
    var hash = this.hash(key); 
    var item = this[hash]; 
    if(item !== undefined) { 
        --this._size; 
        this.unlink(item); 
        delete this[hash]; 
    } 
    return this; 
}; 
/**
 * 清除map
 * @return
 */
Map.prototype.clear = function() { 
    while(this._size){
		this.remove(this.key()); 
	} 
    return this; 
}; 
/**
 * 处理队列
 * @param item
 * @return
 */
Map.prototype.link = function(item) { 
    if(this._size == 0) { 
        item.prev = item; 
        item.next = item; 
        this.current = item; 
    }else { 
        item.prev = this.current.prev; 
        item.prev.next = item; 
        item.next = this.current; 
        this.current.prev = item;
    } 
}; 
Map.prototype.unlink = function(item) { 
    if(this._size == 0){ 
        this.current = undefined;
    }else { 
        item.prev.next = item.next; 
        item.next.prev = item.prev; 
        if(item === this.current){
        	this.current = item.next; 
        } 
    } 
}; 
/**
 * 获取下一个
 * @return
 */
Map.prototype.next = function() { 
    this.current = this.current.next; 
    return this;
}; 
/**
 * 获取key
 * @return
 */
Map.prototype.key = function() { 
    return this.current.key; 
}; 
/**
 * 获取value
 * @return
 */
Map.prototype.value = function() { 
    return this.current.value; 
}; 

测试代码如下:

Java代码 复制代码
  1. var l=
    10000
    ;
      

  2.     var map=
    new
     Map();
      
  3.     var start=
    new
     Date().getTime();   
  4.     
    for
    (var i=
    0
    ;i<l;i++){   
  5.         map.put(
    “key_”
    +i,
    new
     Date());   
  6.     }   
  7.     var end=
    new
     Date().getTime();   
  8.     document.write(
    “向map中添加了  “
    +l+
    ” 个Date对象……….”
    );   
  9.     document.write(
    “<br/>”
    );   
  10.     document.write(
    “耗时  “
    +(end-start)+
    ” 毫秒,map的长度为:”
    +map.size());   
  11.     document.write(
    “<br/>”
    );   
  12.     document.write(
    “在map中提取全部数据……….”
    );   
  13.     document.write(
    “<br/>”
    );   
  14.     start=
    new
     Date().getTime();   
  15.     
    for
    (var i=
    0
    ;i<map.size();i++){   
  16.         map.get(
    “key_”
    +i).getTime();   
  17.     }   
  18.     end=
    new
     Date().getTime();
      
  19.     document.write(
    “耗时  “
    +(end-start)+
    ” 毫秒”
    );   
  20.     document.write(
    “<br/>”
    );   
  21.     document.write(
    “清空map……….”
    );   
  22.     document.write(
    “<br/>”
    );   
  23.     start=
    new
     Date().getTime();   
  24.     map.clear();   
  25.     end=
    new
     Date().getTime();
      
  26.     document.write(
    “耗时  “
    +(end-start)+
    ” 毫秒,map的长度为:”
    +map.size());   
  27.     document.write(
    “<br/>”
    );  
var l=10000;
	var map=new Map();
	var start=new Date().getTime();
	for(var i=0;i<l;i++){
		map.put("key_"+i,new Date());
	}
	var end=new Date().getTime();
	document.write("向map中添加了  "+l+" 个Date对象..........");
	document.write("<br/>");
	document.write("耗时  "+(end-start)+" 毫秒,map的长度为:"+map.size());
	document.write("<br/>");
	document.write("在map中提取全部数据..........");
	document.write("<br/>");
	start=new Date().getTime();
	for(var i=0;i<map.size();i++){
		map.get("key_"+i).getTime();
	}
	end=new Date().getTime();
	document.write("耗时  "+(end-start)+" 毫秒");
	document.write("<br/>");
	document.write("清空map..........");
	document.write("<br/>");
	start=new Date().getTime();
	map.clear();
	end=new Date().getTime();
	document.write("耗时  "+(end-start)+" 毫秒,map的长度为:"+map.size());
	document.write("<br/>");

测试结果如下:
1.IE7

2.Firefox 3.6.8

3.谷歌浏览器5.0

方法next的使用:

Java代码 复制代码
  1. var map=
    new
     Map();
      

  2.     map.put(
    “key_1”
    ,
    “value_1”
    );   
  3.     map.put(
    “key_2”
    ,
    “value_2”
    );   
  4.     map.put(
    “key_3”
    ,
    “value_3”
    );   
  5.     var m=map.next();   
  6.     document.write(
    “map.next:key=”
    +m.key()+
    ” value=”
    +m.value());   
  7.     document.write(
    “<br/>”
    );   
  8.     m=map.next();   
  9.     document.write(
    “map.next:key=”
    +m.key()+
    ” value=”
    +m.value());  
var map=new Map();
	map.put("key_1","value_1");
	map.put("key_2","value_2");
	map.put("key_3","value_3");
	var m=map.next();
	document.write("map.next:key="+m.key()+" value="+m.value());
	document.write("<br/>");
	m=map.next();
	document.write("map.next:key="+m.key()+" value="+m.value());

结果如下:

Java代码 复制代码
  1. map.next:key=key_2 value=value_2   
  2. map.next:key=key_3 value=value_3  

iefirefoxjavascript

1.document.formName.item(“itemName”) 问题


说 明:IE下,可以使用document.formName.item(“itemName”)或 document.formName.elements[“elementName”];Firefox下,只能使用 document.formName.elements[“elementName”].
解决方法:统一使用document.formName.elements[“elementName”].

2.集合类对象问题

说明:IE下,可以使用()或[]获取集合类对象;Firefox下,只能使用[]获取集合类对象.
解决方法:统一使用[]获取集合类对象.

3.自定义属性问题

说明:IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性;Firefox下,只能使用getAttribute()获取自定义属性.
解决方法:统一通过getAttribute()获取自定义属性.

4.eval(“idName”)问题

说明:IE下,,可以使用eval(“idName”)或getElementById(“idName”)来取得id为idName的HTML对 象;Firefox下只能使用getElementById(“idName”)来取得id为idName的HTML对象.
解决方法:统一用getElementById(“idName”)来取得id为idName的HTML对象.

5.变量名与某HTML对象ID相同的问题

说明:IE下,HTML对象的ID可以作为document的下属对象变量名直接使用;Firefox下则不能.Firefox下,可以使用与HTML对象ID相同的变量名;IE下则不能。
解决方法:使用document.getElementById(“idName”)代替document.idName.最好不要取HTML对象ID相同的变量名,以减少错误;在声明变量时,一律加上var,以避免歧义.

6.const问题

说明:Firefox下,可以使用const关键字或var关键字来定义常量;IE下,只能使用var关键字来定义常量.
解决方法:统一使用var关键字来定义常量.

7.input.type属性问题

说明:IE下input.type属性为只读;但是Firefox下input.type属性为读写.

8.window.event问题

说明:window.event只能在IE下运行,而不能在Firefox下运行,这是因为Firefox的event只能在事件发生的现场使用.
解决方法:
IE:
<input name=”Button8_1″ type=”button” value=”IE” onclick=”javascript:gotoSubmit8_1()”/>

<script language=”javascript”>
function gotoSubmit8_1() {

alert(window.event); //use window.event

}
</script>
IE&Firefox:
<input name=”Button8_2″ type=”button” value=”IE” onclick=”javascript:gotoSubmit8_2(event)”/>

<script language=”javascript”>
function gotoSubmit8_2(evt) {

evt=evt evt:(window.event window.event:null);
alert(evt); //use evt

}
</script>

9.event.x与event.y问题

说明:IE下,even对象有x,y属性,但是没有pageX,pageY属性;Firefox下,even对象有pageX,pageY属性,但是没有x,y属性.
解决方法:使用mX(mX = event.x   event.x : event.pageX;)来代替IE下的event.x或者Firefox下的event.pageX.

10.event.srcElement问题

说明:IE下,even对象有srcElement属性,但是没有target属性;Firefox下,even对象有target属性,但是没有srcElement属性.
解决方法:使用obj(obj = event.srcElement   event.srcElement : event.target;)来代替IE下的event.srcElement或者Firefox下的event.target.

11.window.location.href问题

说明:IE或者Firefox2.0.x下,可以使用window.location或window.location.href;Firefox1.5.x下,只能使用window.location.
解决方法:使用window.location来代替window.location.href.

12.模态和非模态窗口问题

说明:IE下,可以通过showModalDialog和showModelessDialog打开模态和非模态窗口;Firefox下则不能.
解决方法:直接使用window.open(pageURL,name,parameters)方式打开新窗口。如果需要将子窗口中的参数传递回父窗口, 可以在子窗口中使用window.opener来访问父窗口. 例如:var parWin = window.opener; parWin.document.getElementById(“Aqing”).value = “Aqing”;

13.frame问题

以下面的frame为例:
<frame src=”xxx.html” id=”frameId” name=”frameName” />

(1)访问frame对象:
IE:使用window.frameId或者window.frameName来访问这个frame对象.
Firefox:只能使用window.frameName来访问这个frame对象.
另外,在IE和Firefox中都可以使用window.document.getElementById(“frameId”)来访问这个frame对象.

(2)切换frame内容:
在IE和Firefox中都可以使用window.document.getElementById(“testFrame”).src = “xxx.html”或window.frameName.location = “xxx.html”来切换frame的内容.

如果需要将frame中的参数传回父窗口,可以在frme中使用parent来访问父窗口。例如:parent.document.form1.filename.value=”Aqing”;

14.body问题

Firefox的body在body标签没有被浏览器完全读入之前就存在;而IE的body则必须在body标签被浏览器完全读入之后才存在.

例如:
Firefox:
<body>
<script type=”text/javascript”>
document.body.onclick = function(evt){
evt = evt || window.event;
alert(evt);
}
</script>
</body>
IE&Firefox:
<body>
</body>
<script type=”text/javascript”>
document.body.onclick = function(evt){
evt = evt || window.event;
alert(evt);
} </script>

15. 事件委托方法

IE:document.body.onload = inject; //Function inject()在这之前已被实现
Firefox:document.body.onload = inject();
有人说标准是:
document.body.onload=new Function(‘inject()’);

16. firefox与IE(parentElement)的父元素的区别

IE:obj.parentElement
firefox:obj.parentNode
解决方法: 因为firefox与IE都支持DOM,因此使用obj.parentNode是不错选择.

17.cursor:hand VS cursor:pointer

firefox不支持hand,但ie支持pointer
解决方法: 统一使用pointer

18.innerText在IE中能正常工作,但是innerText在FireFox中却不行.

解决方法:
if(navigator.appName.indexOf(“Explorer”) > -1){

document.getElementById(‘element’).innerText = “my text”;

} else{

document.getElementById(‘element’).textContent = “my text”;

}

19. FireFox中类似 obj.style.height = imgObj.height 的语句无效

解决方法:
obj.style.height = imgObj.height + ‘px’;

20. ie,firefox以及其它浏览器对于 table 标签的操作都各不相同,在ie中不允许对table和tr的innerHTML赋值,使用js增加一个tr时,使用appendChile方法也不管用。

解决方法:
//向table追加一个空行:
var row = otable.insertRow(-1);
var cell = document.createElement(“td”);
cell.innerHTML = ” “;
cell.className = “XXXX”;
row.appendChild(cell);

21. padding 问题

padding 5px 4px 3px 1px FireFox无法解释简写,必须改成 padding-top:5px; padding-right:4px; padding-bottom:3px; padding-left:1px;

22. 消除ul、ol等列表的缩进时

样式应写成:list-style:none;margin:0px;padding:0px;
其中margin属性对IE有效,padding属性对FireFox有效

23. CSS透明

IE:filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=60)。
FF:opacity:0.6。

24. CSS圆角

IE:不支持圆角。
FF: -moz-border-radius:4px,或者-moz-border-radius-topleft:4px;-moz-border- radius-topright:4px;-moz-border-radius-bottomleft:4px;-moz-border- radius- bottomright:4px;。

25. CSS双线凹凸边框

IE:border:2px outset;。
FF: -moz-border-top-colors: #d4d0c8 white;-moz-border-left-colors: #d4d0c8 white;-moz-border-right-colors:#404040 #808080;-moz-border-bottom-colors:#404040 #808080;

以下以 IE 代替 Internet Explorer,以 MF或FF代替 Mozzila Firefox
1:innerText
IE支持,FIREFOX不支持
解决办法:用innerHTML,2种浏览器都识别innerHTML

2:document.createElement
document.appendChild
在往表里插入行时
FIREFOX支持,IE不支持
解决办法:把行插入到TBODY中,不要直接插入到表

3:setAttribute(‘style’,’color:red;’)
FIREFOX支持(除了IE,现在所有浏览器都支持),IE不支持
解决办法:不用setAttribute(‘style’,’color:red’)
而用object.style.cssText = ‘color:red;'(这写法也有例外)
最好的办法是上面种方法都用上,万无一失 ^_^
4:class
setAttribute(‘class’,’styleClass’)
FIREFOX支持,IE不支持(指定属性名为CLASS,IE不会设置元素的CLASS属性,相反只使用SETATTRIBUTE时IE自动识别CLASSNAME属性)
解决办法:
setAttribute(‘class’,’styleClass’)
setAttribute(‘className’,’styleClass’)
2种都用上(注:IE和FF都支持object.className)

5:用setAttribute设置事件
var obj = document.getElementById(‘objId’);
obj.setAttribute(‘onclick‘,’funcitonname();’);
FIREFOX支持,IE不支持
解决办法:
IE中必须用点记法来引用所需的事件处理程序,并且要用赋予匿名函数
如下:
var obj = document.getElementById(‘objId’);
obj.onclick=function(){fucntionname();};
这种方法所有浏览器都支持

6:建立单选钮
IE以外的浏览器
var rdo = document.createElement(‘input’);
rdo.setAttribute(‘type’,’radio’);
rdo.setAttribute(‘name’,’radiobtn’);
rdo.setAttribute(‘value’,’checked’);

IE:
var rdo =document.createElement(“<input type=’radio’ name=’radiobtn’ value=’checked’>”);
解决办法:
这一点区别和前面的都不一样。这次完全不同,所以找不到共同的办法来解决,那么只有IF-ELSE了
万幸的是,IE可以识别出document的uniqueID属性,别的浏览器都不可以识别出这一属性。问题解决。

0:共同的一些技巧
在动态建立INPUT型输入元素时,一般是先加入,在设置TYPE。这就有可能出错

好习惯:var btn = document.createElement(‘input’);
btn.setAttribut(‘type’,’button’);
document.getElementById(‘formId’).appendChild(btn);

==================================================================================
1. document.form.item 问题
(1)现有问题:
现有代码中存在许多 document.formName.item(“itemName”) 这样的语句,不能在 MF 下运行
(2)解决方法:
改用 document.formName.elements[“elementName”]
(3)其它
参见 2

2. 集合类对象问题
(1)现有问题:
现有代码中许多集合类对象取用时使用 (),IE 能接受,MF 不能。
(2)解决方法:
改用 [] 作为下标运算。如:document.forms(“formName”) 改为 document.forms[“formName”]。
又如:document.getElementsByName(“inputName”)(1) 改为 document.getElementsByName(“inputName”)[1]
(3)其它

3. window.event
(1)现有问题:
使用 window.event 无法在 MF 上运行
(2)解决方法:
MF 的 event 只能在事件发生的现场使用,此问题暂无法解决。可以这样变通:
原代码(可在IE中运行):
<input type=”button” name=”someButton” value=”提交” onclick=”java script:gotoSubmit()”/>

<script language=”javascript”>
function gotoSubmit() {

alert(window.event); // use window.event

}
</script>

新代码(可在IE和MF中运行):
<input type=”button” name=”someButton” value=”提交” onclick=”java script:gotoSubmit(event)”/>

<script language=”javascript”>
function gotoSubmit(evt) {
evt = evt   evt : (window.event   window.event : null);

alert(evt); // use evt

}
</script>
此外,如果新代码中第一行不改,与老代码一样的话(即 gotoSubmit 调用没有给参数),则仍然只能在IE中运行,但不会出错。所以,这种方案 tpl 部分仍与老代码兼容。

4. HTML 对象的 id 作为对象名的问题
(1)现有问题
在 IE 中,HTML 对象的 ID 可以作为 document 的下属对象变量名直接使用。在 MF 中不能。
(2)解决方法
用 getElementById(“idName”) 代替 idName 作为对象变量使用。

5. 用idName字符串取得对象的问题
(1)现有问题
在IE中,利用 eval(idName) 可以取得 id 为 idName 的 HTML 对象,在MF 中不能。
(2)解决方法
用 getElementById(idName) 代替 eval(idName)。

6. 变量名与某 HTML 对象 id 相同的问题
(1)现有问题
在 MF 中,因为对象 id 不作为 HTML 对象的名称,所以可以使用与 HTML 对象 id 相同的变量名,IE 中不能。
(2)解决方法
在声明变量时,一律加上 var ,以避免歧义,这样在 IE 中亦可正常运行。
此外,最好不要取与 HTML 对象 id 相同的变量名,以减少错误。
(3)其它
参见 问题4

7. event.x 与 event.y 问题
(1)现有问题
在IE 中,event 对象有 x, y 属性,MF中没有。
(2)解决方法
在MF中,与event.x 等效的是 event.pageX。但event.pageX IE中没有。
故采用 event.clientX 代替 event.x。在IE 中也有这个变量。
event.clientX 与 event.pageX 有微妙的差别(当整个页面有滚动条的时候),不过大多数时候是等效的。

如果要完全一样,可以稍麻烦些:
mX = event.x   event.x : event.pageX;
然后用 mX 代替 event.x
(3)其它
event.layerX 在 IE 与 MF 中都有,具体意义有无差别尚未试验。

8. 关于frame
(1)现有问题
在 IE中 可以用window.testFrame取得该frame,mf中不行
(2)解决方法
在frame的使用方面mf和ie的最主要的区别是:
如果在frame标签中书写了以下属性:
<frame src=”xx.htm” id=”frameId” name=”frameName” />
那么ie可以通过id或者name访问这个frame对应的window对象
而mf只可以通过name来访问这个frame对应的window对象
例如如果上述frame标签写在最上层的window里面的htm里面,那么可以这样访问
ie: window.top.frameId或者window.top.frameName来访问这个window对象
mf: 只能这样window.top.frameName来访问这个window对象

另外,在mf和ie中都可以使用window.top.document.getElementById(“frameId”)来访问frame标签
并且可以通过window.top.document.getElementById(“testFrame”).src = ‘xx.htm’来切换frame的内容
也都可以通过window.top.frameName.location = ‘xx.htm’来切换frame的内容
关于frame和window的描述可以参见bbs的‘window与frame’文章
以及/test/js/test_frame/目录下面的测试

9. 在mf中,自己定义的属性必须getAttribute()取得
10.在mf中没有 parentElement parement.children 而用
parentNode parentNode.childNodes
childNodes的下标的含义在IE和MF中不同,MF使用DOM规范,childNodes中会插入空白文本节点。
一般可以通过node.getElementsByTagName()来回避这个问题。
当html中节点缺失时,IE和MF对parentNode的解释不同,例如
<form>
<table>
<input/>
</table>
</form>
MF中input.parentNode的值为form, 而IE中input.parentNode的值为空节点

MF中节点没有removeNode方法,必须使用如下方法 node.parentNode.removeChild(node)

11.const 问题
(1)现有问题:
在 IE 中不能使用 const 关键字。如 const constVar = 32; 在IE中这是语法错误。
(2)解决方法:
不使用 const ,以 var 代替。

12. body 对象
MF的body在body标签没有被浏览器完全读入之前就存在,而IE则必须在body完全被读入之后才存在

13. url encoding
在js中如果书写url就直接写&不要写&例如var url = ‘xx.jsp objectName=xx&objectEvent=xxx’;
frm.action = url那么很有可能url不会被正常显示以至于参数没有正确的传到服务器
一般会服务器报错参数没有找到
当然如果是在tpl中例外,因为tpl中符合xml规范,要求&书写为&
一般MF无法识别js中的

14. nodeName 和 tagName 问题
(1)现有问题:
在MF中,所有节点均有 nodeName 值,但 textNode 没有 tagName 值。在 IE 中,nodeName 的使用好象
有问题(具体情况没有测试,但我的IE已经死了好几次)。
(2)解决方法:
使用 tagName,但应检测其是否为空。

15. 元素属性
IE下 input.type属性为只读,但是MF下可以修改

16. document.getElementsByName() 和 document.all[name] 的问题
(1)现有问题:
在 IE 中,getElementsByName()、document.all[name] 均不能用来取得 div 元素(是否还有其它不能取的元素还不知道)。

======================================================================================================
1. 向表中追加行
这是IE和Firefox,Safari,Opera都支持的代码
var cell = documentcreateElement(“td”).appendChild(document.createTextNode(“foo”));
var row = document.createElement(“tr”).appendChild(cell);
document.getElementById(“MyTableBoyd”).appendChild(row);
或者:在TR的父节点添加TBODY。(注:在IE中,利用DOM动态添加表格的行时,在TR的上一层必须添加TBODY,否则动态添加之后无法显示出来)

2. 通过JAVASCRIPT设置元素的样式
var spanElement = document.getElementById(“myspan”);
//spanElement.setAttribute(“style”,”font-weight:bold;color:red”); //IE之外的浏览器
spanElement.style.cssText=”font-weight:bold;color:red”; //IE的方法cssText不是标准属性,但得到IE支持

3. IE和FF在添加Option兼容操作,这里直接贴出本人的代码(注:FF支持直接将Option列表以innerHTML形式嵌入到select节点,但IE不支持)
function removeAllOptions(select_id){
var com=document.getElementById(select_id);
var len=com.options.length;
for(var i=0;i<len;i++){
com.remove(0);
}
}
function addOption(e_select,value,text){
var oOption = document.createElement(“option”);
e_select.options.add(oOption);
if(text!=null){
var text_node=document.createTextNode(text);
oOption.appendChild(text_node);
}
if(value!=null){
oOption.value = value;
}
}

4. 创建输入元素(通用代码)
var button = document.createElement(“input”);
button.setAttribute(“type”,”button”);
document.getElementById(“form”).appendChild(button);

5. 向输入元素增加事件处理程序(通用代码)
var element = document.getElementById(“ee”);
element.onclick=function(){todo();};

6. 创建单选按钮
var ration = document.createElement(“<input type=’radio’ name=’radionsss’ value=’checked’>”);//ie
//非ie创建方法
vat radion = document.createElement(“input”);
radion .setAttribute(“type”,”radio”);
radion.setAttribute(“name”,”radionsss”);
radion.setAttribute(“value”,”checked”);

ckedit上传图片到数据库


 

 

 

 

 

 

 

 

 

 

 

 最近要实现在ckedit上传图片,而且要上传保存到数据库,在网站找了不少资料,基本上都是保存到服务器的文件夹,但那些资料对我也起了很多作用。下面我把我的实现记录下来,作为备忘。(CKEditor 在jsp中实现文件上传的完整例子)http://blog.163.com/prevBlogPerma.do host=ytrtfhj@126&srl=890531092010226023136&mode=prev

 

ckeditor非常强大,但官网上它的图片/文件上传使用了ckfinder,比较麻烦。我首先是在图片链接输入框的右边加个按钮,点击事件链接到已有的上传模块,上传后把图片的下载url(这个花了我不少时间)传递给左边的输入框即可。步骤如下:

  打开plugins\image\dialogs\image.js,在链接输入框代码结尾也就是 m.lang.image.urlMissing)},后面加上这些代码:

{type:'button',id:'myUpload',align:'center',label:'新上传 ',onClick:function(){var thisDialog = this.getDialog();var txtUrlObj = thisDialog.getContentElement('info', 'txtUrl'); var txtUrlId = txtUrlObj.getInputElement().$.id; 
var retFile = window.open("info2j.zrx path=info/info_uploadImage&infotypeid="+top.document.getElementById('infotypeid').value+"&txtUrlId="+txtUrlId, "", "height=300, width=400"); if(retFile != null){this.getDialog().setValueOf('info','txtUrl',retFile);}}},

 

 {type:’button’,id:’myUpload’,align:’center’,label:’新上传 ‘,onClick:function(){var thisDialog = this.getDialog();var txtUrlObj = thisDialog.getContentElement(‘info’, ‘txtUrl’); var txtUrlId = txtUrlObj.getInputElement().$.id; 为了获得图片URL文本框的id,并可以传回页面;我这里由于jsp页面都是放在WEB-INF目录下,所以页面跳转是借助action来实现的。所谓我是先把id传到info2j.action,然后再从info_uploadImage.jsp页面拿,

var retFile = window.open(“info2j.action path=info/info_uploadImage&infotypeid=”+top.document.getElementById(‘infotypeid’).value+”&txtUrlId=”+txtUrlId, “”, “height=300, width=400”);

跳转到info_uploadImage.jsp页面,并把图片URL文本框的id传过去

下面是info_uploadImage.jsp的简单代码

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
	<head>
		
		<title>上传图片</title>
		<script type="text/javascript">
		
		function checkFormat(filePath){
			var i = filePath.lastIndexOf(".");
			var len = filePath.length;
			var str = filePath.substring(i+1,len);
			var extName = "JPG,GIF,PNG,BMP";
		
			if(extName.indexOf(str.toUpperCase()) < 0){
				alert("图片格式不正确");
				return false;
			}
			return true;
			
		}
		
		/*
		图标预览,兼容ie,firefox
		*/
		function fileChange(o){
			if(checkFormat(o.value)){
				if(window.ActiveXObject){
					document.getElementById("uploadImg").width = 100;
					document.getElementById("uploadImg").height = 100;
					document.getElementById("uploadImg").src = o.value;
				}else{
					document.getElementById("uploadImg").width = 100;
					document.getElementById("uploadImg").height = 100;
					document.getElementById("uploadImg").src = o.files[0].getAsDataURL();
				}
				
			}
		}

	   /* 给图片text附上图片地址*/
       function finish(generatedId){
       		//获得图片text的id
       		var imageUrl = document.getElementById("txtUrlId").value;
		   
		    alert("<s:text name='info.upload.success' />!");
		   
			window.opener.document.getElementById(imageUrl).value = "info_downloadImage.zrx imageId="+generatedId;
			window.opener.document.getElementById("previewImage").setAttribute("src","info_downloadImage.zrx imageId="+generatedId);
		    window.close();
	 }
       
    </script>

	</head>

	<body>
		
		
		<s:form id="uploadForm" name="uploadForm" method="post" action="info_upLoadImage.zrx" theme="simple"
			enctype="multipart/form-data"  target="frame">
			<s:hidden id="infotypeid" name="infotypeid"></s:hidden>
			<s:hidden id="txtUrlId" name="txtUrlId"></s:hidden>
			<table align="center">
				<tr>
					<td colspan="2"><s:file id="image" name="image" onchange="return fileChange(this)" /></td>
				</tr>
				<tr>
					<td><input type="submit" value="上传" onclick="upload()"/></td>
					<td><input type="button" value="取消" onclick="javascript:window.close();"/></td>
				</tr>
			</table>
			<div align="center">
				<img src="" width="0" height="0" id="uploadImg"/>
			</div>
			
			</s:form>
		
		
		<iframe name="frame" style="display:none"  src="_self">
			
		</iframe>
	</body>
</html>

 

下面是上传图片和下载图片方法

/**
	* 方法名:upLoadImage
	* 作者: 
	* 描述: 在信息内容编辑区上传图片到数据库
	* @return
	* @throws Exception
	* 日期:2010-4-20
	*/
	public String upLoadImage() throws Exception{
		
        if (null != image) {
            //上传图片
           
        	   infoImage = new InfoContentImage();

                String imageName = imageFileName; // 文件真名
                String imageType = imageContentType;
                Long length = image.length(); // 文件的真实大小

                // 设定InfoAttach对象的属性
                infoImage.setInfotypeid(new Long(infotypeid));
                infoImage.setImagename(imageName);
                infoImage.setImagetype(imageType);
                infoImage.setImagesize(length);
                infoImage.setDate(new Date());

                // 将上传的文件保存到数据库

                try {
                    InputStream is = new BufferedInputStream(new FileInputStream(image));

                    ByteArrayOutputStream os = new ByteArrayOutputStream();
                    int len = 0;
                    byte[] content = new byte[is.available()];

                    while (-1 != (len = is.read(content))) {
                        os.write(content);
                    }
                    infoImage.setImagecontent(os.toByteArray());
                    is.close();
                    os.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
		
        
        Long generatedId = this.infoService.saveInfoContentImage(infoImage);
		
		this.writeMessage("<script type='text/javascript'>parent.finish('"+ generatedId +"');</script>");
		return null;
	}


	
	
	/**
	* 方法名:downloadImage
	* 作者: 
	* 描述:
	* @return
	* @throws Exception
	* 日期:2010-4-21
	*/
	public String downloadImage() throws Exception{
		// 设置下载头文件
		HttpServletResponse response = this.getResponse();
		response.setCharacterEncoding("UTF-8");
		response.setContentType("image/*");
		
		
		OutputStream output = response.getOutputStream();
		
		infoImage = infoService.getInfoContentImageById(imageId);
		byte[] b = infoImage.getImagecontent();
		output.write(b);
		
		return null;
	}

 修改打开上传窗口可以打开多个和打开的窗口不居中的原因,修改原来的image.js

{type:'button',id:'myUpload',align:'center',label:'新上传 ',onClick:function(){var thisDialog = this.getDialog();
 var txtUrlObj = thisDialog.getContentElement('info', 'txtUrl'); var txtUrlId = txtUrlObj.getInputElement().$.id; 
var retFile = window.open("info2j.zrx path=info/info_uploadImage&infotypeid="+top.document.getElementById('infotypeid').value+"&txtUrlId="+txtUrlId, "上传图片", "height=300, width=400,top="+(screen.height-300)/2+",left="+(screen.width-400)/2); if(retFile != null){this.getDialog().setValueOf('info','txtUrl',retFile);}}},

 

  • 大小: 20 KB
  • 大小: 42.3 KB
  • 大小: 41.5 KB
  • 大小: 49.6 KB
  • 大小: 43.6 KB
  • 大小: 44.8 KB
  • 大小: 14.1 KB

DOM文档和Javascript的IE和Firefox兼容性

长久以来JavaScript兼容性一直是Web开发者的一个主要问题。在正式规范、事实标准以及各种实现之间的存在的差异让许多开发者日夜煎熬。为此,主要从以下几方面差异总结IE和Firefox的Javascript兼容性:

  一、函数和方法差异

  二、样式访问和设置

  三、DOM方法及对象引用

  四、事件处理

  五、其他差异的兼容处理

 

一、函数和方法差异

1
. getYear()方法

【分析说明】先看一下以下代码:

var year= new Date().getYear();
document.write(year);

  在IE中得到的日期是”2010″,在Firefox中看到的日期是”110″,主要是因为在 Firefox 里面 getYear 返回的是 “当前年份-1900” 的值。

【兼容处理】

  加上对年份的判断,如:

var year= new Date().getYear();
year = (year<1900 (1900+year):year);document.write(year);

  也可以通过 getFullYear getUTCFullYear 去调用:

var year = new Date().getFullYear();
document.write(year);

 

2
. eval()函数

【分析说明】在IE中,可以使用eval(“idName”)或getElementById(“idName”)来取得id为idName的
HTML对象;Firefox下只能使用getElementById(“idName”)来取得id为idName的HTML对象。

【兼容处理】统一用getElementById(“idName”)来取得id为idName的HTML对象。

 

3
. const声明

【分析说明】在 IE 中不能使用 const 关键字。如:

const constVar = 32; 

在IE中这是语法错误。

【兼容处理】不使用 const ,以 var 代替。

 

4
. var

【分析说明】请看以下代码:

echo=function(str){
 document.write(str);
}pre>

  这个函数在IE上运行正常,Firefox下却报错了。

【兼容处理】而在echo前加上var就正常了,这个就是我们提到var的目的。

 

5
. const 问题

【分析说明】在 IE 中不能使用 const 关键字。如 const constVar = 32; 在IE中这是语法错误。

【解决方法】不使用 const ,以 var 代替。

 

二、样式访问和设置

1
. CSS的”float”属性

【分析说明】Javascript访问一个给定CSS 值的最基本句法是:object.style.property,但部分CSS属性跟Javascript中的保留字命名相同,如”float”,”for”,”class”等,不同浏览器写法不同。

在IE中这样写:

document.getElementById("header").style.styleFloat = "left";

在Firefox中这样写:

document.getElementById("header").style.cssFloat = "left";

【兼容处理】在写之前加一个判断,判断浏览器是否是IE:

if(document.all){  document.getElementById("header").style.styleFloat = "left";}
else{  document.getElementById("header").style.cssFloat = "left";}

 

2
. 访问<label>标签中的”for”

【分析说明】和”float”属性一样,同样需要使用不现的句法区分来访问<label>标签中的”for”。

在IE中这样写:

var myObject = document.getElementById("myLabel");
var myAttribute = myObject.getAttribute("htmlFor");

在Firefox中这样写:

var myObject = document.getElementById("myLabel");
var myAttribute = myObject.getAttribute("for");

【兼容处理】解决的方法也是先

判断浏览器类型。

 

3
. 访问和设置class属性

【分析说明】同样由于class是Javascript保留字的原因,这两种浏览器使用不同的 JavaScript 方法来获取这个属性。

IE8.0之前的所有IE版本的写法:

var myObject = document.getElementById("header");
var myAttribute = myObject.getAttribute("className");

适用于IE8.0 以及 firefox的写法:

var myObject = document.getElementById("header");
var myAttribute = myObject.getAttribute("class");

  另外,在使用setAttribute()设置Class属性的时候,两种浏览器也存在同样的差异。

  setAttribute(“className”,value);

  这种写法适用于IE8.0之前的所有IE版本,注意:IE8.0也不支持”className”属性了。

  setAttribute(“class”,value);适用于IE8.0 以及 firefox。

【兼容处理】

方法一,两种都写上:

var myObject = document.getElementById("header");
myObject.setAttribute("class","classValue");
myObject.setAttribute("className","classValue"); //设置header的class为classValue

方法二,IE和FF都支持object.className,所以可以这样写:

var myObject = document.getElementById("header");
myObject.className="classValue";//设置header的class为classValue

方法三,先判断浏览器类型,再根据浏览器类型采用对应的写法。

 

4
. 对象宽高赋值问题

【分析说明】FireFox中类似 obj.style.height = imgObj.height 的语句无效。

【兼容处理】统一使用 obj.style.height = imgObj.height + ‘px’;

 

三、DOM方法及对象引用

1
. getElementById

【分析说明】先来看一组代码:

<!-- input对象访问1 -->
<input id="id" type="button" 
value="click me" ōnclick="alert(id.value)"/>

  在Firefox中,按钮没反应,在IE中,就可以,因为对于IE来说,一个HTML 元素的 ID 可以直接在脚本中当作变量名来使用,而Firefox中不可以。

【兼容处理】尽量采用W3C DOM 的写法,访问对象的时候,用document.getElementById(“id”) 以ID来访问对
象,且一个ID在页面中必须是唯一的,同样在以标签名来访问对象的时候,用document.getElementsByTagName(“div”)
[0] 。该方式得到较多浏览器的支持。

<!-- input对象访问2 -->
<input id="id" type="button" value="click me"  onclick="alert(document.getElementById('id').value)" />

 

2
. 集合类对象访问

【分析说明】IE下,可以使用()或[]获取集合类对象;Firefox下,只能使用[]获取集合类对象。如:

document.write(document.forms("formName").src);//该写法在IE下能访问到Form对象的scrc属性

 【兼容处理】将document.forms(“formName”)改为 document.forms[“formName”]。统一使用[]获取集合类对象。

 

3
. frame的引用

【分析说明】IE可以通过id或者name访问这个frame对应的window对象,而Firefox只可以通过name来访问这个frame对应的window对象。

  例如如果上述frame标签写在最上层的window里面的htm里面,那么可以这样访问:

IE: window.top.frameId或者window.top.frameName来访问这个window对象;

Firefox:只能这样window.top.frameName来访问这个window对象。

【兼容处理】使用frame的name来访问frame对象,另外,在IE和Firefox中都可以使用window.document.getElementById(”frameId”)来访问这个frame对象。

 

4
. parentElement

【分析说明】IE中支持使用parentElement和parentNode获取父节点。而Firefox只可以使用parentNode。 

【兼容处理】因为firefox与IE都支持DOM,因此统一使用parentNode来访问父节点。

 

5
. table操作

【分析说明】IE下table中无论是用innerHTML还是appendChild插入<tr>都没有效果,而其他浏览器却显示正常。

【兼容处理】解决的方法是,将<tr>加到table的<tbody>元素中,如下面所示:

var row = document.createElement("tr");
var cell = document.createElement("td");
var cell_text = document.createTextNode("插入的内容");
cell.appendChild(cell_text);
row.appendChild(cell);
document.getElementsByTagName("tbody")[0].appendChild(row);

 

6
. 移除节点removeNode()和removeChild()

【分析说明】appendNode在IE和Firefox下都能正常使用,但是removeNode只能在IE下用。

  removeNode方法的功能是删除一个节点,语法为node.removeNode(false)或者node.removeNode(true),返回值是被删除的节点。

  removeNode(false)表示仅仅删除指定节点,然后这个节点的原孩子节点提升为原双亲节点的孩子节点。

  removeNode(true)表示删除指定节点及其所有下属节点。被删除的节点成为了孤立节点,不再具有有孩子节点和双亲节点。

【兼容处理】Firefox中节点没有removeNode方法,只能用removeChild方法代替,先回到父节点,在从父节点上移除要移除的节点。

node.parentNode.removeChild(node);  // 为了在ie和firefox下都能正常使用,取上一层的父结点,然后remove。

 

7
. childNodes获取的节点

【分析说明】childNodes的下标的含义在IE和Firefox中不同,看一下下面的代码:

<ul id="main"> 
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul> 
<input type=button value="click me!" onclick="alert(document.getElementById('main').childNodes.length)"> 

分别用IE和Firefox运行,IE的结果是3,而Firefox则是7。Firefox使用DOM规范,”#text”表示文本(实际是无意义的空格和换行等)在Firefox里也会被解析成一个节点,在IE里只有有实际意义的文本才会解析成”#text”。

【兼容处理】

方法一,获取子节点时,可以通过node.getElementsByTagName()来回避这个问题。但是 getElementsByTagName对复杂的DOM结构遍历明显不如用childNodes,因为childNodes能更好的处理DOM的层次结构。

方法二,在实际运用中,Firefox在遍历子节点时,不妨在for循环里加上:

if(childNode.nodeName=="#text") continue;//或者使用nodeType == 1。

这样可以跳过一些文本节点。

延伸阅读

  《IE和FireFox中的childNodes区别

 

8
. Firefox不能对innerText支持

【分析说明】Firefox不支持innerText,它支持textContent来实现innerText,不过textContent没有像
innerText一样考虑元素的display方式,所以不完全与IE兼容。如果不用textContent,字符串里面不包含HTML代码也可以用
innerHTML代替。也可以用js写个方法实现,可参考《为firefox实现innerText属性
》一文。

【兼容处理】通过判断浏览器类型来兼容:

if(document.all){
document.getElementById('element').innerText = "my text";
} else{
document.getElementById('element').textContent = "my text";
}

 

四、事件处理

  如果在使用javascript的时候涉及到event处理,就需要知道event在不同的浏览器中的差异,主要的JavaScript的事件模型有三种(参考《Supporting Three Event Models at Once
》),它们分别是NN4、IE4+和W3C/Safar。

 

1
. window.event

【分析说明】先看一段代码

function et()
{ 
    alert(event);//IE: [object]
}

  以上代码在IE运行的结果是[object],而在Firefox无法运行。

  因为在IE中event作为window对象的一个属性可以直接使用,但是在Firefox中却使用了W3C的模型,它是通过传参的方法来传播事件的,也就是说你需要为你的函数提供一个事件响应的接口。

【兼容处理】添加对event判断,根据浏览器的不同来得到正确的event:

function et()
{ 
    evt=evt evt:(window.event window.event:null);    //兼容IE和Firefox
    alert(evt);
}

 

2
. 键盘值的取得

【分析说明】IE和Firefox获取键盘值的方法不同,可以理解,Firefox下的event.which与IE下的event.keyCode相当。关于彼此不同,可参考《键盘事件中keyCode、which和charCode 的兼容性测试

【兼容处理】

function myKeyPress(evt){    //兼容IE和Firefox获得keyBoardEvent对象
    evt = (evt)   evt : ((window.event)   window.event : "")      //兼容IE和Firefox获得keyBoardEvent对象的键值
    var key = evt.keyCode evt.keyCode:evt.which;     if(evt.ctrlKey && (key == 13 || key == 10)){        //同时按下了Ctrl和回车键
        //do something;
    }
}

 

3
. 事件源的获取

【分析说明】在使用事件委托的时候,通过事件源获取来判断事件到底来自哪个元素,但是,在IE下,event对象有srcElement属性,但是没有target属性;Firefox下,even对象有target属性,但是没有srcElement属性。 

【兼容处理】

ele=function(evt){ //捕获当前事件作用的对象
   evt=evt||window.event;
  return   (obj=event.srcElement event.srcElement:event.target;);
}

 

4
. 事件监听

【分析说明】在事件监听处理方面,IE提供了attachEvent和detachEvent两个接口,而Firefox提供的是addEventListener和removeEventListener。

【兼容处理】最简单的兼容性处理就是封装这两套接口:

function addEvent(elem, eventName, handler) {
  if (elem.attachEvent) {
    elem.attachEvent("on" + eventName, function(){                    handler.call(elem)});     //此处使用回调函数call(),让this指向elem
  } else if (elem.addEventListener) {
    elem.addEventListener(eventName, handler, false);
  }}
function removeEvent(elem, eventName, handler) {
  if (elem.detachEvent) {
    elem.detachEvent("on" + eventName, function(){                    handler.call(elem)});     //此处使用回调函数call(),让this指向elem
  } else if (elem.removeEventListener) {
    elem.removeEventListener(eventName, handler, false);
  }
}

  需要特别注意,Firefox下,事件处理函数中的this指向被监听元素本身,而在IE下则不然,可使用回调函数call,让当前上下文指向监听的元素。

 

5
. 鼠标位置

【分析说明】IE下,even对象有x,y属性,但是没有pageX,pageY属性;Firefox下,even对象有pageX,pageY属性,但是没有x,y属性。 

【兼容处理】使用mX(mX = event.x   event.x : event.pageX;)来代替IE下的event.x或者Firefox下的event.pageX。复杂点还要考虑绝对位置。

function getAbsPoint(e){
    var x = e.offsetLeft, y = e.offsetTop;
    while (e = e.offsetParent) {
        x += e.offsetLeft;
        y += e.offsetTop;
    }
    alert("x:" + x + "," + "y:" + y);
}

 

五、其他差异的兼容处理

1
. XMLHttpRequest

【分析说明】new ActiveXObject(“Microsoft.XMLHTTP”);只在IE中起作用,Firefox不支持,但支持XMLHttpRequest。

【兼容处理】

 

function createXHR() {
    var xhr=null; 
    if(window.XMLHttpRequest){
        xhr=new ActiveXObject("Msxml2.XMLHTTP"); 
    }else{ 
        try { 
            xhr=new ActiveXObject("Microsoft.XMLHTTP"); 
        } 
        catch() { 
            xhr=null; 
        } 
    }
    if(!xhr)return;
    return xhr;
}

 

2
. 模态和非模态窗口

【分析说明】IE中可以通过showModalDialog和showModelessDialog打开模态和非模态窗口,但是Firefox不支持。 

【解决办法】直接使用window.open(pageURL,name,parameters)方式打开新窗口。 如果需要传递参数,可以使用frame或者iframe。

 

3. 
input.type属性问题

 

IE下 input.type属性为只读,但是Firefox下可以修改

 

4
. 对select元素的option操作

设置options,IE和Firefox写法不同:

Firefox:可直接设置

option.text = 'foooooooo';

IE:只能设置

option.innerHTML = 'fooooooo';

删除一个select的option的方法:

Firefox:可以

select.options.remove(selectedIndex);

IE7:可以用

select.options[i] = null;

IE6:需要写

select.options[i].outerHTML = null;

 

5
. img对象alt和title的解析

【分析说明】img对象有alt和title两个属性,区别在于,alt:当照片不存在或者load错误时的提示。

title:照片的tip说明, 在IE中如果没有定义title,alt也可以作为img的tip使用,但是在Firefox中,两者完全按照标准中的定义使用 

在定义img对象时。

【兼容处理】最好将alt和title对象都写全,保证在各种浏览器中都能正常使用 。

 

6
. img的src刷新问题

【分析说明】先看一下代码:

<img id="pic" onclick= "this.src= 'a.jpg'"    src="aa.jpg" style="cursor: pointer"/>

在IE 下,这段代码可以用来刷新图片,但在FireFox下不行。主要是缓存问题。

【兼容处理】在地址后面加个随机数就解决了: 

<img id="pic" onclick= "javascript:this.src=this.src+' '     +Math.random()"src="a.jpg" style="cursor: pointer"/>

 

总结

  IE和Firefox的Javascript方面存在着不少的差异,要做到兼容,我觉得很有必要把一些常见的整理成一个js库,如DOM的操
作,事件的处理,XMLHttpRequest请求等,或者也可以选择使用现有的一些库(如jQuery,YUI,ExtJs等),不过我觉得还是有必要
了解一下这些差异,这样对于我们参加兼容性和可用性代码很有帮助。

  办法总比问题多,无论浏览器兼容如何折腾人,做前端开发的总能迎刃而解的!