test/emission_fichiers/jquery_003.js
author hamidouk
Mon, 19 Dec 2011 15:25:22 +0100
branchpopcorn-port
changeset 481 a46cfeee6d77
parent 0 c357d5b60635
permissions -rw-r--r--
using jquery ui draggable changes the state of an element from absolute to relative positioning, which breaks the way our seek button expands itself, so we need to force absolute positioning, quite uglily, using jquery.

/**
 * jquery.scrollable 1.0.2. Put your HTML scroll.
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/scrollable.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : March 2008
 * Version : 1.0.2 - Tue Feb 24 2009 10:52:08 GMT-0000 (GMT+00:00)
 */
(function($) {
		
	function fireEvent(opts, name, self, arg) {
		var fn = opts[name];
		
		if ($.isFunction(fn)) { 
			try {  
				return fn.call(self, arg);
				
			} catch (error) {
				if (opts.alert) {
					alert("Error calling scrollable." + name + ": " + error);
				} else {
					throw error;	
				}
				return false;
			} 					
		}
		return true;			
	}
				
	var current = null;	
	
	
	// constructor
	function Scrollable(root, conf) {   
				
		// current instance
		var self = this;  
		if (!current) { current = self; }		
		
		// horizontal flag
		var horizontal = !conf.vertical;		
		
		
		// wrap (root elements for items)
		var wrap = $(conf.items, root);				
		
		// current index
		var index = 0;
		
		
		// get handle to navigational elements
		var navi = root.siblings(conf.navi).eq(0);
		var prev = root.siblings(conf.prev).eq(0);
		var next = root.siblings(conf.next).eq(0);
		var prevPage = root.siblings(conf.prevPage).eq(0);
		var nextPage = root.siblings(conf.nextPage).eq(0);
		
		
		// methods
		$.extend(self, {
				
			getVersion: function() {
				return [1, 0, 1];	
			},
			
			getIndex: function() {
				return index;	
			},
	
			getConf: function() {
				return conf;	
			},
			
			getSize: function() {
				return self.getItems().size();	
			},
	
			getPageAmount: function() {
				return Math.ceil(this.getSize() / conf.size); 	
			},
			
			getPageIndex: function() {
				return Math.ceil(index / conf.size);	
			},

			getRoot: function() {
				return root;	
			},
			
			getItemWrap: function() {
				return wrap;	
			},
			
			getItems: function() {
				return wrap.children();	
			},
			
			/* all seeking functions depend on this */		
			seekTo: function(i, time, fn) {
				
				// default speed
				time = time || conf.speed;
				
				// function given as second argument
				if ($.isFunction(time)) {
					fn = time;
					time = conf.speed;
				}
								
				if (i < 0) { i = 0; }				
				if (i > self.getSize() - conf.size) { return self; } 				

				var item = self.getItems().eq(i);					
				if (!item.length) { return self; }				
				
				// onBeforeSeek
				if (fireEvent(conf, "onBeforeSeek", self, i) === false) {
					return self;	
				}									
				
				if (horizontal) {					
					var left = -(item.outerWidth(true) * i);					
					wrap.animate({left: left}, time, conf.easing, fn ? function() { fn.call(self); } : null);
					
				} else {
					var top = -(item.outerHeight(true) * i); // wrap.offset().top - item.offset().top;					
					wrap.animate({top: top}, time, conf.easing, fn ? function() { fn.call(self); } : null);							
				}	
				
				
				// navi status update
				if (navi.length) {
					var klass = conf.activeClass;
					var page = Math.ceil(i / conf.size);
					page = Math.min(page, navi.children().length - 1);
					navi.children().removeClass(klass).eq(page).addClass(klass);
				} 
				
				// prev buttons disabled flag
				if (i === 0) {
					prev.add(prevPage).addClass(conf.disabledClass);					
				} else {
					prev.add(prevPage).removeClass(conf.disabledClass);
				}
								
				// next buttons disabled flag
				if (i >= self.getSize() - conf.size) {
					next.add(nextPage).addClass(conf.disabledClass);
				} else {
					next.add(nextPage).removeClass(conf.disabledClass);
				}				
				
				current = self;
				index = i;				
				
				// onSeek after index being updated
				fireEvent(conf, "onSeek", self, i);	
				
				return self;
				
			},			
				
			move: function(offset, time, fn) {
				var to = index + offset;
				if (conf.loop && to > (self.getSize() - conf.size)) {
					to = 0;	
				}
				return this.seekTo(to, time, fn);
			},
			
			next: function(time, fn) {
				return this.move(1, time, fn);	
			},
			
			prev: function(time, fn) {
				return this.move(-1, time, fn);	
			},
			
			movePage: function(offset, time, fn) {
				return this.move(conf.size * offset, time, fn);		
			},
			
			setPage: function(page, time, fn) {
				var size = conf.size;
				var index = size * page;
				var lastPage = index + size >= this.getSize(); 
				if (lastPage) {
					index = this.getSize() - conf.size;
				}
				return this.seekTo(index, time, fn);
			},
			
			prevPage: function(time, fn) {
				return this.setPage(this.getPageIndex() - 1, time, fn);
			},  
	
			nextPage: function(time, fn) {
				return this.setPage(this.getPageIndex() + 1, time, fn);
			}, 
			
			begin: function(time, fn) {
				return this.seekTo(0, time, fn);	
			},
			
			end: function(time, fn) {
				return this.seekTo(this.getSize() - conf.size, time, fn);	
			},
			
			reload: function() {
				return load();	
			},
			
			click: function(index, time, fn) {
				
				var item = self.getItems().eq(index);
				var klass = conf.activeClass;			
				
				if (!item.hasClass(klass) && (index >= 0 || index < this.getSize())) {				
					self.getItems().removeClass(klass);
					item.addClass(klass);
					var delta = Math.floor(conf.size / 2);
					var to = index - delta;

					// next to last item must work
					if (to > self.getSize() - conf.size) { to--;	}
					
					if (to !== index) {
						return this.seekTo(to, time, fn);		
					}				 
				}
				
				return self;
			}			
			
		});
	
		
		// mousewheel
		if ($.isFunction($.fn.mousewheel)) { 
			root.bind("mousewheel.scrollable", function(e, delta)  {
				// opera goes to opposite direction
				var step = $.browser.opera ? 1 : -1;
				
				self.move(delta > 0 ? step : -step, 50);
				return false;
			});
		}  
		
		// prev button		
		prev.addClass(conf.disabledClass).click(function() { 
			self.prev(); 
		});
		

		// next button
		next.click(function() { 
			self.next(); 
		});
		
		// prev page button
		nextPage.click(function() { 
			self.nextPage(); 
		});
		

		// next page button
		prevPage.addClass(conf.disabledClass).click(function() { 
			self.prevPage(); 
		});		

		
		// keyboard
		if (conf.keyboard) {
			
			// unfortunately window.keypress does not work on IE.
			$(window).unbind("keypress.scrollable").bind("keypress.scrollable", function(evt) {
				
				var el = current;	
				if (!el) { return; }
					
				if (horizontal && (evt.keyCode == 37 || evt.keyCode == 39)) {					
					el.move(evt.keyCode == 37 ? -1 : 1);
					return evt.preventDefault();
				}	
				
				if (!horizontal && (evt.keyCode == 38 || evt.keyCode == 40)) {
					el.move(evt.keyCode == 38 ? -1 : 1);
					return evt.preventDefault();
				}
				
				return true;
				
			});	 
		}

		// navi 			
		function load() {			
			
			navi.each(function() {
				
				var nav = $(this);
				
				// generate new entries
				if (nav.is(":empty") || nav.data("me") == self) {
					
					nav.empty();
					nav.data("me", self);
					
					for (var i = 0; i < self.getPageAmount(); i++) {		
						
						var item = $("<" + conf.naviItem + "/>").attr("href", i).click(function(e) {							
							var el = $(this);
							el.parent().children().removeClass(conf.activeClass);
							el.addClass(conf.activeClass);
							self.setPage(el.attr("href"));
							return e.preventDefault();
						});
						
						if (i === 0) { item.addClass(conf.activeClass); }
						nav.append(item);					
					}
					
				// assign onClick events to existing entries
				} else {
					
					// find a entries first -> syntaxically correct
					var els = nav.children(); 
					
					els.each(function(i)  {
						var item = $(this);
						item.attr("href", i);
						if (i === 0) { item.addClass(conf.activeClass); }
						
						item.click(function() {
							nav.find("." + conf.activeClass).removeClass(conf.activeClass);
							item.addClass(conf.activeClass);
							self.setPage(item.attr("href"));
						});
						
					});
				}
				
			});
			
			
			// item.click()
			if (conf.clickable) {
				self.getItems().each(function(index, arg) {
					var el = $(this);
					if (!el.data("set")) {
						el.bind("click.scrollable", function() {
							self.click(index);		
						});
						el.data("set", true);
					}
				});				
			}
			
			
			// hover
			if (conf.hoverClass) {
				self.getItems().hover(function()  {
					$(this).addClass(conf.hoverClass);		
				}, function() {
					$(this).removeClass(conf.hoverClass);	
				});
			}			
			
			return self;
		}
		
		load();
		
		
		// interval stuff
		var timer = null;

		function setTimer() {
			timer = setInterval(function()  {
				self.next();
				
			}, conf.interval);	
		}	
		
		if (conf.interval > 0) {			
			
			root.hover(function() {			
				clearInterval(timer);		
			}, function() {		
				setTimer();	
			});
			
			setTimer();	
		}
		
	} 

		
	// jQuery plugin implementation
	jQuery.prototype.scrollable = function(conf) { 
			
		// already constructed --> return API
		var api = this.eq(typeof conf == 'number' ? conf : 0).data("scrollable");
		if (api) { return api; }		
		
 
		var opts = {
			
			// basics
			size: 5,
			vertical:false,			
			clickable: true,
			loop: false,
			interval: 0,			
			speed: 400,
			keyboard: true,			
			
			// other
			activeClass:'active',
			disabledClass: 'disabled',
			hoverClass: null,			
			easing: 'swing',
			
			// navigational elements
			items: '.items',
			prev: '.prev',
			next: '.next',
			prevPage: '.prevPage',
			nextPage: '.nextPage',			
			navi: '.navi',
			naviItem: 'a',

			
			// callbacks
			onBeforeSeek: null,
			onSeek: null,
			alert: true
		}; 
		
		
		$.extend(opts, conf);		
		
		this.each(function() {			
			var el = new Scrollable($(this), opts);
			$(this).data("scrollable", el);	
		});
		
		return this; 
		
	};
			
	
})(jQuery);