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 */ 9function Hotkeys() { 10 11 this.shortcuts = new Array(); 12 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 this.modifier = 'ctrl'; 22 23 /** 24 * Initialization 25 * 26 * This function looks up all the accesskeys used in the current page 27 * (at anchor elements and input elements [type="submit"]) and registers 28 * appropriate shortcuts. 29 * 30 * @author Marek Sacha <sachamar@fel.cvut.cz> 31 */ 32 this.initialize = function() { 33 var t = this; 34 /** 35 * Lookup all anchors with accesskey and register event - go to anchor 36 * target. 37 */ 38 var anchors = document.getElementsByTagName("a"); 39 t.each(anchors, function(a) { 40 if (a.accessKey != "") { 41 t.addShortcut(t.modifier + '+' + a.accessKey, function() { 42 window.location.href = a.href; 43 }); 44 } 45 }); 46 47 /** 48 * Lookup all input [type="submit"] with accesskey and register event - 49 * perform "click" on a button. 50 */ 51 var inputs = document.getElementsByTagName("input"); 52 t.each(inputs, function(i) { 53 if (i.type == "submit") { 54 t.addShortcut(t.modifier + '+' + i.accessKey, function() { 55 i.click(); 56 }); 57 } 58 }); 59 }; 60 61 /** 62 * Keyup processing function 63 * Function returns true if keyboard event has registered handler, and 64 * executes the handler function. 65 * 66 * @param e KeyboardEvent 67 * @author Marek Sacha <sachamar@fel.cvut.cz> 68 * @return b boolean 69 */ 70 this.onkeyup = function(e) { 71 var t = this; 72 var v = t.findShortcut(e); 73 if (v != null && v != false) { 74 v.func.call(t); 75 return false; 76 } 77 return true; 78 }; 79 80 /** 81 * Keydown processing function 82 * Function returns true if keyboard event has registered handler 83 * 84 * @param e KeyboardEvent 85 * @author Marek Sacha <sachamar@fel.cvut.cz> 86 * @return b boolean 87 */ 88 this.onkeydown = function(e) { 89 var t = this; 90 var v = t.findShortcut(e); 91 if (v != null && v != false) { 92 return false; 93 } 94 return true; 95 }; 96 97 /** 98 * Keypress processing function 99 * Function returns true if keyboard event has registered handler 100 * 101 * @param e KeyboardEvent 102 * @author Marek Sacha <sachamar@fel.cvut.cz> 103 * @return b 104 */ 105 this.onkeypress = function(e) { 106 var t = this; 107 var v = t.findShortcut(e); 108 if (v != null && v != false) { 109 return false; 110 } 111 return true; 112 }; 113 114 /** 115 * Register new shortcut 116 * 117 * This function registers new shortcuts, each shortcut is defined by its 118 * modifier keys and a key (with + as delimiter). If shortcut is pressed 119 * cmd_function is performed. 120 * 121 * For example: 122 * pa = "ctrl+alt+p"; 123 * pa = "shift+alt+s"; 124 * 125 * Full example of method usage: 126 * hotkeys.addShortcut('ctrl+s',function() { 127 * document.getElementByID('form_1').submit(); 128 * }); 129 * 130 * @param pa String description of the shortcut (ctrl+a, ctrl+shift+p, .. ) 131 * @param cmd_func Function to be called if shortcut is pressed 132 * @author Marek Sacha <sachamar@fel.cvut.cz> 133 */ 134 this.addShortcut = function(pa, cmd_func) { 135 var t = this; 136 137 var o = { 138 func : cmd_func, 139 alt : false, 140 ctrl : false, 141 shift : false 142 }; 143 144 t.each(t.explode(pa, '+'), function(v) { 145 switch (v) { 146 case 'alt': 147 case 'ctrl': 148 case 'shift': 149 o[v] = true; 150 break; 151 152 default: 153 o.charCode = v.charCodeAt(0); 154 o.keyCode = v.toUpperCase().charCodeAt(0); 155 } 156 }); 157 158 t.shortcuts.push((o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode, o); 159 160 return true; 161 }; 162 163 /** 164 * @property isMac 165 */ 166 this.isMac = (navigator.userAgent.indexOf('Mac') != -1); 167 168 /** 169 * Apply function cb on each element of o in the namespace of s 170 * @param o Array of objects 171 * @param cb Function to be called on each object 172 * @param s Namespace to be used during call of cb (default namespace is o) 173 * @author Marek Sacha <sachamar@fel.cvut.cz> 174 */ 175 this.each = function(o, cb, s) { 176 var n, l; 177 178 if (!o) 179 return 0; 180 181 s = s || o; 182 183 if (o.length !== undefined) { 184 // Indexed arrays, needed for Safari 185 for (n=0, l = o.length; n < l; n++) { 186 if (cb.call(s, o[n], n, o) === false) 187 return 0; 188 } 189 } else { 190 // Hashtables 191 for (n in o) { 192 if (o.hasOwnProperty(n)) { 193 if (cb.call(s, o[n], n, o) === false) 194 return 0; 195 } 196 } 197 } 198 199 return 1; 200 }; 201 202 /** 203 * Explode string according to delimiter 204 * @param s String 205 * @param d Delimiter (default ',') 206 * @author Marek Sacha <sachamar@fel.cvut.cz> 207 * @return a Array of tokens 208 */ 209 this.explode = function(s, d) { 210 return s.split(d || ','); 211 }; 212 213 /** 214 * Find if the shortcut was registered 215 * 216 * @param e KeyboardEvent 217 * @author Marek Sacha <sachamar@fel.cvut.cz> 218 * @return v Shortcut structure or null if not found 219 */ 220 this.findShortcut = function (e) { 221 var t = this; 222 var v = null; 223 224 /* No modifier key used - shortcut does not exist */ 225 if (!e.altKey && !e.ctrlKey && !e.metaKey) { 226 return v; 227 } 228 229 t.each(t.shortcuts, function(o) { 230 if (t.isMac && o.ctrl != e.metaKey) 231 return; 232 else if (!t.isMac && o.ctrl != e.ctrlKey) 233 return; 234 235 if (o.alt != e.altKey) 236 return; 237 238 if (o.shift != e.shiftKey) 239 return; 240 241 if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) { 242 v = o; 243 return; 244 } 245 }); 246 return v; 247 }; 248} 249 250addInitEvent(function(){ 251 var hotkeys = new Hotkeys(); 252 hotkeys.initialize(); 253 254 addEvent(document,'keyup',function (e) { 255 return hotkeys.onkeyup.call(hotkeys,e); 256 }); 257 258 addEvent(document,'keypress',function (e) { 259 return hotkeys.onkeypress.call(hotkeys,e); 260 }); 261 262 addEvent(document,'keydown',function (e) { 263 return hotkeys.onkeydown.call(hotkeys,e); 264 }); 265});