Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Here is an updated version of 2.0 beta 1 with couple of bug fixes #430

Closed
YavorIvanov opened this issue May 8, 2012 · 0 comments
Closed

Comments

@YavorIvanov
Copy link

There were couple of issues related to fade effects, play, navigation and pagination.

Here is the usage case.

<script>
  $(function(){
    $("#slides").slides({
      width: 660, // [Number] Define the slide width
      height: 440, // [Number] Define the slide height
      responsive: false, // [Boolean] slideshow will scale to its container
      navigation: true, // [Boolean] Auto generate the naviagation, next/previous buttons
      pagination: true, // [Boolean] Auto generate the pagination
      effects: {
        navigation: "fade",  // [String] Can be either "slide" or "fade"
        pagination: "fade" // [String] Can be either "slide" or "fade"
      },
      direction: "left", // [String] Define the slide direction: "Up", "Right", "Down", "left"
      fade: {
        interval: 1000, // [Number] Interval of fade in milliseconds
        crossfade: false, // [Boolean] TODO: add this feature. Crossfade the slides, great for images, bad for text
        easing: "" // [String] Dependency: jQuery Easing plug-in <http://gsgd.co.uk/sandbox/jquery/easing/>
      },
      slide: {
        interval: 1000, // [Number] Interval of fade in milliseconds
        browserWindow: false, // [Boolean] Slide in/out from browser window, bad ass
        easing: "" // [String] Dependency: jQuery Easing plug-in <http://gsgd.co.uk/sandbox/jquery/easing/>
      },
      preload: {
        active: true, // [Boolean] Preload the slides before showing them, this needs some work
        image: "<%= asset_path('slides/loading.gif') %>" // [String] Define the path to a load .gif, yes I should do something cooler
      },
      startAtSlide: 1, // [Number] What should the first slide be?
      playInterval: 5000, // [Number] Time spent on each slide in milliseconds
      pauseInterval: 8000, // [Number] Time spent on pause, triggered on any navigation or pagination click
      autoHeight: false, // [Boolean] TODO: add this feature. Auto sets height based on each slide
      navigateStart: function( current ){
        //$('.caption').animate({
        //  bottom:-35
        //},100);
      },
      navigateEnd: function( current ){
        //$('.caption').animate({
        //  bottom:0
        //},200);
      },
      loaded: function() {
        //$('.caption').animate({
        //  bottom:0
        //},200);
      },
    });
    setTimeout('$("#slides").slides("play");',5000);
  });
</script>

Here is the updated version of the SlidesJS code.

/* 
    ===========================================================

    Note: SlidesJS version 2.0 beta 1 is not meant
    for production deployment. Please download the latest
    version at https://github.com/nathansearles/Slides.

    ===========================================================
*/ 

/*

     .d8888b.  888 d8b      888                888888  .d8888b.  
    d88P  Y88b 888 Y8P      888                  "88b d88P  Y88b 
    Y88b.      888          888                   888 Y88b.      
     "Y888b.   888 888  .d88888  .d88b.  .d8888b  888  "Y888b.   
        "Y88b. 888 888 d88" 888 d8P  Y8b 88K      888     "Y88b. 
          "888 888 888 888  888 88888888 "Y8888b. 888       "888 
    Y88b  d88P 888 888 Y88b 888 Y8b.          X88 88P Y88b  d88P 
     "Y8888P"  888 888  "Y88888  "Y8888   88888P' 888  "Y8888P"  
                                                .d88P            
                                              .d88P"             
                                             888P"               

    Created by Nathan Searles <http://nathansearles.com>

    Documentation and examples <http://slidesjs.com>
    Support forum <http://groups.google.com/group/slidesjs>

    Version: 2.0 beta 1
    Updated: June 22nd, 2011

    SlidesJS is an open source project, contribute at GitHub:
    https://github.com/nathansearles/Slides

    (c) 2011 by Nathan Searles

    Thanks to:
    Thomas Reynolds <http://awardwinningfjords.com/>
    Adam j. Sontag <http://ajpiano.com/>

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/*
    Documentaion
    ============================================================

    Basic Markup Structure
    ============================================================

    For just images you can simply use:

    <div id="slides">
            <img src="http://slidesjs.com/examples/standard/img/slide-1.jpg" width="570" height="270" alt="Slide 1">
            <img src="http://slidesjs.com/examples/standard/img/slide-2.jpg" width="570" height="270" alt="Slide 2">
            <img src="http://slidesjs.com/examples/standard/img/slide-3.jpg" width="570" height="270" alt="Slide 3">
            <img src="http://slidesjs.com/examples/standard/img/slide-4.jpg" width="570" height="270" alt="Slide 4">
    </div>

    Or you can use <div>s for your slides

    <div id="slides">
            <div>
                <img src="http://slidesjs.com/examples/standard/img/slide-1.jpg" width="570" height="270" alt="Slide 1">
            </div>
            <div>
                <img src="http://slidesjs.com/examples/standard/img/slide-2.jpg" width="570" height="270" alt="Slide 2">
            </div>
            <div>
                <img src="http://slidesjs.com/examples/standard/img/slide-3.jpg" width="570" height="270" alt="Slide 3">
            </div>
            <div>
                <img src="http://slidesjs.com/examples/standard/img/slide-4.jpg" width="570" height="270" alt="Slide 4">
            </div>
    </div>

    Simple as that. No extra <div>s, no navigation or pagination to define, it's all created for you. SlidesJS creates
    two <div>s for the slideshow, ".slidesContainer" and ".slidesControl", both are required and can not be changed.

    Navigation classes are ".slidesPrevious" and ".slidesNext" and are created as anchor tags. These cannot be changed.

    Pagination uses an unordered list markup structure. The <ul> has a class of ".slidesPagination". This cannot be changed.

    You may define your own navigation or pagination, but they must use the same class names,
    sorry it saves from including extraneous code.

    Basic CSS
    ============================================================

    No CSS required. Shit yeah!

    Initialize SlidesJS
    ============================================================

    <script>
        $(function(){
            $("#slides").slides();
        });
    </script>

    Tip: With SidesJS 2 you need to define the width and height if it's different from the default (780px x 300px). This resolves many issues having to do with loading and makes SlidesJS 2 self contained, not requiring any CSS.

    <pre><script>
     $(function(){
      $("#slides").slides({
        width: 640,
        height: 480
      });
     });
    </script></pre>

    Method Calls - The good stuff
    ============================================================

    Play:
        $("#slides").slides("play");

    Pause:
        $("#slides").slides("pause");

    Stop:
        $("#slides").slides("stop");

    Next:
        $("#slides").slides("next");
            - Uses default effect

        $("#slides").slides("next","fade");
            - Define effect, "slide" or "fade"

    Previous:
        $("#slides").slides("previous");
            - Uses default effect

        $("#slides").slides("previous","fade");
            - Define effect, "slide" or "fade"

    Goto a slide
        $("#slides").slides("slide",2);
            - Goto slide 2 using default effect

        $("#slides").slides("slide",4,"fade");
            - Define effect, "slide" or "fade"

    Update:
        $("#slides").slides("update");
            - Rebuilds pagination 

    Destroy:
        $("#slides").slides("destroy");
            - Removes SlidesJS, returns to predefined state

    Status:
        $("#slides").slides("status");
            - Returns JSON object:
                {
                    current: 4,
                    state: "playing",
                    total: 7
                }

        $("#slides").slides("status","current");
            - Returns current slide number

        $("#slides").slides("status","state");
            - Returns playing, paused, or stopped

        $("#slides").slides("status","total");
            - Returns total slides in slideshow

        Options
        ============================================================
        Check out the notes on the options below
*/

/*
    jQuery UI Widget, skip past this for SlidesJS
*/

/*!
 * jQuery UI Widget @VERSION
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Widget
 */
(function ($, undefined) {
  var slice = Array.prototype.slice;
  var _cleanData = $.cleanData;
  $.cleanData = function (elems) {
    for (var i = 0, elem;
    (elem = elems[i]) != null; i++) {
      $(elem).triggerHandler("remove");
    }
    _cleanData(elems);
  };
  $.widget = function (name, base, prototype) {
    var namespace = name.split(".")[0],
        fullName;
    name = name.split(".")[1];
    fullName = namespace + "-" + name;
    if (!prototype) {
      prototype = base;
      base = $.Widget;
    }
    // create selector for plugin
    $.expr[":"][fullName] = function (elem) {
      return !!$.data(elem, name);
    };
    $[namespace] = $[namespace] || {};
    // create the constructor using $.extend() so we can carry over any
    // static properties stored on the existing constructor (if there is one)
    $[namespace][name] = $.extend(function (options, element) {
      // allow instantiation without "new" keyword
      if (!this._createWidget) {
        return new $[namespace][name](options, element);
      }
      // allow instantiation without initializing for simple inheritance
      // must use "new" keyword (the code above always passes args)
      if (arguments.length) {
        this._createWidget(options, element);
      }
    }, $[namespace][name]);
    var basePrototype = new base();
    // we need to make the options hash a property directly on the new instance
    // otherwise we'll modify the options hash on the prototype that we're
    // inheriting from
    basePrototype.options = $.widget.extend({}, basePrototype.options);
    $.each(prototype, function (prop, value) {
      if ($.isFunction(value)) {
        prototype[prop] = (function () {
          var _super = function (method) {
            return base.prototype[method].apply(this, slice.call(arguments, 1));
          };
          var _superApply = function (method, args) {
            return base.prototype[method].apply(this, args);
          };
          return function () {
            var __super = this._super,
                __superApply = this._superApply,
                returnValue;
            this._super = _super;
            this._superApply = _superApply;
            returnValue = value.apply(this, arguments);
            this._super = __super;
            this._superApply = __superApply;
            return returnValue;
          };
        }());
      }
    });
    $[namespace][name].prototype = $.widget.extend(basePrototype, {
      namespace: namespace,
      widgetName: name,
      widgetEventPrefix: name,
      widgetBaseClass: fullName
    }, prototype);
    $.widget.bridge(name, $[namespace][name]);
  };
  $.widget.extend = function (target) {
    var input = slice.call(arguments, 1),
        inputIndex = 0,
        inputLength = input.length,
        key, value;
    for (; inputIndex < inputLength; inputIndex++) {
      for (key in input[inputIndex]) {
        value = input[inputIndex][key];
        if (input[inputIndex].hasOwnProperty(key) && value !== undefined) {
          target[key] = $.isPlainObject(value) ? $.widget.extend({}, target[key], value) : value;
        }
      }
    }
    return target;
  };
  $.widget.bridge = function (name, object) {
    $.fn[name] = function (options) {
      var isMethodCall = typeof options === "string",
          args = slice.call(arguments, 1),
          returnValue = this;
      // allow multiple hashes to be passed on init
      options = !isMethodCall && args.length ? $.widget.extend.apply(null, [options].concat(args)) : options;
      if (isMethodCall) {
        this.each(function () {
          var instance = $.data(this, name);
          if (!instance) {
            return $.error("cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'");
          }
          if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
            return $.error("no such method '" + options + "' for " + name + " widget instance");
          }
          var methodValue = instance[options].apply(instance, args);
          if (methodValue !== instance && methodValue !== undefined) {
            returnValue = methodValue.jquery ? returnValue.pushStack(methodValue.get()) : methodValue;
            return false;
          }
        });
      } else {
        this.each(function () {
          var instance = $.data(this, name);
          if (instance) {
            instance.option(options || {})._init();
          } else {
            object(options, this);
          }
        });
      }
      return returnValue;
    };
  };
  $.Widget = function (options, element) {
    // allow instantiation without "new" keyword
    if (!this._createWidget) {
      return new $[namespace][name](options, element);
    }
    // allow instantiation without initializing for simple inheritance
    // must use "new" keyword (the code above always passes args)
    if (arguments.length) {
      this._createWidget(options, element);
    }
  };
  $.Widget.prototype = {
    widgetName: "widget",
    widgetEventPrefix: "",
    defaultElement: "<div>",
    options: {
      disabled: false,
      // callbacks
      create: null
    },
    _createWidget: function (options, element) {
      element = $(element || this.defaultElement || this)[0];
      this.element = $(element);
      this.options = $.widget.extend({}, this.options, this._getCreateOptions(), options);
      this.bindings = $();
      this.hoverable = $();
      this.focusable = $();
      if (element !== this) {
        $.data(element, this.widgetName, this);
        this._bind({
          remove: "destroy"
        });
      }
      this._create();
      this._trigger("create");
      this._init();
    },
    _getCreateOptions: $.noop,
    _create: $.noop,
    _init: $.noop,
    destroy: function () {
      this._destroy();
      // we can probably remove the unbind calls in version 2
      // all event bindings should go through this._bind()
      this.element.unbind("." + this.widgetName).removeData(this.widgetName);
      this.widget().unbind("." + this.widgetName).removeAttr("aria-disabled").removeClass(
      this.widgetBaseClass + "-disabled " + "ui-state-disabled");
      // clean up events and states
      this.bindings.unbind("." + this.widgetName);
      this.hoverable.removeClass("ui-state-hover");
      this.focusable.removeClass("ui-state-focus");
    },
    _destroy: $.noop,
    widget: function () {
      return this.element;
    },
    option: function (key, value) {
      var options = key,
          parts, curOption, i;
      if (arguments.length === 0) {
        // don't return a reference to the internal hash
        return $.widget.extend({}, this.options);
      }
      if (typeof key === "string") {
        if (value === undefined) {
          return this.options[key];
        }
        // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
        options = {};
        parts = key.split(".");
        key = parts.shift();
        if (parts.length) {
          curOption = options[key] = $.widget.extend({}, this.options[key]);
          for (i = 0; i < parts.length - 1; i++) {
            curOption[parts[i]] = curOption[parts[i]] || {};
            curOption = curOption[parts[i]];
          }
          curOption[parts.pop()] = value;
        } else {
          options[key] = value;
        }
      }
      this._setOptions(options);
      return this;
    },
    _setOptions: function (options) {
      var self = this;
      $.each(options, function (key, value) {
        self._setOption(key, value);
      });
      return this;
    },
    _setOption: function (key, value) {
      this.options[key] = value;
      if (key === "disabled") {
        this.widget().toggleClass(this.widgetBaseClass + "-disabled ui-state-disabled", !! value).attr("aria-disabled", value);
        this.hoverable.removeClass("ui-state-hover");
        this.focusable.removeClass("ui-state-focus");
      }
      return this;
    },
    enable: function () {
      return this._setOption("disabled", false);
    },
    disable: function () {
      return this._setOption("disabled", true);
    },
    _bind: function (element, handlers) {
      // no element argument, shuffle and use this.element
      if (!handlers) {
        handlers = element;
        element = this.element;
      } else {
        // accept selectors, DOM elements
        element = $(element);
        this.bindings = this.bindings.add(element);
      }
      var instance = this;
      $.each(handlers, function (event, handler) {
        element.bind(event + "." + instance.widgetName, function () {
          // allow widgets to customize the disabled handling
          // - disabled as an array instead of boolean
          // - disabled class as method for disabling individual parts
          if (instance.options.disabled === true || $(this).hasClass("ui-state-disabled")) {
            return;
          }
          return (typeof handler === "string" ? instance[handler] : handler).apply(instance, arguments);
        });
      });
    },
    _hoverable: function (element) {
      this.hoverable = this.hoverable.add(element);
      this._bind(element, {
        mouseenter: function (event) {
          $(event.currentTarget).addClass("ui-state-hover");
        },
        mouseleave: function (event) {
          $(event.currentTarget).removeClass("ui-state-hover");
        }
      });
    },
    _focusable: function (element) {
      this.focusable = this.focusable.add(element);
      this._bind(element, {
        focusin: function (event) {
          $(event.currentTarget).addClass("ui-state-focus");
        },
        focusout: function (event) {
          $(event.currentTarget).removeClass("ui-state-focus");
        }
      });
    },
    _trigger: function (type, event, data) {
      var callback = this.options[type],
          args;
      event = $.Event(event);
      event.type = (type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type).toLowerCase();
      data = data || {};
      // copy original event properties over to the new event
      // this would happen if we could call $.event.fix instead of $.Event
      // but we don't have a way to force an event to be fixed multiple times
      if (event.originalEvent) {
        for (var i = $.event.props.length, prop; i;) {
          prop = $.event.props[--i];
          event[prop] = event.originalEvent[prop];
        }
      }
      this.element.trigger(event, data);
      args = $.isArray(data) ? [event].concat(data) : [event, data];
      return !($.isFunction(callback) && callback.apply(this.element[0], args) === false || event.isDefaultPrevented());
    }
  };
  $.each({
    show: "fadeIn",
    hide: "fadeOut"
  }, function (method, defaultEffect) {
    $.Widget.prototype["_" + method] = function (element, options, callback) {
      options = options || {};
      var hasOptions = !$.isEmptyObject(options),
          effectName = options.effect || defaultEffect;
      options.complete = callback;
      if (options.delay) {
        element.delay(options.delay);
      }
      if (hasOptions && $.effects && ($.effects.effect[effectName] || $.uiBackCompat !== false && $.effects[effectName])) {
        element[method](options);
      } else if (effectName !== method && element[effectName]) {
        element[effectName](options.duration, options.easing, callback);
      } else {
        element.queue(function () {
          $(this)[method]();
          if (callback) {
            callback.call(element[0]);
          }
        });
      }
    };
  });
  // DEPRECATED
  if ($.uiBackCompat !== false) {
    $.Widget.prototype._getCreateOptions = function () {
      return $.metadata && $.metadata.get(this.element[0])[this.widgetName];
    };
  }
})(jQuery);

/*
    SlidesJS, let the good times roll
*/
(function($) {
  $.widget("js.slides", {
        options: {
            width: 780, // [Number] Define the slide width
            responsive: false, // [Boolean] slideshow will scale to its container
            height: 300, // [Number] Define the slide height
            navigation: true, // [Boolean] Auto generate the naviagation, next/previous buttons
            pagination: true, // [Boolean] Auto generate the pagination
            effects: {
                navigation: "slide",  // [String] Can be either "slide" or "fade"
                pagination: "slide" // [String] Can be either "slide" or "fade"
            },
            direction: "left", // [String] Define the slide direction: "Up", "Right", "Down", "left"
            fade: {
                interval: 1000, // [Number] Interval of fade in milliseconds
                crossfade: false, // [Boolean] TODO: add this feature. Crossfade the slides, great for images, bad for text
                easing: "" // [String] Dependency: jQuery Easing plug-in <http://gsgd.co.uk/sandbox/jquery/easing/>
            },
            slide: {
                interval: 1000, // [Number] Interval of fade in milliseconds
                browserWindow: false, // [Boolean] Slide in/out from browser window, bad ass
                easing: "" // [String] Dependency: jQuery Easing plug-in <http://gsgd.co.uk/sandbox/jquery/easing/>
            },
            preload: {
                active: false, // [Boolean] Preload the slides before showing them, this needs some work
                image: "../img/loading.gif" // [String] Define the path to a load .gif, yes I should do something cooler
            },
            startAtSlide: 1, // [Number] What should the first slide be?
            playInterval: 5000, // [Number] Time spent on each slide in milliseconds
            pauseInterval: 8000, // [Number] Time spent on pause, triggered on any navigation or pagination click
            autoHeight: false, // [Boolean] TODO: add this feature. Auto sets height based on each slide
            navigateStart: function( current ){
                // console.log( "navigateStart: ", current );
            },
            navigateEnd: function( current ){
                // console.log( "navigateEnd: ", current );
            },
            loaded: function() {
                // console.log( "loaded" );
            }
        },
    _create: function() {   

            // Error correction for only 1 slide
            if (this.element.children().length < 2) {
                return;
            }

            if ( this.options.slide.browserWindow ) {
                this.element.css({
                    width: window.innerWidth,
                    position: "relative",
                    left: - (window.innerWidth / 2) + (this.options.width / 2),
                    overflow: "hidden"
                });

                $(window).resize( $.proxy(function() {
                    this.element.css({
                        width: window.innerWidth,
                        left: - (window.innerWidth / 2) + (this.options.width / 2)
                    });

                    this.slidesContainer.css({
                        left: this.options.slide.browserWindow ?  (window.innerWidth - this.options.width) / 2 : ""
                    });
                },this));
            }

            this.slidesContainer = this.element.children().not(".slidesNavigation").wrapAll( "<div class='slidesContainer'>" ).parent().css({
                width: this.options.responsive ? "100%" : this.options.width,
                height: this.options.height,
                overflow: this.options.slide.browserWindow ? "visible" : "hidden",
                position: "relative",
                left: this.options.slide.browserWindow ?  (window.innerWidth - this.options.width) / 2 : ""
            });

            this.slidesControl = this.slidesContainer.wrapInner( "<div class='slidesControl'>" ).children().css({
                display: "none"
            });

            // Define the slides
            this.slides = this.slidesControl.children();

            // Set CSS for slidesControl
            this.slidesControl.css({
                position: "relative",
                width: this.options.responsive ? "100%" : this.options.width,
                height: this.options.height,
                left: 0
            });

            // Set CSS for each slide
            this.slides.css({
                position: "absolute",
                top: 0, 
                left: 0,
                zIndex: 0,
                display: "none"
            });

            // Show the starting slide with a fade in
            this.slides.eq( this.options.startAtSlide - 1 ).fadeIn( this.options.fade.interval );

            if ( this.options.preload.active ) {

/*              TODO: loading image, need to remove on load callback

                    this.slidesContainer.css({
                        backgroundImage: "url(" + this.options.preload.image + ")",
                        backgroundPosition: "50% 50%",
                        backgroundRepeat: "no-repeat"
                    });
*/                  
                var preloadImage;

                if (this.slides.eq( this.options.startAtSlide - 1 ).is("img")) {
                    preloadImage = this.slides.eq( this.options.startAtSlide - 1 ).attr("src");
                } else {
                    preloadImage = this.slides.eq( this.options.startAtSlide - 1 ).find("img").attr("src");
                }

                this._loadImage( preloadImage ).then( $.proxy(function( url ) {
                this.slidesControl.fadeIn( this.options.fade.interval );
                    this._trigger( "loaded", this.options.startAtSlide, this );
                },this));
            } else {
                 this.slidesControl.fadeIn( this.options.fade.interval );
            }

            if ( this.options.navigation ) {
                this.prevButton = $("<a>",{
                    "class": "slidesPrevious slidesNavigation",
                    href: "#",
                    title: "Previous",
                    text: "Previous"
                }).appendTo( this.element );

                this.nextButton = $("<a>",{
                    "class": "slidesNext slidesNavigation",
                    href: "#",
                    title: "Next",
                    text: "Next"
                }).appendTo( this.element );
            } else {
                this.nextButton = $(".slidesNext");
                this.prevButton = $(".slidesPrevious");
            }       

            if (this.options.pagination) {
                this._buildPagination();
                // add current class to first pagination
                this.pagination.children().eq( this.options.startAtSlide - 1 ).addClass("slidesCurrent");
            }

            this.current = this.options.startAtSlide - 1;

            this.element.delegate( ".slidesNavigation", "click", $.proxy(this, "_navigate") );

            this.total = this.slides.length;
    },
        _loaded: function() {
            if ( this.options.responsive ) {

                // TODO: cleanup and condense
                this.slidesContainer.css({
                    height: this.slides.height()
                });

                this.slidesControl.css({
                    height: this.slides.height()
                });

                $(window).resize( $.proxy(function() {
                    this.slidesContainer.css({
                        height: this.slides.height()
                    });
                    this.slidesControl.css({
                        height: this.slides.height()
                    });
                },this));
            }
        },
    _buildPagination: function() {

            if (this.pagination) {
                // Remove the current paginaiton
                this.pagination.remove();
                // Redefine slides with new children
                this.slides = this.slidesControl.children();
            }

            this.pagination = $("<ul>",{
                "class": "slidesPagination"
            }).appendTo(this.element);

            this.slides.each(
                $.proxy(function(index, element) {
                    $("<li><a href='#" + index + "' class='slidesNavigation slidesPaginationItem' data-slidesindex=" + index + "> " + ( index + 1 ) + "</a></li>").appendTo(this.pagination);
                },this)
            );

    },
        _loadImage: function(imageSrc) {
            var deferred, preloader;
            var loadImageCache = {};
          if (typeof loadImageCache[imageSrc] === "undefined") {
            deferred = $.Deferred();

            preloader = new Image();
            preloader.onload  = function() {
                    deferred.resolve(this.src);
                };
            preloader.onerror = function() {
                    deferred.reject(this.src);
                };
            preloader.src = imageSrc;

            loadImageCache[imageSrc] = deferred;
          }

          return loadImageCache[imageSrc];
        },
        next: function( effect ) {
            this._navigate("next", effect);
        },
        previous: function( effect ) {
            this._navigate("previous", effect);
        },
        slide: function( slide, effect ) {          
            this.element.data("goto", (slide - 1));
            this._navigate("pagination", effect);
        },
        _navigate: function( event, effect ) {
            var to, position, direction, next, prev, pagination, $target = $(event.target), currentSlide = this.slides.eq( this.current );

            /*
                Slide to error correction
            */
            if ( this.element.data("goto") < 0 ) {
                // If goto is less then 0
                this.element.data("goto",0);
            } else  if ( this.element.data("goto") > this.total ) {
                // If goto is greater then total slides
                this.element.data("goto",(this.total - 1));
            }

            /*
                Check if slides is currently animating
            */
            if ( this.element.data("animated") || $target.data("slidesindex") === this.current || this.element.data("goto") === this.current ) {
                return false;
            }

            /*
                Is this event coming from a click?
            */
            if (typeof(event) === "object") {
                event.preventDefault();

                // Pause on navigation item click
                if ( this.state === "playing" && this.options.pauseInterval ) {
                    this.pause();
                }
            } else {
                if (event === "next") {
                    next = true;
                    effect = effect ? effect : this.options.effects.navigation;
                } else {
                    prev = true;
                    effect = effect ? effect : this.options.effects.navigation;
                }
            }

            /*
                Set to animated
            */
            this.element.data("animated",true);

            if ( $target.hasClass( "slidesNext" ) ) {
                // Next button clicked
                next = true;
                effect = effect ? effect : this.options.effects.navigation;

            } else if ( $target.hasClass("slidesPrevious") ) {

                // Previous button clicked
                prev = true;
                effect = effect ? effect : this.options.effects.navigation;

            }   else if ( $target.hasClass("slidesPaginationItem") ||  event === "pagination") {

                // Paginaiton item clicked
                if ( this.current > $target.data("slidesindex") || this.current > this.element.data("goto") ) {
                    prev = true;                    
                } else {
                    next = true;
                }

                pagination = true;

                effect = effect ? effect : this.options.effects.pagination;
            }


            if (pagination) {
                // Get next from data-slidesindex
                to = this.element.data("goto") > -1 ? this.element.data("goto") : $target.data("slidesindex");
            } else {
                // Get next based on curent
                to = next ? (this.current + 1) : (prev ? this.current - 1 : this.current);
            }

            // Pass slide from number
            this._trigger("navigateStart", ( this.current + 1 ), this);

            // creat the loop
            if ( to == this.slides.length && !pagination ) {
                // last slide, loop to first
                to = 0;
            } else if ( to == -1 && !pagination ) {
                // first slide, loop to last
                to = this.slides.length - 1;
            }

            if (this.options.pagination) {
                // Change the pagination
                this.pagination.children().removeClass("slidesCurrent");
                this.pagination.children().eq( to ).addClass("slidesCurrent");
            }

            // Effects methods
            if (effect === "fade") {
                this._fade({
                    next: next,
                    to: to,
                    currentSlide: currentSlide
                });
            } else {
                this._slide({
                    next: next,
                    to: to,
                    currentSlide: currentSlide
                });
            }
        },
        _slide: function (navigateData) {
            /*
                Thanks to Thomas Reynolds <http://awardwinningfjords.com/>
            */

            var isFlipped = navigateData.next ? 1 : -1;
            var isOpposite = this.options.direction.match(/right|down/) ? -1 : 1;
            var type = this.options.direction.match(/left|right/) ? "horizontal" : "vertical";
            var vector = (type == "horizontal") ? "width" : "height";

            vector = this.options.responsive ? this.slides.width() : this.options[vector] ;

            var position = vector * isOpposite * isFlipped;

            if (this.options.slide.browserWindow) {
                 if (navigateData.next) {
                    position = Math.abs( this.options.width - window.innerWidth - position);
                } else {
                    position = this.options.width - window.innerWidth + position;
                }                   
            }

            var direction = position * -1;

            // Setup the "to" slide
            this.slides.eq( navigateData.to ).css({
                left: type === "vertical" ? 0 : position,
                top:  type === "vertical" ? position : 0,
                zIndex: 5,
                display: "block"
            });

            // animate control
            this.slidesControl.animate({
                left: type === "vertical" ? 0 : direction,
                top:  type === "vertical" ? direction : 0
            },this.options.slide.interval, this.options.slide.easing, $.proxy(function(){
                // after animation reset control position
                this.slidesControl.css({
                    top: 0,
                    left:0
                });
                // reset and show next
                this.slides.eq( navigateData.to ).css({
                    top: 0,
                    left:0,
                    zIndex: 5
                });

                // reset previous slide
                navigateData.currentSlide.css({
                    top: 0,
                    left:0,
                    display: "none",
                    zIndex: 0
                });

                this.current = navigateData.to;

                this._trigger("navigateEnd", ( this.current + 1 ), this);
            }, this));
        },
        _fade: function (navigateData) {

                // put hidden to slide above current
                this.slides.eq( navigateData.to ).css({
                    zIndex: 10
                // fade in next
                }).fadeIn(this.options.fade.interval, this.options.fade.easing, $.proxy(function(){

                        // hide previous
                        navigateData.currentSlide.css({
                            display: "none",
                            zIndex: 0
                        });                             

                        // reset zindex
                        this.slides.eq( navigateData.to ).css({
                            zIndex: 0
                        });                 

                        this.current = navigateData.to;

                        this._trigger("navigateEnd", ( this.current + 1 ), this);

                }, this));
        },
        play: function( gotoNext ) {
            if (gotoNext !== false) {
                this._navigate("next");
            }

            var playInterval = setInterval( $.proxy(function() {
                this._navigate("next");
            }, this), this.options.playInterval);

            // Set status
            this.state = "playing";

            // Store the unique interval ID
            this.element.data("playIntervalId",playInterval);
        },
        pause: function() {
            clearTimeout( this.element.data("pauseTimeoutId") );

            clearInterval( this.element.data("playIntervalId") );

            var pauseTimeout = setTimeout($.proxy(function() {
                this.play();
             }, this), this.options.pauseInterval);

            // Set status
            this.state = "paused";

            // Store the unique pause timeout ID
            this.element.data("pauseTimeoutId",pauseTimeout);
        },
        stop: function() {
            clearInterval( this.element.data("playIntervalId") );

            // Set status
            this.state = "stopped";
        },
        update: function() {
            this._buildPagination();    
        },
        status: function( key ) {
            if (key) {
                return this[key] ? this[key] : false;
            } else {
                return {
                    "state": this.state,
                    "current": this.current,
                    "total": this.total
                };
            }

        },
        _setOption: function(key, value) {
      switch(key) {
                /*
                    TODO: This needs work, note status function use of this[key]
                    $("#slides").slides("option","pagination", false);

        case "pagination":
                    if (value !== this.options.pagination ) {
                        value ? this._buildPagination() : this.pagination.remove();
                    }
          break;
                */
      }
      $.Widget.prototype._setOption.apply(this,arguments);
    },
    destroy: function() {

            this.slidesContainer.contents().unwrap();

            this.slidesControl.contents().unwrap();

            this.element.unbind();

            this.pagination.remove();

            this.nextButton.remove();

            this.prevButton.remove();

            this.slides.attr( "style", "" );

      $.Widget.prototype.destroy.call(this);
    },
        _trigger: function( event, current ) {
            if (event != "create") {
                this.options[event]( current );
            }
            if (event === "navigateEnd") {
                this.element.data("animated",false);
            }
            if (event === "loaded") {
                this._loaded();
            }
        }
  });
})(jQuery);
@YavorIvanov YavorIvanov closed this as not planned Won't fix, can't repro, duplicate, stale Dec 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant