/* ---------------------------------------->>> EXTERNAL PLUG-INS <<<------------------------------------------ */


/**
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:50,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY;};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev]);}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev]);};var handleHover=function(e){var p=(e.type=="mouseover"?e.fromElement:e.toElement)||e.relatedTarget;while(p&&p!=this){try{p=p.parentNode;}catch(e){p=this;}}if(p==this){return false;}var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);}if(e.type=="mouseover"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob);},cfg.timeout);}}};return this.mouseover(handleHover).mouseout(handleHover);};})(jQuery);


/**
 * jQuery Color Animations
 * Copyright 2007 John Resig
 * Released under the MIT and GPL licenses.
 */
(function(jQuery){jQuery.each(['backgroundColor','borderBottomColor','borderLeftColor','borderRightColor','borderTopColor','color','outlineColor'],function(i,attr){jQuery.fx.step[attr]=function(fx){if(fx.state==0){fx.start=getColor(fx.elem,attr);fx.end=getRGB(fx.end)}fx.elem.style[attr]="rgb("+[Math.max(Math.min(parseInt((fx.pos*(fx.end[0]-fx.start[0]))+fx.start[0]),255),0),Math.max(Math.min(parseInt((fx.pos*(fx.end[1]-fx.start[1]))+fx.start[1]),255),0),Math.max(Math.min(parseInt((fx.pos*(fx.end[2]-fx.start[2]))+fx.start[2]),255),0)].join(",")+")"}});function getRGB(color){var result;if(color&&color.constructor==Array&&color.length==3)return color;if(result=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))return[parseInt(result[1]),parseInt(result[2]),parseInt(result[3])];if(result=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))return[parseFloat(result[1])*2.55,parseFloat(result[2])*2.55,parseFloat(result[3])*2.55];if(result=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))return[parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16)];if(result=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))return[parseInt(result[1]+result[1],16),parseInt(result[2]+result[2],16),parseInt(result[3]+result[3],16)];return colors[jQuery.trim(color).toLowerCase()]}function getColor(elem,attr){var color;do{color=jQuery.curCSS(elem,attr);if(color!=''&&color!='transparent'||jQuery.nodeName(elem,"body"))break;attr="backgroundColor"}while(elem=elem.parentNode);return getRGB(color)};var colors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);


// JSON parser
(function($){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},s={'array':function(x){var a=['['],b,f,i,l=x.length,v;for(i=0;i<l;i+=1){v=x[i];f=s[typeof v];if(f){v=f(v);if(typeof v=='string'){if(b){a[a.length]=','}a[a.length]=v;b=true}}}a[a.length]=']';return a.join('')},'boolean':function(x){return String(x)},'null':function(x){return"null"},'number':function(x){return isFinite(x)?String(x):'null'},'object':function(x){if(x){if(x instanceof Array){return s.array(x)}var a=['{'],b,f,i,v;for(i in x){v=x[i];f=s[typeof v];if(f){v=f(v);if(typeof v=='string'){if(b){a[a.length]=','}a.push(s.string(i),':',v);b=true}}}a[a.length]='}';return a.join('')}return'null'},'string':function(x){if(/["\\\x00-\x1f]/.test(x)){x=x.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c}c=b.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16)})}return'"'+x+'"'}};$.toJSON=function(v){var f=isNaN(v)?s[typeof v]:s['number'];if(f)return f(v)};$.parseJSON=function(v,safe){if(safe===undefined)safe=$.parseJSON.safe;if(safe&&!/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(v))return undefined;return eval('('+v+')')};$.parseJSON.safe=false})(jQuery);


// IE needs special treatment, once again
if (!Array.indexOf) {
	Array.prototype.indexOf = function (obj) {
		for (var i = 0; i < this.length; i++) {
			if (this[i] == obj) { return i; }
		} return -1;
	}
}


/* ---------------------------------------->>> OWN PLUG-INS <<<------------------------------------------ */

// CSS Parser
// replace with jQuery UI class transitions as soon as they work in Safari (probably next release after 1.7)
(function ($) {
	$.fn.cssparser = function (e, opts) {
		var settings = jQuery.extend({
			 title: '', // no title: search all files
			 props_animate: [ 'width', 'height', 'top', 'left', 'right' ],
			 props_static: [ 'z-index' ]
		}, opts);

		var regexp = new RegExp('(^|,)\\s*\\' + e + '\\s*(,|$)'),
			styles_animate = {}, styles_animate_arr = [ ], styles_static = {}, styles_static_arr = [ ],
			sheets = document.styleSheets;

		if (sheets.length == 0) return;

		for (var i = 0; i<sheets.length; i++) { // $.each not working properly in IE
			if (settings.title && (document.styleSheets[i].title != settings.title)) {
				continue;
			}
			$.each(document.styleSheets[i].cssRules || document.styleSheets[i].rules, function () {
				if (regexp.test(this.selectorText)) {
					var prop = this.style.cssText.toLowerCase();
					var props = prop.split(';');

					$.each(props, function () {
						if ($.inArray(this.split(':')[0].replace(/ /g, ''), settings.props_animate) != -1) { // check if property has to be animated
							styles_animate_arr.push(this);
						} else { // check if property has to be set
							var checkprop = this;
							$.each(settings.props_static, function () { // check each possible notation
								if (checkprop.indexOf(this) >= 0) {
									styles_static_arr.push(checkprop);
								}
							})
						}
					});
				}
			});
		}

		$.fn.format = function (arg, opt) {
			var arr = [ ];
			$.each(arg, function () {
				var prop = '\'' + this.split(':')[0].replace(/ /g, '') + '\':\'' + this.split(':')[1];
				if (opt != 'static') {
					prop = prop.replace(/ /g, '');
				}
				prop = prop + '\'';
				arr.push(prop);
			});

			var string =  '{' + arr.join(',') + '}';
			if (opt != 'static') {
				styles_animate = $.parseJSON(string);
			} else {
				styles_static = $.parseJSON(string);
			}
		}

		$.fn.format(styles_animate_arr);
		$.fn.format(styles_static_arr, 'static');

		styles = [ styles_animate, styles_static ];

		return styles;
	};
})(jQuery);


// Slideshow
(function ($) {
	$.fn.slideshow = function (opts) {
		var settings = jQuery.extend({
			stylesheet_title: 'slideshow',
			stylesheet_ul: '.slideshow',
			stylesheet_li: '.slide', // example: ".slideshow .slide1 {}"
			stylesheet_ul_hover: '.nojs', // example: ".nojs .slide1:hover {}"
			speed_animation: 200,
			speed_hover: 100
		}, opts);

		return this.each(function () {
			var currentSlide = 0;
			var el = $(this);
			var els = $('li', el);
			var l = els.length;
			var i_slideshow = $('.slideshow').index(el);
			var pager = $('.slideshow-pager:eq(' + i_slideshow + ')');
			var styles_click = [ ], styles_hover = [ ];

			// prevent css :hover
			el.removeClass('nojs');

			// paging
			$.fn.paging = function (i) {
				pager.find('li:eq(' + currentSlide + ')').html('<a href="#">' + (currentSlide + 1) + '</a>');
				pager.find('li:eq(' + i + ')').html('<span>' + (i + 1) + '</span>');
				currentSlide = i;
			}
			$('a', pager).live('click', function (event) {
				var i = $('li', pager).index($(this).parents('li'));
				$.fn.paging(i);
				$('li:eq(' + i + ')', el).trigger('click');

				event.preventDefault();
			});

			// auto sliding (10 secs)
			var auto = setInterval(function () {
				var i = currentSlide;
				if (i == l - 1) {
					i = -1;
				}
				$.fn.clickevent(i + 1);
			}, 10000);

			// initialize
			els.each(function (i) {
				// get styles of each possible state
				styles_click[i] = $.fn.cssparser(settings.stylesheet_ul + ' ' + settings.stylesheet_li + i, { title: settings.stylesheet_title });
				styles_hover[i] = $.fn.cssparser(settings.stylesheet_ul_hover + ' ' + settings.stylesheet_li + i + ':hover', { title: settings.stylesheet_title });
				// add state
				$(this).addClass('slide' + i);
			});

			// click event
			$.fn.clickevent = function (clicked) {
				// console.log(clicked);
				var el_clicked = $('li:eq(' + clicked + ')', el);
				// check if element is the first one (no effect)
				if (el_clicked.attr('class').split('slide')[1] == 0) return false;
				// prevent hover
				el.addClass('animated');
				// click event
				els.each(function (i) {
					var state = $(this).attr('class').split('slide')[1];
					var state_new = l - clicked + i;
					if (state_new >= l) {
						state_new = state_new - l;
					}
					$('a', this).removeClass('last');
					if (state_new == l - 1) {
						$('a', this).addClass('last');
					}
					//if ((state == 0) || (state_new == 0)) $(this).find('span').hide();
					//if (state == 0) el_clicked.find('span').fadeIn('fast');
					$(this).animate(styles_click[state_new][0], settings.speed_animation, function () {
						el.removeClass('animated');
						//if (state == 0) $(this).find('span').show();
					}).css(styles_click[state_new][1]).removeClass('slide' + state).addClass('slide' + state_new);
				});
				// paging
				$.fn.paging(clicked);
			}
			els.click(function (event) {
				clearInterval(auto);

				var clicked = els.index(this);
                // clicking the current picture advances to next one
                if (clicked == currentSlide) {
                	var i = currentSlide;
                    if (i == l - 1) {
                    	i = -1;
                    }
                    $.fn.clickevent(i + 1);
                } else {
                    $.fn.clickevent(clicked);
                }

				event.preventDefault();
			});

			// hover event
			els.hover(function () {
				clearInterval(auto);

					// check if hover is prevented or element is the first one (no effect)
					if (!el.hasClass('animated') && !($(this).attr('class').split('slide')[1] == 0)) {
						var state =  $(this).attr('class').split('slide')[1];
						$(this).animate(styles_hover[state][0], settings.speed_hover);
					}
				}, function () {
					if (!el.hasClass('animated') && !($(this).attr('class').split('slide')[1] == 0)) {
						var state =  $(this).attr('class').split('slide')[1];
						$(this).animate(styles_click[state][0], settings.speed_hover);
					}
			});
		});
	}
})(jQuery);


// hash operations (the hash component of the URL becomes a GET-style parameter list)
(function ($) {
	$.fn.hasher = function (operation, key, value, options) {
		if (operation == 'set' && !value) {
			operation = 'del';
		}
		var keyValueSeparator = '-';
		var assignmentSeparator = '.';
		var hashString;
		if (!(hashString = options.hashString)) {
			hashString = $.fn.hasher.hashString
			var hashStringFromLocation = $(location).attr('hash').replace(new RegExp('^\#?[' + assignmentSeparator + ']*'), '');
			if (hashStringFromLocation != hashString && decodeURIComponent(hashString) != hashStringFromLocation) {
				hashString = hashStringFromLocation;
			}
		}
		var hashAssignments = hashString ? hashString.split(assignmentSeparator) : [ ];
		var valueFound = false;
		var keyValueAssignment = key + keyValueSeparator + value;
		var keyAssignmentPattern = new RegExp('^' + key + '[' + keyValueSeparator + '](.*)');

		if (hashAssignments.length > 0) {
			switch (operation) {
			case 'set':
				for (var i = 0; i < hashAssignments.length; ++i) {
					var hashAssignment = hashAssignments[i];
					if (keyAssignmentPattern.exec(hashAssignment)) {
						if (valueFound) {
							hashAssignments.splice(i--, 1);
						} else {
							hashAssignments[i] = keyValueAssignment;
							valueFound = true;
						}
					}
				}
				if (!valueFound) {
					hashAssignments.push(keyValueAssignment)
				}
				var newHash = hashAssignments.join(assignmentSeparator);
				if (options.noLocationChange) {
					return newHash;
				} else {
					$.fn.hasher.setHash(newHash);
				}
				break;
			case 'del':
				for (var i = 0; i < hashAssignments.length; ++i) {
					var hashAssignment = hashAssignments[i];
					if (keyAssignmentPattern.exec(hashAssignment)) {
						hashAssignments.splice(i--, 1);
					}
				}
				var newHash = hashAssignments.join(assignmentSeparator);
				if (options.noLocationChange) {
					return newHash;
				} else {
					$.fn.hasher.setHash(newHash);
				}
				break;
			case 'get':
				var result = options.collect ? [ ] : value;
				var match;
				$.each(hashAssignments, function (i, hashAssignment) {
					if ((match = keyAssignmentPattern.exec(hashAssignment))) {
						if (options.collect) {
							result.push(match[1]);
						} else {
							result = match[1];
						}
						return options.collect;
					}
				});
				return result;
			}
		} else {
			switch (operation) {
			case 'set':
				if (options.noLocationChange) {
					return keyValueAssignment;
				} else {
					$.fn.hasher.setHash(keyValueAssignment);
				}
				break;
			case 'get':
				return options.collect ? [ ] : '';
			}
		}
	}
	$.fn.hasher.setHash = function (newHashString) {
		$.fn.hasher.hashString = newHashString;
		$(location).attr('hash', newHashString);
	}

	$.fn.hashSet = function (key, value, noLocationChange) {
		return $.fn.hasher('set', key, value, { noLocationChange: noLocationChange });
	}

	$.fn.hashSetAll = function (key, values, noLocationChange) {
		var keyValueSeparator = '-';
		var assignmentSeparator = '.';
		var separator = '', combinedValue = '';
		$.each(values, function (i, value) {
			combinedValue += separator;
			combinedValue += value;
			separator = assignmentSeparator + key + keyValueSeparator;
		});
		return $.fn.hasher('set', key, combinedValue, { noLocationChange: noLocationChange });
	}

	$.fn.hashGet = function (key, defaultValue, hashString) {
		return $.fn.hasher('get', key, defaultValue, { hashString: hashString });
	}

	$.fn.hashGetAll = function (key, hashString) {
		return $.fn.hasher('get', key, null, { hashString: hashString, collect: true });
	}

	$.fn.hashDel = function (key, noLocationChange) {
		return $.fn.hasher('del', key, null, { noLocationChange: noLocationChange });
	}
})(jQuery);


// References filter
(function ($) {
	// attach click handler to pager links
	$.fn.pager = function (currentPage) {
		var currentStartIndex = $.fn.references.startIndex;
		$('a', $.fn.references.elements.pager).bind('click', function (event) {
			var startIndexFromQuery = this.href.replace(new RegExp('^[^#]*[?](?:.*&)?' + startIndexSelector + '=([0-9]+)(?:&.*)?'), '$1');
			var hashString = this.href.replace(/^.*?#/, '');
			var startIndex = parseInt($.fn.hashGet(startIndexSelector, startIndexFromQuery, hashString), 10) || 1;
			$.fn.references.startIndex = startIndex;
			$.fn.executeFilter();
			$.fn.hashSet('start', startIndex);
			event.preventDefault();
		});
	};

	$.fn.executeFilter = function () {
		// if references data not there yet, get data and repeat this function when it's there
		if (!$.fn.references.cachedReferencesData) {
			$.getJSON(referencesUrl, function (referencesData) {
				$.fn.references.cachedReferencesData = referencesData;
				$.fn.executeFilter();
			});
			return;
		}
		// do the actual filtering if not done yet
		if (!$.fn.references.included) {
			$.fn.filterReferencesData();
		}
		// show the results
		$.fn.displayFilteredReferences();
	};

	$.fn.filterReferencesData = function () {
		var chosenTags = $.fn.references.chosenTags;

		// reset all activated filters optically
		$.fn.references.elements.filters.find('li.current').removeClass('current');

		// structure chosen tags
		var chosenTagsGroupedByCategory = { };
		var chosenTagNames = [ ];
		$.each(chosenTags, function (i, chosenTag) {
			if (chosenTag) {
				var filterLink = $.fn.references.filterLinks[chosenTag];
				if (!filterLink) {
					return true;
				}
				// arrange filter array
				var categoryIndex = $.fn.references.elements.filters.index(filterLink.parents('ul'));
				if (!chosenTagsGroupedByCategory[categoryIndex]) {
					chosenTagsGroupedByCategory[categoryIndex] = [ ];
				}
				chosenTagsGroupedByCategory[categoryIndex].push(chosenTag);
				// show selected filters
				filterLink.parent('li').addClass('current');
				// create string with selected filters
				chosenTagNames.push($.trim(filterLink.text()));
			}
		});

		// show filters on page and change hash
		var filterDisplayText = chosenTagNames.slice(0, maxDisplayedTags).join(filterDisplaySeparator);
		$.fn.references.elements.filterDisplay.text(filterDisplayText);
		if (chosenTagNames.length > maxDisplayedTags) {
			$.fn.references.elements.filterDisplay
				.append(filterDisplaySeparator + moreTagsIndicator);
		}
		$.fn.hashSetAll('tag', $.map(chosenTags, $.fn.encode));

		// toggle reset link
		if (chosenTagNames.length > 0) {
			$.fn.references.elements.resetContainer.removeClass('hide');
		} else {
			$.fn.references.elements.resetContainer.addClass('hide');
		}

		// evaluate the filter to find which references are included
		var referencesData = $.fn.references.cachedReferencesData;
		var excluded = { };
		// loop trough items and add to excluded if filter critera are not fulfilled
		$.each(referencesData.items, function (referenceIndex, referenceData) {
			$.each(chosenTagsGroupedByCategory, function (categoryIndex, chosenTagsInCategory) {
				if (chosenTagsInCategory.length) {
					var noCategoryTagsFound = true;
					$.each(chosenTagsInCategory, function (tagIndex, tag) {
						if ((referenceData.tags[categoryIndex].indexOf(tag) >= 0)) {
							noCategoryTagsFound = false;
							return false;
						}
					});
					if (noCategoryTagsFound) {
						excluded[referenceIndex] = true;
					}
				}
			});
		});
		// collect all not-excluded references
		var included = [ ];
		$.each(referencesData.items, function (referenceIndex, referenceData) {
			if (!excluded[referenceIndex]) {
				included.push(referenceIndex);
			}
		});
		$.fn.references.included = included;
	};

	$.fn.displayFilteredReferences = function (calledViaTimer) {
		if (!calledViaTimer) {
			if (!$.fn.displayFilteredReferences.timer) {
				$.fn.references.elements.progressBar.animate(
					{ width: "100%" },
					{
						queue: true,
						duration: $.fn.references.progressBarDelay,
						complete: function () {
								$.fn.references.elements.progressBar.css("width", "0");
							}
					});
				$.fn.displayFilteredReferences.timer = setTimeout(function () {
					$.fn.displayFilteredReferences(true);
				}, $.fn.references.progressBarDelay - 1);
			}
			return;
		}

		var startIndex = $.fn.references.startIndex;

		// clear references display area
		$.fn.references.elements.refs.html('');

		// create reference items
		var referencesData = $.fn.references.cachedReferencesData;
		var chosenTags = $.fn.references.chosenTags;
		var included = $.fn.references.included;
		var totalReferences = included.length;
		var showFirstBox = chosenTags.length == 0 && !$.fn.hashGet(filterVisibilitySelector);
		var showSecondBox = true;
		var referencesPerPage = itemsPerPage - (showFirstBox ? 1 : 0) - (showSecondBox ? 1 : 0);
		$.fn.references.referencesPerPage = referencesPerPage;
		startIndex = Math.max(1, Math.min(startIndex, totalReferences));
		var selectedPage = Math.ceil((startIndex - 1) / referencesPerPage) + 1;
		var maxPage = selectedPage + Math.floor((totalReferences - startIndex) / referencesPerPage);
		var endIndex = Math.min(startIndex + referencesPerPage - 1, totalReferences);
		$('#pagingFrom').text(startIndex);
		$('#pagingTo').text(endIndex);
		$('#pagingTotal').text(totalReferences);
		if (totalReferences) {
			$('#pagingDisplay').show();
		} else {
			$('#pagingDisplay').hide();
		}

		var colCounter = 0, cssClass;
		if (showFirstBox) {
			cssClass = $.fn.getCSSClass(colCounter++);
			$('<li class="col c25"><div class="' + cssClass + '"><div class="box-ref"><div class="info"><div class="box-blue-arrow"><div class="box-blue"><div class="box"><span class="title">' + firstBox_title + '</span><span class="small">' + firstBox_text + '</span></div></div></div></div></div></div>')
				.appendTo($.fn.references.elements.refs);
		}

		$.each(included.slice(startIndex - 1), function (refCounter, referenceIndex) {
			if (refCounter >= referencesPerPage) {
				return false;
			}
			var referenceData = referencesData.items[referenceIndex];
			// check in which position the item is rendered	and adjust CSS class
			cssClass = $.fn.getCSSClass(colCounter++);

			// render item
			var href = referenceData.url;
			var tagParameters = [ resetTagsSelector ];
			$.each(chosenTags, function (i, chosenTag) {
				tagParameters.push(tagSelector + "=" + $.fn.encode(chosenTag));
			});
			href = href + (tagParameters.length ? '?' + tagParameters.join('&') : '');
			$('<li class="col c25" id="el' + referenceIndex + '"><div class="' + cssClass + '"><div class="box-ref"><div class="ref"><a href="' + href + '" class="overlay"><span class="overlay"></span></a></div></div></div></li>')
				.appendTo($.fn.references.elements.refs);
			var el = $('#el' + referenceIndex + ' a');
			// change link if filter is applied
			$(el).attr('href', href);
			// render image, title and description
			if (referenceData.img) {
				$('<img/>').attr('src', referenceData.img)
					.appendTo(el);
			}
			$('<span class="title"/>').text(/*itemNumber + 1 + ': ' + */ $.fn.normalizeDashes(referenceData.brand))
				.appendTo(el);
			$('<span class="small"/>').text($.fn.normalizeDashes(referenceData.desc))
				.appendTo(el);
		});

		if (showSecondBox) {
			cssClass = $.fn.getCSSClass(colCounter++);
			$('<li class="col c25"><div class="' + cssClass + '"><div class="box-ref"><div class="ref"><a href="' + secondBox_link + '" class="overlay"><span class="box-blue"><span class="box"><span class="title">' + secondBox_title + '</span><span class="small">' + secondBox_text + '</span></span></span><span class="overlay"></span></a></div></div></div></li>')
				.appendTo($.fn.references.elements.refs);
		}

		// create pager links
		$.fn.references.elements.pager.html('');
		if (maxPage > 1) {
			if (selectedPage > 1) {
				var hashValue = $.fn.hashSet('start', Math.max(startIndex - referencesPerPage, 1), true);
				$('<li> <a href="#' + hashValue + '" class="prev">' + text_prev + '</a> </li>')
					.appendTo($.fn.references.elements.pager);
			}
			for (var pageNumber = 1; pageNumber <= maxPage; ++pageNumber) {
				if (pageNumber == selectedPage) {
					$('<li><span>' + pageNumber + '<\/span><\/li>')
						.appendTo($.fn.references.elements.pager);
				} else {
					var hashValue = $.fn.hashSet('start', Math.max(startIndex + (pageNumber - selectedPage) * referencesPerPage, 1), true);
					$('<li><a href="#' + hashValue + '">' + pageNumber + '<\/a><\/li>')
						.appendTo($.fn.references.elements.pager);
				}
			}
			if (selectedPage < maxPage) {
				var hashValue = $.fn.hashSet('start', startIndex + referencesPerPage, true);				
				$('<li> <a href="#' + hashValue + '" class="next">' + text_next + '</a> </li>')
					.appendTo($.fn.references.elements.pager);
			}
		}
		$.fn.pager(selectedPage);
		$.fn.references.elements.progressBar.stop(false, true);
		$.fn.displayFilteredReferences.timer = null;
	};

	$.fn.getCSSClass = function (i) {
		var mod = i % 4, cssClass;
		switch (mod) {
		case 0:
			cssClass = 'contl';
			break;
		case 1:
			cssClass = 'contml';
			break;
		case 2:
			cssClass = 'contmr';
			break;
		default:
			cssClass = 'contr';
			break;
		}
		return cssClass;
	};

	$.fn.getTagFromLink = function (link) {
		var tag = null;
		$.each($(link.attr('class').split(/\s+/)), function (i, className) {
			if ((tag = $.fn.getTagFromSelector(className))) {
				return false;
			}
		});
		return tag;
	};

	$.fn.getTagFromSelector = function (tagAsSelector) {
		var match;
		if ((match = tagAsSelector.match(new RegExp("^" + tagSelector + "-(.+)")))) {
			return $.fn.decode(match[1]);
		} else {
			return null;
		}
	}

	$.fn.normalizeDashes = function (text) {
		return text.replace(/(\s|\n|<br>)-(\s|\n|<br>)/g, "$1\u2013$2");
	};

	$.fn.decode = function (text) {
		var decoded = decodeURIComponent(text.replace(/[+]/g, ' '));
		if (decoded.match(/%[0-9A-F]{2}/)) {
			decoded = decodeURIComponent(decoded.replace(/[+]/g, ' '));
		}
		return decoded;
	}

	$.fn.HEX_DIGITS = '0123456789ABCDEF';
	$.fn.encode = function (text) {
		var result = '';
		for (var i = 0; i < text.length; ++i) {
			var c = text.charAt(i);
			switch (c) {
			case '.':
			case ':':
			case '-':
			case '+':
			case '%':
			case '/':
			case '#':
			case '?':
			case '"':
			case '\'':
				result += '%';
				result += "25";
				c = c.charCodeAt(0);
				result += $.fn.HEX_DIGITS.charAt((c >> 4) & 0xF);
				result += $.fn.HEX_DIGITS.charAt(c & 0xF);
				break;
			case ' ':
				result += '+';
				break;
			default:
				result += c;
				break;
			}
		}
		return result;
	}

	$.fn.references = function () {
		$.fn.references.elements = {
			refs: $('#refs ul'),
			pager: $('#pager'),
			filters: $('#filter ul'),
			filterDisplay: $('#filterDisplay'),
			resetLink: $('#resetLink'),
			resetContainer: $('#resetCols'),
			progressBar: $('#progress')
		};
		$.fn.references.progressBarDelay = 200;

		// check if we need to filter
		var chosenTags = $.map($.fn.hashGetAll('tag'), $.fn.decode);
		var startIndex = parseInt($.fn.hashGet(startIndexSelector), 10);
		var filterVisibility = $.fn.hashGet(filterVisibilitySelector);

		$.fn.references.referencesPerPage = referencesPerPage;
		$.fn.references.chosenTags = chosenTags;
		$.fn.references.startIndex = startIndex || 1;

		if (chosenTags.length || startIndex || filterVisibility) {
			$.fn.executeFilter();
		} else {
			$.fn.pager(1);
		}

		// tabulate filter links by tag and attach click handlers
		$.fn.references.filterLinks = { };
		$.each($('a', $.fn.references.elements.filters), function (i, filterLink) {
			filterLink = $(filterLink);
			var tag = $.fn.getTagFromLink(filterLink);
			$.fn.references.filterLinks[tag] = filterLink;
			filterLink.bind('click', function (event) {
				var thisFilterLink = $(this);
				var linkTag = $.fn.getTagFromLink(thisFilterLink);
				var text = thisFilterLink.text();
				var chosenTags = $.fn.references.chosenTags;
				var chosenTagIndex;
				if ((chosenTagIndex = chosenTags.indexOf(linkTag)) >= 0) {
					chosenTags.splice(chosenTagIndex, 1);
					// remove blue text colour - Mantis 25196
					thisFilterLink.blur();
				} else {
					chosenTags.push(linkTag);
				}
				$.fn.references.included = null;
				$.fn.references.startIndex = 1;
				$.fn.hashDel(startIndexSelector);
				$.fn.executeFilter();
				event.preventDefault();
			});
		});

		// attach click handler to reset link
		$.fn.references.elements.resetLink.bind('click', function (event) {
			$.fn.references.elements.resetContainer.addClass('hide');
			$.fn.references.chosenTags = [ ];
			$.fn.references.included = null;
			$.fn.references.startIndex = 1;
			$.fn.executeFilter();
			event.preventDefault();
		});

		// hide/show filter and set text for toggle filter link
		if (!filterVisibility) filterVisibility = 'hidden';
		$('#filter, #toggle').attr('class', filterVisibility);
		switch (filterVisibility) {
		case 'hidden':
			$('#toggle').text(text_show);
			$('#filter').hide();
			break;
		case 'expanded':
			$('#toggle').text(text_hide);
			$('#filter').show();
			break;
		}

		// attach click handler to toggle filter link
		$('#toggle').click(function (event) {
			if (!$(this).hasClass('expanded')) {
				$(this).removeClass('hidden').addClass('expanded').text(text_hide);
				$('#filter').slideDown();
				$.fn.hashSet(filterVisibilitySelector, 'expanded');
				if (!$.fn.hashGet('tag')) {
					$.fn.executeFilter();
				}
			} else {
				$(this).removeClass('expanded').addClass('hidden').text(text_show);
				$('#filter').slideUp();
				$.fn.hashSet(filterVisibilitySelector, 'hidden');
			}
			event.preventDefault();
		});

		// prefetch references data
		$.getJSON(referencesUrl, function (referencesData) {
			$.fn.references.cachedReferencesData = referencesData;
/* preload images? Better not, we need the first page to be ready quickly
			$.each(referencesData.items, function (referenceIndex, referenceData) {
				var preloadedImage = new Image();
				preloadedImage.src = referenceData.img;
			});
*/
		});
	};
})(jQuery);


/* ---------------------------------------->>> EXECUTE WHEN READY <<<------------------------------------------ */

$(document).ready(function () {

	// ---------------------------------------------------------------------- //
	// META NAVIGATION

	if (jQuery.browser.msie && jQuery.browser.version < 7) {
		$('#meta-countries, #meta-search label').hover(function () {
			$(this).addClass('hover');
		}, function () {
			$(this).removeClass('hover');
		});
	}

	// Search

	// show field
	$.fn.showsearch = function (e) {
		$('#meta-search div').removeClass('nojs');
		if (e.attr('type') != 'text') {
			$('#meta-search input[type=text]').focus();
		}
	}
	$('#meta-search input').focus(function () {
		$.fn.showsearch($(this));
	});

	// toggle field
	$(document).bind('click', function (e) {
		var el = $(e.target);

		if (!$('#meta-search div').hasClass('nojs')) {
			if (!(el.parents().is('#meta-search') || el.parents().is('ul.skip'))) {
				$('#meta-search div').addClass('nojs');
			}
		}
		if ((el.is('#meta-search label') || el.parents().is('ul.skip'))) {
			$.fn.showsearch($(this));
		}
	});

	// Countries

	if (jQuery.browser.msie && jQuery.browser.version < 7) {
		$('#nav-meta li').hover(function () {
			$(this).addClass('hover');
		}, function () {
			$(this).removeClass('hover');
		});
	}

	// ---------------------------------------------------------------------- //
	// OVERLAYS

	// IE and FF2 aren't capable of animating alpha-transparency properly

	if (!((jQuery.browser.msie && jQuery.browser.version < 9) || (jQuery.browser.mozilla && parseFloat(jQuery.browser.version) < 1.9))) {
		$('a.overlay').addClass('overlay-js');
		$('a.overlay-js').hoverIntent(function () {
				$('.overlay', this).fadeIn(200);
				$('span', this).animate({'color': '#2FA4FF'}, 200);
				setTimeout(function () { $('span', this).css({ 'color': '#2FA4FF' }); }, 200);
			}, function () {
				$('.overlay', this).fadeOut(200);
				$('span', this).animate({ 'color': '#333' }, 200);
				setTimeout(function () { $('span', this).css({'color':'#333'}); }, 200);
		});
	}

	// References
	if ($('#refs').length) {
		$.fn.references();
	}

	// Slideshow
	$('.slideshow').slideshow();

});
