Welcome to the DFO World Wiki. With many major updates since the release of DFO, many items are missing. Visit Item Database Project to learn more.
Please remember to click "show preview" before saving the page.
Thanks for the updated logo snafuPop!

MediaWiki:Gadget-jquery.rotate.js

From DFO World Wiki
Jump to: navigation, search

Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
/** 
 * jQuery rotate plugIn. Allows rotating images using JavaScript
 * <nowiki>
 * Invoke automated jsHint-validation on save: A feature on WikimediaCommons
 * Interested? See [[:commons:MediaWiki:JSValidator.js]], [[:commons:Help:JSValidator.js]].
 *
**/

/*global jQuery:false, $:false, Wilq32:true */

// Following taken from jQueryRotate.2.2.js; with some minor modifications (see START MODIFICATION) for integration


// VERSION: 2.2 LAST UPDATE: 13.03.2012
/* 
 * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
 *
 * Made by Wilq32, wilq32@gmail.com, Wroclaw, Poland, 01.2009
 * Website: http://code.google.com/p/jqueryrotate/
 */
// Documentation removed from script file (was kinda useless and outdated)
(function ($) {
	/*jshint curly:false, eqeqeq:false, strict:false, asi:true, bitwise:false*/
	var supportedCSS, styles = document.getElementsByTagName("head")[0].style,
		toCheck = "transformProperty WebkitTransform OTransform msTransform MozTransform".split(" ");

	for (var a = 0; a < toCheck.length; a++)
		if (styles[toCheck[a]] !== undefined) supportedCSS = toCheck[a];

	// Bad eval to preven google closure to remove it from code o_O - changed not in code anymore
	// After compresion replace it back to var IE = 'v' == '\v'
	var IE = "v" == "\v";

	jQuery.fn.extend({
		rotate: function (parameters) {
			// These lines were modified. Re-include them when updating this plugIn
			// START MODIFICATION
			if (parameters && parameters.getSupportCSS) {
				return supportedCSS;
			}
			// END MODIFICATION

			if (this.length === 0 || typeof parameters == "undefined") return;
			if (typeof parameters == "number") parameters = {
				angle: parameters
			};
			var returned = [];
			for (var i = 0, i0 = this.length; i < i0; i++) {
				var element = this.get(i);
				if (!element.Wilq32 || !element.Wilq32.PhotoEffect) {

					var paramClone = $.extend(true, {}, parameters);
					var newRotObject = new Wilq32.PhotoEffect(element, paramClone)._rootObj;

					returned.push($(newRotObject));
				} else {
					element.Wilq32.PhotoEffect._handleRotation(parameters);
				}
			}
			return returned;
		},
		getRotateAngle: function () {
			var ret = [];
			for (var i = 0, i0 = this.length; i < i0; i++) {
				var element = this.get(i);
				if (element.Wilq32 && element.Wilq32.PhotoEffect) {
					ret[i] = element.Wilq32.PhotoEffect._angle;
				}
			}
			return ret;
		},
		stopRotate: function () {
			for (var i = 0, i0 = this.length; i < i0; i++) {
				var element = this.get(i);
				if (element.Wilq32 && element.Wilq32.PhotoEffect) {
					clearTimeout(element.Wilq32.PhotoEffect._timer);
				}
			}
		}
	});

	// Library agnostic interface

	Wilq32 = window.Wilq32 || {};
	Wilq32.PhotoEffect = (function () {

		if (supportedCSS) {
			return function (img, parameters) {
				img.Wilq32 = {
					PhotoEffect: this
				};

				this._img = this._rootObj = this._eventObj = img;
				this._handleRotation(parameters);
			}
		} else {
			return function (img, parameters) {
				// Make sure that class and id are also copied - just in case you would like to refeer to an newly created object
				this._img = img;

				this._rootObj = document.createElement('span');
				this._rootObj.style.display = "inline-block";
				this._rootObj.Wilq32 = {
					PhotoEffect: this
				};
				img.parentNode.insertBefore(this._rootObj, img);

				if (img.complete) {
					this._Loader(parameters);
				} else {
					var self = this;
					// TODO: Remove jQuery dependency
					jQuery(this._img).bind("load", function () {
						self._Loader(parameters);
					});
				}
			}
		}
	})();

	Wilq32.PhotoEffect.prototype = {
		_setupParameters: function (parameters) {
			this._parameters = this._parameters || {};
			if (typeof this._angle !== "number") this._angle = 0;
			if (typeof parameters.angle === "number") this._angle = parameters.angle;
			this._parameters.animateTo = (typeof parameters.animateTo === "number") ? (parameters.animateTo) : (this._angle);

			this._parameters.step = parameters.step || this._parameters.step || null;
			this._parameters.easing = parameters.easing || this._parameters.easing || function (x, t, b, c, d) {
				return -c * ((t = t / d - 1) * t * t * t - 1) + b;
			}
			this._parameters.duration = parameters.duration || this._parameters.duration || 1000;
			this._parameters.callback = parameters.callback || this._parameters.callback || function () {};
			if (parameters.bind && parameters.bind != this._parameters.bind) this._BindEvents(parameters.bind);
		},
		_handleRotation: function (parameters) {
			this._setupParameters(parameters);
			if (this._angle == this._parameters.animateTo) {
				this._rotate(this._angle);
			} else {
				this._animateStart();
			}
		},

		_BindEvents: function (events) {
			var evt;
			if (events && this._eventObj) {
				// Unbinding previous Events
				if (this._parameters.bind) {
					var oldEvents = this._parameters.bind;
					for (evt in oldEvents)
						if (oldEvents.hasOwnProperty(evt))
						// TODO: Remove jQuery dependency
							jQuery(this._eventObj).unbind(evt, oldEvents[evt]);
				}

				this._parameters.bind = events;
				for (evt in events)
					if (events.hasOwnProperty(evt))
					// TODO: Remove jQuery dependency
						jQuery(this._eventObj).bind(evt, events[evt]);
			}
		},

		_Loader: (function () {
			if (IE) {
				return function (parameters) {
						var t = this;
						var width = t._img.width;
						var height = t._img.height;
						t._img.parentNode.removeChild(t._img);

						t._vimage = t.createVMLNode('image');
						t._vimage.src = t._img.src;
						t._vimage.style.height = height + "px";
						t._vimage.style.width = width + "px";
						t._vimage.style.position = "absolute"; // FIXES IE PROBLEM - its only rendered if its on absolute position!
						t._vimage.style.top = "0px";
						t._vimage.style.left = "0px";

						/* Group minifying a small 1px precision problem when rotating object */
						t._container = t.createVMLNode('group');
						t._container.style.width = width;
						t._container.style.height = height;
						t._container.style.position = "absolute";
						t._container.setAttribute('coordsize', width - 1 + ',' + (height - 1)); // This -1, -1 trying to fix ugly problem with small displacement on IE
						t._container.appendChild(t._vimage);

						t._rootObj.appendChild(t._container);
						t._rootObj.style.position = "relative"; // FIXES IE PROBLEM
						t._rootObj.style.width = width + "px";
						t._rootObj.style.height = height + "px";
						t._rootObj.setAttribute('id', t._img.getAttribute('id'));
						t._rootObj.className = t._img.className;
						t._eventObj = t._rootObj;
						t._handleRotation(parameters);
					} 
				} else {
					return function (parameters) {
						var t = this;
						t._rootObj.setAttribute('id', t._img.getAttribute('id'));
						t._rootObj.className = t._img.className;

						t._width = t._img.width;
						t._height = t._img.height;
						t._widthHalf = t._width / 2; // used for optimisation
						t._heightHalf = t._height / 2; // used for optimisation

						var _widthMax = Math.sqrt((t._height) * (t._height) + (t._width) * (t._width));

						t._widthAdd = _widthMax - t._width;
						t._heightAdd = _widthMax - t._height; // widthMax because maxWidth=maxHeight
						t._widthAddHalf = t._widthAdd / 2; // used for optimisation
						t._heightAddHalf = t._heightAdd / 2; // used for optimisation

						t._img.parentNode.removeChild(t._img);

						t._aspectW = ((parseInt(t._img.style.width, 10)) || t._width) / t._img.width;
						t._aspectH = ((parseInt(t._img.style.height, 10)) || t._height) / t._img.height;

						t._canvas = document.createElement('canvas');
						t._canvas.setAttribute('width', t._width);
						t._canvas.style.position = "relative";
						t._canvas.style.left = -t._widthAddHalf + "px";
						t._canvas.style.top = -t._heightAddHalf + "px";
						t._canvas.Wilq32 = t._rootObj.Wilq32;

						t._rootObj.appendChild(t._canvas);
						t._rootObj.style.width = t._width + "px";
						t._rootObj.style.height = t._height + "px";
						t._eventObj = t._canvas;

						t._cnv = t._canvas.getContext('2d');
						t._handleRotation(parameters);
					}
				}
		})(),

		_animateStart: function () {
			if (this._timer) {
				clearTimeout(this._timer);
			}
			this._animateStartTime = +new Date();
			this._animateStartAngle = this._angle;
			this._animate();
		},
		_animate: function () {
			var actualTime = +new Date();
			var checkEnd = actualTime - this._animateStartTime > this._parameters.duration;

			// TODO: Bug for animatedGif for static rotation ? (to test)
			if (checkEnd && !this._parameters.animatedGif) {
				clearTimeout(this._timer);
			} else {
				if (this._canvas || this._vimage || this._img) {
					var angle = this._parameters.easing(0, actualTime - this._animateStartTime, this._animateStartAngle, this._parameters.animateTo - this._animateStartAngle, this._parameters.duration);
					this._rotate((~~(angle * 10)) / 10);
				}
				if (this._parameters.step) {
					this._parameters.step(this._angle);
				}
				var self = this;
				this._timer = setTimeout(function () {
					self._animate.call(self);
				}, 10);
			}

			// To fix Bug that prevents using recursive function in callback I moved this function to back
			if (this._parameters.callback && checkEnd) {
				this._angle = this._parameters.animateTo;
				this._rotate(this._angle);
				this._parameters.callback.call(this._rootObj);
			}
		},

		_rotate: (function () {
			var rad = Math.PI / 180;
			if (IE) {
					return function (angle) {
						this._angle = angle;
						this._container.style.rotation = (angle % 360) + "deg";
					}
			} else if (supportedCSS) {
				return function (angle) {
					this._angle = angle;
					this._img.style[supportedCSS] = "rotate(" + (angle % 360) + "deg)";
				}
			} else {
				return function (angle) {
					this._angle = angle;
					angle = (angle % 360) * rad;
					// clear canvas	
					this._canvas.width = this._width + this._widthAdd;
					this._canvas.height = this._height + this._heightAdd;

					// REMEMBER: all drawings are read from backwards.. so first function is translate, then rotate, then translate, translate..
					this._cnv.translate(this._widthAddHalf, this._heightAddHalf); // at least center image on screen
					this._cnv.translate(this._widthHalf, this._heightHalf); // we move image back to its orginal 
					this._cnv.rotate(angle); // rotate image
					this._cnv.translate(-this._widthHalf, -this._heightHalf); // move image to its center, so we can rotate around its center
					this._cnv.scale(this._aspectW, this._aspectH); // SCALE - if needed ;)
					this._cnv.drawImage(this._img, 0, 0); // First - we draw image
				}
			}
		})()
	}

	if (IE) {
		Wilq32.PhotoEffect.prototype.createVMLNode = (function () {
			document.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
			try {
				if (!document.namespaces.rvml) document.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
				return function (tagName) {
					return document.createElement('<rvml:' + tagName + ' class="rvml">');
				};
			} catch (e) {
				return function (tagName) {
					return document.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
				};
			}
		})();
	}

	$(document).triggerHandler('plugInLoaded', ['rotate', '2.2', 'MIT']);
})(jQuery);