views:

539

answers:

2

I've implemented the AnythingSlider (http://css-tricks.com/anythingslider-jquery-plugin/) using image and video content (videos use the longtail flv player - licensed version 5).

Problem: When the user plays the video, the slideshow doesn't know this has happened, so the slideshow keeps cycling while the video runs. So you have the slideshow running - and user can hear the audio but the video has cycled off.

I'm trying to figure out an event-listener that will look and see when the LONGTAIL player is in PLAYING state and signals to the AnythingSlider that it needs to STOP.

Here's what I've got so far ... the video player event listeners are working (right now I have alerts popping up so that I can be sure the events are being heard). An alert pops up with the player is initialized .. and alert pops up when we press the PLAY button on the video ... and an alert pops up when the video STOPS playing. But ... I've yet to work out the proper syntax for signaling to the anythingslider to STOP!

I thought it would be this:

$VUslider.startStop(false);

Below is the code I have so far ... beginning with the code that initializes the slider.

    function formatText(index, panel) {
  return index + "";
  }
$(function () {
 $('.VUslider').VUslider({
 autoPlay: true,
    delay: 7000,
    startStopped: false,
    animationTime: 200,
    hashTags: true,
    buildNavigation: false,
    pauseOnHover: true,
    navigationFormatter: formatText
    });
});

var player = null;
function playerReadyCallback(obj)  {
 player = document.getElementsByName(obj.id)[0];
    alert('the videoplayer '+obj['id']+' has been instantiated');
    player.addModelListener('STATE',     'stateMonitor');
}
function stateMonitor(obj) {
   currentState = obj['newstate'];
 if(currentState == 'PLAYING') {
   alert ('the videoplayer '+obj['id']+'  is playing now!');
   $VUslider.startStop(false);  // Trigger slideshow stop   
    }
 if(obj.newstate == 'COMPLETED') {
   alert ('the videoplayer '+obj['id']+'  has stopped playing now!');
   $VUslider.startStop(true);  // Trigger slideshow start   
    }
}

FOR REFERENCE ... HERE IS THE ANYTHING SLIDER CODE:

(function($){

    $.VUslider = function(el, options){
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el; 

        // Set up a few defaults
        base.currentPage = 1;
        base.timer = null;
        base.playing = false;

        // Add a reverse reference to the DOM object
        base.$el.data("AnythingSlider", base);

        base.init = function(){
            base.options = $.extend({},$.VUslider.defaults, options);

            // Cache existing DOM elements for later 
            base.$wrapper = base.$el.find('> div').css('overflow', 'hidden');
            base.$slider  = base.$wrapper.find('> ul');
            base.$items   = base.$slider.find('> li');
            base.$single  = base.$items.filter(':first');

            // Build the navigation if needed
            if(base.options.buildNavigation) base.buildNavigation();

            // Get the details
            base.singleWidth = base.$single.outerWidth();
            base.pages = base.$items.length;

            // Top and tail the list with 'visible' number of items, top has the last section, and tail has the first
            // This supports the "infinite" scrolling
            base.$items.filter(':first').before(base.$items.filter(':last').clone().addClass('cloned'));
            base.$items.filter(':last' ).after(base.$items.filter(':first').clone().addClass('cloned'));

            // We just added two items, time to re-cache the list
            base.$items = base.$slider.find('> li'); // reselect

            // Setup our forward/backward navigation
            base.buildNextBackButtons();

            // If autoPlay functionality is included, then initialize the settings
            if(base.options.autoPlay) {
                base.playing = !base.options.startStopped; // Sets the playing variable to false if startStopped is true
                base.buildAutoPlay();
            };

            // If pauseOnHover then add hover effects
            if(base.options.pauseOnHover) {
                base.$el.hover(function(){
                    base.clearTimer();
                }, function(){
                    base.startStop(base.playing);
                });
            }

            // If a hash can not be used to trigger the plugin, then go to page 1
            if((base.options.hashTags == true && !base.gotoHash()) || base.options.hashTags == false){
                base.setCurrentPage(1);
            };
        };

        base.gotoPage = function(page, autoplay){
            // When autoplay isn't passed, we stop the timer
            if(autoplay !== true) autoplay = false;
            if(!autoplay) base.startStop(false);

            if(typeof(page) == "undefined" || page == null) {
                page = 1;
                base.setCurrentPage(1);
            };

            // Just check for bounds
            if(page > base.pages + 1) page = base.pages;
            if(page < 0 ) page = 1;

            var dir = page < base.currentPage ? -1 : 1,
                n = Math.abs(base.currentPage - page),
                left = base.singleWidth * dir * n;

            base.$wrapper.filter(':not(:animated)').animate({
                scrollLeft : '+=' + left
            }, base.options.animationTime, base.options.easing, function () {
                if (page == 0) {
                    base.$wrapper.scrollLeft(base.singleWidth * base.pages);
                    page = base.pages;
                } else if (page > base.pages) {
                    base.$wrapper.scrollLeft(base.singleWidth);
                    // reset back to start position
                    page = 1;
                };
                base.setCurrentPage(page);

            });
        };

        base.setCurrentPage = function(page, move){
            // Set visual
            if(base.options.buildNavigation){
                base.$nav.find('.cur').removeClass('cur');
                $(base.$navLinks[page - 1]).addClass('cur');    
            };

            // Only change left if move does not equal false
            if(move !== false) base.$wrapper.scrollLeft(base.singleWidth * page);

            // Update local variable
            base.currentPage = page;
        };

        base.goForward = function(autoplay){
            if(autoplay !== true) autoplay = false;
            base.gotoPage(base.currentPage + 1, autoplay);
        };

        base.goBack = function(){
            base.gotoPage(base.currentPage - 1);
        };

        // This method tries to find a hash that matches panel-X
        // If found, it tries to find a matching item
        // If that is found as well, then that item starts visible
        base.gotoHash = function(){
            if(/^#?panel-\d+$/.test(window.location.hash)){
                var index = parseInt(window.location.hash.substr(7));
                var $item = base.$items.filter(':eq(' + index + ')');
                if($item.length != 0){
                    base.setCurrentPage(index);
                    return true;
                };
            };
            return false; // A item wasn't found;
        };

        // Creates the numbered navigation links
        base.buildNavigation = function(){
            base.$nav = $("<div id='thumbNav'></div>").appendTo(base.$el);
            base.$items.each(function(i,el){
                var index = i + 1;
                var $a = $("<a href='#'></a>");

                // If a formatter function is present, use it
                if( typeof(base.options.navigationFormatter) == "function"){
                    $a.html(base.options.navigationFormatter(index, $(this)));
                } else {
                    $a.text(index);
                }
                $a.click(function(e){
                    base.gotoPage(index);

                    if (base.options.hashTags)
                        base.setHash('panel-' + index);

                    e.preventDefault();
                });
                base.$nav.append($a);
            });
            base.$navLinks = base.$nav.find('> a');
        };


        // Creates the Forward/Backward buttons
        base.buildNextBackButtons = function(){
            var $forward = $('<a class="arrow forward">></a>'),
                $back    = $('<a class="arrow back"><</a>');

            // Bind to the forward and back buttons
            $back.click(function(e){
                base.goBack();
                e.preventDefault();
            });

            $forward.click(function(e){
                base.goForward();
                e.preventDefault();
            });

            // Append elements to page
            base.$wrapper.after($back).after($forward);
        };

        // Creates the Start/Stop button
        base.buildAutoPlay = function(){

            base.$startStop = $("<a href='#' id='start-stop'></a>").html(base.playing ? base.options.stopText :  base.options.startText);
            base.$el.append(base.$startStop);            
            base.$startStop.click(function(e){
                base.startStop(!base.playing);
                e.preventDefault();
            });

            // Use the same setting, but trigger the start;
            base.startStop(base.playing);
        };

        // Handles stopping and playing the slideshow
        // Pass startStop(false) to stop and startStop(true) to play
        base.startStop = function(playing){
            if(playing !== true) playing = false; // Default if not supplied is false

            // Update variable
            base.playing = playing;

            // Toggle playing and text
            if(base.options.autoPlay) base.$startStop.toggleClass("playing", playing).html( playing ? base.options.stopText : base.options.startText );

            if(playing){
                base.clearTimer(); // Just in case this was triggered twice in a row
                base.timer = window.setInterval(function(){
                    base.goForward(true);
                }, base.options.delay);
            } else {
                base.clearTimer();
            };
        };

        base.clearTimer = function(){
            // Clear the timer only if it is set
            if(base.timer) window.clearInterval(base.timer);
        };

        // Taken from AJAXY jquery.history Plugin
        base.setHash = function ( hash ) {
            // Write hash
            if ( typeof window.location.hash !== 'undefined' ) {
                if ( window.location.hash !== hash ) {
                    window.location.hash = hash;
                };
            } else if ( location.hash !== hash ) {
                location.hash = hash;
            };

            // Done
            return hash;
        };
        // <-- End AJAXY code


        // Trigger the initialization
        base.init();
    };


    $.VUslider.defaults = {
        easing: "swing",                // Anything other than "linear" or "swing" requires the easing plugin
        autoPlay: true,                 // This turns off the entire FUNCTIONALY, not just if it starts running or not
        startStopped: false,            // If autoPlay is on, this can force it to start stopped
        delay: 3000,                    // How long between slide transitions in AutoPlay mode
        animationTime: 600,             // How long the slide transition takes
        hashTags: true,                 // Should links change the hashtag in the URL?
        buildNavigation: true,          // If true, builds and list of anchor links to link to each slide
        pauseOnHover: true,             // If true, and autoPlay is enabled, the show will pause on hover
        startText: "Start",             // Start text
        stopText: "Stop",               // Stop text
        navigationFormatter: null       // Details at the top of the file on this use (advanced use)
    };


    $.fn.VUslider = function(options){
        if(typeof(options) == "object"){
            return this.each(function(i){           
                (new $.VUslider(this, options));

                // This plugin supports multiple instances, but only one can support hash-tag support
                // This disables hash-tags on all items but the first one
                options.hashTags = false;
            }); 
        } else if (typeof(options) == "number") {

            return this.each(function(i){
                var anySlide = $(this).data('AnythingSlider');
                if(anySlide){
                    anySlide.gotoPage(options);
                }
            });
        }
    };


})(jQuery);
A: 

Are you setting $VUslider to equal $('.VUslider').VUslider({ . . }); ?

In your example code you are not.

You should be doing something like this:

$VUslider = $('.VUslider').VUslider({
    autoPlay: true,
    delay: 7000,
    startStopped: false,
    animationTime: 200,
    hashTags: true,
    buildNavigation: false,
    pauseOnHover: true,
    navigationFormatter: formatText
});
PetersenDidIt
I've just added the anythingslider javascript to the post above.
Lacy
Updated my answer with a code example
PetersenDidIt
OK - I updated the function ... but still nothing going. Here's a beta page to show exactly what's going on. http://silverberry.org/beta/slider-longtail/
Lacy
A: 

This is somewhat of a stab in the dark, so I'll try to explain my reasoning a bit.

After you've created the VUslider bits as you're already doing, try doing this to start/stop the slider:

$('.VUslider').VUslider.startStop(false);

// this will toggle between starting and stopping but doesn't give control
// to call start or stop specifically.
$('#start-stop').click();

When you call $('.VUslider').VUslider({...}), it doesn't return anything, so there's no handle to VUslider at that point ($.each(..) doesn't return anything). This will hopefully get you a reference to the script and to the startStop function.

HTH

Carl
Tried this ... no luck... (thankfully you can really easily tell if the slideshow has stopped because the pause button turns to a green play button. Unfortunately, in this case it kept playing.) Frustrating to get half of the script worked out (the event listeners) - only to not be able to actually have it do anything!
Lacy
The more I read through the VUslider code, the more I think the developer has not exposed any of the internal methods (ie. can't call startStop as a user). The startStop function is attached to an internal reference (base) and not exposed externally. If you don't mind modifying the original script, I can give you the code to expose this function.
Carl
@Lacy, I've changed my code suggestion. Give this a try and let me know if it works for you. Instead of trying to call into the library, which I still think isn't quite possible, I've leveraged the attached function the library places on the start/stop link.
Carl
IT WORKED! There's some quirks though ... It's not fully aware of what's going on - I think it just is looking for clicks now - If you press play on the video ... it stops the slideshow. If you stop the video - and then restart the video - it restarts the slideshow (as I guess it registers another click, and thinks it should change the state again)?THANK YOU so much for looking at this :) I'm so excited that it's stopping in the first place!!
Lacy
You're exactly right about it just registering clicks. You could do some local state management/checking but it could get out of sync with the actual slider. If the slider library designer will expose the start/stop functionality, you can get around this easier.
Carl