You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1055 lines
32 KiB
1055 lines
32 KiB
/* |
|
=========================================================== |
|
|
|
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 + " data-skip-pjax=true> " + ( 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; |
|
} else { |
|
prev = true; |
|
} |
|
} |
|
|
|
/* |
|
Set to animated |
|
*/ |
|
this.element.data("animated",true); |
|
|
|
if ( $target.hasClass( "slidesNext" ) ) { |
|
// Next button clicked |
|
next = true; |
|
|
|
} else if ( $target.hasClass("slidesPrevious") ) { |
|
|
|
// Previous button clicked |
|
prev = true; |
|
|
|
} 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); |