API for node operations, api_javascript techniques to subvert native operations HTML DOM nodes

Source: Internet
Author: User
Tags tagname first row
The first time I saw the definition of agile development, I was fascinated by agile development. Generally speaking, agile development can let us use the code can reuse again, because it is reused again, so relatively safe, again debugging is not the first time so bothered, save time and effort. The continuous reuse of the code in the process of the existence of the bug is constantly repaired, but also because of continuous reuse, this template has become more and more independent, the application of more and more wide fan, and finally in the security to reach the fortress, in the development of the arbitrary, in the maintenance of a calm face.

Agile development is really a concern, but how to develop this kind of abstruse martial arts? In my own case, it is impossible to teach martial arts, because the company in my development, the power of thinking, decided to start from the excellent framework of open source, to see it a line of code to understand, and then for my use. Because it is a person development, the front desk and backstage have to be arranged, which from that side to start? Have had one or two months of development experience, feel that the front desk JS very time-consuming, and always feel doing repetitive things, such as sending AJAX requests, receive results after the operation node (sometimes encountered incompatible situations, such as select and table in IE do not support the use of innerHTML, Style in IE will not automatically converted to strings, to use Csstext instead, once these situations, really is extremely hit the programmer's enthusiasm, because you have to spend time to find alternatives, to debug, as well as node rotation, pop-up layer, form verification, such as a series of cumbersome work. So I will resolutely from the front desk JS start. In order to develop how to improve the reusability of JS, I chose to learn from jquery. It took a few months to see the half, slightly gained. I have one of the JS module "Infinite Depth Operation node" (literary good, name is not appropriate to do not mind) out. With it, I became easy to manipulate nodes, the code became streamlined, and without the need to write extra code to be compatible with browsers, the function was done.

First of all, let me talk about what makes the operation node annoying to us:

  • Writing AJAX programs, dynamic additions and deletions to change page elements is almost inevitable, using attributes innerHTML is the way we often use, but in IE table,thead,tfoot,tbody,tr,col,colgroup,html,title, The Style,frameset innerHTML properties are read-only, which means that we cannot update these nodes using innerHTML. (There is no mention of SELECT, in fact, select is not successful, it is estimated that IE bugs). Examples are as follows: (The following $id represents document.getElementById)
    <select id= "Jkit" >
    <option value= "1" >jquery</option>
    </select>
    Execute code:
    $id (' Jkit '). InnerHTML = ' <option>jquery</option> ';
    IE did not report any errors, but select an option node is not. If you use Innerhtml,ie for table, you will report unknown runtime error
    A common compatibility method for this scenario is an addition to an outer element, as follows:
    <div id= "Jkit" >
    <select>
    <option value= "1" >jquery</option>
    </select>
    </div>
    Execute code:
    $id (' Jkit '). InnerHTML = ' <select><option value= ' 1 ' >jkit</option></select> ';
    IE also succeeds in changing the Select, but there is a disadvantage that if you register events with the Select, all of these events will be lost, and you will have to code to re-register the events.
  • New nodes are added before and after the specified node, which is related to node positioning, node creation, and setting of node properties. Using innerHTML is usually used only to overwrite all nodes of a DOM element, if you want to change only one of the element's subnodes, or just want to add nodes before and after a child node, still use innerHTML is counterproductive, difficult to implement, and after using innerHTML, The events registered with the child node are definitely lost. Instead of using innerHTML, you have to use the native Dom method, but this alternative does not work, look at the following example:
    <SELECT>
        <option value= "1" >jquery</option>
        <option value= "2" >JKIT</OPTION>
        < Option value= "3" >mars</option>
    </select>
    Now I want to add an option before Jkit, using the native Dom method:
    var newNode = document.createelement (' option '),//Create a new node
    selector = document.getElementById (' jkit3 '),
    /* can also be used selector.options, but getelementsbytagname more general.
    Well, how about with childnodes? It's best not to, for a blank node, IE and FF are handled differently,
    In this case, in FF, the firstchild of the Select is a blank text node,
    Because there are newline and whitespace characters between the Select and the first option,
    FF will create the node for it, and IE will ignore the */
    options = document.getelementsbytagname (' option ');
    Newnode.setattribute (' Value ', ' new ');
    Newnode.setattribute (' text ', ' NewNode '); text does not support this setting
    Newnode.text = ' newNode '; IE does not support this approach
    newnode.innerhtml = ' NewNode ';
    Selector.insertbefore (Newnode,options[1]); //Insert before Kit
    After executing the above code, select has one more option:
    <select>
    <option value= "1" >jquery</option>
    <option value= "New" >newNode</option>
    <option value= "2" >jkit</option>
    <option value= "3" >mars</option>
    </select>
    Add a node this will use 6 code, now just add a node, that for bulk operation how to do ah? And the native Dom method is not easy to use, the name is long and the parameter order is not good to remember, when you have to turn over the document (unless your development every day in the operation of nodes, every day with these methods). Some people say, also not very troublesome Ah, I can write the 6 code a method, and then through the reference to complete the bulk operation. To some extent it can reduce the workload, but it's not realistic to look a little further. There are three reasons: first, each new node's properties are not the same, add a different position, you also have to determine the location of the new node outside the method and within the method to determine the node to add those, the next node to add which attribute, the code in the law can only make you a little more relaxed; second, the above code can see that Add a new node, you want to eliminate a lot of incompatible implementation methods, in terms of setting properties, each element has a different attribute, there are differences in compatibility scenarios, and when you write a method for different elements, you have to remember the compatibility scheme for each element, but who dares to remember all compatibility scenarios, And programmers want to make a difference in technology, by raising the logic of thinking, rather than memory, there is no need to make painstaking efforts in this regard; Three, a project is to implement the function, the next project, there are similar functions, but in the details of the difference, according to the above practice, you can imagine that your code reusability is very low, Because to change some of the details, you'll have to rethink the logic you've written, re refactor the code for your details, and that's too inefficient to be completely agile.

    See this, estimated readers will ask, if not to do so, can development really do copy and paste it? To be sure, that is impossible. The comprehensive code is also unlikely to meet the different inclusive logic. But you can do a very high reusability, the key is to find out the common characteristics of different logic and very good independent. The operation node procedure above I say that the reusability is low, because the operation of the node with a specific logic mixed together, that is, the code of the specific logic and operation of the node is too close to the code, to the next logical node operation, and then want to reuse the last code, you must review the last written logic, The Operation node code is then separated and then sent to use. The following is a description of the infinite level of node operation that I developed, it is very good to logically independent, and the logic is irrelevant.
  • For the Select example above, option is the child node of the Select, we are working on a two-tier tree structure, and if we go deeper, what about the descendants of the operation element? How do I locate an element descendant node? The following is also implemented as a native Dom method:
    <table>
    <tr>
    <td>
    <ul>
    <li></li>
    <li></li>
    </ul>
    </td>
    <td>
    <ul>
    <li></li>
    </ul>
    </td>
    </tr>
    </table>
    Now I want to add an option before the first Li, implemented using the native Dom method:
    NewNode = document.createelement (' li '),
    Table = document.getElementById (' jkit4 '),
    Take Li's parent node:
    ULS = Table.getelementsbytagname (' ul '),
    /* getElementsByTagName Although general, but if the LI tag nested li,li parent node of the sibling also has Li, then getElementsByTagName will be taken to these nodes, if your HTML structure is really complex, It's hard to locate the Li node you're looking for after you take out the results. In this case, you only go through a layer of childnodes to look down, but previously mentioned childnodes in IE and FF behavior is not, so you have to do compatibility processing. */
    Lis = table.getelementsbytagname (' li ');
    newnode.innerhtml = ' NewNode ';
    Inserts at the specified location
    Uls[0].insertbefore (Newnode,lis[0]);
    The change is not in the distance, similar to the above implementation, encountered complex HTML structure, may be positioning more trouble, some people say that positioning is not difficult, I can find the Li on the given an id attribute, so how complex can also be a step positioning, but I would like to ask if the bulk operation? If there are many rows in the table, each row is related to the operation, is that not each Li given a person ID? Yes, it's not hard to pass the loop, but I'm against it. If there is a good alternative, I am more in favor of keeping clean HTML, in the project I developed, used to locate the element-free attribute I was given as little as possible, because I have enough flexible solution to find the node. When it comes to clean HTML, here's a Han digression. How to keep the HTML clean? In my development, HTML is not promiscuous any logical JavaScript code (only receive the background data of some variables, and these variables are uniformly placed in the end of the HTML, variables too much, organized in the form of groups), to the element registration events will not be onclick, Onblur and other event code embedded in the HTML, see the source code you will not see any onclick,onblur in the HTML and other event codes. Back to the subject of this article! Here are three points to talk about how to make our work easier!

The next thing to talk about is how to write code to make our events easier. Ignore the technical aspects of the event, if there is such a JS class, there are a number of methods, these methods are enough to enable us to complete the above and more complex than the above events. This assumes the existence of the class, because only the method name, without concrete implementation, we call it an interface. What we're going to talk about here is defining the interface, and when we feel that the method in the interface satisfies the requirements, we're going to implement it. (This is a better development process, first planning action)

  • Instantiating an Object

    In the development project, because more than one infinite level of nodes operate the plugin, there are many, including the common Plug-ins and business-to-business, such as rotation, paging, form verification, form elements to set values, bulk upload pictures, the event of repackaging, batch processing of events, search automatic completion, shopping cart AJAX operations, and classes of public methods. So the whole JS will have a lot of classes, each class corresponding to a JS variable, so there are a lot of public JS variables, if the development of inadvertently in other places to declare a variable of the same name, then this class is gone. To avoid this, I encapsulate all classes in a class named $jkit, so that there is only one public variable. The plug-in class becomes a partial, how do I access it? I also define a $CL class that defines methods that are used to access $jkit classes, so that even if there are more than one plug-in, there will be only two public variables $cl and $jkit. The $CL is responsible for calling $jkit. For example, the Newobj method in $CL is used to instantiate the plug-in object. Newobj has two parameters, the first specifies which plug-in to instantiate, and the second parameter is used to instantiate the initialization parameters of the plug-in, and is passed in the form of an array.
    <table id= "Jkit" >
    <tbody>
    <tr>
    <th class= "Align" >Option</th>
    <th>
    <a href= "javascript:void (0);" >Status</a>
    </th>
    <th>
    <a href= "javascript:void (0);" >Attribute</a>
    </th>
    </tr>
    <tr>
    <td></td>
    <td>
    <select size= "3" name= "status" >
    <option value= "All" > </option>
    <option value= "0" > Down frame </option>
    </select>
    </td>
    <td>
    <ul>
    <li id= "Lior" >L</li>
    <li>XL</li>
    </ul>
    </td>
    </tr>
    <tr>
    <td></td>
    <td></td>
    <td></td>
    </tr>
    </tbody>
    </table>
    /* The following code instantiates an infinite hierarchical node manipulation plug-in object, which is equivalent to the construction of a new object tree, new object tree with a new member method. In the following example, the new object tree Reference is Table,table is also the root of the new tree. Its descendant objects are determined by the second parameter childs. The root reference of the new tree is the entry of its descendant object. Focus on the second parameter. Childs is an array structure in which the first element of the array is TR, which represents the child node TR that is the DOM root node root to reconstruct the new object. If there is no TR in the original Dom root node, the object will not be constructed, and if TR has a TR inline, it will not construct the node for the inline TR, that is, it will only construct the object for the child node. The second element is TD th, why there are two? Because the child under the TR node can be th can also be TD, if you want to be at the same time for the th TD construction of new objects, it is necessary to write at the same time, separated by space, check the order is not limited. The third element is select UL, why can these two be written together? Because they are at the same level, relative to the root node, they are all on the third level. As long as the same level can be written together. The following and so on, the number is unlimited, is the infinite level. The hierarchical structure of the new object tree corresponds to the hierarchy of the original DOM tree one by one. */
    root = document.getElementById (' category '),

    Childs = [' tr ', ' TD th ', ' Select ul ', ' li option '],

    Table = $CL. NEWOBJ (' Manode ', [Root, Childs]);
  • The member method of the new tree,When you read the API below, please remember two points in your mind first, all methods of the root object and descendant object are directed at the original Dom object, such as calling del for the new object, essentially deleting the corresponding original DOM object, and then rebuilding the corresponding branch every time the object's additions and deletions are changed.

    Root Object Unique method
    function map (index1,index2,,, indexn) {}
    This method is used to find a descendant node, and Table.map (1,1,0) finds the first object in the second cell of the second row, which is the corresponding object of the select. When a map has only one parameter, and the parameter is a DOM native object, the method returns the corresponding new object.
    function Index (domelement) {}
    The method returns the corresponding element of the native DomElement object, Table.index (document.getElementById (' Lior ')), returns [1,2,0,0], and the result is an array form
    Methods unique to descendant objects
    function Add (index, HTML) {}
    This method is used to increase the sibling node, where index is the displacement relative to the object where the method is invoked, and HTML is the node to insert. HTML can be any string
    Table.map (2) of any HTML word that conforms to the standard of the consortium. Add ( -1, ' <TR><TD></TD><TD></TD><TD ></td></tr> '), add a new line before the third line (you can insert multiple rows at the same time)
    Table.map (2). Add ( -2, ' <tr><td></td>< Td></td><td></td></tr> '), adds a row to the previous line in the third row
    Table.map (0). Add (2, ' <tr><td> </td><td></td><td></td></tr> '), add a row to the first line after line
    Table.map (1). Add (0, ' <tr ><td></td><td></td><td></td></tr> '), index 0 indicates a new row before the current line and deletes the current row
    Table.map (1). Add (' <tr><td></td><td></td><td></td></tr> '), Omitting the first argument, which is a more specific use, will add one line to the last line of
    Table.map (1,1), regardless of which object is used. Add (1, ' <td class= ' one ' > Add cell </td> ') , add a cell after the second cell in the second row, and then delve into the nodes like this, just by the map method to determine the node can be
    Function del (index) {}
    This method is used to delete sibling nodes, and index is the displacement relative to the location of the object that called the method
    Table.map (1). Del (), index omitted to indicate deletion itself, where the deletion of the second row is equivalent to Table.map (1). del (0)
    Table.map (0). del (2), which deletes the second row after the current calling object, here is the third row
    Table.map (2). Del (-2), here Delete the second line before the current calling object, this is to delete the first row
    Table.map (0,1). del ([0,-1,1]), if index is an array, then is to delete the sibling node of the specified index, then ignore which object is invoked, the index is a negative number from the last count,-1 for the last, here delete the first, The second and last th
    Table.map (0,1). Del (0,-1), if there are two parameters, indicating the deletion of the sibling node of the specified interval, then ignore which object is invoked, the index is a negative number from the last count,-1 for the last one, here delete the first to the latter element, the parameter large can be used as the first parameter , size order is not limited
    function GetParent () {}
    Gets the native DOM object node corresponding to the calling object's parent object, Table.map (0,1). GetParent (). tagname to TR
    function Gethigher () {}
    Gets the parent object of the calling object, Table.map (0,1). Gethigher.getnode (). tagname to TR
    Root objects and methods owned by descendant objects
    function GetNode () {}
    Gets the native DOM object node corresponding to the calling object, Table.getnode (). TagName is Table,table.map (0,1). GetNode () is th
    function SizeOf () {}
    Gets the number of child objects of the calling object, Table.sizeof () is 3, which indicates that there are three rows
    function pos () {}
    Gets the location of the calling object at all of its sibling nodes, Table.map (1). POS () is 1
    function html (HTML) {}
    Gets the innerhtml of the calling object corresponding to the native DOM object, and assigns a value to its innerHTML property if there are arguments (do not assign values to innerHTML objects that are read-only)
    function attr (HTML) {}
    Gets the innerhtml of the calling object corresponding to the native DOM object, and assigns a value to its corresponding property (not implemented) if there are arguments
    function before (index,html) {}
    Adds a node to the calling object's specified child object, index is the relative offset
    Table.before (1, ' <tr><td></td><td></td><td></td></tr> '), Add a row before the second line
    Table.map (1,2,0). Before ( -1, ' <li style= "color:red;" > Add Li Node </li> '), add an Li in front of the last Li (the index is negative for the last count, 1 represents the last)
    Table.before (' <tr><td></td><td></td><td></td></tr> '), Omit the first argument to represent the new node in front of the first child object
    function Append (index,html) {}
    Adds a node to the calling object's specified child object, index is the relative offset
    Table.append (1, ' <tr><td></td><td></td><td></td></tr> '), Add a row after the second line
    Table.map (1,2,0). Append ( -1, ' <li style= "color:red;" > Add Li Node </li> '), add an Li after the last Li (the index is negative for the last count,-1 for the last)
    Table.append (' <tr><td></td><td></td><td></td></tr> '), Omitting the first argument means adding a node after the first child object
    function Replace (index,html) {}
    The HTML-generated node replaces the native DOM node corresponding to the specified child object of the calling object, and index is the relative displacement
    Table.replace (2, ' <tr><td> New Line </td><td></td><td></td></tr> '), Add a new row and replace the second row with it
    Table.replace ( -1, ' <tr><td> New Line </td><td></td><td></td></tr> '), Add a new row and replace it with the last line (the index is a negative number from the last count,-1 represents the last)
    function Clean (index) {}
    This method is used to delete sibling nodes, and index is the displacement relative to the location of the object that called the method
    Table.clean (), index omitted indicates deletion of the first child object, where the first row is deleted equivalent to Table.map (1). del (0)
    Table.clean (2), which means the deletion of the third line
    Table.clean (-2), which indicates the deletion of the last line
    Table.map (0). Clean ([0,-1,1]), if index is an array, it is to delete the child object of the specified index, the index is a negative number from the last count,-1 for the last one, here to delete the first, the second and the last th
    Table.map (0). Clean (0,-1), if there are two parameters, indicating the deletion of the child object of the specified interval, the index is a negative number for the last meter,-1 for the last one, here delete the first to the latter element, the parameter large can be used as the first parameter, the size order is not limited
    if the root node of the new tree is a table, and its child nodes are tbody/thead/tfoot, because we do not manipulate the nodes more often than we do, then I do a processing that allows skipping over these nodes. Of course, if you want to operate the tbody is also OK, you can do that. [' Tbody thead tfoot ', ' tr ', ' TD ']; just want to take one of the words can [' tbody ', ' tr ', ' TD ']; Direct TR, you can [' TR ', ' TD '], This situation will generate new objects for all TR in the Tbody/thead/tfoot

Conclusion: Back to think, with such a plug-in, node operation is not a piece of cake, the operation of the node mentioned above the three major problems can be solved. And this plug-in is independent of any logic, does not need two times processing, can be used to pick up, encountered can not meet the needs of the time to expand it. Imagine that one day the development process is like a jigsaw puzzle, the development of a good plug-in after the combination of a project out, that is how wonderful things ah. The result may not be as good as expected, but it can be expected that, in this direction, it is inevitable that events will become simpler and easier. Because the length is too long, the source code section will be the next time when the article is detailed interpretation.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.