[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
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;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |