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