views:

444

answers:

2

I'm trying to implement a basic jQuery infinite carousel. As much for the learning process as for anything else (as a rule I'm not a fan of re-inventing wheels, but...I have to learn somehow, might as well start with the basics).

I've managed to get the list to animate left happily enough, but I'm stuck when it comes to selecting the first element of the list. I've tried to use:

$('ul#services > li:first');
$('ul#services > li:first-child');
$('ul#services > li').eq([0]);

(xhtml below),

In each case a console.log(first) (the var name used) returns all of the list-items. Am I doing something blatantly, and obviously, wrong?

The eventual plan is to clone the first li, append it to the parent ul, remove the li from the list and allow the list to scroll infinitely. It's just a list of services rather than links so I'm not -at the moment- planning to have scroll or left/right functionality.

Current xhtml:

(edited to add the entirety of the current code/html)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd"&gt;

<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <title></title>

    <link rel="stylesheet" type="text/css" href="css/stylesheet.css" />

    <!--[if IE 8]>

        <link rel="stylesheet" type="text/css" href="css/ie8.css" />

    <![endif]-->

    <!--[if lte IE 7]>

        <link rel="stylesheet" type="text/css" href="css/ie7.css" />

    <![endif]-->

    <style type="text/css" media="screen">
ul#services {overflow: visible; }
    </style>

    <script type="text/javascript" src="js/jquery.js"></script>


    <script type="text/javascript">

        $(document).ready(

            function() {

                $(document).ready(function() {

                    $('h1 > span.businessName').each(
                            function() {
                                var text = $(this).html();
                                var first_letter = text.substr(0,1);

                                if ( /[a-zA-Z]/.test(first_letter) ) {
                                    $(this).html('<span class="firstLetter">' + first_letter + '</span>' + text.slice(1));
                                }
                            }
                    ); 
            });

                $('ul#services > li').filter(':odd').addClass('odd');
                $('ul#services > li').filter(':visible:last').addClass('last');

//--> Function starts

        jQuery.fn.carousel = function() {
            // 1. find the width of the list items:

                var listWidth = $('ul#services > li').outerWidth();

            // 2a. find the current first item:

                var curFirst = $('ul#services > li').first();

                console.log(curFirst);

            // 2b. append the current first item:

            // 2c. remove the first item 

            // 3. animate the list, to move left by listWidth:

                $('ul#services > li').delay(500).css('position','relative').animate(
                    {
                    left: '-=' + listWidth
                    },
                    5000,
                        function() {

    //                      $('ul#services').get(0).remove();
                            $('ul#services').delay(500).carousel()
                        }
                );
            };
//--> Function ends.
            $('ul#services').carousel();

            }
        )

    </script>


</head>

<body>

    <div id="pageWrap">

        <div id="branding">

            <h1><span class="businessName">business name</span> <span class="tagline">some other info</span></h1>
            <hr id="rule">

        </div>

        <div id="content">

<div class="carousel">

    <div class="wrapper">

        <ul id="services">
            <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>

    </div>

        </div>

        <div id="mainPane">
<p>Lorem ipsum dolor sit amet...</p>
        </div>

        <div id="sidebar">

            <div id="contact">
    <!--
        STARTS hCARD (below)
    -->
                <div id="hcard">
                    <div id="hcard-yy-xx" class="vcard">
                        <span class="fn"><span class="given-name">YY</span> <span class="family-name">XX</span></span>
                        <div class="org">business name</div>
                        <a class="email" href="mailto:[email protected]">email</a>

                            <div class="tel">

                            </div>
                            <a class="downloadAs" href="http://suda.co.uk/projects/microformats/hcard/get-contact.php?uri=http://www.davidrhysthomas.co.uk/arch/tester.html"&gt;Download contact information</a>
                    </div>
                </div>
    <!--
        ENDS hCARD (above)
    -->
            </div>

            <div id="professionalBodies">

                <ul>
                    <li>some stuff</li>
                </ul>

            </div>

        </div>

    </div>

        <div class="push"></div>

    </div>

        <div id="footer">


        </div>

</body>

</html>

Updated, in response to Nick Craver's answer:

...I believe you want: $('ul#services li:first').remove(); ...What you probably want there is something like $('ul#services > li:first').delay(500)...

Using $('ul#services li:first').remove(); generates the error:

Uncaught TypeError: Object # has no method 'remove'

and there seems to be no difference in behaviour from using $('ul#services > li:first').delay(500)...

+1  A: 

http://api.jquery.com/first-selector/

$('ul#services li:first)

is correct, your problem must be elsewhere, try .first() ?

Alex
Looks good to me http://jsbin.com/ixusa/edit
Mark
Assuming you meant `var first = $('ul#services > li').first()` I can only say that it didn't work.
David Thomas
@ricebowl That worked for me. http://jsbin.com/ixusa/3/edit
Mark
+1  A: 

Since you're learning it, I won't do all the corrections here, but here are the main points:

This is erroring: $('ul#services').get(0).remove();
I believe you want: $('ul#services li:first').remove();

This is the main reason for what you're seeing: $('ul#services > li').delay(500)... This starts the animation on each of the child <li> and what you see is 10 console.log because you're kicking off carousel 10 times, 1 for each <li>.

What you probably want there is something like $('ul#services > li:first').delay(500)...

All of that make sense? I'm not exactly sure what you want the end result to be, just trying to explain your current behavior.

Nick Craver
Ah! I'd picked up on the `remove()` error, thanks to Google's console. The...animation issue hadn't even occurred to me. Thanks! I'm assuming , then, that I'd need to animate the `ul` rather than the descendant `li`s (I've left my mistake in my comment, but editing to note that I've caught your suggestion re animating $('ul#services > li:first')` thanks again? +1
David Thomas
@ricebowl - I'm not exactly sure what you want the result to be, so hard to say, you want them to scroll up or...?
Nick Craver
Scroll left. Ideally I'm trying to clone the first list-element, append it to the list and then remove the cloned-element. Rinse and repeat...
David Thomas
Incidentally, using `$('ul#services').get(0).remove()` generates the error: "Uncaught TypeError: Object #<an HTMLUListElement> has no method 'remove'" in Chrome's console.
David Thomas
@ricebowl - Check this out, more what you're after? http://jsfiddle.net/an3St/2/
Nick Craver
Other than the right-to-left scroll preference, that's exactly what I'm after =) thanks! +accepted!
David Thomas