xref: /plugin/magnifier/script.js (revision c3568e34a15239e5146a3bbdf95b899f1a06ceb6)
1(function ($){
2
3	var addCSSRule = (function(style){
4	    var sheet = document.head.appendChild(style).sheet;
5	    return function(selector, css){
6	        var propText = Object.keys(css).map(function(p){
7	            return p+":"+css[p];
8	        }).join(";");
9	        sheet.insertRule(selector + "{" + propText + "}", sheet.cssRules.length);
10	        return sheet;
11	    };
12	})(document.createElement("style"));
13
14	/**
15	 * normalizeEvent
16	 *
17	 * Firefox does not implement offsetX, OffsetY, so we have to detect for this an
18	 * manually calculate it ourselves using the pageX, pageY less the event
19	 * target's left offset and right offset
20	 *
21	 * If using a browser that supports offsetX, OffsetY, just return the event,
22	 * don't need to do anything
23	 */
24	var normalizeEvent = function(event) {
25	  if(!event.offsetX) {
26	    event.offsetX = (event.pageX - $(event.target).offset().left);
27	    event.offsetY = (event.pageY - $(event.target).offset().top);
28	  }
29	  return event.data;
30	};
31
32	// private
33	var magnifier = function(){
34
35		this.rootNode = null;
36		this.magnifierImage = null;
37		this.magnifierContent = null;
38	};
39
40	(function(_){
41
42		var magnifierRoot = null;
43		var currentAngleSheet = null;
44
45		_.init = function(magnifierNode) {
46
47			this.rootNode = magnifierNode;
48			this.magnifierImage = new Image();
49			this.magnifierImage.src = this.rootNode.attr('magnifierImage');
50
51			// register other handlers
52			this.rootNode.mousemove(this, _.mousemove);
53			this.rootNode.mouseout(this, _.mouseout);
54			this.rootNode.mouseover(this, _.mouseover);
55		};
56
57		_.mouseover = function(event)
58		{
59    		var $$ = normalizeEvent(event);
60			if ( magnifierRoot == null ) {
61
62				magnifierRoot = $('<svg></svg>').addClass('magnifierWrapper').attr('pointer-events', 'none');
63				$$.magnifierContent = $('<rect></rect>').addClass('magnifierContent').css('backgroundImage', 'url(' + $$.rootNode.attr('magnifierImage') + ')');
64				magnifierRoot.append($$.magnifierContent);
65
66				// macht im Opera Problem ...
67				$("body").append(magnifierRoot);
68			}
69
70			_.mousemove(event);
71		};
72
73		_.mousemove = function(event)
74		{
75    		var $$ = normalizeEvent(event);
76			_.setPosition(event.pageX,event.pageY, event.offsetX, event.offsetY, $$);
77		};
78
79		_.mouseout = function(event)
80		{
81    		var $$ = normalizeEvent(event);
82			var rootOffset = $$.rootNode.offset();
83			// Check Position over Element before removing!
84			if ( rootOffset.left > event.offsetX ||
85				 (rootOffset.left + $$.rootNode.width()) < event.offsetX ||
86				 rootOffset.top < event.offsetY ||
87				 (rootOffset.top + rootOffset.height) > event.offsetY )
88				 {
89					if ( magnifierRoot ) {
90						magnifierRoot.remove();
91						magnifierRoot = null;
92					}
93				 }
94		};
95
96		_.setPosition = function(x, y, contentX, contentY, $$)
97		{
98			if ( !$$ || !$$.magnifierImage || !contentX || !contentY || !$$.magnifierContent ) {
99				return;
100			}
101
102			// Background position
103			var posX = -(contentX / $$.rootNode.width() * $$.magnifierImage.width - $$.magnifierContent.width() / 2);
104			var posY = -(contentY / $$.rootNode.height() * $$.magnifierImage.height - $$.magnifierContent.height() / 2);
105
106			// Radial position
107			var position = (1 / $$.rootNode.width() * ($$.rootNode.width() - contentX));
108			var arc = -(110 * position + 35) * Math.PI / 180;
109
110			var left0 = 202;
111			var top0 = 0;
112
113			var left = left0 * Math.cos(arc) - top0 * Math.sin(arc) - 165;
114			var top = left0 * Math.sin(arc) + top0 * Math.cos(arc) + 113;
115			var angle = 'rotate(' + (position * -110) + 'deg)';
116
117			if ( currentAngleSheet != null ) {
118				$(currentAngleSheet).remove();
119			}
120
121			currentAngleSheet = addCSSRule("div.magnifierWrapper:after,svg.magnifierWrapper:after", {
122																'-webkit-transform': angle,
123																'-moz-transform': angle,
124																'-o-transform': angle,
125																'-ms-transform': angle
126									});
127
128			$$.magnifierContent.css({
129										'background-position': posX + "px " + posY + "px",
130										'backgroundPositionX': posX,
131										'backgroundPositionY': posY,
132										'margin-left' : left,
133										'margin-top': top
134									});
135
136			if ( !magnifierRoot || !x || !y ) {
137				return;
138			}
139
140			magnifierRoot.offset({ left:x - 18, top: y - magnifierRoot.height() });
141		};
142
143	})(magnifier.prototype);
144
145	// public
146	$.magnify = function(magnifierNode) {
147		return (new magnifier()).init(magnifierNode);
148	};
149
150	$(function(){
151		$('img.magnifierImage').each(function(index, item){
152			$.magnify($(item));
153		});
154	});
155
156})(jQuery);
157