[转]IE到Mozilla迁移指南(把应用从IE迁移到Mozilla)[英文]

 
Internet Explorer To Mozilla Migration Guide
  • Introduction
    • What is Mozilla
    • Mozilla Philosophy (standards compliant, etc)
  • General Cross Browser Coding Tips
    • Browser Detection the Right Way (capabilities VS browser specific checks)
    • Abstracting Out Browser Differences
  • DHTML
    • DOM Differences
      • document.all/global namespace VS document.getElementById
      • Document Fragments
      • Table of mappings from IE -> Standards/Mozilla (innerhtml)
    • JavaScript Differences
      • getYear() VS getFullYear
      • execution - adding code to the end won't mean everything else has completed - use onload handlers
      • window.open is async!
    • CSS
      • Units matter
      • Image spacing
    • Events
      • IE event model VS Netscape/W3C model
      • Table of mappings
  • Rich Text Editing
    • Differences between Designmode in IE and Mozilla
  • XML
    • whitespace differences in XML
      • nodeType == 3 for text nodes
    • XML Data Islands
    • XSLT
      • XSLT JS Interface
    • XML Web Services
      • XMLHttpRequest
      • SOAP
      • WSDL (?)
  • Quirks VS Standard Modes
    • Doctypes
  • Furthur reading
    • Books
    • Mozilla.org
    • DevEdge
General Cross Browser Coding Tips

Even though Web Standards exist, different browsers behave differently, sometimes even the same browser may behave so on different platforms.

Since different browsers sometimes use different apis for the same function, it is common to find multiple if() else() blocks throughout code to differentiate between browsers.

    . . .        var elm;    if (ns4)      elm = document.layers["myID"];    else if (ie4)      elm = document.all["myID"];  

The problem with doing this is that if a new browser is going to be supported, all these blocks need to be updated.

Therefore, when developing for multiple browsers, the easiest way to avoid the need to recode for a new browser is to abstract out functionality. Rather than multiple if() else() blocks throughout code, it is more efficient to take common tasks and abstract them out into their own functions. Not only does it make the code easier to read, it simplifies adding support for new clients.

    var elm = getElmById("myID");        function getElmById(aID){      var rv = null;          if (isMozilla || isIE5)        rv = document.getElementById(aID)      else if (isNetscape4)        rv = document.layers[aID]      else if (isIE4)        rv = document.all[aID];      return rv;    }  

However, there is still a issue with the code: the browser sniffing. Usually, browser sniffing is done via the useragent, such as:

      Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016

While useragent sniffing provides detailed information on what browser is being used, code handling useragents can make mistaked when new versions of browsers arrive, thus requiring code changes.

If the type of browser doesn't matter (say non-supported browser have already been blocked from accessing the web application), it is better to sniff by browser capability.

Rather than
       if (isMozilla || isIE5)
it should be:
       if (document.getElementById)

This would allow other browsers that support that command, like Opera or Safari, to work without any changes.

Useragent sniffing however does make sense when accuracy is important, such as verifying that a browser meets the version requirements of the web application or to workaround a bug in a certain version.

JavaScript allows inline conditional statements, which can help readability of code:

       var foo = (condition) ? conditionIsTrue : conditionIsFalse;

For example, to retrieve an element:

       function getElement(aID){         var rv = (document.getElementById) ? document.getElementById(aID) : document.all[aID];         return rv;       }
DOM Differences

The Document Object Model (DOM) is the tree structure holding the elements inside the document. DHTML's biggest use is to modify the DOM by JavaScript, and the most often used task is to get a reference to an element.

Accessing Elements

The cross-browser way to get an reference to an element is via document.getElementById(aID). This works in IE5.5+ and Mozilla-based browsers, and is part of the DOM Level 1 specification.

Mozilla does not support accessing an element via document.elementName or even just via its name, which Internet Explorer does. Mozilla also does not support the Netscape 4 document.layers method and Internet Explorer's document.all.

It is also sometimes needed to get references to all elements with the same tagname, and in Mozilla, the DOM Level 1 getElementsByTagName() is the way to do so It returns in JavaScript an array, and can be called on the document element or other nodes to access only their subtree. To get an array of all elements in the DOM tree, getElementsByTagName(*) can be used.

One common use of these methods is to move an element to a certain position and toggling its visibility (menus, animations). Netscape 4 used the tag, which mozilla does not support. For Mozilla, the

tag is used, as does IE.

Traversing the DOM

Mozilla supports the W3C DOM standard way of traversing the DOM tree. Children of an node can be accessed via node.childeNodes, which returns an array. Other methods available are firstChild and lastChild.

Nodes can access their parents via node.parentNode. Nodes can also acces their siblings via the node.nextSibling and node.previousSibling.

Generating and Manipulating Content

Mozilla supports the legacy methods for adding content into the DOM dynamically, such as document.write, document.open and document.close.

Mozilla also supports Internet Explorer's InnerHTML method, which can be called on almost any node. It does not however, support OuterHTML and innerText.

Internet Explorer has several content manipulation methods that are non-standard and not supported in Mozilla, such as retrieving the value, inserting text or inserting elements adjacent to an node such as getAdjacentElement and insertAdjacentHTML. Below is the chart of the W3C standard and Mozilla support ways of manipulation content, all of which are mehotds of any DOM node:

MethodDescription
appendChild( aNode )Creates a new child node. Returns a reference to the new child node.
cloneNode( aDeep )Makes a copy of the node it is called on and returns the copy. If aDeep is true, it recursively clones the subtree as well.
createElement( aTagName )Creates and returns a new, parentless DOM node of the type specified by aTagName.
createTextNode( aTextValue )Creates and returns a new, parentless DOM textnode with the data value specified by aTextValue.
insertBefore( aNewNode, aChildNode )Inserts aNewNode before aChildNode, which must be a child of the current node.
removeChild( aChildNode )Removes aChildNode and returns a reference to it.
replaceChild( aNewNode, aChildNode )Replaces aChildNode with aNewNode and returns a reference to the removed child node.
Document Fragments

For performance reasons, it can be usefull to create documents in memory, rather than working on the existing document's DOM. In DOM Level 1 Core, document fragments were introduced. They are "lightweight" documents, as they contain a subset of a normal document's interfaces. For example, getElementById does not exit, but appendChild does. Document fragments are also easily added to existing documents.

In Mozilla, document fragments are created via document.createDocumentFragment(), which returns an empty document fragment.

Internet Explorer's implementation of document fragments however does not comply with the W3C standard, and simply returns a full document.

Element Dimensions

width/height of an element, offsetWidth for exp.

JavaScript

Most differences between Mozilla and Internet Explorer are due to the DOM interfaces exposed to JavaScript. There are very few core JavaScript differences, and issues encountered are often timing related.

JavaScript Date Differences

The only Date difference is the getYear method. In Mozilla, per the specification, it is not Y2k compliant, and running new Date().getYear() in 2004 will return "104". Per the ECMA specification, getYear returns the year minus 1900, originally meant to return "98" for 1998. getYear was deprecated in ECMAScript v3 and replced with getFullYear().

JavaScript Execution Differences

Different browsers execute JavaScript differently. For example, the following code:

    ...    
      
      
Loading...
<script> document.getElementById("foo").innerHTML = "Done."; </script>

assumes that the div node exists already in the DOM by the time the script block gets executed. This is however not garantueed. To be sure that all elements exist, it is best to use the onload event handler on the tag.

                
      
      
Loading...
<script> function doFinish(){ document.getElementById("foo").innerHTML = "Done."; } </script> ...

Such timing-related issues are also hardware related - slower systems can reveal bugs that faster systems hide. One concrete example is window.open, which opens a new window.

    <script>      function doOpenWindow(){        var myWindow = window.open("about:blank");        myWindow.location.href = "http://www.ibm.com";      }      </script>    

The problem with the code is that window.open is asyncronous - it does not block the JavaScript execution until the window has finished loading.

Debugging JavaScript

Mozilla provides several ways to debug JavaScript related issues. The first tool is the built-in JavaScript console, where errors and warnings are logged. It can be opened by going to Tools -> Web Development -> JavaScript Console.

The JavaScript console can show the full log list, or just errors/warnings/messages. The error message in the screenshot says that at aol.com, line 95 tries to access an undefined variable called is_ns70. Clicking on the link will open Mozilla's internal view source window with the offending line highlighted.

The console also allows for evaluating JavaScript. Typing in 1+1 into the input field and pressing the "Evaluate" button will evaluate the entered JavaScript syntax.

Mozilla's JavaScript engine has built in support for debugging, and thus can provide powerfull tools for JavaScript developers. The Mozilla JavaScript Debugger (called Venkman) is a powerfull, cross platform JavaScript debugger that integrates with Mozilla. It is usually bundled with Mozilla releases and can be found in Tools -> Web Development -> JavaScript Debugger. It can be downloaded and installed from http://www.mozilla.org/projects/venkman/. Tutorials can be found at the development page, located at http://www.hacksrus.com/~ginda/venkman/.

The JavaScript debugger can debug JavaScript running in the Mozilla browser window. It supports such standard debugging features such as breakpoint management, call stack inspection, and variable/object inspection. All features are accessible via the User Interface or via the debugger's interactive console. The console also allows to execute arbitrary JavaScript in the same scope as the JavaScript currently being debugged.

Event Differences

Events is one of the few areas where Mozilla and Internet Explorer are nearly completly different.

The Mozilla Event Model

The Mozilla event model is completly different from the Internet Explorer model. It follows the W3C and Netscape model.

In Internet Explorer, if a function is called from an event, itcan access the event object via window.event. In Mozilla, event handlers get passed an event object, and they must specifically pass it on to the function called via an argument. A cross-browser event handling example:

    
      
      
Click me!
<script> function handleEvent(aEvent){ // if aEvent is null, means the IE event model, so get window.event. var myEvent = aEvent ? aEvent : window.event; } </script>

The properties and functions the event object exposes are also often named differently between Mozilla and IE. A table can be found below:

IE NameMozilla NameDescription
altKeyaltKeyBoolean property which returns wether the alt key was pressed during the event.
cancelBubblestopPropagation()Used to stop the event from bubbling furthur.
clientXclientXThe X coordinate of the event, in relation to the client area.
clientYclientYThe Y coordinate of the event, in relation to the content window.
ctrlKeyctrlKeyBoolean property which returns wether the ctrl key was pressed during the event.
fromElementrelatedTargetFor mouse events, this is the element that the mouse moved away from.
keyCodekeyCodeFor keyboard events, this is a number representing the key that was pressed. Is 0 for mouse events.
returnValuepreventDefault()Used to prevent the default action of the event from occuring.
screenXscreenXThe X coordinate of the event, in relation to the screen.
screenXscreenYThe Y coordinate of the event, in relation to the screen.
shiftKeyshiftKeyBoolean property which returns wether the shift key was pressed during the event.
srcElementtargetThe element to which the event was originally dispatched.
toElementrelatedTargetFor mouse events, this is the element that the mouse moved towards.
typetypeReturns the name of the event.
Attaching Event Handlers

Mozilla supports two ways to attach events via JavaScript. The first way, supported by all browers is to set event properties directly on objects. To set an click event handler, a function reference is passed to the object's onclick property.

    
      
      
Click me!
<script> function handleEvent(aEvent){ // if aEvent is null, means the IE event model, so get window.event. var myEvent = aEvent ? aEvent : window.event; } function onPageLoad(){ document.getElementById("myDiv").onclick = handleEvent; } </script>

The W3C standard way of attaching listeners to DOM nodes is fully supported in Mozilla. The addEventListener() and removeEventListener() methods are used, and have the benefit of being able to set multiple listeners for the same event type. Both methods require three parameters - the event type, a function reference and a boolean denoting if the listener should catch events in their capture phase. If the boolean is set to false, it will only catch bubbling events. W3C events have three "phases" - capturing, at target and bubbling, and every event object has a eventPhase attribute indicating the phase numerically (0 indexed). Every time an event is triggered, the event starts at the outermost element of the DOM, the element at top of the DOM tree. It then walks the DOM using the most direct route towards the target, which is called the capturing phase. After arriving at the target, it walks up the DOM tree back to the outermost node, called bubbling. Internet Explorer's event model only has the bubbling phase, therefore setting the third parameter to false will result in IE-like behavior.

    
      
      
Click me!
<script> function handleEvent(aEvent){ // if aEvent is null, means the IE event model, so get window.event. var myEvent = aEvent ? aEvent : window.event; } function onPageLoad(){ document.getElementById("myDiv").addEventListener("click", handleEvent, false); } </script>

One advantage of addEventListener() and removeEventListener() over setting properties is that one can have multiple event listeners for the same event, each calling another function. Due to this, removing an event listener requires all three parameters to be the same as the ones used when adding the listener.

Mozilla does not support Internet Explorer's method of converting <script> tags into event handlers, which extends

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值