The pits in which JavaScript operates on DOM

Posted by JDBurnZ on Thu, 06 Jun 2019 01:26:06 +0200

There are many cross-browser pits in operating DOM for js. It took me nearly a week to sort out these pits. I will sort out the pits according to the examples.

The working mode of DOM is to load the static content of documents first and refresh them dynamically. Dynamic refresh does not affect the static content of documents.

PS: All DOM objects in IE are implemented as COM objects, which means that DOM in IE may be different from other browsers.

Node interface

Characteristics/methods Type/return type Explain
nodeName String The name of the node; defined according to the type of node
nodeValue String The value of a node; defined according to the type of node
nodeType Number One of the type constants of nodes
ownerDocument Document Returns the root element of an element
firstChild Node Point to the first node in the childNodes list
lastChild Node Point to the last node in the child Nodes list
childNodes NodeList List of all subnodes
previousSibling Node Returns the previous sibling node of the selected node, or null if it does not exist
nextSibling Node Returns the next sibling node of the selected node, or null if it does not exist
hasChildNodes() Boolean If the current element node has child nodes, return true or false
attributes NamedNodeMap Returns the Named NodeMap containing the properties of the selected node
appendChild(node) node Add node to the end of child Nodes
removeChild(node) node Delete node from childNodes
replaceChild(newnode, oldnode) Node Replace oldnode in childNodes with newnode
insertBefore Node Insert new child nodes before existing ones

First Child is equivalent to childNodes[0]; last Child is equivalent to childNodes[box.childNodes.length]. - 1].

NoeType returns the type of node

Element node returns 1
 Attribute node returns 2
 - Text node returns 3 

Inner HTML and nodeValue

For text nodes, the nodeValue attribute contains text.

For attribute nodes, the nodeValue attribute contains attribute values.

The nodeValue attribute is not available for document nodes and element nodes.

The difference between the two

box.childNodes[0].nodeValue = '<strong>abc</strong>';//The results are as follows:<strong>abc</strong>
abcbox.innerHTML = '<strong>abc</strong>';//The results were as follows:abc

The nodeName attribute obtains the node name

For element nodes, the tag name is returned, such as < a herf > < a > the tag name is returned as "a"
For attribute nodes, the name of the attribute is returned, such as class="test" returns the test.
-- Returns the content of the text for the text node 

tagName

document.getElementByTagName(tagName): Returns an array containing references to these nodes

The getElementsByTagName() method returns an object array, HTMLCollection(NodeList), which holds a list of nodes with all the same element names.

document.getElementsByTagName('*');//Get all the elements

PS: IE browsers use wildcards to treat the specification declaration of the original html of the document as the first element node.

document.getElementsByTagName('li');//Get all li elements and return an array
document.getElementsByTagName('li')[0];//Get the first li element, HTMLLIElement
document.getElementsByTagName('li').item(0);//Get the first li element, HTMLLIElement
document.getElementsByTagName('li').length;//Get the number of all li elements

Absolute references to nodes:

Returns the root node of the document: document.documentElement
 Returns the live tag node in the current document: document.activeElement
 Return the source node that the mouse moved out: event.fromElement
 Return the source node that the mouse moved in: event.toElement
 Returns the source node of the activation event: event.srcElement

Relative references to nodes: (Let the current node be a node)

Return to the parent node: node.parentNode || node.parentElement (IE)
Returns a collection of child nodes (including text nodes and label nodes): node.childNodes
 Returns the set of child label nodes: node.children
 Returns a collection of sub-text nodes: node.textNodes
 Returns the first child node: node.firstChild
 Returns the last child node: node.lastChild
 Return to the next node of the same affiliation: node.nextSibling
 Returns the same node: node.previousSibling 

Node information

Does it contain a node: node.contains()

Is there a child node.hasChildNodes() 

Create a new node

CreateDocument Fragment () - Create Document Fragment Node
 createElement(tagname) - Create an element with a tagName
 createTextNode(text) - Create text nodes that contain text text

Get the location of the mouse click event

document.onclick = mouseClick;

function mouseClick(ev){
    ev = ev || window.event;//Windows.event is used for IE compatibility
    var x = 0; var y = 0;

    if(ev.pageX){
        x = ev.pageX;
        y = ev.pageY;
    }else if(ev.clientX){
        var offsetX = 0 , offsetY = 0;
        if(document.documentElement.scrollLeft){
            offsetX = document.documentElement.scrollLeft;
            offsetY = document.documentElement.scrollTop;
        }else if(document.body){
            offsetX = document.body.scrollLeft;
            offsetY = document.body.scrollTop;
        }
        x = ev.clientX + offsetX;
        y = ev.clientY + offsetY;
    }
    alert("The location of your click is x="+ x + " y=" + y);
}

The attributes described below are very supportive of chrome and Safari.

Question 1: Firefox, Chrome, Safari and IE9 all use pageX and pageY attributes of non-standard events to get the mouse position of web pages. Page X/Y gets the distance between the trigger point and the upper left corner of the document area. Page is the reference point and does not change with slider movement.

Question 2: In IE, event objects have x, y attributes (x coordinates and Y coordinates of the location of the event) but not in Firefox. In Firefox, the equivalent of event.x is event.pageX. event.clientX is subtly different from event. pageX (when the entire page has scrollbars), but most of the time it is equivalent.

offsetX:IE is unique and chrome supports it. Compared with the position of the element triggering the event, the mouse uses the upper-left corner of the content area of the element box model as the reference point. If there is a boder, there may be a negative value.

Question 3:
scrollTop is the distance from scrollbar to scrollbar, and all browsers support document.documentElement.

Other references: http://segmentfault.com/a/119...

Reference table

(+for support, -for non-support):

offsetX/offsetY: W3C- IE+ Firefox- Opera+ Safari+ chrome+

x/y: W3C- IE+ Firefox- Opera+ Safari+ chrome+

layerX/layerY: W3C- IE- Firefox+ Opera- Safari+ chrome+

pageX/pageY: W3C- IE- Firefox+ Opera+ Safari+ chrome+

clientX/clientY: W3C+ IE+ Firefox+ Opera+ Safari+ chrome+

screenX/screenY: W3C+ IE+ Firefox+ Opera+ Safari+ chrome+

Check DEMO below:
You will find that offsetX is undefined under Firefox, and it will display normally in chrome and IE.

https://jsfiddle.net/f4am208m...

Differences between offsetLeft and style.left

1.style.left returns a string, such as 10px. offsetLeft returns values, such as 10.

2. Style. ft is readable and written, offsetLeft is read-only.

3. The value of style. left needs to be defined in advance (the definition in the stylesheet is invalid, only the value defined in html can be fetched), otherwise the value is empty.

GetComputed Style and current Style

getComputedStyle() takes two parameters: to get the element of the calculation style and a pseudo-element, if no pseudo-element is needed, it can be null. However, getComputedStyle is not supported in IE, which provides the current Style attribute.

GetComputed Style (obj, false) supports w3c (FF12, chrome 14, safari): In the new version of FF, only the first parameter, namely the operation object, and the second parameter, writing "false", is also a common way of writing, in order to be compatible with the old version of Firefox browser.
Disadvantage: Normal in standard browsers, but not supported in IE6/7/8

 window.onload=function(){
    var oBtn=document.getElementById('btn');
    var oDiv=document.getElementById('div1');

    oBtn.onclick=function(){
        //alert(oDiv.style.width); // Written in the stylesheet can not be read, can only be written in the line
        //alert(getComputedStyle(oDiv).width); // Not Recognized for Standard Browsers IE6, 7, 8
        //Alert (oDiv. current Style. width); // For IE browsers, standard browsers are not recognized
        if(oDiv.currentStyle){
            alert(oDiv.currentStyle.width);
        }else{
            alert(getComputedStyle(oDiv).width);
        }

    };
};

Cancel form submission

<script type="text/javascript">
    function listenEvent(eventObj,event,eventHandler){
        if(eventObj.addEventListener){
            eventObj.addEventListener(event,eventHandler,false);
        }else if(eventObj.attachEvent){
            event = "on" + event;
            eventObj.attachEvent(event,eventHandler);
        }else{
            eventObj["on" + event] = eventHandler;
        }
    }

    function cancelEvent(event){
        if(event.preventDefault){
            event.preventDefault();//w3c
        }else{
            event.returnValue = true;//IE
        }
    }

    window.onload = function () {
        var form = document.forms["picker"];
        listenEvent(form,"submit",validateFields);
    };

    function validateFields(evt){
        evt = evt ? evt : window.event;
        ...
        if(invalid){
            cancelEvent(evt);
        }
    }
</script>

Determine the size of the browser window

For mainstream browsers, such as IE9, Firefox, Chrome and Safari, window object properties called innerWidth and innerHeight are supported, which return to the viewport area of the window, minus the size of any scrollbar. IE does not support innerWidth and innerHeight

<script type="text/javascript">
    function size(){
        var w = 0, h=0;

        if(!window.innerWidth){
            w = (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth);

            h = (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight);
        }else{
            w = window.innerWidth;
            h = window.innerHeight;
        }
        return {width:w,height:h};
    }

    console.log(size());//Object { width: 1366, height: 633 }
</script>

Practical JavaScript solutions (covering all browsers):

var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;

var h=window.innerHeight || document.documentElement.clientHeight|| document.body.clientHeight;

For IE 6, 7 and 8, the following solutions are proposed:

document.documentElement.clientHeight
document.documentElement.clientWidth

perhaps

document.body.clientHeight
document.body.clientWidth

The body attribute of the Document object corresponds to the < body > tag of the HTML document. The documentElement attribute of the Document object represents the root node of the HTML document.

attributes attribute

attributes property returns the set of attribute nodes of the node.

document.getElementById('box').attributes//NamedNodeMap
document.getElementById('box').attributes.length;//Number of attribute nodes returned
document.getElementById('box').attributes[0]; //Attr, returns the last attribute node
document.getElementById('box').attributes[0].nodeType; //2. Node type
document.getElementById('box').attributes[0].nodeValue; //Attribute value
document.getElementById('box').attributes['id']; //Attr, returns a node with an id attribute
document.getElementById('box').attributes.getNamedItem('id'); //Attr

setAttribute and getAttribute

In IE, we don't know the class attribute, so we need to change it to the class Name attribute. Similarly, in Firefox, we don't know the class Name attribute. Firefox only knows the class attribute, so we usually do the following:

element.setAttribute(class, value);  //for firefox
element.setAttribute(className, value);  //for IE

IE: Custom attributes can be obtained by using the method of obtaining regular attributes, or by using getAttribute().
Firefox: You can only use getAttribute() to get custom attributes.

Solution: Unified access to custom attributes through getAttribute()

document.getElementById('box').getAttribute('id');//Get the id value of the element
document.getElementById('box').id;//Get the id value of the element
document.getElementById('box').getAttribute('mydiv');//Get custom attribute values for elements
document.getElementById('box').mydiv//Getting custom attribute values for elements, IE does not support non-
document.getElementById('box').getAttribute('class');//Getting the class value of the element is not supported by IE
document.getElementById('box').getAttribute('className');//Non-IE does not support

PS: In IE7 and lower versions of IE browsers, setting class and style attributes using setAttribute() method is ineffective. Although IE8 solves this bug, it is not recommended to use it.

removeAttribute() method

removeAttribute()Can be removed HTML Attributes.
document.getElementById('box').removeAttribute('style');//Remove Attribute

PS: IE6 and lower versions do not support the removeAttribute() method.

Cross-browser Event object

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
       #drop{
           width: 300px;
           height: 200px;
           background-color: #ff0000;
           padding: 5px;
           border: 2px solid #000000;
       }
       #item{
           width: 100px;
           height: 100px;
           background-color: #ffff00;
           padding: 5px;
           margin: 20px;
           border: 1px dashed black;
       }
       *[draggable = true]{
           -moz-user-select: none;
           -webkit-user-select: none;
           cursor: move;
       }
    </style>
</head>
<body>
<div>
    <p>It is incompatible to drag small golden squares into large red squares. IE7 And the following browsers, compatible with mainstream browsers!</p>
</div>
<div id="item" draggable="true"></div>
<div id="drop"></div>
<script type="text/javascript">
    function listenEvent(target,type,handler){
        if(target.addEventListener){//w3c
            target.addEventListener(type,handler,false);
        }else if(target.attachEvent){//IE
            type = "on" + type;
            target.attachEvent(type,handler);//IE
        }else{
            target["on" + type] = handler;
        }
    }

    //Cancel event
    function cancelEvent(e){
        if(e.preventDefault){
            e.preventDefault();//w3c
        }else{
            e.returnValue = false;//IE
        }
    }
    //Cancel delivery
    function cancelPropagation(e){
        if(e.stopPropagation){
            e.stopPropagation();//w3c
        }else{
            e.cancelBubble = true;//IE
        }
    }

    window.onload = function () {
        var target = document.getElementById('drop');
        listenEvent(target,'dragenter',cancelEvent);
        listenEvent(target,"dragover",dragOver);
        listenEvent(target,'drop', function (evt) {
            cancelPropagation(evt);
            evt = evt || window.event;
            evt.dataTransfer.dropEffect = 'copy';
            var id = evt.dataTransfer.getData('Text');
            target.appendChild(document.getElementById(id));
        });

        var item = document.getElementById('item');
        item.setAttribute("draggable",'true');
        listenEvent(item,'dragstart', function (evt) {
            evt = evt || window.event;
            evt.dataTransfer.effectAllowed = 'copy';
            evt.dataTransfer.setData('Text',item.id);
        });
    };

    function dragOver(evt){
        if(evt.preventDefault) evt.preventDefault();
        evt = evt || window.event;
        evt.dataTransfer.dropEffect = 'copy';
        return false;
    }
</script>
</body>
</html>

dataTransfer object

| Attribute | Description|
| ------------- |:-------------:| 
| dropEffect | Sets or gets the type of drag operation and the type of cursor to display|
| effectAllowed | Sets or gets data transfer operations that can be applied to the source elements of the object|

| Method | Description|
| ------------- |:-------------:| 
| clearData | Delete one or more data formats from the clipboard through a dataTransfer or clipboard Data object|
| getData | Get data in a specified format from the clipboard through a dataTransfer or clipboard Data object
| setData | Give data to a dataTransfer or clipboard Data object in a specified format

HTML5 drag-and-drop browser support

Internet Explorer 9, Firefox, Opera 12, Chrome, and Safari 5. Support drag-and-drop

To make the element draggable, set the draggable property to true:

<img draggable="true" />

| Event | Description|
| ------------- |:-------------:| 
| dragstart | dragstart event starts|
| drag | on drag operation|
| dragenter | drag onto the target to determine whether the target accepts placement
| dragover | drags onto the target to determine feedback to the user
| drop | placement occurs
| dragleave | drag away from the target
| dragend | dragend

Some browser compatibility of the above code:

1.For compatibility IE,We will`window.event`Assign to `evt`,Other browsers will receive it correctly`event`Object assignment`evt`. 
2.w3c Use addEventListener To add event listeners to event elements, and IE Then use attachEvent. addEventListener For the current object bubbled up by the event, and attachEvent yes window
3.For event types, IE Need to add`on + type`Properties, while other browsers do not
4.For preventing default event behavior of elements, the following are w3c and IE Practice:

    e.preventDefault();//w3c   
    e.returnValue = false;//IE
    
5.For cancelling event propagation, w3c and IE There are also different treatment mechanisms:
    e.stopPropagation();//w3c
    e.cancelBubble = true;//IE

Acquisition of target objects across browsers

//Acquisition of target objects across browsers
function getTarget(ev){
    if(ev.target){//w3c
        return ev.target;
    }else if(window.event.srcElement){//IE
        return window.event.srcElement;
    }
}  

w3c and IE also have different ways of getting trigger objects:

event.target;//w3c
event.srcElement;//IE       

We can use trinomial operators to accommodate them:

obj = event.srcElement ? event.srcElement : event.target;

The problem of innerText

innerText works well in IE, but not in FireFox.

<p id="element"></p>
<script type="text/javascript">
    if(navigator.appName.indexOf("Explorer") >-1){
        document.getElementById('element').innerText = "my text";
    } else{
        document.getElementById('element').textContent = "my text";
    }
</script>

Getting and setting innerText across browsers

//Getting innerText across browsers
function getInnerText(element){
    return (typeof element.textContent == 'string') ? element.textContent : element.innerText;
}
 
//Setting innerText across browsers
function setInnerText(element,text){
    if(typeof element.textContent == 'string'){
        element.textContent = text;
    }else{
        element.innerText = text;
    }
}    

Use of oninput,onpropertychange,onchange

The onchange trigger event must satisfy two conditions:

a) Current object attributes change and are triggered by keyboard or mouse events (script triggers are invalid)

b) the current object loses focus (onblur);

If onpropertychange changes the current object property, it will trigger events, but it is IE-specific.

oninput is a non-IE browser version of onpropertychange, which supports browsers such as firefox and opera. However, when it is bound to an object, not all attribute changes of the object can trigger events, it only works when the value of the object changes.

Accessing the XMLHTTPRequest object

<script type="text/javascript">
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();//Non IE
    }else if(window.ActiveXObject){
        xhr = new ActiveXObject("Microsoft.XMLHttp");//IE
    }
</script>

Ban Selection of Web Content

Questions:  
FF needs to be banned by CSS and IE by JS  

Solution:  
IE: obj.onselectstart = function() {return false;}  
FF: -moz-user-select:none;   

Three non-bubbling incidents

All browsers'focus/blur events are not bubbling. Fortunately, most browsers support focusin / focus out events, but hateful firefox doesn't even support this.

IE6, 7, 8 submit events do not bubble.
change events under IE6, 7, 8 will not be triggered until blur.

The Evil Wheel Event

The support of roller events can be described as a mess, with the following rules:

IE6-11 chrome mousewheel wheelDetla lower-120 upper 120

firefox DOMMouseScroll detail 3 up-3

firefox wheel detlaY lower 3 up-3

IE9-11 wheel deltaY lower 40 upper-40

chrome wheel deltaY up to-100 below 100  

For mouse wheel events, IE supports mousewheel and Firefox supports DOMMouseScroll.
To determine whether the mouse wheel is up or down, IE uses the wheelDelta attribute and Firefox uses the detail attribute.

Event Delegation Method

  
//Event Delegation Method  
IE: document.body.onload = inject; //Function inject()It has been implemented before that.  
FF: document.body.onload = inject();   

HTML5 browser support

Source address: http://fmbip.com/litmus/

Query operation

Queries refer to finding a set of elements through some characteristic strings, or judging whether the elements satisfy the strings.

1. IE6/7 does not distinguish id from nam
 When using getElementById and getElementsByName under IE6/7, elements with the same id or name as the given value are returned at the same time. Since name is usually agreed by the back end, we should ensure that id does not duplicate name when we write JS.

2. IE6/7 does not support getElements ByClassName and querySelector All   
These two functions have been supported since IE8, so under IE6/7, only getElementByTagName is actually available.

3. IE6/7 does not support getElements ByTagName ('*') returning non-element nodes    
Either you don't need *, or you can write a function to filter it.

4. Query Selector All is not friendly to property selectors under IE8    
Almost all browsers have problems with predefined attributes, try to use custom attributes or do not use attribute selectors.

5. QueySelectorAll does not support pseudo-classes under IE8    
Sometimes pseudo-classes are very useful, IE8 does not support them, jquery provides: first,: last,: even,: odd,: eq,: nth,: lt,: gt are not pseudo-classes, we should not use them at any time.

6. IE9 matches function cannot handle elements that are not on the DOM tree
 As long as the element is not in the dom tree, it will return false. It is impossible to leave the element in the body and delete it after matching. Of course, we can also write the matching function ourselves to avoid backflow.    

Reference:
http://w3help.org/zh-cn/kb/

Topics: IE Attribute Firefox Javascript