~bcsaller/juju-gui/export-ui

« back to all changes in this revision

Viewing changes to app/app.js

  • Committer: Benjamin Saller
  • Author(s): Benjamin Saller
  • Date: 2013-05-05 17:28:34 UTC
  • mfrom: (647.1.8 help-popup)
  • Revision ID: bcsaller@gmail.com-20130505172834-0ocgmh0qcua2jphb
Popup Help Generated from new keyboard handling.

Replace exisitng keyboard support with new declarative system.
Generate popup help using declared bindings.

R=matthew.scott, gary.poster
CC=
https://codereview.appspot.com/9038045

Show diffs side-by-side

added added

removed removed

Lines of Context:
120
120
    },
121
121
 
122
122
    /**
 
123
     * Declarative keybindings on the window object.
 
124
     *
 
125
     * Prefix supported are:
 
126
     *   C - Control
 
127
     *   A - Alt
 
128
     *   S - Shift
 
129
     *
 
130
     * Followed by a lowercase letter. For example
 
131
     *
 
132
     * A-s is the 'Alt + s' keybinding.
 
133
     *
 
134
     * This maps to an object which has the following behavior.
 
135
     *
 
136
     * target: {String} CSS selector of one element
 
137
     * focus: {Boolean} Focus the element.
 
138
     * toggle: {Boolean} Toggle element visibility.
 
139
     * callback: {Function} Taking (event, target).
 
140
     * help: {String} Help text to display in popup.
 
141
     *
 
142
     * All are optional.
 
143
     *
 
144
     *
 
145
     */
 
146
    keybindings: {
 
147
      'A-s': {
 
148
        target: '#charm-search-field',
 
149
        focus: true,
 
150
        help: 'Select the charm Search'
 
151
      },
 
152
      'S-/': {
 
153
        target: '#shortcut-help',
 
154
        toggle: true,
 
155
        callback: function(evt, target) {
 
156
          // This could be its own view.
 
157
          if (target && !target.getHTML().length) {
 
158
            var bindings = [];
 
159
            Y.each(this.keybindings, function(v, k) {
 
160
              if (v.help) {
 
161
                bindings.push({key: k, help: v.help});
 
162
              }
 
163
            });
 
164
            target.setHTML(
 
165
                views.Templates.shortcuts({bindings: bindings}));
 
166
          }
 
167
        },
 
168
        help: 'Display this help'
 
169
      },
 
170
      'A-e': {
 
171
        callback: function(evt) {
 
172
          this.fire('navigateTo', {url: '/:gui:/'});
 
173
        },
 
174
        help: 'Navigate to the Environment overview.'
 
175
      },
 
176
      'esc': {
 
177
        callback: function() {
 
178
          // Explicitly hide anything we might care about.
 
179
          Y.one('#shortcut-help').hide();
 
180
        },
 
181
        help: 'Cancel current action'
 
182
      }
 
183
    },
 
184
 
 
185
    /**
123
186
     * Data driven behaviors
124
187
     *
125
188
     * Placeholder for real behaviors associated with DOM Node data-*
154
217
     * @method activateHotkeys
155
218
     */
156
219
    activateHotkeys: function() {
157
 
      Y.one(window).on('keydown', function(ev) {
158
 
        var key = [],
159
 
            keyStr = null,
160
 
            data = { preventDefault: false };
161
 
        if (ev.altKey) {
162
 
          key.push('alt');
163
 
        } else if (ev.ctrlKey) {
164
 
          key.push('ctrl');
165
 
        } else if (ev.shiftKey) {
166
 
          key.push('shift');
167
 
        }
168
 
        if (key.length === 0 &&
169
 
            // If we have no modifier, check if this is a function or the ESC
170
 
            // key. If it is not one of these keys, do nothing.
171
 
            !(ev.keyCode >= 112 && ev.keyCode <= 123 || ev.keyCode === 27)) {
172
 
          return; //nothing to do
173
 
        }
174
 
        keyStr = keyCodeToString(ev.keyCode);
175
 
        if (!keyStr) {
176
 
          keyStr = ev.keyCode;
177
 
        }
178
 
        key.push(keyStr);
179
 
        Y.fire('window-' + key.join('-') + '-pressed', data);
180
 
        if (data.preventDefault) {
181
 
          ev.preventDefault();
182
 
        }
 
220
      var key_map = {
 
221
        '/': 191, '?': 63,
 
222
        enter: 13, esc: 27, backspace: 8,
 
223
        tab: 9, pageup: 33, pagedown: 34};
 
224
      var code_map = {};
 
225
      Y.each(key_map, function(v, k) {
 
226
        code_map[v] = k;
183
227
      });
184
 
 
185
 
      Y.detachAll('window-alt-E-pressed');
186
 
      Y.on('window-alt-E-pressed', function(data) {
187
 
        this.fire('navigateTo', {url: this.nsRouter.url({gui: '/'})});
188
 
        data.preventDefault = true;
189
 
      }, this);
190
 
 
191
 
      Y.detachAll('window-alt-S-pressed');
192
 
      Y.on('window-alt-S-pressed', function(data) {
193
 
        var field = Y.one('#charm-search-field');
194
 
        if (field) {
195
 
          field.focus();
196
 
        }
197
 
        data.preventDefault = true;
198
 
      }, this);
199
 
 
200
 
      /**
201
 
       * Transform a numeric keyCode value to its string version. Example:
202
 
       * 16 returns 'shift'.
203
 
       *
204
 
       * @param {number} keyCode The numeric value of a key.
205
 
       * @return {string} The string version of the given keyCode.
206
 
       * @method keyCodeToString
207
 
       */
208
 
      function keyCodeToString(keyCode) {
209
 
        if (keyCode === 16) {
210
 
          return 'shift';
211
 
        }
212
 
        if (keyCode === 17) {
213
 
          return 'control';
214
 
        }
215
 
        if (keyCode === 18) {
216
 
          return 'alt';
217
 
        }
218
 
        if (keyCode === 27) {
219
 
          return 'esc';
220
 
        }
221
 
        // Numbers or Letters
222
 
        if (keyCode >= 48 && keyCode <= 57 || //Numbers
223
 
            keyCode >= 65 && keyCode <= 90) { //Letters
224
 
          return String.fromCharCode(keyCode);
225
 
        }
226
 
        //F1 -> F12
227
 
        if (keyCode >= 112 && keyCode <= 123) {
228
 
          return 'F' + (keyCode - 111);
229
 
        }
230
 
        return null;
231
 
      }
 
228
      Y.one(window).on('keydown', function(evt) {
 
229
        //Normalize key-code
 
230
        var symbolic = [];
 
231
        if (evt.ctrlKey) { symbolic.push('C');}
 
232
        if (evt.altKey) { symbolic.push('A');}
 
233
        if (evt.shiftKey) { symbolic.push('S');}
 
234
        symbolic.push(code_map[evt.keyCode] ||
 
235
                      String.fromCharCode(evt.keyCode).toLowerCase());
 
236
        var trigger = symbolic.join('-');
 
237
        var spec = this.keybindings[trigger];
 
238
        if (spec) {
 
239
          var target = Y.one(spec.target);
 
240
          if (target) {
 
241
            if (spec.toggle) { target.toggleView(); }
 
242
            if (spec.focus) { target.focus(); }
 
243
          }
 
244
          if (spec.callback) { spec.callback.call(this, evt, target); }
 
245
          // If we handled the event nothing else has to.
 
246
          evt.stopPropagation();
 
247
          evt.preventDefault();
 
248
        }
 
249
      }, this);
232
250
    },
233
251
 
234
252
    /**
1119
1137
    'app-subapp-extension',
1120
1138
    'sub-app',
1121
1139
    'subapp-browser',
 
1140
    'event-key',
1122
1141
    'event-touch',
1123
1142
    'model-controller']
1124
1143
});