[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/scripts/ -> hotkeys.js (source)

   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() {
  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       *  overwritten in intitialize (see below)
  22       */
  23      this.modifier = 'ctrl+alt';
  24  
  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;
  39  
  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          }
  46  
  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          });
  60  
  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          });
  74  
  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          });
  88  
  89          /**
  90           * Register listeners on document to catch keyboard events.
  91           */
  92  
  93          addEvent(document,'keyup',function (e) {
  94              return t.onkeyup.call(t,e);
  95          });
  96  
  97          addEvent(document,'keypress',function (e) {
  98              return t.onkeypress.call(t,e);
  99          });
 100  
 101          addEvent(document,'keydown',function (e) {
 102              return t.onkeydown.call(t,e);
 103          });
 104      };
 105  
 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      };
 124  
 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      };
 141  
 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      };
 158  
 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;
 181  
 182          var o = {
 183              func : cmd_func,
 184              alt : false,
 185              ctrl : false,
 186              shift : false
 187          };
 188  
 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;
 196  
 197                  default:
 198                      o.charCode = v.charCodeAt(0);
 199                      o.keyCode = v.toUpperCase().charCodeAt(0);
 200              }
 201          });
 202  
 203          t.shortcuts.push((o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode,  o);
 204  
 205          return true;
 206      };
 207  
 208      /**
 209       * @property isMac
 210       */
 211      this.isMac = is_macos;
 212  
 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;
 222  
 223          if (!o)
 224              return 0;
 225  
 226          s = s || o;
 227  
 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          }
 243  
 244          return 1;
 245      };
 246  
 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      };
 257  
 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;
 268  
 269          /* No modifier key used - shortcut does not exist */
 270          if (!e.altKey && !e.ctrlKey && !e.metaKey) {
 271              return v;
 272          }
 273  
 274          t.each(t.shortcuts, function(o) {
 275              if (o.ctrl != e.ctrlKey)
 276                  return;
 277  
 278              if (o.alt != e.altKey)
 279                  return;
 280  
 281              if (o.shift != e.shiftKey)
 282                  return;
 283  
 284              if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {
 285                  v = o;
 286                  return;
 287              }
 288          });
 289          return v;
 290      };
 291  }
 292  
 293  /**
 294   * Init function for hotkeys. Called from js.php, to ensure hotkyes are initialized after toolbar.
 295   * Call of addInitEvent(initializeHotkeys) is unnecessary now.
 296   *
 297   * @author Marek Sacha <sachamar@fel.cvut.cz>
 298   */
 299  function initializeHotkeys() {
 300      var hotkeys = new Hotkeys();
 301      hotkeys.initialize();
 302  }