6

I tried to add and remove div tags while scrolling like the Dojo grid works. I only want to display 7 div tags.

While scrolling left inside the container, when the first div tag (on the left side) was hidden from the webpage, then that hidden div is removed from the container and a new one is attached onto the right side.

The same process should be applied while scrolling to the right.

It's similar to this example. But in stead of scrolling the <tr> tag, I want to scroll through <div>'s.

This is what I tried before: https://jsfiddle.net/9y2ptsbg/3/ How can I do it? If there's any plugin out there (like Dojo), it's also helpful.

g00glen00b
  • 41,995
  • 13
  • 95
  • 133
  • You actually do nothing related to appending divs in your _onscroll_ function – Tien Nguyen Apr 01 '15 at 11:01
  • @TienNguyen I used `for loop` for appedning, this is not a gud idea.? –  Apr 01 '15 at 11:05
  • 1
    it is not a problem. your foor loop executed only once. It means that you append divs only once. Look at this to grasp the problem. https://jsfiddle.net/mandarin6b0/9y2ptsbg/4/ . You can continue from this point to solve your problem – Tien Nguyen Apr 01 '15 at 11:09

4 Answers4

1

maybe this js fiddle would help ?
https://jsfiddle.net/9y2ptsbg/12/

var container = $("#container"),
info = $("#info");

var j = 0;
var colors = ['rgba(143, 146, 199, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)', 'rgba(229, 86, 61, 0.49)', 'rgba(212, 229, 61, 0.49)', 'rgba(206, 61, 229, 0.49)', 'rgba(229, 157, 61, 0.49)', 'rgba(61, 165, 229, 0.49)', 'rgba(61, 229, 133, 0.49)', 'rgba(229, 61, 61, 0.49)', 'rgba(116, 61, 229, 0.49', 'rgba(218, 229, 61, 0.49)', 'rgba(21, 43, 157, 0.49)', 'rgba(153, 157, 21, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)', 'rgba(229, 86, 61, 0.49)', 'rgba(212, 229, 61, 0.49)', 'rgba(206, 61, 229, 0.49)', 'rgba(229, 157, 61, 0.49)', 'rgba(61, 165, 229, 0.49)', 'rgba(61, 229, 133, 0.49)', 'rgba(229, 61, 61, 0.49)', 'rgba(116, 61, 229, 0.49', 'rgba(218, 229, 61, 0.49)', 'rgba(21, 43, 157, 0.49)', 'rgba(153, 157, 21, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)']

var ary = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36'],
cursor = 0,
attachDiv = function (_curr) {
container.empty();
var j = 0;

for (var i = _curr; i < _curr + 8; i++) {

    container.append('<div  class = "blocks blocks' + i + '" style="left:' +   (j * 25) + '%; background:' + colors[i] + ';">' + ary[i] + '</div>');
    j++;
}
};
var hasScrolled = false,
locked = false,
ticker = function () {
    if (hasScrolled && !locked) {
        locked = true;
        var xz = container.scrollLeft(),
            maxScrollLeft = container.get(0).scrollWidth - container.get(0).clientWidth,
            middle = maxScrollLeft / 2;
        if (xz == 0) {
            cursor = Math.max(0, cursor - 4);
        } else if (xz == maxScrollLeft) {
            cursor = Math.min(cursor + 4, ary.length - 8)
        }
        attachDiv(cursor);
        container.scrollLeft(middle);
        info.text(cursor);
        locked = false;
    }
    hasScrolled = false;
}
setInterval(ticker, 250);
    container.on('scroll', function () {
    hasScrolled = true;
});

attachDiv(0);
ilyass
  • 402
  • 2
  • 9
0

Try

$(function() {
          
  // adjust `colors` length to multiples of 7
  var colors = [
    "rgba(143, 146, 199, 0.49)",
    "rgba(199, 143, 186, 0.49)",
    "rgba(149, 199, 143, 0.49)",
    "rgba(229, 86, 61, 0.49)",
    "rgba(212, 229, 61, 0.49)",
    "rgba(206, 61, 229, 0.49)",
    "rgba(229, 157, 61, 0.49)",
    "rgba(61, 165, 229, 0.49)",
    "rgba(61, 229, 133, 0.49)",
    "rgba(229, 61, 61, 0.49)",
    "rgba(116, 61, 229, 0.49",
    "rgba(218, 229, 61, 0.49)",
    "rgba(21, 43, 157, 0.49)",
    "rgba(153, 157, 21, 0.49)",
    "rgba(199, 143, 186, 0.49)",
    "rgba(149, 199, 143, 0.49)",
    "rgba(229, 86, 61, 0.49)",
    "rgba(212, 229, 61, 0.49)",
    "rgba(206, 61, 229, 0.49)",
    "rgba(229, 157, 61, 0.49)",
    "rgba(61, 165, 229, 0.49)",
    "rgba(61, 229, 133, 0.49)",
    "rgba(229, 61, 61, 0.49)",
    "rgba(116, 61, 229, 0.49",
    "rgba(218, 229, 61, 0.49)",
    "rgba(21, 43, 157, 0.49)",
    "rgba(153, 157, 21, 0.49)",
    "rgba(199, 143, 186, 0.49)"
    // "rgba(149, 199, 143, 0.49)"
  ];
  
  var container = $("<div/>", {
    "id":"container",
    "title":"click to pause , resume `scroller`"
  });
  
  var n = 7;

  var scrolled = false;

  var elems = $.map(colors, function(color, i) {
    return $("<div>", {
      "class": "blocks-" + (i + 1),
      "text": i + 1,
      "css": {
        "backgroundColor": color,
        "left": (i * 25) + "%"
      }
    })[0].outerHTML
  });
  
  var scroller = function scroller(e) {

    var xz = container.scrollLeft();
    
    var wx = container.width() * .73;
    
    var keys = $.map($("div:first, div:last", container), function(el) {
      return Number(el.className.replace(/[^\d+]/g, ""));
    });
    
    var first = keys[0];
    
    var last = keys[1];
    
    var _scroller = function _scroller(elem, idx) {

      if (idx === 1 && scrolled) {
        scrolled = false;
        elem.scroll()
        return
      };
      
      elem
      .stop(true, true)
      .off("scroll")
      .empty()
      .append(
        elems
        .slice(idx ? (idx - 1) - n : last
               , idx ? idx - 1 : last + n)
        .map(function(el, i) {
           return $(el).css("left", (i * 25) + "%")[0].outerHTML
        }).join("")
      )
      .delay(250)
      .animate({
          scrollLeft: (idx ? "+=" : "-=") + elem.width() / 3
        }, 1000, function() {
            scrolled = true;
            elem.on("scroll", scroller).scroll()
      })      
    };
        
    if (xz < n && first !== 1 ) {
      _scroller(container, first)
    };
    
    if (xz > wx && last !== colors.length) {              
       _scroller(container);   
    };
    


  };

  $("body")
  .append(
    container.data("scroll", true).html(elems.slice(0, n))
    .on("scroll", scroller)
  );
  
  container.on("click", function() {
     if (container.data("scroll")) {
       container.data("scroll", false).off("scroll")
     } else {
       container.data("scroll", true)
       .on("scroll", scroller).scroll()
     }
  })

});
[class^=blocks] {
  padding: 0px;
  width: 25%;
  position: absolute;
  height: 150%;
  text-align: center;
  font-size: 100px;
}
#container {
  width: 100%;
  height: 250px;
  position: relative;
  overflow: auto;
  margin-top: 50%;
  background: #2a2a2a;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
guest271314
  • 1
  • 15
  • 104
  • 177
  • Thank you for you answer and your answer is very useful for me. But not able to see the some blocks, like in first scroll i cann't see the `7`th block. I want to stop and check the each blocks. Again great thanks for your answer :) –  Apr 07 '15 at 11:39
  • @aja See updated post. Added click event to "pause" , "resume" `scroller` handler , by clicking on `#container`. Should be able to check each `.block` after first `click` "pauses" `scroller` , second `click` "resumes" `scroller` . Added `title` attribute to `#container` to notify of `click` functionality ; though `title` attribute , notification can be removed . You are welcome:) – guest271314 Apr 07 '15 at 14:30
  • Great thanks of you. And sory for again asking you. I want to display the element like` dojo`. But your script displays when scroll to the container, that time remove the all blocks(7) and add the new blocks(7). But i want add the blocks to the container by how many blocks are hideded from the display. For example, Onscroll, display the 6th blocks is first, that time display 6 7 8 9. Thank you again –  Apr 07 '15 at 15:23
  • @aja Not certain interpret "For example, Onscroll, display the 6th blocks is first, that time display 6 7 8 9." correctly ? See , at original post _"I tried to add and remove the div tag onscroll like dojo grid.?"_ , _"I want to display the only 7 div tags."_ ? At http://dojotoolkit.org/documentation/tutorials/1.9/working_grid/demo/rowclick.php , elements appear to be added , removed , added again ? Is requirement to _not_ to remove elements on `scroll` event ? – guest271314 Apr 07 '15 at 15:36
  • Hmm ok. I want to add and remove div tag exactly dojo grid. What the reason to i ask this, in my script generate the 40 laks values, that time will appear the 40 laks div tags, so my program ran very slowly. That the reason i thought this kind of method (dojo grid) is suited for my problem. Can you help me.? Greats thanks to you for spend your time for me. Thank you –  Apr 08 '15 at 04:19
0

Yes it's possible. First of all, you will need something like this as structure:

<div class="scroll">
    <div class="container">
        <div class="element element-1">1</div>
        <div class="element element-2">2</div>
        <div class="element element-3">3</div>
        <div class="element element-4">4</div>
        <div class="element element-5">5</div>
        <div class="element element-6">6</div>
    </div>
</div>

The .scroll element will be your scrolling container, it's limited in either width or height (depending on how you want to scroll) and has an overflow.

The .container on the other hands takes the highest possible width, so for 6 elements it would be element width * 6.

Finally, because you want to create a left/right scrolling animation, you probably want to set float: left to all .element nodes.

The JavaScript code isn't hard either. You want to add an onScroll event handler to the .scroll element, you can do that like this:

query(".scroll").on("scroll", function(evt) {

});

Then you want to detect whether or not you're scrolling to the left or right. You can do that by comparing the scrolling offset to the previous scrolling offset, for example:

if (lastPos && lastPos - evt.target.scrollLeft > 0) {
    // Scrolling to the left
} else if (lastPos && lastPos - evt.target.scrollLeft < 0) {
    // Scrolling to the right
}
lastPos = evt.target.scrollLeft;

Now, inside the if, you want to loop over all your .element's, detect whether or not on the left- or rightside of the visible portion, and if it is on one of those sides, you move it to the other side (depending on the scrolling direction).

To check whether or not the element is on the left- or right-side of the .scroll, I'm using Element.getBoundingClientRect():

var isLeftOfContainer = function(element) {
    var bounds = element.getBoundingClientRect();
    return (-bounds.left + element.parentNode.offsetLeft) >= bounds.width;
};

var isRightOfContainer = function(element) {
    var bounds = element.getBoundingClientRect();
    var box = element.parentNode.parentNode.getBoundingClientRect();
    return bounds.left - element.parentNode.offsetLeft > box.width;
};

To move the node to the other side, I'm using dojo/dom-construct::place(). You can add either "first" or "last" as third parameter, depending on the direction you're scrolling, for example:

domConstruct.place(elem, elem.parentNode, "first");

This will move the element (elem) to the first position of the parent node. Which is the thing we want to do when we're scrolling to the left.

To loop over all elements you can use dojo/query, for example:

query(".element").forEach(function(element) {

});

Remember that when you're scrolling to the left, you want to loop through the array from the last element to the first element, so that if 2 elements got hidden at the same time, the 6th element is added as first element before adding the 5th element as first element. This ensures that you always add the elements in the right order.

Then finally you have to adjust the scrolling position of the .scroll element. If you move a DOM node to the other side of the list, it has a side effect that all elements will move. This will lead to weird/buggy behavior if you don't move back the scrolling position.

You can do that by adjusting the scrollLeft attribute of the .scroll element.

Everything combined you could come up with something like this: http://jsfiddle.net/c3u6bfmf/

g00glen00b
  • 41,995
  • 13
  • 95
  • 133
  • Thank you. I want to display the `blocks` by the `array` content. I'm store the data into array, like `["1","10",40",56" ...]` then create the div tags by the array element. That array has above 5000 data. So i want to display the array element by `dojo`. How can i do it.? –  Apr 08 '15 at 10:27
  • With `dojo/dom-construct` you can also create elements. So, loop over your array and use `domConstruct.create()` to create the elements. With `domConstruct.place()` you can then place your new elements onto the `.container`. Don't forget to adjust the `width` of the `.container`, since it depends on the number of items inside. – g00glen00b Apr 08 '15 at 10:51
  • Take a look at http://stackoverflow.com/a/688685/1915448 as well. It's a bit outdated, but the concept is still the same (in stead of `dojo.create` you use `domConstruct.create`. – g00glen00b Apr 08 '15 at 10:53
0

Actually in the example you have given you are scrolling through divs. Each div contains a table, but that's beside the point.

I would say you need one content div, and play with its margins in javascript according to current scroll position. Just make sure the total width remains the same.

This would ensure the standard scrollbar is shown correctly and doesn't "jump", while the content can be adjusted to its position.

In the example you provided, BTW, they use 3 divs with partial content - only the div or divs in display have content, and perhaps partial content (only some content on its bottom or top, enough to fill the displayed area).

Anyway, the key here is to maintain a scrollable element large enough for the scrollbar to maintain its size and position, or to use a custom scrollbar written completely in javascript.

Itai Bar-Haim
  • 1,686
  • 16
  • 40