PageSourceSearch

https://elitonshop.ru/published/SC/html/scripts/3rdparty/highslide/highslide.js

js elitonshop.ru collected 2026-10-08 23:49:38 UTC 45,367 bytes, 1,515 lines download raw bytes

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