PageSourceSearch

https://www.electoralgeography.com/new/en/wp-content/plugins/highslide/highslide.js

js electoralgeography.com collected 2026-10-02 10:27:56 UTC 44,629 bytes, 1,529 lines download raw bytes

1/******************************************************************************
2Name:    Highslide JS
3Version: 3.2.3 (August 8 2007)
4Author:  Torstein Hønsi
5Support: http://vikjavev.no/highslide/forum
6Email:   See http://vikjavev.no/megsjol
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******************************************************************************/
28
29var hs = {
30
31// Apply your own settings here, or override them in the html file.  
32graphicsDir : 'highslide/graphics/',
33restoreCursor : "zoomout.cur", // necessary for preload
34expandSteps : 10, // number of steps in zoom. Each step lasts for duration/step milliseconds.
35expandDuration : 250, // milliseconds
36restoreSteps : 10,
37restoreDuration : 250,
38allowMultipleInstances: true,
39hideThumbOnExpand : true,
40captionSlideSpeed : 1, // set to 0 to disable slide in effect
41outlineWhileAnimating : false, // not recommended, animation gets jaggy on slow systems.
42outlineStartOffset : 3, // ends at 10
43marginLeft : 10,
44marginRight : 35, // leave room for scrollbars + outline
45marginTop : 10,
46marginBottom : 35, // leave room for scrollbars + outline
47numberOfImagesToPreload : 5,
48zIndexCounter : 1001, // adjust to other absolutely positioned elements
49fullExpandIcon : 'fullexpand.gif',
50fullExpandTitle : 'Expand to actual size',
51restoreTitle : 'Click to close image, click and drag to move. Use arrow keys for next and previous.',
52focusTitle : 'Click to bring to front',
53loadingText : 'Loading...',
54loadingTitle : 'Click to cancel',
55loadingOpacity : 0.75,
56showCredits : true, // you can set this to false if you want
57creditsText : 'Powered by <i>Highslide JS</i>',
58creditsHref : 'http://vikjavev.no/highslide/',
59creditsTitle : 'Go to the Highslide JS homepage',
60enableKeyListener : true,
61
62// These settings can also be overridden inline for each image
63anchor : 'auto', // where the image expands from
64align : 'auto', // position in the client (overrides anchor)
65targetX: null, // the id of a target element
66targetY: null,
67captionId : null,
68captionTemplateId : null,
69slideshowGroup : null, // defines groups for next/previous links and keystrokes
70spaceForCaption : 30, // leaves space below images with captions
71minWidth: 200,
72minHeight: 200,
73allowSizeReduction: true, // allow the image to reduce to fit client size. If false, this overrides minWidth and minHeight
74outlineType : 'drop-shadow', // set null to disable outlines
75wrapperClassName : null, // for enhanced css-control
76
77		
78// END OF YOUR SETTINGS
79
80
81// declare internal properties
82preloadTheseImages : new Array(),
83continuePreloading: true,
84expandedImagesCounter : 0,
85expanders : new Array(),
86overrides : new Array(
87	'anchor',
88	'align',
89	'targetX',
90	'targetY',
91	'outlineType',
92	'outlineWhileAnimating',
93	'spaceForCaption', 
94	'wrapperClassName',
95	'minWidth',
96	'minHeight',
97	'captionId',
98	'captionTemplateId',
99	'allowSizeReduction',
100	'slideshowGroup'
101),
102overlays : new Array(),
103pendingOutlines : new Array(),
104origNodes : new Array(),
105faders : new Array(),
106ie : (document.all && !window.opera),
107safari : navigator.userAgent.indexOf("Safari") != -1,
108hasFocused : false,
109
110$ : function (id) {
111	return document.getElementById(id);
112},
113
114push : function (arr, val) {
115	arr[arr.length] = val;
116},
117
118createElement : function (tag, attribs, styles, parent, nopad) {
119	var el = document.createElement(tag);
120	if (attribs) hs.setAttribs(el, attribs);
121	if (nopad) hs.setStyles(el, {padding: 0, border: 'none', margin: 0});
122	if (styles) hs.setStyles(el, styles);
123	if (parent) parent.appendChild(el);	
124	return el;
125},
126
127setAttribs : function (el, attribs) {
128	for (var x in attribs) {
129		el[x] = attribs[x];
130	}
131},
132
133setStyles : function (el, styles) {
134	for (var x in styles) {
135		try { 
136			if (hs.ie && x == 'opacity') el.style.filter = 'alpha(opacity='+ (styles[x] * 100) +')';
137			else el.style[x] = styles[x]; 
138		}
139		catch (e) {}
140	}
141},
142
143ieVersion : function () {
144	arr = navigator.appVersion.split("MSIE");
145	return parseFloat(arr[1]);
146},
147
148clientInfo : function ()	{
149	var iebody = document.compatMode && document.compatMode != "BackCompat" 
150		? document.documentElement : document.body;
151	
152	this.width = hs.ie ? iebody.clientWidth : self.innerWidth;
153	this.height = hs.ie ? iebody.clientHeight : self.innerHeight;
154	this.scrollLeft = hs.ie ? iebody.scrollLeft : pageXOffset;
155	this.scrollTop = hs.ie ? iebody.scrollTop : pageYOffset;
156} ,
157
158position : function(el)	{ 
159	var parent = el;	
160	var p = { x: parent.offsetLeft, y: parent.offsetTop };
161	while (parent.offsetParent)	{
162		parent = parent.offsetParent;
163		p.x += parent.offsetLeft;
164		p.y += parent.offsetTop;
165		if (parent != document.body && parent != document.documentElement) {
166			p.x -= parent.scrollLeft;
167			p.y -= parent.scrollTop;
168		}
169	}
170	return p;
171},
172
173expand : function(a, params, custom) {
174	try {
175		new HsExpander(a, params, custom);
176		return false;		
177	} catch (e) { return true; }	
178},
179
180focusTopmost : function() {
181	var topZ = 0, topmostKey = -1;
182	for (i = 0; i < hs.expanders.length; i++) {
183		if (hs.expanders[i]) {
184			if (hs.expanders[i].wrapper.style.zIndex && hs.expanders[i].wrapper.style.zIndex > topZ) {
185				topZ = hs.expanders[i].wrapper.style.zIndex;
186				
187				topmostKey = i;
188			}
189		}
190	}
191	if (topmostKey == -1) hs.focusKey = -1;
192	else hs.expanders[topmostKey].focus();
193}, 
194
195
196closeId : function(id) { // for text links
197	return hs.close(id);
198},
199
200close : function(el) {
201	try { hs.getExpander(el).doClose(); } catch (e) {}
202	return false;
203},
204
205getAdjacentAnchor : function(key, op) {
206	var aAr = document.getElementsByTagName('A'), hsAr = new Array, activeI = -1, j = 0;
207	for (i = 0; i < aAr.length; i++) {
208		if (hs.isHsAnchor(aAr[i]) && ((hs.expanders[key].slideshowGroup == hs.getParam(aAr[i], 'slideshowGroup')))) {
209			hsAr[j] = aAr[i];
210			if (hs.expanders[key] && aAr[i] == hs.expanders[key].a) {
211				activeI = j;
212			}
213			j++;
214		}
215	}
216	return hsAr[activeI + op];
217},
218
219getParam : function (a, param) {
220	try {
221		var s = a.onclick.toString().replace(/\s/g, ' ').split('{')[2].split('}')[0];
222		if (hs.safari) { // stupid bug
223			for (var i = 0; i < hs.overrides.length; i++) {
224				s = s.replace(hs.overrides[i] +':', ','+ hs.overrides[i] +':').replace(new RegExp("^\\s*?,"), '');
225			}
226		}
227		eval('var arr = {'+ s +'};');
228		if (arr[param]) return arr[param];
229		else return hs[param];
230	} catch (e) {
231		return hs[param];
232	}
233},
234
235getSrc : function (a) {
236	var src = hs.getParam(a, 'src');
237	if (src) return src;
238	return a.rel.replace(/_slash_/g, '/') || a.href;
239},
240
241cloneNode : function (id) {
242	if (!hs.$(id) && !hs.origNodes[id]) return null;
243	var clone;
244	if (hs.origNodes[id]) {
245		clone = hs.origNodes[id].cloneNode(1);
246		hs.setId(clone, /-hsOrig$/, 1);
247	} else {
248		clone = hs.$(id).cloneNode(1);
249		if (!id.match(/-hsCache[0-9]+$/)) {
250			hs.origNodes[id] = hs.$(id);
251			hs.setId(hs.$(id), '-hsOrig');
252		}
253	}
254	return clone;
255},
256
257setId : function (d, suff, remove) {
258	if (d.id) d.id = remove ? d.id.replace(suff, '') : d.id + suff;
259	if (d.name) d.name = remove ? d.name.replace(suff, '') : d.name + suff;
260	if (hs.geckoBug && hs.geckoBug(d)) return;
261	var a = d.childNodes;		
262	for (var i = 0; i < a.length; i++) {
263		if (a[i]) hs.setId(a[i], suff, remove);
264	}
265},
266
267purge : function(d) {
268	var a = d.attributes, i, l, n;
269    if (a) {
270        l = a.length;
271        for (i = 0; i < l; i += 1) {
272            n = a[i].name;
273            if (typeof d[n] === 'function') {
274                d[n] = null;
275            }
276        }
277    }
278    if (hs.geckoBug && hs.geckoBug(d)) return;
279	a = d.childNodes;
280    if (a) {
281        l = a.length;
282        for (i = 0; i < l; i += 1) {
283            hs.purge(d.childNodes[i]);
284        }
285    }
286},
287
288previousOrNext : function (el, op) {
289	if (typeof el == 'object') var activeKey = hs.getWrapperKey(el);
290	else if (typeof el == 'number') var activeKey = el;
291	try { hs.getAdjacentAnchor(activeKey, op).onclick(); } catch (e) {}
292	try { hs.expanders[activeKey].doClose(); } catch (e) {}	
293	return false;
294},
295
296previous : function (el) {
297	return hs.previousOrNext(el, -1);
298},
299
300next : function (el) {
301	return hs.previousOrNext(el, 1);	
302},
303
304keyHandler : function(e) {
305	if (!e) e = window.event;
306	if (!e.target) e.target = e.srcElement; // ie
307	if (e.target.form) return; // form element has focus
308	
309	var op = null;
310	switch (e.keyCode) {
311		case 34: // Page Down
312		case 39: // Arrow right
313		case 40: // Arrow down
314			op = 1;
315			break;
316		case 33: // Page Up
317		case 37: // Arrow left
318		case 38: // Arrow up
319			op = -1;
320			break;
321		case 27: // Escape
322		case 13: // Enter
323			op = 0;
324	}
325	if (op !== null) {
326		hs.removeEventListener(document, 'keydown', hs.keyHandler);
327		try { if (!hs.enableKeyListener) return true; } catch (e) {}
328		
329		if (e.preventDefault) e.preventDefault();
330    	else e.returnValue = false;
331		if (op == 0) {
332			try { hs.getExpander().doClose(); } catch (e) {}
333			return false;
334		} else {
335			return hs.previousOrNext(hs.focusKey, op);
336		}
337	} else return true;
338},
339
340registerOverlay : function (overlay) {
341	hs.push(hs.overlays, overlay);
342},
343
344getWrapperKey : function (element) {
345	var key = -1, el, re = /^highslide-wrapper-([0-9]+)$/;
346	// 1. look in open expanders
347	el = element;
348	while (el.parentNode)	{
349		el = el.parentNode;
350		if (el.id && el.id.match(re)) return el.id.replace(re, "$1");
351	}
352	// 2. look in thumbnail
353	el = element;
354	while (el.parentNode)	{
355		if (el.tagName && hs.isHsAnchor(el)) {
356			for (key = 0; key < hs.expanders.length; key++) {
357				exp = hs.expanders[key];
358				if (exp && exp.a == el) return key;
359			}
360		}
361		el = el.parentNode;
362	}
363},
364
365getExpander : function (el) {
366	try {
367		if (!el) return hs.expanders[hs.focusKey];
368		if (typeof(el) == 'string') el = hs.$(el);
369		return hs.expanders[hs.getWrapperKey(el)];
370	} catch (e) {}
371},
372
373cleanUp : function () {
374	for (i = 0; i < hs.expanders.length; i++) {
375		if (hs.expanders[i] && hs.expanders[i].isExpanded) hs.focusTopmost();
376	}
377},
378
379mouseClickHandler : function(e) 
380{	
381	if (!e) e = window.event;
382	if (e.button > 1) return true;
383	if (!e.target) e.target = e.srcElement;
384	
385	var fobj = e.target;
386	while (fobj.parentNode
387		&& !(fobj.className && fobj.className.match(/highslide-(image|move|html)/)))
388	{
389		fobj = fobj.parentNode;
390	}
391
392	if (!fobj.parentNode) return;
393	
394	hs.dragExp = hs.getExpander(fobj);
395	
396	if (fobj.className.match(/highslide-(image|move)/)) {
397		var isDraggable = true;
398		var wLeft = parseInt(hs.dragExp.wrapper.style.left);
399		var wTop = parseInt(hs.dragExp.wrapper.style.top);			
400	}
401
402	if (e.type == 'mousedown') {
403		if (isDraggable) // drag or focus
404		{
405			if (fobj.className.match('highslide-image')) hs.dragExp.content.style.cursor = 'move';
406			
407			hs.wLeft = wLeft;
408			hs.wTop = wTop;
409			
410			hs.dragX = e.clientX;
411			hs.dragY = e.clientY;
412			hs.addEventListener(document, 'mousemove', hs.mouseMoveHandler);
413			if (e.preventDefault) e.preventDefault(); // FF
414			
415			if (hs.dragExp.content.className.match(/highslide-(image|html)-blur/)) {
416				hs.dragExp.focus();
417				hs.hasFocused = true;
418			}
419			return false;
420		}
421		else if (fobj.className.match(/highslide-html/)) { // just focus
422			hs.dragExp.focus();
423			hs.dragExp.redoShowHide();
424			hs.hasFocused = false; // why??
425		}
426		
427	} else if (e.type == 'mouseup') {
428		hs.removeEventListener(document, 'mousemove', hs.mouseMoveHandler);
429		if (isDraggable && hs.dragExp) {
430			if (fobj.className.match('highslide-image')) {
431				fobj.style.cursor = hs.styleRestoreCursor;
432			}
433			var hasMoved = wLeft != hs.wLeft || wTop != hs.wTop;
434			if (!hasMoved && !hs.hasFocused && !fobj.className.match(/highslide-move/)) {
435				hs.dragExp.onClick();
436			} else if (hasMoved || (!hasMoved && hs.hasHtmlexpanders)) {
437				hs.dragExp.redoShowHide();
438			}
439			hs.hasFocused = false;
440		
441		} else if (fobj.className.match('highslide-image-blur')) {
442			fobj.style.cursor = hs.styleRestoreCursor;		
443		}
444	}
445},
446
447mouseMoveHandler : function(e)
448{
449	if (!hs.dragExp || !hs.dragExp.wrapper) return;
450	if (!e) e = window.event;
451
452	hs.dragExp.x.min = hs.wLeft + e.clientX - hs.dragX;
453	hs.dragExp.y.min = hs.wTop + e.clientY - hs.dragY;
454	
455	var w = hs.dragExp.wrapper;
456	
457	w.style.left = hs.dragExp.x.min +'px';
458	w.style.top  = hs.dragExp.y.min +'px';
459	
460	if (hs.dragExp.objOutline) {
461		var o = hs.dragExp.objOutline;
462		o.table.style.left = (hs.dragExp.x.min - o.offset) +'px';
463		o.table.style.top = (hs.dragExp.y.min - o.offset) +'px';
464	}	
465	return false;
466},
467
468addEventListener : function (el, event, func) {
469	try {
470		el.addEventListener(event, func, false);
471	} catch (e) {
472		try {
473			el.detachEvent('on'+ event, func);
474			el.attachEvent('on'+ event, func);
475		} catch (e) {
476			el['on'+ event] = func;
477		}
478	} 
479},
480
481removeEventListener : function (el, event, func) {
482	try {
483		el.removeEventListener(event, func, false);
484	} catch (e) {
485		try {
486			el.detachEvent('on'+ event, func);
487		} catch (e) {
488			el['on'+ event] = null;
489		}
490	}
491},
492
493isHsAnchor : function (a) {
494	return (a.onclick && a.onclick.toString().replace(/\s/g, ' ').match(/hs.(htmlE|e)xpand/));
495},
496
497preloadFullImage : function (i) {
498	if (hs.continuePreloading && hs.preloadTheseImages[i] && hs.preloadTheseImages[i] != 'undefined') {
499		var img = document.createElement('img');
500		img.onload = function() { hs.preloadFullImage(i + 1); };
501		img.src = hs.preloadTheseImages[i];
502	}
503},
504
505preloadImages : function (number) {
506	if (number && typeof number != 'object') hs.numberOfImagesToPreload = number;
507	var re, j = 0;
508	
509	var aTags = document.getElementsByTagName('A');
510	for (i = 0; i < aTags.length; i++) {
511		a = aTags[i];
512		re = hs.isHsAnchor(a);
513		if (re && re[0] == 'hs.expand') {
514			if (j < hs.numberOfImagesToPreload) {
515				hs.preloadTheseImages[j] = hs.getSrc(a); 
516				j++;
517			}
518		}
519	}
520	
521	// preload outlines
522	new HsOutline(hs.outlineType, function () { hs.preloadFullImage(0)} );
523	
524	// preload cursor
525	var cur = hs.createElement('img', { src: hs.graphicsDir + hs.restoreCursor });
526},
527
528genContainer : function () {
529	if (!hs.container) {
530		hs.container = hs.createElement('div', 
531			null, 
532			{ position: 'absolute', left: 0, top: 0, width: '100%', zIndex: hs.zIndexCounter }, 
533			document.body,
534			true
535		);
536	}	
537},
538
539fade : function (el, o, oFinal, dir, i) {
540	o = parseFloat(o);
541	if (o <= 0) el.style.visibility = 'hidden';
542	else el.style.visibility = 'visible';
543	if (dir * (o - oFinal) > 0) return;
544	if (i == null) i = hs.faders.length;
545	if (typeof(el.i) != 'undefined' && el.i != i) {
546		clearTimeout(hs.faders[el.i]);
547		o = el.tempOpacity;
548	}
549	el.i = i;
550	el.tempOpacity = o;
551	el.style.visibility = (o <= 0) ? 'hidden' : 'visible';
552	hs.setStyles(el, { opacity: o });
553	hs.faders[i] = setTimeout(function() { 
554			hs.fade(el, Math.round((o + 0.1 * dir)*100)/100, oFinal, dir, i);
555	 	}, 25);
556}
557}; // end hs object
558
559//-----------------------------------------------------------------------------
560HsOutline = function (outlineType, onLoad) {
561	if (!outlineType) {
562		if (onLoad) onLoad();
563		return;
564	}
565	this.onLoad = onLoad;
566	this.outlineType = outlineType;
567	var v = hs.ieVersion(), tr;
568	
569	hs.genContainer();
570	
571	this.hasAlphaImageLoader = hs.ie && v >= 5.5 && v < 7;
572	this.hasPngSupport = !hs.ie || (hs.ie && v >= 7);
573	this.hasOutline = this.outlineType && (this.hasAlphaImageLoader || this.hasPngSupport);
574	
575	this.table = hs.createElement(
576		'table',
577		{	
578			cellSpacing: 0 // saf
579		},
580		{
581			visibility: 'hidden',
582			position: 'absolute',
583			zIndex: hs.zIndexCounter++,
584			borderCollapse: 'collapse'
585		},
586		hs.container,
587		true
588	);
589	this.tbody = hs.createElement('tbody', null, null, this.table);
590	
591	this.td = Array();
592	for (var i = 0; i <= 8; i++) {
593		if (i % 3 == 0) tr = hs.createElement('tr', null, null, this.tbody, true);
594		this.td[i] = hs.createElement('td', null, null, tr, true);
595		var style = i != 4 ? { lineHeight: 0, fontSize: 0} : { position : 'relative' };
596		hs.setStyles(this.td[i], style);
597	}
598	
599	this.preloadGraphic(); 
600};
601
602HsOutline.prototype.preloadGraphic = function () {	
603	var src = hs.graphicsDir + "outlines/"+ this.outlineType +".png";
604				
605	var appendTo = hs.safari ? hs.container : null;
606	this.graphic = hs.createElement('img', null, { position: 'absolute', left: '-9999px', 
607		top: '-9999px' }, appendTo, true); // for onload trigger
608	
609	var pThis = this;
610	this.graphic.onload = function() { pThis.onGraphicLoad(); };
611	
612	this.graphic.src = src;
613};
614
615HsOutline.prototype.onGraphicLoad = function () {
616	var o = this.offset = this.graphic.width / 4;
617	var pos = [[0,0],[0,-4],[-2,0],[0,-8],0,[-2,-8],[0,-2],[0,-6],[-2,-2]];
618	for (var i = 0; i <= 8; i++) {
619		if (pos[i]) {
620			if (this.hasAlphaImageLoader) {
621				var w = (i == 1 || i == 7) ? '100%' : this.graphic.width +'px';
622				var div = hs.createElement('div', null, { width: '100%', height: '100%', position: 'relative', overflow: 'hidden'}, this.td[i], true);
623				hs.createElement ('div', null, { 
624						filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale, src='"+ this.graphic.src + "')", 
625						position: 'absolute',
626						width: w, 
627						height: this.graphic.height +'px',
628						left: (pos[i][0]*o)+'px',
629						top: (pos[i][1]*o)+'px'
630					}, 
631				div,
632				true);
633			} else {
634				hs.setStyles(this.td[i], { background: 'url('+ this.graphic.src +') '+ (pos[i][0]*o)+'px '+(pos[i][1]*o)+'px'});
635			}
636			
637			// common
638			var dim = 2 * o;
639			hs.setStyles (this.td[i], { height: dim +'px', width: dim +'px' } );
640		}
641	}
642	
643	hs.pendingOutlines[this.outlineType] = this;
644	if (this.onLoad) this.onLoad();
645};
646
647HsOutline.prototype.destroy = function() {
648	hs.purge(this.table);
649	try { this.table.parentNode.removeChild(this.table); } catch (e) {}
650};
651
652//-----------------------------------------------------------------------------
653// The expander object
654HsExpander = function(a, params, custom, contentType) {
655	hs.continuePreloading = false;
656		
657	this.custom = custom;
658	// override inline parameters
659	for (i = 0; i < hs.overrides.length; i++) {
660		var name = hs.overrides[i];
661		if (params && typeof params[name] != 'undefined') this[name] = params[name];
662		else this[name] = hs[name];
663	}
664	
665	if (params && params.thumbnailId) {
666		var el = hs.$(params.thumbnailId);
667	
668	} else { // first img within anchor
669		for (i = 0; i < a.childNodes.length; i++) {
670			if (a.childNodes[i].tagName && a.childNodes[i].tagName == 'IMG') {
671				var el = a.childNodes[i];
672				break;
673			}			
674		}
675	}
676	if (!el) el = a;
677	
678	// cancel other
679	for (i = 0; i < hs.expanders.length; i++) {
680		if (hs.expanders[i] && hs.expanders[i].thumb != el && !hs.expanders[i].onLoadStarted) {
681			hs.expanders[i].cancelLoading();
682		}
683	}
684	// check if already open
685	for (i = 0; i < hs.expanders.length; i++) {
686		if (hs.expanders[i] && hs.expanders[i].thumb == el) {
687			hs.expanders[i].focus();
688			return false;
689		}		
690	}
691
692	if (!hs.allowMultipleInstances) {
693		var prev = hs.expandedImagesCounter - 1;
694		if (hs.expanders[prev]) hs.expanders[prev].doClose();
695	}
696	
697	var key = this.key = hs.expandedImagesCounter++;
698	hs.expanders[this.key] = this;
699	if (contentType == 'html') {
700		this.isHtml = true;
701		this.contentType = 'html';
702	} else {
703		this.isImage = true;
704		this.contentType = 'image';
705	}
706	this.a = a;
707	
708	this.thumbsUserSetId = el.id || a.id;
709	this.thumb = el;		
710	
711	this.overlays = new Array();
712
713	var pos = hs.position(el); 
714	
715	// instanciate the wrapper
716	this.wrapper = hs.createElement(
717		'div',
718		{
719			id: 'highslide-wrapper-'+ this.key,
720			className: this.wrapperClassName
721		},
722		{
723			visibility: 'hidden',
724			position: 'absolute',
725			zIndex: hs.zIndexCounter++
726		}, null, true );
727	this.wrapper.onmouseover = function (e) { 
728    	try { hs.expanders[key].onMouseOver(); } catch (e) {} 
729    };
730    this.wrapper.onmouseout = function (e) { 
731    	try { hs.expanders[key].onMouseOut(); } catch (e) {}
732	};
733	
734	// store properties of thumbnail
735	this.thumbWidth = el.width ? el.width : el.offsetWidth;		
736	this.thumbHeight = el.height ? el.height : el.offsetHeight;
737	this.thumbLeft = pos.x;
738	this.thumbTop = pos.y;
739	
740	// thumb borders
741	this.thumbOffsetBorderW = (this.thumb.offsetWidth - this.thumbWidth) / 2;
742	this.thumbOffsetBorderH = (this.thumb.offsetHeight - this.thumbHeight) / 2;
743	
744	// get the wrapper
745	hs.genContainer();
746	if (hs.pendingOutlines[this.outlineType]) {
747		this.connectOutline();
748		this[this.contentType +'Create']();
749	} else if (!this.outlineType) {
750		this[this.contentType +'Create']();
751	} else {
752		this.displayLoading();
753		var pThis = this;
754		new HsOutline(this.outlineType, 
755			function () { 
756				pThis.connectOutline();
757				pThis[pThis.contentType +'Create']();
758			} 
759		);
760	}
761	
762};
763
764HsExpander.prototype.connectOutline = function(x, y) {	
765	var w = hs.pendingOutlines[this.outlineType];
766	this.objOutline = w;
767	hs.pendingOutlines[this.outlineType] = null;
768};
769
770HsExpander.prototype.displayLoading = function() {
771	if (this.onLoadStarted || this.loading) return;
772		
773	this.originalCursor = this.a.style.cursor;
774	this.a.style.cursor = 'wait';
775	
776	if (!hs.loading) {
777		hs.loading = hs.createElement('a',
778			{
779				className: 'highslide-loading',
780				title: hs.loadingTitle,
781				innerHTML: hs.loadingText
782			},
783			{
784				position: 'absolute',
785				opacity: hs.loadingOpacity
786			}, hs.container
787		);
788	}
789	
790	this.loading = hs.loading;
791	this.loading.href = 'javascript:hs.expanders['+ this.key +'].cancelLoading()';
792	this.loading.visibility = 'visible';		
793	
794	this.loading.style.left = (this.thumbLeft + this.thumbOffsetBorderW 
795		+ (this.thumbWidth - this.loading.offsetWidth) / 2) +'px';
796	this.loading.style.top = (this.thumbTop 
797		+ (this.thumbHeight - this.loading.offsetHeight) / 2) +'px';
798	setTimeout(
799		"if (hs.expanders["+ this.key +"] && hs.expanders["+ this.key +"].loading) "
800		+ "hs.expanders["+ this.key +"].loading.style.visibility = 'visible';", 
801		100
802	);
803};
804
805HsExpander.prototype.imageCreate = function() {
806	var key = this.key;
807
808	var img = document.createElement('img');
809    this.content = img;
810    img.onload = function () { try { hs.expanders[key].onLoad(); } catch (e) {} };
811    img.className = 'highslide-image';
812    img.style.visibility = 'hidden'; // prevent flickering in IE
813    img.style.display = 'block';
814	img.style.position = 'absolute';
815    img.style.zIndex = 3;
816    img.title = hs.restoreTitle;
817    if (hs.safari) hs.container.appendChild(img);
818    // uncomment this to flush img size:
819    // if (hs.ie) img.src = null;
820	img.src = hs.getSrc(this.a);
821	
822	this.displayLoading();
823};
824
825HsExpander.prototype.onLoad = function() {	
826	try { 
827	
828		if (!this.content) return;
829		if (this.onLoadStarted) return; // old Gecko loop
830		else this.onLoadStarted = true;
831		
832			   
833		if (this.loading) {
834			this.loading.style.visibility = 'hidden';
835			this.loading = null;
836			this.a.style.cursor = this.originalCursor || '';
837		}
838		if (this.isImage) {			
839			this.newWidth = this.content.width;
840			this.newHeight = this.content.height;
841			this.fullExpandWidth = this.newWidth;
842			this.fullExpandHeight = this.newHeight;
843			
844			this.content.width = this.thumbWidth;
845			this.content.height = this.thumbHeight;
846			
847		} else if (this.htmlGetSize) this.htmlGetSize();
848		
849		// identify caption div
850		var modMarginBottom = hs.marginBottom;
851		if (!this.captionId && this.thumbsUserSetId)  this.captionId = 'caption-for-'+ this.thumbsUserSetId;
852		if (this.captionId) {
853			this.caption = hs.cloneNode(this.captionId);
854		}
855		if (this.captionTemplateId) {
856			var s = (this.caption) ? this.caption.innerHTML : '';
857			this.caption = hs.cloneNode(this.captionTemplateId);
858			if (this.caption) this.caption.innerHTML
859				= this.caption.innerHTML.replace(/\s/g, ' ').replace('{caption}', s);
860		}
861		
862		var modMarginBottom = hs.marginBottom;
863		if (this.caption) modMarginBottom += this.spaceForCaption;
864		
865		this.wrapper.appendChild(this.content);
866		this.content.style.position = 'relative'; // Saf
867		if (this.caption) this.wrapper.appendChild(this.caption);
868		this.wrapper.style.left = this.thumbLeft +'px';
869		this.wrapper.style.top = this.thumbTop +'px';
870		hs.container.appendChild(this.wrapper);
871		
872		// correct for borders
873		this.offsetBorderW = (this.content.offsetWidth - this.thumbWidth) / 2;
874		this.offsetBorderH = (this.content.offsetHeight - this.thumbHeight) / 2;
875		var modMarginRight = hs.marginRight + 2 * this.offsetBorderW;
876		modMarginBottom += 2 * this.offsetBorderH;
877		
878		var ratio = this.newWidth / this.newHeight;
879		var minWidth = this.allowSizeReduction ? this.minWidth : this.newWidth;
880		var minHeight = this.allowSizeReduction ? this.minHeight : this.newHeight;
881		
882		var justify = { x: 'auto', y: 'auto' };
883		if (this.align == 'center') {
884			justify.x = 'center';
885			justify.y = 'center';
886		} else {
887			if (this.anchor.match(/^top/)) justify.y = null;
888			if (this.anchor.match(/right$/)) justify.x = 'max';
889			if (this.anchor.match(/^bottom/)) justify.y = 'max';
890			if (this.anchor.match(/left$/)) justify.x = null;
891		}
892		
893		client = new hs.clientInfo();		
894		
895		// justify
896		this.x = { 
897			min: parseInt(this.thumbLeft) - this.offsetBorderW + this.thumbOffsetBorderW,
898			span: this.newWidth,
899			minSpan: this.newWidth < minWidth ? this.newWidth : minWidth,
900			justify: justify.x,
901			target: this.targetX,
902			marginMin: hs.marginLeft, 
903			marginMax: modMarginRight,
904			scroll: client.scrollLeft,
905			clientSpan: client.width,
906			thumbSpan: this.thumbWidth
907		};
908		var oldRight = this.x.min + parseInt(this.thumbWidth);
909		this.x = this.justify(this.x);
910		this.y = { 
911			min: parseInt(this.thumbTop) - this.offsetBorderH + this.thumbOffsetBorderH,
912			span: this.newHeight,
913			minSpan: this.newHeight < minHeight ? this.newHeight : minHeight,
914			justify: justify.y,
915			target: this.targetY,
916			marginMin: hs.marginTop, 
917			marginMax: modMarginBottom, 
918			scroll: client.scrollTop,
919			clientSpan: client.height,
920			thumbSpan: this.thumbHeight
921		};
922		var oldBottom = this.y.min + parseInt(this.thumbHeight);
923		this.y = this.justify(this.y);
924		
925		if (this.isHtml) this.htmlSizeOperations();	
926		if (this.isImage) this.correctRatio(ratio);
927
928		var x = this.x;
929		var y = this.y;
930		
931		this.show();
932	} catch (e) {
933		if (hs.expanders[this.key] && hs.expanders[this.key].a) 
934			window.location.href = hs.getSrc(hs.expanders[this.key].a);
935	}
936};
937
938HsExpander.prototype.show = function () {
939	// Selectbox bug
940	var imgPos = {x: this.x.min - 20, y: this.y.min - 20, w: this.x.span + 40, h: this.y.span + 40 + this.spaceForCaption};
941	hs.hideSelects = (hs.ie && hs.ieVersion() < 7);
942	if (hs.hideSelects) this.showHideElements('SELECT', 'hidden', imgPos);
943	// Iframes bug
944	hs.hideIframes = (window.opera || navigator.vendor == 'KDE' || (hs.ie && hs.ieVersion() < 5.5));
945	if (hs.hideIframes) this.showHideElements('IFRAME', 'hidden', imgPos);
946	
947	// Make outline ready	
948	if (this.objOutline && !this.outlineWhileAnimating) this.positionOutline(this.x.min, this.y.min, this.x.span, this.y.span);
949	var o2 = this.objOutline ? this.objOutline.offset : 0;
950	
951	// Apply size change		
952	this.changeSize(
953		1,
954		this.thumbLeft + this.thumbOffsetBorderW - this.offsetBorderW,
955		this.thumbTop + this.thumbOffsetBorderH - this.offsetBorderH,
956		this.thumbWidth,
957		this.thumbHeight,
958		this.x.min,
959		this.y.min,
960		this.x.span,
961		this.y.span, 
962		hs.expandDuration,
963		hs.expandSteps,
964		hs.outlineStartOffset,
965		o2
966	);
967};
968
969HsExpander.prototype.justify = function (p) {
970	
971	var tgt, dim = p == this.x ? 'x' : 'y';
972	if (p.target && p.target.match(/ /)) {
973		tgt = p.target.split(' ');
974		p.target = tgt[0];
975	}
976	if (p.target && hs.$(p.target)) {
977		p.min = hs.position(hs.$(p.target))[dim];
978		if (tgt && tgt[1] && tgt[1].match(/^[-]?[0-9]+px$/)) p.min += parseInt(tgt[1]);
979		
980	} else if (p.justify == 'auto' || p.justify == 'center') {
981		var hasMovedMin = false;
982		var allowReduce = true;
983		
984		// calculate p.min
985		if (p.justify == 'center') p.min = Math.round(p.scroll + (p.clientSpan - p.span - p.marginMax) / 2);
986		else p.min = Math.round(p.min - ((p.span - p.thumbSpan) / 2)); // auto
987		
988		if (p.min < p.scroll + p.marginMin) {
989			p.min = p.scroll + p.marginMin;
990			hasMovedMin = true;		
991		}
992		
993		if (p.span < p.minSpan) {
994			p.span = p.minSpan;
995			allowReduce = false;
996		}
997		// calculate right/newWidth
998		if (p.min + p.span > p.scroll + p.clientSpan - p.marginMax) {
999			if (hasMovedMin && allowReduce) p.span = p.clientSpan - p.marginMin - p.marginMax; // can't expand more
1000			else if (p.span < p.clientSpan - p.marginMin - p.marginMax) { // move newTop up
1001				p.min = p.scroll + p.clientSpan - p.span - p.marginMin - p.marginMax;
1002			} else { // image larger than client
1003				p.min = p.scroll + p.marginMin;
1004				if (allowReduce) p.span = p.clientSpan - p.marginMin - p.marginMax;
1005			}
1006			
1007		}
1008		
1009		if (p.span < p.minSpan) {
1010			p.span = p.minSpan;
1011			allowReduce = false;
1012		}
1013		
1014	} else if (p.justify == 'max') {
1015		p.min = Math.floor(p.min - p.span + p.thumbSpan);
1016	}
1017		
1018	if (p.min < p.marginMin) {
1019		tmpMin = p.min;
1020		p.min = p.marginMin; 
1021		if (allowReduce) p.span = p.span - (p.min - tmpMin);
1022	}
1023	return p;
1024};
1025
1026HsExpander.prototype.correctRatio = function(ratio) {
1027	var x = this.x;
1028	var y = this.y;
1029	var changed = false;
1030	if (x.span / y.span > ratio) { // width greater
1031		var tmpWidth = x.span;
1032		x.span = y.span * ratio;
1033		if (x.span < x.minSpan) { // below minWidth
1034			x.span = x.minSpan;	
1035			y.span = x.span / ratio;
1036		}
1037		changed = true;
1038	
1039	} else if (x.span / y.span < ratio) { // height greater
1040		var tmpHeight = y.span;
1041		y.span = x.span / ratio;
1042		changed = true;
1043	}
1044	
1045	if (changed) {
1046		x.min = parseInt(this.thumbLeft) - this.offsetBorderW + this.thumbOffsetBorderW;
1047		x.minSpan = x.span;
1048		this.x = this.justify(x);
1049		
1050		y.min = parseInt(this.thumbTop) - this.offsetBorderH + this.thumbOffsetBorderH;
1051		y.minSpan = y.span;
1052		this.y = this.justify(y);
1053	}
1054};
1055
1056HsExpander.prototype.changeSize = function(dir, x1, y1, w1, h1, x2, y2, w2, h2, dur, steps, oo1, oo2) {
1057	dW = (w2 - w1) / steps;
1058	dH = (h2 - h1) / steps;
1059	dX = (x2 - x1) / steps;
1060	dY = (y2 - y1) / steps;
1061	dOo = (oo2 - oo1) /steps;
1062	for (i = 1; i <= steps; i++) {
1063		w1 += dW;
1064		h1 += dH;
1065		x1 += dX;
1066		y1 += dY;
1067		oo1 += dOo;
1068		
1069		var obj = "hs.expanders["+ this.key +"]";
1070		var s = "try {";
1071		if (i == 1) {
1072			s += obj +".content.style.visibility = 'visible';"
1073				+ "if ("+ obj +".thumb.tagName == 'IMG' && hs.hideThumbOnExpand) "+ obj +".thumb.style.visibility = 'hidden';"
1074		}
1075		if (i == steps) {
1076			w1 = w2;
1077			h1 = h2;
1078			x1 = x2;
1079			y1 = y2;
1080			oo1 = oo2;
1081		}
1082		s += obj +"."+ this.contentType +"SetSize("+ Math.round(w1) +", "+ Math.round(h1) +", "
1083			+ Math.round(x1) +", "+ Math.round(y1) +", "+ Math.round(oo1);
1084		if (i == steps) s += ', '+ dir;
1085		s += ");} catch (e) {}";
1086		setTimeout(s, Math.round(i * (dur / steps)));
1087	}
1088};
1089
1090HsExpander.prototype.imageSetSize = function (w, h, x, y, offset, end) {
1091	try {
1092		this.content.width = w;
1093		this.content.height = h;
1094		
1095		if (this.objOutline && this.outlineWhileAnimating) {
1096			var o = this.objOutline.offset - offset;
1097			this.positionOutline(x + o, y + o, w - 2 * o, h - 2 * o, 1);
1098		}
1099		
1100		hs.setStyles ( this.wrapper,
1101			{
1102				'visibility': 'visible',
1103				'left': x +'px',
1104				'top': y +'px'
1105			}
1106		);
1107		
1108		var exp = 'hs.expanders['+ this.key +']';
1109		if (end == 1) setTimeout('if ('+ exp +')'+ exp +'.onExpanded()', 0); // jerk in IE
1110		else if (end == -1) setTimeout('if ('+ exp +')'+ exp +'.onEndClose()', 0);
1111	} catch (e) {
1112		window.location.href = hs.getSrc(this.a);
1113	}
1114};
1115
1116HsExpander.prototype.positionOutline = function(x, y, w, h, vis) {
1117	if (!this.objOutline) return;
1118	var o = this.objOutline;
1119	if (vis) o.table.style.visibility = 'visible';
1120	o.table.style.left = (x - o.offset) +'px';
1121	o.table.style.top = (y - o.offset) +'px';
1122	o.table.style.width = (w + 2 * (this.offsetBorderW + o.offset)) +'px';
1123	w += 2 * (this.offsetBorderW - o.offset);
1124	h += + 2 * (this.offsetBorderH - o.offset);
1125	o.td[4].style.width = w >= 0 ? w +'px' : 0;
1126	o.td[4].style.height = h >= 0 ? h +'px' : 0;
1127	if (o.hasAlphaImageLoader) o.td[3].style.height = o.td[5].style.height = o.td[4].style.height;
1128};
1129
1130HsExpander.prototype.onExpanded = function() {
1131	if (this.objOutline) this.objOutline.table.style.visibility = 'visible';
1132	this.isExpanded = true;
1133	this.focus();
1134	if (this.isHtml && this.objectLoadTime == 'after') this.writeExtendedContent();
1135	this.createCustomOverlays();
1136	if (hs.showCredits) this.writeCredits();
1137	
1138	if (this.caption) this.writeCaption();
1139	
1140	if (this.fullExpandWidth > this.x.span) this.createFullExpand();
1141	if (!this.caption) this.onDisplayFinished();
1142};
1143
1144HsExpander.prototype.onDisplayFinished = function() {
1145	var key = this.key;
1146	var outlineType = this.outlineType;
1147	new HsOutline(outlineType, function () { 
1148		try { hs.expanders[key].preloadNext();	} catch (e) {}
1149	});
1150};
1151
1152HsExpander.prototype.preloadNext = function() {
1153	var next = hs.getAdjacentAnchor(this.key, 1);	
1154	if (next.onclick.toString().match(/hs\.expand/)) 
1155		var img = hs.createElement('img', { src: hs.getSrc(next) });
1156};
1157
1158HsExpander.prototype.cancelLoading = function() {
1159	this.a.style.cursor = this.originalCursor;	
1160	if (this.loading) hs.loading.style.visibility = 'hidden';		
1161	hs.expanders[this.key] = null;
1162};
1163
1164HsExpander.prototype.writeCredits = function () {
1165	var credits = hs.createElement('a',
1166		{
1167			href: hs.creditsHref,
1168			className: 'highslide-credits',
1169			innerHTML: hs.creditsText,
1170			title: hs.creditsTitle
1171		}
1172	);
1173	this.createOverlay(credits, 'top left');
1174};
1175
1176HsExpander.prototype.writeCaption = function() {
1177	try {
1178		this.wrapper.style.width = this.wrapper.offsetWidth +'px';	
1179		this.caption.style.visibility = 'hidden';
1180		this.caption.className += ' highslide-display-block';
1181		
1182		var height;
1183		if (hs.ie && (hs.ieVersion() < 6 || document.compatMode == 'BackCompat')) {
1184			height = this.caption.offsetHeight;
1185		} else {
1186			var temp = hs.createElement('div', {innerHTML: this.caption.innerHTML}, 
1187				null, null, true); // to get height
1188			this.caption.innerHTML = '';
1189			this.caption.appendChild(temp);	
1190			height = this.caption.childNodes[0].offsetHeight;//parseInt(hs.getStyle(this.caption, 'height'));
1191			this.caption.innerHTML = this.caption.childNodes[0].innerHTML;
1192		}
1193		this.caption.style.overflow = 'hidden';
1194		this.caption.style.height = 0;
1195		
1196		this.caption.style.zIndex = 2;
1197		
1198		if (hs.captionSlideSpeed) {
1199			step = Math.round(height/50);
1200			if (step == 0) step = 1;
1201			step = step * hs.captionSlideSpeed;
1202		} else step = height;
1203
1204		var t = 0;
1205		for (var h = height % step; h <= height; h += step, t += 10) {
1206			var end = (h == height) ? 1 : 0;
1207			var eval = "try { "
1208				+ "hs.expanders["+ this.key +"].placeCaption("+ h +", "+ end +");"
1209				+ "} catch (e) {}";			
1210			setTimeout (eval, t);
1211		}
1212	
1213	} catch (e) {}	
1214};
1215
1216HsExpander.prototype.placeCaption = function(height, end) {
1217	if (!this.caption) return;
1218	this.caption.style.height = height +'px';
1219	this.caption.style.visibility = 'visible';
1220	var o = this.objOutline;
1221	if (o) {
1222		o.td[4].style.height = (this.wrapper.offsetHeight - 2 * this.objOutline.offset) +'px';
1223		if (o.hasAlphaImageLoader) o.td[3].style.height = o.td[5].style.height = o.td[4].style.height;
1224	}
1225	if (end) this.onDisplayFinished();
1226};
1227
1228HsExpander.prototype.showHideElements = function (tagName, visibility, imgPos) {
1229	var els = document.getElementsByTagName(tagName);
1230	if (els) {			
1231		for (i = 0; i < els.length; i++) {
1232			if (els[i].nodeName == tagName) {  
1233				var hiddenBy = els[i].getAttribute('hidden-by');
1234				 
1235				if (visibility == 'visible' && hiddenBy) {
1236					hiddenBy = hiddenBy.replace('['+ this.key +']', '');
1237					els[i].setAttribute('hidden-by', hiddenBy);
1238					if (!hiddenBy) els[i].style.visibility = 'visible';				
1239					
1240				} else if (visibility == 'hidden') { // hide if behind
1241					var elPos = hs.position(els[i]);
1242					elPos.w = els[i].offsetWidth;
1243					elPos.h = els[i].offsetHeight;
1244				
1245					var clearsX = (elPos.x + elPos.w < imgPos.x || elPos.x > imgPos.x + imgPos.w);
1246					var clearsY = (elPos.y + elPos.h < imgPos.y || elPos.y > imgPos.y + imgPos.h);
1247					var wrapperKey = hs.getWrapperKey(els[i]);
1248					if (!clearsX && !clearsY && wrapperKey != this.key) { // element falls behind image
1249						if (!els[i].currentStyle || (els[i].currentStyle && els[i].currentStyle['visibility'] != 'hidden')) { // IE
1250							if (!hiddenBy) {
1251								els[i].setAttribute('hidden-by', '['+ this.key +']');
1252							} else if (!hiddenBy.match('['+ this.key +']')) {
1253								els[i].setAttribute('hidden-by', hiddenBy + '['+ this.key +']');
1254							}
1255							els[i].style.visibility = 'hidden';	  
1256						}
1257					} else if (hiddenBy == '['+ this.key +']' || hs.focusKey == wrapperKey) { // on move
1258						els[i].setAttribute('hidden-by', '');
1259						els[i].style.visibility = 'visible';
1260					} else if (hiddenBy && hiddenBy.match('['+ this.key +']')) {
1261						els[i].setAttribute('hidden-by', hiddenBy.replace('['+ this.key +']', ''));
1262					}
1263				}   
1264			}
1265		}
1266	}
1267};
1268
1269HsExpander.prototype.focus = function() {
1270	// blur others
1271	for (i = 0; i < hs.expanders.length; i++) {
1272		if (hs.expanders[i] && i == hs.focusKey) {
1273			var blurExp = hs.expanders[i];
1274			blurExp.content.className += ' highslide-'+ blurExp.contentType +'-blur';
1275			if (blurExp.caption) {
1276				hs.setId(blurExp.caption, '-hsBlur'+i);
1277				blurExp.caption.className += ' highslide-caption-blur';
1278			}
1279			if (blurExp.isImage) {
1280				blurExp.content.style.cursor = hs.ie ? 'hand' : 'pointer';
1281				blurExp.content.title = hs.focusTitle;	
1282			} else { hs.setId(blurExp.innerContent, '-hsBlur'+i); }
1283		}
1284	}
1285	
1286	// focus this
1287	this.wrapper.style.zIndex = hs.zIndexCounter++;
1288	if (this.objOutline) this.objOutline.table.style.zIndex = this.wrapper.style.zIndex;
1289	
1290	this.content.className = 'highslide-'+ this.contentType;
1291	if (this.caption) {
1292		hs.setId(this.caption, '-hsBlur' + this.key, 1);
1293		this.caption.className = this.caption.className.replace(' highsli
1293de-caption-blur', '');
1294	}
1295	
1296	if (this.isImage) {
1297		this.content.title = hs.restoreTitle;
1298		
1299		hs.styleRestoreCursor = window.opera ? 'pointer' : 'url('+ hs.graphicsDir + hs.restoreCursor +'), pointer';
1300		if (hs.ie && hs.ieVersion() < 6) hs.styleRestoreCursor = 'hand';
1301		this.content.style.cursor = hs.styleRestoreCursor;
1302	} else {
1303		hs.setId(this.innerContent, '-hsBlur' + this.key, 1);
1304	}
1305	
1306	hs.focusKey = this.key;	
1307	hs.addEventListener(document, 'keydown', hs.keyHandler);
1308	
1309};
1310
1311HsExpander.prototype.onClick = function() {
1312	this.doClose();
1313};
1314
1315HsExpander.prototype.doClose = function() {
1316	hs.removeEventListener(document, 'keydown', hs.keyHandler);
1317	try {
1318		this.isClosing = true;
1319		
1320		var x = parseInt(this.wrapper.style.left);
1321		var y = parseInt(this.wrapper.style.top);
1322		var w = (this.isImage) ? this.content.width : parseInt(this.content.style.width);
1323		var h = (this.isImage) ? this.content.height : parseInt(this.content.style.height);
1324		
1325		if (this.objOutline) {
1326			if (this.outlineWhileAnimating) this.positionOutline(x, y, w, h);
1327			else if (this.preserveContent) this.objOutline.table.style.visibility = 'hidden';
1328			else this.objOutline.destroy();
1329		}
1330		
1331		// remove children
1332		var n = this.wrapper.childNodes.length;
1333		for (i = n - 1; i >= 0 ; i--) {
1334			var child = this.wrapper.childNodes[i];
1335			if (child != this.content) {
1336				hs.purge(this.wrapper.childNodes[i]);
1337				this.wrapper.removeChild(this.wrapper.childNodes[i]);
1338			}
1339		}
1340		if (this.isHtml) this.htmlOnClose();
1341		
1342		this.wrapper.style.width = 'auto';
1343		this.content.style.cursor = 'default';
1344		var o2 = this.objOutline ? this.objOutline.offset : 0;
1345		
1346		this.changeSize(
1347			-1,
1348			x,
1349			y,
1350			w,
1351			h,
1352			this.thumbLeft - this.offsetBorderW + this.thumbOffsetBorderW,
1353			this.thumbTop - this.offsetBorderH + this.thumbOffsetBorderH,
1354			this.thumbWidth,
1355			this.thumbHeight, 
1356			hs.restoreDuration,
1357			hs.restoreSteps,
1358			o2,
1359			hs.outlineStartOffset
1360		);
1361		
1362	} catch (e) {
1363		this.onEndClose();
1364	} 
1365};
1366
1367HsExpander.prototype.onEndClose = function () {
1368	this.thumb.style.visibility = 'visible';
1369	
1370	if (hs.hideSelects) this.showHideElements('SELECT', 'visible');
1371	if (hs.hideIframes) this.showHideElements('IFRAME', 'visible');
1372	
1373	if (this.preserveContent) this.sleep();
1374	else {
1375		if (this.objOutline && this.outlineWhileAnimating) this.objOutline.destroy();
1376	
1377		hs.purge(this.wrapper);
1378		this.wrapper.parentNode.removeChild(this.wrapper);
1379	}
1380	hs.expanders[this.key] = null;
1381
1382	hs.cleanUp();
1383};
1384
1385HsExpander.prototype.createOverlay = function (el, position, hideOnMouseOut, opacity) {
1386	if (typeof el == 'string') el = hs.cloneNode(el);
1387	if (!el || typeof el == 'string' || !this.isImage) return;
1388	
1389	if (!opacity) opacity = 1;
1390	if (!position) position = 'center center';
1391	var overlay = hs.createElement(
1392		'div',
1393		null,
1394		{
1395			'left' : 0,
1396			'top' : 0,
1397			'position' : 'absolute',
1398			'zIndex' : 3,
1399			'visibility' : 'hidden',
1400			'opacity' : opacity
1401		},
1402		this.wrapper,
1403		true
1404	);
1405	el.className += ' highslide-display-block';
1406	overlay.appendChild(el);	
1407	
1408	var left = this.offsetBorderW;
1409	var dLeft = this.content.width - overlay.offsetWidth;
1410	var top = this.offsetBorderH;
1411	var dTop = this.content.height - overlay.offsetHeight;
1412	
1413	if (position.match(/^bottom/)) top += dTop;
1414	if (position.match(/^center/)) top += dTop / 2;
1415	if (position.match(/right$/)) left += dLeft;
1416	if (position.match(/center$/)) left += dLeft / 2;
1417	overlay.style.left = left +'px';
1418	overlay.style.top = top +'px';
1419	
1420	if (hideOnMouseOut) overlay.setAttribute('hideOnMouseOut', true);
1421	overlay.setAttribute('opacity', opacity);
1422	hs.fade(overlay, 0, opacity, 1);
1423	
1424	hs.push(this.overlays, overlay);
1425};
1426
1427HsExpander.prototype.createCustomOverlays = function() {
1428	for (i = 0; i < hs.overlays.length; i++) {
1429		var o = hs.overlays[i];
1430		if (o.thumbnailId == null || o.thumbnailId == this.thumbsUserSetId) {
1431			this.createOverlay(o.overlayId, o.position, o.hideOnMouseOut, o.opacity);
1432		}
1433	}
1434};
1435
1436HsExpander.prototype.onMouseOver = function () {
1437	for (i = 0; i < this.overlays.length; i++) {
1438		hs.fade(this.overlays[i], 0, this.overlays[i].getAttribute('opacity'), 1);
1439	}
1440};
1441
1442HsExpander.prototype.onMouseOut = function() {
1443	var hideThese = new Array();
1444	var j = 0;
1445	for (i = 0; i < this.overlays.length; i++) {
1446		if (this.overlays[i].getAttribute('hideOnMouseOut')) {
1447			hideThese[j] = this.overlays[i];
1448			j++;
1449		}
1450	}
1451	for (i = 0; i < hideThese.length; i++) {		
1452		hs.fade(hideThese[i], hideThese[i].getAttribute('opacity'), 0, -1);
1453	}
1454};
1455
1456
1457HsExpander.prototype.createFullExpand = function () {
1458	var a = hs.createElement(
1459		'a',
1460		{
1461			href: 'javascript:hs.expanders['+ this.key +'].doFullExpand();',
1462			title: hs.fullExpandTitle
1463		},
1464		{
1465			background: 'url('+ hs.graphicsDir + hs.fullExpandIcon+')',
1466			display: 'block',
1467			margin: '0 10px 10px 0',
1468			width: '45px',
1469			height: '44px'
1470		}, null, true
1471	);
1472	
1473	this.createOverlay(a, 'bottom right', true, 0.75);
1474	this.fullExpandIcon = a;
1475};
1476
1477HsExpander.prototype.doFullExpand = function () {
1478	try {
1479		hs.purge(this.fullExpandIcon);
1480		this.fullExpandIcon.parentNode.removeChild(this.fullExpandIcon);
1481		this.focus();
1482		
1483		this.x.min = parseInt(this.wrapper.style.left) - (this.fullExpandWidth - this.content.width) / 2;
1484		if (this.x.min < hs.marginLeft) this.x.min = hs.marginLeft;		
1485		this.wrapper.style.left = this.x.min +'px';
1486		
1487		var borderOffset = this.wrapper.offsetWidth - this.content.width;		
1488		
1489		this.content.width = this.fullExpandWidth;
1490		this.content.height = this.fullExpandHeight;
1491		
1492		this.x.span = this.content.width;
1493		this.wrapper.style.width = (this.x.span + borderOffset) +'px';
1494		
1495		this.y.span = this.wrapper.offsetHeight - 2 * this.offsetBorderH;
1496		this.positionOutline(this.x.min, this.y.min, this.x.span, this.y.span);
1497		
1498		// reposition overlays
1499		for (var i = 0; i < this.overlays.length; i++) {
1500			hs.purge(this.overlays[i]);
1501			this.overlays[i].parentNode.removeChild(this.overlays[i]);
1502		}	
1503		if (hs.showCredits) this.writeCredits();
1504		this.createCustomOverlays();
1505		
1506		this.redoShowHide();
1507	
1508	} catch (e) {
1509		window.location.href = this.content.src;
1510	}
1511};
1512
1513// on end move and resize
1514HsExpander.prototype.redoShowHide = function() {
1515	var imgPos = {
1516		x: parseInt(this.wrapper.style.left) - 20, 
1517		y: parseInt(this.wrapper.style.top) - 20, 
1518		w: this.content.offsetWidth + 40, 
1519		h: this.content.offsetHeight + 40 + this.spaceForCaption
1520	};
1521	if (hs.hideSelects) this.showHideElements('SELECT', 'hidden', imgPos);
1522	if (hs.hideIframes) this.showHideElements('IFRAME', 'hidden', imgPos);
1523
1524};
1525
1526// set handlers
1527hs.addEventListener(document, 'mousedown', hs.mouseClickHandler);
1528hs.addEventListener(document, 'mouseup', hs.mouseClickHandler);
1529hs.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.