/**
 * ProductBrowser Plugin written for Klett und Balmer Verlag Zug
 *
 * Plugin to handle ProductBrowser HTML Boxes. Enabling tabbing,
 * item scrolling and toggle expanding|condensing view to see
 * all items at one sight.
 *
 * @author H2G Internetagentur
 * @version 1.00 2011-01-10
 * @version 1.01 2011-05-04 :: adding tooltip function on article
 *                          :: groups if description too long
 * @version 1.2  2011-06-28 :: optimize user presets on pb (108)
 * @version 1.3  2011-09-08 :: adding google analytics pagetracker (125)
 */
(function($) {
	var opts;
	// define var to store mode of element (condensed|expanded)
	var browserMode = new Object();
	// plugin definition
	$.fn.productBrowser = function(options) {
		// build main options before initial procedure
		opts = $.extend({}, $.fn.productBrowser.defaults, options);
		// initalize plugin
		return this.each(function(i,el) {
			var browser = i; var imgHeight = 0; var store = false;
			// set local var to start pagetracking by google analytics
			var doTrack = false;
			// setting value of browserMode mode (condensed|expanded)
			browserMode[browser] = 'condensed';
			// setting reference to current active tab
			var activeTab = $(this).find(".tabs .active a").attr('href');
			// setting current tab height in pixel
			var tabHeight = $(activeTab).height();
			// store initial switch expand|collapse string
			var txtSwitch = $(activeTab).find('.switch a').html();
			// store browser id for session storing browser state (active)
			var browserID = $(this).attr('id');
			// enabling tab switching on top
			$(this).find(".tabs a").click(function() {
				// switching only if tab is not active
				if ($(this).attr('href') != activeTab) {
					// condense current first before switch to new tab
					$.fn.productBrowser.condense(browserMode[browser], this, activeTab, tabHeight, function() {
						// resetting switch anchor default text string
						$(activeTab).find('.switch a').html(txtSwitch);
						// hide current active tab
						$(activeTab).css({'display':'none'});
						// change active tab id to clicked tab
						activeTab = $(this).attr('href');
						// display new active tab
						$(activeTab).css({'display':'block'});
						//recalculating active tab height
						tabHeight = $(activeTab).height();
						// update active state on tabs
						$(this).parents("ul").find("li").each(function() {
							($(this).find("a").attr('href') == activeTab) ?
								$(this).addClass('active') : $(this).removeClass('active');
						});
						// store active state in session storage
						if ((store) && (browserID.length > 0)) { $.ajax({
							type: "POST", url: opts.sessionhandler,
							data: "pbid="+browserID+"&pane="+activeTab
						}); } // end if ((store) && (browserID.length > 0))
						// adding google analytics pagetracker
						if (doTrack && pageTracker) { pageTracker._trackEvent(
							'productbrowser','click_on_tab',location.pathname+'#'+getTabName(browserID)
						); } // switch mode to condensed by default
						browserMode[browser] = 'condensed';
					});
				} return false;
			});
			// loop through each pane inside tabbed box
			$(this).find('.pane').each(function(i,el) {
				// remove hidden class and set element to display none
				if ("#"+$(this).attr('id') != activeTab)
					$(this).css({'display':'none'});
				// initialize tube dom object
				var tube = $(this).find('.outer-tube');
				// getting the current inner tube position
				var pos = parseInt($(this).find(".controls .active a").attr('rel'));
				// getting the size amount of scrollable views inside tube
				var size = parseInt($(this).find(".controls span").size());
				// seeking for largest height of images inside inner tube
				$(this).find(".inner-tube img").each(function() {
					var height = $(this).height(); if (imgHeight < height)
				{ imgHeight = height; } });
				// adding top offset to all images which are smaller
				$(this).find(".inner-tube img").each(function() {
					var height = $(this).height(); if (height > 0) {
					$(this).css({'margin-top':(imgHeight - height)+'px'});	
				} });
				// setting controller and offset heights
				var c = new Image(); c.src = $(this).find('.move img').attr('src');
				var padding = Math.round(imgHeight / 2) - Math.round(c.height / 2);
				// getting next|back control elements
				var next = $(this).find('.next').css({
					'padding-top': padding+'px',
					'height': (imgHeight - padding)+'px'
				}).bind('click', function() { if (!isNaN(pos)) {
					// incrementing position value to move forward
					pos = (pos < size) ? (pos+1) : pos;
					// hiding next button if end has reached
					if (pos == size) { $(next).fadeOut(opts.fade); }
					// move tube position one step forward
					$.fn.productBrowser.move(tube, pos, function() {
						// show back button on callback
						$(back).fadeIn(opts.fade);
						// updating control elements on top
						$(this).parent().find('.controls span').each(function() {
							if ($(this).hasClass('active')) { $(this).removeClass('active'); }
							if ($(this).find('a').attr('rel') == pos) { $(this).addClass('active'); }
						});
						// store pane position state of current pane
						if ((store) && (browserID.length > 0)) { $.ajax({
							type: "POST", url: opts.sessionhandler,
							data: "pbid="+browserID+"&pane="+activeTab+"&pos="+pos
						}); } // end if ((store) && (browserID.length > 0))
						// adding google analytics pagetracker event
						if (doTrack && pageTracker) { pageTracker._trackEvent(
							'productbrowser','browse',location.pathname+'#'+getTabName(browserID)+'['+pos+']'
						); }
					});
				}});
				// getting next|back control elements
				var back = $(this).find('.back').css({
					'padding-top': padding+'px',
					'height': (imgHeight - padding)+'px'
				}).bind('click', function() { if (!isNaN(pos)) {
					// decrementing position value to move back
					pos = (pos > 1) ? (pos-1) : pos;
					// hiding back button if start has reached
					if (pos == 1) { $(back).fadeOut(opts.fade); }
					// move tube position one step back
					$.fn.productBrowser.move(tube, pos, function() {
						// show next button on callback
						$(next).fadeIn(opts.fade);
						// updating control elements on top
						$(this).parent().find('.controls span').each(function() {
							if ($(this).hasClass('active')) { $(this).removeClass('active'); }
							if ($(this).find('a').attr('rel') == pos) { $(this).addClass('active'); }
						});
						// store pane position state of current pane
						if ((store) && (browserID.length > 0)) { $.ajax({
							type: "POST", url: opts.sessionhandler,
							data: "pbid="+browserID+"&pane="+activeTab+"&pos="+pos
						}); } // end if ((store) && (browserID.length > 0))
						// adding google analytics pagetracker event
						if (doTrack && pageTracker) { pageTracker._trackEvent(
							'productbrowser','browse',location.pathname+'#'+getTabName(browserID)+'['+pos+']'
						); }
					});
				}});
				// adding hover functionality on next|back buttons
				$(this).find('.move').hover(function() {
					var src = $(this).find('img').attr('src');
					$(this).find('img').attr({'src':src.replace(/_off/, '_on')});
				}, function() {
					var src = $(this).find('img').attr('src');
					$(this).find('img').attr({'src':src.replace(/_on/, '_off')});
				});
				// enabling top controls by adding click events
				$(this).find('.controls a').bind('click', function() {
					pos = parseInt($(this).attr('rel')); if (!isNaN(pos)) {
					$.fn.productBrowser.move(tube, pos, function() {
						// updating control elements on callback
						$(this).parent().find('.controls span').each(function() {
							if ($(this).hasClass('active')) { $(this).removeClass('active'); }
							if ($(this).find('a').attr('rel') == pos) { $(this).addClass('active'); }
						});
						// update next arrow control button
						if ($(next).css('display') == 'none') {
							if (pos < size) { $(next).fadeIn(opts.fade); }
						} else { if (pos == size) { $(next).fadeOut(opts.fade); } }
						// update back arrow control button
						if ($(back).css('display') == 'none') {
							if (pos > 1) { $(back).fadeIn(opts.fade); }
						} else { if (pos == 1) { $(back).fadeOut(opts.fade); }	}
						// store pane position state of current pane
						if ((store) && (browserID.length > 0)) { $.ajax({
							type: "POST", url: opts.sessionhandler,
							data: "pbid="+browserID+"&pane="+activeTab+"&pos="+pos
						}); } // end if ((store) && (browserID.length > 0))
						// adding google analytics pagetracker event
						if (doTrack && pageTracker) { pageTracker._trackEvent(
							'productbrowser','browse',location.pathname+'#'+getTabName(browserID)+'['+pos+']'
						); }
					});
				}});
				// enable expand|condense toggle switch
				$(this).find('.switch a').bind('click', function() {
					if (browserMode[browser] == 'condensed') {
						// store expanded|condensed state of current pane
						if ((store) && (browserID.length > 0)) { $.ajax({
							type: "POST", url: opts.sessionhandler,
							data: "pbid="+browserID+"&pane="+activeTab+"&pos="+pos+"&state=expanded"
						}); } // end if ((store) && (browserID.length > 0))
						// adding google analytics pagetracker event
						if (doTrack && pageTracker) { pageTracker._trackEvent(
							'productbrowser','expand',location.pathname+'#'+getTabName(browserID)
						); }
						$.fn.productBrowser.expand(browserMode[browser], this, activeTab, tabHeight, function() {
							// changing text string of toggle switch anchor
							$(activeTab).find('.switch a').html(opts.toggle);
							// switching box mode value (expanded)
							browserMode[browser] = 'expanded';
						});
					} else {
						// store expanded|condensed state of current pane
						if ((store) && (browserID.length > 0)) { $.ajax({
							type: "POST", url: opts.sessionhandler,
							data: "pbid="+browserID+"&pane="+activeTab+"&pos="+pos+"&state=condensed"
						}); } // end if ((store) && (browserID.length > 0))
						// adding google analytics pagetracker event
						if (doTrack && pageTracker) { pageTracker._trackEvent(
							'productbrowser','condense',location.pathname+'#'+getTabName(browserID)
						); }
						$.fn.productBrowser.condense(browserMode[browser], this, activeTab, tabHeight, function() {
							// changing text string of toggle switch anchor
							$(activeTab).find('.switch a').html(txtSwitch);
							// switching box mode value (condensed)
							browserMode[browser] = 'condensed';
						});
					}	return false;
				});
				// show next button if tube has more
				if (size > 1) { $(next).fadeIn(opts.fade); }
				// enable auto expand on page load
				if ($(this).hasClass('expanded'))
					$(this).find('.switch a').trigger('click');
				// set current pane position if bigger than start
				if (pos > 1) { $(this).find('.controls .active a').trigger('click'); }
				// probe for tooltip if description text is too long
				$(this).find('.item a.tip').each(function() {
					var desc = $(this).html(); if (desc.length > opts.maxlength) {
						// setting short text on anchor element
						$(this).html(desc.substr(0,(opts.maxlength-4))+' ...');
						// adding class attribute hastip and set rel attribut
						$(this).addClass('hastip').attr({'rel':desc});;
						// enable tooltip functionality on element
						$.fn.productBrowser.addtip($(this));
					}
				});
				// adding google analytics tracking code on inner anchors
				$(this).find('.item a').each(function(i,el) {
					$(this).bind('click', function() {
						if (doTrack && pageTracker) {
							var p = $(el).parent().get(0).tagName;
							switch (p.toLowerCase()) {
								case 'header': var _action = 'click_on_image'; break;
								case 'h1': var _action = 'click_on_product'; break;
								case 'p': var _action = 'click_on_articlegroup'; break;
								default: var _action = 'click';
							} // adding click action to pagetracker
							pageTracker._trackEvent(
								'productbrowser',_action,$(this).attr('href')
							);
							// perform redirect to click page
							if ($(this).attr('target') == '_blank') {
								window.open($(this).attr('href'));
							} else {
								window.location.href = $(this).attr('href');
							}
							// disabling native browser event
							return false;
						} else { return true; }
					});
				}); // end adding google analytics tracking code
			});
			// enabling session storage on initialization end
			if (parseInt(opts.sessionstore) == 1) { store = true; }
			// enabling pagetracking by google analytics
			if (parseInt(opts.trackPages) == 1) { doTrack = true; }
		});
	};
	// adding tooltip feature on given element anchor
	$.fn.productBrowser.addtip = function(el) {
		// creating reference to tooltip box
		var tip = $("<div></div>").css({
			'display':'none',
			'position':'absolute',
			'top':'0','left':'0',
			'z-index':'10000',
			'padding':'2px 5px',
			'font-size':'11px',
			'color':'#646464',
			'background-color':'#fff',
			'border':'1px solid #646464',
			'-mox-box-shadow':'1px 1px 3px #bbb',
			'-webkit-box-shadow':'1px 1px 3px #bbb',
			'box-shadow':'1px 1px 3px #bbb'
		}).html($(el).attr('rel'));
		// building hover mouse actions
		$(el).hover(function() {
			$("body").append(tip); $(tip).show();
		}, function() {
			$(tip).hide(); $(tip).remove();
		}).mousemove(function(event) {
			var tipWidth = $(tip).width(); // Find width of tooltip
			var tipHeight = $(tip).height(); // Find height of tooltip
			var posx = event.pageX + 4; // Get X coordinates
			var posy = event.pageY - parseInt(2 * tipHeight); // Get Y coordinates
			// absolute position the tooltip according to mouse pointer
			$(tip).css({'top':posy+'px','left':posx+'px'});
		});
	};
	// static function to animate inner tube
	$.fn.productBrowser.move = function(tube,pos,callback) {
		// getting outer tube width to determine tube offset
		var offset = parseInt($(tube).width());
		// calculating the new inner tube offset position
		var left = ((pos - 1) * offset);
		// animating inner tube
		$(tube).find('.inner-tube').stop(true,true).animate({
			'left': '-'+left+'px'
		}, opts.speed, opts.animation, function() {
			if (typeof callback == "function") {
				callback.call(tube);
			}
		});
	};
	// static function to condense productbrowser to minimized state
	$.fn.productBrowser.condense = function(mode,tab,pane,height,callback) {
		if (mode == 'expanded') {
			// hiding item elements inside expanded tube
			$(pane).find('.expanded-pane .item').fadeOut(opts.fade);
			// animate height of expanded box back
			$(pane).find('.expanded-pane').animate({
				'height': (height-getOffset(pane))+'px'
			}, opts.speed, opts.animation, function() {
				// remove expandex box layer
				$(this).remove();
				// display inner pane again
				$(pane).find('.inner-pane').css({'display':'block'});
				// call callback function
				if (typeof callback == "function")
					callback.call(tab);
			});
		} else if (mode == 'condensed') {
			// return callback immediately if pane is condensed
			if (typeof callback == "function")
				callback.call(tab);
		}		
	};
	// static function to expand productbrowser to show all items
	$.fn.productBrowser.expand = function(mode,tab,pane,height,callback) {
		// fixing actual height of current active pane
		$(pane).css({'height':height+'px'});
		// calculating height of inner pane layer
		var innerHeight = $(pane).find('.inner-pane').height();
		// fading out inner pane and create expanded pane
		$(pane).find('.inner-pane').fadeOut(opts.fade, function() {
			var div = $("<div></div>")
				.addClass('expanded-pane')
				.css({'height':innerHeight+'px'});
			// create inner tube layer
			var tube = $("<div></div>")
				.addClass('inner-tube');
			// cloning items inside inner pane tube
			$(this).find('.item').each(function(i,el) {
				// dividing item elements in group of three
				if ($(tube).find('.item').size() == 3) {
					$(div).append(tube); tube = $("<div></div>")
						.addClass('inner-tube');
				}
				// cloning item element to add to tube
				var item = $("<div></div>").addClass('item')
					.append($(el).find('img').clone())
					.append($(el).find('h1').clone())
					.append($(el).find('p').clone());
				// attaching link reference to image
				$(item).find('img').wrap($("<a></a>").attr({
					'href':$(el).find('h1 a').attr('href')
				}));
				// add tooltip function to each group anchor
				$(item).find('a.hastip').each(function() {
					$.fn.productBrowser.addtip($(this));
				});
				// append item to current tube element
				$(tube).append(item);
			});
			// append last tube element and add to pane
			$(pane).prepend($(div).append(tube));
			// remove fixed height from pane
			$(pane).removeAttr('style');
			// calculating new height of expanded pane
			var height = 0;
			$(div).find('.inner-tube').each(function(i,el) {
				var h = 0; $(this).find('.item').each(function() {
					if ($(this).height() > h) h = $(this).height();
				}); height = height + (h + getOffset(pane));
			});
			// animating productbrowser pane to new height
			$(div).animate({
				'height': height+'px'
			}, opts.speed, opts.animation, function() {
				// execute callback function
				if (typeof callback == "function")
					callback.call(tab);
			});
		});
	};
	function getOffset(pane) {
		var p = $(pane).find('.inner-tube').css('padding-top');
		if (parseInt(p) != NaN) { return parseInt(p); }
		else { return 0; }
	}
	function getTabName(id) {
		return $('#'+id).find('.tabs .active a').html();
	}
	// only for debugging purpose
	function debug($msg) {
		if (window.console && window.console.log)
			window.console.log('debug: '+$msg);
	}
	// plugin defaults array
	$.fn.productBrowser.defaults = {
		sessionhandler: '/katalog/session.php',
		sessionstore: 1,
		session: true,
		toggle: 'verkleinern',
		animation: 'easeOutQuint',
		speed: 600,
		fade: 'fast',
		maxlength: 20,
		trackPages: 1
	}
})(jQuery);
