1 /*! 2 * This file is part of Aloha Editor Project http://aloha-editor.org 3 * Copyright © 2010-2011 Gentics Software GmbH, aloha@gentics.com 4 * Contributors http://aloha-editor.org/contribution.php 5 * Licensed unter the terms of http://www.aloha-editor.org/license.html 6 *//* 7 * Aloha Editor is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU Affero General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version.* 11 * 12 * Aloha Editor is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU Affero General Public License for more details. 16 * 17 * You should have received a copy of the GNU Affero General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 define( 22 ['aloha/core', 'util/class', 'aloha/jquery', 'aloha/floatingmenu', 'aloha/ext', 'aloha/console', 'i18n!aloha/nls/i18n'], 23 function(Aloha, Class, jQuery, FloatingMenu, Ext, console, i18n) { 24 "use strict"; 25 26 var 27 // $ = jQuery, 28 // Aloha = window.Aloha, 29 // Ext = window.Ext, 30 // Class = window.Class; 31 GENTICS = window.GENTICS; 32 33 // Ensure Namespace 34 Aloha.ui = Aloha.ui || {}; 35 36 // internationalize ext js message box buttons 37 Ext.MessageBox.buttonText.yes = i18n.t('yes'); 38 Ext.MessageBox.buttonText.no = i18n.t('no'); 39 Ext.MessageBox.buttonText.cancel = i18n.t('cancel'); 40 41 /** 42 * This is the Gentics Version of the ExtJS Menu. It is necessary to extend the 43 * Ext.menu.Menu in order to stop propagation of the mousedown event on the DOM 44 * element of the menu, because a click in the menu shall not deactivate the 45 * editable. 46 */ 47 Ext.ux.GENTICSMenu = Ext.extend(Ext.menu.Menu, { 48 /** 49 * overwrite onRender 50 */ 51 onRender: function() { 52 // call the super method 53 Ext.ux.GENTICSMenu.superclass.onRender.apply(this, arguments); 54 55 // stop propagation of the mousedown event 56 jQuery(this.el.dom).mousedown(function (e) { 57 e.stopPropagation(); 58 }); 59 } 60 }); 61 62 /** 63 * Constructor for an Aloha button. 64 * @namespace Aloha.ui 65 66 * @class Button 67 * @param {Object} properties Properties of the button: 68 * - label: Label that is displayed on the button. 69 * - onclick: Callback function of the button when activated. 70 * - menu: Array of Aloha.ui.Button elements that are displayed as drop-down menu. 71 * - iconClass: Icon displayed on the button. 72 * - icon: URL to an icon that is displayed on the button. 73 * - toggle: Boolean that indicates if the button is a toggle button. 74 */ 75 Aloha.ui.Button = Class.extend({ 76 _constructor: function(properties) { 77 this.init(properties); 78 }, 79 80 /** 81 * Init method for an Aloha button. 82 * This method is necessary due to JS specific initalization. 83 * @namespace Aloha.ui 84 85 * @class Button 86 * @param {Object} properties Properties of the button: 87 * - label: Label that is displayed on the button. 88 * - onclick: Callback function of the button when activated. 89 * - menu: Array of Aloha.ui.Button elements that are displayed as drop-down menu. 90 * - iconClass: Icon displayed on the button. 91 * - icon: URL to an icon that is displayed on the button. 92 * - toggle: Boolean that indicates if the button is a toggle button. 93 */ 94 init: function(properties) { 95 /** 96 * Label that is displayed on the button 97 * @hide 98 */ 99 this.label = false; 100 101 /** 102 * Name for the button 103 */ 104 this.name = false; 105 106 /** 107 * CSS class for an icon on the button 108 * @hide 109 */ 110 this.iconClass = false; 111 112 /** 113 * URL to an icon to display on the button 114 * @hide 115 */ 116 this.icon = false; 117 118 /** 119 * Callback function when the button is activated. 120 * The "this" variable refers to the button inside the callback function. 121 * @hide 122 */ 123 this.onclick = false; 124 125 /** 126 * Array of buttons that are displayed in a drop down menu. 127 * If a menu is provided and no onclick callback then clicking the button also opens the menu 128 * @hide 129 */ 130 this.menu = null; 131 132 /** 133 * Indicates if the button is a toggle button 134 * @hide 135 */ 136 this.toggle = false; 137 138 /** 139 * Property that indicates if the button is in pressed state 140 * @hide 141 */ 142 this.pressed = false; 143 144 /** 145 * Property that indicates whether the button is currently visible 146 * @hide 147 */ 148 this.visible = true; 149 150 /** 151 * Property that indicates whether the button is currently enabled 152 * @hide 153 */ 154 this.enabled = true; 155 156 /** 157 * Tooltip text 158 * @hide 159 */ 160 this.tooltip = false; 161 162 /** 163 * holds the ext object of the button 164 * @hide 165 */ 166 this.extButton = null; 167 168 /** 169 * holds the listeners of the button 170 * @hide 171 */ 172 this.listenerQueue = []; 173 174 GENTICS.Utils.applyProperties(this, properties); 175 176 // use icon class as a fallback for name 177 if (this.name === false) { 178 this.name = this.iconClass; 179 } 180 181 /** 182 * Unique Id of the button 183 * @hide 184 */ 185 this.id = this.generateId(); 186 }, 187 188 /** 189 * Generate a unique id for the button 190 * @return unique id 191 * @hide 192 */ 193 generateId: function () { 194 Aloha.ui.Button.idCounter = Aloha.ui.Button.idCounter + 1; 195 return 'aloha-button' + Aloha.ui.Button.idCounter; 196 }, 197 198 /** 199 * Set the 'pressed' state of the button if it is a toggle button 200 * @param {bool} pressed true when the button shall be 'pressed', false if not 201 */ 202 setPressed: function(pressed) { 203 if (this.toggle) { 204 this.pressed = pressed; 205 if (typeof this.extButton === 'object' && this.extButton != null && this.extButton.pressed != pressed) { 206 this.extButton.toggle(this.pressed); 207 } 208 } 209 }, 210 211 /** 212 * Indicates if the button is currently in "pressed" state. 213 * This is only relevant if the button is a toggle button. 214 * If the button is no toggle button this function always returns false. 215 * @return {bool} True if the button is pressed, false otherwise. 216 */ 217 isPressed: function() { 218 if (this.toggle) { 219 return this.pressed; 220 } 221 return false; 222 }, 223 224 /** 225 * Show the button. When this button is added to the FloatingMenu, it is 226 * necessary to call FloatingMenu.doLayout() after the visibility 227 * of the button is changed 228 */ 229 show: function() { 230 this.visible = true; 231 }, 232 233 /** 234 * Hide the button. When this button is added to the FloatingMenu, it is 235 * necessary to call FloatingMenu.doLayout() after the visibility 236 * of the button is changed 237 */ 238 hide: function() { 239 this.visible = false; 240 }, 241 242 /** 243 * Check whether the button is visible or not 244 * @return true when the button is visible, false if not 245 */ 246 isVisible: function() { 247 return this.visible; 248 }, 249 250 /** 251 * Enable the button - make it clickable 252 */ 253 enable: function() { 254 this.enabled = true; 255 if (typeof this.extButton === 'object') { 256 this.extButton.enable(); 257 } 258 }, 259 260 /** 261 * Disable the button 262 */ 263 disable: function() { 264 this.enabled = false; 265 if (typeof this.extButton === 'object') { 266 this.extButton.disable(); 267 } 268 }, 269 270 /** 271 * Check whether the button is currently enabled 272 * @return true when the button is enabled, false if it is disabled 273 */ 274 isEnabled: function() { 275 return this.enabled; 276 }, 277 278 /** 279 * Get the Ext menu from this button 280 * @return Ext menu 281 * @hide 282 */ 283 getExtMenu: function() { 284 var menu, i, entry; 285 if ( this.menu && typeof this.menu === 'object') { 286 // build the drop down menu 287 menu = new Ext.ux.GENTICSMenu(); 288 for (i = 0; i < this.menu.length; ++i) { 289 entry = this.menu[i]; 290 menu.addItem(new Ext.menu.Item(entry.getExtMenuConfigProperties())); 291 } 292 } 293 return menu; 294 }, 295 296 /** 297 * Get the config properties for this button as menu entry 298 * @return config properties for this button as menu entry 299 * @hide 300 */ 301 getExtMenuConfigProperties: function() { 302 var me = this, 303 submenu = this.getExtMenu(); 304 305 return { 306 text: this.label, 307 icon: this.icon, 308 iconCls: this.iconClass, 309 handler: function () { 310 if (typeof me.onclick == 'function') { 311 me.onclick(); 312 } 313 }, 314 menu: submenu 315 }; 316 }, 317 318 /** 319 * Return an object containing the config properties to generate this button 320 * @return config properties 321 * @hide 322 */ 323 getExtConfigProperties: function() { 324 var me = this, 325 menu = this.getExtMenu(), 326 327 // configuration for the button 328 buttonConfig = { 329 text : this.label, 330 enableToggle: this.toggle, 331 pressed : this.pressed, 332 icon: this.icon, 333 iconCls: this.iconClass, 334 scale : this.scale||this.size, 335 width : this.width||undefined, 336 rowspan : this.rowspan || ((this.size == 'large' || this.size == 'medium') ? 2 : 1), 337 menu : menu, 338 handler : function(element, event) { 339 if (typeof me.onclick === 'function') { 340 me.onclick.apply(me, [element, event]); 341 } 342 if ( me.toggle ) { 343 me.pressed = !me.pressed; 344 } 345 }, 346 xtype : (menu && typeof this.onclick == 'function') ? 'splitbutton' : 'button', 347 tooltipType : 'qtip', 348 tooltip : this.tooltip, 349 id : this.id, 350 arrowAlign: this.arrowAlign || (this.size == 'large' || this.size == 'small' ? 'right' : 'bottom') 351 }; 352 353 return buttonConfig; 354 } 355 }); 356 357 /** 358 * id counter, for generation of unique id's for the buttons 359 * @hide 360 */ 361 Aloha.ui.Button.idCounter = 0; 362 363 /** 364 * extJS Multi Split Button 365 * 366 * Display a Word-like formatting selection button 367 * Selection images are typically 52*42 in size 368 * 369 * Example configuration 370 * xtype : 'genticsmultisplitbutton', 371 * items : [{ 372 * 'name' : 'normal', // the buttons name, used to identify it 373 * 'title' : 'Basic Text', // the buttons title, which will be displayed 374 * 'icon' : 'img/icon.jpg', // source for the icon 375 * 'click' : function() { alert('normal'); } // callback if the button is clicked 376 * 'wide' : false // wether it's a wide button, which would be dispalyed at the bottom 377 * }] 378 * 379 * you might want to check out the tutorial at 380 * http://www.extjs.com/learn/Tutorial:Creating_new_UI_controls 381 * @hide 382 */ 383 Ext.ux.MultiSplitButton = Ext.extend(Ext.Component, { 384 initComponent: function() { 385 var me = this; 386 this.on('beforehide', function() { 387 me.closePanel(); 388 }); 389 }, 390 /** 391 * add a css class to the wrapper-div autogenerated by extjs 392 * @hide 393 */ 394 autoEl: { 395 cls: 'aloha-multisplit-wrapper' 396 }, 397 398 /** 399 * will contain a reference to the ul dom object 400 * @hide 401 */ 402 ulObj: null, 403 404 /** 405 * holds a reference to the expand button 406 * @hide 407 */ 408 panelButton: null, 409 410 /** 411 * hold a reference to the wrapper div 412 * @hide 413 */ 414 wrapper: null, 415 416 /** 417 * true if the panel is expanded 418 * @hide 419 */ 420 panelOpened: false, 421 422 /** 423 * get items for the multisplit button according to config 424 * configuration for a multisplit button has to be stored 425 * within an array: 426 * 427 * Aloha.settings.components.[MULTISPLITBUTTON-NAME] = [ 'item1', 'item2' ]; 428 * 429 * An example for that would be: 430 * 431 * // settings for phrasing element for the format plugin 432 * Aloha.settings.components.phrasing = [ 'h1', 'h2', 'h3', 'removeFormat' ]; 433 * 434 * if there is no config available, it will just use all items available 435 * @return button items for this multisplit button 436 */ 437 _getItems: function() { 438 var that = this, 439 items = [], 440 i, length; 441 442 if (Aloha.settings.components && 443 Aloha.settings.components[this.name] && 444 typeof Aloha.settings.components[this.name] === 'object') { 445 // iterate over all buttons in our config... 446 jQuery.each(Aloha.settings.components[this.name], function (idx, button) { 447 for (i = 0, length = that.items.length; i < length; i++) { 448 if (that.items[i].name === button) { 449 // ... and find the appropriate internal button 450 items.push(that.items[i]); 451 break; 452 } 453 } 454 }); 455 return items; 456 } else { 457 return this.items; 458 } 459 }, 460 461 /** 462 * render the multisplit button 463 * @return void 464 * @hide 465 */ 466 onRender: function() { 467 Ext.ux.MultiSplitButton.superclass.onRender.apply(this, arguments); 468 // create a reference to this elements dom object 469 this.wrapper = jQuery(this.el.dom); 470 471 var 472 me = this, 473 i, 474 item, 475 items, 476 html = '<ul class="aloha-multisplit">'; 477 478 items = this._getItems(); 479 480 // add a new button to the list for each configured item 481 for (i=0; i<items.length; i++) { 482 item = items[i]; 483 if (typeof item.visible == 'undefined') { 484 item.visible = true; 485 } 486 // wide buttons will always be rendered at the bottom of the list 487 if (item.wide) { 488 continue; 489 } 490 html += '<li>' + 491 '<button xmlns:ext="http://www.extjs.com/" class="' + item.iconClass + '" ext:qtip="' + item.tooltip + '" gtxmultisplititem="' + i + '"> </button>' + 492 '</li>'; 493 } 494 495 // now add the wide buttons at the bottom of the list 496 for (i=0; i<items.length; i++) { 497 item = items[i]; 498 // now only wide buttons will be rendered 499 if (!item.wide) { 500 continue; 501 } 502 503 html += '<li>' + 504 '<button xmlns:ext="http://www.extjs.com/" class="aloha-multisplit-wide ' + item.iconClass + '" ext:qtip="' + item.tooltip + '" gtxmultisplititem="' + i + '">' + 505 item.text + '</button>' + 506 '</li>'; 507 } 508 509 html += '</ul>'; 510 511 // register on move event, which occurs when the panel was dragged 512 // this should be done within the constructor, but ist not possible there 513 // since the extTabPanel will not be initialized at this moment 514 FloatingMenu.extTabPanel.on('move', function () { 515 me.closePanel(); 516 }); 517 FloatingMenu.extTabPanel.on('tabchange', function () { 518 me.closePanel(); 519 }); 520 521 // add onclick event handler 522 this.ulObj = jQuery(this.el.createChild(html).dom) 523 .click(function (event) { 524 me.onClick(event); 525 }); 526 527 // add the expand button 528 this.panelButton = jQuery( 529 this.el.createChild('<button class="aloha-multisplit-toggle aloha-multisplit-toggle-open"> </button>').dom 530 ) 531 .click(function () { 532 me.togglePanel(); 533 }); 534 }, 535 536 /** 537 * callback if a button has been clicked 538 * @param event jquery event object 539 * @return void 540 * @hide 541 */ 542 onClick: function(event) { 543 // check if the element has a gtxmultisplititem attribute assigned 544 if (!event.target.attributes.gtxmultisplititem) { 545 return; 546 } 547 var el = jQuery(event.target); 548 549 // collapse the panel 550 this.closePanel(); 551 552 // wide buttons cannot become the active element 553 if (!el.hasClass('aloha-multisplit-wide')) { 554 this.setActiveDOMElement(el); 555 } 556 557 // invoke the items function 558 this.items[event.target.attributes.gtxmultisplititem.value].click(); 559 }, 560 561 /** 562 * set the active item specified by its name 563 * @param name the name of the item to be marked as active 564 * @return void 565 * @hide 566 */ 567 setActiveItem: function(name) { 568 var button; 569 570 // collapse the panel 571 this.closePanel(); 572 573 button = jQuery('#' + this.id + ' .aloha-button-' + name); 574 if (button.length === 1) { 575 this.setActiveDOMElement(button); 576 this.activeItem = name; 577 } else { 578 this.setActiveDOMElement(null); 579 this.activeItem = null; 580 } 581 }, 582 583 /** 584 * mark an item as active 585 * @param el jquery obj for item to be marked as active 586 * @return void 587 * @hide 588 */ 589 setActiveDOMElement: function(el) { 590 // when the component (or one of its owners) is currently hidden, we need to set the active item later 591 var ct = this, top; 592 while (typeof ct !== 'undefined') { 593 if (ct.hidden) { 594 this.activeDOMElement = el; 595 return; 596 } 597 ct = ct.ownerCt; 598 } 599 600 jQuery(this.ulObj).find('.aloha-multisplit-activeitem').removeClass('aloha-multisplit-activeitem'); 601 if(el) { 602 el.parent().addClass('aloha-multisplit-activeitem'); 603 } 604 605 if ( !el || el.parent().is(':hidden')) { 606 return; 607 } 608 609 // reposition multisplit contents to the active item 610 if ( el && this.ulObj ) { 611 this.ulObj.css('margin-top', 0); 612 top = el.position().top; 613 this.ulObj.css({ 614 'margin-top': - top + 6, 615 'height': 46 + top - 6 616 }); 617 } 618 619 this.activeDOMElement = undefined; 620 }, 621 /** 622 * toggle the panel display from closed to expanded or vice versa 623 * @return void 624 * @hide 625 */ 626 togglePanel: function() { 627 if (this.panelOpened) { 628 this.closePanel(); 629 } else { 630 this.openPanel(); 631 } 632 }, 633 634 /** 635 * expand the button panel 636 * @return void 637 * @hide 638 */ 639 openPanel: function() { 640 if (this.panelOpened) { 641 return; 642 } 643 644 var o = this.wrapper.offset(); 645 646 // detach the ul element and reattach it onto the body 647 this.ulObj 648 .appendTo(jQuery('body')) 649 .addClass('aloha-multisplit-expanded') 650 .mousedown(function (e) { 651 e.stopPropagation(); 652 }) 653 .css({ 654 // relocate the ul 655 'top': o.top - 1, 656 'left': o.left - 1 657 }) 658 .animate({ 659 // display expand animation 660 height: (this.ulObj.prop)?this.ulObj.prop('scrollHeight'):this.ulObj.attr('scrollHeight') 661 }); 662 663 // TODO change to css 664 this.panelButton 665 .removeClass('aloha-multisplit-toggle-open') 666 .addClass('aloha-multisplit-toggle-close'); 667 this.panelOpened = true; 668 }, 669 670 /** 671 * collapses the panel 672 * @return void 673 * @hide 674 */ 675 closePanel: function() { 676 if (!this.panelOpened) { 677 return; 678 } 679 680 this.ulObj 681 .removeClass('aloha-multisplit-expanded') 682 .appendTo(this.wrapper); 683 684 // TODO change to css 685 this.panelButton 686 .addClass('aloha-multisplit-toggle-open') 687 .removeClass('aloha-multisplit-toggle-close'); 688 this.panelOpened = false; 689 }, 690 691 /** 692 * hides a multisplit item 693 * @return void 694 * @hide 695 */ 696 hideItem: function(name) { 697 for (var i = 0; i<this.items.length; i++) { 698 if (this.items[i].name == name) { 699 this.items[i].visible = false; 700 // hide the corresponding dom object 701 jQuery('#' + this.id + ' [gtxmultisplititem=' + i + ']').parent().hide(); 702 return; 703 } 704 } 705 }, 706 707 /** 708 * shows an item 709 * @return void 710 * @hide 711 */ 712 showItem: function(name) { 713 for (var i = 0; i<this.items.length; i++) { 714 if (this.items[i].name == name) { 715 this.items[i].visible = true; 716 // hide the corresponding dom object 717 jQuery('#' + this.id + ' [gtxmultisplititem=' + i + ']').parent().show(); 718 return; 719 } 720 } 721 } 722 }); 723 Ext.reg('alohamultisplitbutton', Ext.ux.MultiSplitButton); 724 725 /** 726 * Aloha MultiSplit Button 727 * @namespace Aloha.ui 728 * @class MultiSplitButton 729 * @param {Object} properties properties object for the new multisplit button 730 * however you just have to fill out the items property of this object 731 * items : [{ 732 * 'name' : 'normal', // the buttons name, used to identify it 733 * 'tooltip' : 'Basic Text', // the buttons tooltip, which will be displayed on hover 734 * 'text' : 'Basic Text', // text to display on wide buttons 735 * 'icon' : 'img/icon.jpg', // source for the icon 736 * 'click' : function() { alert('normal'); } // callback if the button is clicked 737 * 'wide' : false // whether it's a wide button, which would be dispalyed at the bottom 738 * }] 739 */ 740 Aloha.ui.MultiSplitButton = Class.extend({ 741 _constructor: function(properties) { 742 /** 743 * Items in the Multisplit Button 744 * @hide 745 */ 746 this.items = []; 747 GENTICS.Utils.applyProperties(this, properties); 748 749 /** 750 * unique id for all buttons 751 * @hide 752 */ 753 this.id = this.generateId(); 754 }, 755 756 /** 757 * Generate a unique id for the button 758 * @return unique id 759 * @hide 760 */ 761 generateId: function () { 762 Aloha.ui.MultiSplitButton.idCounter = Aloha.ui.MultiSplitButton.idCounter + 1; 763 return 'aloha-multisplitbutton' + Aloha.ui.MultiSplitButton.idCounter; 764 }, 765 766 /** 767 * Return an object containing the config properties to generate this button 768 * @return config properties 769 * @hide 770 */ 771 getExtConfigProperties: function() { 772 return { 773 'xtype' : 'alohamultisplitbutton', 774 'items' : this.items, 775 'name' : this.name, 776 'id' : this.id 777 }; 778 }, 779 780 /** 781 * Set the active item of the multisplitbutton 782 * @param {String} name name of the item to be set active 783 */ 784 setActiveItem: function(name) { 785 if (this.extButton && typeof name !== 'undefined') { 786 this.extButton.setActiveItem(name); 787 } 788 }, 789 790 /** 791 * check whether the multisplit button is visible 792 * @return boolean true if visible 793 */ 794 isVisible: function() { 795 // if all items are hidden, disable this item 796 for (var i=0; i<this.items.length; i++) { 797 // if just one item is visible that's enough 798 if (this.items[i].visible) { 799 return true; 800 } 801 } 802 return false; 803 }, 804 805 /** 806 * shows an item of the multisplit button 807 * @param {String} name the item's name 808 */ 809 showItem: function(name) { 810 if (typeof this.extButton === 'undefined') { 811 return; 812 } 813 this.extButton.showItem(name); 814 }, 815 816 /** 817 * hides an item of the multisplit button 818 * @param {String} name the item's name 819 */ 820 hideItem: function(name) { 821 if (typeof this.extButton === 'undefined') { 822 return; 823 } 824 this.extButton.hideItem(name); 825 } 826 }); 827 828 /** 829 * Method to access translations 830 * @deprecated 831 * This will be removed in one of the next version 832 */ 833 Aloha.i18n = function(component, key, replacements) { 834 console.deprecated ('Aloha', 'i18n() is deprecated. Use module "i18n!aloha/nls/i18n" instead.'); 835 return key; 836 }; 837 838 839 /** 840 * Displays a message according to it's type 841 * @method 842 * @param {Aloha.Message} message the Aloha.Message object to be displayed 843 */ 844 Aloha.showMessage = function (message) { 845 846 if (FloatingMenu.obj) { 847 FloatingMenu.obj.css('z-index', 8900); 848 } 849 850 851 switch (message.type) { 852 case Aloha.Message.Type.ALERT: 853 Ext.MessageBox.alert(message.title, message.text, message.callback); 854 break; 855 case Aloha.Message.Type.CONFIRM: 856 Ext.MessageBox.confirm(message.title, message.text, message.callback); 857 break; 858 case Aloha.Message.Type.WAIT: 859 Ext.MessageBox.wait(message.text, message.title); 860 break; 861 862 default: 863 Aloha.log('warn', this, 'Unknown message type for message {' + message.toString() + '}'); 864 break; 865 } 866 }; 867 868 /** 869 * Hides the currently active modal, which was displayed by showMessage() 870 * @method 871 */ 872 Aloha.hideMessage = function () { 873 Ext.MessageBox.hide(); 874 }; 875 876 /** 877 * checks if a modal dialog is visible right now 878 * @method 879 * @return true if a modal is currently displayed 880 */ 881 Aloha.isMessageVisible = function () { 882 return Ext.MessageBox.isVisible(); 883 }; 884 885 /** 886 * id counter, for generation of unique id's for the buttons 887 * @hide 888 */ 889 Aloha.ui.MultiSplitButton.idCounter = 0; 890 891 return Aloha.ui; 892 893 }); 894