
/**
 * jquery.scrollable 0.11. Making HTML elements scroll.
 *
 * http://flowplayer.org/tools/scrollable.html
 *
 * Copyright (c) 2008 Tero Piirainen (tero@flowplayer.org)
 *
 * Released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * >> Basically you can do anything you want but leave this header as is <<
 *
 * Since  : 0.01 - 03/01/2008
 * Version: 0.11 - 05/29/2008
 */
(function($) {

	// plugin initialization
	$.fn.extend({
		scrollable: function(arg1, arg2, arg3) {

			return this.each(function() {
				if (typeof arg1 == "string") {
					var el = $.data(this, "scrollable");
					el[arg1].apply(el, [arg2, arg3]);

				} else {
					new $.scrollable(this, arg1, arg2);
				}
			});
		}
	});

	// constructor
	$.scrollable = function(el, opts) {

		// store this instance
		$.data(el, "scrollable", this);

		this.init(el, opts);
	};


	// methods
	$.extend($.scrollable.prototype, {

		init: function(el, config)  {

			// current instance
			var self = this;

			var opts = {
				size: 3,
				horizontal:false,
				activeClass:'active',
				speed: 300,
				onSeek: null,

				// jquery selectors
				items: '.items',
				prev:'.prev',
				next:'.next',
				navi:'.navi',
				naviItem:'span'
			};

			this.opts = $.extend(opts, config);

			// root / itemRoot
			var root = this.root = $(el);
			var itemRoot = $(opts.items, root);
			if (!itemRoot.length) itemRoot = root;

			// wrap itemRoot.children() inside container
			itemRoot.css({position:'relative', overflow:'hidden', visibility:'visible'});
			itemRoot.children().wrapAll('<div class="__scrollable" style="position:absolute"/>');

			this.wrap = itemRoot.children(":first");
			this.wrap.css(opts.horizontal ? "width" : "height", "200000em").after('<br clear="all"/>');
			this.items = this.wrap.children();
			this.index = 0;


			// set height based on size
			if (opts.horizontal) {
				itemRoot.width(opts.size * (this.items.eq(1).offset().left - this.items.eq(0).offset().left) -2);
			} else {
				itemRoot.height(opts.size * (this.items.eq(1).offset().top - this.items.eq(0).offset().top) -2);
			}

			// mousewheel
			if ($.isFunction($.fn.mousewheel)) {
				root.bind("mousewheel.scrollable", function(event, delta)  {
					self.move(-delta, 50);
					return false;
				});
			}

			// keyboard
			$(window).bind("keypress.scrollable", function(evt) {

				if ($(evt.target).parents(".__scrollable").length) {

					if (opts.horizontal && (evt.keyCode == 37 || evt.keyCode == 39)) {
						self.move(evt.keyCode == 37 ? -1 : 1);
						return false;
					}

					if (!opts.horizontal && (evt.keyCode == 38 || evt.keyCode == 40)) {
						self.move(evt.keyCode == 38 ? -1 : 1);
						return false;
					}
				}

				return true;

			});


			// item.click()
			this.items.each(function(index, arg) {
				$(this).bind("click.scrollable", function() {
					self.click(index);
				});
			});

			this.activeIndex = 0;

			// prev
			//$(opts.prev, root).click(function() { self.prev() });
			// next
			//$(opts.next, root).click(function() { self.next() });



			// Мои вмешательства --------------------
			// prev
			/*$(opts.prev, root).mouseover(
				//while ($(opts.prev, root).hover) {
					function() {
						while ($(opts.prev, root).hover) {
							self.prev()
						}
					}
				//}
			);*/
			// prev
			$(opts.prev, root).mouseover(
				function() {
					self.begin(550)
				}
			);
			// next
			$(opts.next, root).mouseover(
				function() {
					self.end(550)
				}
			);
			// --------------------------------------


			/*$(opts.prev, root).mouseover(
				function(){											  			//первый параметр, при наведении мыши на элемент
					var setInt = setInterval( function() { self.prev() } ); 	//запускаем интервал
				},
				function(){ 													//второй параметр, при выходе мыши из пространства элемента
					clearInterval(setInt);										//удаляем интервал, функция анимации больше не вызывается по окончании установленного времени
				}
			);*/




			// navi
			$(opts.navi, root).each(function() {
				var navi = $(this);

				var status = self.getStatus();

				// generate new entries
				if (navi.is(":empty")) {
					for (var i = 0; i < status.pages; i++) {

						var item = $("<" + opts.naviItem + "/>").attr("page", i).click(function() {
							var el = $(this);
							el.parent().children().removeClass(opts.activeClass);
							el.addClass(opts.activeClass);
							self.setPage(el.attr("page"));

						});

						if (i == 0) item.addClass(opts.activeClass);
						navi.append(item);
					}

				// assign onClick events to existing entries
				} else {

					navi.children().each(function(i)  {
						var item = $(this);
						item.attr("page", i);
						if (i == 0) item.addClass(opts.activeClass);

						item.click(function() {
							item.parent().children().removeClass(opts.activeClass);
							item.addClass(opts.activeClass);
							self.setPage(item.attr("page"));
						});

					});
				}

			});

		},


		click: function(index) {

			var item = this.items.eq(index);
			var klass = this.opts.activeClass;

			if (!item.hasClass(klass) && (index >= 0 || index < this.items.size())) {

				var prev = this.items.eq(this.activeIndex).removeClass(klass);
				item.addClass(klass);

				this.seekTo(index - Math.floor(this.opts.size / 2));
				this.activeIndex = index;
			}
		},

		getStatus: function() {
			var len =  this.items.size();
			var s = {
				length: len,
				index: this.index,
				size: this.opts.size,
				pages: Math.floor(len / this.opts.size),
				page: Math.floor(this.index / this.opts.size)
			};

			return s;
		},


		// all other seeking functions depend on this generic seeking function
		seekTo: function(index, time) {

			if (index < 0) index = 0;
			index = Math.min(index, this.items.length - this.opts.size);

			var item = this.items.eq(index);
			if (item.size() == 0) return false;
			this.index = index;


			if (this.opts.horizontal) {
				var left = this.wrap.offset().left - item.offset().left;
				this.wrap.animate({left: left}, time || this.opts.speed);

			} else {
				var top = this.wrap.offset().top - item.offset().top;
				this.wrap.animate({top: top}, time || this.opts.speed);
			}

			// custom onSeek callback
			if ($.isFunction(this.opts.onSeek)) {
				this.opts.onSeek.call(this.getStatus());
			}

			// navi status update
			var navi = $(this.opts.navi, this.root);

			if (navi.length) {
				var klass = this.opts.activeClass;
				var page = Math.round(index / this.opts.size);
				navi.children().removeClass(klass).eq(page).addClass(klass);
			}


			return true;
		},


		move: function(offset, time) {
			this.seekTo(this.index + offset, time);
		},

		next: function(time) {
			this.move(1, time);
		},

		prev: function(time) {
			this.move(-1, time);
		},

		movePage: function(offset, time) {
			this.move(this.opts.size * offset, time);
		},

		setPage: function(index, time) {
			this.seekTo(this.opts.size * index, time);
		},

		prevPage: function(time) {
			var page = Math.floor(this.index / this.opts.size);
			this.seekTo(this.opts.size * (page-1), time);
		},

		nextPage: function(time) {
			var page = Math.floor(this.index / this.opts.size);
			this.seekTo(this.opts.size * (page+1), time);
		},

		begin: function(time) {
			this.seekTo(0, time);
		},

		end: function(time) {
			this.seekTo(this.items.size() - this.opts.size, time);
		}


	});

})(jQuery);




