How to implement “prevUntil” in Vanilla JavaScript without libraries?

前端 未结 7 908
遇见更好的自我
遇见更好的自我 2020-12-29 11:32

I need to implement the functionality of jQuery\'s prevUntil() method in Vanilla JavaScript.

I\'ve got several

elements on the same level:
相关标签:
7条回答
  • 2020-12-29 11:51

    Example Using previousSibling:

        var className = "needle";
        var element = clickedElement;
        while(element.previousSibling && element.previousSibling.className != className) {
           element = element.previousSibling;
        }
        element.previousSibling; // the element or null
    
    0 讨论(0)
  • 2020-12-29 11:54

    Just take a look at how jQuery does it.

    prevUntil: function( elem, i, until ) {
        return jQuery.dir( elem, "previousSibling", until );
    },
    

    Which uses a while / looping function caled dir(). The prevUntil just keeps going until previousSibling is the same as the until element.

    dir: function( elem, dir, until ) {
        var matched = [],
            cur = elem[ dir ];
    
        while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
            if ( cur.nodeType === 1 ) {
                matched.push( cur );
            }
            cur = cur[dir];
        }
        return matched;
    },
    
    0 讨论(0)
  • 2020-12-29 11:57

    You could use indexOf to determine if the index of the siblings are less than the index of the target element:

    // jshint esversion: 9
    
    // get the target node
    const node = document.querySelector("div:nth-child(3)");
    
    // get the target node's index
    const node_index = node.parentNode.indexOf(node);
    
    // get the siblings of the target node
    const siblings = node => [...node.parentNode.children].filter(child => 
      child !== node
    );
    console.log(siblings);
    
    // get the prevUntil
    const class_name = "\bmy_class\b";
    const prevUntil = siblings.filter((sibling, i) =>
      i < node_index && (sibling.getAttribute("class") || "").includes(class_name)
    );
    console.log(prevUntil);
    

    Good luck.

    0 讨论(0)
  • 2020-12-29 12:02

    This answer was previously published here in response to a similar question .

    There are a few ways to do it.

    Either one of the following should do the trick.

    // METHOD A (ARRAY.FILTER, STRING.INDEXOF)
    var siblings = function(node, children) {
        siblingList = children.filter(function(val) {
            return [node].indexOf(val) != -1;
        });
        return siblingList;
    }
    
    // METHOD B (FOR LOOP, IF STATEMENT, ARRAY.PUSH)
    var siblings = function(node, children) {
        var siblingList = [];
        for (var n = children.length - 1; n >= 0; n--) {
            if (children[n] != node) {
                siblingList.push(children[n]);
            }  
        }
        return siblingList;
    }
    
    // METHOD C (STRING.INDEXOF, ARRAY.SPLICE)
    var siblings = function(node, children) {
       siblingList = children;
       index = siblingList.indexOf(node);
       if(index != -1) {
           siblingList.splice(index, 1);
       }
       return siblingList;
    }
    

    FYI: The jQuery code-base is a great resource for observing Grade A Javascript.

    Here is an excellent tool that reveals the jQuery code-base in a very streamlined way. http://james.padolsey.com/jquery/

    0 讨论(0)
  • 2020-12-29 12:03

    Use .children in combination with .parentNode. Then filter the NodeList, after converting it into an array: http://jsfiddle.net/pimvdb/DYSAm/.

    var div = document.getElementsByTagName('div')[0];
    var siblings = [].slice.call(div.parentNode.children) // convert to array
                     .filter(function(v) { return v !== div }); // remove element itself
    console.log(siblings);
    
    0 讨论(0)
  • 2020-12-29 12:08

    How about this:

    while ( node = node.previousElementSibling ) {
        if ( ( ' ' + node.className + ' ' ).indexOf( 'foo' ) !== -1 ) {
            // found; do your thing
            break;
        }
    }
    

    Don't bother telling me that this doesn't work in IE8...

    0 讨论(0)
提交回复
热议问题