tags:

views:

1417

answers:

4

I have a list element containing a number of between 20-30 events. I only want to show 5 of those, and have a «More» link I can click to watch the the next five. It doesn't matter if the five next events are appended.

Can't find a jQuery script that actually does this, or am I just blind? I don't want to use carousel plugins or anything like that.

+1  A: 

This works but sure you will have to tweak it some what :)

html:

<div style="width:200px;border:3px groove blue;">
   <ul id="list">
    <li>Thai</li>
    <li>Turkish</li>
    <li>Portuguese</li>
    <li>American English</li>
    <li>Arabic</li>
    <li>Canadian French</li>
    <li>Chinese Simplified</li>
    <li>Chinese Traditional</li>
    <li>Czech</li>
    <li>Danish</li>
    <li>Dutch</li>
    <li>English</li>
    <li>Finnish</li>
    <li>French</li>
    <li>German</li>
    <li>Greek</li>
    <li>Hebrew</li>
    <li>Hungarian</li>
    <li>Italian</li>
    <li>Japanese</li>
    <li>Norweigan</li>
    <li>Polish</li>
    <li>Russian</li>
    <li>Spanish</li>
   </ul>    
   <a href="#" id="lnkMore">More</a>
</div>

javascript:

<script type="text/javascript">
    var len = 0;
    var curStart = 0;
    var count = 5;
    var items=new Array();
    function BackupList() {
        var lst = $("ul#list");
        len= $("ul#list li").length;
        if (len <= count)
            return;

        $("ul#list li").each(function() {
            items.push($(this));
            $(this).remove();
        });

        var html="";
        for (curStart; curStart < count && curStart < len; curStart++) {
            html += "<li>" + $(items[curStart]).html() + "</li>";
        }
        $(html).appendTo($(lst));
    }

    function ShowMore() {
        if (curStart >= len) {
            curStart = 0;
        }

        $("ul#list li").each(function() {
            $(this).remove();
        });

        var l = curStart;
        var html = "";
        for (curStart; curStart < (l + count) && curStart < len; curStart++) {
            html += "<li>" + items[curStart].html() + "</li>";
        }
        $(html).appendTo($("ul#list"));
    }
</script>

Wire jquery for event:

<script type="text/javascript">
    $(document).ready(function() {
        BackupList();
        $("a#lnkMore").click(function() { ShowMore(); });
    });
</script>
TheVillageIdiot
+3  A: 

Well, fortunately for us programmers, who write code for food and fame, not every imaginable piece of functionality has been written yet as a plugin :)

But this is quite easy:

var from = 0, step = 5;

function showNext(list) {
  list
    .find('li').hide().end()
    .find('li:lt(' + (from + step) + '):not(li:lt(' + from + '))')
      .show();
  from += step;
}

function showPrevious(list) {
  from -= step;
  list
    .find('li').hide().end()
    .find('li:lt(' + from + '):not(li:lt(' + (from - step) + '))')
      .show();
}

// show initial set
showNext($('ul'));

// clicking on the 'more' link:
$('#more').click(function(e) {
  e.preventDefault();
  showNext($('ul'));
});

Of course this is better extracted into plugin-like function, but I'm gonna leave that as an exercise for a reader ;)

Damir Zekić
This looks nice, but how do I initially hide every list item except the first five?
rebellion
The initial call to `showNext(yourList)` will hide everything but the first five elements. I guess you would want to call it on `$(document).ready()`.
Damir Zekić
It didn't work for me, but it was only me who forgot to wrap all the li's in a ul ;) Thanks!
rebellion
Just a quick question. If I want to be able to link back to the previous five elements, how should I sort this?
rebellion
I've updated the original post with a sample function
Damir Zekić
A: 

You want to start off with each element in the list hidden (CSS: display: none). Then have your more link undernearth the list element.

$(document).ready(function()
{
    $("a#myMoreLink").click(function()
    {
     var items = $("ul#myList > li:hidden");

     if(items.length > 0)
      items.slice(0, 5).show();
     else
      $(this).html("No more");

     return false;
    });

    $("a#myMoreLink").click();
});

With HTML:

<ul id="myList">
    <li style="display: none"></li>
    <li style="display: none"></li>
</ul>
<a href="http://" id="myMoreLink">More</a>

Something like that. $("a#myMoreLink").click(); is called to show the initial 5 items upon loading the page.

Eric Muyser
Buggy code: it will always switch between first 5 and second 5 elements. Elements from 10 to 15 will never be displayed.
Damir Zekić
I didn't test the code, it's pseudo-code. OP said it didn't matter if they were appended (easily changeable).It does work. I just tested it. There's just a typo mylist -> myList.You down-rep me for that and make up some bug about 10-15 elements? This isn't a competition, jeez.Here's the full code:http://pastebin.com/m56bb8358
Eric Muyser
+2  A: 
<html>
<head><title>Test</title></head>
<body>
<ul class="more">
  <li>one</li>
  <li>two</li>
  <li>three</li>
  <li>four</li>
  <li>five</li>
  <li>six</li>
  <li>seven</li>
  <li>eight</li>
  <li>nine</li>
  <li>ten</li>
</ul>
<script type="text/javascript" src="jquery-1.3.1.js"></script>
<script type="text/javascript">
$(function() {
  $("ul.more").each(function() {
    $("li:gt(4)", this).hide(); /* :gt() is zero-indexed */
    $("li:nth-child(5)", this).after("<li class='more'><a href='#'>More...</a></li>"); /* :nth-child() is one-indexed */
  });
  $("li.more a").live("click", function() {
    var li = $(this).parents("li:first");
    li.parent().children().show();
    li.remove();
    return false;
  });
});
</script>
</script
</body>
</html>

Basically what this does:

  1. Hides the 6th and subsequent list items;
  2. Inserts a list item after the 5th saying "More...";
  3. Uses live events to add an event handler to the "More..." links so that when they are clicked they show all list items in that list and then remove themselves.

Edit: Fixed up a few little errors. The above is a fully working example now (just make sure the jquery link is correct).

cletus