User:Rillke/SlideRotator.js

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
importScript('User:Rillke/blur.js');

function ClsGsCaption(img, left, top, maxheight, maxwidth, minheight, minwidth, blurradius, html, padding) {
	if ('string' === typeof img) img = $(img);
	if ('object' === typeof img && !$.isArray(img)) img = $(img);
	img = img.eq(0);
	
	var wrapperID = 'cbWS' + Math.round(Math.random()*65536);
	var oldImgStyle = img.attr('style');
	var $wrapperSpan = $('<span>', { style: oldImgStyle, id: wrapperID }).css('position', 'relative').css('display', 'inline-block');
	img.data('oldStyle', oldImgStyle);
	img.attr('style', '');
	img.wrap($wrapperSpan);
	
	$wrapperSpan = img.parent();
	if (!$wrapperSpan.length) $wrapperSpan = $('#' + wrapperID);
	
	var $imgClone = img.clone().attr('id', Math.round(Math.random()*65536));
	var $imgCloneWrap = $('<span>').append($imgClone);
	$imgCloneWrap.css('left', (-1*left) + 'px').css('top', (-1*top) + 'px').css('position', 'absolute').css('display', 'inline-block');
	
	var $textDiv = $('<div>', { style: 'overflow:hidden; position:absolute;', html: html }).css('left', left + 'px').css('top', top + 'px');
	if (maxheight) $textDiv.css('max-height', maxheight);
	if (maxwidth) $textDiv.css('max-width', maxwidth);
	if (minheight) $textDiv.css('min-height', minheight);
	if (minwidth) $textDiv.css('min-width', minwidth);
	
	var $viewWindow = $('<div>', { style: 'overflow:hidden; position:absolute;' }).css('left', left + 'px').css('top', top + 'px').append($imgCloneWrap);
	var $colorWindow = $('<div>', { style: 'overflow:hidden; position:absolute;' }).css('left', left + 'px').css('top', top + 'px').text(' ');
	
	$wrapperSpan.append($viewWindow, $colorWindow, $textDiv);
	
	if (blurradius) $imgClone.blurRadius(blurradius);
	
	this.rTimeout = 0;
	
	// Finally save all the things we need later
	this.$viewWindow = $viewWindow;
	this.$colorWindow = $colorWindow;
	this.$textDiv = $textDiv.css('padding', padding + 'px').css('font-size', '1.0em');
	this.$wrapperSpan = $wrapperSpan;
	this.$imgCloneWrap = $imgCloneWrap;
	this.$imgClone = $imgClone;
	this.$img = img;
	this.padding = padding;
	
	this.resize(false);
}
ClsGsCaption.prototype.resize = function(async) {
	var _this = this;
	var maybeResize = function() {
		_this.$viewWindow.css('width', _this.$textDiv.width() + _this.padding*2);
		_this.$viewWindow.css('height', _this.$textDiv.height() + _this.padding*2);
		_this.$colorWindow.css('width', _this.$textDiv.width() + _this.padding*2);
		_this.$colorWindow.css('height', _this.$textDiv.height() + _this.padding*2);
	};
	clearTimeout(this.rTimeout);
	if (async) {
		this.rTimeout = setTimeout(function() {
			maybeResize();
		}, 10);
	} else {
		maybeResize();
	}
}
ClsGsCaption.prototype.show = function() {
	this.$viewWindow.show();
	this.$colorWindow.show();
	this.$textDiv.show();
}
ClsGsCaption.prototype.hide = function() {
	this.$viewWindow.hide();
	this.$colorWindow.hide();
	this.$textDiv.hide();
}
ClsGsCaption.prototype.remove = function() {
	this.$img.attr('style', this.$img.data('oldStyle'));
	this.$img.siblings().remove();
	this.$img.unwrap();
}
ClsGsCaption.prototype.html = function(html) {
	if (html) this.$textDiv.html(html);
	this.resize(false);
	return this.$textDiv.html();
}
ClsGsCaption.prototype.moveTo = function(top, left, duration, callback) {
	this.$viewWindow.animate({
		top: top,
		left: left
	}, duration);
	this.$colorWindow.animate({
		top: top,
		left: left
	}, duration);
	this.$textDiv.animate({
		top: top,
		left: left
	}, duration);
	this.$imgCloneWrap.animate({
		top: -1*top,
		left: -1*left
	}, duration, callback);
}
ClsGsCaption.prototype.width = function() {
	return this.$textDiv.width();
}
ClsGsCaption.prototype.height = function() {
	return this.$textDiv.height();
}
ClsGsCaption.prototype.blurRadius = function(radius) {
	if (radius) this.$imgClone.blurRadius(radius);
}
ClsGsCaption.prototype.formCSS = function(name, value) {
	this.$textDiv.css(name, value);
	this.$viewWindow.css(name, value);
	this.$colorWindow.css(name, value);
}
ClsGsCaption.prototype.formCSSO = function(obj) {
	this.$textDiv.css(obj);
	this.$viewWindow.css(obj);
	this.$colorWindow.css(obj);
}
ClsGsCaption.prototype.background = function(value) {
	this.$colorWindow.css('background', value);
}
ClsGsCaption.prototype.fadeColorTo = function(duration, opacity, callback) {
	this.$colorWindow.fadeTo(duration, opacity, callback);
}
ClsGsCaption.prototype.fadeBlurTo = function(duration, opacity, callback) {
	this.$viewWindow.fadeTo(duration, opacity, callback);
}
ClsGsCaption.prototype.fadeTextTo = function(duration, opacity, callback) {
	this.$textDiv.fadeTo(duration, opacity, callback);
}
ClsGsCaption.prototype.materialize = function(color, opacity, blurradius) {
	var _this = this;
	if (!blurradius) blurradius = 7;
	_this.$colorWindow.fadeTo(0, 0);
	_this.$textDiv.animate({
		left: '+=' + 20,
		opacity: '-=' + 1
	}, 0);
	_this.$colorWindow.css('background', color);
	var animateText = function() {
		_this.blurRadius(Math.round(blurradius / 2));
		_this.$textDiv.animate({
			left: '-=' + 20,
			opacity: '+=' + 1
		}, 1000, undefined, _this.blurRadius(blurradius));
	};
	_this.$colorWindow.fadeTo(1700, opacity, animateText);
}

$(document).ready(function() {

var ClsSlide = function(file, input, ii) {
	this.file = file;
	this.input = input;
	this.ii = ii;
};

$('div.SlideRotator').each(function (ix, el) {
	var $el = $(el);
	var slides = $el.nextUntil('div.SlideRotatorE', 'p');
	
	// Fixed width now.
	var width = $el.width();
	$el.css('width', width + 'px');
	
	// Calculating height if a ratio is provided
	var ratio = $el.find('.ratio-H-to-W').text();
	if (ratio) $el.css('height', width * ratio + 'px');
	
	var titles = [];
	var templateSlideData = [];
	var slidesByFile = {};
	slides.each(function(i, p) {
		$p = $(p);
		var fileSrc = 'File:' + $p.find('.srs-file').text().replace(/^File:/, '');
		titles.push( fileSrc );
		templateSlideData.push( { caption: { text: ($p.find('.srs-caption').html() || 'No caption-text present!')
				, positioning: ($p.find('.srs-caption-position').text() || 'left')
				, maxHeight: ($p.find('.srs-caption-maxHeight').text() || '200px')
				, maxWidth: ($p.find('.srs-caption-maxWidth').text() || '150px')
				, minHeight: ($p.find('.srs-caption-minHeight').text() || '0px')
				, minWidth: ($p.find('.srs-caption-minWidth').text() || '0px')
				, color: ($p.find('.srs-caption-color').text() || '#fff')
				, opacity: ($p.find('.srs-caption-opacity').text() || 0.6)
				, blurRadius: ($p.find('.srs-caption-blurRadius').text() || 7)
			}, image: { title: fileSrc
				, vPosition: ($p.find('.srs-vPosition').text() || 'center')
			}
		});
	});
	
	var gotImageDimensions = function(result) {
		// Process result and build container
		var pg, pgs, arrpos, arrlen, title;
		pgs = result.query.pages;
		arrlen = titles.length;
		for (var i = 0; i < arrlen; i++ ) {
			title = titles[i];
			for (var pid in pgs) {
				pg = pgs[pid];
				if (pg.title === title) {
					slidesByFile[pg.title + '|' + i] = new ClsSlide(pg.title, templateSlideData[i], pg.imageinfo[0]);
				}
			}
		}
		var $img, sl, $imgContainerDiv, currentObj, previousObj, nextObj;
		for (var slid in slidesByFile) {
			sl = slidesByFile[slid];
			$img = $('<img>', { height: sl.ii.thumbheight, width: sl.ii.thumbwidth }).data('myParent', sl).load(function() {
				myParent = $(this).data('myParent');
				myParent.loaded = true;
				if (myParent.cb) myParent.cb();
			}).attr('src', sl.ii.thumburl);
			sl.imgTopPosition = ('center' === sl.input.image.vPosition) ? (($el.height() - sl.ii.thumbheight) /2) : sl.input.image.vPosition;
			$imgContainerDiv = $('<div>', { style: 'position:absolute; top:' + ( sl.imgTopPosition ) + 'px; overflow:hidden; display:none;' }).append($('<span>', { style: 'width: 100%, height:100%' }).append($img)).appendTo($el);
			sl.$img = $img;
			sl.$imgContainerDiv = $imgContainerDiv;
		}
		
		var offset = arrlen - 1, oldOffset = 0;
		var exposeObjects = function() {
			currentObj = slidesByFile[titles[offset]  + '|' + offset];
			goNext(true);
			nextObj = slidesByFile[titles[offset]  + '|' + offset];
			goPrev(true); goPrev(true);
			previousObj = slidesByFile[titles[offset]  + '|' + offset];
			goNext(true);
		};
		var goNext = function(noExpose) {
			if (!noExpose) oldOffset = offset;
			offset++;
			offset = offset % arrlen;
			if (!noExpose) exposeObjects();
		};
		var goPrev = function(noExpose) {
			if (!noExpose) oldOffset = offset;
			offset--;
			offset = offset % arrlen;
			offset = (offset < 0) ? arrlen + offset : offset;
			if (!noExpose) exposeObjects();
		};
		var goTo = function(n, noExpose) {
			if (!noExpose) oldOffset = offset;
			offset = n % arrlen;
			offset = (offset < 0) ? arrlen - offset : offset;
			if (!noExpose) exposeObjects();
		};
		var removeCaption = function(obj) {
			if (obj && obj.capt) {
				obj.capt.remove();
				obj.capt = undefined;
			}
		};
		var doTransition = function(complete) {
			currentObj.$imgContainerDiv.show().animate({
				left: '0'
			}, {
				duration: 1000,
				complete: function() {
					// Remove the captions
					removeCaption(currentObj);
					removeCaption(nextObj);
					removeCaption(previousObj);
					if (nextObj) {
						nextObj.$imgContainerDiv.show();
						nextObj.$imgContainerDiv.css('left', width + 'px');
					}
					if (previousObj) {
						previousObj.$imgContainerDiv.show();
						previousObj.$imgContainerDiv.css('left', (-1 * width) + 'px');
					}
					if (complete) complete();
				},
				step: function() {
					// Adjust position of the previous and following slides
					// in case the show was moved forward, oldOffset is smaller than offset and vice versa
					if (previousObj) previousObj.$imgContainerDiv.css('left', (currentObj.$imgContainerDiv.position().left - width) + 'px');
				}
			});
			
		};
		goNext();
		
		var createCaption = function () {
			if (currentObj.capt) return;
			setTimeout(function() {
				var capt = currentObj.capt = new ClsGsCaption( currentObj.$img,
					0, //-1*hPos + 15
					-1*currentObj.imgTopPosition, // -1*top + 15
					currentObj.input.caption.maxHeight,
					currentObj.input.caption.maxWidth,
					currentObj.input.caption.minHeight,
					currentObj.input.caption.minWidth,
					0,
					currentObj.input.caption.text,
					5
				);
				capt.formCSSO({
					'-webkit-border-top-right-radius': '12px',
					'-webkit-border-bottom-right-radius': '12px',
					'-moz-border-radius-topright': '12px',
					'-moz-border-radius-bottomright': '12px',
					'border-top-right-radius': '12px',
					'border-bottom-right-radius': '12px'
				});
				capt.materialize(currentObj.input.caption.color, currentObj.input.caption.opacity, currentObj.input.caption.blurRadius);
				// setTimeout(function() { capt.remove(); console.log('done') }, 8000);
			}, 300);
		};
		// Now replace the load-container with images.
		var init = function() {
			$el.find('.srLoader').fadeOut();
			doTransition(createCaption); 
		};
		if (currentObj.loaded) {
			init();
		} else {
			currentObj.cb = init;
		}

		setInterval(function() { 
			goNext();
			doTransition(createCaption);
		}, 10000);
	};
	
	// Query information from API
	var params = { 'format': 'json'
		,'action': 'query'
		,'prop': 'imageinfo'
		,'titles': titles.join('|')
		,'iiprop': 'url'
		,'iiurlwidth': width
		// Set max-height to prevent too big images. Users should crop and upload a new one in this case
		,'iiurlheight': $el.height() * 8
	};
	$.ajax({
		url: mw.util.wikiScript('api'),
		data: params,
		dataType: 'json',
		error: function(x, t, s) {
			if (window.console && console.log) {
				console.log('Error:');
				console.log(t);
			}
		},
		success: gotImageDimensions,
		type: 'GET',
		cache: true
	});
});

}); // $(document).ready