PageSourceSearch

https://gbi-complex.ru/js/WB_Gallery.class.js?v=20220328095306

js gbi-complex.ru collected 2026-10-05 00:27:32 UTC 22,618 bytes, 697 lines download raw bytes

1
2/**
3 * Gallery element class
4 * 
5 * @author Marius Tomas <[email protected]>
6 * @version 2.1.1, 2012-08-30
7 * @param {Object} data
8 */
9function WB_Gallery(data) { this.__construct(data); }
10
11WB_Gallery.prototype.elem = null;
12WB_Gallery.prototype.id = null;
13WB_Gallery.prototype.type = "thumbs";
14WB_Gallery.prototype.slideshowInterval = 10;
15WB_Gallery.prototype.slideshowSpeed = 400;
16WB_Gallery.prototype.images = [];
17WB_Gallery.prototype.imageIndex = 0;
18WB_Gallery.prototype.slideshowTimer = null;
19WB_Gallery.prototype.displayedImage = null;
20WB_Gallery.prototype.loadingImage = null;
21WB_Gallery.prototype.listImgCont = null;
22WB_Gallery.prototype.thumbImgCont = null;
23WB_Gallery.prototype.fullThumbWidth = 0;
24WB_Gallery.prototype.fullThumbHeight = 0;
25WB_Gallery.prototype.thumbWidth = 64;
26WB_Gallery.prototype.thumbHeight = 64;
27WB_Gallery.prototype.columnWidth = 70;
28WB_Gallery.prototype.rowHeight = 70;
29WB_Gallery.prototype.thumbAlign = "left";
30WB_Gallery.prototype.thumbPadding = 6;
31WB_Gallery.prototype.thumbOpacity = 100;
32WB_Gallery.prototype.isFullWidth = false;
33WB_Gallery.prototype.width = 320;
34WB_Gallery.prototype.height = 240;
35WB_Gallery.prototype.border = null;
36WB_Gallery.prototype.borderWidths = null;
37WB_Gallery.prototype.padding = null;
38WB_Gallery.prototype.galleryPath = "";
39WB_Gallery.prototype.imageCover = false;
40WB_Gallery.prototype.disablePopup = false;
41WB_Gallery.prototype.showPictureCaption = "always";
42WB_Gallery.prototype.displayedCaption = null;
43WB_Gallery.prototype.initialRender = false;
44WB_Gallery.prototype.onImageDisplayed = null;
45
46WB_Gallery.lightBoxInited = false;
47
48var galleryList = [];
49WB_Gallery.getGalleryList = function() {
50	return galleryList;
51};
52
53/**
54 * Construct gallery element
55 * @param data gallery data object
56 */
57WB_Gallery.prototype.__construct = function(data) {
58	galleryList.push(this);
59	this.elem = $("#" + data.id);
60	this.slideshowTimer = null;
61	this.id = data.id;
62	this.type = data.type;
63	this.thumbWidth = data.thumbWidth;
64	this.thumbHeight = data.thumbHeight;
65	this.columnWidth = data.columnWidth;
66	this.rowHeight = data.rowHeight;
67	this.thumbAlign = data.thumbAlign;
68	this.thumbPadding = data.thumbPadding;
69	this.thumbOpacity = data.thumbOpacity;
70	this.slideshowInterval = data.interval;
71	this.slideshowSpeed = data.speed;
72	this.images = data.images;
73	this.imageIndex = 0;
74	this.border = data.border;
75	this.borderWidths = data.borderWidths;
76	this.padding = data.padding;
77	this.isFullWidth = data.fullWidth;
78	this.width = this.elem.width();
79	this.height = this.elem.height();
80	this.imageCover = data.imageCover;
81	this.disablePopup = data.disablePopup;
82	this.showPictureCaption = data.showPictureCaption;
83	if (!window.wb_builder) {
84		this.initialRender = true;
85	}
86	switch (this.type) {
87		case "slideshow": this.renderSlideshow(); break;
88		case "list": this.renderList(); break;
89		case "masonry": this.renderMasonry(); break;
90		default: this.renderThumbs(); break;
91	}
92};
93
94WB_Gallery.prototype.renderThumbs = function() {
95	this.displayedImage = null;
96	this.loadingImage = null;
97	var elem = null;
98	this.elem.html(elem = $('<div class="wb-thumbs-only" style="width: 100%; height: 100%; overflow: auto;"></div>'));
99	this.elem.css("text-align", this.thumbAlign);
100	for (var i = 0; i < this.images.length; i++) {
101		this.addImage(elem, this.images[i], i, false);
102	}
103	elem.children('.wb_thumb').css('padding', (this.thumbPadding / 2) + 'px');
104};
105
106WB_Gallery.prototype.renderSlideshow = function() {
107	var thisClass = this;
108	this.displayedImage = null;
109	this.loadingImage = null;
110	var cont = $(
111		'<div class="gallery-slideshow">'+
112			'<div class="gallery-slide-image" style="overflow: hidden;"></div>'+
113			'<div class="gallery-slide-left"><i class="fa fa-chevron-left"></i></div>'+
114			'<div class="gallery-slide-right"><i class="fa fa-chevron-right"></i></div>'+
115		'</div>'
116	);
117	this.elem.html(cont);
118	this.listImgCont = cont.children("div").eq(0);
119	this.listImgCont.css('opacity', (this.thumbOpacity / 100));
120	var larr = cont.children("div").eq(1);
121	var rarr = cont.children("div").eq(2);
122
123	larr.click(function() {
124		thisClass.slideshowPrev();
125	});
126
127	rarr.click(function() {
128		thisClass.slideshowNext();
129	});
130
131	$(window).on('resize', function() {
132		var w = thisClass.elem.width(), h = thisClass.elem.height();
133		if (w !== thisClass.width || h !== thisClass.height) {
134			thisClass.width = w;
135			thisClass.height = h;
136			thisClass.displayImage(thisClass.listImgCont);
137		}
138	});
139	if (this.slideshowTimer)
140		clearInterval(this.slideshowTimer);
141	if( this.slideshowInterval && this.images.length > 1 ) {
142		this.slideshowTimer = setTimeout(function() {
143			thisClass.slideshowNext();
144		}, this.slideshowInterval * 1000);
145	}
146	else
147		this.slideshowTimer = null;
148	this.imageIndex = -1;
149	this.slideshowNext();
150};
151
152WB_Gallery.prototype.renderList = function() {
153	var thisClass = this;
154	this.elem.empty();
155	this.displayedImage = null;
156	this.loadingImage = null;
157
158	var w = this.width;
159	var h = this.height;
160	var tw = this.thumbWidth;
161	var th = this.thumbHeight;
162
163	//var pad = 3;
164	
165	var thumbcont = $('<div></div>');
166	this.callback = function() {
167		var img = thisClass.imageElems[thisClass.imageIndex];
168		$(img.parentNode.parentNode.parentNode).children(".tmb-selected").removeClass("tmb-selected");
169		$(img.parentNode.parentNode).addClass("tmb-selected");
170	};
171	this.imageElems = {};
172
173	//var images = [];
174	for (var i = 0; i < this.images.length; i++) {
175		var img = this.addImage(thumbcont, this.images[i], i, true);
176		img.idx = i;
177		this.imageElems[img.idx] = img;
178		$(img).css({cursor: "pointer"});
179		$(img).click(function() {
180			thisClass.imageIndex = this.idx;
181			thisClass.displayImage(thisClass.listImgCont, thisClass.callback);
182		});
183		//var par_in = $(img.parentNode);
184		var par = $(img.parentNode.parentNode);
185		if (i === this.imageIndex) {
186		   par.addClass("tmb-selected");
187			tw = this.thumbWidth + 8;
188			th = this.thumbHeight + 8;
189  		}
190	}
191
192	this.fullThumbWidth = tw;
193	this.fullThumbHeight = th;
194
195	thumbcont.css({position: "absolute", left: "0", top: "5px", width: (tw * this.images.length) + "px", height: th + "px"});
196
197	var galcont = $('<div></div>');
198	galcont.css({position: "relative", width: w + "px", height: h + "px"});
199	galcont.addClass("gallery-list");
200
201	var imgcont = $('<div></div>');
202	imgcont.css({position: "relative", width: w + "px", height: (h - th - 10) + "px", overflow: "hidden"});
203	imgcont.addClass("gallery-list-image");
204
205	var icon;
206
207	var thumbdiv_in1 = document.createElement("DIV");
208	$(thumbdiv_in1).css({position: "relative", "float": "left", width: "16px", height: (th + 10) + "px", cursor: "pointer"});
209	thumbdiv_in1.className = "gallery-list-left";
210	$(thumbdiv_in1).click(function() {
211		thisClass.slideBy(-thisClass.fullThumbWidth * 3);
212	});
213	icon = document.createElement("I");
214	icon.setAttribute("class", "fa fa-chevron-left");
215	thumbdiv_in1.appendChild(icon);
216
217	var thumbdiv_in2 = $('<div></div>');
218	thumbdiv_in2.css({position: "relative", "float": "left", width: (w-32) + "px", height: (th + 10) + "px", overflow: "hidden"});
219	thumbdiv_in2.addClass("gallery-list-thumbs");
220
221	var thumbdiv_in3 = document.createElement("DIV");
222	$(thumbdiv_in3).css({position: "relative", "float": "left", width: "16px", height: (th + 10) + "px", cursor: "pointer"});
223	thumbdiv_in3.className = "gallery-list-right";
224	$(thumbdiv_in3).click(function() {
225		thisClass.slideBy(thisClass.fullThumbWidth * 3);
226	});
227	icon = document.createElement("I");
228	icon.setAttribute("class", "fa fa-chevron-right");
229	thumbdiv_in3.appendChild(icon);
230
231	var thumbdiv = $('<div></div>');
232	thumbdiv.css({position: "relative", width: w + "px", height: (th + 10) + "px", overflow: "hidden"});
233
234	thumbdiv_in2.append(thumbcont);
235
236	thumbdiv.append(thumbdiv_in1);
237	thumbdiv.append(thumbdiv_in2);
238	thumbdiv.append(thumbdiv_in3);
239
240	galcont.append(imgcont);
241	galcont.append(thumbdiv);
242	
243	$(window).on('resize', function() {
244		var w = thisClass.elem.width(), h = thisClass.elem.height();
245		if (w !== thisClass.width || h !== thisClass.height) {
246			thisClass.width = w;
247			thisClass.height = h;
248			galcont.css({width: w, height: h});
249			imgcont.css({width: w, height: (h - th - 10)});
250			thumbdiv_in2.css({width: (w - 32)});
251			thumbdiv.css({width: w});
252			thisClass.displayImage(thisClass.listImgCont);
253		}
254	});
255
256	this.listImgCont = imgcont;
257	this.thumbImgCont = thumbdiv_in2;
258	this.elem.append(galcont);
259	// this.displayImage(this.listImgCont);
260	
261	if (this.slideshowTimer)
262		clearInterval(this.slideshowTimer);
263	if( this.slideshowInterval && this.images.length > 1 ) {
264		this.slideshowTimer = setTimeout(function() {
265			thisClass.slideshowNext(thisClass.callback);
266		}, this.slideshowInterval * 1000);
267	}
268	else
269		this.slideshowTimer = null;
270	this.imageIndex = -1;
271	this.slideshowNext(this.callback);
272};
273
274WB_Gallery.prototype.renderMasonry = function() {
275	this.displayedImage = null;
276	this.loadingImage = null;
277	var elem = $('<div class="wb-masonry-items"/>');
278	var cont = $('<div class="wb-masonry" style="width: 100%; height: 100%; overflow: auto;"/>');
279	cont.append(elem);
280	this.elem.append(cont);
281	if( this.thumbAlign === "left" )
282		elem.css("float", "left");
283	else if( this.thumbAlign === "right" )
284		elem.css("float", "right");
285	else
286		elem.css("margin", "0 auto");
287
288	for (var i = 0; i < this.images.length; i++) {
289		this.addImage(elem, this.images[i], i, false);
290	}
291	elem.children('.wb_thumb').css('padding', (this.thumbPadding / 2) + 'px');
292
293	elem.masonry({
294		itemSelector: ".wb_thumb",
295		columnWidth: this.columnWidth,
296		fitWidth: true/*,
297		transitionDuration: 0 */
298	});
299
300	var thisClass = this;
301	var lastWidth = this.elem.width();
302	$(window).on('resize', function() {
303		var elemWidth = thisClass.elem.width();
304		if (elemWidth !== lastWidth) {
305			lastWidth = elemWidth;
306			if (elemWidth < thisClass.columnWidth + thisClass.thumbPadding) {
307				elem.find('.wb_thumb img').css({ width: (elemWidth - thisClass.thumbPadding) + 'px', height: 'auto' });
308			} else {
309				elem.find('.wb_thumb img').css({ width: '', height: '' });
310			}
311		}
312	});
313};
314
315WB_Gallery.prototype.slideBy = function(delta) {
316	var cont = $(this.thumbImgCont);
317	var div = $(this.thumbImgCont).children("div").eq(0);
318	var pos = div.position();
319	var x = pos ? pos.left : 0;
320	x -= delta;
321	var minx = -(div.width() - cont.width());
322	if( x < minx ) x = minx;
323	if( x > 0 ) x = 0;
324	div.animate({left: x + "px"});
325};
326
327WB_Gallery.prototype.calcImageStyles = function(displayCont, cont, image) {
328	var bw, bh;
329	var cover = this.isFullWidth || this.imageCover;
330	/* if( cover ) {
331		bw = bh = 0;
332	}
333	else if( typeof this.border === "object" && this.border.weight && typeof this.border.weight === "object" ) {
334		if (this.border.differ) {
335			bh = ((this.border.style[0] === "none") ? 0 : this.border.weight[0]) + ((this.border.style[2] === "none") ? 0 : this.border.weight[2]);
336			bw = ((this.border.style[1] === "none") ? 0 : this.border.weight[1]) + ((this.border.style[3] === "none") ? 0 : this.border.weight[3]);
337		} else {
338			bh = bw = ((this.border.style[0] === "none") ? 0 : (this.border.weight[0] * 2));
339		}
340	}
341	else {
342		bw = ((this.border.style === "none") ? 0 : (this.border.weight * 2));
343		bh = ((this.border.style === "none") ? 0 : (this.border.weight * 2));
344	} */
345
346	bw = bh = 0; // since img element is "box-sizing: border-box" it means that border size is automatically included in total image size
347	var pad = cover ? 0 : this.padding;
348	var maxWidth = (displayCont.innerWidth() - pad * 2 - bw);
349	var maxHeight = (displayCont.innerHeight() - pad * 2 - bh);
350
351	var w = image.width;
352	var h = image.height;
353	if (cover || w > maxWidth || h > maxHeight) { // One of these is larger than the window
354		var ratio1 = w / maxWidth;
355		var ratio2 = h / maxHeight;
356		var ratio = cover ? Math.min(ratio1, ratio2) : Math.max(ratio1, ratio2);
357		w = Math.floor(w / ratio);
358		h = Math.floor(h / ratio);
359	}
360	return {
361		left: Math.floor((maxWidth - w) / 2 + pad),
362		top: Math.floor((maxHeight - h) / 2 + pad),
363		image_width: w,
364		image_height: h
365	};
366};
367
368WB_Gallery.prototype.displayImage = function(display_cont, callback) {
369	var thisClass = this;
370
371	var image = this.images[this.imageIndex];
372	if (!image) return;
373	
374	if (typeof callback == 'function') callback();
375	var link = (this.type !== "thumbs" && this.type !== "masonry" && image.hasOwnProperty("link") && image.link) ? image.link : null;
376	var cont = $(link ? "<a>" : "<div>");
377	if( link ) {
378		cont.attr("href", link.url);
379		if( link.target )
380			cont.attr("target", link.target);
381	}
382	var title = (image.hasOwnProperty("title") && image.title && image.title !== "") ? image.title : "";
383	if( title === "" && link && link.name )
384		title = link.name;
385	cont.attr("title", title);
386	cont.imageIndex = this.imageIndex;
387	var jcont = cont;
388	cont.addClass("gallery-image");
389//	cont.css((this.isFullWidth || this.imageCover) ? {border: "none"} : this.border.css);
390
391	var stl = this.calcImageStyles(display_cont, cont, image);
392
393	var caption = $('<div class="wb-picture-caption"/>');
394	if( !this.fillCaptionContainer(caption, image, false, true) )
395		caption = null;
396	else {
397		if( this.showPictureCaption === "hover" )
398			caption.addClass("wb-on-hover");
399		caption.css({
400			opacity: 0, // set initial opacity so that caption would fade in
401			transition: "opacity " + (thisClass.slideshowSpeed / 1000).toFixed(3) + "s linear"
402		});
403	}
404
405	jcont.css({
406		display: "none",
407		position: "absolute",
408		left: stl.left + "px",
409		top: stl.top + "px"
410	});
411	var img = new Image();
412	cont.append(img);
413	img.width = stl.image_width;
414	img.height = stl.image_height;
415	$(img).css({ width: stl.image_width, height: stl.image_height });
416	$(img).css((this.isFullWidth || this.imageCover) ? {border: "none"} : this.border.css);
417	img.alt = "";
418	img.onload = function() {
419		if (thisClass.displayedImage) {
420			thisClass.displayedImage.fadeOut(thisClass.slideshowSpeed);
421		}
422		if (thisClass.displayedCaption) {
423			thisClass.displayedCaption.css({
424				opacity: 0,
425				transition: "opacity " + (thisClass.slideshowSpeed / 1000).toFixed(3) + "s linear"
426			});
427			setTimeout((function() {
428				this.remove();
429			}).bind(thisClass.displayedCaption), thisClass.slideshowSpeed);
430		}
431		thisClass.displayedCaption = caption;
432		jcont.fadeIn(thisClass.slideshowSpeed, function() {
433			if (thisClass.displayedImage) {
434				thisClass.displayedImage.remove();
435			}
436			if (cont.parent() && cont.parent().length) {
437				thisClass.displayedImage = cont;
438			} else {
439				thisClass.displayedImage = null;
440			}
441			thisClass.loadingImage = null;
442			if (thisClass.slideshowTimer) {
443				if (thisClass.slideshowTimer)
444					clearTimeout(thisClass.slideshowTimer);
445				if( thisClass.slideshowInterval && thisClass.images.length > 1 ) {
446					thisClass.slideshowTimer = setTimeout(function(){
447						thisClass.slideshowNext(thisClass.callback);
448					}, thisClass.slideshowInterval * 1000);
449				}
450				else
451					thisClass.slideshowTimer = null;
452			}
453		});
454	};
455	display_cont.append(cont);
456
457	if( caption ) {
458		display_cont.append(caption);
459		setTimeout((function() {
460			this.css("opacity", ""); // Reset opacity to one in css rules on the next frame
461		}).bind(caption), 0);
462		setTimeout((function() {
463			this.css("transition", ""); // Reset transition to one in css rules after fade in has finished
464		}).bind(caption), thisClass.slideshowSpeed);
465	}
466
467	this.loadingImage = cont;
468	img.src = image.image;
469	if( !link )
470		this.initImageLightBox(img, this.imageIndex);
471	
472	if (typeof this.onImageDisplayed === 'function') this.onImageDisplayed(img.src);
473};
474
475WB_Gallery.prototype.parseHash = function () {
476	var hash = window.location.hash.substring(1),
477		params = {gid: '', pid: ''};
478
479	if(hash.length < 5) {
480		return params;
481	}
482
483	var vars = hash.split('&');
484	for (var i = 0; i < vars.length; i++) {
485		if(!vars[i]) {
486			continue;
487		}
488		var pair = vars[i].split('=');
489		if(pair.length < 2) {
490			continue;
491		}
492		if (i == 1 && pair) {
493			params.gid = pair[1];
494		}
495
496		if (i == 2 && pair) {
497			params.pid = pair[1];
498		}
499	}
500	return params;
501};
502
503WB_Gallery.prototype.initImageLightBox = function(img, imageIndex) {
504	var lightBoxInited = WB_Gallery.lightBoxInited;
505	WB_Gallery.lightBoxInited = true;
506	var params;
507	if ((this.type === 'slideshow' || this.type === 'list') && this.disablePopup)
508		return;
509	if (this.initialRender) {
510		params = this.parseHash();
511		imageIndex = params.pid ? parseInt(params.pid) : imageIndex;
512	}
513
514	var lightBoxElem = $('body > .pswp');
515	var thisSelf = this;
516
517	if (!lightBoxInited && this.initialRender && params && params.pid) {
518		var images = [];
519		for( var i = 0, il = thisSelf.images.length; i < il; i++ ) {
520			var image = thisSelf.images[i];
521			var title = image.hasOwnProperty("title") ? image.title : null;
522			images.push({
523				src: image.image,
524				w: image.width,
525				h: image.height,
526				/* do not use thumb because it has different size proportions
527				 * comparing to original image. This leads to glitchy effect
528				 * original image appearing in photoswipe.
529				 */
530				// msrc: image.thumb
531				msrc: null,
532				title: (title === null || title === "") ? "- wb-untitled -" : title, // title must not be empty if we want to see the caption block at all
533				link: (image.hasOwnProperty("link") && image.link) ? image.link : null,
534				description: image.hasOwnProperty("description") ? image.description : null
535			});
536		}
537		(new PhotoSwipe(lightBoxElem.get(0), PhotoSwipeUI_Default, images, {
538			index: imageIndex,
539			addCaptionHTMLFn: function(item, captionElement, isFake) {
540				var $cont = $(captionElement.children[0]);
541				$cont.empty();
542				return thisSelf.fillCaptionContainer($cont, item, true, true);
543			}
544		})).init();
545
546		thisSelf.initialRender = false;
547	}
548
549	$(img)
550		.css({cursor: "pointer"})
551		.on("click touchstart touchend touchmove", function(e) {
552			if (e.type === 'touchstart') {
553				$(this).data('pswpDisabled', false);
554			} else if (e.type === 'touchmove') {
555				$(this).data('pswpDisabled', true);
556			}
557			if ((e.type === 'click' || e.type === 'touchend') && !$(this).data('pswpDisabled')) {
558				var images = [];
559				for( var i = 0, il = thisSelf.images.length; i < il; i++ ) {
560					var image = thisSelf.images[i];
561					var title = image.hasOwnProperty("title") ? image.title : null;
562					images.push({
563						src: image.image,
564						w: image.width,
565						h: image.height,
566						/* do not use thumb because it has different size proportions
567						 * comparing to original image. This leads to glitchy effect
568						 * original image appearing in photoswipe.
569						 */
570						// msrc: image.thumb
571						msrc: null,
572						title: (title === null || title === "") ? "- wb-untitled -" : title, // title must not be empty if we want to see the caption block at all
573						link: (image.hasOwnProperty("link") && image.link) ? image.link : null,
574						description: image.hasOwnProperty("description") ? image.description : null
575					});
576				}
577				(new PhotoSwipe(lightBoxElem.get(0), PhotoSwipeUI_Default, images, {
578					index: imageIndex,
579					addCaptionHTMLFn: function(item, captionElement, isFake) {
580						var $cont = $(captionElement.children[0]);
581						$cont.empty();
582						return thisSelf.fillCaptionContainer($cont, item, true, true);
583					}
584				})).init();
585				
586				lightBoxElem.attr('id', thisSelf.id + '_pswp');
587			}
588		});
589};
590
591WB_Gallery.prototype.slideshowNext = function(callback) {
592	if (this.images.length === 0) return;
593	this.imageIndex++;
594	if (this.imageIndex >= this.images.length) {
595		this.imageIndex = 0;
596	}
597	this.displayImage(this.elem.children().first().children().first(), callback);
598};
599
600WB_Gallery.prototype.slideshowPrev = function(callback) {
601	if (this.images.length === 0) return;
602	this.imageIndex--;
603	if (this.imageIndex < 0) {
604		this.imageIndex = this.images.length - 1;
605	}
606	this.displayImage(this.elem.children().first().children().first(), callback);
607};
608
609WB_Gallery.prototype.addImage = function(cont, image, imageIndex, nolightbox) {
610	var isThumbsOnlyMode = (this.type === "thumbs" || this.type === "masonry");
611	var link = (isThumbsOnlyMode && image.hasOwnProperty("link") && image.link) ? image.link : null;
612	var div = $(link ? "<a/>" : "<div/>");
613	if( link ) {
614		div.attr("href", link.url);
615		if( link.target )
616			div.attr("target", link.target);
617	}
618	div.addClass("wb_thumb");
619
620	var bdiv = $("<div/>");
621
622	var img = document.createElement("IMG");
623	img.src = image.thumb;
624	if( image.image === image.thumb ) {
625		var w = image.width;
626		var h = image.height;
627		var k, th;
628		if( this.type === 'masonry' ) {
629			k = w / this.thumbWidth;
630		}
631		else {
632			var k1 = w / this.thumbWidth;
633			var k2 = h / this.thumbHeight;
634			k = Math.min(k1, k2);
635		}
636		if( !k )
637			k = 1;
638		w = w / k;
639		h = h / k;
640		th = (this.type === 'masonry') ? h : this.thumbHeight;
641		img.width = w;
642		img.height = h;
643		$(img).css({position: "absolute", left: (this.thumbWidth - w) / 2, top: (th - h) / 2});
644		bdiv.css({position: "relative", "box-sizing": "content-box", width: this.thumbWidth, height: th, overflow: "hidden"});
645	}
646	else {
647		img.width = this.thumbWidth;
648		if( this.type === 'masonry' && image.width )
649			img.height = Math.round(this.thumbWidth * image.height / image.width);
650		else
651			img.height = this.thumbHeight;
652	}
653	var title = (image.hasOwnProperty("title") && image.title && image.title !== "") ? image.title : "";
654	if( title === "" && link && link.name )
655		title = link.name;
656	div.attr("title", title);
657	img.alt = title;
658	$(img).css({zIndex: "1"});
659	if (!nolightbox && !link) {
660		this.initImageLightBox(img, imageIndex);
661	}
662	if ((this.type === 'thumbs' || this.type === 'masonry') && this.border && this.border.css) {
663		bdiv.css(this.border.css);
664	}
665	bdiv.append(img);
666	if( isThumbsOnlyMode && this.thumbWidth >= 100 ) {
667		var descDiv = $('<div class="wb-picture-caption"/>');
668		if( this.fillCaptionContainer(descDiv, image, false, false) ) {
669			if( this.showPictureCaption === "hover" )
670				descDiv.addClass("wb-on-hover");
671			bdiv.append(descDiv);
672		}
673	}
674	div.append(bdiv);
675	cont.append(div);
676	return img;
677};
678
679WB_Gallery.prototype.fillCaptionContainer = function($cont, item, createLink, createDescription) {
680	var title = (item.title === "- wb-untitled -") ? "" : item.title;
681	var link = createLink ? item.link : null;
682	var titleVisible = title !== "" || link;
683	var descriptionVisible = createDescription && item.description && item.description !== "";
684	if( !titleVisible && !descriptionVisible )
685		return false;
686	if( titleVisible ) {
687		var $title = $('<h3 class="wb-lightbox-title">');
688		var text = (title !== "") ? title : link.name;
689		var $text = link ? $('<a>').attr("href", link.url).attr("target", link.target).text(text) : document.createTextNode(text);
690		$title.append($text);
691		$cont.append($title);
692	}
693	if( descriptionVisible ) {
694		$cont.append($('<div class="wb-lightbox-description">').text(item.description));
695	}
696	return true;
697};

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.