简体   繁体   中英

javascript not removing undefined objects from array

I've got an in page text search using JS, which is here:

$.fn.eoTextSearch = function(pat) {
    var out = []
    var textNodes = function(n) {
        if (!window['Node']) {
            window.Node = new Object();
            Node.ELEMENT_NODE = 1;
            Node.ATTRIBUTE_NODE = 2;
            Node.TEXT_NODE = 3;
            Node.CDATA_SECTION_NODE = 4;
            Node.ENTITY_REFERENCE_NODE = 5;
            Node.ENTITY_NODE = 6;
            Node.PROCESSING_INSTRUCTION_NODE = 7;
            Node.COMMENT_NODE = 8;
            Node.DOCUMENT_NODE = 9;
            Node.DOCUMENT_TYPE_NODE = 10;
            Node.DOCUMENT_FRAGMENT_NODE = 11;
            Node.NOTATION_NODE = 12;
        }
        if (n.nodeType == Node.TEXT_NODE) {
            var t = typeof pat == 'string' ?
            n.nodeValue.indexOf(pat) != -1 :
            pat.test(n.nodeValue);
            if (t) {
                out.push(n.parentNode)
            }
        }
        else {
            $.each(n.childNodes, function(a, b) {
                textNodes(b)
            })
        }
    }
    this.each(function() {
        textNodes(this)
    })
    return out
};

And I've got the ability to hide columns and rows in a table. When I submit a search and get the highlighted results, there would be in this case, the array length of the text nodes found would be 6, but there would only be 3 highlighted on the page. When you output the array to the console you get this:

So you get the 3 tags which I was expecting, but you see that the array is actually consisting of a [span,undefined,span,undefined,undefined,span] . Thus giving me the length of 6.

<span>
<span>
<span>
[span, undefined, span, undefined, undefined, span]

I don't know why it's not stripping out all of the undefined text nodes when I do the check for them. Here's what I've got for the function.

performTextSearch = function(currentObj){
    if($.trim(currentObj.val()).length > 0){
        var n = $("body").eoTextSearch($.trim(currentObj.val())),
            recordTitle = "matches",
            arrayRecheck = new Array(),
            genericElemArray = new Array()
        if(n.length == 1){
            recordTitle = "match"
        }

        //check to see if we need to do a recount on the array length. 
        //if it's more than 0, then they're doing a compare and we need to strip out all of the text nodes that don't have a visible parent.
        if($(".rows:checked").length > 0){
            $.each(n,function(i,currElem){
                if($(currElem).length != 0 && typeof currElem != 'undefined'){
                    if($(currElem).closest("tr").is(":visible") || $(currElem).is(":visible")){
                        //remove the element from the array
                        console.log(currElem)
                        arrayRecheck[i] = currElem
                    }
                }
            })
        }
        if(arrayRecheck.length > 0){
            genericElemArray.push(arrayRecheck)
            console.log(arrayRecheck)
        }
        else{
            genericElemArray.push(n)    
        }
        genericElemArray = genericElemArray[0]
        $("#recordCount").text(genericElemArray.length + " " +recordTitle)
        $(".searchResults").show()
        for(var i = 0; i < genericElemArray.length; ++i){ 
            void($(genericElemArray[i]).addClass("yellowBkgd").addClass("highLighted"))
        }   
    }
    else{
        $(".highLighted").css("background","none")  
    }           
}

If you look at the code below "//check to see if we need to do a recount on the array length. ", you'll see where I'm stripping out the text nodes based off of the display and whether or not the object is defined. I'm checking the length instead of undefined because the typeof == undefined wasn't working at all for some reason. Apparently, things are still slipping by though.

Any idea why I'm still getting undefined objects in the array?

My apologies for such a big post!

Thanks in advance

I've modified your eoTextSearch() function to remove dependencies on global variables in exchange for closures:

$.fn.extend({
  // helper function
  // recurses into a DOM object and calls a custom function for every descendant
  eachDescendant: function (callback) {
    for (var i=0, j=this.length; i<j; i++) {
      callback.call(this[i]);
      $.fn.eachDescendant.call(this[i].childNodes, callback);
    }
    return this;
  },
  // your text search function, revised
  eoTextSearch: function () {
    var text = document.createTextNode("test").textContent 
               ? "textContent" : "innerText";
    // the "matches" function uses an out param instead of a return value
    var matches = function (pat, outArray) {
      var isRe = typeof pat.test == "function";
      return function() {
        if (this.nodeType != 3) return; // ...text nodes only
        if (isRe && pat.test(this[text]) || this[text].indexOf(pat) > -1) {
          outArray.push(this.parentNode);
        }
      }
    };
    // this is the function that will *actually* become eoTextSearch()
    return function (stringOrPattern) {
      var result = $(); // start with an empty jQuery object
      this.eachDescendant( matches(stringOrPattern, result) );
      return result;
    }
  }()  // <- instant calling is important here
});

And then you can do something like this:

$("body").eoTextSearch("foo").filter(function () {
  return $(this).closest("tr").is(":visible");
});

To remove unwanted elements from the search result. No "recounting the array length" necessary. Or you use each() directly and decide within what to do.

I cannot entirely get my head around your code, but the most likely issue is that you are removing items from the array, but not shrinking the array afterwards. Simply removing items will return you "undefined", and will not collapse the array.

I would suggest that you do one of the following:

  1. Copy the array to a new array, but only copying those items that are not undefined

  2. Only use those array items that are not undefined.

I hope this is something of a help.

Found the answer in another post.

Remove empty elements from an array in Javascript

Ended up using the answer's second option and it worked alright.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM