PageSourceSearch

https://yperboreia.org/highslide/highslide-with-gallery.js

js yperboreia.org collected 2026-09-29 12:35:24 UTC 64,675 bytes, 2,265 lines download raw bytes

1/******************************************************************************
2Name:    Highslide JS
3Version: 4.0.3 (August 14 2008)
4Config:  default +slideshow +positioning +transitions
5Author:  Torstein Hønsi
6Support: http://highslide.com/support
7
8Licence:
9Highslide JS is licensed under a Creative Commons Attribution-NonCommercial 2.5
10License (http://creativecommons.org/licenses/by-nc/2.5/).
11
12You are free:
13	* to copy, distribute, display, and perform the work
14	* to make derivative works
15
16Under the following conditions:
17	* Attribution. You must attribute the work in the manner  specified by  the
18	  author or licensor.
19	* Noncommercial. You may not use this work for commercial purposes.
20
21* For  any  reuse  or  distribution, you  must make clear to others the license
22  terms of this work.
23* Any  of  these  conditions  can  be  waived  if  you  get permission from the 
24  copyright holder.
25
26Your fair use and other rights are in no way affected by the above.
27******************************************************************************/
28var hs = {
29// Language strings
30lang : {
31	loadingText : 'Loading...',
32	loadingTitle : 'Click to cancel',
33	focusTitle : 'Click to bring to front',
34	fullExpandTitle : 'Expand to actual size',
35	creditsText : 'Powered by <i>Highslide JS</i>',
36	creditsTitle : 'Go to the Highslide JS homepage',
37	previousText : 'Previous',
38	nextText : 'Next', 
39	moveText : 'Move',
40	closeText : 'Close', 
41	closeTitle : 'Close (esc)', 
42	resizeTitle : 'Resize',
43	playText : 'Play',
44	playTitle : 'Play slideshow (spacebar)',
45	pauseText : 'Pause',
46	pauseTitle : 'Pause slideshow (spacebar)',
47	previousTitle : 'Previous (arrow left)',
48	nextTitle : 'Next (arrow right)',
49	moveTitle : 'Move',
50	fullExpandText : 'Full size',
51	number: 'Image %1 of %2',
52	restoreTitle : 'Click to close image, click and drag to move. Use arrow keys for next and previous.'
53},
54// See http://highslide.com/ref for examples of settings  
55graphicsDir : 'highslide/graphics/',
56restoreCursor : 'zoomout.cur', // necessary for preload
57expandSteps : 10, // number of steps in zoom. Each step lasts for duration/step milliseconds.
58expandDuration : 250, // milliseconds
59restoreSteps : 10,
60restoreDuration : 250,
61marginLeft : 15,
62marginRight : 15,
63marginTop : 15,
64marginBottom : 15,
65zIndexCounter : 1001, // adjust to other absolutely positioned elements
66loadingOpacity : 0.75,
67allowMultipleInstances: true,
68numberOfImagesToPreload : 5,
69outlineWhileAnimating : 2, // 0 = never, 1 = always, 2 = HTML only 
70outlineStartOffset : 3, // ends at 10
71fullExpandPosition : 'bottom right',
72fullExpandOpacity : 1,
73padToMinWidth : false, // pad the popup width to make room for wide caption
74showCredits : true, // you can set this to false if you want
75creditsHref : 'http://vikjavev.no/highslide/',
76enableKeyListener : true,
77transitions : [],
78transitionDuration: 500,
79dimmingOpacity: 0, // Lightbox style dimming background
80dimmingDuration: 50, // 0 for instant dimming
81
82anchor : 'auto', // where the image expands from
83align : 'auto', // position in the client (overrides anchor)
84targetX: null, // the id of a target element
85targetY: null,
86dragByHeading: true,
87minWidth: 200,
88minHeight: 200,
89allowSizeReduction: true, // allow the image to reduce to fit client size. If false, this overrides minWidth and minHeight
90outlineType : 'drop-shadow', // set null to disable outlines
91wrapperClassName : 'highslide-wrapper', // for enhanced css-control
92skin : {
93	controls:
94		'<div class="highslide-controls"><ul>'+
95			'<li class="highslide-previous">'+
96				'<a href="#" title="{hs.lang.previousTitle}">'+
97				'<span>{hs.lang.previousText}</span></a>'+
98			'</li>'+
99			'<li class="highslide-play">'+
100				'<a href="#" title="{hs.lang.playTitle}">'+
101				'<span>{hs.lang.playText}</span></a>'+
102			'</li>'+
103			'<li class="highslide-pause">'+
104				'<a href="#" title="{hs.lang.pauseTitle}">'+
105				'<span>{hs.lang.pauseText}</span></a>'+
106			'</li>'+
107			'<li class="highslide-next">'+
108				'<a href="#" title="{hs.lang.nextTitle}">'+
109				'<span>{hs.lang.nextText}</span></a>'+
110			'</li>'+
111			'<li class="highslide-move">'+
112				'<a href="#" title="{hs.lang.moveTitle}">'+
113				'<span>{hs.lang.moveText}</span></a>'+
114			'</li>'+
115			'<li class="highslide-full-expand">'+
116				'<a href="#" title="{hs.lang.fullExpandTitle}">'+
117				'<span>{hs.lang.fullExpandText}</span></a>'+
118			'</li>'+
119			'<li class="highslide-close">'+
120				'<a href="#" title="{hs.lang.closeTitle}" >'+
121				'<span>{hs.lang.closeText}</span></a>'+
122			'</li>'+
123		'</ul></div>'
124},
125// END OF YOUR SETTINGS
126
127
128// declare internal properties
129preloadTheseImages : [],
130continuePreloading: true,
131expanders : [],
132overrides : [
133	'allowSizeReduction',
134	'anchor',
135	'align',
136	'targetX',
137	'targetY',
138	'outlineType',
139	'outlineWhileAnimating',
140	'captionId',
141	'captionText',
142	'captionEval',
143	'captionOverlay',
144	'headingId',
145	'headingText',
146	'headingEval',
147	'headingOverlay',
148	'dragByHeading',
149	'autoplay',
150	'numberPosition',
151	'transitions',
152	'dimmingOpacity',
153	
154	'wrapperClassName',
155	'minWidth',
156	'minHeight',
157	'maxWidth',
158	'maxHeight',
159	'slideshowGroup',
160	'easing',
161	'easingClose',
162	'fadeInOut',
163	'src'
164],
165overlays : [],
166idCounter : 0,
167oPos : {
168	x: ['leftpanel', 'left', 'center', 'right', 'rightpanel'],
169	y: ['above', 'top', 'middle', 'bottom', 'below']
170},
171mouse: {},
172headingOverlay: {},
173captionOverlay: {},
174faders : [],
175
176slideshows : [],
177
178pendingOutlines : {},
179clones : {},
180ie : (document.all && !window.opera),
181safari : /Safari/.test(navigator.userAgent),
182geckoMac : /Macintosh.+rv:1\.[0-8].+Gecko/.test(navigator.userAgent),
183
184$ : function (id) {
185	return document.getElementById(id);
186},
187
188push : function (arr, val) {
189	arr[arr.length] = val;
190},
191
192createElement : function (tag, attribs, styles, parent, nopad) {
193	var el = document.createElement(tag);
194	if (attribs) hs.setAttribs(el, attribs);
195	if (nopad) hs.setStyles(el, {padding: 0, border: 'none', margin: 0});
196	if (styles) hs.setStyles(el, styles);
197	if (parent) parent.appendChild(el);	
198	return el;
199},
200
201setAttribs : function (el, attribs) {
202	for (var x in attribs) el[x] = attribs[x];
203},
204
205setStyles : function (el, styles) {
206	for (var x in styles) {
207		if (hs.ie && x == 'opacity') {
208			if (styles[x] > 0.99) el.style.removeAttribute('filter');
209			else el.style.filter = 'alpha(opacity='+ (styles[x] * 100) +')';
210		}
211		else el.style[x] = styles[x];
212	}
213},
214
215ieVersion : function () {
216	var arr = navigator.appVersion.split("MSIE");
217	return arr[1] ? parseFloat(arr[1]) : null;
218},
219
220getPageSize : function () {
221	var iebody = document.compatMode && document.compatMode != 'BackCompat' 
222		? document.documentElement : document.body;	
223	
224	
225	var b = document.body;
226	var xScroll = (window.innerWidth && window.scrollMaxX) 
227			? window.innerWidth + window.scrollMaxX :
228				(b.scrollWidth > b.offsetWidth ? b.scrollWidth : b.offsetWidth),
229		yScroll = (window.innerHeight && window.scrollMaxY) 
230			? window.innerHeight + window.scrollMaxY :
231				(b.scrollHeight > b.offsetHeight ? b.scrollHeight : b.offsetHeight),
232		pageWidth = hs.ie ? iebody.scrollWidth :
233			(document.documentElement.clientWidth || self.innerWidth),
234      	pageHeight = hs.ie ? iebody.clientHeight : 
235			(document.documentElement.clientHeight || self.innerHeight);
236	
237	var width = hs.ie ? iebody.clientWidth : 
238			(document.documentElement.clientWidth || self.innerWidth),
239		height = hs.ie ? iebody.clientHeight : self.innerHeight;
240	
241	return {
242		pageWidth: xScroll < pageWidth ? pageWidth : xScroll,
243		pageHeight: yScroll < pageHeight ? pageHeight : yScroll,
244		width: width,
245		height: height,		
246		scrollLeft: hs.ie ? iebody.scrollLeft : pageXOffset,
247		scrollTop: hs.ie ? iebody.scrollTop : pageYOffset
248	}
249},
250
251getPosition : function(el)	{
252	var p = { x: el.offsetLeft, y: el.offsetTop };
253	while (el.offsetParent)	{
254		el = el.offsetParent;
255		p.x += el.offsetLeft;
256		p.y += el.offsetTop;
257		if (el != document.body && el != document.documentElement) {
258			p.x -= el.scrollLeft;
259			p.y -= el.scrollTop;
260		}
261	}
262	return p;
263},
264expand : function(a, params, custom) {
265	if (a.getParams) return params;
266	
267	try {
268		new hs.Expander(a, params, custom);
269		return false;		
270	} catch (e) { return true; }
271},
272getElementByClass : function (el, tagName, className) {
273	var els = el.getElementsByTagName(tagName);
274	for (var i = 0; i < els.length; i++) {
275    	if ((new RegExp(className)).test(els[i].className)) {
276			return els[i];
277		}
278	}
279	return null;
280},
281replaceLang : function(s) {
282	s = s.replace(/\s/g, ' ');
283	var re = /{hs\.lang\.([^}]+)\}/g,
284		matches = s.match(re),
285		lang;
286	for (var i = 0; i < matches.length; i++) {
287		lang = matches[i].replace(re, "$1");
288		if (hs.lang[lang]) s = s.replace(matches[i], hs.lang[lang]);
289	}
290	return s;
291},
292
293
294focusTopmost : function() {
295	var topZ = 0, topmostKey = -1;
296	for (var i = 0; i < hs.expanders.length; i++) {
297		if (hs.expanders[i]) {
298			if (hs.expanders[i].wrapper.style.zIndex && hs.expanders[i].wrapper.style.zIndex > topZ) {
299				topZ = hs.expanders[i].wrapper.style.zIndex;
300				
301				topmostKey = i;
302			}
303		}
304	}
305	if (topmostKey == -1) hs.focusKey = -1;
306	else hs.expanders[topmostKey].focus();
307},
308
309getParam : function (a, param) {
310	a.getParams = a.onclick;
311	var p = a.getParams ? a.getParams() : null;
312	a.getParams = null;
313	
314	return (p && typeof p[param] != 'undefined') ? p[param] : 
315		(typeof hs[param] != 'undefined' ? hs[param] : null);
316},
317
318getSrc : function (a) {
319	var src = hs.getParam(a, 'src');
320	if (src) return src;
321	return a.href;
322},
323
324getNode : function (id) {
325	var node = hs.$(id), clone = hs.clones[id], a = {};
326	if (!node && !clone) return null;
327	if (!clone) {
328		clone = node.cloneNode(true);
329		clone.id = '';
330		hs.clones[id] = clone;
331		return node;
332	} else {
333		return clone.cloneNode(true);
334	}
335},
336
337discardElement : function(d) {
338	hs.garbageBin.appendChild(d);
339	hs.garbageBin.innerHTML = '';
340},
341dim : function(exp) {
342	if (!hs.dimmer) {
343		hs.dimmer = hs.createElement ('div', 
344			{ 
345				className: 'highslide-dimming',
346				owner: '',
347				onclick: function() {
348					 
349						hs.close();
350				}
351			}, 
352			{ position: 'absolute', left: 0 }, hs.container, true);
353		hs.addEventListener(window, 'resize', hs.setDimmerSize);
354	}
355	hs.dimmer.style.display = '';
356	hs.setDimmerSize();
357	hs.dimmer.owner += '|'+ exp.key;
358	if (hs.geckoMac && hs.dimmingGeckoFix) 
359		hs.dimmer.style.background = 'url('+ hs.graphicsDir + 'geckodimmer.png)';		
360	else
361		hs.fade(hs.dimmer, 0, exp.dimmingOpacity, hs.dimmingDuration); 
362},
363undim : function(key) {
364	if (!hs.dimmer) return;
365	if (typeof key != 'undefined') hs.dimmer.owner = hs.dimmer.owner.replace('|'+ key, '');
366	if (
367		(typeof key != 'undefined' && hs.dimmer.owner != '')
368		|| (hs.upcoming && hs.getParam(hs.upcoming, 'dimmingOpacity'))
369	) return;
370	if (hs.geckoMac && hs.dimmingGeckoFix) 
371		hs.dimmer.style.background = 'none';
372	else hs.fade(hs.dimmer, hs.dimmingOpacity, 0, hs.dimmingDuration);
373	setTimeout( function() {
374		hs.setStyles(hs.dimmer, { display: 'none', width: 0, height: 0 });
375	}, hs.dimmingDuration);
376},
377setDimmerSize : function() {
378	if (!hs.dimmer) return;
379	var page = hs.getPageSize();
380	hs.setStyles(hs.dimmer, { width: page.pageWidth +'px', height: page.pageHeight +'px'});
381},
382
383previousOrNext : function (el, op) {
384	hs.updateAnchors();
385	var exp = hs.last = hs.getExpander(el);
386	try {
387		var adj = hs.upcoming =  exp.getAdjacentAnchor(op);
388		adj.onclick(); 		
389	} catch (e){
390		hs.last = hs.upcoming = null;
391	}
392	try { exp.close(); } catch (e) {}
393	return false;
394},
395
396previous : function (el) {
397	return hs.previousOrNext(el, -1);
398},
399
400next : function (el) {
401	return hs.previousOrNext(el, 1);	
402},
403
404keyHandler : function(e) {
405	if (!e) e = window.event;
406	if (!e.target) e.target = e.srcElement; // ie
407	if (e.target.form) return true; // form element has focus
408	
409	var op = null;
410	switch (e.keyCode) {
411		case 32: // Space
412			op = 2;
413			break;
414		case 34: // Page Down
415		case 39: // Arrow right
416		case 40: // Arrow down
417			op = 1;
418			break;
419		case 8:  // Backspace
420		case 33: // Page Up
421		case 37: // Arrow left
422		case 38: // Arrow up
423			op = -1;
424			break;
425		case 27: // Escape
426		case 13: // Enter
427			op = 0;
428	}
429	if (op !== null) {if (op != 2)hs.removeEventListener(document, window.opera ? 'keypress' : 'keydown', hs.keyHandler);
430		if (!hs.enableKeyListener) return true;
431		
432		if (e.preventDefault) e.preventDefault();
433    	else e.returnValue = false;
434    	
435    	var exp = hs.getExpander();
436    	if (exp) {
437			if (op == 0) {
438				exp.close();
439			} else if (op == 2) {
440				if (exp.slideshow) exp.slideshow.hitSpace();
441			} else {
442				if (exp.slideshow) exp.slideshow.pause();
443				hs.previousOrNext(exp.key, op);
444			}
445			return false;
446		}
447	}
448	return true;
449},
450
451
452registerOverlay : function (overlay) {
453	hs.push(hs.overlays, overlay);
454},
455
456
457addSlideshow : function (options) {
458	hs.push(hs.slideshows, options);
459},
460
461getWrapperKey : function (element) {
462	var el, re = /^highslide-wrapper-([0-9]+)$/;
463	// 1. look in open expanders
464	el = element;
465	while (el.parentNode)	{
466		if (el.id && re.test(el.id)) return el.id.replace(re, "$1");
467		el = el.parentNode;
468	}
469	// 2. look in thumbnail
470	el = element;
471	while (el.parentNode)	{
472		if (el.tagName && hs.isHsAnchor(el)) {
473			for (var key = 0; key < hs.expanders.length; key++) {
474				var exp = hs.expanders[key];
475				if (exp && exp.a == el) return key;
476			}
477		}
478		el = el.parentNode;
479	}
480	return null; 
481},
482
483getExpander : function (el) {
484	if (typeof el == 'undefined') return hs.expanders[hs.focusKey] || null;
485	if (typeof el == 'number') return hs.expanders[el] || null;
486	if (typeof el == 'string') el = hs.$(el);
487	return hs.expanders[hs.getWrapperKey(el)] || null;
488},
489
490isHsAnchor : function (a) {
491	return (a.onclick && a.onclick.toString().replace(/\s/g, ' ').match(/hs.(htmlE|e)xpand/));
492},
493
494reOrder : function () {
495	for (var i = 0; i < hs.expanders.length; i++)
496		if (hs.expanders[i] && hs.expanders[i].isExpanded) hs.focusTopmost();
497},
498
499mouseClickHandler : function(e) 
500{	
501	if (!e) e = window.event;
502	if (e.button > 1) return true;
503	if (!e.target) e.target = e.srcElement;
504	
505	var el = e.target;
506	while (el.parentNode
507		&& !(/highslide-(image|move|html|resize)/.test(el.className)))
508	{
509		el = el.parentNode;
510	}
511	var exp = hs.getExpander(el);
512	if (exp && (exp.isClosing || !exp.isExpanded)) return true;
513		
514	if (exp && e.type == 'mousedown') {
515		if (e.target.form) return true;
516		var match = el.className.match(/highslide-(image|move|resize)/);
517		if (match) {
518			hs.dragArgs = { exp: exp , type: match[1], left: exp.x.min, width: exp.x.span, top: exp.y.min, 
519				height: exp.y.span, clickX: e.clientX, clickY: e.clientY };
520			
521			
522			hs.addEventListener(document, 'mousemove', hs.dragHandler);
523			if (e.preventDefault) e.preventDefault(); // FF
524			
525			if (/highslide-(image|html)-blur/.test(exp.content.className)) {
526				exp.focus();
527				hs.hasFocused = true;
528			}
529			return false;
530		}
531	} else if (e.type == 'mouseup') {
532		
533		hs.removeEventListener(document, 'mousemove', hs.dragHandler);
534		
535		if (hs.dragArgs) {
536			if (hs.dragArgs.type == 'image')
537				hs.dragArgs.exp.content.style.cursor = hs.styleRestoreCursor;
538			var hasDragged = hs.dragArgs.hasDragged;
539			
540			if (!hasDragged &&!hs.hasFocused && !/(move|resize)/.test(hs.dragArgs.type)) {
541				exp.close();
542			} 
543			else if (hasDragged || (!hasDragged && hs.hasHtmlexpanders)) {
544				hs.dragArgs.exp.redoShowHide();
545			}
546			if (hasDragged) hs.setDimmerSize();
547			
548			hs.hasFocused = false;
549			hs.dragArgs = null;
550		
551		} else if (/highslide-image-blur/.test(el.className)) {
552			el.style.cursor = hs.styleRestoreCursor;		
553		}
554	}
555	return false;
556},
557
558dragHandler : function(e)
559{
560	if (!hs.dragArgs) return true;
561	if (!e) e = window.event;
562	var a = hs.dragArgs, exp = a.exp;
563	
564	a.dX = e.clientX - a.clickX;
565	a.dY = e.clientY - a.clickY;	
566	
567	var distance = Math.sqrt(Math.pow(a.dX, 2) + Math.pow(a.dY, 2));
568	if (!a.hasDragged) a.hasDragged = (a.type != 'image' && distance > 0)
569		|| (distance > (hs.dragSensitivity || 5));
570	
571	if (a.hasDragged && e.clientX > 5 && e.clientY > 5) {
572		
573		if (a.type == 'resize') exp.resize(a);
574		else exp.move(a);
575	}
576	return false;
577},
578
579wrapperMouseHandler : function (e) {
580	try {
581		if (!e) e = window.event;
582		var over = /mouseover/i.test(e.type); 
583		if (!e.target) e.target = e.srcElement; // ie
584		if (hs.ie) e.relatedTarget = 
585			over ? e.fromElement : e.toElement; // ie
586		var exp = hs.getExpander(e.target);
587		if (!exp || !e.relatedTarget || hs.getExpander(e.relatedTarget) == exp 
588			|| hs.dragArgs) return;
589		for (var i = 0; i < exp.overlays.length; i++) {
590			var o = hs.$('hsId'+ exp.overlays[i]);
591			if (o && o.hideOnMouseOut) {
592				var from = over ? 0 : o.opacity,
593					to = over ? o.opacity : 0;			
594				hs.fade(o, from, to);
595			}
596		}	
597	} catch (e) {}
598},
599
600addEventListener : function (el, event, func) {
601	try {
602		el.addEventListener(event, func, false);
603	} catch (e) {
604		try {
605			el.detachEvent('on'+ event, func);
606			el.attachEvent('on'+ event, func);
607		} catch (e) {
608			el['on'+ event] = func;
609		}
610	} 
611},
612
613removeEventListener : function (el, event, func) {
614	try {
615		el.removeEventListener(event, func, false);
616	} catch (e) {
617		try {
618			el.detachEvent('on'+ event, func);
619		} catch (e) {
620			el['on'+ event] = null;
621		}
622	}
623},
624
625preloadFullImage : function (i) {
626	if (hs.continuePreloading && hs.preloadTheseImages[i] && hs.preloadTheseImages[i] != 'undefined') {
627		var img = document.createElement('img');
628		img.onload = function() { 
629			img = null;
630			hs.preloadFullImage(i + 1);
631		};
632		img.src = hs.preloadTheseImages[i];
633	}
634},
635preloadImages : function (number) {
636	if (number && typeof number != 'object') hs.numberOfImagesToPreload = number;
637	
638	var arr = hs.getAnchors();
639	for (var i = 0; i < arr.images.length && i < hs.numberOfImagesToPreload; i++) {
640		hs.push(hs.preloadTheseImages, hs.getSrc(arr.images[i]));
641	}
642	
643	// preload outlines
644	if (hs.outlineType)	new hs.Outline(hs.outlineType, function () { hs.preloadFullImage(0)} );
645	else
646	
647	hs.preloadFullImage(0);
648	
649	// preload cursor
650	var cur = hs.createElement('img', { src: hs.graphicsDir + hs.restoreCursor });
651},
652
653
654init : function () {
655	if (!hs.container) {
656		hs.container = hs.createElement('div', 
657			null, 
658			{ position: 'absolute', left: 0, top: 0, width: '100%', zIndex: hs.zIndexCounter }, 
659			document.body,
660			true
661		);
662		hs.loading = hs.createElement('a', {
663				className: 'highslide-loading',
664				title: hs.lang.loadingTitle,
665				innerHTML: hs.lang.loadingText,
666				href: 'javascript:;'
667			}, {
668				position: 'absolute',
669				opacity: hs.loadingOpacity,
670				left: '-9999px',
671				zIndex: 1
672			}, hs.container
673		);
674		hs.garbageBin = hs.createElement('div', null, { display: 'none' }, hs.container);
675		
676		// http://www.robertpenner.com/easing/ 
677		Math.linearTween = function (t, b, c, d) {
678			return c*t/d + b;
679		};
680		Math.easeInQuad = function (t, b, c, d) {
681			return c*(t/=d)*t + b;
682		};
683		Math.easeInOutQuad = function (t, b, c, d) {
684			if ((t/=d/2) < 1) return c/2*t*t + b;
685			return -c/2 * ((--t)*(t-2) - 1) + b;
686		};
687		for (var x in hs.langDefaults) hs.lang[x] = hs[x] || hs.lang[x] || hs.langDefaults[x];
688	}
689},
690
691updateAnchors : function() {
692	var els = document.getElementsByTagName('*'), all = [], images = [],groups = {}, re;
693	for (var i = 0; i < els.length; i++) {
694		re = hs.isHsAnchor(els[i]);
695		if (re) {
696			hs.push(all, els[i]);
697			if (re[0] == 'hs.expand') hs.push(images, els[i]);
698			var g = hs.getParam(els[i], 'slideshowGroup') || 'none';
699			if (!groups[g]) groups[g] = [];
700			hs.push(groups[g], els[i]);
701		}
702	}
703	hs.anchors = { all: all, groups: groups, images: images };
704	
705	return hs.anchors;
706},
707
708getAnchors : function() {
709	return hs.anchors || hs.updateAnchors();
710},
711
712
713fade : function (el, o, oFinal, dur, i, dir) {
714	if (typeof i == 'undefined') { // new fader
715		if (typeof dur != 'number') dur = 250;
716		if (dur < 25) { // instant
717			hs.setStyles( el, { opacity: oFinal	});
718			return;
719		}
720		i = hs.faders.length;
721		dir = oFinal > o ? 1 : -1;
722		var step = (25 / (dur - dur % 25)) * Math.abs(o - oFinal);
723	}
724	o = parseFloat(o);
725	var skip = (el.fade === 0 || el.fade === false || (el.fade == 2 && hs.ie));
726	el.style.visibility = ((skip ? oFinal : o) <= 0) ? 'hidden' : 'visible';
727	
728	if (skip || o < 0 || (dir == 1 && o > oFinal)) return;
729	
730	if (el.fading && el.fading.i != i) { // reverse
731		clearTimeout(hs.faders[el.fading.i]);
732		o = el.fading.o;
733	}
734	el.fading = {i: i, o: o, step: (step || el.fading.step)};
735	el.style.visibility = (o <= 0) ? 'hidden' : 'visible';
736	hs.setStyles(el, { opacity: o });
737	hs.faders[i] = setTimeout(function() {
738		hs.fade(el, o + el.fading.step * dir, oFinal, null, i, dir);
739	}, 25);
740},
741
742close : function(el) {
743	var exp = hs.getExpander(el);
744	if (exp) exp.close();
745	return false;
746}
747}; // end hs object
748
749
750//-----------------------------------------------------------------------------
751hs.Outline =  function (outlineType, onLoad) {
752	this.onLoad = onLoad;
753	this.outlineType = outlineType;
754	var v = hs.ieVersion(), tr;
755	
756	this.hasAlphaImageLoader = hs.ie && v >= 5.5 && v < 7;
757	if (!outlineType) {
758		if (onLoad) onLoad();
759		return;
760	}
761	
762	hs.init();
763	this.table = hs.createElement(
764		'table', { cellSpacing: 0 },
765		{
766			visibility: 'hidden',
767			position: 'absolute',
768			borderCollapse: 'collapse'
769		},
770		hs.container,
771		true
772	);
773	var tbody = hs.createElement('tbody', null, null, this.table, 1);
774	
775	this.td = [];
776	for (var i = 0; i <= 8; i++) {
777		if (i % 3 == 0) tr = hs.createElement('tr', null, { height: 'auto' }, tbody, true);
778		this.td[i] = hs.createElement('td', null, null, tr, true);
779		var style = i != 4 ? { lineHeight: 0, fontSize: 0} : { position : 'relative' };
780		hs.setStyles(this.td[i], style);
781	}
782	this.td[4].className = outlineType;
783	
784	this.preloadGraphic(); 
785};
786
787hs.Outline.prototype = {
788preloadGraphic : function () {
789	var src = hs.graphicsDir + (hs.outlinesDir || "outlines/")+ this.outlineType +".png";
790				
791	var appendTo = hs.safari ? hs.container : null;
792	this.graphic = hs.createElement('img', null, { position: 'absolute', left: '-9999px', 
793		top: '-9999px' }, appendTo, true); // for onload trigger
794	
795	var pThis = this;
796	this.graphic.onload = function() { pThis.onGraphicLoad(); };
797	
798	this.graphic.src = src;
799},
800
801onGraphicLoad : function () {
802	var o = this.offset = this.graphic.width / 4,
803		pos = [[0,0],[0,-4],[-2,0],[0,-8],0,[-2,-8],[0,-2],[0,-6],[-2,-2]],
804		dim = { height: (2*o) +'px', width: (2*o) +'px' };
805	hs.discardElement(this.graphic);
806	for (var i = 0; i <= 8; i++) {
807		if (pos[i]) {
808			if (this.hasAlphaImageLoader) {
809				var w = (i == 1 || i == 7) ? '100%' : this.graphic.width +'px';
810				var div = hs.createElement('div', null, { width: '100%', height: '100%', position: 'relative', overflow: 'hidden'}, this.td[i], true);
811				hs.createElement ('div', null, { 
812						filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale, src='"+ this.graphic.src + "')", 
813						position: 'absolute',
814						width: w, 
815						height: this.graphic.height +'px',
816						left: (pos[i][0]*o)+'px',
817						top: (pos[i][1]*o)+'px'
818					}, 
819				div,
820				true);
821			} else {
822				hs.setStyles(this.td[i], { background: 'url('+ this.graphic.src +') '+ (pos[i][0]*o)+'px '+(pos[i][1]*o)+'px'});
823			}
824			
825			if (window.opera && (i == 3 || i ==5)) 
826				hs.createElement('div', null, dim, this.td[i], true);
827			
828			hs.setStyles (this.td[i], dim);
829		}
830	}
831	if (hs.pendingOutlines[this.outlineType]) hs.pendingOutlines[this.outlineType].destroy();
832	hs.pendingOutlines[this.outlineType] = this;
833	if (this.onLoad) this.onLoad();
834},
835	
836setPosition : function (exp, pos, vis) {
837	pos = pos || {
838		x: exp.x.min,
839		y: exp.y.min,
840		w: exp.x.span + exp.x.p1 + exp.x.p2,
841		h: exp.y.span + exp.y.p1 + exp.y.p2
842	};
843	if (vis) this.table.style.visibility = (pos.h >= 4 * this.offset) 
844		? 'visible' : 'hidden';
845	hs.setStyles(this.table, {
846		left: (pos.x - this.offset) +'px',
847		top: (pos.y - this.offset) +'px',
848		width: (pos.w + 2 * (exp.x.cb + this.offset)) +'px'
849	});
850	
851	pos.w += 2 * (exp.x.cb - this.offset);
852	pos.h += + 2 * (exp.y.cb - this.offset);
853	hs.setStyles (this.td[4], {
854		width: pos.w >= 0 ? pos.w +'px' : 0,
855		height: pos.h >= 0 ? pos.h +'px' : 0
856	});
857	if (this.hasAlphaImageLoader) this.td[3].style.height 
858		= this.td[5].style.height = this.td[4].style.height;
859},
860	
861destroy : function(hide) {
862	if (hide) this.table.style.visibility = 'hidden';
863	else hs.discardElement(this.table);
864}
865};
866
867
868//-----------------------------------------------------------------------------
869// The expander object
870hs.Expander = function(a, params, custom, contentType) {
871	this.a = a;
872	this.custom = custom;
873	this.contentType = contentType || 'image';
874	this.isImage = !this.isHtml;
875	
876	hs.continuePreloading = false;
877	this.overlays = [];
878	this.last = hs.last;
879	hs.last = null;
880	hs.init();
881	var key = this.key = hs.expanders.length;
882	
883	// override inline parameters
884	for (var i = 0; i < hs.overrides.length; i++) {
885		var name = hs.overrides[i];
886		this[name] = params && typeof params[name] != 'undefined' ?
887			params[name] : hs[name];
888	}
889	if (!this.src) this.src = a.href;
890	
891	// get thumb
892	var el = (params && params.thumbnailId) ? hs.$(params.thumbnailId) : a;
893	el = this.thumb = el.getElementsByTagName('img')[0] || el;
894	this.thumbsUserSetId = el.id || a.id;
895	
896	// check if already open
897	for (var i = 0; i < hs.expanders.length; i++) {
898		if (hs.expanders[i] && hs.expanders[i].a == a 
899			&& !(this.last && this.transitions[1] == 'crossfade')) {
900			hs.expanders[i].focus();
901			return false;
902		}
903	}	
904	// cancel other
905	for (var i = 0; i < hs.expanders.length; i++) {
906		if (hs.expanders[i] && hs.expanders[i].thumb != el && !hs.expanders[i].onLoadStarted) {
907			hs.expanders[i].cancelLoading();
908		}
909	}
910	hs.expanders[this.key] = this;
911	if (!hs.allowMultipleInstances) {
912		if (hs.expanders[key-1]) hs.expanders[key-1].close();
913		if (typeof hs.focusKey != 'undefined' && hs.expanders[hs.focusKey])
914			hs.expanders[hs.focusKey].close();
915	}
916	
917	var pos = hs.getPosition(el);
918	
919	// initiate metrics
920	var x = this.x = {};
921	x.t = el.width ? parseInt(el.width) : el.offsetWidth;
922	x.tpos = pos.x;
923	x.tb = (el.offsetWidth - x.t) / 2;
924	var y = this.y = {};
925	y.t = el.height ? parseInt(el.height) : el.offsetHeight;
926	y.tpos = pos.y;
927	y.tb = (el.offsetHeight - y.t) / 2;
928	x.p1 = x.p2 = y.p1 = y.p2 = 0;
929	
930	// instanciate the wrapper
931	this.wrapper = hs.createElement(
932		'div',
933		{
934			id: 'highslide-wrapper-'+ this.key,
935			className: this.wrapperClassName
936		},
937		{
938			visibility: 'hidden',
939			position: 'absolute',
940			zIndex: hs.zIndexCounter++
941		}, null, true );
942	
943	this.wrapper.onmouseover = this.wrapper.onmouseout = hs.wrapperMouseHandler;
944	if (this.contentType == 'image' && this.outlineWhileAnimating == 2)
945		this.outlineWhileAnimating = 0;
946	
947	// get the outline
948	if (!this.outlineType 
949		|| (this.last && this.isImage && this.transitions[1] == 'crossfade')) {
950	
951		this[this.contentType +'Create']();
952	
953	} else if (hs.pendingOutlines[this.outlineType]) {
954		this.connectOutline();
955		this[this.contentType +'Create']();
956	
957	} else {
958		this.showLoading();
959		var exp = this;
960		new hs.Outline(this.outlineType, 
961			function () { 
962				exp.connectOutline();
963				exp[exp.contentType +'Create']();
964			} 
965		);
966	}
967	return true;
968};
969
970hs.Expander.prototype = {
971
972connectOutline : function(x, y) {
973	var o = this.outline = hs.pendingOutlines[this.outlineType];
974	o.table.style.zIndex = this.wrapper.style.zIndex;
975	hs.pendingOutlines[this.outlineType] = null;
976},
977
978showLoading : function() {
979	if (this.onLoadStarted || this.loading) return;
980	
981	this.loading = hs.loading;
982	var exp = this;
983	this.loading.onclick = function() {
984		exp.cancelLoading();
985	};
986	var exp = this, 
987		l = (this.x.tpos + this.x.tb 
988			+ (this.x.t - this.loading.offsetWidth) / 2) +'px',
989		t = (this.y.tpos 
990			+ (this.y.t - this.loading.offsetHeight) / 2) +'px';
991	if (!tgt && this.last && this.transitions[1] == 'crossfade') 
992		var tgt = this.last; 
993	if (tgt) {
994		l = (tgt.x.min + tgt.x.cb + tgt.x.p1
995			+ (tgt.x.span - this.loading.offsetWidth) / 2) +'px';
996		t = (tgt.y.min + tgt.y.cb + tgt.y.p1
997			+ (tgt.y.span - this.loading.offsetHeight) / 2) +'px';
998		this.loading.style.zIndex = hs.zIndexCounter++;
999	}
1000	setTimeout(function () { if (exp.loading) hs.setStyles(exp.loading, { left: l, top: t })}, 100); 
1001},
1002
1003imageCreate : function() {
1004	var exp = this;
1005	
1006	var img = document.createElement('img');
1007    this.content = img;
1008    img.onload = function () {
1009    	if (hs.expanders[exp.key]) exp.contentLoaded(); 
1010	};
1011    if (hs.blockRightClick) img.oncontextmenu = function() { return false; };
1012    img.className = 'highslide-image';
1013    hs.setStyles(img, {
1014    	visibility: 'hidden',
1015    	display: 'block',
1016    	position: 'absolute',
1017		maxWidth: '9999px',
1018		zIndex: 3
1019	});
1020    img.title = hs.lang.restoreTitle;
1021    if (hs.safari) hs.container.appendChild(img);
1022    if (hs.ie && hs.flushImgSize) img.src = null;
1023	img.src = this.src;
1024	
1025	this.showLoading();
1026},
1027
1028contentLoaded : function() {
1029	try {	
1030		if (!this.content) return;
1031		this.content.onload = null;
1032		if (this.onLoadStarted) return;
1033		else this.onLoadStarted = true;
1034		
1035		var x = this.x, y = this.y;
1036		
1037		if (this.loading) {
1038			hs.setStyles(this.loading, { left: '-9999px', top: '-9999px' });
1039			this.loading = null;
1040		}
1041		this.marginBottom = hs.marginBottom;	
1042			x.full = this.content.width;
1043			y.full = this.content.height;
1044			
1045			hs.setStyles(this.content, {
1046				width: this.x.t +'px',
1047				height: this.y.t +'px'
1048			});
1049		
1050		this.wrapper.appendChild(this.content);
1051		this.content.style.position = 'relative'; // Saf 
1052		hs.setStyles (this.wrapper, {
1053			left: this.x.tpos +'px',
1054			top: this.y.tpos +'px'
1055		});
1056		hs.container.appendChild(this.wrapper);
1057		
1058		// correct for borders
1059		x.cb = (this.content.offsetWidth - this.x.t) / 2;
1060		y.cb = (this.content.offsetHeight - this.y.t) / 2;
1061		var modMarginRight = hs.marginRight + 2 * x.cb;
1062		this.marginBottom += 2 * y.cb;
1063		this.getOverlays();
1064		this.initSlideshow();
1065		
1066		var ratio = x.full / y.full;
1067		var minWidth = this.allowSizeReduction 
1068			? this.minWidth : x.full;
1069		var minHeight = this.allowSizeReduction 
1070			? this.minHeight : y.full;
1071		
1072		var justify = { x: 'auto', y: 'auto' };
1073		
1074		if (this.align == 'center') {
1075			justify.x = 'center';
1076			justify.y = 'center';
1077		} else {
1078			if (this.anchor.match(/^top/)) justify.y = null;
1079			if (this.anchor.match(/right$/)) justify.x = 'max';
1080			if (this.anchor.match(/^bottom/)) justify.y = 'max';
1081			if (this.anchor.match(/left$/)) justify.x = null;
1082		}
1083		
1084		var page = hs.getPageSize();
1085		// justify
1086		x.min = x.tpos - x.cb + x.tb;
1087		x.span = Math.min(x.full, this.maxWidth || x.full);
1088		x.minSpan = Math.min(x.full, minWidth);
1089		x.justify = justify.x;
1090		x.target = this.targetX;
1091		x.marginMin = hs.marginLeft; 
1092		x.marginMax = modMarginRight;
1093		x.scroll = page.scrollLeft;
1094		x.clientSpan = page.width;
1095		this.justify(x);
1096		
1097		
1098		y.min = y.tpos - y.cb + y.tb;
1099		y.span = Math.min(y.full, this.maxHeight || y.full);
1100		y.minSpan = Math.min(y.full, minHeight);
1101		y.justify = justify.y;
1102		y.target = this.targetY;
1103		y.marginMin = hs.marginTop; 
1104		y.marginMax = this.marginBottom; 
1105		y.scroll = page.scrollTop;
1106		y.clientSpan = page.height;
1107		this.justify(y);
1108		if (this.overlayBox) this.sizeOverlayBox(0, 1);
1109		
1110		
1111		if (this.allowSizeReduction) {
1112				this.correctRatio(ratio);
1113			var ss = this.slideshow;
1114			
1115			if (ss && this.last && ss.fixedControls && ss.useControls) {
1116				var pos = ss.overlayOptions.position || '';
1117				for (var dim in hs.oPos) for (var i = 0; i < 5; i++) {
1118					if (pos.match(hs.oPos[dim][i]))
1119						this[dim].min = this.last[dim].min 
1120							+ (this.last[dim].p1 - this[dim].p1)
1121							+ (this.last[dim].span - this[dim].span) * [0, 0, .5, 1, 1][i]  
1122				}
1123			}
1124			
1125			if (this.isImage && this.x.full > this.x.span) {
1126				this.createFullExpand();
1127				if (this.overlays.length == 1) this.sizeOverlayBox();	
1128			}
1129		}
1130		
1131		this.show();
1132		
1133	} catch (e) {
1134		window.location.href = this.src;
1135	}
1136},
1137
1138justify : function (p, moveOnly) {
1139	var tgt, dim = p == this.x ? 'x' : 'y';
1140	
1141	
1142	if (p.target && p.target.match(/ /)) {
1143		tgt = p.target.split(' ');
1144		p.target = tgt[0];
1145	}
1146	if (p.target && hs.$(p.target)) {
1147		p.min = hs.getPosition(hs.$(p.target))[dim];
1148		if (tgt && tgt[1] && tgt[1].match(/^[-]?[0-9]+px$/)) p.min += parseInt(tgt[1]);
1149		
1150	} else if (p.justify == 'auto' || p.justify == 'center') {
1151	
1152		var hasMovedMin = false;
1153		
1154		var allowReduce = true;
1155		if (p.justify == 'center') p.min = Math.round(p.scroll + (p.clientSpan - p.span - p.marginMax - p.p1 - p.p2) / 2);
1156		else
1157			p.min = Math.round(p.min - ((p.span + p.p1 + p.p2 - p.t) / 2));
1158		if (p.min < p.scroll + p.marginMin) {
1159			p.min = p.scroll + p.marginMin;
1160			hasMovedMin = true;		
1161		}
1162		if (!moveOnly && p.span < p.minSpan) {
1163			p.span = p.minSpan;
1164			allowReduce = false;
1165		}
1166		if (p.min + p.span + p.p1 + p.p2 > p.scroll + p.clientSpan - p.marginMax) {
1167			if (!moveOnly && hasMovedMin && allowReduce) {
1168				p.span = p.clientSpan - p.marginMin - p.marginMax; // can't expand more
1169			} else if (p.span + p.p1 + p.p2 < p.clientSpan - p.marginMin - p.marginMax) { // move newTop up
1170				p.min = p.scroll + p.clientSpan - p.span - p.marginMin - p.marginMax - p.p1 - p.p2;
1171			} else { // image larger than viewport
1172				p.min = p.scroll + p.marginMin;
1173				if (!moveOnly && allowReduce) p.span = p.clientSpan - p.marginMin - p.marginMax;
1174			}
1175			
1176		}
1177		
1178		if (!moveOnly && p.span < p.minSpan) {
1179			p.span = p.minSpan;
1180			allowReduce = false;
1181		}
1182		
1183	
1184	} else if (p.justify == 'max') {
1185		p.min = Math.floor(p.min - p.span + p.t);
1186	}
1187	
1188		
1189	if (p.min < p.marginMin) {
1190		tmpMin = p.min;
1191		p.min = p.marginMin; 
1192		
1193		if (allowReduce && !moveOnly) p.span = p.span - (p.min - tmpMin);
1194		
1195	}
1196},
1197
1198correctRatio : function(ratio) {
1199		
1200	var x = this.x, y = this.y;
1201	var changed = false;
1202	if (x.span / y.span > ratio) { // width greater
1203		x.span = y.span * ratio;
1204		if (x.span < x.minSpan) { // below minWidth
1205			x.span = x.minSpan;
1206			y.span = x.span / ratio;
1207		}
1208		changed = true;
1209	
1210	} else if (x.span / y.span < ratio) { // height greater
1211		var tmpHeight = y.span;
1212		y.span = x.span / ratio;
1213		changed = true;
1214	}
1215	if (this.overlayBox) {
1216		while (y.span > this.minHeight && x.span > this.minWidth 
1217				&& y.marginMin + y.p1 + y.span + y.p2 + y.marginMax > y.clientSpan) {
1218			var o;
1219			y.span -= 10;
1220			x.span = y.span * ratio;
1221			this.sizeOverlayBox(0, 1);
1222		}
1223	}
1224	if (changed) {
1225		x.min = x.tpos - x.cb + x.tb;
1226		x.minSpan = x.span;
1227		this.justify(x, true);
1228	
1229		y.min = y.tpos - y.cb + y.tb;
1230		y.minSpan = y.span;
1231		this.justify(y, true);
1232		if (this.overlayBox) this.sizeOverlayBox();
1233	}
1234},
1235
1236show : function () {
1237	
1238	// Selectbox bug
1239	var imgPos = {x: this.x.min - 20, y: this.y.min - 20, w: this.x.span + 40, 
1240		h: this.y.span + 40 };
1241	hs.hideSelects = (hs.ie && hs.ieVersion() < 7);
1242	if (hs.hideSelects) this.showHideElements('SELECT', 'hidden', imgPos);
1243	// Iframes bug
1244	hs.hideIframes = ((window.opera && navigator.appVersion < 9) || navigator.vendor == 'KDE' 
1245		|| (hs.ie && hs.ieVersion() < 5.5));
1246	if (hs.hideIframes) this.showHideElements('IFRAME', 'hidden', imgPos);
1247	// Scrollbars bug
1248	if (hs.geckoMac) this.showHideElements('*', 'hidden', imgPos); 
1249	
1250		
1251	// Apply size change
1252	this.changeSize(
1253		1,
1254		{ 
1255			xmin: this.x.tpos + this.x.tb - this.x.cb,
1256			ymin: this.y.tpos + this.y.tb - this.y.cb,
1257			xspan: this.x.t,
1258			yspan: this.y.t,
1259			xp1: 0,
1260			xp2: 0,
1261			yp1: 0,
1262			yp2: 0,
1263			o: hs.outlineStartOffset
1264		},
1265		{
1266			xmin: this.x.min,
1267			ymin: this.y.min,
1268			xspan: this.x.span,
1269			yspan: this.y.span,
1270			xp1: this.x.p1,
1271			yp1: this.y.p1,
1272			xp2: this.x.p2,
1273			yp2: this.y.p2,
1274			o: this.outline ? this.outline.offset : 0
1275		},
1276		hs.expandDuration,
1277		hs.expandSteps
1278	);
1279},
1280
1281changeSize : function(up, from, to, dur, steps) {
1282	// transition
1283	var trans = this.transitions,
1284	other = up ? (this.last ? this.last.a : null) : hs.upcoming,
1285	t = (trans[1] && other 
1286			&& hs.getParam(other, 'transitions')[1] == trans[1]) ?
1287		trans[1] : trans[0];
1288		
1289	
1290	if (this[t] && t != 'expand') {
1291		this[t](up, from, to); 
1292		return;
1293	}
1294	
1295	if (up) hs.setStyles(this.wrapper, { opacity: 1 });
1296	
1297	if (this.outline && !this.outlineWhileAnimating) {
1298		if (up) this.outline.setPosition(this);
1299		else this.outline.destroy();
1300	}
1301	
1302	
1303	if (!up && this.overlayBox) {
1304		hs.discardElement(this.overlayBox);
1305		
1306	}
1307	if (this.fadeInOut) {
1308		from.op = up ? 0 : 1;
1309		to.op = up;
1310	}
1311	var t,
1312	exp = this,
1313	easing = Math[this.easing] || Math.easeInQuad;
1314	if (!up) easing = Math[this.easingClose] || easing;
1315	
1316	for (var i = 1; i <= steps; i++) {
1317		t = Math.round(i * (dur / steps));
1318		
1319		(function(){
1320			var pI = i, size = {};
1321			
1322			for (var x in from) {
1323				size[x] = easing(t, from[x], to[x] - from[x], dur);
1324				if (!/^op$/.test(x)) size[x] = Math.round(size[x]);
1325			}
1326			setTimeout ( function() {
1327				if (up && pI == 1) {
1328					exp.content.style.visibility = 'visible';
1329					exp.a.className += ' highslide-active-anchor';
1330				}
1331				exp.setSize(size);
1332			}, t);				
1333		})();		
1334	}
1335	
1336	if (up) { 
1337			
1338		setTimeout(function() {
1339			if (exp.outline) exp.outline.table.style.visibility = "visible";
1340		}, t);
1341		setTimeout(function() {
1342			exp.afterExpand();
1343		}, t + 50);
1344	}
1345	else setTimeout(function() { exp.afterClose(); }, t);
1346		
1347},
1348
1349setSize : function (to) {
1350	try {		
1351		if (to.op) hs.setStyles(this.wrapper, { opacity: to.op });
1352		hs.setStyles ( this.wrapper, {
1353			width : (to.xspan +to.xp1 + to.xp2 +
1354				2 * this.x.cb) +'px',
1355			height : (to.yspan +to.yp1 + to.yp2 +
1356				2 * this.y.cb) +'px',
1357			left: to.xmin +'px',
1358			top: to.ymin +'px'
1359		});
1360		hs.setStyles(this.content, {
1361			top: to.yp1 +'px',
1362			left: to.xp1 +'px',
1363			width: to.xspan +'px',
1364			height: to.yspan +'px'
1365		});
1366		
1367		if (this.outline && this.outlineWhileAnimating) {
1368			var o = this.outline.offset - to.o;
1369			this.outline.setPosition(this, {
1370				x: to.xmin + o, 
1371				y: to.ymin + o, 
1372				w: to.xspan + to.xp1 + to.xp2 + - 2 * o, 
1373				h: to.yspan + to.yp1 + to.yp2 + - 2 * o
1374			}, 1);
1375		}
1376			
1377		this.wrapper.style.visibility = 'visible';
1378		
1379	} catch (e) {
1380		window.location.href = this.src;	
1381	}
1382},
1383
1384fade : function(up, from, to) {
1385	this.outlineWhileAnimating = false;
1386	var exp = this,	t = up ? 250 : 0;
1387	
1388	if (up) {
1389		hs.setStyles(this.wrapper, { opacity: 0 });
1390		this.setSize(to);
1391		this.content.style.visibility = 'visible';
1392
1393		hs.fade (this.wrapper, 0, 1);
1394	}
1395	
1396	if (this.outline) {
1397		this.outline.table.style.zIndex = this.wrapper.style.zIndex;
1398		var dir = up || -1;
1399		for (var i = from.o; dir * i <= dir * to.o; i += dir, t += 25) {
1400			(function() {
1401				var o = up ? to.o - i : from.o - i;
1402				setTimeout(function() {
1403					exp.outline.setPosition(exp, {
1404						x: (exp.x.min + o), 
1405						y: (exp.y.min + o),
1406						w: (exp.x.span - 2 * o + exp.x.p1 + exp.x.p2), 
1407						h: (exp.y.span - 2 * o + exp.y.p1 + exp.y.p2)
1408					}, 1);
1409				}, t);
1410			})();
1411		}
1412	}
1413	
1414	
1415	if (up) setTimeout(function() { exp.afterExpand(); }, t+50);
1416	else {
1417		setTimeout( function() {
1418			if (exp.outline) exp.outline.destroy(exp.preserveContent);
1419			hs.fade (exp.wrapper, 1, 0);
1420			setTimeout( function() {
1421				exp.afterClose();
1422			}, 250);
1423		}, t);		
1424	}
1425},
1426
1427crossfade : function (up, from, to) {
1428	if (!up) return;
1429	var exp = this, steps = parseInt(hs.transitionDuration / 25), last = this.last;
1430	hs.removeEventListener(document, 'mousemove', hs.dragHandler);
1431	
1432	hs.setStyles(this.content, { 
1433		width: to.xspan +'px', 
1434		height: to.yspan +'px'		
1435	});
1436	this.outline = this.last.outline;
1437	this.last.outline = null;
1438	this.fadeBox = hs.createElement('div', 
1439		{ className: 'highslide-image' },
1440		{ 
1441			position: 'absolute', 
1442			zIndex: 4,
1443			overflow: 'hidden',
1444			display: 'none'
1445		}
1446	);
1447	var names = { oldImg: last, newImg: this };
1448	for (var x in names) { 	
1449		this[x] = names[x].content.cloneNode(1);
1450		hs.setStyles(this[x], {
1451			position: 'absolute',
1452			border: 0,
1453			visibility: 'visible'
1454		});
1455		this.fadeBox.appendChild(this[x]);
1456	}
1457	this.wrapper.appendChild(this.fadeBox);
1458	
1459	from = {
1460		xmin: last.x.min,
1461		xspan: last.x.span,
1462		xp1: last.x.p1,
1463		xp2: last.x.p2,
1464		ymin: last.y.min,
1465		yspan: last.y.span,
1466		yp1: last.y.p1,
1467		yp2: last.y.p2,
1468		o: 1 / steps
1469	};
1470	
1471	to.yspan = this.y.span;
1472	to.o = 1;
1473	var t, easing = Math.easeInOutQuad;
1474	
1475	this.crossfadeStep(from);
1476	function prep() {
1477		if (exp.overlayBox) {
1478			exp.wrapper.appendChild(exp.overlayBox);
1479				
1480			for (var i = 0; i < exp.last.overlays.length; i++) {
1481				var oDiv = hs.$('hsId'+ exp.last.overlays[i]);
1482				if (oDiv.reuse === exp.key) exp.overlayBox.appendChild(oDiv);
1483				else hs.fade(oDiv, oDiv.opacity, 0);
1484			}
1485		}
1486		exp.fadeBox.style.display = '';
1487		exp.last.content.style.display = 'none';
1488	};
1489	if (/rv:1\.[0-8].+Gecko/.test(navigator.userAgent)) setTimeout(prep, 0);
1490	else prep();
1491	
1492	for (var i = 1; i <= steps; i++) {
1493		t = Math.round(i * (hs.transitionDuration / steps));
1494		
1495		(function(){
1496			var size = {}, pI = i;
1497			for (var x in from)	{
1498				var val = easing(t, from[x], to[x] - from[x], hs.transitionDuration);
1499				size[x] = (x != 'o') ? Math.round(val) : val;
1500			}
1501			
1502			setTimeout ( function() {
1503				exp.crossfadeStep(size);
1504			}, t);				
1505		})();
1506	}
1507	setTimeout ( function () {
1508		exp.crossfadeEnd();
1509	}, t + 100);
1510
1511},
1512
1513crossfadeStep : function (size) {
1514	try {
1515		if (this.outline) this.outline.setPosition(this, { 
1516			x: size.xmin, 
1517			y: size.ymin, 
1518			w: size.xspan + size.xp1 + size.xp2, 
1519			h: size.yspan + size.yp1 + size.yp2
1520		}, 1);
1521		this.last.wrapper.style.clip = 'rect('
1522			+ (size.ymin - this.last.y.min)+'px, '
1523			+ (size.xspan + size.xp1 + size.xp2 + 2 * this.last.x.cb + size.xmin - this.last.x.min) +'px, '
1524			+ (size.yspan + size.yp1 + size.yp2 + 2 * this.last.y.cb + size.ymin - this.last.y.min) +'px, '
1525			+ (size.xmin - this.last.x.min)+'px)';
1526			
1527		hs.setStyles(this.content, {
1528			top: size.yp1 +'px',
1529			left: size.xp1 +'px',
1530			marginTop: (this.y.min - size.ymin) +'px',
1531			marginLeft: (this.x.min - size.xmin) +'px'
1532		});
1533		
1534		hs.setStyles(this.wrapper, {
1535			top: size.ymin +'px',
1536			left: size.xmin +'px',
1537			width: (size.xp1 + size.xp2 + size.xspan + 2 * this.x.cb)+ 'px',
1538			height: (size.yp1 + size.yp2 + size.yspan + 2 * this.y.cb) + 'px'
1539		});
1540			
1541		hs.setStyles(this.fadeBox, {
1542			width: size.xspan + 'px',
1543			height: size.yspan +'px',
1544			left: size.xp1 +'px',
1545			top: size.yp1 +'px',
1546			visibility: 'visible'
1547		});
1548		
1549		hs.setStyles(this.oldImg, {
1550			top: (this.last.y.min - size.ymin + this.last.y.p1 - size.yp1)+'px',
1551			left: (this.last.x.min - size.xmin + this.last.x.p1 - size.xp1)+'px'
1552		});		
1553		
1554		hs.setStyles(this.newImg, {
1555			opacity: size.o,
1556			top: (this.y.min - size.ymin + this.y.p1 - size.yp1) +'px',
1557			left: (this.x.min - size.xmin + this.x.p1 - size.xp1) +'px'
1558		});
1559		hs.setStyles(this.overlayBox, {
1560			width: size.xspan + 'px',
1561			height: size.yspan +'px',
1562			left: (size.xp1 + this.x.cb)  +'px',
1563			top: (size.yp1 + this.y.cb) +'px'
1564		});
1565	} catch (e) {}
1566},
1567crossfadeEnd : function() {
1568	this.wrapper.style.background = this.wrapperBG || '';
1569	
1570	this.wrapper.style.visibility = this.content.style.visibility = 'visible';
1571	this.fadeBox.style.display = 'none';
1572	this.a.className += ' highslide-active-anchor';
1573	this.afterExpand();
1574	this.last.afterClose();
1575},
1576reuseOverlay : function(o, el) {
1577	if (!this.last) return false;
1578	for (var i = 0; i < this.last.overlays.length; i++) {
1579		var oDiv = hs.$('hsId'+ this.last.overlays[i]);
1580		if (oDiv && oDiv.hsId == o.hsId) {
1581			this.genOverlayBox();
1582			oDiv.reuse = this.key;
1583			hs.push(this.overlays, this.last.overlays[i]);
1584			return true;
1585		}
1586	}
1587	return false;
1588},
1589
1590
1591afterExpand : function() {
1592	this.isExpanded = true;	
1593	this.focus();
1594	
1595	if (this.dimmingOpacity) hs.dim(this);
1596	if (hs.upcoming && hs.upcoming == this.a) hs.upcoming = null;
1597	this.prepareNextOutline();
1598	
1599	
1600	if (this.overlayBox) this.showOverlays();
1601	
1602},
1603
1604
1605prepareNextOutline : function() {
1606	var key = this.key;
1607	var outlineType = this.outlineType;
1608	new hs.Outline(outlineType, 
1609		function () { try { hs.expanders[key].preloadNext(); } catch (e) {} });
1610},
1611
1612
1613preloadNext : function() {
1614	var next = this.getAdjacentAnchor(1);
1615	if (next && next.onclick.toString().match(/hs\.expand/)) 
1616		var img = hs.createElement('img', { src: hs.getSrc(next) });
1617},
1618
1619
1620getAdjacentAnchor : function(op) {
1621	var current = this.getAnchorIndex(), as = hs.anchors.groups[this.slideshowGroup || 'none'];
1622	
1623	/*< ? if ($cfg->slideshow) : ?>s*/
1624	if (!as[current + op] && this.slideshow && this.slideshow.repeat) {
1625		if (op == 1) return as[0];
1626		else if (op == -1) return as[as.length-1];
1627	}
1628	/*< ? endif ?>s*/
1629	return as[current + op] || null;
1630},
1631
1632getAnchorIndex : function() {
1633	var arr = hs.anchors.groups[this.slideshowGroup || 'none'];
1634	for (var i = 0; i < arr.length; i++) {
1635		if (arr[i] == this.a) return i; 
1636	}
1637	return null;
1638},
1639
1640
1641getNumber : function() {
1642	if (this[this.numberPosition]) {
1643		var arr = hs.anchors.groups[this.slideshowGroup || 'none'];
1644		var s = hs.lang.number.replace('%1', this.getAnchorIndex() + 1).replace('%2', arr.length);
1645		this[this.numberPosition].innerHTML = 
1646			'<div class="highslide-number">'+ s +'</div>'+ this[this.numberPosition].innerHTML;
1647	}
1648},
1649initSlideshow : function() {
1650	if (this.slideshow) return;
1651	
1652	if (!this.last) {
1653		for (var i = 0; i < hs.slideshows.length; i++) {
1654			var ss = hs.slideshows[i], sg = ss.slideshowGroup;
1655			if (sg === this.slideshowGroup) {
1656				this.slideshow = new hs.Slideshow(ss);
1657			}
1658		} 
1659	} else {
1660		this.slideshow = this.last.slideshow;
1661	}
1662	var ss = this.slideshow;
1663	if (!ss) return;
1664	var exp = ss.exp = this;
1665	
1666	ss.checkFirstAndLast();
1667	
1668	if (ss.useControls) {
1669		var o = ss.overlayOptions || {};
1670		o.overlayId = ss.controls;
1671		o.hsId = 'controls';
1672		this.createOverlay(o);
1673	}
1674	if (!this.last && this.autoplay) ss.play(true);
1675	if (ss.autoplay) {
1676		ss.autoplay = setTimeout(function() {
1677			hs.next(exp.key);
1678		}, (ss.interval || 500));
1679	}
1680},
1681
1682cancelLoading : function() {	
1683	hs.expanders[this.key] = null;
1684	if (hs.upcoming == this.a) hs.upcoming = null;
1685	hs.undim();
1686	if (this.loading) hs.loading.style.left = '-9999px';
1687},
1688
1689writeCredits : function () {
1690	if (this.credits) return;
1691	this.credits = hs.createElement('a',
1692		{
1693			href: hs.creditsHref,
1694			className: 'highslide-credits',
1695			innerHTML: hs.lang.creditsText,
1696			title: hs.lang.creditsTitle
1697		}
1698	);
1699	this.createOverlay({ 
1700		overlayId: this.credits, 
1701		position: 'top left', 
1702		hsId: 'credits' 
1703	});
1704},
1705
1706getInline : function(types, addOverlay) {
1707	for (var i = 0; i < types.length; i++) {
1708		var type = types[i], s = null;
1709		if (!this[type +'Id'] && this.thumbsUserSetId)  
1710			this[type +'Id'] = type +'-for-'+ this.thumbsUserSetId;
1711		if (this[type +'Id']) this[type] = hs.getNode(this[type +'Id']);
1712		if (!this[type] && !this[type +'Text'] && this[type +'Eval']) try {
1713			s = eval(this[type +'Eval']);
1714		} catch (e) {}
1715		if (!this[type] && this[type +'Text']) {
1716			s = this[type +'Text'];
1717		}
1718		if (!this[type] && !s) {
1719			var next = this.a.nextSibling;
1720			while (next && !hs.isHsAnchor(next)) {
1721				if ((new RegExp('highslide-'+ type)).test(next.className || null)) {
1722					this[type] = next.cloneNode(1);
1723					break;
1724				}
1725				next = next.nextSibling;
1726			}
1727		}
1728		if (!this[type] && !s && this.numberPosition == type) s = '\n';
1729		
1730		if (!this[type] && s) this[type] = hs.createElement('div', 
1731				{ className: 'highslide-'+ type, innerHTML: s } );
1732				
1733		if (addOverlay && this[type]) {
1734			var o = { position: (type == 'heading') ? 'above' : 'below' };
1735			for (var x in this[type+'Overlay']) o[x] = this[type+'Overlay'][x];
1736			o.overlayId = this[type];
1737			this.createOverlay(o);
1738		}
1739	}
1740},
1741
1742
1743showHideElements : function (tagName, visibility, imgPos) {
1744	var els = document.getElementsByTagName(tagName);
1745	var prop = tagName == '*' ? 'overflow' : 'visibility';
1746	for (var i = 0; i < els.length; i++) {
1747		if (prop == 'visibility' || (document.defaultView.getComputedStyle(
1748				els[i], "").getPropertyValue('overflow') == 'auto'
1749				|| els[i].getAttribute('hidden-by') != null)) {
1750			var hiddenBy = els[i].getAttribute('hidden-by');
1751			if (visibility == 'visible' && hiddenBy) {
1752				hiddenBy = hiddenBy.replace('['+ this.key +']', '');
1753				els[i].setAttribute('hidden-by', hiddenBy);
1754				if (!hiddenBy) els[i].style[prop] = els[i].origProp;
1755			} else if (visibility == 'hidden') { // hide if behind
1756				var elPos = hs.getPosition(els[i]);
1757				elPos.w = els[i].offsetWidth;
1758				elPos.h = els[i].offsetHeight;
1759				if (!this.dimmingOpacity) { // hide all if dimming
1760				
1761					var clearsX = (elPos.x + elPos.w < imgPos.x || elPos.x > imgPos.x + imgPos.w);
1762					var clearsY = (elPos.y + elPos.h < imgPos.y || elPos.y > imgPos.y + imgPos.h);
1763				}
1764				var wrapperKey = hs.getWrapperKey(els[i]);
1765				if (!clearsX && !clearsY && wrapperKey != this.key) { // element falls behind image
1766					if (!hiddenBy) {
1767						els[i].setAttribute('hidden-by', '['+ this.key +']');
1768						els[i].origProp = els[i].style[prop];
1769						els[i].style[prop] = 'hidden';
1770					} else if (!hiddenBy.match('['+ this.key +']')) {
1771						els[i].setAttribute('hidden-by', hiddenBy + '['+ this.key +']');
1772					}
1773				} else if (hiddenBy == '['+ this.key +']' || hs.focusKey == wrapperKey) { // on move
1774					els[i].setAttribute('hidden-by', '');
1775					els[i].style[prop] = els[i].origProp || '';
1776				} else if (hiddenBy && hiddenBy.match('['+ this.key +']')) {
1777					els[i].setAttribute('hidden-by', hiddenBy.replace('['+ this.key +']', ''));
1778				}
1779						
1780			}
1781		}
1782	}
1783},
1784
1785focus : function() {
1786	this.wrapper.style.zIndex = hs.zIndexCounter++;
1787	// blur others
1788	for (var i = 0; i < hs.expanders.length; i++) {
1789		if (hs.expanders[i] && i == hs.focusKey) {
1790			var blurExp = hs.expanders[i];
1791			blurExp.content.className += ' highslide-'+ blurExp.contentType +'-blur';
1792				blurExp.content.style.cursor = hs.ie ? 'hand' : 'pointer';
1793				blurExp.content.title = hs.lang.focusTitle;
1794		}
1795	}
1796	
1797	// focus this
1798	if (this.outline) this.outline.table.style.zIndex 
1799		= this.wrapper.style.zIndex;
1800	this.content.className = 'highslide-'+ this.contentType;
1801		this.content.title = hs.lang.restoreTitle;
1802		
1803		hs.styleRestoreCursor = window.opera ? 'pointer' : 'url('+ hs.graphicsDir + hs.restoreCursor +'), pointer';
1804		if (hs.ie && hs.ieVersion() < 6) hs.styleRestoreCursor = 'hand';
1805		this.content.style.cursor = hs.styleRestoreCursor;
1806		
1807	hs.focusKey = this.key;	
1808	hs.addEventListener(document, window.opera ? 'keypress' : 'keydown', hs.keyHandler);	
1809},
1810
1811move : function (e) {
1812	this.x.min = e.left + e.dX;
1813	this.y.min = e.top + e.dY;
1814	
1815	if (e.type == 'image') this.content.style.cursor = 'move';
1816	hs.setStyles(this.wrapper, { left: this.x.min +'px', top: this.y.min +'px' });
1817	
1818	if (this.outline) this.outline.setPosition(this);
1819	
1820},
1821resize : function (e) {
1822	var w, h, r = e.width / e.height;
1823	w = Math.max(e.width + e.dX, Math.min(this.minWidth, this.x.full));
1824	if (this.isImage && Math.abs(w - this.x.full) < 12) w = this.x.full;
1825	h = w / r;
1826	
1827	if (h < Math.min(this.minHeight, this.y.full)) {
1828		h = Math.min(this.minHeight, this.y.full);
1829		if (this.isImage) w = h * r;
1830	}
1831	
1832	this.x.span = w;
1833	this.y.span = h;
1834	var size = { width: this.x.span +'px', height: this.y.span +'px' };
1835	hs.setStyles(this.content, size);
1836	if (this.overlayBox) this.sizeOverlayBox(true);
1837	hs.setStyles(this.wrapper, {
1838		width: (this.x.p1 + this.x.p2 +2 * this.x.cb + this.x.span) +'px',
1839		height: (this.y.p1 + this.y.p2 +2 * this.y.cb + this.y.span) +'px'
1840	});
1841	if (this.slideshow && this.isImage) {
1842		if (w == this.x.full) this.slideshow.disable('full-expand');
1843		else this.slideshow.enable('full-expand');
1844	}
1845	if (this.outline) this.outline.setPosition(this);
1846	
1847},
1848
1849close : function() {
1850	if (this.isClosing || !this.isExpanded
1851		 || (hs.upcoming && this.transitions[1] == 'crossfade')
1852		) return;
1853	this.isClosing = true;
1854	if (this.slideshow && !hs.upcoming) this.slideshow.pause();
1855	
1856	hs.removeEventListener(document, window.opera ? 'keypress' : 'keydown', hs.keyHandler);
1857	
1858	try {
1859		this.content.style.cursor = 'default';
1860		this.changeSize(
1861			0,
1862			{
1863				xmin: this.x.min,
1864				ymin: this.y.min,
1865				xspan: this.x.span,
1866				yspan: parseInt(this.content.style.height),
1867				xp1: this.x.p1,
1868				yp1: this.y.p1,
1869				xp2: this.x.p2,
1870				yp2: this.y.p2,
1871				o: this.outline ? this.outline.offset : 0
1872			},
1873			{
1874				xmin: this.x.tpos - this.x.cb + this.x.tb,
1875				ymin: this.y.tpos - this.y.cb + this.y.tb,
1876				xspan: this.x.t,
1877				yspan: this.y.t,
1878				xp1: 0,
1879				yp1: 0,
1880				xp2: 0,
1881				yp2: 0,
1882				o: hs.outlineStartOffset
1883			},
1884			hs.restoreDuration,
1885			hs.restoreSteps
1886		);
1887		
1888	} catch (e) { this.afterClose(); } 
1889},
1890
1891createOverlay : function (o) {
1892	var el = o.overlayId;
1893	if (typeof el == 'string') el = hs.getNode(el);
1894	if (!el || typeof el == 'string') return;
1895	el.style.display = 'block';
1896	o.hsId = o.hsId || o.overlayId; 
1897	if (this.transitions[1] == 'crossfade' && this.reuseOverlay(o, el)) return;
1898	this.genOverlayBox();
1899	var width = o.width && /^[0-9]+(px|%)$/.test(o.width) ? o.width : 'auto';
1900	if (/^(left|right)panel$/.test(o.position) && !/^[0-9]+px$/.test(o.width)) width = '200px';
1901	
1902	var overlay = hs.createElement(
1903		'div',
1904		{ id: 'hsId'+ hs.idCounter++, hsId: o.hsId },
1905		{
1906			position: 'absolute',
1907			width: width
1908		},
1909		this.overlayBox,
1910		true
1911	);
1912	
1913	overlay.appendChild(el);
1914	if (o.hideOnMouseOut) overlay.hideOnMouseOut = true;
1915	overlay.opacity = o.opacity || 1;
1916	overlay.hsPos = o.position;
1917	overlay.fade = o.fade;
1918	
1919	if (this.gotOverlays) {
1920		this.positionOverlay(overlay);
1921		if (!overlay.hideOnMouseOut || this.mouseIsOver) hs.fade(overlay, 0, overlay.opacity);
1922	}
1923	hs.push(this.overlays, hs.idCounter - 1);
1924},
1925positionOverlay : function(overlay) {
1926	var p = overlay.hsPos || 'middle center';
1927	if (/left$/.test(p)) overlay.style.left = 0; 
1928	if (/center$/.test(p))	hs.setStyles (overlay, { 
1929		left: '50%',
1930		marginLeft: '-'+ Math.round(overlay.offsetWidth / 2) +'px'
1931	});	
1932	if (/right$/.test(p))	overlay.style.right = 0;
1933	
1934	if (/^leftpanel$/.test(p)) { 
1935		hs.setStyles(overlay, {
1936			right: '100%',
1937			marginRight: this.x.cb +'px',
1938			top: - this.y.cb +'px',
1939			bottom: - this.y.cb +'px',
1940			overflow: 'auto'
1941		});		 
1942		this.x.p1 = overlay.offsetWidth;
1943	
1944	} else if (/^rightpanel$/.test(p)) {
1945		hs.setStyles(overlay, {
1946			left: '100%',
1947			marginLeft: this.x.cb +'px',
1948			top: - this.y.cb +'px',
1949			bottom: - this.y.cb +'px',
1950			overflow: 'auto'
1951		});
1952		this.x.p2 = overlay.offsetWidth;
1953	}
1954	if (/^top/.test(p)) overlay.style.top = 0; 
1955	if (/^middle/.test(p))	hs.setStyles (overlay, { 
1956		top: '50%', 
1957		marginTop: '-'+ Math.round(overlay.offsetHeight / 2) +'px'
1958	});	
1959	if (/^bottom/.test(p)) overlay.style.bottom = 0;
1960	if (/^above$/.test(p)) {
1961		hs.setStyles(overlay, {
1962			left: (- this.x.p1 - this.x.cb) +'px',
1963			right: (- this.x.p2 - this.x.cb) +'px',
1964			bottom: '100%',
1965			marginBottom: this.y.cb +'px',
1966			width: 'auto'
1967		});
1968		this.y.p1 = overlay.offsetHeight;
1969	
1970	} else if (/^below$/.test(p)) {
1971		hs.setStyles(overlay, {
1972			left: (- this.x.p1 - this.x.cb) +'px',
1973			right: (- this.x.p2 - this.x.cb) +'px',
1974			top: '100%',
1975			marginTop: this.y.cb +'px',
1976			width: 'auto'
1977		});
1978		this.y.p2 = overlay.offsetHeight;	
1979	}
1980},
1981
1982getOverlays : function() {	
1983	this.getInline(['heading', 'caption'], true);
1984	this.getNumber();
1985	if (this.heading && this.dragByHeading) this.heading.className += ' highsli
1985de-move';
1986	if (hs.showCredits) this.writeCredits();
1987	for (var i = 0; i < hs.overlays.length; i++) {
1988		var o = hs.overlays[i], tId = o.thumbnailId, sg = o.slideshowGroup;
1989		if ((!tId && !sg) || (tId && tId == this.thumbsUserSetId)
1990				|| (sg && sg === this.slideshowGroup)) {
1991			this.createOverlay(o);
1992		}
1993	}
1994	var os = [];
1995	for (var i = 0; i < this.overlays.length; i++) {
1996		var o = hs.$('hsId'+ this.overlays[i]);
1997		if (/panel$/.test(o.hsPos)) this.positionOverlay(o);
1998		else hs.push(os, o);
1999	}
2000	var curW = this.x.p1 + this.x.full + this.x.p2;
2001	if (hs.padToMinWidth && curW < hs.minWidth) {
2002		this.x.p1 += (hs.minWidth - curW) / 2;
2003		this.x.p2 += (hs.minWidth - curW) / 2;
2004	}
2005	for (var i = 0; i < os.length; i++) this.positionOverlay(os[i]);
2006	this.gotOverlays = true;
2007},
2008genOverlayBox : function() {
2009	if (!this.overlayBox) this.overlayBox = hs.createElement (
2010		'div', null,
2011		{
2012			position : 'absolute', 
2013			width: this.x.span ? this.x.span +'px' : this.x.full +'px',
2014			height: 0,
2015			visibility : 'hidden',
2016			overflow : 'hidden',
2017			zIndex : 5
2018		},
2019		hs.container,
2020		true
2021	);
2022},
2023sizeOverlayBox : function(doWrapper, doPanels) {
2024	hs.setStyles( this.overlayBox, {
2025		width: this.x.span +'px', 
2026		height: this.y.span +'px'
2027	});
2028	if (doWrapper || doPanels) {
2029		for (var i = 0; i < this.overlays.length; i++) {
2030			var o = hs.$('hsId'+ this.overlays[i]);
2031			if (o && /^(above|below)$/.test(o.hsPos)) {
2032				if (hs.ie && (hs.ieVersion() <= 6 || document.compatMode == 'BackCompat')) {
2033					o.style.width = (this.overlayBox.offsetWidth + 2 * this.x.cb
2034						- this.x.p1 - this.x.p2) +'px';
2035				}
2036				this.y[o.hsPos == 'above' ? 'p1' : 'p2'] = o.offsetHeight;
2037			}
2038		}
2039	}
2040	if (doWrapper) {
2041		hs.setStyles(this.content, {
2042			top: this.y.p1 +'px'
2043		});
2044		hs.setStyles(this.overlayBox, {
2045			top: (this.y.p1 + this.y.cb) +'px'
2046		});
2047	}
2048},
2049
2050showOverlays : function() {
2051	hs.setStyles(this.overlayBox, {
2052		top: (this.y.p1 + this.y.cb) +'px',
2053		left: /*this.padded ? 0 : */(this.x.p1 + this.x.cb) +'px',
2054		overflow : 'visible'
2055	});
2056	this.wrapper.appendChild (this.overlayBox);
2057	
2058	if (hs.safari) {
2059		var stl = this.content.style;
2060		stl.display = 'inline';
2061		setTimeout(function() {	stl.display = 'block'; }, 50);
2062	}
2063	var page = hs.getPageSize(), 
2064		mX = hs.mouse.x + page.scrollLeft, 
2065		mY = hs.mouse.y + page.scrollTop;
2066	this.mouseIsOver = this.x.min < mX && mX < this.x.min + this.x.p1 + this.x.span + this.x.p2
2067			&& this.y.min < mY && mY < this.y.min + this.y.p1 + this.y.span + this.y.p2;
2068	for (var i = 0; i < this.overlays.length; i++) {
2069		var o = hs.$('hsId'+ this.overlays[i]);
2070		if (!o.hideOnMouseOut || this.mouseIsOver) hs.fade(o, 0, o.opacity);
2071	}
2072},
2073
2074
2075
2076createFullExpand : function () {
2077	if (this.slideshow) {
2078		this.slideshow.enable('full-expand');
2079		return;
2080	}
2081	this.fullExpandLabel = hs.createElement(
2082		'a',
2083		{
2084			href: 'javascript:hs.expanders['+ this.key +'].doFullExpand();',
2085			title: hs.lang.fullExpandTitle,
2086			className: 'highslide-full-expand'
2087		}
2088	);
2089	
2090	this.createOverlay({ 
2091		overlayId: this.fullExpandLabel, 
2092		position: hs.fullExpandPosition, 
2093		hideOnMouseOut: true, 
2094		opacity: hs.fullExpandOpacity
2095	});
2096},
2097
2098doFullExpand : function () {
2099	try {
2100		if (this.fullExpandLabel) hs.discardElement(this.fullExpandLabel);
2101		
2102		this.focus();
2103		
2104		this.x.min = parseInt(this.wrapper.style.left) - (this.x.full - this.content.width) / 2;
2105		if (this.x.min < hs.marginLeft) this.x.min = hs.marginLeft;		
2106		this.wrapper.style.left = this.x.min +'px';
2107		
2108		hs.setStyles(this.content, { width: this.x.full +'px', height: this.y.full +'px'});
2109		
2110		this.x.span = this.x.full;
2111		this.y.span = this.y.full;
2112		
2113		
2114		if (this.overlayBox) this.sizeOverlayBox(true);		
2115		
2116		
2117		hs.setStyles(this.wrapper, {
2118			width: (this.x.p1 + 2 * this.x.cb + this.x.span + this.x.p2) +'px',
2119			height: (this.y.p1 + 2 * this.y.cb + this.y.span + this.y.p2) +'px'
2120		});
2121		
2122		
2123		if (this.outline) this.outline.setPosition(this);
2124		
2125		
2126		this.redoShowHide();
2127		
2128		hs.setDimmerSize();
2129		
2130	
2131	} catch (e) {
2132		window.location.href = this.content.src;
2133	}
2134},
2135
2136
2137// on end move and resize
2138redoShowHide : function() {
2139	var imgPos = {
2140		x: parseInt(this.wrapper.style.left) - 20, 
2141		y: parseInt(this.wrapper.style.top) - 20, 
2142		w: this.content.offsetWidth + 40, 
2143		h: this.content.offsetHeight + 40
2144	};
2145	if (hs.hideSelects) this.showHideElements('SELECT', 'hidden', imgPos);
2146	if (hs.hideIframes) this.showHideElements('IFRAME', 'hidden', imgPos);
2147	if (hs.geckoMac) this.showHideElements('*', 'hidden', imgPos);
2148
2149},
2150
2151afterClose : function () {
2152	this.a.className = this.a.className.replace('highslide-active-anchor', '');
2153	
2154	if (hs.hideSelects) this.showHideElements('SELECT', 'visible');
2155	if (hs.hideIframes) this.showHideElements('IFRAME', 'visible');
2156	if (hs.geckoMac) this.showHideElements('*', 'visible');
2157		if (this.outline && this.outlineWhileAnimating) this.outline.destroy();
2158	
2159		hs.discardElement(this.wrapper);
2160	if (this.dimmingOpacity) hs.undim(this.key);
2161	hs.expanders[this.key] = null;		
2162	hs.reOrder();
2163}
2164
2165};
2166
2167
2168hs.Slideshow = function (options) {
2169	hs.updateAnchors();
2170	for (var x in options) this[x] = options[x];
2171	if (this.useControls) this.getControls();
2172};
2173hs.Slideshow.prototype = {
2174getControls: function() {
2175	this.controls = hs.createElement('div', { innerHTML: hs.replaceLang(hs.skin.controls) }, 
2176		null, hs.container);
2177	
2178	var buttons = ['play', 'pause', 'previous', 'next', 'move', 'full-expand', 'close'];
2179	this.btn = {};
2180	var pThis = this;
2181	for (var i = 0; i < buttons.length; i++) {
2182		this.btn[buttons[i]] = hs.getElementByClass(this.controls, 'li', 'highslide-'+ buttons[i]);
2183		this.enable(buttons[i]);
2184	}
2185	this.btn.pause.style.display = 'none';
2186	this.disable('full-expand');
2187},
2188checkFirstAndLast: function() {
2189	if (this.repeat) return;
2190	var cur = this.exp.getAnchorIndex(), re = /disabled$/;
2191	if (cur == 0) 
2192		this.disable('previous');
2193	else if (re.test(this.btn.previous.getElementsByTagName('a')[0].className))
2194		this.enable('previous');
2195	if (cur + 1 == hs.anchors.groups[this.slideshowGroup || 'none'].length) {
2196		this.disable('next');
2197		this.disable('play');
2198	} else if (re.test(this.btn.next.getElementsByTagName('a')[0].className)) {
2199		this.enable('next');
2200		this.enable('play');
2201	}
2202},
2203enable: function(btn) {
2204	var sls = this, a = this.btn[btn].getElementsByTagName('a')[0], re = /disabled$/;
2205	a.onclick = function() {
2206		sls[btn]();
2207		return false;
2208	};
2209	if (re.test(a.className)) a.className = a.className.replace(re, '');
2210},
2211disable: function(btn) {
2212	var a = this.btn[btn].getElementsByTagName('a')[0];
2213	a.onclick = function() { return false; };
2214	if (!/disabled$/.test(a.className)) a.className += ' disabled';
2215},
2216hitSpace: function() {
2217	if (this.autoplay) this.pause();
2218	else this.play();
2219},
2220play: function(wait) {
2221	if (this.btn) {
2222		this.btn.play.style.display = 'none';
2223		this.btn.pause.style.display = '';
2224	}
2225	
2226	this.autoplay = true;	
2227	if (!wait) hs.next(this.exp.key);
2228},
2229pause: function() {
2230	if (this.btn) {
2231		this.btn.pause.style.display = 'none';
2232		this.btn.play.style.display = '';
2233	}
2234	
2235	clearTimeout(this.autoplay);
2236	this.autoplay = null;
2237},
2238previous: function() {
2239	this.pause();
2240	hs.previous(this.btn.previous);
2241},
2242next: function() {
2243	this.pause();
2244	hs.next(this.btn.next);
2245},
2246move: function() {},
2247'full-expand': function() {
2248	hs.getExpander().doFullExpand();
2249},
2250close: function() {
2251	hs.close(this.btn.close);
2252}
2253
2254};
2255hs.langDefaults = hs.lang;
2256// history
2257var HsExpander = hs.Expander;
2258
2259// set handlers
2260hs.addEventListener(document, 'mousemove', function(e) {
2261	hs.mouse = { x: e.clientX, y: e.clientY	};
2262});
2263hs.addEventListener(document, 'mousedown', hs.mouseClickHandler);
2264hs.addEventListener(document, 'mouseup', hs.mouseClickHandler);
2265hs.addEventListener(window, 'load', hs.preloadImages);

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.