PageSourceSearch

https://www.fisieo.it/script/slider/jquery.sequence.js

js fisieo.it collected 2026-10-06 13:58:43 UTC 65,279 bytes, 1,253 lines download raw bytes

1/*
2Sequence.js (http://www.sequencejs.com)
3Version: 1.0
4Author: Ian Lunn @IanLunn
5Author URL: http://www.ianlunn.co.uk/
6Github: https://github.com/IanLunn/Sequence
7
8This is a FREE script and is available under a MIT License:
9http://www.opensource.org/licenses/mit-license.php
10
11Sequence.js and its dependencies are (c) Ian Lunn Design 2012 - 2013 unless otherwise stated.
12
13Sequence also relies on the following open source scripts:
14
15- jQuery imagesLoaded 2.1.0 (http://github.com/desandro/imagesloaded)
16	Paul Irish et al
17	Available under a MIT License: http://www.opensource.org/licenses/mit-license.php
18
19- jQuery TouchWipe 1.1.1 (http://www.netcu.de/jquery-touchwipe-iphone-ipad-library)
20	Andreas Waltl, netCU Internetagentur (http://www.netcu.de)
21	Available under a MIT License: http://www.opensource.org/licenses/mit-license.php
22
23- Modernizr 2.6.1 Custom Build (http://modernizr.com/)
24	Copyright (c) Faruk Ates, Paul Irish, Alex Sexton
25	Available under the BSD and MIT licenses: www.modernizr.com/license/
26	*/
27
28;(function($) {
29	var windowLoaded = false;
30	$(window).bind("load", function() {
31		windowLoaded = true;
32	});
33
34	function Sequence(element, options, defaults, get) {
35		var self = this;
36		self.container = $(element); //the Sequence containing element
37		self.canvas = self.container.children('.sequence-canvas'); //the Sequence canvas which holds Sequence's frames (<li> elements)
38		self.frames = self.canvas.children('li'); //the Sequence frames (top level <li> elements within the Sequence canvas)
39
40		try { //is Modernizr.prefixed installed?
41			Modernizr.prefixed;
42			if(Modernizr.prefixed === undefined){
43				throw "undefined";
44			}
45		}
46		catch(err) { //if not...get the custom build necessary for Sequence
47			get.modernizr();
48		}
49
50		var prefixes = { //convert JS transition names to CSS names
51			'WebkitTransition' : '-webkit-',
52			'MozTransition'    : '-moz-',
53			'OTransition'      : '-o-',
54			'msTransition'     : '-ms-',
55			'transition'       : ''
56		},
57		transitions = { //convert JS transition names to JS transition end and animation end event names (also apply a classname of .sequence to the event)
58			'WebkitTransition' : 'webkitTransitionEnd.sequence webkitAnimationEnd.sequence',
59			'MozTransition'    : 'transitionend.sequence animationend.sequence',
60			'OTransition'      : 'otransitionend.sequence oanimationend.sequence',
61			'msTransition'     : 'MSTransitionEnd.sequence MSAnimationEnd.sequence',
62			'transition'       : 'transitionend.sequence animationend.sequence'
63		};
64
65		self.prefix = prefixes[Modernizr.prefixed('transition')], //work out the CSS prefix for the browser being used (-webkit- for example)
66		self.transitionProperties = {},
67		self.transitionEnd = transitions[Modernizr.prefixed('transition')], //work out the JS transitionEnd name for the browser being used (webkitTransitionEnd webkitAnimationEnd for example)
68		self.numberOfFrames = self.frames.length, //number of frames (<li>) Sequence consists of
69
70		self.transitionsSupported = (self.prefix !== undefined) ? true : false, //determine if transitions are supported
71		self.hasTouch = ("ontouchstart" in window) ? true : false, //determine if this is a touch enabled device
72		self.isPaused = false, //whether Sequence is paused
73		self.isBeingHoveredOver = false, //whether the Sequence canvas is currently being hovered over
74
75		self.container.removeClass('sequence-destroyed'); //if Sequence is destroyed using .destroy(), it is given a clas of "destroy", remove that now if present
76
77		//CALLBACKS
78		self.paused = function() {},												//executes when Sequence is paused
79		self.unpaused = function() {},											//executes when Sequence is unpaused
80
81		self.beforeNextFrameAnimatesIn = function() {},			//executes before the next frame animates in
82		self.afterNextFrameAnimatesIn = function() {},			//executes after the next frame animates in
83		self.beforeCurrentFrameAnimatesOut = function() {},	//executes before the current frame animates out
84		self.afterCurrentFrameAnimatesOut = function() {},	//executes after the current frame animates out
85
86		self.afterLoaded = function() {};										//executes after Sequence is initiated
87		self.destroyed = function() {};											//executes when Sequence is destroyed via the destory() function
88
89		//INIT
90		self.settings = $.extend({}, defaults, options); //combine default options with developer defined ones
91		self.settings.preloader = renderUiElements(self, self.settings.preloader, '.sequence-preloader'); //set up the preloader and save it
92		self.isStartingFrame = (self.settings.animateStartingFrameIn) ? true : false; //determine if the first frame should animate in
93		self.settings.unpauseDelay = (self.settings.unpauseDelay === null) ? self.settings.autoPlayDelay 
93: self.settings.unpauseDelay; //if the unpauseDelay is not specified, make it the same as the autoPlayDelay speed
94		self.getHashTagFrom = (self.settings.hashDataAttribute) ? "data-sequence-hashtag": "id"; //get the hashtag from the ID or data attribute?
95		self.frameHashID = []; //array that matches frames with has IDs
96		self.direction = self.settings.autoPlayDirection;
97
98		if(self.settings.hideFramesUntilPreloaded && self.settings.preloader !== undefined  && self.settings.preloader !== false) { //if using a preloader and hiding frames until preloading has completed...
99			self.frames.hide(); //hide Sequence's frames
100		}
101
102		if(self.prefix === "-o-") { //if Opera prefixes are required...
103			self.transitionsSupported = get.operaTest(); //run a test to see if Opera correctly supports transitions (Opera 11 has bugs relating to transitions)
104		}
105
106		self.frames.removeClass("animate-in"); //remove any instance of "animate-in", which should be used incase JS is disabled
107
108		//functionality to run once Sequence has preloaded
109		function oncePreloaded() {
110			self.afterLoaded(); //callback
111			if(self.settings.hideFramesUntilPreloaded && self.settings.preloader !== undefined  && self.settings.preloader !== false) {
112				self.frames.show();
113			}
114			if(self.settings.preloader !== undefined  && self.settings.preloader !== false){
115				if(self.settings.hidePreloaderUsingCSS && self.transitionsSupported) {
116					self.prependPreloadingCompleteTo = (self.settings.prependPreloadingComplete === true) ? self.settings.preloader : $(self.settings.prependPreloadingComplete);
117					self.prependPreloadingCompleteTo.addClass("preloading-complete");
118					setTimeout(init, self.settings.hidePreloaderDelay);
119				}else{
120					self.settings.preloader.fadeOut(self.settings.hidePreloaderDelay, function() {
121						clearInterval(self.defaultPreloader);
122						init();
123					});
124				}
125			}else{
126				init();
127			}
128		}
129
130		var preloadTheseFramesLength = self.settings.preloadTheseFrames.length; //how many frames to preload?
131		var preloadTheseImagesLength = self.settings.preloadTheseImages.length; //how many single images to load?
132
133		function saveImagesToArray(length, srcOnly) {
134			var imagesToPreload = []; //saves the images that are to be preloaded
135			if(!srcOnly){
136				for(var i = length; i > 0; i--){ //for each frame to be preloaded...
137					self.frames.eq(self.settings.preloadTheseFrames[i-1]-1).find("img").each(function() { //find <img>'s in specific frames, and for each found...
138						imagesToPreload.push($(this)[0]); //add it to the array of images to be preloaded
139					});
140				}
141			}else{
142				for(var j = length; j > 0; j--) { //for each frame to be preloaded...
143					imagesToPreload.push($("body").find('img[src="'+self.settings.preloadTheseImages[j-1]+'"]')); //find any <img> with the given source and add it to the array of images to be preloaded
144				}
145			}
146			return imagesToPreload;
147		}
148
149		//jQuery imagesLoaded plugin v2.1.0 (http://github.com/desandro/imagesloaded)
150		function imagesLoaded(imagesToPreload, callback) {
151			var BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
152			var $this = imagesToPreload,
153			deferred = $.isFunction($.Deferred) ? $.Deferred() : 0,
154			hasNotify = $.isFunction(deferred.notify),
155			$images = $this.find('img').add( $this.filter('img') ),
156			loaded = [],
157			proper = [],
158			broken = [];
159
160			//Register deferred callbacks
161			if($.isPlainObject(callback)) {
162				$.each(callback, function(key, value) {
163					if(key === 'callback') {
164						callback = value;
165					}else if(deferred) {
166						deferred[key](value);
167					}
168				});
169			}
170
171			function doneLoading() {
172				var $proper = $(proper),
173				$broken = $(broken);
174
175				if(deferred) {
176					if(broken.length) {
177						deferred.reject($images, $proper, $broken);
178					}else{
179						deferred.resolve($images);
180					}
181				}
182
183				if($.isFunction(callback)) {
184					callback.call($this, $images, $proper, $broken);
185				}
186			}
187
188			function imgLoaded( img, isBroken ) {
189				if(img.src === BLANK || $.inArray(img, loaded) !== -1) { // don't proceed if BLANK image, or image is already loaded
190					return;
191			}
192
193				loaded.push(img); // store element in loaded images array
194
195				if(isBroken) { // keep track of broken and properly loaded images
196					broken.push(img);
197				}else{
198					proper.push(img);
199				}
200
201				$.data(img, 'imagesLoaded', {isBroken: isBroken, src: img.src }); // cache image and its state for future calls
202
203				if(hasNotify) { // trigger deferred progress method if present
204					deferred.notifyWith($(img), [isBroken, $images, $(proper), $(broken)]);
205				}
206
207				if($images.length === loaded.length) { // call doneLoading and clean listeners if all images are loaded
208					setTimeout(doneLoading);
209					$images.unbind('.imagesLoaded');
210				}
211			}
212
213			if(!$images.length) { // if no images, trigger immediately
214				doneLoading();
215			}else{
216				$images.bind('load.imagesLoaded error.imagesLoaded', function(event) {
217					imgLoaded(event.target, event.type === 'error'); // trigger imgLoaded
218				}).each(function(i, el) {
219					var src = el.src;
220					var cached = $.data(el, 'imagesLoaded'); // find out if this image has been already checked for status if it was, and src has not changed, call imgLoaded on it
221					if(cached && cached.src === src) {
222						imgLoaded(el, cached.isBroken);
223						return;
224					}
225
226					if(el.complete && el.naturalWidth !== undefined) { // if complete is true and browser supports natural sizes, try to check for image status manually
227						imgLoaded(el, el.naturalWidth === 0 || el.naturalHeight === 0);
228						return;
229					}
230
231					// cached images don't fire load sometimes, so we reset src, but only when dealing with IE, or image is complete (loaded) and failed manual check webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
232					if(el.readyState || el.complete) {
233						el.src = BLANK;
234						el.src = src;
235					}
236				});
237			}
238		}
239
240		if(self.settings.preloader !== undefined && self.settings.preloader !== false && (preloadTheseFramesLength !== 0 || preloadTheseImagesLength !== 0)) { //if using the preloader and the dev has specified some images should preload...
241			var frameImagesToPreload = saveImagesToArray(preloadTheseFramesLength); //get images from particular Sequence frames to be preloaded
242			var individualImagesToPreload = saveImagesToArray(preloadTheseImagesLength, true); //get images with specific source values to be preloaded
243			var imagesToPreload = $(frameImagesToPreload.concat(individualImagesToPreload)); //combine frame images and individual images
244
245			imagesLoaded(imagesToPreload, oncePreloaded);
246		}else{ //if not using the preloader...
247			if(windowLoaded === true) { //if the window has already loaded...
248				oncePreloaded(); //run the init functionality when the preloader has finished
249				$(this).unbind("load.sequence"); //unbind the load event as it's no longer needed
250			}else{ //if the window hasn't already loaded...
251				$(window).bind("load.sequence", function() { //when the window loads...	
252					oncePreloaded(); //run the init functionality when the preloader has finished
253					$(this).unbind("load.sequence"); //unbind the load event as it's no longer needed
254				});
255			}
256		}
257
258		function init() {
259			$(self.settings.preloader).remove(); //remove the preloader element
260
261			self.nextButton = renderUiElements(self, self.settings.nextButton, ".sequence-next"); //set up the next button
262			self.prevButton = renderUiElements(self, self.settings.prevButton, ".sequence-prev"); //set up the previous button
263			self.pauseButton = renderUiElements(self, self.settings.pauseButton, ".sequence-pause"); //set up the pause button
264			self.pagination = renderUiElements(self, self.settings.pagination, ".sequence-pagination"); //set up the pagination
265
266			if((self.nextButton !== undefined && self.nextButton !== false) && self.settings.showNextButtonOnInit === true){self.nextButton.show();} //if using a next button, show it
267			if((self.prevButton !== undefined && self.prevButton !== false) && self.settings.showPrevButtonOnInit === true){self.prevButton.show();} //if using a previous button, show it
268			if((self.pauseButton !== undefined && self.pauseButton !== false) && self.settings.showPauseButtonOnInit === true){self.pauseButton.show();} //if using a pause button, show it
269
270			if(self.settings.pauseIcon !== false) {
271				self.pauseIcon = renderUiElements(self, self.settings.pauseIcon, ".sequence-pause-icon");
272				if(self.pauseIcon !== undefined) {
273					self.pauseIcon.hide();
274				}
275			}else{
276				self.pauseIcon = undefined;
277			}
278
279			if(self.pagination !== undefined && self.pagination !== false) {
280				self.paginationLinks = self.pagination.children(); //get each pagination link
281
282				self.paginationLinks.on('click.sequence', function() { //when a pagination link is clicked...
283					var associatedFrameNumber = $(this).index() + 1; //get the number of the frame this link is associated with
284					self.goTo(associatedFrameNumber); //go to the associate frame
285				});
286
287				if(self.settings.showPaginationOnInit === true) {
288					self.pagination.show();
289				}
290			}
291
292			self.nextFrameID = self.settings.startingFrameID;
293
294			if(self.settings.hashTags === true) { //if using hashtags...
295				self.frames.each(function() { //for each frame...
296					self.frameHashID.push($(this).prop(self.getHashTagFrom)); //add the hashtag to an array
297				});
298
299				self.currentHashTag = location.hash.replace("#", ""); //get the current hashtag
300				if(self.currentHashTag === undefined || self.currentHashTag === "") { //if there is no hashtag...
301					self.nextFrameID = self.settings.startingFrameID; //use the startingFrameID
302				}else{
303					self.frameHashIndex = $.inArray(self.currentHashTag, self.frameHashID); //get the index of the frame that matches the hashtag
304					if(self.frameHashIndex !== -1){  //if the hashtag matches a Sequence frame ID...
305						self.nextFrameID = self.frameHashIndex + 1; //use the frame associated to the hashtag
306					}else{
307						self.nextFrameID = self.settings.startingFrameID; //use the startingFrameID
308					}
309				}
310			}
311
312			self.nextFrame = self.frames.eq(self.nextFrameID-1); //get the next frame
313			self.nextFrameChildren = self.nextFrame.children(); //get the elements within the next frame to be animated
314
315			if(self.pagination !== undefined) { //if using pagination, make the starting frame the current one in pagination
316				$(self.paginationLinks[self.settings.startingFrameID-1]).addClass('current'); //add the 'current' class to the current frame
317			}
318
319			if(self.transitionsSupported) { //initiate the full featured Sequence if transitions are supported...
320				if(!self.settings.animateStartingFrameIn) { //start first frame in animated in position
321					self.currentFrameID = self.nextFrameID;
322
323					if(self.settings.moveActiveFrameToTop) {
324						self.nextFrame.css('z-index', self.numberOfFrames);
325					}
326
327					resetElements(self.prefix, self.nextFrameChildren, "0s");
328					self.nextFrame.addClass("animate-in");
329					if(self.settings.hashTags && self.settings.hashChangesOnFirstFrame) {
330						self.currentHashTag = self.nextFrame.prop(self.getHashTagFrom);
331						document.location.hash = "#"+self.currentHashTag;
332					}
333
334					setTimeout(function() {
335						resetElements(self.prefix, self.nextFrameChildren, "");
336					}, 100);
337
338					resetAutoPlay(self, true, self.settings.autoPlayDelay);
339				}else if(self.settings.reverseAnimationsWhenNavigatingBackwards && self.settings.autoPlayDirection -1 && self.settings.animateStartingFrameIn) { //animate in backwards
340					resetElements(self.prefix, self.nextFrameChildren, "0s");
341					self.nextFrame.addClass("animate-out");
342					self.goTo(self.nextFrameID, -1, true);
343				}else{ //animate in forwards
344					self.goTo(self.nextFrameID, 1, true);
345				}
346			}else{ //initiate a basic slider for browsers that don't support CSS3 transitions
347				self.container.addClass("sequence-fallback");
348				self.currentFrameID = self.nextFrameID;
349				if(self.settings.hashTags && self.settings.hashChangesOnFirstFrame){
350					self.currentHashTag = self.nextFrame.prop(self.getHashTagFrom);
351					document.location.hash = "#"+self.currentHashTag;
352				}
353
354				self.frames.addClass("animate-in");
354 //move each frame into its animate-in position
355				self.frames.not(':eq('+(self.nextFrameID-1)+')').css({"display": "none", "opacity": 0}); //set all frames (except the next one) to display: none, opacity: 0
356				resetAutoPlay(self, true, self.settings.autoPlayDelay);
357			}
358			//END INIT
359			//EVENTS
360			if(self.nextButton !== undefined) { //if a next button is defined...
361				self.nextButton.bind('click.sequence', function() { //when the next button is clicked...
362					self.next(); //go to the next frame
363				});
364			}
365
366			if(self.prevButton !== undefined) { //if a previous button is defined...
367				self.prevButton.bind('click.sequence', function() { //when the previous button is clicked...
368					self.prev(); //go to the previous frame
369				});
370			}
371
372			if(self.pauseButton !== undefined) { //if a pause button is defined...
373				self.pauseButton.bind('click.sequence', function() { //when the pause button is clicked...
374					self.pause(true); //pause Sequence and set hardPause to true
375				});
376			}
377
378			function keyEvents(keyPressed, keyDirections) {
379				var keyCode;
380				var keyCodes;
381
382				for(keyCodes in keyDirections) {
383					if(keyCodes === "left" || keyCodes === "right") {
384						keyCode = defaultKeys[keyCodes];
385					}else{
386						keyCode = keyCodes;
387					}
388
389					if(keyPressed === parseFloat(keyCode)) { //if the key pressed is associated with a function...
390						initCustomKeyEvent(self, keyDirections[keyCodes]); //initiate the function
391					}
392				}
393			}
394
395			if(self.settings.keyNavigation) {
396				var defaultKeys = {
397					'left'	: 37,
398					'right'	: 39
399				};
400
401				$(document).bind('keydown.sequence', function(e) { //when a key is pressed...
402					var keyCodeChar = String.fromCharCode(e.keyCode);
403					if((keyCodeChar > 0 && keyCodeChar <= self.numberOfFrames) && (self.settings.numericKeysGoToFrames)) {
404						self.nextFrameID = keyCodeChar;
405						self.goTo(self.nextFrameID); //go to specified frame
406					}
407
408					keyEvents(e.keyCode, self.settings.keyEvents); //run default keyevents
409					keyEvents(e.keyCode, self.settings.customKeyEvents); //run custom keyevents
410				});
411			}
412
413			if(self.settings.pauseOnHover && self.settings.autoPlay && !self.hasTouch) { //if using pauseOnHover and autoPlay on non touch devices
414				self.canvas.on({
415					'mouseenter.sequence': function() { //when the mouse enter the Sequence element...
416						self.isBeingHoveredOver = true;
417						if(!self.isHardPaused) { //if Sequence is hard paused (via a pause button)...
418							self.pause(); //pause autoPlay
419						}
420					},
421					'mouseleave.sequence': function() { //when the mouse leaves the Sequence element...
422						self.isBeingHoveredOver = false;
423						if(!self.isHardPaused) { //if Sequence is not hard paused (via a pause button)...
424							self.unpause(); //unpause autoPlay
425						}
426					}
427				});
428			}
429
430			if(self.settings.hashTags) { //if hashchange is enabled in the settings...
431				$(window).bind('hashchange.sequence', function() { //when the hashtag changes...
432					var newTag = location.hash.replace("#", ""); //grab the new hashtag
433
434					if(self.currentHashTag !== newTag) { //if the last hashtag is not the same as the current one...
435						self.currentHashTag = newTag; //save the new tag
436						self.frameHashIndex = $.inArray(self.currentHashTag, self.frameHashID); //get the index of the frame that matches the hashtag
437						if(self.frameHashIndex !== -1) { //if the hashtag matches a Sequence frame ID...
438							self.nextFrameID = self.frameHashIndex + 1; //set that frame as the next one
439								self.goTo(self.nextFrameID); //go to the next frame
440							}
441						}
442					});
443			}
444
445			function cancelTouch() {
446				self.canvas.on("touchmove.sequence", onTouchMove);
447				startX = null;
448				isMoving = false;
449			}
450
451			function onTouchMove(e) {
452				if(self.settings.swipePreventsDefault) {
453					e.preventDefault();
454				}
455				if(isMoving) {
456					var x = e.originalEvent.touches[0].pageX;
457					var y = e.originalEvent.touches[0].pageY;
458					var dx = startX - x;
459					var dy = startY - y;
460					if(Math.abs(dx) >= self.settings.swipeThreshold) {
461						cancelTouch();
462						if(dx > 0) {
463							initCustomKeyEvent(self, self.settings.swipeEvents.left);
464						}else{
465							initCustomKeyEvent(self, self.settings.swipeEvents.right);
466						}
467					}else if(Math.abs(dy) >= self.settings.swipeThreshold) {
468						cancelTouch();
469						if(dy > 0) {
470							initCustomKeyEvent(self, self.settings.swipeEvents.down);
471						}else{
472							initCustomKeyEvent(self, self.settings.swipeEvents.up);
473						}
474					}
475				}
476			}
477
478			function onTouchStart(e) {
479				if(e.originalEvent.touches.length === 1) {
480					startX = e.originalEvent.touches[0].pageX;
481					startY = e.originalEvent.touches[0].pageY;
482					isMoving = true;
483					self.canvas.on("touchmove.sequence", onTouchMove);
484				}
485			}
486
487			if(self.settings.swipeNavigation && self.hasTouch) { //if using swipeNavigation and the device has touch capabilities...
488				//jQuery TouchWipe v1.1.1 (http://www.netcu.de/jquery-touchwipe-iphone-ipad-library)
489				var startX;
490				var startY;
491				var isMoving = false;
492
493				self.canvas.on("touchstart.sequence", onTouchStart);
494			}
495			//END EVENTS
496		}
497	} //END CONSTRUCTOR
498
499	Sequence.prototype = {
500
501		//PUBLIC METHODS
502		/*
503		start autoPlay -- causing Sequence to automatically change frame every x amount of milliseconds
504		
505		delay: a time in ms before starting the autoPlay feature (if unspecified, the default will be used)
506		*/
507		startAutoPlay: function(delay) {
508			var self = this;
509			delay = (delay === undefined) ? self.settings.autoPlayDelay : delay; //if a delay isn't specified, use the default
510			self.unpause();
511
512			resetAutoPlay(self); //stop autoPlay before starting it again
513			self.autoPlayTimer = setTimeout(function() { //start a new autoPlay timer and...
514				if(self.settings.autoPlayDirection === 1) { //go to either the next or previous frame
515					self.next();
516				}else{
517					self.prev();
518				}
519			}, delay); //after a specified delay
520		},
521
522		//stop causing Sequence to automatically change frame every x amount of seconds
523		stopAutoPlay: function() {
524			var self = this;
525			self.pause(true);
526			clearTimeout(self.autoPlayTimer); //stop the autoPlay timer
527		},
528
529		/*
530		Toggle startAutoPlay (unpausing autoPlay) and stopAutoPlay (pausing autoPlay)
531
532		hardPause: if true, Sequence's pauseOnHover will not execute. Useful for pause buttons.
533
534		Note: Sequence 0.7.3 and below didn't have an .unpause() function -- .pause() would pause/unpause
535		based on the current state. .unpause() is now included for clarity but the .pause() function will
536		still toggle between paused and unpaused states.
537		*/
538		pause: function(hardPause) {
539			var self = this;
540			if(!self.isSoftPaused) { //if pausing Sequence...
541				if(self.pauseButton !== undefined) { //if a pause button is defined...
542					self.pauseButton.addClass("paused");
542 //add the class of "paused" to the pause button
543					if(self.pauseIcon !== undefined) { //if a pause icon is defined...
544						self.pauseIcon.show(); //show the pause icon
545					}
546				}
547				self.paused(); //callback when Sequence is paused
548				self.isSoftPaused = true;
549				self.isHardPaused = (hardPause) ? true : false; //if hardPausing, set hardPause to true
550				self.isPaused = true;
551				resetAutoPlay(self); //stop autoPlay
552			}else{ //if unpausing Sequence...
553				self.unpause();
554			}
555		},
556
557		/*
558		Start the autoPlay feature, as well as deal with any changes to pauseButtons, pauseIcons and public variables etc
559		
560		callback: if false, the unpause callback will not be initiated (this is because unpause is used internally during the stop and start of each frame)
561		*/
562		unpause: function(callback) {
563			var self = this;
564			if(self.pauseButton !== undefined) { //if a pause button is defined...
565				self.pauseButton.removeClass("paused"); //remove the class of "paused" from the pause button
566				if(self.pauseIcon !== undefined) { //if a pause icon is defined...
567					self.pauseIcon.hide(); //hide the pause icon
568				}
569			}
570
571			self.isSoftPaused = false;
572			self.isHardPaused = false;
573			self.isPaused = false;
574
575			if(!self.active) {
576				if(callback !== false) {
577					self.unpaused(); //callback when Sequence is unpaused
578				}
579				resetAutoPlay(self, true, self.settings.unpauseDelay); //start autoPlay after a delay specified via the unpauseDelay setting
580			}else{
581				self.delayUnpause = true; //Sequence is animating so delay the unpause event until the animation completes
582			}
583		},
584
585		//Go to the frame ahead of the current one
586		next: function() {
587			var self = this;
588			self.nextFrameID = (self.currentFrameID !== self.numberOfFrames) ? self.currentFrameID + 1 : 1; //work out the next frame
589			if(self.active === false || self.active === undefined) { //if Sequence isn't currently animating...
590				self.goTo(self.nextFrameID, 1); //go to the next frame
591			}else{ //if Sequence is currently animating...
592				self.goTo(self.nextFrameID, 1, true); //go immediately to the next frame (ignoring the transition threshold)
593			}
594		},
595
596		//Go to the frame prior to the current one
597		prev: function() {
598			var self = this;
599			self.nextFrameID = (self.currentFrameID === 1) ? self.numberOfFrames : self.currentFrameID - 1; //work out the prev frame
600			if(self.active === false || self.active === undefined) { //if Sequence isn't currently animating...
601				self.goTo(self.nextFrameID, -1); //go to the prev frame
602			}else{ //if Sequence is currently animating...
603				self.goTo(self.nextFrameID, -1, true); //go immediately to the prev frame (ignoring the transition threshold)
604			}
605		},
606
607		/*
608		Go to a specific frame
609		
610		id: number of the frame to go to
611		direction: direction to get to that frame (1 = forward, -1 = reverse)
612		ignoreTransitionThreshold: if true, ignore the transitionThreshold setting and immediately go to the specified frame
613		*/
614		goTo: function(id, direction, ignoreTransitionThreshold) {
615			var self = this;
616			id = parseFloat(id); //convert the id to a number just in case
617			var transitionThreshold = (ignoreTransitionThreshold === true) ? 0 : self.settings.transitionThreshold; //if transitionThreshold is to be ignored, set it to zero
618
619			if((id === self.currentFrameID) //if the id of the frame the user is trying to go to is the same as the currently active one...
620			|| (self.settings.navigationSkip && self.navigationSkipThresholdActive) //or navigationSkip is enabled and the navigationSkipThreshold is active (which prevents frame from being navigated too fast)...
621			|| (!self.settings.navigationSkip && self.active) //or navigationSkip is disbaled but Sequence is animating...
622			|| (!self.transitionsSupported && self.active) //or Sequence is in fallback mode and Sequence is animating...
623			|| (!self.settings.cycle && direction === 1 && self.currentFrameID === self.numberOfFrames) //or cycling is disabled, the user is navigating forward and this is the last frame...
624			|| (!self.settings.cycle && direction === -1 && self.currentFrameID === 1) //or cycling is disabled, the user is navigating backwards and this is the first frame...
625			|| (self.settings.preventReverseSkipping && self.direction !== direction && self.active)) { //or Sequence is animating and the user is trying to change the direction of navigation...
626				return false; //don't go to another frame
627			}else if(self.settings.navigationSkip && self.active) { //if navigationSkip is enabled and Sequence is animating (a frame is being skipped before it has finished animating)...
628				self.navigationSkipThresholdActive = true; //the navigationSkipThreshold is now active
629				if(self.settings.fadeFrameWhenSkipped) { //if a frame should fade when skipped...
630					self.nextFrame.stop().animate({"opacity": 0}, self.settings.fadeFrameTime); //fade
631				}
632
633				clearTimeout(self.transitionThresholdTimer);
634
635				setTimeout(function() { //start the navigationSkipThreshold timer to prevent being able to navigate too quickly
636					self.navigationSkipThresholdActive = false; //once the timer is complete, navigationSkip can occur again
637				}, self.settings.navigationSkipThreshold);
638			}
639
640			if(!self.active || self.settings.navigationSkip) { //if there are no animations running or navigationSkip is enabled...
641				self.active = true; //Sequence is now animating
642				resetAutoPlay(self); //stop any autoPlay timer that may be running
643
644				if(direction === undefined) { //if no direction to navigate was defined...
645					self.direction = (id > self.currentFrameID) ? 1 : -1; //work out which way to go based on what frame is currently active
646				}else{
647					self.direction = direction; //go to the developer defined frame
648				}
649
650				self.currentFrame = self.canvas.children(".animate-in"); //find which frame is active -- the frame currently being viewed (and about to be animated out)
651				self.nextFrame = self.frames.eq(id-1); //grab the next frame
652				self.currentFrameChildren = self.currentFrame.children();	//save the child elements of the current frame
653				self.nextFrameChildren = self.nextFrame.children(); //save the child elements of the next frame
654
655				if(self.pagination !== undefined) { //if using pagination...
656					self.paginationLinks.removeClass('current'); //remove the 'current' class from all pagination links
657					$(self.paginationLinks[id-1]).addClass('current'); //add the 'current' class to the current frame
658				}
659
660				if(self.transitionsSupported) { //if the browser supports CSS3 transitions...
661					if(self.currentFrame.length !== undefined) { //if there is a current frame (one that is in it's animate-in position)...
662						self.beforeCurrentFrameAnimatesOut(); //callback
663						if(self.settings.moveActiveFrameToTop) { //if the active frame should move to the top...
664							self.currentFrame.css("z-index", 1); //move this frame to the bottom as it is now inactive
665						}
666						resetElements(self.prefix, self.nextFrameChildren, "0s"); //give the next frame elements a transition-duration and transition-delay of 0s so they don't transition to their reset position
667						if(!self.settings.reverseAnimationsWhenNavigatingBackwards || self.direction === 1) { //if user hit next button...
668							self.nextFrame.removeClass("animate-out"); //reset the next frame back to its starting position
669							resetElements(self.prefix, self.currentFrameChildren, "");  //remove any inline styles from the elements to be animated so styles via the "animate-out" class can take full effect
670						}else if(self.settings.reverseAnimationsWhenNavigatingBackwards && self.direction === -1) { //if the user hit prev button
671							self.nextFrame.addClass("animate-out"); //reset the next frame back to its animate-out position
672							reverseTransitionProperties(self); //reverse the transition-duration, transition-delay and transition-timing-function
673						}
674					}else{
675						self.isStartingFrame = false; //no longer the first frame
676					}
677
678					self.active = true; //Sequence is now animating
679					self.currentFrame.unbind(self.transitionEnd); //remove the animation end event
680					self.nextFrame.unbind(self.transitionEnd); //remove the animation end event
681
682					if(self.settings.fadeFrameWhenSkipped && self.settings.navigationSkip) { //if a frame may have faded out when it was previously skipped...
683						self.nextFrame.css("opacity", 1); //show it again
684					}
685
686					self.beforeNextFrameAnimatesIn(); //callback
687					if(self.settings.moveActiveFrameToTop) { //if an active frame should be moved to the top...
688						self.nextFrame.css('z-index', self.numberOfFrames);
689					}
690
691					//modifications to the current and next frame's elements to get them ready to animate
692					if(!self.settings.reverseAnimationsWhenNavigatingBackwards || self.direction === 1) { //if user hit next button...
693						setTimeout(function() { //50ms timeout to give the browser a chance to modify the DOM sequentially
694							resetElements(self.prefix, self.nextFrameChildren, ""); //remove any inline styles from the elements to be animated so styles via the "animate-in" class can take full effect
695							waitForAnimationsToComplete(self, self.nextFrame, self.nextFrameChildren, "in"); //wait for the next frame to animate in
696							if(self.afterCurrentFrameAnimatesOut !== "function () {}" || (self.settings.transitionThreshold === true && ignoreTransitionThreshold !== true)) { //if the afterCurrentFrameAnimatesOut is being used...
697								waitForAnimationsToComplete(self, self.currentFrame, self.currentFrameChildren, "out", true, 1); //wait for the current frame to animate out as well
698							}
699						}, 50);
700
701						//final class changes to make animations happen
702						setTimeout(function() { //50ms timeout to give the browser a chance to modify the DOM sequentially
703							if(self.settings.transitionThreshold === false || self.settings.transitionThreshold === 0 || ignoreTransitionThreshold === true) { //if not using a transitionThreshold...
704								self.currentFrame.toggleClass("animate-out animate-in"); //remove the "animate-in" class and add the "animate-out" class to the current frame
705								self.nextFrame.addClass("animate-in");
705 //add the "animate-in" class
706							}else { //if using a transitionThreshold...
707								self.currentFrame.toggleClass("animate-out animate-in"); //remove the "animate-in" class and add the "animate-out" class to the current frame
708								if(self.settings.transitionThreshold !== true) { //if there's no transitionThreshold or the dev specified a transitionThreshold in milliseconds
709									self.transitionThresholdTimer = setTimeout(function() { //cause the next frame to animate in after a certain period
710										self.nextFrame.addClass("animate-in"); //add the "animate-in" class
711									}, transitionThreshold);
712								}
713							}
714						}, 50);
715					}else if(self.settings.reverseAnimationsWhenNavigatingBackwards && self.direction === -1) { //if the user hit prev button
716						setTimeout(function() { //50ms timeout to give the browser a chance to modify the DOM sequentially
717							//remove any inline styles from the elements so styles via the "animate-in" and "animate-out" class can take full effect
718							resetElements(self.prefix, self.currentFrameChildren, "");
719							resetElements(self.prefix, self.nextFrameChildren, "");
720							reverseTransitionProperties(self); //reverse the transition-duration, transition-delay and transition-timing-function
721
722							waitForAnimationsToComplete(self, self.nextFrame, self.nextFrameChildren, "in"); //wait for the next frame to animate in
723							if(self.afterCurrentFrameAnimatesOut !== "function () {}" || (self.settings.transitionThreshold === true && ignoreTransitionThreshold !== true)) { //if the afterCurrentFrameAnimatesOut is being used...
724								waitForAnimationsToComplete(self, self.currentFrame, self.currentFrameChildren, "out", true, -1); //wait for the current frame to animate out as well
725							}
726						}, 50);
727
728						//final class changes to make animations happen
729						setTimeout(function() { //50ms timeout to give the browser a chance to modify the DOM sequentially
730							if(self.settings.transitionThreshold === false || self.settings.transitionThreshold === 0 || ignoreTransitionThreshold === true) { //if not using a transitionThreshold...
731								self.currentFrame.removeClass("animate-in"); //remove the "animate-in" class from the current frame
732								self.nextFrame.toggleClass("animate-out animate-in"); //add the "animate-out" class and remove the "animate-in" class from the next frame
733							}else{ //if using a transitionThreshold...
734								self.currentFrame.removeClass("animate-in");
735								if(self.settings.transitionThreshold !== true) { //if there's no transitionThreshold or the dev specified a transitionThreshold in milliseconds
736									self.transitionThresholdTimer = setTimeout(function() { //cause the next frame to animate in after a certain period
737										self.nextFrame.toggleClass("animate-out animate-in"); //add the "animate-in" class and remove the "animate-out" class
738									}, transitionThreshold);
739								}
740							}
741						}, 50);
742					}
743				}else{ //if the browser doesn't support CSS3 transitions...
744					function animationComplete() {
745						setHashTag(self);
746						self.active = false;
747						resetAutoPlay(self, true, self.settings.autoPlayDelay);
748					}
749
750					switch(self.settings.fallback.theme) {
751						case "fade": //if using the fade fallback theme...
752							self.frames.css({"position": "relative"}); //this allows for fadein/out in IE
753							self.beforeCurrentFrameAnimatesOut();
754							self.currentFrame = self.frames.eq(self.currentFrameID-1);
755							self.currentFrame.animate({"opacity": 0}, self.settings.fallback.speed, function() { //hide the current frame
756								self.currentFrame.css({"display": "none", "z-index": "1"});
757								self.afterCurrentFrameAnimatesOut();
758								self.beforeNextFrameAnimatesIn();
759								self.nextFrame.css({"display": "block", "z-index": self.numberOfFrames}).animate({"opacity": 1}, 500, function() {
760									self.afterNextFrameAnimatesIn();
761								}); //make the next frame the current one and show it
762								animationComplete();
763							});
764
765							self.frames.css({"position": "relative"}); //this allows for fadein/out in IE
766						break;
767
768						case "slide": //if using the slide fallback theme...
769						default:
770							//create objects which will save the .css() and .animation() objects
771							var animateOut = {};
772							var animateIn = {};
773							var moveIn = {};
774
775							//construct the .css() and .animation() objects
776							if(self.direction === 1) {
777								animateOut.left = "-100%";
778								animateIn.left = "100%";
779							}else{
780								animateOut.left = "100%";
781								animateIn.left = "-100%";
782							}
783
784							moveIn.left = "0";
785							moveIn.opacity = 1;
786
787							self.currentFrame = self.frames.eq(self.currentFrameID-1);
788							self.beforeCurrentFrameAnimatesOut();
789							self.currentFrame.animate(animateOut, self.settings.fallback.speed, function() {
790								self.currentFrame.css({"display": "none", "z-index": "1"});
791								self.afterCurrentFrameAnimatesOut();
792							}); //cause the current frame to animate out
793							self.beforeNextFrameAnimatesIn(); //callback
794							self.nextFrame.show().css(animateIn);
795							self.nextFrame.css({"display": "block", "z-index": self.numberOfFrames}).animate(moveIn, self.settings.fallback.speed, function() { //cause the next frame to animate in
796								animationComplete();
797								self.afterNextFrameAnimatesIn(); //callback
798							});
799						break;
800					}
801				}
802				self.currentFrameID = id; //make the currentFrameID the same as the one that is to animate in
803			}
804		},
805
806		/* 
807			removes Sequence from the element it's attached to
808
809			callback: a callback to run once .destroy() has finished (or see the sequence.destroyed() callback)
810		*/
811		destroy: function(callback) {
812			var self = this;
813
814			self.container.addClass('sequence-destroyed');
814 //add a class of "destroyed" in case the developer wants to animate opacity etc
815
816			//REMOVE EVENTS
817			if(self.nextButton !== undefined) { //remove the next button click event if a next button is defined
818				self.nextButton.unbind('click.sequence');
819			}
820			if(self.prevButton !== undefined) { //remove the previous button click event if a previous button is defined
821				self.prevButton.unbind('click.sequence');
822			}
823			if(self.pauseButton !== undefined) { //remove the pause button click event if a pause button is defined
824				self.pauseButton.unbind('click.sequence');
825			}
826
827			if(self.pagination !== undefined) {
828				self.paginationLinks.unbind('click.sequence');
829			}
830
831			$(document).unbind('keydown.sequence'); //unbind key events
832			self.canvas.unbind('mouseenter.sequence, mouseleave.sequence, touchstart.sequence, touchmove.sequence'); //unbind mouse and touch events
833			$(window).unbind('hashchange.sequence'); //unbind hashchange
834
835			//CLEAR TIMERS
836			self.stopAutoPlay();
837			clearTimeout(self.transitionThresholdTimer);
838
839			//TIDY UP THE DOM
840			self.canvas.children('li').remove(); //because Sequence rearranges frames so the active one is always on top, remove them all...
841			self.canvas.prepend(self.frames); //then add them back in, in their original order
842			self.frames.removeClass('animate-in animate-out').removeAttr('style'); //remove classes and inline styles from all frames
843			self.frames.eq(self.currentFrameID-1).addClass('animate-in'); //keep the current frame in it's animate-in position
844
845			//HIDE UI ELEMENTS
846			if(self.nextButton !== undefined && self.nextButton !== false) { //if a next button is defined and was shown on initiation, hide it
847				self.nextButton.hide();
848			}
849			if(self.prevButton !== undefined && self.prevButton !== false) { //if a prev button is defined and was shown on initiation, hide it
850				self.prevButton.hide();
851			}
852			if(self.pauseButton !== undefined && self.pauseButton !== false) { //if a pause button is defined and was shown on initiation, hide it
853				self.pauseButton.hide();
854			}
855			if(self.pauseIcon !== undefined && self.pauseIcon !== false) { //if a pause icon is defined, hide it
856				self.pauseIcon.hide();
857			}
858			if(self.pagination !== undefined && self.pagination !== false) { //if pagination is defined and was shown on initiation, hide it
859				self.pagination.hide();
860			}
861
862			//CALLBACKS - a callback can either be passed into the destroy() function or by using the sequence.destroyed() publc method
863			if(callback !== undefined) {
864				callback(); //callback past into the function
865			}
866
867			self.destroyed(); //callback
868			self.container.removeData(); //remove data
869		}
870		//END PUBLIC METHODS
871	}; //END PROTOTYPE
872
873	//PRIVATE METHODS
874
875	//trigger keyEvents, customKeyEvents and swipeEvents
876	var initCustomKeyEvent = function(sequence, event) {
877		switch(event) {
878			case "next":
879			sequence.next();
880			break;
881			case "prev":
882			sequence.prev();
883			break;
884			case "pause":
885			sequence.pause(true);
886			break;
887		}
888	};
889
890	/*
891	reset the transition-duration and transition-delay properties of an element
892	
893	elementToReset = the element that is to have it's properties reset
894	cssValue = the value to be given to the transition-duration and transition-delay properties
895	*/
896	var resetElements = function(prefix, elementToReset, cssValue) {
897		elementToReset.css(
898			prefixCSS(prefix, {
899				"transition-duration": cssValue,
900				"transition-delay": cssValue,
901				"transition-timing-function": ""
902			})
903			);
904	};
905
906	/*
907	when navigating backwards and reverseAnimationsWhenNavigatingBackwards is true, take the transition properties for forward animation and manipulate the animated elements to create a perfect reversal
908	*/
909	var reverseTransitionProperties = function(sequence) {
910		var currentFrameChildrenDurations = []; //saves the duration for each of the current frame's element
911		var nextFrameChildrenDurations = []; //saves the duration for each of the next frame's element
912
913		sequence.currentFrameChildren.each(function() { //get the overall duration (including delay) for each animated element in the current frame
914			currentFrameChildrenDurations.push(parseFloat($(this).css(sequence.prefix+'transition-duration').replace('s', '')) + parseFloat($(this).css(sequence.prefix+'transition-delay').replace('s', '')));
915		});
916
917		sequence.nextFrameChildren.each(function() { //get the overall duration (including delay) for each animated element in the current frame
918			nextFrameChildrenDurations.push(parseFloat($(this).css(sequence.prefix+'transition-duration').replace('s', '')) + parseFloat($(this).css(sequence.prefix+'transition-delay').replace('s', '')));
919		});
920
921		var maximumCurrentFrameDuration = Math.max.apply(Math, currentFrameChildrenDurations); //find which transition duration is the longest
922		var maximumNextFrameDuration = Math.max.apply(Math, nextFrameChildrenDurations); //find which transition duration is the longest
923		var transitionDifference = maximumCurrentFrameDuration - maximumNextFrameDuration; //get the overal transition difference between the current and next frame
924		var currentDelay = 0;
925		var nextDelay = 0;
926
927		if(transitionDifference < 0 && !sequence.settings.preventDelayWhenReversingAnimations) { //if the current frame has a greater duration than the next frame...
928			/* note: because the current frame will take longer to animate out than the next to animate in, when this animation is reversed, the current frame will have a delay applied before it animates out. By default, Sequence will aim to avoid this (via the preventDelayWhenReversingAnimations option) because a delay on the current frame may confuse the user. The delay is removed, which means the reversal of animation is slightly out of sync */
929			currentDelay = Math.abs(transitionDifference);
930		}else if(transitionDifference > 0) { //if the next frame has a greater duration than the current frame, add the difference on as a delay
931			nextDelay = Math.abs(transitionDifference);
932		}
933
934		var reverseEachProperty = function(transitionProperties, currentFrameChildren, maximumFrameDuration, frameDelay) {
935			currentFrameChildren.each(function() {
936				var duration = parseFloat($(this).css(sequence.prefix+'transition-duration').replace('s', '')); //get the elements transition-duration
937				var delay = parseFloat($(this).css(sequence.prefix+'transition-delay').replace('s', '')); //get the elements transition-delay
938				var transitionFunction = $(this).css(sequence.prefix+'transition-timing-function'); //get the elements transiion-timing-function
939				if(transitionFunction.indexOf("cubic-bezier") >= 0) { //if the transition is a cubic-bezier...
940					var cubicBezier = transitionFunction.replace('cubic-bezier(', '').replace(')', '').split(','); //remove the CSS function and just get the array
941					$.each(cubicBezier, function(index, value) { //for each point that makes up the cubic bezier...
942						cubicBezier[index] = parseFloat(value); //turn the point into a number (rather than text)
943					});
944
945					//reverse the cubic bezier
946					var reversedCubicBezier = [
947					1 - cubicBezier[2],
948					1 - cubicBezier[3],
949					1 - cubicBezier[0],
950					1 - cubicBezier[1]
951					];
952					transitionFunction = 'cubic-bezier('+reversedCubicBezier+')'; //add the reversed cubic bezier back into a CSS function
953				}else{ //if the function isn't a cubic-bezier (WebKit returns "linear" as a text string rather than a cubic-bezier)
954					transitionFunction = 'linear'; //use a linear transition function
955				}
956				var frameDuration = duration + delay; //get the overall duration of the element
957
958				transitionProperties["transition-duration"] = duration + 's'; //reapply the element's transition-duration (to override any inline styles)
959				transitionProperties["transition-delay"] = (maximumFrameDuration - frameDuration + frameDelay) + 's'; //add a delay if required
960				transitionProperties["transition-timing-function"] = transitionFunction; //reapply the reversed transition function
961				$(this).css(
962					prefixCSS(sequence.prefix, transitionProperties) //set the new transition properties
963					);
964			});
965		};
966
967		reverseEachProperty(sequence.transitionProperties, sequence.currentFrameChildren, maximumCurrentFrameDuration, currentDelay); //reverse properties for each of the current frame's elements
968		reverseEachProperty(sequence.transitionProperties, sequence.nextFrameChildren, maximumNextFrameDuration, nextDelay); //reverse properties for each of the next frame's elements
969	};
970
971	/*
972	adds the browser vendors prefix onto multiple CSS properties
973	
974	prefix = the prefix for the browser Sequence is being viewed in (-webkit- for example)
975	properties = the properties to be prefixed (transition-duration for example)
976	*/
977	var prefixCSS = function(prefix, properties) {
978		var css = {};
979		for(var property in properties) { //for each property to be modified...
980			css[prefix + property] = properties[property]; //add the prefix to the property name
981		}
982		return css; //return the prefixed CSS
983	};
984
985	/*
986	internal function used to start and stop autoPlay
987	start: if true, autoPlay will be started, else it'll be stopped
988	delay: a time in ms before starting the autoPlay feature (if unspecified, the default will be used)
989	*/
990	var resetAutoPlay = function(sequence, start, delay) {
991		if(start === true) { //if starting autoPlay
992			if(sequence.settings.autoPlay && !sequence.isSoftPaused) { //if using autoPlay and Sequence isn't paused...
993				clearTimeout(sequence.autoPlayTimer); //stop the autoPlay timer
994				sequence.autoPlayTimer = setTimeout(function() { //start a new autoPlay timer and...
995					if(sequence.settings.autoPlayDirection === 1) { //go to either the next or previous frame
996						sequence.next();
997					}else{
998						sequence.prev();
999					}
1000				}, delay); //after a specified delay
1001			}
1002		}else{ //if stopping autoPlay
1003			clearTimeout(sequence.autoPlayTimer); //stop the autoPlay timer
1004		}
1005	};
1006
1007	/*functionality to initiate the preloader, next/previous buttons and so on
1008	
1009	devOption: true = the developer wants to use the default selector. false = don't use a uiElement. string = the developer defined selector to use for the UI element
1010	defaultOption: the default selector to use for the UI element, when the developer specifies false for devOption
1011	*/
1012	var renderUiElements = function(sequence, devOption, defaultOption) {
1013		switch(devOption) {
1014			case false: //don't set up a uiElement
1015			return undefined;
1016
1017			case true: //use the default uiElement
1018				if(defaultOption === ".sequence-preloader") { //if setting up the preloader...
1019					get.defaultPreloader(sequence.container, sequence.transitionsSupported, sequence.prefix); //get the default preloader
1020				}
1021				return $(defaultOption); //return the default element
1022
1023			default: //if using a developer defined selector...
1024				return $(devOption); //return the developer defined element
1025		}
1026	};
1027
1028	/*
1029	prevents the next frame from animating until the current frame has finished animating
1030
1031	frame: the frame <li> which is animating
1032	self.currentFrameChildren: the animated direct child elements of the frame
1033	transitionPhase: whether the elements are animating "in" to an active position or "out" of an active position
1034	inAfterwards: whether the next frame should animate in afterwards
1035	direction: the direction of animation
1036	*/
1037	var waitForAnimationsToComplete = function(sequence, frame, currentFrameChildren, transitionPhase, inAfterwards, direction) {
1038
1039		if(transitionPhase === "out") { //if waiting on a frame's element to animate out...
1040			var onceComplete = function() {
1041				sequence.afterCurrentFrameAnimatesOut(); //callback
1042
1043				if(sequence.settings.transitionThreshold === true) {
1044					if(direction === 1) {
1045						sequence.nextFrame.addClass("animate-in");
1045 //add the "animate-in" class
1046					}else if(direction === -1) {
1047						sequence.nextFrame.toggleClass("animate-out animate-in");
1048					}
1049				}
1050			};
1051		}else if(transitionPhase === "in") { //if waiting on a frame's element to animate in...
1052			var onceComplete = function() {
1053				sequence.afterNextFrameAnimatesIn(); //callback
1054				setHashTag(sequence); //set the hashtag to represent the newly active frame
1055
1056				sequence.active = false; //Sequence is not animating
1057
1058				if(!sequence.isHardPaused && !sequence.isBeingHoveredOver) { //if Sequence isn't hard paused (via a pause button for example) or being hovered over...
1059					if(!sequence.delayUnpause) { //if unpausing isn't delayed (Sequence wasn't animating when unpause was invoked)...
1060						sequence.unpause(false); //unpause Sequence but don't run the unpause callback
1061					}else{ //if unpausing was delay because Sequence was animating when unpause was invoked...
1062						sequence.delayUnpause = false;
1063						sequence.unpause(); //unpause Sequence
1064					}
1065				}
1066			};
1067		}
1068
1069		currentFrameChildren.data('animationEnded', false); // set the data attribute of each animated element to indicate that the animation has not yet ended
1070		frame.bind(sequence.transitionEnd, function(e) { //when an element finishes animating...
1071			$(e.target).data('animationEnded', true); // set the data attrbiute to indicate that the element has finished it's animation
1072
1073			// now check if all elements have finished animating
1074			var allAnimationsEnded = true;
1075			currentFrameChildren.each(function() { //for each element being animated within a frame...
1076				if($(this).data('animationEnded') === false) { //if the animation hasn't ended...
1077					allAnimationsEnded = false; //not all animations have ended yet
1078					return false; //break out of the animationEnded check early
1079				}
1080			});
1081
1082			if(allAnimationsEnded) { //if all animations have ended...
1083				frame.unbind(sequence.transitionEnd); //stop waiting for animations to end
1084				onceComplete();
1085			}
1086		});
1087	};
1088
1089	var setHashTag = function(sequence) {
1090		if(sequence.settings.hashTags) { //if hashTags is enabled...
1091			sequence.currentHashTag = sequence.nextFrame.prop(sequence.getHashTagFrom); //get the hashtag name
1092			sequence.frameHashIndex = $.inArray(sequence.currentHashTag, sequence.frameHashID); //get the index of the frame that matches the hashtag
1093			if(sequence.frameHashIndex !== -1 && (sequence.settings.hashChangesOnFirstFrame || (!sequence.isStartingFrame || !sequence.transitionsSupported))) { //if the hashtag matches a Sequence frame ID...
1094				sequence.nextFrameID = sequence.frameHashIndex + 1;
1095				document.location.hash = "#"+sequence.currentHashTag;
1096			}else{
1097				sequence.nextFrameID = sequence.settings.startingFrameID;
1098				sequence.isStartingFrame = false;
1099			}
1100		}
1101	};
1102
1103	var get = {
1104		/* Modernizr 2.6.1 (Custom Build) | MIT & BSD
1105		 * Build: http://modernizr.com/download/#-svg-prefixed-testprop-testallprops-domprefixes
1106		 */
1107		modernizr: function() {
1108			;window.Modernizr=function(a,b,c){function x(a){i.cssText=a}function y(a,b){return x(prefixes.join(a+";")+(b||""))}function z(a,b){return typeof a===b}function A(a,b){return!!~(""+a).indexOf(b)}function B(a,b){for(var d in a){var e=a[d];if(!A(e,"-")&&i[e]!==c)return b=="pfx"?e:!0}return!1}function C(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:z(f,"function")?f.bind(d||b):f}return!1}function D(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+m.join(d+" ")+d).split(" ");return z(b,"string")||z(b,"undefined")?B(e,b):(e=(a+" "+n.join(d+" ")+d).split(" "),C(e,b,c))}var d="2.6.1",e={},f=b.documentElement,g="modernizr",h=b.createElement(g),i=h.style,j,k={}.toString,l="Webkit Moz O ms",m=l.split(" "),n=l.toLowerCase().split(" "),o={svg:"http://www.w3.org/2000/svg"},p={},q={},r={},s=[],t=s.slice,u,v={}.hasOwnProperty,w;!z(v,"undefined")&&!z(v.call,"undefined")?w=function(a,b){return v.call(a,b)}:w=function(a,b){return b in a&&z(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=self;if(typeof c!="function")throw new TypeError;
1108var d=t.call(arguments,1),e=function(){if(self instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(t.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(t.call(arguments)))};return e}),p.svg=function(){return!!b.createElementNS&&!!b.createElementNS(o.svg,"svg").createSVGRect};for(var E in p)w(p,E)&&(u=E.toLowerCase(),e[u]=p[E](),s.push((e[u]?"":"no-")+u));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)w(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,enableClasses&&(f.className+=" "+(b?"":"no-")+a),e[a]=b}return e},x(""),h=j=null,e._version=d,e._domPrefixes=n,e._cssomPrefixes=m,e.testProp=function(a){return B([a])},e.testAllProps=D,e.prefixed=function(a,b,c){return b?D(a,b,c):D(a,"pfx")},e}(self,self.document);
1109		},
1110
1111		defaultPreloader: function(prependTo, transitions, prefix) {
1112			var icon = '<div class="sequence-preloader"><svg class="preloading" xmlns="http://www.w3.org/2000/svg"><circle class="circle" cx="6" cy="6" r="6" /><circle class="circle" cx="22" cy="6" r="6" /><circle class="circle" cx="38" cy="6" r="6" /></svg></div>';
1113
1114			$("head").append("<style>.sequence-preloader{height: 100%;position: absolute;width: 100%;z-index: 999999;}@"+prefix+"keyframes preload{0%{opacity: 1;}50%{opacity: 0;}100%{opacity: 1;}}.sequence-preloader .preloading .circle{fill: #ff9442;display: inline-block;height: 12px;position: relative;top: -50%;width: 12px;"+prefix+"animation: preload 1s infinite; animation: preload 1s infinite;}.preloading{display:block;height: 12px;margin: 0 auto;top: 50%;margin-top:-6px;position: relative;width: 48px;}.sequence-preloader .preloading .circle:nth-child(2){"+prefix+"animation-delay: .15s; animation-delay: .15s;}.sequence-preloader .preloading .circle:nth-child(3){"+prefix+"animation-delay: .3s; animation-delay: .3s;}.preloading-complete{opacity: 0;visibility: hidden;"+prefix+"transition-duration: 1s; transition-duration: 1s;}div.inline{background-color: #ff9442; margin-right: 4px; float: left;}</style>");
1115			prependTo.prepend(icon);
1116			if(!Modernizr.svg && !transitions) { //if SVG isn't supported, remain calm and add this fallback instead...
1117				$(".sequence-preloader").prepend('<div class="preloading"><div class="circle inline"></div><div class="circle inline"></div><div class="circle inline"></div></div>');
1118				setInterval(function() {
1119					$(".sequence-preloader .circle").fadeToggle(500);
1120				}, 500);
1121			}else if(!transitions) { //if transitions aren't supported, toggle the opacity instead
1122				setInterval(function() {
1123					$(".sequence-preloader").fadeToggle(500);
1124				}, 500);
1125			}
1126		},
1127
1128		//a quick test to work out if Opera supports transitions properly (to work around the fact that Opera 11 supports transitions but doesn't return a transition value properly)
1129		operaTest: function() {
1130			$("body").append('<span id="sequence-opera-test"></span>');
1131			var $operaTest = $("#sequence-opera-test");
1132			$operaTest.css("-o-transition", "1s");
1133			//if the expected value isn't returned...
1134			if($operaTest.css("-o-transition") !== "1s") {
1135				//cause Opera to go into the fallback theme
1136				return false;
1137			}else{
1138				return true;
1139			}
1140			$operaTest.remove();
1141		}
1142	};
1143	//END PRIVATE METHODS
1144
1145	//PRIVATE VARIABLES
1146
1147	var defaults = {
1148		//General Settings
1149		startingFrameID: 1, //The frame (the list item `<li>`) that should first be displayed when Sequence loads
1150		cycle: true, //Whether Sequence should navigate to the first frame after the last frame and vice versa
1151		animateStartingFrameIn: false, //Whether the first frame should animate in to its active position
1152		transitionThreshold: false, //The delay between a frame animating out and the next animating in (false = no delay, true = the next frame will animate in only once the current frame has animated out)
1153		reverseAnimationsWhenNavigatingBackwards: true, //Whether animations should be reversed when a user navigates backwards by clicking a previous button/swiping/pressing the left key
1154		preventDelayWhenReversingAnimations: false, //Whether a delay should be removed when animations are reversed. This delay is removed by default to prevent user confusion
1155		moveActiveFrameToTop: true, //Whether a frame should be given a higher `z-index` than other frames whilst it is active, to bring it above the others
1156
1157		//Autoplay Settings
1158		autoPlay: false, //Cause Sequence to automatically change between frames over a period of time, as defined in autoPlayDelay
1159		autoPlayDirection: 1, //The direction in which Sequence should auto play
1160		autoPlayDelay: 5000, //The duration in milliseconds at which frames should remain on screen before animating to the next
1161
1162		//Frame Skipping Settings
1163		navigationSkip: true, //Whether the user can navigate through frames before each frame has finished animating
1164		navigationSkipThreshold: 250, //Amount of time that must pass before the next frame can be navigated to
1165		fadeFrameWhenSkipped: true, //If a frame is skipped before it finishes animating, it will quickly fade out
1166		fadeFrameTime: 150, //If fadeFrameWhenSkipped is true, how quickly a frame should fade out when skipped (in milliseconds)
1167		preventReverseSkipping: false, //Whether the user can change the direction of navigation during frames animating (if navigating forward, the user can only skip forwards when other frames are animating).
1168
1169		//Next/Prev Button Settings
1170		nextButton: false, //if true, Sequence will use an element with class ".sequence-next" as the next button, else specify your own selector. false = don't use an in-built next button
1171		showNextButtonOnInit: true, //if true, Sequence will make the next button display: block; once Sequence has loaded (give the next button selector display: none; in the CSS to hide it until its usable)
1172		prevButton: false, //if true, Sequence will use an element with class ".sequence-prev" as the previous button, else specify your own selector. false = don't use an in-built previous button
1173		showPrevButtonOnInit: true, //if true, Sequence will make the previous button display: block; once Sequence has loaded (give the previous button selector display: none; in the CSS to hide it until its usable)
1174
1175		//Pause Settings
1176		pauseButton: false, //if true, Sequence will use an element with class ".sequence-pause" as the pause button, else specify your own selector. false = don't use an in-built pause button
1177		unpauseDelay: null, //the time to wait before navigating to the next frame when Sequence is unpaused. Note that if an unpauseDelay is not specified, the default is the same as the autoPlayDelay setting
1178		pauseOnHover: true, //pause Sequence when the Sequence container is hovered over
1179		pauseIcon: false, 	//if true, Sequence will use an element with class ".sequence-pause-icon" as the pause icon, else specify your own selector. false = don't use an in-built pause icon (the pause icon will display when Sequence is paused)
1180		showPauseButtonOnInit: true, //if true, Sequence will make the pause button display: block; once Sequence has loaded (give the pause button selector display: none; in the CSS to hide it until its usable)
1181
1182		//Pagination Settings
1183		pagination: false, //if true, Sequence will use an element with class ".sequence-pagination" as the paginated navigation, else specify your own selector. false = don't use in-built pagination
1184		showPaginationOnInit: true,  //if true, Sequence will make the pagination display: block; once Sequence has loaded (give the pagination selector display: none; in the CSS to hide it until its usable)
1185
1186		//Preloader Settings
1187		preloader: false,
1188		preloadTheseFrames: [1], //all images in these frames will load before Sequence initiates
1189		preloadTheseImages: [ //specify particular images to load before Sequence initiates
1190			/* Example usage
1191			"images/catEatingSalad.jpg",
1192			"images/meDressedAsBatman.png"
1193			*/
1194		],
1195		/*Note: You can use preloadTheseFrames and preloadTheseImages together. You might want to load all images in frame 1 and just one big image from frame 2 for example*/
1196		hideFramesUntilPreloaded: true,
1197		prependPreloadingComplete: true,
1198		hidePreloaderUsingCSS: true,
1199		hidePreloaderDelay: 0,
1200
1201		//Keyboard settings
1202		keyNavigation: true, //false prevents the following keyboard settings
1203		numericKeysGoToFrames: true,
1204		keyEvents: {
1205			left: "prev",
1206			right: "next"
1207		},
1208		customKeyEvents: {
1209			/* Example usage
1210			65: "prev",	//a
1211			68: "next",	//d
1212			83: "prev",	//s
1213			87: "next"	//w
1214			*/
1215		},
1216
1217		//Touch Swipe Settings
1218		swipeNavigation: true,
1219		swipeThreshold: 20,
1220		swipePreventsDefault: false, //be careful if setting this to true
1221		swipeEvents: {
1222			left: "prev",
1223			right: "next",
1224			up: false,
1225			down: false
1226		},
1227
1228		//hashTags Settings
1229		//when using hashTags, please include a reference to Ben Alman's jQuery HashChange plugin above your reference to Sequence.js
1230
1231		//info: http://benalman.com/projects/jquery-hashchange-plugin/
1232		//plugin: https://raw.github.com/cowboy/jquery-hashchange/v1.3/jquery.ba-hashchange.min.js
1233		//GitHub: https://github.com/cowboy/jquery-hashchange
1234		hashTags: false, //when a frame is navigated to, change the hashtag to the frames ID
1235		hashDataAttribute: false, //false = the hashTag is taken from a frames ID attribute | true = the hashTag is taken from the data attribute "data-sequence-hash"
1236		hashChangesOnFirstFrame: false, //false = the hashTag won't change for the first frame but will for those after
1237
1238		//Fallback Theme Settings (For browsers that don't support CSS3 transitions)
1239		fallback: {
1240			theme: "slide",
1241			speed: 500
1242		}
1243	};
1244	//END PRIVATE VARIABLES
1245
1246	$.fn.sequence = function(options) {
1247		return this.each(function() {
1248			if (!$.data(this, 'sequence')) { //prevent multiple initiations on the same element
1249				$.data(this, 'sequence', new Sequence($(this), options, defaults, get));
1250      }
1251		});
1252	};
1253})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.