Skip to content Skip to sidebar Skip to footer

Move To Specific Div Based On Button Click

I was trying to move the divs (here it's question number) based on the prev and next button. So that the selected question is always visible on screen. Here is the demo : http://js

Solution 1:

Using scrollLeft is a bit tricky. I did a small redo of your use-case based on positioning and then moving it based on left of the container. The tricky part is to reliably calculate the negative position when scrolled to the extreme right. Also, need to take into account the widths and margins.

Check the below snippet:

var $wrap = $("#numWrap"), $strip = $("#strip"), 
    $leftArrow = $(".wrapper > .arrows").first(), 
    wrapWidth = $wrap.width() + $leftArrow.width(), 
    margin = 10;
    
fill(20); select($(".numberItem").first());

$strip.on("click", ".numberItem", function() { select($(this)); });

functionselect($elem) {
    $(".numberItem").removeClass("selected");
    $elem.addClass("visited").addClass("selected");
    focus($elem[0]);    
}

functionfocus(elem) {
    var stripPos = $strip.position(), 
        numPos = $(elem).offset(), 
        elemWidth = $(elem).width() + margin, 
        numRight = numPos.left + elemWidth;
    
    if (numRight > wrapWidth) {
        $strip.css({"left": stripPos.left - elemWidth}); 
    }
    if (numPos.left < (margin + $leftArrow.width()))  {
        $strip.css({"left": stripPos.left + elemWidth}); 
    }
}

$(".wrapper").on("click", "a.arrow", function() {
    var stripPos = $strip.position();
    if (this.id == "lft") {
        $strip.css({"left": stripPos.left + (wrapWidth / 2)}); 
    } else {
        $strip.css({"left": stripPos.left - (wrapWidth / 2)});
    }
});

$(".controls").on("click", "a.arrow", function() {
    var $sel = $(".selected"), numPos, $sel, elemWidth; 
    	$elem = $sel.length > 0 ? $sel.first() : $(".numberItem").first();
    if (this.id == "lft") {
        $sel = $elem.prev().length > 0 ? $elem.prev() : $elem;
        select($sel); 
    } else {
        $sel = $elem.next().length > 0 ? $elem.next() : $elem;
        select($sel);
    }
    numPos = $sel.offset(); elemWidth = $sel.width() + margin;
    numRight = numPos.left + elemWidth;
    if (numPos.left > wrapWidth) {
        $strip.css({"left": -($sel.text()) * $sel.width() });
    }
    if (numRight < 0) {
        $strip.css({"left": +($sel.text()) * $sel.width() });
    }
});

functionfill(num){
    for (var i = 1; i <= num; i++) {
        var $d = $("<a href='#' class='numberItem'>" + i + "</a>");
        $strip.append($d);
    }
}
* { box-sizing: border-box; padding: 0; margin: 0; font-family: sans-serif; }
div.wrapper { 
    background-color: #ddd; width: 100vw; height: 64px; 
    clear: both; overflow: hidden; margin-top: 16px;
}
div.arrows { 
    float: left; width: 10%; min-width: 24px; height: 64px; line-height: 64px;
    text-align: center; vertical-align: middle; overflow: hidden;
}
div.numWrap { 
    float: left; height: 64px; line-height: 64px;
    width: 80%; vertical-align: middle; 
    overflow: hidden; position: relative;
}
div.strip { 
    position: absolute; left: 0px;
    width: auto; white-space: nowrap; 
    transition: left 1s;
}
a.numberItem { 
    display: inline-block; text-align: center; margin: 0px8px;
    background-color: #fff; border-radius: 50%; width: 48px; height: 48px; 
    font-size: 1.2em; line-height: 48px; text-decoration: none;
}
a.numberItem.visited { background-color: #fff; color: #000; border: 2px solid #01aebc; }
a.numberItem.selected { background-color: #01aebc; color: #fff; }
div.controls { clear: both; }
div.controls > div.arrows { width: auto; margin: 012px; }
a, a:focus, a:active, a:link, a:visited { 
    display: inline-block; 
    text-decoration: none; font-weight: 600; 
}
<scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><divclass="wrapper"><divclass="arrows"><aid="lft"class="arrow"href="#">&#x3008;</a></div><divid="numWrap"class="numWrap"><divid="strip"class="strip"></div></div><divclass="arrows"><aid="rgt"class="arrow"href="#">&#x3009;</a></div></div><divclass="controls"><divclass="arrows"><aid="lft"class="arrow"href="#">&#x3008;&nbsp; Previous</a></div><divclass="arrows"><aid="rgt"class="arrow"href="#">Next &nbsp;&#x3009;</a></div><div>

Explanation:

  1. Using absolute positioning on the number container, which is nested to get 100% width.

Markup:

<divclass="wrapper"><divclass="arrows"><aid="lft"class="arrow"href="#">&#x3008;</a></div><divid="numWrap"class="numWrap"><divid="strip"class="strip"></div><!-- nesting here --></div><divclass="arrows"><aid="rgt"class="arrow"href="#">&#x3009;</a></div></div>

CSS:

div.wrapper { 
    background-color: #ddd; width: 100vw; height: 64px; 
    clear: both; overflow: hidden; margin-top: 16px;
}
div.arrows { 
    float: left; width: 10%; min-width: 24px; height: 64px; line-height: 64px;
    text-align: center; vertical-align: middle; overflow: hidden;
}
div.numWrap { 
    float: left; height: 64px; line-height: 64px;
    width: 80%; vertical-align: middle; 
    overflow: hidden; position: relative; /* relatively positioned */
}
div.strip { 
    position: absolute; left: 0px;        /* absolutely positioned */width: auto; white-space: nowrap; 
    transition: left 1s;                  /* instead of jquery animate */
}

With this structure, we can now use left to control the scrolling.

  1. For partially obscured numbers, try to gently focus-in (nudge into view) a number which is partially obscured. This can be done by checking the position relative to parent and adding the width/margin to it and also accounting for width of the left arrow (it might peep thru).

Javascript:

functionfocus(elem) {
    var stripPos = $strip.position(), 
        numPos = $(elem).offset(), 
        elemWidth = $(elem).width() + margin, 
        numRight = numPos.left + elemWidth;

    // if it is towards right side, nudge it back insideif (numRight > wrapWidth) {
        $strip.css({"left": stripPos.left - elemWidth}); 
    } 
    // if it is towards left side, nudge it back insideif (numPos.left < (margin + $leftArrow.width()))  {
        $strip.css({"left": stripPos.left + elemWidth}); 
    } 
}
  1. Once the user has scrolled the list too far and then tries to click on previous / next buttons to select a question, then we need to move the entire container upto the selected number. We can easily do this by multiplying the question number with element width and then changing the left in positive (if towards right) or in negative (if towards left).

Javascript:

// if left of element is more than the width of parent
if (numPos.left > wrapWidth) {
    $strip.css({"left": -($sel.text()) * $sel.width() });
}
// if right of element is less than 0 i.e. starting position
if (numRight < 0) {
    $strip.css({"left": +($sel.text()) * $sel.width() });
}

Here is a fiddle to play with: http://jsfiddle.net/abhitalks/aw166qhx/

You will need to further adapt it to your use-case, but you get the idea.

Post a Comment for "Move To Specific Div Based On Button Click"