use SVG icons for media file links
[dokuwiki.git] / lib / scripts / hotkeys.js
blob76a277aea2ad6b09e7d2850def2b16678b58d90d
1 /**
2  * Some of these scripts were taken from TinyMCE (http://tinymce.moxiecode.com/) and were modified for DokuWiki
3  *
4  * Class handles accesskeys using javascript and also provides ability
5  * to register and use other hotkeys as well.
6  *
7  * @author Marek Sacha <sachamar@fel.cvut.cz>
8  */
9 function Hotkeys() {
11     this.shortcuts = new Array();
13     /**
14      * Set modifier keys, for instance:
15      *  this.modifier = 'ctrl';
16      *  this.modifier = 'ctrl+shift';
17      *  this.modifier = 'ctrl+alt+shift';
18      *  this.modifier = 'alt';
19      *  this.modifier = 'alt+shift';
20      *
21      *  overwritten in intitialize (see below)
22      */
23     this.modifier = 'ctrl+alt';
25     /**
26      * Initialization
27      *
28      * This function looks up all the accesskeys used in the current page
29      * (at anchor elements and button elements [type="submit"]) and registers
30      * appropriate shortcuts.
31      *
32      * Secondly, initialization registers listeners on document to catch all
33      * keyboard events.
34      *
35      * @author Marek Sacha <sachamar@fel.cvut.cz>
36      */
37     this.initialize = function() {
38         var t = this;
40         //switch modifier key based on OS FS#1958
41         if(is_macos){
42             t.modifier = 'ctrl+alt';
43         }else{
44             t.modifier = 'alt';
45         }
47         /**
48          * Lookup all anchors with accesskey and register event - go to anchor
49          * target.
50          */
51         var anchors = document.getElementsByTagName("a");
52         t.each(anchors, function(a) {
53             if (a.accessKey != "") {
54                 t.addShortcut(t.modifier + '+' + a.accessKey, function() {
55                     location.href = a.href;
56                 });
57                 a.accessKey = '';
58             }
59         });
61         /**
62          * Lookup all button [type="submit"] with accesskey and register event -
63          * perform "click" on a button.
64          */
65         var inputs = document.getElementsByTagName("button");
66         t.each(inputs, function(i) {
67             if (i.type == "submit" && i.accessKey != "") {
68                 t.addShortcut(t.modifier + '+' + i.accessKey, function() {
69                     i.click();
70                 });
71                 i.accessKey = '';
72             }
73         });
75         /**
76          * Lookup all buttons with accesskey and register event -
77          * perform "click" on a button.
78          */
79         var buttons = document.getElementsByTagName("button");
80         t.each(buttons, function(b) {
81             if (b.accessKey != "") {
82                 t.addShortcut(t.modifier + '+' + b.accessKey, function() {
83                     b.click();
84                 });
85                 b.accessKey = '';
86             }
87         });
89         /**
90          * Register listeners on document to catch keyboard events.
91          */
93         addEvent(document,'keyup',function (e) {
94             return t.onkeyup.call(t,e);
95         });
97         addEvent(document,'keypress',function (e) {
98             return t.onkeypress.call(t,e);
99         });
101         addEvent(document,'keydown',function (e) {
102             return t.onkeydown.call(t,e);
103         });
104     };
106     /**
107      * Keyup processing function
108      * Function returns true if keyboard event has registered handler, and
109      * executes the handler function.
110      *
111      * @param e KeyboardEvent
112      * @author Marek Sacha <sachamar@fel.cvut.cz>
113      * @return b boolean
114      */
115     this.onkeyup = function(e) {
116         var t = this;
117         var v = t.findShortcut(e);
118         if (v != null && v != false) {
119             v.func.call(t);
120             return false;
121         }
122         return true;
123     };
125     /**
126      * Keydown processing function
127      * Function returns true if keyboard event has registered handler
128      *
129      * @param e KeyboardEvent
130      * @author Marek Sacha <sachamar@fel.cvut.cz>
131      * @return b boolean
132      */
133     this.onkeydown = function(e) {
134         var t = this;
135         var v = t.findShortcut(e);
136         if (v != null && v != false) {
137             return false;
138         }
139         return true;
140     };
142     /**
143      * Keypress processing function
144      * Function returns true if keyboard event has registered handler
145      *
146      * @param e KeyboardEvent
147      * @author Marek Sacha <sachamar@fel.cvut.cz>
148      * @return b
149      */
150     this.onkeypress = function(e) {
151         var t = this;
152         var v = t.findShortcut(e);
153         if (v != null && v != false) {
154             return false;
155         }
156         return true;
157     };
159     /**
160      * Register new shortcut
161      *
162      * This function registers new shortcuts, each shortcut is defined by its
163      * modifier keys and a key (with + as delimiter). If shortcut is pressed
164      * cmd_function is performed.
165      *
166      * For example:
167      *  pa = "ctrl+alt+p";
168      *  pa = "shift+alt+s";
169      *
170      * Full example of method usage:
171      *  hotkeys.addShortcut('ctrl+s',function() {
172      *      document.getElementByID('form_1').submit();
173      *  });
174      *
175      * @param pa String description of the shortcut (ctrl+a, ctrl+shift+p, .. )
176      * @param cmd_func Function to be called if shortcut is pressed
177      * @author Marek Sacha <sachamar@fel.cvut.cz>
178      */
179     this.addShortcut = function(pa, cmd_func) {
180         var t = this;
182         var o = {
183             func : cmd_func,
184             alt : false,
185             ctrl : false,
186             shift : false
187         };
189         t.each(t.explode(pa, '+'), function(v) {
190             switch (v) {
191                 case 'alt':
192                 case 'ctrl':
193                 case 'shift':
194                     o[v] = true;
195                     break;
197                 default:
198                     o.charCode = v.charCodeAt(0);
199                     o.keyCode = v.toUpperCase().charCodeAt(0);
200             }
201         });
203         t.shortcuts.push((o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode,  o);
205         return true;
206     };
208     /**
209      * @property isMac
210      */
211     this.isMac = is_macos;
213     /**
214      * Apply function cb on each element of o in the namespace of s
215      * @param o Array of objects
216      * @param cb Function to be called on each object
217      * @param s Namespace to be used during call of cb (default namespace is o)
218      * @author Marek Sacha <sachamar@fel.cvut.cz>
219      */
220     this.each = function(o, cb, s) {
221         var n, l;
223         if (!o)
224             return 0;
226         s = s || o;
228         if (o.length !== undefined) {
229             // Indexed arrays, needed for Safari
230             for (n=0, l = o.length; n < l; n++) {
231                 if (cb.call(s, o[n], n, o) === false)
232                     return 0;
233             }
234         } else {
235             // Hashtables
236             for (n in o) {
237                 if (o.hasOwnProperty(n)) {
238                     if (cb.call(s, o[n], n, o) === false)
239                         return 0;
240                 }
241             }
242         }
244         return 1;
245     };
247     /**
248      * Explode string according to delimiter
249      * @param s String
250      * @param d Delimiter (default ',')
251      * @author Marek Sacha <sachamar@fel.cvut.cz>
252      * @return a Array of tokens
253      */
254     this.explode = function(s, d) {
255         return  s.split(d || ',');
256     };
258     /**
259      * Find if the shortcut was registered
260      *
261      * @param e KeyboardEvent
262      * @author Marek Sacha <sachamar@fel.cvut.cz>
263      * @return v Shortcut structure or null if not found
264      */
265     this.findShortcut = function (e) {
266         var t = this;
267         var v = null;
269         /* No modifier key used - shortcut does not exist */
270         if (!e.altKey && !e.ctrlKey && !e.metaKey) {
271             return v;
272         }
274         t.each(t.shortcuts, function(o) {
275             if (o.ctrl != e.ctrlKey)
276                 return;
278             if (o.alt != e.altKey)
279                 return;
281             if (o.shift != e.shiftKey)
282                 return;
284             if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {
285                 v = o;
286                 return;
287             }
288         });
289         return v;
290     };
294  * Init function for hotkeys. Called from js.php, to ensure hotkyes are initialized after toolbar.
295  * Call of addInitEvent(initializeHotkeys) is unnecessary now.
297  * @author Marek Sacha <sachamar@fel.cvut.cz>
298  */
299 function initializeHotkeys() {
300     var hotkeys = new Hotkeys();
301     hotkeys.initialize();