[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/editor/atto/yui/src/editor/js/ -> menu.js (source)

   1  // This file is part of Moodle - http://moodle.org/
   2  //
   3  // Moodle is free software: you can redistribute it and/or modify
   4  // it under the terms of the GNU General Public License as published by
   5  // the Free Software Foundation, either version 3 of the License, or
   6  // (at your option) any later version.
   7  //
   8  // Moodle is distributed in the hope that it will be useful,
   9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11  // GNU General Public License for more details.
  12  //
  13  // You should have received a copy of the GNU General Public License
  14  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  15  
  16  /**
  17   * A Menu for the Atto editor.
  18   *
  19   * @module     moodle-editor_atto-menu
  20   * @submodule  menu-base
  21   * @package    editor_atto
  22   * @copyright  2013 Damyon Wiese
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  var MENUDIALOGUE = '' +
  27          '<div class="open {{config.buttonClass}} atto_menu" ' +
  28              'style="min-width:{{config.innerOverlayWidth}};">' +
  29              '<ul class="dropdown-menu">' +
  30                  '{{#each config.items}}' +
  31                      '<li role="presentation" class="atto_menuentry">' +
  32                          '<a href="#" role="menuitem" data-index="{{@index}}" {{#each data}}data-{{@key}}="{{this}}"{{/each}}>' +
  33                              '{{{text}}}' +
  34                          '</a>' +
  35                      '</li>' +
  36                  '{{/each}}' +
  37              '</ul>' +
  38          '</div>';
  39  
  40  /**
  41   * A Menu for the Atto editor used in Moodle.
  42   *
  43   * This is a drop down list of buttons triggered (and aligned to) a
  44   * location.
  45   *
  46   * @namespace M.editor_atto
  47   * @class Menu
  48   * @main
  49   * @constructor
  50   * @extends M.core.dialogue
  51   */
  52  Menu = function() {
  53      Menu.superclass.constructor.apply(this, arguments);
  54  };
  55  
  56  Y.extend(Menu, M.core.dialogue, {
  57  
  58      /**
  59       * A list of the menu handlers which have been attached here.
  60       *
  61       * @property _menuHandlers
  62       * @type Array
  63       * @private
  64       */
  65      _menuHandlers: null,
  66  
  67      initializer: function(config) {
  68          var headertext,
  69              bb;
  70  
  71          this._menuHandlers = [];
  72  
  73          // Create the actual button.
  74          var template = Y.Handlebars.compile(MENUDIALOGUE),
  75              menu = Y.Node.create(template({
  76                  config: config
  77              }));
  78          this.set('bodyContent', menu);
  79  
  80          bb = this.get('boundingBox');
  81          bb.addClass('editor_atto_controlmenu');
  82          bb.addClass('editor_atto_menu');
  83          bb.one('.moodle-dialogue-wrap')
  84              .removeClass('moodle-dialogue-wrap')
  85              .addClass('moodle-dialogue-content');
  86  
  87          headertext = Y.Node.create('<h3/>')
  88                  .addClass('accesshide')
  89                  .setHTML(this.get('headerText'));
  90          this.get('bodyContent').prepend(headertext);
  91  
  92          // Hide the header and footer node entirely.
  93          this.headerNode.hide();
  94          this.footerNode.hide();
  95  
  96          this._setupHandlers();
  97      },
  98  
  99      /**
 100       * Setup the Event handlers.
 101       *
 102       * @method _setupHandlers
 103       * @private
 104       */
 105      _setupHandlers: function() {
 106          var contentBox = this.get('contentBox');
 107          // Handle menu item selection.
 108          this._menuHandlers.push(
 109              // Select the menu item on space, and enter.
 110              contentBox.delegate('key', this._chooseMenuItem, '32, enter', '.atto_menuentry', this),
 111  
 112              // Move up and down the menu on up/down.
 113              contentBox.delegate('key', this._handleKeyboardEvent, 'down:38,40', '.dropdown-menu', this),
 114  
 115              // Hide the menu when clicking outside of it.
 116              contentBox.on('focusoutside', this.hide, this),
 117  
 118              // Hide the menu on left/right, and escape keys.
 119              contentBox.delegate('key', this.hide, 'down:37,39,esc', '.dropdown-menu', this)
 120          );
 121      },
 122  
 123      /**
 124       * Simulate other types of menu selection.
 125       *
 126       * @method _chooseMenuItem
 127       * @param {EventFacade} e
 128       */
 129      _chooseMenuItem: function(e) {
 130          e.target.simulate('click');
 131          e.preventDefault();
 132      },
 133  
 134      /**
 135       * Hide a menu, removing all of the event handlers which trigger the hide.
 136       *
 137       * @method hide
 138       * @param {EventFacade} e
 139       */
 140      hide: function(e) {
 141          if (this.get('preventHideMenu') === true) {
 142              return;
 143          }
 144  
 145          // We must prevent the default action (left/right/escape) because
 146          // there are other listeners on the toolbar which will focus on the
 147          // editor.
 148          if (e) {
 149              e.preventDefault();
 150          }
 151  
 152          return Menu.superclass.hide.call(this, arguments);
 153      },
 154  
 155      /**
 156       * Implement arrow-key navigation for the items in a toolbar menu.
 157       *
 158       * @method _handleKeyboardEvent
 159       * @param {EventFacade} e The keyboard event.
 160       * @static
 161       */
 162      _handleKeyboardEvent: function(e) {
 163          // Prevent the default browser behaviour.
 164          e.preventDefault();
 165  
 166          // Get a list of all buttons in the menu.
 167          var buttons = e.currentTarget.all('a[role="menuitem"]');
 168  
 169          // On cursor moves we loops through the buttons.
 170          var found = false,
 171              index = 0,
 172              direction = 1,
 173              checkCount = 0,
 174              current = e.target.ancestor('a[role="menuitem"]', true);
 175  
 176          // Determine which button is currently selected.
 177          while (!found && index < buttons.size()) {
 178              if (buttons.item(index) === current) {
 179                  found = true;
 180              } else {
 181                  index++;
 182              }
 183          }
 184  
 185          if (!found) {
 186              Y.log("Unable to find this menu item in the menu", 'debug', LOGNAME);
 187              return;
 188          }
 189  
 190          if (e.keyCode === 38) {
 191              // Moving up so reverse the direction.
 192              direction = -1;
 193          }
 194  
 195          // Try to find the next
 196          do {
 197              index += direction;
 198              if (index < 0) {
 199                  index = buttons.size() - 1;
 200              } else if (index >= buttons.size()) {
 201                  // Handle wrapping.
 202                  index = 0;
 203              }
 204              next = buttons.item(index);
 205  
 206              // Add a counter to ensure we don't get stuck in a loop if there's only one visible menu item.
 207              checkCount++;
 208              // Loop while:
 209              // * we are not in a loop and have not already checked every button; and
 210              // * we are on a different button; and
 211              // * the next menu item is not hidden.
 212          } while (checkCount < buttons.size() && next !== current && next.hasAttribute('hidden'));
 213  
 214          if (next) {
 215              next.focus();
 216          }
 217  
 218          e.preventDefault();
 219          e.stopImmediatePropagation();
 220      }
 221  }, {
 222      NAME: "menu",
 223      ATTRS: {
 224          /**
 225           * The header for the drop down (only accessible to screen readers).
 226           *
 227           * @attribute headerText
 228           * @type String
 229           * @default ''
 230           */
 231          headerText: {
 232              value: ''
 233          }
 234  
 235      }
 236  });
 237  
 238  Y.Base.modifyAttrs(Menu, {
 239      /**
 240       * The width for this menu.
 241       *
 242       * @attribute width
 243       * @default 'auto'
 244       */
 245      width: {
 246          value: 'auto'
 247      },
 248  
 249      /**
 250       * When to hide this menu.
 251       *
 252       * By default, this attribute consists of:
 253       * <ul>
 254       * <li>an object which will cause the menu to hide when the user clicks outside of the menu</li>
 255       * </ul>
 256       *
 257       * @attribute hideOn
 258       */
 259      hideOn: {
 260          value: [
 261              {
 262                  eventName: 'clickoutside'
 263              }
 264          ]
 265      },
 266  
 267      /**
 268       * The default list of extra classes for this menu.
 269       *
 270       * @attribute extraClasses
 271       * @type Array
 272       * @default editor_atto_menu
 273       */
 274      extraClasses: {
 275          value: [
 276              'editor_atto_menu'
 277          ]
 278      },
 279  
 280      /**
 281       * Override the responsive nature of the core dialogues.
 282       *
 283       * @attribute responsive
 284       * @type boolean
 285       * @default false
 286       */
 287      responsive: {
 288          value: false
 289      },
 290  
 291      /**
 292       * The default visibility of the menu.
 293       *
 294       * @attribute visible
 295       * @type boolean
 296       * @default false
 297       */
 298      visible: {
 299          value: false
 300      },
 301  
 302      /**
 303       * Whether to centre the menu.
 304       *
 305       * @attribute center
 306       * @type boolean
 307       * @default false
 308       */
 309      center: {
 310          value: false
 311      },
 312  
 313      /**
 314       * Hide the close button.
 315       * @attribute closeButton
 316       * @type boolean
 317       * @default false
 318       */
 319      closeButton: {
 320          value: false
 321      }
 322  });
 323  
 324  Y.namespace('M.editor_atto').Menu = Menu;


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1