Korey
Korey

Reputation: 54

jquery .each() only doing last element

I am having problems with this function not running correctly... it only makes the last Element have the box appear.

NOTES: <aside> is position: fixed; and I do know this is not a "Proper" use of <article> tags, but it helps me to differentiate them for now.

HTML:

    <aside class="character">
        <div class="personHolder">
            <div class="person"></div>
        </div>
        <div class="arrow_box"></div>
    </aside>
    <main class="main">
        <section class="sections" id="Home">
            <article class="article1">
                <h1 class="sectionHeaders">Home</h1>
            </article>
        </section>
        <section class="sections" id="About">
            <article class="article2">                
                <h1 class="sectionHeaders">About Me</h1>
            </article>
        </section>
        <section class="sections" id="Projects">
            <article class="article3">                
                <h1 class="sectionHeaders">Projects</h1>
            </article>
        </section>
        <section class="sections" id="Contact">
            <article class="article3">                
                 <h1 class="sectionHeaders">Contact Me</h1>
            </article>
        </section>
    </main>

JavaScript/JQuery:

function checkElement() {
    var article1 = $(".article1");
    var article2 = $(".article2");
    var article3 = $(".article3");
    var article4 = $(".article4");
    var arrowTop = 170;
    var arrowBottom = 258;

    var articles = [article1, article2, article3, article4];

    $.each(articles, function(index, value) {
        if(value.offset().top < arrowTop && 
           value.offset().top + value.height() > arrowBottom) {
            $(".arrow_box").show();
        } else {
            $(".arrow_box").hide();
        }
    });
}

The following is the best thing I can do to a Fiddle, as I cannot make the fiddle work correctly... (Sorry) Free Website Host

I have tried the below before as well.

$("article").each(function() {
    if(this.offset().top < arrowTop && 
       this.offset().top + 
       this.height() > arrowBottom) {
        $(".arrow_box").show();
    } else {
        $(".arrow_box").hide();
    }
});

FINAL SOLUTION:

var showing = false;
$("article").each(function() {
    if (showing) return;
    if($(this).offset().top < arrowTop && 
       $(this).offset().top + 
       $(this).height() > arrowBottom) {
        $(".arrow_box").show();
        showing = true;
    } else {
        $(".arrow_box").hide();
    }
});

Upvotes: 2

Views: 916

Answers (1)

William
William

Reputation: 751

It seems like you are saying that each article has its own arrow box. In your function, you will check the offset of all articles, but the $(".arrow_box") selector will be the same for all articles, so you will hide/show it only depending on the last articles offset.

I dont know your HTML tree, but try to change the selector to something like

value.closest(".arrow_box").show();

Update

You want to cancel the each() once you have found an article in range. This can be done like this for instance:

var showing = false;
$("article").each(function() {
    if (showing) return;
    if(this.offset().top < arrowTop && 
       this.offset().top + 
       this.height() > arrowBottom) {
        $(".arrow_box").show();
        showing = true;
    } else {
        $(".arrow_box").hide();
    }
});

Upvotes: 3

Related Questions