简体   繁体   中英

Extreme JavaScript newbie - combining functions

Please excuse my lack of knowledge, I'm barely starting to learn. There's an unordered list that is pulled into a webpage via an include file. Certain pages only should display certain list items from that unordered list. So the solution a developer came up with is a simple one, hide the ones you don't want to see by having a script on each page, like so:

myFunction();
function myFunction() {
  var list = document.getElementsByClassName("content")[0];
  list.getElementsByTagName("li")[0].style.display="none";
list.getElementsByTagName("li")[1].style.display="none";
list.getElementsByTagName("li")[2].style.display="none";
list.getElementsByTagName("li")[3].style.display="none";
}

Now looking at this site, it makes more sense to have it as one long, scrolling page rather than multiple pages, but obviously this won't work with this script. Is there a way to have several instances of this include on the page, and use similar logic, but have each instance of that include only display certain list items from the unordered list, perhaps by wrapping each instance in an ID and targeting that ID?

For example:

<div id="one">
#include virtual="/content.html"
</div>

<div id="two">
#include virtual="/content.html" 
</div>

Where content.html contains the unordered list, but div id one only displays certain list items from that list, and div id two displays certain (different) list items from that list?

I hope that makes sense. Again, apologies if I'm not explaining this well. Any guidance much appreciated.

Thank you!

The architecture you are looking for is a filter function - you take a list of items, go through them one at a time, and if they aren't something you want to keep, take them out. You need to write this in a way that generalizes to any list and any keep/not-keep criteria, then run that function with the specific lists and criteria you have in mind.

So, something like this:

<div id="one">
#include virtual="/content.html"
</div>

<div id="two">
#include virtual="/content.html" 
</div>

<script>
// listDivId: The "id" of the div the list is under
// predicate: A function that takes the list item, and its index 
// in the list, and returns either true or false depending on 
// whether it should still be there
function filterContent(listDivId, predicate) {
    // First get the div you want to filter, if it's not there, return
    const listDiv = document.getElementById(listDivId);
    if (listDiv === null) return;
    // Then, get the list itself
    const list = listDiv.getElementsByClassName("content")[0].getElementsByTagName("li");
    // The "list" variable is now an array of "li" items, with a different 
    // item from list[0] to list[list.length - 1]. Use this while loop to 
    // go through each of them once
    let i = 0;
    while (i < list.length) {
        // Call the predicate. If it returns false, hide the item.
        if (!predicate(list[i], i)) {
            list[i].style.display = "none";
        }
        i = i + 1;
    }
}

// Now define our predicates.
function shouldAppearInOne(element, i) {
    return i >= 0 && i < 3;
}

function shouldAppearInTwo(element, i) {
    return i >= 3 && i < 6;
}

// Once we have both of those, call the filter function with those predicates
filterContent("one", shouldAppearInOne);
filterContent("two", shouldAppearInTwo);
</script>

As an aside, you mentioned that content.html is dynamically generated - frankly, this filtering thing would actually be better to put in the code that generates content.html . Instead of setting display = none on the list items you don't want to be there, you instead write the items that you do want to have there before the browser ever got a chance to sort through them:

let i = 0;
while (i < list.length) {
    // If we do want to include it, write the <li> element
    // (note that this assumes that `list` is just the text in the elements)
    if (predicate(list[i], i) {
        document.write("<li>" + list[i] + "</li>");
    }
    i = i + 1;
}

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