image_viewer_rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +5 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/image_viewer_rails/application.js +16 -0
- data/app/assets/javascripts/image_viewer_rails/image_viewer.js +392 -0
- data/app/assets/javascripts/image_viewer_rails/jquery.rotate.js +313 -0
- data/app/assets/javascripts/image_viewer_rails/keymaster.js +236 -0
- data/app/assets/javascripts/image_viewer_rails/keymaster_filter.js +23 -0
- data/app/controllers/image_viewer_rails/application_controller.rb +4 -0
- data/app/helpers/image_viewer_rails/application_helper.rb +4 -0
- data/app/views/layouts/image_viewer_rails/application.html.erb +14 -0
- data/config/routes.rb +2 -0
- data/lib/image_viewer_rails.rb +4 -0
- data/lib/image_viewer_rails/engine.rb +5 -0
- data/lib/image_viewer_rails/version.rb +3 -0
- data/lib/tasks/image_viewer_rails_tasks.rake +4 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/image_viewer_rails_test.rb +7 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- metadata +157 -0
@@ -0,0 +1,313 @@
|
|
1
|
+
// VERSION: 2.2 LAST UPDATE: 13.03.2012
|
2
|
+
/*
|
3
|
+
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
4
|
+
*
|
5
|
+
* Made by Wilq32, wilq32@gmail.com, Wroclaw, Poland, 01.2009
|
6
|
+
* Website: http://code.google.com/p/jqueryrotate/
|
7
|
+
*/
|
8
|
+
|
9
|
+
// Documentation removed from script file (was kinda useless and outdated)
|
10
|
+
|
11
|
+
(function($) {
|
12
|
+
var supportedCSS,styles=document.getElementsByTagName("head")[0].style,toCheck="transformProperty WebkitTransform OTransform msTransform MozTransform".split(" ");
|
13
|
+
for (var a=0;a<toCheck.length;a++) if (styles[toCheck[a]] !== undefined) supportedCSS = toCheck[a];
|
14
|
+
// Bad eval to preven google closure to remove it from code o_O
|
15
|
+
// After compresion replace it back to var IE = 'v' == '\v'
|
16
|
+
var IE = eval('"v"=="\v"');
|
17
|
+
|
18
|
+
jQuery.fn.extend({
|
19
|
+
rotate:function(parameters)
|
20
|
+
{
|
21
|
+
if (this.length===0||typeof parameters=="undefined") return;
|
22
|
+
if (typeof parameters=="number") parameters={angle:parameters};
|
23
|
+
var returned=[];
|
24
|
+
for (var i=0,i0=this.length;i<i0;i++)
|
25
|
+
{
|
26
|
+
var element=this.get(i);
|
27
|
+
if (!element.Wilq32 || !element.Wilq32.PhotoEffect) {
|
28
|
+
|
29
|
+
var paramClone = $.extend(true, {}, parameters);
|
30
|
+
var newRotObject = new Wilq32.PhotoEffect(element,paramClone)._rootObj;
|
31
|
+
|
32
|
+
returned.push($(newRotObject));
|
33
|
+
}
|
34
|
+
else {
|
35
|
+
element.Wilq32.PhotoEffect._handleRotation(parameters);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
return returned;
|
39
|
+
},
|
40
|
+
getRotateAngle: function(){
|
41
|
+
var ret = [];
|
42
|
+
for (var i=0,i0=this.length;i<i0;i++)
|
43
|
+
{
|
44
|
+
var element=this.get(i);
|
45
|
+
if (element.Wilq32 && element.Wilq32.PhotoEffect) {
|
46
|
+
ret[i] = element.Wilq32.PhotoEffect._angle;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
return ret;
|
50
|
+
},
|
51
|
+
stopRotate: function(){
|
52
|
+
for (var i=0,i0=this.length;i<i0;i++)
|
53
|
+
{
|
54
|
+
var element=this.get(i);
|
55
|
+
if (element.Wilq32 && element.Wilq32.PhotoEffect) {
|
56
|
+
clearTimeout(element.Wilq32.PhotoEffect._timer);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
});
|
61
|
+
|
62
|
+
// Library agnostic interface
|
63
|
+
|
64
|
+
Wilq32=window.Wilq32||{};
|
65
|
+
Wilq32.PhotoEffect=(function(){
|
66
|
+
|
67
|
+
if (supportedCSS) {
|
68
|
+
return function(img,parameters){
|
69
|
+
img.Wilq32 = {
|
70
|
+
PhotoEffect: this
|
71
|
+
};
|
72
|
+
|
73
|
+
this._img = this._rootObj = this._eventObj = img;
|
74
|
+
this._handleRotation(parameters);
|
75
|
+
}
|
76
|
+
} else {
|
77
|
+
return function(img,parameters) {
|
78
|
+
// Make sure that class and id are also copied - just in case you would like to refeer to an newly created object
|
79
|
+
this._img = img;
|
80
|
+
|
81
|
+
this._rootObj=document.createElement('span');
|
82
|
+
this._rootObj.style.display="inline-block";
|
83
|
+
this._rootObj.Wilq32 =
|
84
|
+
{
|
85
|
+
PhotoEffect: this
|
86
|
+
};
|
87
|
+
img.parentNode.insertBefore(this._rootObj,img);
|
88
|
+
|
89
|
+
if (img.complete) {
|
90
|
+
this._Loader(parameters);
|
91
|
+
} else {
|
92
|
+
var self=this;
|
93
|
+
// TODO: Remove jQuery dependency
|
94
|
+
jQuery(this._img).bind("load", function()
|
95
|
+
{
|
96
|
+
self._Loader(parameters);
|
97
|
+
});
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
})();
|
102
|
+
|
103
|
+
Wilq32.PhotoEffect.prototype={
|
104
|
+
_setupParameters : function (parameters){
|
105
|
+
this._parameters = this._parameters || {};
|
106
|
+
if (typeof this._angle !== "number") this._angle = 0 ;
|
107
|
+
if (typeof parameters.angle==="number") this._angle = parameters.angle;
|
108
|
+
this._parameters.animateTo = (typeof parameters.animateTo==="number") ? (parameters.animateTo) : (this._angle);
|
109
|
+
|
110
|
+
this._parameters.step = parameters.step || this._parameters.step || null;
|
111
|
+
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; }
|
112
|
+
this._parameters.duration = parameters.duration || this._parameters.duration || 1000;
|
113
|
+
this._parameters.callback = parameters.callback || this._parameters.callback || function(){};
|
114
|
+
if (parameters.bind && parameters.bind != this._parameters.bind) this._BindEvents(parameters.bind);
|
115
|
+
},
|
116
|
+
_handleRotation : function(parameters){
|
117
|
+
this._setupParameters(parameters);
|
118
|
+
if (this._angle==this._parameters.animateTo) {
|
119
|
+
this._rotate(this._angle);
|
120
|
+
}
|
121
|
+
else {
|
122
|
+
this._animateStart();
|
123
|
+
}
|
124
|
+
},
|
125
|
+
|
126
|
+
_BindEvents:function(events){
|
127
|
+
if (events && this._eventObj)
|
128
|
+
{
|
129
|
+
// Unbinding previous Events
|
130
|
+
if (this._parameters.bind){
|
131
|
+
var oldEvents = this._parameters.bind;
|
132
|
+
for (var a in oldEvents) if (oldEvents.hasOwnProperty(a))
|
133
|
+
// TODO: Remove jQuery dependency
|
134
|
+
jQuery(this._eventObj).unbind(a,oldEvents[a]);
|
135
|
+
}
|
136
|
+
|
137
|
+
this._parameters.bind = events;
|
138
|
+
for (var a in events) if (events.hasOwnProperty(a))
|
139
|
+
// TODO: Remove jQuery dependency
|
140
|
+
jQuery(this._eventObj).bind(a,events[a]);
|
141
|
+
}
|
142
|
+
},
|
143
|
+
|
144
|
+
_Loader:(function()
|
145
|
+
{
|
146
|
+
if (IE)
|
147
|
+
return function(parameters)
|
148
|
+
{
|
149
|
+
var width=this._img.width;
|
150
|
+
var height=this._img.height;
|
151
|
+
this._img.parentNode.removeChild(this._img);
|
152
|
+
|
153
|
+
this._vimage = this.createVMLNode('image');
|
154
|
+
this._vimage.src=this._img.src;
|
155
|
+
this._vimage.style.height=height+"px";
|
156
|
+
this._vimage.style.width=width+"px";
|
157
|
+
this._vimage.style.position="absolute"; // FIXES IE PROBLEM - its only rendered if its on absolute position!
|
158
|
+
this._vimage.style.top = "0px";
|
159
|
+
this._vimage.style.left = "0px";
|
160
|
+
|
161
|
+
/* Group minifying a small 1px precision problem when rotating object */
|
162
|
+
this._container = this.createVMLNode('group');
|
163
|
+
this._container.style.width=width;
|
164
|
+
this._container.style.height=height;
|
165
|
+
this._container.style.position="absolute";
|
166
|
+
this._container.setAttribute('coordsize',width-1+','+(height-1)); // This -1, -1 trying to fix ugly problem with small displacement on IE
|
167
|
+
this._container.appendChild(this._vimage);
|
168
|
+
|
169
|
+
this._rootObj.appendChild(this._container);
|
170
|
+
this._rootObj.style.position="relative"; // FIXES IE PROBLEM
|
171
|
+
this._rootObj.style.width=width+"px";
|
172
|
+
this._rootObj.style.height=height+"px";
|
173
|
+
this._rootObj.setAttribute('id',this._img.getAttribute('id'));
|
174
|
+
this._rootObj.className=this._img.className;
|
175
|
+
this._eventObj = this._rootObj;
|
176
|
+
this._handleRotation(parameters);
|
177
|
+
}
|
178
|
+
else
|
179
|
+
return function (parameters)
|
180
|
+
{
|
181
|
+
this._rootObj.setAttribute('id',this._img.getAttribute('id'));
|
182
|
+
this._rootObj.className=this._img.className;
|
183
|
+
|
184
|
+
this._width=this._img.width;
|
185
|
+
this._height=this._img.height;
|
186
|
+
this._widthHalf=this._width/2; // used for optimisation
|
187
|
+
this._heightHalf=this._height/2;// used for optimisation
|
188
|
+
|
189
|
+
var _widthMax=Math.sqrt((this._height)*(this._height) + (this._width) * (this._width));
|
190
|
+
|
191
|
+
this._widthAdd = _widthMax - this._width;
|
192
|
+
this._heightAdd = _widthMax - this._height; // widthMax because maxWidth=maxHeight
|
193
|
+
this._widthAddHalf=this._widthAdd/2; // used for optimisation
|
194
|
+
this._heightAddHalf=this._heightAdd/2;// used for optimisation
|
195
|
+
|
196
|
+
this._img.parentNode.removeChild(this._img);
|
197
|
+
|
198
|
+
this._aspectW = ((parseInt(this._img.style.width,10)) || this._width)/this._img.width;
|
199
|
+
this._aspectH = ((parseInt(this._img.style.height,10)) || this._height)/this._img.height;
|
200
|
+
|
201
|
+
this._canvas=document.createElement('canvas');
|
202
|
+
this._canvas.setAttribute('width',this._width);
|
203
|
+
this._canvas.style.position="relative";
|
204
|
+
this._canvas.style.left = -this._widthAddHalf + "px";
|
205
|
+
this._canvas.style.top = -this._heightAddHalf + "px";
|
206
|
+
this._canvas.Wilq32 = this._rootObj.Wilq32;
|
207
|
+
|
208
|
+
this._rootObj.appendChild(this._canvas);
|
209
|
+
this._rootObj.style.width=this._width+"px";
|
210
|
+
this._rootObj.style.height=this._height+"px";
|
211
|
+
this._eventObj = this._canvas;
|
212
|
+
|
213
|
+
this._cnv=this._canvas.getContext('2d');
|
214
|
+
this._handleRotation(parameters);
|
215
|
+
}
|
216
|
+
})(),
|
217
|
+
|
218
|
+
_animateStart:function()
|
219
|
+
{
|
220
|
+
if (this._timer) {
|
221
|
+
clearTimeout(this._timer);
|
222
|
+
}
|
223
|
+
this._animateStartTime = +new Date;
|
224
|
+
this._animateStartAngle = this._angle;
|
225
|
+
this._animate();
|
226
|
+
},
|
227
|
+
_animate:function()
|
228
|
+
{
|
229
|
+
var actualTime = +new Date;
|
230
|
+
var checkEnd = actualTime - this._animateStartTime > this._parameters.duration;
|
231
|
+
|
232
|
+
// TODO: Bug for animatedGif for static rotation ? (to test)
|
233
|
+
if (checkEnd && !this._parameters.animatedGif)
|
234
|
+
{
|
235
|
+
clearTimeout(this._timer);
|
236
|
+
}
|
237
|
+
else
|
238
|
+
{
|
239
|
+
if (this._canvas||this._vimage||this._img) {
|
240
|
+
var angle = this._parameters.easing(0, actualTime - this._animateStartTime, this._animateStartAngle, this._parameters.animateTo - this._animateStartAngle, this._parameters.duration);
|
241
|
+
this._rotate((~~(angle*10))/10);
|
242
|
+
}
|
243
|
+
if (this._parameters.step) {
|
244
|
+
this._parameters.step(this._angle);
|
245
|
+
}
|
246
|
+
var self = this;
|
247
|
+
this._timer = setTimeout(function()
|
248
|
+
{
|
249
|
+
self._animate.call(self);
|
250
|
+
}, 10);
|
251
|
+
}
|
252
|
+
|
253
|
+
// To fix Bug that prevents using recursive function in callback I moved this function to back
|
254
|
+
if (this._parameters.callback && checkEnd){
|
255
|
+
this._angle = this._parameters.animateTo;
|
256
|
+
this._rotate(this._angle);
|
257
|
+
this._parameters.callback.call(this._rootObj);
|
258
|
+
}
|
259
|
+
},
|
260
|
+
|
261
|
+
_rotate : (function()
|
262
|
+
{
|
263
|
+
var rad = Math.PI/180;
|
264
|
+
if (IE)
|
265
|
+
return function(angle)
|
266
|
+
{
|
267
|
+
this._angle = angle;
|
268
|
+
this._container.style.rotation=(angle%360)+"deg";
|
269
|
+
}
|
270
|
+
else if (supportedCSS)
|
271
|
+
return function(angle){
|
272
|
+
this._angle = angle;
|
273
|
+
this._img.style[supportedCSS]="rotate("+(angle%360)+"deg)";
|
274
|
+
}
|
275
|
+
else
|
276
|
+
return function(angle)
|
277
|
+
{
|
278
|
+
this._angle = angle;
|
279
|
+
angle=(angle%360)* rad;
|
280
|
+
// clear canvas
|
281
|
+
this._canvas.width = this._width+this._widthAdd;
|
282
|
+
this._canvas.height = this._height+this._heightAdd;
|
283
|
+
|
284
|
+
// REMEMBER: all drawings are read from backwards.. so first function is translate, then rotate, then translate, translate..
|
285
|
+
this._cnv.translate(this._widthAddHalf,this._heightAddHalf); // at least center image on screen
|
286
|
+
this._cnv.translate(this._widthHalf,this._heightHalf); // we move image back to its orginal
|
287
|
+
this._cnv.rotate(angle); // rotate image
|
288
|
+
this._cnv.translate(-this._widthHalf,-this._heightHalf); // move image to its center, so we can rotate around its center
|
289
|
+
this._cnv.scale(this._aspectW,this._aspectH); // SCALE - if needed ;)
|
290
|
+
this._cnv.drawImage(this._img, 0, 0); // First - we draw image
|
291
|
+
}
|
292
|
+
|
293
|
+
})()
|
294
|
+
}
|
295
|
+
|
296
|
+
if (IE)
|
297
|
+
{
|
298
|
+
Wilq32.PhotoEffect.prototype.createVMLNode=(function(){
|
299
|
+
document.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
|
300
|
+
try {
|
301
|
+
!document.namespaces.rvml && document.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
|
302
|
+
return function (tagName) {
|
303
|
+
return document.createElement('<rvml:' + tagName + ' class="rvml">');
|
304
|
+
};
|
305
|
+
} catch (e) {
|
306
|
+
return function (tagName) {
|
307
|
+
return document.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
|
308
|
+
};
|
309
|
+
}
|
310
|
+
})();
|
311
|
+
}
|
312
|
+
|
313
|
+
})(jQuery);
|
@@ -0,0 +1,236 @@
|
|
1
|
+
// keymaster.js - 64fc7e56aa97efd9a1802a15e773fa98d3903372
|
2
|
+
// (c) 2011-2012 Thomas Fuchs
|
3
|
+
// keymaster.js may be freely distributed under the MIT license.
|
4
|
+
|
5
|
+
;(function(global){
|
6
|
+
var k,
|
7
|
+
_handlers = {},
|
8
|
+
_mods = { 16: false, 18: false, 17: false, 91: false },
|
9
|
+
_scope = 'all',
|
10
|
+
// modifier keys
|
11
|
+
_MODIFIERS = {
|
12
|
+
'⇧': 16, shift: 16,
|
13
|
+
'⌥': 18, alt: 18, option: 18,
|
14
|
+
'⌃': 17, ctrl: 17, control: 17,
|
15
|
+
'⌘': 91, command: 91
|
16
|
+
},
|
17
|
+
// special keys
|
18
|
+
_MAP = {
|
19
|
+
backspace: 8, tab: 9, clear: 12,
|
20
|
+
enter: 13, 'return': 13,
|
21
|
+
esc: 27, escape: 27, space: 32,
|
22
|
+
left: 37, up: 38,
|
23
|
+
right: 39, down: 40,
|
24
|
+
del: 46, 'delete': 46,
|
25
|
+
home: 36, end: 35,
|
26
|
+
pageup: 33, pagedown: 34,
|
27
|
+
',': 188, '.': 190, '/': 191,
|
28
|
+
'`': 192, '-': 189, '=': 187,
|
29
|
+
';': 186, '\'': 222,
|
30
|
+
'[': 219, ']': 221, '\\': 220
|
31
|
+
},
|
32
|
+
code = function(x){
|
33
|
+
return _MAP[x] || x.toUpperCase().charCodeAt(0);
|
34
|
+
},
|
35
|
+
_downKeys = [];
|
36
|
+
|
37
|
+
for(k=1;k<20;k++) _MAP['f'+k] = 111+k;
|
38
|
+
|
39
|
+
// IE doesn't support Array#indexOf, so have a simple replacement
|
40
|
+
function index(array, item){
|
41
|
+
var i = array.length;
|
42
|
+
while(i--) if(array[i]===item) return i;
|
43
|
+
return -1;
|
44
|
+
}
|
45
|
+
|
46
|
+
var modifierMap = {
|
47
|
+
16:'shiftKey',
|
48
|
+
18:'altKey',
|
49
|
+
17:'ctrlKey',
|
50
|
+
91:'metaKey'
|
51
|
+
};
|
52
|
+
function updateModifierKey(event) {
|
53
|
+
for(k in _mods) _mods[k] = event[modifierMap[k]];
|
54
|
+
};
|
55
|
+
|
56
|
+
// handle keydown event
|
57
|
+
function dispatch(event, scope){
|
58
|
+
var key, handler, k, i, modifiersMatch;
|
59
|
+
key = event.keyCode;
|
60
|
+
|
61
|
+
if (index(_downKeys, key) == -1) {
|
62
|
+
_downKeys.push(key);
|
63
|
+
}
|
64
|
+
|
65
|
+
// if a modifier key, set the key.<modifierkeyname> property to true and return
|
66
|
+
if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko
|
67
|
+
if(key in _mods) {
|
68
|
+
_mods[key] = true;
|
69
|
+
// 'assignKey' from inside this closure is exported to window.key
|
70
|
+
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
updateModifierKey(event);
|
74
|
+
|
75
|
+
// see if we need to ignore the keypress (filter() can can be overridden)
|
76
|
+
// by default ignore key presses if a select, textarea, or input is focused
|
77
|
+
if(!assignKey.filter.call(this, event)) return;
|
78
|
+
|
79
|
+
// abort if no potentially matching shortcuts found
|
80
|
+
if (!(key in _handlers)) return;
|
81
|
+
|
82
|
+
// for each potential shortcut
|
83
|
+
for (i = 0; i < _handlers[key].length; i++) {
|
84
|
+
handler = _handlers[key][i];
|
85
|
+
|
86
|
+
// see if it's in the current scope
|
87
|
+
if(handler.scope == scope || handler.scope == 'all'){
|
88
|
+
// check if modifiers match if any
|
89
|
+
modifiersMatch = handler.mods.length > 0;
|
90
|
+
for(k in _mods)
|
91
|
+
if((!_mods[k] && index(handler.mods, +k) > -1) ||
|
92
|
+
(_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false;
|
93
|
+
// call the handler and stop the event if neccessary
|
94
|
+
if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
|
95
|
+
if(handler.method(event, handler)===false){
|
96
|
+
if(event.preventDefault) event.preventDefault();
|
97
|
+
else event.returnValue = false;
|
98
|
+
if(event.stopPropagation) event.stopPropagation();
|
99
|
+
if(event.cancelBubble) event.cancelBubble = true;
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
};
|
105
|
+
|
106
|
+
// unset modifier keys on keyup
|
107
|
+
function clearModifier(event){
|
108
|
+
var key = event.keyCode, k,
|
109
|
+
i = index(_downKeys, key);
|
110
|
+
|
111
|
+
// remove key from _downKeys
|
112
|
+
if (i >= 0) {
|
113
|
+
_downKeys.splice(i, 1);
|
114
|
+
}
|
115
|
+
|
116
|
+
if(key == 93 || key == 224) key = 91;
|
117
|
+
if(key in _mods) {
|
118
|
+
_mods[key] = false;
|
119
|
+
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
|
120
|
+
}
|
121
|
+
};
|
122
|
+
|
123
|
+
function resetModifiers() {
|
124
|
+
for(k in _mods) _mods[k] = false;
|
125
|
+
for(k in _MODIFIERS) assignKey[k] = false;
|
126
|
+
}
|
127
|
+
|
128
|
+
// parse and assign shortcut
|
129
|
+
function assignKey(key, scope, method){
|
130
|
+
var keys, mods, i, mi;
|
131
|
+
if (method === undefined) {
|
132
|
+
method = scope;
|
133
|
+
scope = 'all';
|
134
|
+
}
|
135
|
+
key = key.replace(/\s/g,'');
|
136
|
+
keys = key.split(',');
|
137
|
+
|
138
|
+
if((keys[keys.length-1])=='')
|
139
|
+
keys[keys.length-2] += ',';
|
140
|
+
// for each shortcut
|
141
|
+
for (i = 0; i < keys.length; i++) {
|
142
|
+
// set modifier keys if any
|
143
|
+
mods = [];
|
144
|
+
key = keys[i].split('+');
|
145
|
+
if(key.length > 1){
|
146
|
+
mods = key.slice(0,key.length-1);
|
147
|
+
for (mi = 0; mi < mods.length; mi++)
|
148
|
+
mods[mi] = _MODIFIERS[mods[mi]];
|
149
|
+
key = [key[key.length-1]];
|
150
|
+
}
|
151
|
+
// convert to keycode and...
|
152
|
+
key = key[0]
|
153
|
+
key = code(key);
|
154
|
+
// ...store handler
|
155
|
+
if (!(key in _handlers)) _handlers[key] = [];
|
156
|
+
_handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });
|
157
|
+
}
|
158
|
+
};
|
159
|
+
|
160
|
+
// Returns true if the key with code 'keyCode' is currently down
|
161
|
+
// Converts strings into key codes.
|
162
|
+
function isPressed(keyCode) {
|
163
|
+
if (typeof(keyCode)=='string') {
|
164
|
+
keyCode = code(keyCode);
|
165
|
+
}
|
166
|
+
return index(_downKeys, keyCode) != -1;
|
167
|
+
}
|
168
|
+
|
169
|
+
function getPressedKeyCodes() {
|
170
|
+
return _downKeys.slice(0);
|
171
|
+
}
|
172
|
+
|
173
|
+
function filter(event){
|
174
|
+
var tagName = (event.target || event.srcElement).tagName;
|
175
|
+
// ignore keypressed in any elements that support keyboard data input
|
176
|
+
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
177
|
+
}
|
178
|
+
|
179
|
+
// initialize key.<modifier> to false
|
180
|
+
for(k in _MODIFIERS) assignKey[k] = false;
|
181
|
+
|
182
|
+
// set current scope (default 'all')
|
183
|
+
function setScope(scope){ _scope = scope || 'all' };
|
184
|
+
function getScope(){ return _scope || 'all' };
|
185
|
+
|
186
|
+
// delete all handlers for a given scope
|
187
|
+
function deleteScope(scope){
|
188
|
+
var key, handlers, i;
|
189
|
+
|
190
|
+
for (key in _handlers) {
|
191
|
+
handlers = _handlers[key];
|
192
|
+
for (i = 0; i < handlers.length; ) {
|
193
|
+
if (handlers[i].scope === scope) handlers.splice(i, 1);
|
194
|
+
else i++;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
};
|
198
|
+
|
199
|
+
// cross-browser events
|
200
|
+
function addEvent(object, event, method) {
|
201
|
+
if (object.addEventListener)
|
202
|
+
object.addEventListener(event, method, false);
|
203
|
+
else if(object.attachEvent)
|
204
|
+
object.attachEvent('on'+event, function(){ method(window.event) });
|
205
|
+
};
|
206
|
+
|
207
|
+
// set the handlers globally on document
|
208
|
+
addEvent(document, 'keydown', function(event) { dispatch(event, _scope) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
|
209
|
+
addEvent(document, 'keyup', clearModifier);
|
210
|
+
|
211
|
+
// reset modifiers to false whenever the window is (re)focused.
|
212
|
+
addEvent(window, 'focus', resetModifiers);
|
213
|
+
|
214
|
+
// store previously defined key
|
215
|
+
var previousKey = global.key;
|
216
|
+
|
217
|
+
// restore previously defined key and return reference to our key object
|
218
|
+
function noConflict() {
|
219
|
+
var k = global.key;
|
220
|
+
global.key = previousKey;
|
221
|
+
return k;
|
222
|
+
}
|
223
|
+
|
224
|
+
// set window.key and window.key.set/get/deleteScope, and the default filter
|
225
|
+
global.key = assignKey;
|
226
|
+
global.key.setScope = setScope;
|
227
|
+
global.key.getScope = getScope;
|
228
|
+
global.key.deleteScope = deleteScope;
|
229
|
+
global.key.filter = filter;
|
230
|
+
global.key.isPressed = isPressed;
|
231
|
+
global.key.getPressedKeyCodes = getPressedKeyCodes;
|
232
|
+
global.key.noConflict = noConflict;
|
233
|
+
|
234
|
+
if(typeof module !== 'undefined') module.exports = key;
|
235
|
+
|
236
|
+
})(this);
|