New DOM API

    In this article I will talk about the latest in the DOM API, which we can use now or in the near future.
    The publication of the article is dedicated to the joyful event of the beginning of the implementation of some new DOM4 API methods in Google Chrome. Many methods and properties can be used now, some of them work through prefixes, but for each method or property I will try to give Polyfill that implements them or discards browser prefixes.
    I tried to describe the methods in accordance with the JSDoc for the Google Closure Compiler .


    DOM4 Mutation methods


    Specification

    U Element.prototypehas a number of very interesting methods that will be familiar to jQuery lovers, but they work in a slightly different way.

    • append(...{(Node|string)})
    • prepend(...{(Node|string)})
    • before(...{(Node|string)})
    • after(...{(Node|string)})

      The method inserts the n-th number of nodes into the current node. Nodes are passed as arguments to the function (for example: node.append(otherNode1, otherNode2).
      With this, you can pass instead of the node text, and it is automatically converted to TextNode , as if you called document.createTextNode(text).
      The function appendinserts the node at the end of its list of nodes, prepend- in principle, function beforeand after- in front of and after the current node, respectively.

    • remove()
      The method removes the current node from the parent.
    • replace(...{(Node|string)})
      The method replaces the current node with one or more nodes that are specified as method parameters.

      All of these methods have no return value.


    Such a pattern will allow you to pass a NodeList or an array with nodes to this method :

    element.append.apply(element, document.querySelectorAll("div"))


    The documenttwo methods have been added of the six: appendand prepend.

    Of all the DOM4, Mutation methods are only removeimplemented in the latest version of Google Chrome.
    Polyfill of these methods for all browsers is in my library .

    DOM Selector API 2: NodeRef and: scope


    Specification

    • document.querySelector(string, NodeRef{(Node|NodeList|Array.)})
    • document.querySelectorAll(string, NodeRef{(Node|NodeList|Array.)})
    • document.find(string, NodeRef{(Node|NodeList|Array.)})
    • document.findAll(string, NodeRef{(Node|NodeList|Array.)})


    Good old querySelector [All] methods got a second parameter, but only in the implementation for document. And also new methods find [All] were added.

    The second parameter allows you to specify the context in which we will search for nodes by the selector. For instance:

    document.findAll("li", [ulElement1, ulElement2])


    Will find all elements
  • in two elements ulElement1 and ulElement2 .

    The : scope pseudo class allows you to do really cool things. This is another way to specify the search context - it points to the current element in which we search by selector.
    It allows you to search by previously invalid selectors "> .class" or "~ tagname". Just specify : scope at the beginning and these selectors will become valid. The full power of : scope is visible when
    we use it with NodeRef:

    document.querySelectorAll(":scope > p", [divElement1, divElement2])

    Find all immediate children with tag p in divElement1 and divElement2 ! I want to note that you can omit the : scope pseudo-class for the findand methods findAll. For these methods, such a call is considered valid:
    document.findAll("> p", [divElement1, divElement2])


    WebKit currently supports the: scope pseudo-class, but it does it wrong . The good news is that after my bug report, the wrong support : scope will be removed . If you still need to check the true support of this pseudo-class, here is the code for this: gist .
    I support find[All]and : scope in the querySelectorAllspecification that I am currently doing.

    Element.prototype.matches


    Specification

    This method was previously called matchesSelector . It checks the node against the CSS selector.
    Small polyfill with dropping browser prefixes: gist . A more advanced version in my library .

    classList




    DOM API specification for working with element CSS classes.

    Methods:

    • add(...class{string})Adds class to element.className
    • remove(...class{string})Removes class from element.className
    • toggle(boolean: class{string})Deletes a class if it exists from element.className and returns false . Adds in case of lack of element.className and returns true .
    • contains(boolean: class{string})Checks for a class in element.className . Returns true or false, respectively.
    Previously, techniques addand removeworked with only one class at a time, and recently in the standard has added the ability to work with multiple CSS-classes:

    document.documentElement.classList.add("test1", "test2", "test3")
    document.documentElement.classList.remove("test1", "test2", "test3")


    Polyfill for classList, until the old specification, I have in my library . A new version will soon be available, which will patch the old implementation.

    Events Constructor


    Specification

    The new DOM API standard defines event constructors. Now we can forget about the torment with

    event = document.createEvent("click")
    event.initMouseEvent( /*тут что-то, я даже сам не помню что*/ )


    And just write:

    event = new Event("click")


    We can pass any text value to the constructor in quality e.type, the second parameter is an object that contains the initialization parameters bubbles and cancelable . bubbles set to false will prevent the event from popping up. cancelable set to false will prevent the event from being canceled through the method preventDefault.
    By default, bubbles and cancelable are false .

    event = new Event("some:event", {bubbles : true, cancelable : false})
    event = new Event("dbclick1")
    element.dispachEvent(event)


    If you need to add data for the handler, you just need to add them to the object event:

    event = new Event("click")
    event.button = 1


    I note that in this case, all events created in this way are ordinary events, i.e. new Event("click")will not create a MouseEvent , but simply an Event .

    The second class for creating events is this CustomEvent. Using this class differs only in that you can pass the detail property to the initialization object.

    event = new CustomEvent("somecustom:event", {bubbles : true, cancelable : false, detail : {"some data" : 123}})


    Designers Eventand CustomEventimplemented in all modern browsers (for more than a year) except Android WebKit browsers. Polyfill for older browsers.

    Also, there is a discussion about special events for keyboard, drag & drop and mouse. But so far they are not implemented by any browser.
    (Note: Opera 12.10 supports the constructor for KeyboardEvent, but it does not work according to the specification )

    HTMLLabelElement.prototype.control and HTML * Element.prototype.labels for form elements


    Specification for control

    property control contains a link to a form element is associated with this item:

    label.control.value = "123"

    Let me remind you that according to the specification, one element can have only one connected form element.

    Specification for labels

    property labels , on the contrary, comprises NodeList elements to form element. NodeList because, by specification, a single form element may have several related elements.

    console.log(input.labels.length)


    Properties are implemented in most browsers. Polyfill for older browsers

    HTMLOlElement.prototype.reversed


    Specification

    The reversed property of a numbered list causes the numbering to go in the opposite direction. This takes into account the start property . Here are simple examples that should say more words:

    1. Элемент списка 1
    2. Элемент списка 2
    3. Элемент списка 3
    4. Элемент списка 4
    5. Элемент списка 5


    It will be interpreted by the browser as:

    5. List item 1
    4. List item 2
    3. List item 3
    2. List item 4
    1. List item 5
    


    And this markup:

    1. Элемент списка 1
    2. Элемент списка 2
    3. Элемент списка 3
    4. Элемент списка 4
    5. Элемент списка 5


    will be interpreted by the browser as:

    100. List item 1
    99. List item 2
    98. List item 3
    97. List item 4
    96. List item 5
    


    Support for the reversed property is in Google Chrome. For other browsers there is Polyfill .

    Event.prototype.stopImmediatePropagation


    Specification

    The method works similarly to the same method from jQuery .

    In short, it not only stops the event popup, but processes the event immediately , without executing the following event handlers.

    Only Opera before version 12.10 does not support this method. Polyfill for her.

    Support IE <9



    IE8 has prototypes of DOM objects, so adding support there is easy. I put the polyfill for IE8 into a separate file and attach it via Conditional Comments .

    For IE6 / 7, everything is more complicated, you need to either abandon these browsers to fully or fully implement the DOM API for them, which I did, which I described in my article DOM-shim for all browsers including IE <8 .

    The article code is posted on github . If you want to help or find a mistake, make a pull request or write me in a personal. Also write in the comments if you need to consider a topic in more detail or need more examples.

  • Also popular now: