1YUI.add('widget-child', function (Y, NAME) { 2 3/** 4 * Extension enabling a Widget to be a child of another Widget. 5 * 6 * @module widget-child 7 */ 8 9var Lang = Y.Lang; 10 11/** 12 * Widget extension providing functionality enabling a Widget to be a 13 * child of another Widget. 14 * 15 * @class WidgetChild 16 * @param {Object} config User configuration object. 17*/ 18function Child() { 19 20 // Widget method overlap 21 Y.after(this._syncUIChild, this, "syncUI"); 22 Y.after(this._bindUIChild, this, "bindUI"); 23 24} 25 26Child.ATTRS = { 27 28 /** 29 * @attribute selected 30 * @type Number 31 * @default 0 32 * 33 * @description Number indicating if the Widget is selected. Possible 34 * values are: 35 * <dl> 36 * <dt>0</dt> <dd>(Default) Not selected</dd> 37 * <dt>1</dt> <dd>Fully selected</dd> 38 * <dt>2</dt> <dd>Partially selected</dd> 39 * </dl> 40 */ 41 selected: { 42 value: 0, 43 validator: Lang.isNumber 44 }, 45 46 47 /** 48 * @attribute index 49 * @type Number 50 * @readOnly 51 * 52 * @description Number representing the Widget's ordinal position in its 53 * parent Widget. 54 */ 55 index: { 56 readOnly: true, 57 getter: function () { 58 59 var parent = this.get("parent"), 60 index = -1; 61 62 if (parent) { 63 index = parent.indexOf(this); 64 } 65 66 return index; 67 68 } 69 }, 70 71 72 /** 73 * @attribute parent 74 * @type Widget 75 * @readOnly 76 * 77 * @description Retrieves the parent of the Widget in the object hierarchy. 78 */ 79 parent: { 80 readOnly: true 81 }, 82 83 84 /** 85 * @attribute depth 86 * @type Number 87 * @default -1 88 * @readOnly 89 * 90 * @description Number representing the depth of this Widget relative to 91 * the root Widget in the object heirarchy. 92 */ 93 depth: { 94 readOnly: true, 95 getter: function () { 96 97 var parent = this.get("parent"), 98 root = this.get("root"), 99 depth = -1; 100 101 while (parent) { 102 103 depth = (depth + 1); 104 105 if (parent == root) { 106 break; 107 } 108 109 parent = parent.get("parent"); 110 111 } 112 113 return depth; 114 115 } 116 }, 117 118 /** 119 * @attribute root 120 * @type Widget 121 * @readOnly 122 * 123 * @description Returns the root Widget in the object hierarchy. If the 124 * ROOT_TYPE property is set, the search for the root Widget will be 125 * constrained to parent Widgets of the specified type. 126 */ 127 root: { 128 readOnly: true, 129 getter: function () { 130 131 var getParent = function (child) { 132 133 var parent = child.get("parent"), 134 FnRootType = child.ROOT_TYPE, 135 criteria = parent; 136 137 if (FnRootType) { 138 criteria = (parent && Y.instanceOf(parent, FnRootType)); 139 } 140 141 return (criteria ? getParent(parent) : child); 142 143 }; 144 145 return getParent(this); 146 147 } 148 } 149 150}; 151 152Child.prototype = { 153 154 /** 155 * Constructor reference used to determine the root of a Widget-based 156 * object tree. 157 * <p> 158 * Currently used to control the behavior of the <code>root</code> 159 * attribute so that recursing up the object heirarchy can be constrained 160 * to a specific type of Widget. Widget authors should set this property 161 * to the constructor function for a given Widget implementation. 162 * </p> 163 * 164 * @property ROOT_TYPE 165 * @type Object 166 */ 167 ROOT_TYPE: null, 168 169 /** 170 * Returns the node on which to bind delegate listeners. 171 * 172 * Override of Widget's implementation of _getUIEventNode() to ensure that 173 * all event listeners are bound to the Widget's topmost DOM element. 174 * This ensures that the firing of each type of Widget UI event (click, 175 * mousedown, etc.) is facilitated by a single, top-level, delegated DOM 176 * event listener. 177 * 178 * @method _getUIEventNode 179 * @for Widget 180 * @protected 181 */ 182 _getUIEventNode: function () { 183 var root = this.get("root"), 184 returnVal; 185 186 if (root) { 187 returnVal = root.get("boundingBox"); 188 } 189 190 return returnVal; 191 }, 192 193 /** 194 * @method next
195 * @description Returns the Widget's next sibling. 196 * @param {Boolean} circular Boolean indicating if the parent's first child 197 * should be returned if the child has no next sibling. 198 * @return {Widget} Widget instance. 199 */ 200 next: function (circular) { 201 202 var parent = this.get("parent"), 203 sibling; 204 205 if (parent) { 206 sibling = parent.item((this.get("index")+1)); 207 } 208 209 if (!sibling && circular) { 210 sibling = parent.item(0); 211 } 212 213 return sibling; 214 215 }, 216 217 218 /** 219 * @method previous 220 * @description Returns the Widget's previous sibling. 221 * @param {Boolean} circular Boolean indicating if the parent's last child 222 * should be returned if the child has no previous sibling. 223 * @return {Widget} Widget instance. 224 */ 225 previous: function (circular) { 226 227 var parent = this.get("parent"), 228 index = this.get("index"), 229 sibling; 230 231 if (parent && index > 0) { 232 sibling = parent.item([(index-1)]); 233 } 234 235 if (!sibling && circular) { 236 sibling = parent.item((parent.size() - 1)); 237 } 238 239 return sibling; 240 241 }, 242 243 244 // Override of Y.WidgetParent.remove() 245 // Sugar implementation allowing a child to remove itself from its parent. 246 remove: function (index) { 247 248 var parent, 249 removed; 250 251 if (Lang.isNumber(index)) { 252 removed = Y.WidgetParent.prototype.remove.apply(this, arguments); 253 } 254 else { 255 256 parent = this.get("parent"); 257 258 if (parent) { 259 removed = parent.remove(this.get("index")); 260 } 261 262 } 263 264 return removed; 265 266 }, 267 268 269 /** 270 * @method isRoot 271 * @description Determines if the Widget is the root Widget in the 272 * object hierarchy. 273 * @return {Boolean} Boolean indicating if Widget is the root Widget in the 274 * object hierarchy. 275 */ 276 isRoot: function () { 277 return (this == this.get("root")); 278 }, 279 280 281 /** 282 * @method ancestor 283 * @description Returns the Widget instance at the specified depth. 284 * @param {number} depth Number representing the depth of the ancestor. 285 * @return {Widget} Widget instance. 286 */ 287 ancestor: function (depth) { 288 289 var root = this.get("root"), 290 parent; 291 292 if (this.get("depth") > depth) { 293 294 parent = this.get("parent"); 295 296 while (parent != root && parent.get("depth") > depth) { 297 parent = parent.get("parent"); 298 } 299 300 } 301 302 return parent; 303 304 }, 305 306 307 /** 308 * Updates the UI to reflect the <code>selected</code> attribute value. 309 * 310 * @method _uiSetChildSelected 311 * @protected 312 * @param {number} selected The selected value to be reflected in the UI. 313 */ 314 _uiSetChildSelected: function (selected) { 315 316 var box = this.get("boundingBox"), 317 sClassName = this.getClassName("selected"); 318 319 if (selected === 0) { 320 box.removeClass(sClassName); 321 } 322 else { 323 box.addClass(sClassName); 324 } 325 326 }, 327 328 329 /** 330 * Default attribute change listener for the <code>selected</code> 331 * attribute, responsible for updating the UI, in response to 332 * attribute changes. 333 * 334 * @method _afterChildSelectedChange 335 * @protected 336 * @param {EventFacade} event The event facade for the attribute change. 337 */ 338 _afterChildSelectedChange: function (event) { 339 this._uiSetChildSelected(event.newVal); 340 }, 341 342 343 /** 344 * Synchronizes the UI to match the WidgetChild state. 345 * <p> 346 * This method is invoked after bindUI is invoked for the Widget class 347 * using YUI's aop infrastructure. 348 * </p> 349 * 350 * @method _syncUIChild 351 * @protected 352 */ 353 _syncUIChild: function () { 354 this._uiSetChildSelected(this.get("selected")); 355 }, 356 357 358 /** 359 * Binds event listeners responsible for updating the UI state in response 360 * to WidgetChild related state changes. 361 * <p> 362 * This method is invoked after bindUI is invoked for the Widget class
363 * using YUI's aop infrastructure. 364 * </p> 365 * @method _bindUIChild 366 * @protected 367 */ 368 _bindUIChild: function () { 369 this.after("selectedChange", this._afterChildSelectedChange); 370 } 371 372}; 373 374Y.WidgetChild = Child; 375 376 377}, 'patched-v3.18.1', {"requires": ["base-build", "widget"]}); 378 379YUI.add('widget-position-align', function (Y, NAME) { 380 381/** 382Provides extended/advanced XY positioning support for Widgets, through an 383extension. 384 385It builds on top of the `widget-position` module, to provide alignment and 386centering support. Future releases aim to add constrained and fixed positioning 387support. 388 389@module widget-position-align 390**/ 391var Lang = Y.Lang, 392 393 ALIGN = 'align', 394 ALIGN_ON = 'alignOn', 395 396 VISIBLE = 'visible', 397 BOUNDING_BOX = 'boundingBox', 398 399 OFFSET_WIDTH = 'offsetWidth', 400 OFFSET_HEIGHT = 'offsetHeight', 401 REGION = 'region', 402 VIEWPORT_REGION = 'viewportRegion'; 403 404/** 405Widget extension, which can be used to add extended XY positioning support to 406the base Widget class, through the `Base.create` method. 407 408**Note:** This extension requires that the `WidgetPosition` extension be added 409to the Widget (before `WidgetPositionAlign`, if part of the same extension list 410passed to `Base.build`). 411 412@class WidgetPositionAlign 413@param {Object} config User configuration object. 414@constructor 415**/ 416function PositionAlign (config) {} 417 418PositionAlign.ATTRS = { 419 420 /** 421 The alignment configuration for this widget. 422 423 The `align` attribute is used to align a reference point on the widget, with 424 the reference point on another `Node`, or the viewport. The object which 425 `align` expects has the following properties: 426 427 * __`node`__: The `Node` to which the widget is to be aligned. If set to 428 `null`, or not provided, the widget is aligned to the viewport. 429 430 * __`points`__: A two element Array, defining the two points on the widget 431 and `Node`/viewport which are to be aligned. The first element is the 432 point on the widget, and the second element is the point on the 433 `Node`/viewport. Supported alignment points are defined as static 434 properties on `WidgetPositionAlign`. 435 436 @example Aligns the top-right corner of the widget with the top-left corner 437 of the viewport: 438 439 myWidget.set('align', { 440 points: [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.TL] 441 }); 442 443 @attribute align 444 @type Object 445 @default null 446 **/ 447 align: { 448 value: null 449 }, 450 451 /** 452 A convenience Attribute, which can be used as a shortcut for the `align` 453 Attribute. 454 455 If set to `true`, the widget is centered in the viewport. If set to a `Node` 456 reference or valid selector String, the widget will be centered within the 457 `Node`. If set to `false`, no center positioning is applied. 458 459 @attribute centered 460 @type Boolean|Node 461 @default false 462 **/ 463 centered: { 464 setter : '_setAlignCenter', 465 lazyAdd:false, 466 value :false 467 }, 468 469 /** 470 An Array of Objects corresponding to the `Node`s and events that will cause 471 the alignment of this widget to be synced to the DOM. 472 473 The `alignOn` Attribute is expected to be an Array of Objects with the 474 following properties: 475 476 * __`eventName`__: The String event name to listen for. 477 478 * __`node`__: The optional `Node` that will fire the event, it can be a 479 `Node` reference or a selector String. This will default to the widget's 480 `boundingBox`. 481 482 @example Sync this widget's alignment on window resize: 483 484 myWidget.set('alignOn', [ 485 { 486 node : Y.one('win'), 487 eventName: 'resize' 488 } 489 ]); 490 491 @attribute alignOn 492 @type Array 493 @default [] 494 **/ 495 alignOn: { 496 value : [], 497 validator: Y.Lang.isArray 498 } 499}; 500 501/** 502Constant used to specify the top-left corner for alignment 503 504@property TL 505@type String 506@value 'tl' 507@static 508**/ 509PositionAlign.TL = 'tl'; 510 511/** 512Constant used to specify the top-right corner for alignment 513 514@property TR
515@type String 516@value 'tr' 517@static 518**/ 519PositionAlign.TR = 'tr'; 520 521/** 522Constant used to specify the bottom-left corner for alignment 523 524@property BL 525@type String 526@value 'bl' 527@static 528**/ 529PositionAlign.BL = 'bl'; 530 531/** 532Constant used to specify the bottom-right corner for alignment 533 534@property BR 535@type String 536@value 'br' 537@static 538**/ 539PositionAlign.BR = 'br'; 540 541/** 542Constant used to specify the top edge-center point for alignment 543 544@property TC 545@type String 546@value 'tc' 547@static 548**/ 549PositionAlign.TC = 'tc'; 550 551/** 552Constant used to specify the right edge, center point for alignment 553 554@property RC 555@type String 556@value 'rc' 557@static 558**/ 559PositionAlign.RC = 'rc'; 560 561/** 562Constant used to specify the bottom edge, center point for alignment 563 564@property BC 565@type String 566@value 'bc' 567@static 568**/ 569PositionAlign.BC = 'bc'; 570 571/** 572Constant used to specify the left edge, center point for alignment 573 574@property LC 575@type String 576@value 'lc' 577@static 578**/ 579PositionAlign.LC = 'lc'; 580 581/** 582Constant used to specify the center of widget/node/viewport for alignment 583 584@property CC 585@type String 586@value 'cc' 587@static 588*/ 589PositionAlign.CC = 'cc'; 590 591PositionAlign.prototype = { 592 // -- Protected Properties ------------------------------------------------- 593 594 595 initializer : function() { 596 if (!this._posNode) { 597 Y.error('WidgetPosition needs to be added to the Widget, ' + 598 'before WidgetPositionAlign is added'); 599 } 600 601 Y.after(this._bindUIPosAlign, this, 'bindUI'); 602 Y.after(this._syncUIPosAlign, this, 'syncUI'); 603 }, 604 605 /** 606 Holds the alignment-syncing event handles. 607 608 @property _posAlignUIHandles 609 @type Array 610 @default null 611 @protected 612 **/ 613 _posAlignUIHandles: null, 614 615 // -- Lifecycle Methods ---------------------------------------------------- 616 617 initializer: function() { 618 if ( ! this._posNode) { 619 Y.error('WidgetPosition needs to be added to the Widget, ' + 620 'before WidgetPositionAlign is added'); 621 } 622 623 Y.after(this._bindUIPosAlign, this, 'bindUI'); 624 Y.after(this._syncUIPosAlign, this, 'syncUI'); 625 }, 626 627 destructor: function () { 628 this._detachPosAlignUIHandles(); 629 }, 630 631 /** 632 Bind event listeners responsible for updating the UI state in response to 633 the widget's position-align related state changes. 634 635 This method is invoked after `bindUI` has been invoked for the `Widget` 636 class using the AOP infrastructure. 637 638 @method _bindUIPosAlign 639 @protected 640 **/ 641 _bindUIPosAlign: function () { 642 this.after('alignChange', this._afterAlignChange); 643 this.after('alignOnChange', this._afterAlignOnChange); 644 this.after('visibleChange', this._syncUIPosAlign); 645 }, 646 647 /** 648 Synchronizes the current `align` Attribute value to the DOM. 649 650 This method is invoked after `syncUI` has been invoked for the `Widget` 651 class using the AOP infrastructure. 652 653 @method _syncUIPosAlign 654 @protected 655 **/ 656 _syncUIPosAlign: function () { 657 var align = this.get(ALIGN); 658 659 this._uiSetVisiblePosAlign(this.get(VISIBLE)); 660 661 if (align) { 662 this._uiSetAlign(align.node, align.points); 663 } 664 }, 665 666 // -- Public Methods ------------------------------------------------------- 667 668 /** 669 Aligns this widget to the provided `Node` (or viewport) using the provided 670 points. This method can be invoked with no arguments which will cause the 671 widget's current `align` Attribute value to be synced to the DOM. 672 673 @example Aligning to the top-left corner of the `<body>`: 674 675 myWidget.align('body', 676 [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.TR]); 677 678 @method align 679 @param {Node|String|null} [node] A reference (or selector String) for the 680 `Node` which with the widget is to be aligned. If null is passed in, the 681 widget will be aligned with the viewport. 682 @param {Array[2]} [points] A two item array specifying the points on the 683 widget and `Node`/viewport which will to be aligned. The first entry is 684 the point on the widget, and the second entry is the point on the 685 `Node`/viewport. Valid point references are defined as static constants on 686 the `WidgetPositionAlign` extension. 687 @chainable 688 **/ 689 align: function (node, points) { 690 if (arguments.length) { 691 // Set the `align` Attribute. 692 this.set(ALIGN, {
693 node : node, 694 points: points 695 }); 696 } else { 697 // Sync the current `align` Attribute value to the DOM. 698 this._syncUIPosAlign(); 699 } 700 701 return this; 702 }, 703 704 /** 705 Centers the widget in the viewport, or if a `Node` is passed in, it will 706 be centered to that `Node`. 707 708 @method centered 709 @param {Node|String} [node] A `Node` reference or selector String defining 710 the `Node` which the widget should be centered. If a `Node` is not passed 711 in, then the widget will be centered to the viewport. 712 @chainable 713 **/ 714 centered: function (node) { 715 return this.align(node, [PositionAlign.CC, PositionAlign.CC]); 716 }, 717 718 // -- Protected Methods ---------------------------------------------------- 719 720 /** 721 Returns coordinates realative to the passed `Node` alignment. 722 723 @method _getAlignToXY 724 @param {Node} 'Node' The node to align to. 725 @param {Array} [point] The node alignment points. 726 @param {Number} 'Node' x coordinate. 727 @param {Number} 'Node' y coordinate. 728 @return {Array} the coordinates. 729 @private 730 **/ 731 _getAlignToXY: function (node, point, x, y) { 732 var xy; 733 734 switch (point) { 735 case PositionAlign.TL: 736 xy = [x, y]; 737 break; 738 739 case PositionAlign.TR: 740 xy = [ 741 x - node.get(OFFSET_WIDTH), 742 y 743 ]; 744 break; 745 746 case PositionAlign.BL: 747 xy = [ 748 x, 749 y - node.get(OFFSET_HEIGHT) 750 ]; 751 break; 752 753 case PositionAlign.BR: 754 xy = [ 755 x - node.get(OFFSET_WIDTH), 756 y - node.get(OFFSET_HEIGHT) 757 ]; 758 break; 759 760 case PositionAlign.TC: 761 xy = [ 762 x - (node.get(OFFSET_WIDTH) / 2), 763 y 764 ]; 765 break; 766 767 case PositionAlign.BC: 768 xy = [ 769 x - (node.get(OFFSET_WIDTH) / 2), 770 y - node.get(OFFSET_HEIGHT) 771 ]; 772 break; 773 774 case PositionAlign.LC: 775 xy = [ 776 x, 777 y - (node.get(OFFSET_HEIGHT) / 2) 778 ]; 779 break; 780 781 case PositionAlign.RC: 782 xy = [ 783 x - node.get(OFFSET_WIDTH), 784 y - (node.get(OFFSET_HEIGHT) / 2) 785 ]; 786 break; 787 788 case PositionAlign.CC: 789 xy = [ 790 x - (node.get(OFFSET_WIDTH) / 2), 791 y - (node.get(OFFSET_HEIGHT) / 2) 792 ]; 793 break; 794 795 default: 796 break; 797 798 } 799 800 return xy; 801 }, 802 803 /** 804 Returns `Widget` alignment coordinates realative to the given `Node`. 805 806 @method _getAlignedXY 807 @param {Node|String|null} [node] The node to align to, or null to indicate 808 the viewport. 809 @param {Array} points The alignment points. 810 @return {Array} the coordinates. 811 @protected 812 **/ 813 _getAlignedXY: function (node, points) { 814 if ( ! Lang.isArray(points) || points.length !== 2) { 815 Y.error('align: Invalid Points Arguments'); 816 return; 817 } 818 819 var nodeRegion = this._getRegion(node), nodePoint, xy; 820 821 if ( ! nodeRegion) { 822 // No-op, nothing to align to. 823 return; 824 } 825 826 nodePoint = points[1]; 827 828 // TODO: Optimize KWeight - Would lookup table help? 829 switch (nodePoint) { 830 case PositionAlign.TL: 831 xy = [nodeRegion.left, nodeRegion.top]; 832 break; 833 834 case PositionAlign.TR: 835 xy = [nodeRegion.right, nodeRegion.top]; 836 break; 837 838 case PositionAlign.BL: 839 xy = [nodeRegion.left, nodeRegion.bottom]; 840 break; 841 842 case PositionAlign.BR: 843 xy = [nodeRegion.right, nodeRegion.bottom]; 844 break; 845 846 case PositionAlign.TC: 847 xy = [ 848 nodeRegion.left + Math.floor(nodeRegion.width / 2), 849 nodeRegion.top 850 ]; 851 break; 852 853 case PositionAlign.BC: 854 xy = [ 855 nodeRegion.left + Math.floor(nodeRegion.width / 2), 856 nodeRegion.bottom 857 ]; 858 break; 859 860 case PositionAlign.LC: 861 xy = [ 862 nodeRegion.left, 863 nodeRegion.top + Math.floor(nodeRegion.height / 2) 864 ]; 865 break; 866 867 case PositionAlign.RC: 868 xy = [ 869 nodeRegion.right, 870 nodeRegion.top + Math.floor(nodeRegion.height / 2) 871 ]; 872 break; 873 874 case PositionAlign.CC: 875 xy = [ 876 nodeRegion.left + Math.floor(nodeRegion.width / 2), 877 nodeRegion.top + Math.floor(nodeRegion.height / 2) 878 ]; 879 break; 880 881 default: 882 break; 883 884 } 885 886 return this._getAlignToXY(this._posNode, points[0], xy[0], xy[1]); 887 }, 888 889 /** 890 Default setter for `center` Attribute changes. Sets up the appropriate 891 value, and passes it through the to the align attribute. 892 893 @method _setAlignCenter 894 @param {Boolean|Node} val The Attribute value being set. 895 @return {Boolean|Node} the value passed in. 896 @protected 897 **/ 898 _setAlignCenter: function (val) { 899 if (val) { 900 this.set(ALIGN, { 901 node : val === true ? null : val, 902 points: [PositionAlign.CC, PositionAlign.CC] 903 }); 904 } 905 906 return val; 907 }, 908 909 /** 910 Updates the UI to reflect the `align` value passed in. 911 912 **Note:** See the `align` Attribute documentation, for the Object structure 913 expected. 914 915 @method _uiSetAlign 916 @param {Node|String|null} [node] The node to align to, or null to indicate 917 the viewport. 918 @param {Array} points The alignment points. 919 @protected 920 **/ 921 _uiSetAlign: function (node, points) { 922 var xy = this._getAlignedXY(node, points); 923 924 if (xy) { 925 this._doAlign(xy); 926 } 927 }, 928 929 /** 930 Attaches or detaches alignment-syncing event handlers based on the widget's 931 `visible` Attribute state. 932 933 @method _uiSetVisiblePosAlign 934 @param {Boolean} visible The current value of the widget's `visible` 935 Attribute. 936 @protected 937 **/ 938 _uiSetVisiblePosAlign: function (visible) { 939 if (visible) { 940 this._attachPosAlignUIHandles(); 941 } else { 942 this._detachPosAlignUIHandles(); 943 } 944 }, 945 946 /** 947 Attaches the alignment-syncing event handlers. 948 949 @method _attachPosAlignUIHandles 950 @protected 951 **/ 952 _attachPosAlignUIHandles: function () { 953 if (this._posAlignUIHandles) { 954 // No-op if we have already setup the event handlers. 955 return; 956 } 957 958 var bb = this.get(BOUNDING_BOX), 959 syncAlign = Y.bind(this._syncUIPosAlign, this), 960 handles = []; 961 962 Y.Array.each(this.get(ALIGN_ON), function (o) { 963 var event = o.eventName, 964 node = Y.one(o.node) || bb; 965 966 if (event) { 967 handles.push(node.on(event, syncAlign)); 968 } 969 }); 970 971 this._posAlignUIHandles = handles; 972 }, 973 974 /** 975 Detaches the alignment-syncing event handlers. 976 977 @method _detachPosAlignUIHandles 978 @protected 979 **/ 980 _detachPosAlignUIHandles: function () { 981 var handles = this._posAlignUIHandles; 982 if (handles) { 983 new Y.EventHandle(handles).detach(); 984 this._posAlignUIHandles = null; 985 } 986 }, 987 988 // -- Private Methods ------------------------------------------------------ 989 990 /** 991 Helper method, used to align the given point on the widget, with the XY page 992 coordinates provided. 993 994 @method _doAlign 995 @param {Array} xy XY page coordinates to align to. 996 @private 997 **/ 998 _doAlign: function(xy) { 999 if (xy) { 1000 this.move(xy); 1001 } 1002 }, 1003 1004 /** 1005 Returns the region of the passed-in `Node`, or the viewport region if 1006 calling with passing in a `Node`. 1007 1008 @method _getRegion 1009 @param {Node} [node] The node to get the region of. 1010 @return {Object} The node's region. 1011 @private 1012 **/ 1013 _getRegion: function (node) { 1014 var nodeRegion; 1015 1016 if ( ! node) { 1017 nodeRegion = this._posNode.get(VIEWPORT_REGION); 1018 } else { 1019 node = Y.Node.one(node); 1020 if (node) { 1021 nodeRegion = node.get(REGION); 1022 } 1023 } 1024 1025 return nodeRegion; 1026 }, 1027 1028 // -- Protected Event Handlers --------------------------------------------- 1029 1030 /** 1031 Handles `alignChange` events by updating the UI in response to `align` 1032 Attribute changes. 1033 1034 @method _afterAlignChange 1035 @param {EventFacade} e 1036 @protected 1037 **/ 1038 _afterAlignChange: function (e) { 1039 var align = e.newVal; 1040 if (align) { 1041 this._uiSetAlign(align.node, align.points); 1042 } 1043 }, 1044 1045 /** 1046 Handles `alignOnChange` events by updating the alignment-syncing event 1047 handlers. 1048 1049 @method _afterAlignOnChange 1050 @param {EventFacade} e 1051 @protected 1052 **/ 1053 _afterAlignOnChange: function(e) { 1054 this._detachPosAlignUIHandles(); 1055 1056 if (this.get(VISIBLE)) { 1057 this._attachPosAlignUIHandles(); 1058 } 1059 } 1060}; 1061 1062Y.WidgetPositionAlign = PositionAlign; 1063 1064 1065}, 'patched-v3.18.1', {"requires": ["widget-position"]}); 1066 1067YUI.add('widget-position-constrain', function (Y, NAME) { 1068 1069/** 1070 * Provides constrained xy positioning support for Widgets, through an extension. 1071 * 1072 * It builds on top of the widget-position module, to provide constrained positioning support. 1073 * 1074 * @module widget-position-constrain 1075 */ 1076var CONSTRAIN = "constrain", 1077 CONSTRAIN_XYCHANGE = "constrain|xyChange", 1078 CONSTRAIN_CHANGE = "constrainChange", 1079 1080 PREVENT_OVERLAP = "preventOverlap", 1081 ALIGN = "align", 1082 1083 EMPTY_STR = "", 1084 1085 BINDUI = "bindUI", 1086 1087 XY = "xy", 1088 X_COORD = "x", 1089 Y_COORD = "y", 1090 1091 Node = Y.Node, 1092 1093 VIEWPORT_REGION = "viewportRegion", 1094 REGION = "region", 1095 1096 PREVENT_OVERLAP_MAP; 1097 1098/** 1099 * A widget extension, which can be used to add constrained xy positioning support to the base Widget class, 1100 * through the <a href="Base.html#method_build">Base.build</a> method. This extension requires that 1101 * the WidgetPosition extension be added to the Widget (before WidgetPositionConstrain, if part of the same 1102 * extension list passed to Base.build). 1103 * 1104 * @class WidgetPositionConstrain 1105 * @param {Object} User configuration object 1106 */ 1107function PositionConstrain(config) {} 1108 1109/** 1110 * Static property used to define the default attribute 1111 * configuration introduced by WidgetPositionConstrain. 1112 * 1113 * @property ATTRS 1114 * @type Object 1115 * @static 1116 */ 1117PositionConstrain.ATTRS = { 1118 1119 /** 1120 * @attribute constrain 1121 * @type boolean | Node 1122 * @default null
1123 * @description The node to constrain the widget's bounding box to, when setting xy. Can also be 1124 * set to true, to constrain to the viewport. 1125 */ 1126 constrain : { 1127 value: null, 1128 setter: "_setConstrain" 1129 }, 1130 1131 /** 1132 * @attribute preventOverlap 1133 * @type boolean 1134 * @description If set to true, and WidgetPositionAlign is also added to the Widget, 1135 * constrained positioning will attempt to prevent the widget's bounding box from overlapping 1136 * the element to which it has been aligned, by flipping the orientation of the alignment 1137 * for corner based alignments 1138 */ 1139 preventOverlap : { 1140 value:false 1141 } 1142}; 1143 1144/** 1145 * @property _PREVENT_OVERLAP 1146 * @static 1147 * @protected 1148 * @type Object 1149 * @description The set of positions for which to prevent 1150 * overlap. 1151 */ 1152PREVENT_OVERLAP_MAP = PositionConstrain._PREVENT_OVERLAP = { 1153 x: { 1154 "tltr": 1, 1155 "blbr": 1, 1156 "brbl": 1, 1157 "trtl": 1 1158 }, 1159 y : { 1160 "trbr": 1, 1161 "tlbl": 1, 1162 "bltl": 1, 1163 "brtr": 1 1164 } 1165}; 1166 1167PositionConstrain.prototype = { 1168 1169 initializer : function() { 1170 if (!this._posNode) { 1171 Y.error("WidgetPosition needs to be added to the Widget, before WidgetPositionConstrain is added"); 1172 } 1173 Y.after(this._bindUIPosConstrained, this, BINDUI); 1174 }, 1175 1176 /** 1177 * Calculates the constrained positions for the XY positions provided, using 1178 * the provided node argument is passed in. If no node value is passed in, the value of 1179 * the "constrain" attribute is used. 1180 * 1181 * @method getConstrainedXY 1182 * @param {Array} xy The xy values to constrain 1183 * @param {Node | boolean} node Optional. The node to constrain to, or true for the viewport 1184 * @return {Array} The constrained xy values 1185 */ 1186 getConstrainedXY : function(xy, node) { 1187 node = node || this.get(CONSTRAIN); 1188 1189 var constrainingRegion = this._getRegion((node === true) ? null : node), 1190 nodeRegion = this._posNode.get(REGION); 1191 1192 return [ 1193 this._constrain(xy[0], X_COORD, nodeRegion, constrainingRegion), 1194 this._constrain(xy[1], Y_COORD, nodeRegion, constrainingRegion) 1195 ]; 1196 }, 1197 1198 /** 1199 * Constrains the widget's bounding box to a node (or the viewport). If xy or node are not 1200 * passed in, the current position and the value of "constrain" will be used respectively. 1201 * 1202 * The widget's position will be changed to the constrained position. 1203 * 1204 * @method constrain 1205 * @param {Array} xy Optional. The xy values to constrain 1206 * @param {Node | boolean} node Optional. The node to constrain to, or true for the viewport 1207 */ 1208 constrain : function(xy, node) { 1209 var currentXY, 1210 constrainedXY, 1211 constraint = node || this.get(CONSTRAIN); 1212 1213 if (constraint) { 1214 currentXY = xy || this.get(XY); 1215 constrainedXY = this.getConstrainedXY(currentXY, constraint); 1216 1217 if (constrainedXY[0] !== currentXY[0] || constrainedXY[1] !== currentXY[1]) { 1218 this.set(XY, constrainedXY, { constrained:true }); 1219 } 1220 } 1221 }, 1222 1223 /** 1224 * The setter implementation for the "constrain" attribute. 1225 * 1226 * @method _setConstrain 1227 * @protected 1228 * @param {Node | boolean} val The attribute value 1229 */ 1230 _setConstrain : function(val) { 1231 return (val === true) ? val : Node.one(val); 1232 }, 1233 1234 /** 1235 * The method which performs the actual constrain calculations for a given axis ("x" or "y") based 1236 * on the regions provided. 1237 * 1238 * @method _constrain 1239 * @protected 1240 * 1241 * @param {Number} val The value to constrain 1242 * @param {String} axis The axis to use for constrainment 1243 * @param {Region} nodeRegion The region of the node to constrain 1244 * @param {Region} constrainingRegion The region of the node (or viewport) to constrain to 1245 * 1246 * @return {Number} The constrained value 1247 */ 1248 _constrain: function(val, axis, nodeRegion, constrainingRegion) { 1249 if (constrainingRegion) { 1250 1251 if (this.get(PREVENT_OVERLAP)) { 1252 val = this._preventOverlap(val, axis, nodeRegion, constrainingRegion); 1253 } 1254 1255 var x = (axis == X_COORD), 1256 1257 regionSize = (x) ? constrainingRegion.width : constrainingRegion.height, 1258 nodeSize = (x) ? nodeRegion.width : nodeRegion.height, 1259 minConstraint = (x) ? constrainingRegion.left : constrainingRegion.top, 1260 maxConstraint = (x) ? constrainingRegion.right - nodeSize : constrainingRegion.bottom - nodeSize; 1261 1262 if (val < minConstraint || val > maxConstraint) { 1263 if (nodeSize < regionSize) { 1264 if (val < minConstraint) { 1265 val = minConstraint; 1266 } else if (val > maxConstraint) { 1267 val = maxConstraint; 1268 } 1269 } else { 1270 val = minConstraint; 1271 } 1272 } 1273 } 1274 1275 return val; 1276 }, 1277 1278 /** 1279 * The method which performs the preventOverlap calculations for a given axis ("x" or "y") based 1280 * on the value and regions provided. 1281 * 1282 * @method _preventOverlap 1283 * @protected 1284 * 1285 * @param {Number} val The value being constrain 1286 * @param {String} axis The axis to being constrained 1287 * @param {Region} nodeRegion The region of the node being constrained 1288 * @param {Region} constrainingRegion The region of the node (or viewport) we need to constrain to 1289 * 1290 * @return {Number} The constrained value 1291 */ 1292 _preventOverlap : function(val, axis, nodeRegion, constrainingRegion) { 1293 1294 var align = this.get(ALIGN), 1295 x = (axis === X_COORD), 1296 nodeSize, 1297 alignRegion, 1298 nearEdge, 1299 farEdge, 1300 spaceOnNearSide, 1301 spaceOnFarSide; 1302 1303 if (align && align.points && PREVENT_OVERLAP_MAP[axis][align.points.join(EMPTY_STR)]) { 1304 1305 alignRegion = this._getRegion(align.node); 1306 1307 if (alignRegion) { 1308 nodeSize = (x) ? nodeRegion.width : nodeRegion.height; 1309 nearEdge = (x) ? alignRegion.left : alignRegion.top; 1310 farEdge = (x) ? alignRegion.right : alignRegion.bottom; 1311 spaceOnNearSide = (x) ? alignRegion.left - constrainingRegion.left : alignRegion.top - constrainingRegion.top; 1312 spaceOnFarSide = (x) ? constrainingRegion.right - alignRegion.right : constrainingRegion.bottom - alignRegion.bottom; 1313 } 1314 1315 if (val > nearEdge) { 1316 if (spaceOnFarSide < nodeSize && spaceOnNearSide > nodeSize) { 1317 val = nearEdge - nodeSize; 1318 } 1319 } else { 1320 if (spaceOnNearSide < nodeSize && spaceOnFarSide > nodeSize) { 1321 val = farEdge; 1322 } 1323 } 1324 } 1325 1326 return val; 1327 }, 1328 1329 /** 1330 * Binds event listeners responsible for updating the UI state in response to 1331 * Widget constrained positioning related state changes. 1332 * <p> 1333 * This method is invoked after bindUI is invoked for the Widget class
1334 * using YUI's aop infrastructure. 1335 * </p> 1336 * 1337 * @method _bindUIPosConstrained 1338 * @protected 1339 */ 1340 _bindUIPosConstrained : function() { 1341 this.after(CONSTRAIN_CHANGE, this._afterConstrainChange); 1342 this._enableConstraints(this.get(CONSTRAIN)); 1343 }, 1344 1345 /** 1346 * After change listener for the "constrain" attribute, responsible 1347 * for updating the UI, in response to attribute changes. 1348 * 1349 * @method _afterConstrainChange 1350 * @protected 1351 * @param {EventFacade} e The event facade 1352 */ 1353 _afterConstrainChange : function(e) { 1354 this._enableConstraints(e.newVal); 1355 }, 1356 1357 /** 1358 * Updates the UI if enabling constraints, and sets up the xyChange event listeners 1359 * to constrain whenever the widget is moved. Disabling constraints removes the listeners. 1360 * 1361 * @method _enableConstraints 1362 * @private 1363 * @param {boolean} enable Enable or disable constraints 1364 */ 1365 _enableConstraints : function(enable) { 1366 if (enable) { 1367 this.constrain(); 1368 this._cxyHandle = this._cxyHandle || this.on(CONSTRAIN_XYCHANGE, this._constrainOnXYChange); 1369 } else if (this._cxyHandle) { 1370 this._cxyHandle.detach(); 1371 this._cxyHandle = null; 1372 } 1373 }, 1374 1375 /** 1376 * The on change listener for the "xy" attribute. Modifies the event facade'
1376s 1377 * newVal property with the constrained XY value. 1378 * 1379 * @method _constrainOnXYChange 1380 * @protected 1381 * @param {EventFacade} e The event facade for the attribute change 1382 */ 1383 _constrainOnXYChange : function(e) { 1384 if (!e.constrained) { 1385 e.newVal = this.getConstrainedXY(e.newVal); 1386 } 1387 }, 1388 1389 /** 1390 * Utility method to normalize region retrieval from a node instance, 1391 * or the viewport, if no node is provided. 1392 * 1393 * @method _getRegion 1394 * @private 1395 * @param {Node} node Optional. 1396 */ 1397 _getRegion : function(node) { 1398 var region; 1399 if (!node) { 1400 region = this._posNode.get(VIEWPORT_REGION); 1401 } else { 1402 node = Node.one(node); 1403 if (node) { 1404 region = node.get(REGION); 1405 } 1406 } 1407 return region; 1408 } 1409}; 1410 1411Y.WidgetPositionConstrain = PositionConstrain; 1412 1413 1414}, 'patched-v3.18.1', {"requires": ["widget-position"]}); 1415 1416YUI.add('widget-position', function (Y, NAME) { 1417 1418/** 1419 * Provides basic XY positioning support for Widgets, though an extension 1420 * 1421 * @module widget-position 1422 */ 1423 var Lang = Y.Lang, 1424 Widget = Y.Widget, 1425 1426 XY_COORD = "xy", 1427 1428 POSITION = "position", 1429 POSITIONED = "positioned", 1430 BOUNDING_BOX = "boundingBox", 1431 RELATIVE = "relative", 1432 1433 RENDERUI = "renderUI", 1434 BINDUI = "bindUI", 1435 SYNCUI = "syncUI", 1436 1437 UI = Widget.UI_SRC, 1438 1439 XYChange = "xyChange"; 1440 1441 /** 1442 * Widget extension, which can be used to add positioning support to the base Widget class, 1443 * through the <a href="Base.html#method_build">Base.build</a> method. 1444 * 1445 * @class WidgetPosition 1446 * @param {Object} config User configuration object 1447 */ 1448 function Position(config) { 1449 } 1450 1451 /** 1452 * Static property used to define the default attribute 1453 * configuration introduced by WidgetPosition. 1454 * 1455 * @property ATTRS 1456 * @static 1457 * @type Object 1458 */ 1459 Position.ATTRS = { 1460 1461 /** 1462 * @attribute x 1463 * @type number 1464 * @default 0 1465 * 1466 * @description Page X co-ordinate for the widget. This attribute acts as a facade for the 1467 * xy attribute. Changes in position can be monitored by listening for xyChange events. 1468 */ 1469 x: { 1470 setter: function(val) { 1471 this._setX(val); 1472 }, 1473 getter: function() { 1474 return this._getX(); 1475 }, 1476 lazyAdd:false 1477 }, 1478 1479 /** 1480 * @attribute y 1481 * @type number 1482 * @default 0 1483 * 1484 * @description Page Y co-ordinate for the widget. This attribute acts as a facade for the 1485 * xy attribute. Changes in position can be monitored by listening for xyChange events. 1486 */ 1487 y: { 1488 setter: function(val) { 1489 this._setY(val); 1490 }, 1491 getter: function() { 1492 return this._getY(); 1493 }, 1494 lazyAdd: false 1495 }, 1496 1497 /** 1498 * @attribute xy 1499 * @type Array 1500 * @default [0,0] 1501 * 1502 * @description Page XY co-ordinate pair for the widget. 1503 */ 1504 xy: { 1505 value:[0,0], 1506 validator: function(val) { 1507 return this._validateXY(val); 1508 } 1509 } 1510 }; 1511 1512 /** 1513 * Default class used to mark the boundingBox of a positioned widget. 1514 * 1515 * @property POSITIONED_CLASS_NAME
1516 * @type String 1517 * @default "yui-widget-positioned" 1518 * @static 1519 */ 1520 Position.POSITIONED_CLASS_NAME = Widget.getClassName(POSITIONED); 1521 1522 Position.prototype = { 1523 1524 initializer : function() { 1525 this._posNode = this.get(BOUNDING_BOX); 1526 1527 // WIDGET METHOD OVERLAP 1528 Y.after(this._renderUIPosition, this, RENDERUI); 1529 Y.after(this._syncUIPosition, this, SYNCUI); 1530 Y.after(this._bindUIPosition, this, BINDUI); 1531 }, 1532 1533 /** 1534 * Creates/Initializes the DOM to support xy page positioning. 1535 * <p> 1536 * This method in invoked after renderUI is invoked for the Widget class 1537 * using YUI's aop infrastructure. 1538 * </p> 1539 * @method _renderUIPosition 1540 * @protected 1541 */ 1542 _renderUIPosition : function() { 1543 this._posNode.addClass(Position.POSITIONED_CLASS_NAME); 1544 }, 1545 1546 /** 1547 * Synchronizes the UI to match the Widgets xy page position state. 1548 * <p> 1549 * This method in invoked after syncUI is invoked for the Widget class 1550 * using YUI's aop infrastructure. 1551 * </p> 1552 * @method _syncUIPosition 1553 * @protected 1554 */ 1555 _syncUIPosition : function() { 1556 var posNode = this._posNode; 1557 if (posNode.getStyle(POSITION) === RELATIVE) { 1558 this.syncXY(); 1559 } 1560 this._uiSetXY(this.get(XY_COORD)); 1561 }, 1562 1563 /** 1564 * Binds event listeners responsible for updating the UI state in response to 1565 * Widget position related state changes. 1566 * <p> 1567 * This method in invoked after bindUI is invoked for the Widget class 1568 * using YUI's aop infrastructure. 1569 * </p> 1570 * @method _bindUIPosition 1571 * @protected 1572 */ 1573 _bindUIPosition :function() { 1574 this.after(XYChange, this._afterXYChange); 1575 }, 1576 1577 /** 1578 * Moves the Widget to the specified page xy co-ordinate position. 1579 * 1580 * @method move 1581 * 1582 * @param {Number|Number[]} x The new x position or [x, y] values passed 1583 * as an array to support simple pass through of Node.getXY results 1584 * @param {Number} [y] The new y position 1585 */ 1586 move: function () { 1587 var args = arguments, 1588 coord = (Lang.isArray(args[0])) ? args[0] : [args[0], args[1]]; 1589 this.set(XY_COORD, coord); 1590 }, 1591 1592 /** 1593 * Synchronizes the Panel's "xy", "x", and "y" properties with the 1594 * Widget's position in the DOM. 1595 * 1596 * @method syncXY 1597 */ 1598 syncXY : function () { 1599 this.set(XY_COORD, this._posNode.getXY(), {src: UI}); 1600 }, 1601 1602 /** 1603 * Default validator for the XY attribute 1604 * 1605 * @method _validateXY 1606 * @protected 1607 * @param {Array} val The XY page co-ordinate value which is being set. 1608 * @return {boolean} true if valid, false if not. 1609 */ 1610 _validateXY : function(val) { 1611 return (Lang.isArray(val) && Lang.isNumber(val[0]) && Lang.isNumber(val[1])); 1612 }, 1613 1614 /** 1615 * Default setter for the X attribute. The setter passes the X value through 1616 * to the XY attribute, which is the sole store for the XY state. 1617 * 1618 * @method _setX 1619 * @protected 1620 * @param {Number} val The X page co-ordinate value 1621 */ 1622 _setX : function(val) { 1623 this.set(XY_COORD, [val, this.get(XY_COORD)[1]]); 1624 }, 1625 1626 /** 1627 * Default setter for the Y attribute. The setter passes the Y value through 1628 * to the XY attribute, which is the sole store for the XY state. 1629 * 1630 * @method _setY 1631 * @protected 1632 * @param {Number} val The Y page co-ordinate value 1633 */ 1634 _setY : function(val) { 1635 this.set(XY_COORD, [this.get(XY_COORD)[0], val]); 1636 }, 1637 1638 /** 1639 * Default getter for the X attribute. The value is retrieved from 1640 * the XY attribute, which is the sole store for the XY state. 1641 * 1642 * @method _getX 1643 * @protected 1644 * @return {Number} The X page co-ordinate value 1645 */ 1646 _getX : function() { 1647 return this.get(XY_COORD)[0]; 1648 }, 1649 1650 /** 1651 * Default getter for the Y attribute. The value is retrieved from 1652 * the XY attribute, which is the sole store for the XY state. 1653 * 1654 * @method _getY 1655 * @protected 1656 * @return {Number} The Y page co-ordinate value 1657 */ 1658 _getY : function() { 1659 return this.get(XY_COORD)[1]; 1660 }, 1661 1662 /** 1663 * Default attribute change listener for the xy attribute, responsible 1664 * for updating the UI, in response to attribute changes. 1665 * 1666 * @method _afterXYChange 1667 * @protected 1668 * @param {EventFacade} e The event facade for the attribute change 1669 */ 1670 _afterXYChange : function(e) { 1671 if (e.src != UI) { 1672 this._uiSetXY(e.newVal); 1673 } 1674 }, 1675 1676 /** 1677 * Updates the UI to reflect the XY page co-ordinates passed in. 1678 * 1679 * @method _uiSetXY 1680 * @protected 1681 * @param {String} val The XY page co-ordinates value to be reflected in the UI 1682 */ 1683 _uiSetXY : function(val) { 1684 this._posNode.setXY(val); 1685 } 1686 }; 1687
1688 Y.WidgetPosition = Position; 1689 1690 1691}, 'patched-v3.18.1', {"requires": ["base-build", "node-screen", "widget"]}); 1692 1693YUI.add('widget-stack', function (Y, NAME) { 1694 1695/** 1696 * Provides stackable (z-index) support for Widgets through an extension. 1697 * 1698 * @module widget-stack 1699 */ 1700 var L = Y.Lang, 1701 UA = Y.UA, 1702 Node = Y.Node, 1703 Widget = Y.Widget, 1704 1705 ZINDEX = "zIndex", 1706 SHIM = "shim", 1707 VISIBLE = "visible", 1708 1709 BOUNDING_BOX = "boundingBox", 1710 1711 RENDER_UI = "renderUI", 1712 BIND_UI = "bindUI", 1713 SYNC_UI = "syncUI", 1714 1715 OFFSET_WIDTH = "offsetWidth", 1716 OFFSET_HEIGHT = "offsetHeight", 1717 PARENT_NODE = "parentNode", 1718 FIRST_CHILD = "firstChild", 1719 OWNER_DOCUMENT = "ownerDocument", 1720 1721 WIDTH = "width", 1722 HEIGHT = "height", 1723 PX = "px", 1724 1725 // HANDLE KEYS 1726 SHIM_DEFERRED = "shimdeferred", 1727 SHIM_RESIZE = "shimresize", 1728 1729 // Events 1730 VisibleChange = "visibleChange", 1731 WidthChange = "widthChange", 1732 HeightChange = "heightChange", 1733 ShimChange = "shimChange", 1734 ZIndexChange = "zIndexChange", 1735 ContentUpdate = "contentUpdate", 1736 1737 // CSS 1738 STACKED = "stacked"; 1739 1740 /** 1741 * Widget extension, which can be used to add stackable (z-index) support to the 1742 * base Widget class along with a shimming solution, through the 1743 * <a href="Base.html#method_build">Base.build</a> method. 1744 * 1745 * @class WidgetStack 1746 * @param {Object} User configuration object 1747 */ 1748 function Stack(config) {} 1749 1750 // Static Properties 1751 /** 1752 * Static property used to define the default attribute 1753 * configuration introduced by WidgetStack. 1754 * 1755 * @property ATTRS 1756 * @type Object 1757 * @static 1758 */ 1759 Stack.ATTRS = { 1760 /** 1761 * @attribute shim 1762 * @type boolean 1763 * @default false, for all browsers other than IE6, for which a shim is enabled by default. 1764 * 1765 * @description Boolean flag to indicate whether or not a shim should be added to the Widgets 1766 * boundingBox, to protect it from select box bleedthrough. 1767 */ 1768 shim: { 1769 value: (UA.ie == 6) 1770 }, 1771 1772 /** 1773 * @attribute zIndex 1774 * @type number 1775 * @default 0 1776 * @description The z-index to apply to the Widgets boundingBox. Non-numerical values for 1777 * zIndex will be converted to 0 1778 */ 1779 zIndex: { 1780 value : 0, 1781 setter: '_setZIndex' 1782 } 1783 }; 1784 1785 /** 1786 * The HTML parsing rules for the WidgetStack class. 1787 * 1788 * @property HTML_PARSER 1789 * @static 1790 * @type Object 1791 */ 1792 Stack.HTML_PARSER = { 1793 zIndex: function (srcNode) { 1794 return this._parseZIndex(srcNode); 1795 } 1796 }; 1797 1798 /** 1799 * Default class used to mark the shim element 1800 * 1801 * @property SHIM_CLASS_NAME
1802 * @type String 1803 * @static 1804 * @default "yui3-widget-shim" 1805 */ 1806 Stack.SHIM_CLASS_NAME = Widget.getClassName(SHIM); 1807 1808 /** 1809 * Default class used to mark the boundingBox of a stacked widget. 1810 * 1811 * @property STACKED_CLASS_NAME 1812 * @type String 1813 * @static 1814 * @default "yui3-widget-stacked" 1815 */ 1816 Stack.STACKED_CLASS_NAME = Widget.getClassName(STACKED); 1817 1818 /** 1819 * Default markup template used to generate the shim element. 1820 * 1821 * @property SHIM_TEMPLATE 1822 * @type String 1823 * @static 1824 */ 1825 Stack.SHIM_TEMPLATE = '<iframe class="' + Stack.SHIM_CLASS_NAME + '" frameborder="0" title="Widget Stacking Shim" src="javascript:false" tabindex="-1" role="presentation"></iframe>'; 1826 1827 Stack.prototype = { 1828 1829 initializer : function() { 1830 this._stackNode = this.get(BOUNDING_BOX); 1831 this._stackHandles = {}; 1832 1833 // WIDGET METHOD OVERLAP 1834 Y.after(this._renderUIStack, this, RENDER_UI); 1835 Y.after(this._syncUIStack, this, SYNC_UI); 1836 Y.after(this._bindUIStack, this, BIND_UI); 1837 }, 1838 1839 /** 1840 * Synchronizes the UI to match the Widgets stack state. This method in 1841 * invoked after syncUI is invoked for the Widget class using YUI's aop infrastructure. 1842 * 1843 * @method _syncUIStack 1844 * @protected 1845 */ 1846 _syncUIStack: function() { 1847 this._uiSetShim(this.get(SHIM)); 1848 this._uiSetZIndex(this.get(ZINDEX)); 1849 }, 1850 1851 /** 1852 * Binds event listeners responsible for updating the UI state in response to 1853 * Widget stack related state changes. 1854 * <p> 1855 * This method is invoked after bindUI is invoked for the Widget class 1856 * using YUI's aop infrastructure. 1857 * </p> 1858 * @method _bindUIStack 1859 * @protected 1860 */ 1861 _bindUIStack: function() { 1862 this.after(ShimChange, this._afterShimChange); 1863 this.after(ZIndexChange, this._afterZIndexChange); 1864 }, 1865 1866 /** 1867 * Creates/Initializes the DOM to support stackability. 1868 * <p> 1869 * This method in invoked after renderUI is invoked for the Widget class 1870 * using YUI's aop infrastructure. 1871 * </p> 1872 * @method _renderUIStack 1873 * @protected 1874 */ 1875 _renderUIStack: function() { 1876 this._stackNode.addClass(Stack.STACKED_CLASS_NAME); 1877 }, 1878 1879 /** 1880 Parses a `zIndex` attribute value from this widget's `srcNode`. 1881 1882 @method _parseZIndex 1883 @param {Node} srcNode The node to parse a `zIndex` value from. 1884 @return {Mixed} The parsed `zIndex` value. 1885 @protected 1886 **/ 1887 _parseZIndex: function (srcNode) { 1888 var zIndex; 1889 1890 // Prefers how WebKit handles `z-index` which better matches the 1891 // spec: 1892 // 1893 // * http://www.w3.org/TR/CSS2/visuren.html#z-index 1894 // * https://bugs.webkit.org/show_bug.cgi?id=15562 1895 // 1896 // When a node isn't rendered in the document, and/or when a 1897 // node is not positioned, then it doesn't have a context to derive 1898 // a valid `z-index` value from. 1899 if (!srcNode.inDoc() || srcNode.getStyle('position') === 'static') { 1900 zIndex = 'auto'; 1901 } else { 1902 // Uses `getComputedStyle()` because it has greater accuracy in 1903 // more browsers than `getStyle()` does for `z-index`. 1904 zIndex = srcNode.getComputedStyle('zIndex'); 1905 } 1906 1907 // This extension adds a stacking context to widgets, therefore a 1908 // `srcNode` witout a stacking context (i.e. "auto") will return 1909 // `null` from this DOM parser. This way the widget's default or 1910 // user provided value for `zIndex` will be used. 1911 return zIndex === 'auto' ? null : zIndex; 1912 }, 1913 1914 /** 1915 * Default setter for zIndex attribute changes. Normalizes zIndex values to 1916 * numbers, converting non-numerical values to 0. 1917 * 1918 * @method _setZIndex 1919 * @protected 1920 * @param {String | Number} zIndex 1921 * @return {Number} Normalized zIndex 1922 */ 1923 _setZIndex: function(zIndex) { 1924 if (L.isString(zIndex)) { 1925 zIndex = parseInt(zIndex, 10); 1926 } 1927 if (!L.isNumber(zIndex)) { 1928 zIndex = 0; 1929 } 1930 return zIndex; 1931 }, 1932 1933 /** 1934 * Default attribute change listener for the shim attribute, responsible 1935 * for updating the UI, in response to attribute changes. 1936 * 1937 * @method _afterShimChange 1938 * @protected 1939 * @param {EventFacade} e The event facade for the attribute change 1940 */ 1941 _afterShimChange : function(e) { 1942 this._uiSetShim(e.newVal); 1943 }, 1944 1945 /** 1946 * Default attribute change listener for the zIndex attribute, responsible 1947 * for updating the UI, in response to attribute changes. 1948 * 1949 * @method _afterZIndexChange 1950 * @protected 1951 * @param {EventFacade} e The event facade for the attribute change 1952 */ 1953 _afterZIndexChange : function(e) { 1954 this._uiSetZIndex(e.newVal); 1955 }, 1956 1957 /** 1958 * Updates the UI to reflect the zIndex value passed in. 1959 * 1960 * @method _uiSetZIndex 1961 * @protected 1962 * @param {number} zIndex The zindex to be reflected in the UI 1963 */ 1964 _uiSetZIndex: function (zIndex) { 1965 this._stackNode.setStyle(ZINDEX, zIndex); 1966 }, 1967 1968 /** 1969 * Updates the UI to enable/disable the shim. If the widget is not currently visible, 1970 * creation of the shim is deferred until it is made visible, for performance reasons. 1971 * 1972 * @method _uiSetShim 1973 * @protected 1974 * @param {boolean} enable If true, creates/renders the shim, if false, removes it. 1975 */ 1976 _uiSetShim: function (enable) { 1977 if (enable) { 1978 // Lazy creation 1979 if (this.get(VISIBLE)) { 1980 this._renderShim(); 1981 } else { 1982 this._renderShimDeferred(); 1983 } 1984 1985 // Eagerly attach resize handlers 1986 // 1987 // Required because of Event stack behavior, commit ref: cd8dddc 1988 // Should be revisted after Ticket #2531067 is resolved. 1989 if (UA.ie == 6) { 1990 this._addShimResizeHandlers(); 1991 } 1992 } else { 1993 this._destroyShim(); 1994 } 1995 }, 1996 1997 /** 1998 * Sets up change handlers for the visible attribute, to defer shim creation/rendering 1999 * until the Widget is made visible. 2000 * 2001 * @method _renderShimDeferred 2002 * @private 2003 */ 2004 _renderShimDeferred : function() { 2005 2006 this._stackHandles[SHIM_DEFERRED] = this._stackHandles[SHIM_DEFERRED] || []; 2007 2008 var handles = this._stackHandles[SHIM_DEFERRED], 2009 createBeforeVisible = function(e) { 2010 if (e.newVal) { 2011 this._renderShim(); 2012 } 2013 }; 2014 2015 handles.push(this.on(VisibleChange, createBeforeVisible)); 2016 // Depending how how Ticket #2531067 is resolved, a reversal of 2017 // commit ref: cd8dddc could lead to a more elagent solution, with 2018 // the addition of this line here: 2019 // 2020 // handles.push(this.after(VisibleChange, this.sizeShim)); 2021 }, 2022 2023 /** 2024 * Sets up event listeners to resize the shim when the size of the Widget changes. 2025 * <p> 2026 * NOTE: This method is only used for IE6 currently, since IE6 doesn't support a way to 2027 * resize the shim purely through CSS, when the Widget does not have an explicit width/height 2028 * set. 2029 * </p> 2030 * @method _addShimResizeHandlers 2031 * @private 2032 */ 2033 _addShimResizeHandlers : function() { 2034 2035 this._stackHandles[SHIM_RESIZE] = this._stackHandles[SHIM_RESIZE] || []; 2036 2037 var sizeShim = this.sizeShim, 2038 handles = this._stackHandles[SHIM_RESIZE]; 2039 2040 handles.push(this.after(VisibleChange, sizeShim)); 2041 handles.push(this.after(WidthChange, sizeShim)); 2042 handles.push(this.after(HeightChange, sizeShim)); 2043 handles.push(this.after(ContentUpdate, sizeShim)); 2044 }, 2045 2046 /** 2047 * Detaches any handles stored for the provided key 2048 * 2049 * @method _detachStackHandles 2050 * @param String handleKey The key defining the group of handles which should be detached 2051 * @private 2052 */ 2053 _detachStackHandles : function(handleKey) { 2054 var handles = this._stackHandles[handleKey], 2055 handle; 2056 2057 if (handles && handles.length > 0) { 2058 while((handle = handles.pop())) { 2059 handle.detach(); 2060 } 2061 } 2062 }, 2063 2064 /** 2065 * Creates the shim element and adds it to the DOM 2066 * 2067 * @method _renderShim 2068 * @private 2069 */ 2070 _renderShim : function() { 2071 var shimEl = this._shimNode, 2072 stackEl = this._stackNode; 2073 2074 if (!shimEl) { 2075 shimEl = this._shimNode = this._getShimTemplate(); 2076 stackEl.insertBefore(shimEl, stackEl.get(FIRST_CHILD)); 2077 2078 this._detachStackHandles(SHIM_DEFERRED); 2079 this.sizeShim(); 2080 } 2081 }, 2082 2083 /** 2084 * Removes the shim from the DOM, and detaches any related event 2085 * listeners. 2086 * 2087 * @method _destroyShim 2088 * @private 2089 */ 2090 _destroyShim : function() { 2091 if (this._shimNode) { 2092 this._shimNode.get(PARENT_NODE).removeChild(this._shimNode); 2093 this._shimNode = null; 2094 2095 this._detachStackHandles(SHIM_DEFERRED); 2096 this._detachStackHandles(SHIM_RESIZE); 2097 } 2098 }, 2099 2100 /** 2101 * For IE6, synchronizes the size and position of iframe shim to that of 2102 * Widget bounding box which it is protecting. For all other browsers, 2103 * this method does not do anything. 2104 * 2105 * @method sizeShim 2106 */ 2107 sizeShim: function () { 2108 var shim = this._shimNode, 2109 node = this._stackNode; 2110 2111 if (shim && UA.ie === 6 && this.get(VISIBLE)) { 2112 shim.setStyle(WIDTH, node.get(OFFSET_WIDTH) + PX); 2113 shim.setStyle(HEIGHT, node.get(OFFSET_HEIGHT) + PX); 2114 } 2115 }, 2116 2117 /** 2118 * Creates a cloned shim node, using the SHIM_TEMPLATE html template, for use on a new instance. 2119 * 2120 * @method _getShimTemplate 2121 * @private 2122 * @return {Node} node A new shim Node instance. 2123 */ 2124 _getShimTemplate : function() { 2125 return Node.create(Stack.SHIM_TEMPLATE, this._stackNode.get(OWNER_DOCUMENT)); 2126 } 2127 }; 2128
2129 Y.WidgetStack = Stack; 2130 2131 2132}, 'patched-v3.18.1', {"requires": ["base-build", "widget"], "skinnable": true}); 2133 2134YUI.add('widget-stdmod', function (Y, NAME) { 2135 2136/** 2137 * Provides standard module support for Widgets through an extension. 2138 * 2139 * @module widget-stdmod 2140 */ 2141 var L = Y.Lang, 2142 Node = Y.Node, 2143 UA = Y.UA, 2144 Widget = Y.Widget, 2145 2146 EMPTY = "", 2147 HD = "hd", 2148 BD = "bd", 2149 FT = "ft", 2150 HEADER = "header", 2151 BODY = "body", 2152 FOOTER = "footer", 2153 FILL_HEIGHT = "fillHeight", 2154 STDMOD = "stdmod", 2155 2156 NODE_SUFFIX = "Node", 2157 CONTENT_SUFFIX = "Content", 2158 2159 FIRST_CHILD = "firstChild", 2160 CHILD_NODES = "childNodes", 2161 OWNER_DOCUMENT = "ownerDocument", 2162 2163 CONTENT_BOX = "contentBox", 2164 2165 HEIGHT = "height", 2166 OFFSET_HEIGHT = "offsetHeight", 2167 AUTO = "auto", 2168 2169 HeaderChange = "headerContentChange", 2170 BodyChange = "bodyContentChange", 2171 FooterChange = "footerContentChange", 2172 FillHeightChange = "fillHeightChange", 2173 HeightChange = "heightChange", 2174 ContentUpdate = "contentUpdate", 2175 2176 RENDERUI = "renderUI", 2177 BINDUI = "bindUI", 2178 SYNCUI = "syncUI", 2179 2180 APPLY_PARSED_CONFIG = "_applyParsedConfig", 2181 2182 UI = Y.Widget.UI_SRC; 2183 2184 /** 2185 * Widget extension, which can be used to add Standard Module support to the 2186 * base Widget class, through the <a href="Base.html#method_build">Base.build</a> 2187 * method. 2188 * <p> 2189 * The extension adds header, body and footer sections to the Widget's content box and 2190 * provides the corresponding methods and attributes to modify the contents of these sections. 2191 * </p> 2192 * @class WidgetStdMod 2193 * @param {Object} The user configuration object 2194 */ 2195 function StdMod(config) {} 2196 2197 /** 2198 * Constant used to refer the the standard module header, in methods which expect a section specifier 2199 * 2200 * @property HEADER 2201 * @static
2202 * @type String 2203 */ 2204 StdMod.HEADER = HEADER; 2205 2206 /** 2207 * Constant used to refer the the standard module body, in methods which expect a section specifier 2208 * 2209 * @property BODY 2210 * @static 2211 * @type String 2212 */ 2213 StdMod.BODY = BODY; 2214 2215 /** 2216 * Constant used to refer the the standard module footer, in methods which expect a section specifier 2217 * 2218 * @property FOOTER 2219 * @static 2220 * @type String 2221 */ 2222 StdMod.FOOTER = FOOTER; 2223 2224 /** 2225 * Constant used to specify insertion position, when adding content to sections of the standard module in 2226 * methods which expect a "where" argument. 2227 * <p> 2228 * Inserts new content <em>before</em> the sections existing content. 2229 * </p> 2230 * @property AFTER 2231 * @static 2232 * @type String 2233 */ 2234 StdMod.AFTER = "after"; 2235 2236 /** 2237 * Constant used to specify insertion position, when adding content to sections of the standard module in 2238 * methods which expect a "where" argument. 2239 * <p> 2240 * Inserts new content <em>before</em> the sections existing content. 2241 * </p> 2242 * @property BEFORE 2243 * @static
2244 * @type String 2245 */ 2246 StdMod.BEFORE = "before"; 2247 /** 2248 * Constant used to specify insertion position, when adding content to sections of the standard module in 2249 * methods which expect a "where" argument. 2250 * <p> 2251 * <em>Replaces</em> the sections existing content, with new content. 2252 * </p> 2253 * @property REPLACE 2254 * @static 2255 * @type String 2256 */ 2257 StdMod.REPLACE = "replace"; 2258 2259 var STD_HEADER = StdMod.HEADER, 2260 STD_BODY = StdMod.BODY, 2261 STD_FOOTER = StdMod.FOOTER, 2262 2263 HEADER_CONTENT = STD_HEADER + CONTENT_SUFFIX, 2264 FOOTER_CONTENT = STD_FOOTER + CONTENT_SUFFIX, 2265 BODY_CONTENT = STD_BODY + CONTENT_SUFFIX; 2266 2267 /** 2268 * Static property used to define the default attribute 2269 * configuration introduced by WidgetStdMod. 2270 * 2271 * @property ATTRS 2272 * @type Object 2273 * @static 2274 */ 2275 StdMod.ATTRS = { 2276 2277 /** 2278 * @attribute headerContent 2279 * @type HTML 2280 * @default undefined 2281 * @description The content to be added to the header section. This will replace any existing content 2282 * in the header. If you want to append, or insert new content, use the <a href="#method_setStdModContent">setStdModContent</a> method. 2283 */ 2284 headerContent: { 2285 value:null 2286 }, 2287 2288 /** 2289 * @attribute footerContent 2290 * @type HTML 2291 * @default undefined 2292 * @description The content to be added to the footer section. This will replace any existing content 2293 * in the footer. If you want to append, or insert new content, use the <a href="#method_setStdModContent">setStdModContent</a> method. 2294 */ 2295 footerContent: { 2296 value:null 2297 }, 2298 2299 /** 2300 * @attribute bodyContent 2301 * @type HTML 2302 * @default undefined 2303 * @description The content to be added to the body section. This will replace any existing content 2304 * in the body. If you want to append, or insert new content, use the <a href="#method_setStdModContent">setStdModContent</a> method. 2305 */ 2306 bodyContent: { 2307 value:null 2308 }, 2309 2310 /** 2311 * @attribute fillHeight 2312 * @type {String} 2313 * @default WidgetStdMod.BODY 2314 * @description The section (WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER) which should be resized to fill the height of the standard module, when a 2315 * height is set on the Widget. If a height is not set on the widget, then all sections are sized based on 2316 * their content. 2317 */ 2318 fillHeight: { 2319 value: StdMod.BODY, 2320 validator: function(val) { 2321 return this._validateFillHeight(val); 2322 } 2323 } 2324 }; 2325 2326 /** 2327 * The HTML parsing rules for the WidgetStdMod class. 2328 * 2329 * @property HTML_PARSER 2330 * @static 2331 * @type Object 2332 */ 2333 StdMod.HTML_PARSER = { 2334 headerContent: function(contentBox) { 2335 return this._parseStdModHTML(STD_HEADER); 2336 }, 2337 2338 bodyContent: function(contentBox) { 2339 return this._parseStdModHTML(STD_BODY); 2340 }, 2341 2342 footerContent : function(contentBox) { 2343 return this._parseStdModHTML(STD_FOOTER); 2344 } 2345 }; 2346 2347 /** 2348 * Static hash of default class names used for the header, 2349 * body and footer sections of the standard module, keyed by 2350 * the section identifier (WidgetStdMod.STD_HEADER, WidgetStdMod.STD_BODY, WidgetStdMod.STD_FOOTER) 2351 * 2352 * @property SECTION_CLASS_NAMES 2353 * @static 2354 * @type Object 2355 */ 2356 StdMod.SECTION_CLASS_NAMES = { 2357 header: Widget.getClassName(HD), 2358 body: Widget.getClassName(BD), 2359 footer: Widget.getClassName(FT) 2360 }; 2361 2362 /** 2363 * The template HTML strings for each of the standard module sections. Section entries are keyed by the section constants, 2364 * WidgetStdMod.HEADER, WidgetStdMod.BODY, WidgetStdMod.FOOTER, and contain the HTML to be added for each section. 2365 * e.g. 2366 * <pre> 2367 * { 2368 * header : '<div class="yui-widget-hd"></div>', 2369 * body : '<div class="yui-widget-bd"></div>', 2370 * footer : '<div class="yui-widget-ft"></div>' 2371 * } 2372 * </pre> 2373 * @property TEMPLATES 2374 * @type Object 2375 * @static 2376 */ 2377 StdMod.TEMPLATES = { 2378 header : '<div class="' + StdMod.SECTION_CLASS_NAMES[STD_HEADER] + '"></div>', 2379 body : '<div class="' + StdMod.SECTION_CLASS_NAMES[STD_BODY] + '"></div>', 2380 footer : '<div class="' + StdMod.SECTION_CLASS_NAMES[STD_FOOTER] + '"></div>' 2381 }; 2382 2383 StdMod.prototype = { 2384 2385 initializer : function() { 2386 this._stdModNode = this.get(CONTENT_BOX); 2387 2388 Y.before(this._renderUIStdMod, this, RENDERUI); 2389 Y.before(this._bindUIStdMod, this, BINDUI); 2390 Y.before(this._syncUIStdMod, this, SYNCUI); 2391 }, 2392 2393 /** 2394 * Synchronizes the UI to match the Widgets standard module state. 2395 * <p> 2396 * This method is invoked after syncUI is invoked for the Widget class
2397 * using YUI's aop infrastructure. 2398 * </p> 2399 * @method _syncUIStdMod 2400 * @protected 2401 */ 2402 _syncUIStdMod : function() { 2403 var stdModParsed = this._stdModParsed; 2404 2405 if (!stdModParsed || !stdModParsed[HEADER_CONTENT]) { 2406 this._uiSetStdMod(STD_HEADER, this.get(HEADER_CONTENT)); 2407 } 2408 2409 if (!stdModParsed || !stdModParsed[BODY_CONTENT]) { 2410 this._uiSetStdMod(STD_BODY, this.get(BODY_CONTENT)); 2411 } 2412 2413 if (!stdModParsed || !stdModParsed[FOOTER_CONTENT]) { 2414 this._uiSetStdMod(STD_FOOTER, this.get(FOOTER_CONTENT)); 2415 } 2416 2417 this._uiSetFillHeight(this.get(FILL_HEIGHT)); 2418 }, 2419 2420 /** 2421 * Creates/Initializes the DOM for standard module support. 2422 * <p> 2423 * This method is invoked after renderUI is invoked for the Widget class 2424 * using YUI's aop infrastructure. 2425 * </p> 2426 * @method _renderUIStdMod 2427 * @protected 2428 */ 2429 _renderUIStdMod : function() { 2430 this._stdModNode.addClass(Widget.getClassName(STDMOD)); 2431 this._renderStdModSections(); 2432 2433 //This normally goes in bindUI but in order to allow setStdModContent() to work before renderUI 2434 //stage, these listeners should be set up at the earliest possible time. 2435 this.after(HeaderChange, this._afterHeaderChange); 2436 this.after(BodyChange, this._afterBodyChange); 2437 this.after(FooterChange, this._afterFooterChange); 2438 }, 2439 2440 _renderStdModSections : function() { 2441 if (L.isValue(this.get(HEADER_CONTENT))) { this._renderStdMod(STD_HEADER); } 2442 if (L.isValue(this.get(BODY_CONTENT))) { this._renderStdMod(STD_BODY); } 2443 if (L.isValue(this.get(FOOTER_CONTENT))) { this._renderStdMod(STD_FOOTER); } 2444 }, 2445 2446 /** 2447 * Binds event listeners responsible for updating the UI state in response to 2448 * Widget standard module related state changes. 2449 * <p> 2450 * This method is invoked after bindUI is invoked for the Widget class 2451 * using YUI's aop infrastructure. 2452 * </p> 2453 * @method _bindUIStdMod 2454 * @protected 2455 */ 2456 _bindUIStdMod : function() { 2457 // this.after(HeaderChange, this._afterHeaderChange); 2458 // this.after(BodyChange, this._afterBodyChange); 2459 // this.after(FooterChange, this._afterFooterChange); 2460 2461 this.after(FillHeightChange, this._afterFillHeightChange); 2462 this.after(HeightChange, this._fillHeight); 2463 this.after(ContentUpdate, this._fillHeight); 2464 }, 2465 2466 /** 2467 * Default attribute change listener for the headerContent attribute, responsible 2468 * for updating the UI, in response to attribute changes. 2469 * 2470 * @method _afterHeaderChange 2471 * @protected 2472 * @param {EventFacade} e The event facade for the attribute change 2473 */ 2474 _afterHeaderChange : function(e) { 2475 if (e.src !== UI) { 2476 this._uiSetStdMod(STD_HEADER, e.newVal, e.stdModPosition); 2477 } 2478 }, 2479 2480 /** 2481 * Default attribute change listener for the bodyContent attribute, responsible 2482 * for updating the UI, in response to attribute changes. 2483 * 2484 * @method _afterBodyChange 2485 * @protected 2486 * @param {EventFacade} e The event facade for the attribute change 2487 */ 2488 _afterBodyChange : function(e) { 2489 if (e.src !== UI) { 2490 this._uiSetStdMod(STD_BODY, e.newVal, e.stdModPosition); 2491 } 2492 }, 2493 2494 /** 2495 * Default attribute change listener for the footerContent attribute, responsible 2496 * for updating the UI, in response to attribute changes. 2497 * 2498 * @method _afterFooterChange 2499 * @protected 2500 * @param {EventFacade} e The event facade for the attribute change 2501 */ 2502 _afterFooterChange : function(e) { 2503 if (e.src !== UI) { 2504 this._uiSetStdMod(STD_FOOTER, e.newVal, e.stdModPosition); 2505 } 2506 }, 2507 2508 /** 2509 * Default attribute change listener for the fillHeight attribute, responsible 2510 * for updating the UI, in response to attribute changes. 2511 * 2512 * @method _afterFillHeightChange 2513 * @protected 2514 * @param {EventFacade} e The event facade for the attribute change 2515 */ 2516 _afterFillHeightChange: function (e) { 2517 this._uiSetFillHeight(e.newVal); 2518 }, 2519 2520 /** 2521 * Default validator for the fillHeight attribute. Verifies that the 2522 * value set is a valid section specifier - one of WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER, 2523 * or a falsey value if fillHeight is to be disabled. 2524 * 2525 * @method _validateFillHeight 2526 * @protected 2527 * @param {String} val The section which should be setup to fill height, or false/null to disable fillHeight 2528 * @return true if valid, false if not 2529 */ 2530 _validateFillHeight : function(val) { 2531 return !val || val == StdMod.BODY || val == StdMod.HEADER || val == StdMod.FOOTER; 2532 }, 2533 2534 /** 2535 * Updates the rendered UI, to resize the provided section so that the standard module fills out 2536 * the specified widget height. Note: This method does not check whether or not a height is set 2537 * on the Widget. 2538 * 2539 * @method _uiSetFillHeight 2540 * @protected 2541 * @param {String} fillSection A valid section specifier - one of WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER 2542 */ 2543 _uiSetFillHeight : function(fillSection) {
2544 var fillNode = this.getStdModNode(fillSection); 2545 var currNode = this._currFillNode; 2546 2547 if (currNode && fillNode !== currNode){ 2548 currNode.setStyle(HEIGHT, EMPTY); 2549 } 2550 2551 if (fillNode) { 2552 this._currFillNode = fillNode; 2553 } 2554 2555 this._fillHeight(); 2556 }, 2557 2558 /** 2559 * Updates the rendered UI, to resize the current section specified by the fillHeight attribute, so 2560 * that the standard module fills out the Widget height. If a height has not been set on Widget, 2561 * the section is not resized (height is set to "auto"). 2562 * 2563 * @method _fillHeight 2564 * @private 2565 */ 2566 _fillHeight : function() { 2567 if (this.get(FILL_HEIGHT)) { 2568 var height = this.get(HEIGHT); 2569 if (height != EMPTY && height != AUTO) { 2570 this.fillHeight(this.getStdModNode(this.get(FILL_HEIGHT))); 2571 } 2572 } 2573 }, 2574 2575 /** 2576 * Updates the rendered UI, adding the provided content (either an HTML string, or node reference), 2577 * to the specified section. The content is either added before, after or replaces existing content 2578 * in the section, based on the value of the <code>where</code> argument. 2579 * 2580 * @method _uiSetStdMod 2581 * @protected 2582 * 2583 * @param {String} section The section to be updated. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 2584 * @param {String | Node} content The new content (either as an HTML string, or Node reference) to add to the section 2585 * @param {String} where Optional. Either WidgetStdMod.AFTER, WidgetStdMod.BEFORE or WidgetStdMod.REPLACE. 2586 * If not provided, the content will replace existing content in the section. 2587 */ 2588 _uiSetStdMod : function(section, content, where) { 2589 // Using isValue, so that "" is valid content 2590 if (L.isValue(content)) { 2591 var node = this.getStdModNode(section, true); 2592 2593 this._addStdModContent(node, content, where); 2594 2595 this.set(section + CONTENT_SUFFIX, this._getStdModContent(section), {src:UI}); 2596 } else { 2597 this._eraseStdMod(section); 2598 } 2599 this.fire(ContentUpdate); 2600 }, 2601 2602 /** 2603 * Creates the DOM node for the given section, and inserts it into the correct location in the contentBox. 2604 * 2605 * @method _renderStdMod 2606 * @protected 2607 * @param {String} section The section to create/render. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 2608 * @return {Node} A reference to the added section node 2609 */ 2610 _renderStdMod : function(section) { 2611 2612 var contentBox = this.get(CONTENT_BOX), 2613 sectionNode = this._findStdModSection(section); 2614 2615 if (!sectionNode) { 2616 sectionNode = this._getStdModTemplate(section); 2617 } 2618 2619 this._insertStdModSection(contentBox, section, sectionNode); 2620 2621 this[section + NODE_SUFFIX] = sectionNode; 2622 return this[section + NODE_SUFFIX]; 2623 }, 2624 2625 /** 2626 * Removes the DOM node for the given section. 2627 * 2628 * @method _eraseStdMod 2629 * @protected 2630 * @param {String} section The section to remove. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 2631 */ 2632 _eraseStdMod : function(section) { 2633 var sectionNode = this.getStdModNode(section); 2634 if (sectionNode) { 2635 sectionNode.remove(true); 2636 delete this[section + NODE_SUFFIX]; 2637 } 2638 }, 2639 2640 /** 2641 * Helper method to insert the Node for the given section into the correct location in the contentBox. 2642 * 2643 * @method _insertStdModSection 2644 * @private 2645 * @param {Node} contentBox A reference to the Widgets content box. 2646 * @param {String} section The section to create/render. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 2647 * @param {Node} sectionNode The Node for the section. 2648 */ 2649 _insertStdModSection : function(contentBox, section, sectionNode) { 2650 var fc = contentBox.get(FIRST_CHILD); 2651 2652 if (section === STD_FOOTER || !fc) { 2653 contentBox.appendChild(sectionNode); 2654 } else { 2655 if (section === STD_HEADER) { 2656 contentBox.insertBefore(sectionNode, fc); 2657 } else { 2658 var footer = this[STD_FOOTER + NODE_SUFFIX]; 2659 if (footer) { 2660 contentBox.insertBefore(sectionNode, footer); 2661 } else { 2662 contentBox.appendChild(sectionNode); 2663 } 2664 } 2665 } 2666 }, 2667 2668 /** 2669 * Gets a new Node reference for the given standard module section, by cloning 2670 * the stored template node. 2671 * 2672 * @method _getStdModTemplate 2673 * @protected 2674 * @param {String} section The section to create a new node for. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 2675 * @return {Node} The new Node instance for the section 2676 */ 2677 _getStdModTemplate : function(section) { 2678 return Node.create(StdMod.TEMPLATES[section], this._stdModNode.get(OWNER_DOCUMENT)); 2679 }, 2680 2681 /** 2682 * Helper method to add content to a StdMod section node. 2683 * The content is added either before, after or replaces the existing node content 2684 * based on the value of the <code>where</code> argument. 2685 * 2686 * @method _addStdModContent 2687 * @private 2688 * 2689 * @param {Node} node The section Node to be updated. 2690 * @param {Node|NodeList|String} children The new content Node, NodeList or String to be added to section Node provided. 2691 * @param {String} where Optional. Either WidgetStdMod.AFTER, WidgetStdMod.BEFORE or WidgetStdMod.REPLACE. 2692 * If not provided, the content will replace existing content in the Node. 2693 */ 2694 _addStdModContent : function(node, children, where) { 2695 2696 // StdMod where to Node where 2697 switch (where) { 2698 case StdMod.BEFORE: // 0 is before fistChild 2699 where = 0; 2700 break; 2701 case StdMod.AFTER: // undefined is appendChild 2702 where = undefined; 2703 break; 2704 default: // replace is replace, not specified is replace 2705 where = StdMod.REPLACE; 2706 } 2707 2708 node.insert(children, where); 2709 }, 2710 2711 /** 2712 * Helper method to obtain the precise height of the node provided, including padding and border. 2713 * The height could be a sub-pixel value for certain browsers, such as Firefox 3. 2714 *
2715 * @method _getPreciseHeight 2716 * @private 2717 * @param {Node} node The node for which the precise height is required. 2718 * @return {Number} The height of the Node including borders and padding, possibly a float. 2719 */ 2720 _getPreciseHeight : function(node) { 2721 var height = (node) ? node.get(OFFSET_HEIGHT) : 0, 2722 getBCR = "getBoundingClientRect"; 2723 2724 if (node && node.hasMethod(getBCR)) { 2725 var preciseRegion = node.invoke(getBCR); 2726 if (preciseRegion) { 2727 height = preciseRegion.bottom - preciseRegion.top; 2728 } 2729 } 2730 2731 return height; 2732 }, 2733 2734 /** 2735 * Helper method to to find the rendered node for the given section, 2736 * if it exists. 2737 * 2738 * @method _findStdModSection 2739 * @private 2740 * @param {String} section The section for which the render Node is to be found. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 2741 * @return {Node} The rendered node for the given section, or null if not found. 2742 */ 2743 _findStdModSection: function(section) { 2744 return this.get(CONTENT_BOX).one("> ." + StdMod.SECTION_CLASS_NAMES[section]); 2745 }, 2746 2747 /** 2748 * Utility method, used by WidgetStdMods HTML_PARSER implementation 2749 * to extract data for each section from markup. 2750 * 2751 * @method _parseStdModHTML 2752 * @private 2753 * @param {String} section 2754 * @return {String}
2754 Inner HTML string with the contents of the section 2755 */ 2756 _parseStdModHTML : function(section) { 2757 2758 var node = this._findStdModSection(section); 2759 2760 if (node) { 2761 if (!this._stdModParsed) { 2762 this._stdModParsed = {}; 2763 Y.before(this._applyStdModParsedConfig, this, APPLY_PARSED_CONFIG); 2764 } 2765 this._stdModParsed[section + CONTENT_SUFFIX] = 1; 2766 2767 return node.get("innerHTML"); 2768 } 2769 2770 return null; 2771 }, 2772 2773 /** 2774 * This method is injected before the _applyParsedConfig step in 2775 * the application of HTML_PARSER, and sets up the state to 2776 * identify whether or not we should remove the current DOM content 2777 * or not, based on whether or not the current content attribute value 2778 * was extracted from the DOM, or provided by the user configuration 2779 * 2780 * @method _applyStdModParsedConfig 2781 * @private 2782 */ 2783 _applyStdModParsedConfig : function(node, cfg, parsedCfg) { 2784 var parsed = this._stdModParsed; 2785 if (parsed) { 2786 parsed[HEADER_CONTENT] = !(HEADER_CONTENT in cfg) && (HEADER_CONTENT in parsed); 2787 parsed[BODY_CONTENT] = !(BODY_CONTENT in cfg) && (BODY_CONTENT in parsed); 2788 parsed[FOOTER_CONTENT] = !(FOOTER_CONTENT in cfg) && (FOOTER_CONTENT in parsed); 2789 } 2790 }, 2791 2792 /** 2793 * Retrieves the child nodes (content) of a standard module section 2794 * 2795 * @method _getStdModContent 2796 * @private 2797 * @param {String} section The standard module section whose child nodes are to be retrieved. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 2798 * @return {Node} The child node collection of the standard module section. 2799 */ 2800 _getStdModContent : function(section) { 2801 return (this[section + NODE_SUFFIX]) ? this[section + NODE_SUFFIX].get(CHILD_NODES) : null; 2802 }, 2803 2804 /** 2805 * Updates the body section of the standard module with the content provided (either an HTML string, or node reference). 2806 * <p> 2807 * This method can be used instead of the corresponding section content attribute if you'd like to retain the current content of the section, 2808 * and insert content before or after it, by specifying the <code>where</code> argument. 2809 * </p> 2810 * @method setStdModContent 2811 * @param {String} section The standard module section whose content is to be updated. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 2812 * @param {String | Node} content The content to be added, either an HTML string or a Node reference. 2813 * @param {String} where Optional. Either WidgetStdMod.AFTER, WidgetStdMod.BEFORE or WidgetStdMod.REPLACE. 2814 * If not provided, the content will replace existing content in the section. 2815 */ 2816 setStdModContent : function(section, content, where) { 2817 //var node = this.getStdModNode(section) || this._renderStdMod(section); 2818 this.set(section + CONTENT_SUFFIX, content, {stdModPosition:where}); 2819 //this._addStdModContent(node, content, where); 2820 }, 2821 2822 /** 2823 Returns the node reference for the specified `section`. 2824 2825 **Note:** The DOM is not queried for the node reference. The reference 2826 stored by the widget instance is returned if it was set. Passing a 2827 truthy for `forceCreate` will create the section node if it does not 2828 already exist. 2829 2830 @method getStdModNode 2831 @param {String} section The section whose node reference is required. 2832 Either `WidgetStdMod.HEADER`, `WidgetStdMod.BODY`, or 2833 `WidgetStdMod.FOOTER`. 2834 @param {Boolean} forceCreate Whether the section node should be created 2835 if it does not already exist. 2836 @return {Node} The node reference for the `section`, or null if not set. 2837 **/ 2838 getStdModNode : function(section, forceCreate) { 2839 var node = this[section + NODE_SUFFIX] || null; 2840 2841 if (!node && forceCreate) { 2842 node = this._renderStdMod(section); 2843 } 2844 2845 return node; 2846 }, 2847 2848 /** 2849 * Sets the height on the provided header, body or footer element to 2850 * fill out the height of the Widget. It determines the height of the 2851 * widgets bounding box, based on it's configured height value, and 2852 * sets the height of the provided section to fill out any 2853 * space remaining after the other standard module section heights 2854 * have been accounted for. 2855 * 2856 * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 2857 * height has not been set on the Widget, since for an "auto" height Widget, 2858 * the heights of the header/body/footer will drive the height of the Widget.</p> 2859 * 2860 * @method fillHeight 2861 * @param {Node} node The node which should be resized to fill out the height 2862 * of the Widget bounding box. Should be a standard module section node which belongs 2863 * to the widget. 2864 */ 2865 fillHeight : function(node) { 2866 if (node) { 2867 var contentBox = this.get(CONTENT_BOX), 2868 stdModNodes = [this.headerNode, this.bodyNode, this.footerNode], 2869 stdModNode, 2870 cbContentHeight, 2871 filled = 0, 2872 remaining = 0, 2873 2874 validNode = false;
2875 2876 for (var i = 0, l = stdModNodes.length; i < l; i++) { 2877 stdModNode = stdModNodes[i]; 2878 if (stdModNode) { 2879 if (stdModNode !== node) { 2880 filled += this._getPreciseHeight(stdModNode); 2881 } else { 2882 validNode = true; 2883 } 2884 } 2885 } 2886 2887 if (validNode) { 2888 if (UA.ie || UA.opera) { 2889 // Need to set height to 0, to allow height to be reduced 2890 node.set(OFFSET_HEIGHT, 0); 2891 } 2892 2893 cbContentHeight = contentBox.get(OFFSET_HEIGHT) - 2894 parseInt(contentBox.getComputedStyle("paddingTop"), 10) - 2895 parseInt(contentBox.getComputedStyle("paddingBottom"), 10) - 2896 parseInt(contentBox.getComputedStyle("borderBottomWidth"), 10) - 2897 parseInt(contentBox.getComputedStyle("borderTopWidth"), 10); 2898 2899 if (L.isNumber(cbContentHeight)) { 2900 remaining = cbContentHeight - filled; 2901 if (remaining >= 0) { 2902 node.set(OFFSET_HEIGHT, remaining); 2903 } 2904 } 2905 } 2906 } 2907 } 2908 }; 2909 2910 Y.WidgetStdMod = StdMod; 2911 2912 2913}, 'patched-v3.18.1', {"requires": ["base-build", "widget"]}); 2914 2915YUI.add('aui-aria', function (A, NAME) { 2916 2917/** 2918 * The Aria Component. 2919 * 2920 * @module aui-aria 2921 */ 2922 2923var Lang = A.Lang, 2924 isBoolean = Lang.isBoolean, 2925 isFunction = Lang.isFunction, 2926 isObject = Lang.isObject, 2927 isString = Lang.isString, 2928 STR_REGEX = /([^a-z])/ig, 2929 2930 _toAriaRole = A.cached(function(str) { 2931 return str.replace(STR_REGEX, function() { 2932 return ''; 2933 }).toLowerCase(); 2934 }); 2935 2936/** 2937 * A base class for Aria. 2938 * 2939 * @class A.Plugin.Aria 2940 * @extends Plugin.Base 2941 * @param {Object} config Object literal specifying widget configuration 2942 * properties. 2943 * @constructor 2944 */ 2945var Aria = A.Component.create({ 2946 2947 /** 2948 * Static property provides a string to identify the class. 2949 * 2950 * @property NAME
2951 * @type String 2952 * @static 2953 */ 2954 NAME: 'aria', 2955 2956 /** 2957 * Static property provides a string to identify the namespace. 2958 * 2959 * @property NS 2960 * @type String 2961 * @static 2962 */ 2963 NS: 'aria', 2964 2965 /** 2966 * Static property used to define the default attribute configuration for 2967 * the `A.Aria`. 2968 * 2969 * @property ATTRS 2970 * @type Object 2971 * @static 2972 */ 2973 ATTRS: { 2974 2975 /** 2976 * The ARIA attributes collection. 2977 * 2978 * @attribute attributes 2979 * @default {} 2980 * @type Object 2981 */ 2982 attributes: { 2983 value: {}, 2984 validator: isObject 2985 }, 2986 2987 /** 2988 * The ARIA attribute value format. 2989 * 2990 * @attribute attributeValueFormat 2991 * @type Function 2992 */ 2993 attributeValueFormat: { 2994 value: function(val) { 2995 return val; 2996 }, 2997 validator: isFunction 2998 }, 2999 3000 /** 3001 * Node container for the ARIA attribute. 3002 * 3003 * @attribute attributeNode 3004 * @writeOnce 3005 */ 3006 attributeNode: { 3007 writeOnce: true, 3008 setter: A.one, 3009 valueFn: function() { 3010 return this.get('host').get('boundingBox'); 3011 } 3012 }, 3013 3014 /** 3015 * The ARIA role name. 3016 * 3017 * @attribute roleName
3018 * @type String 3019 */ 3020 roleName: { 3021 valueFn: function() { 3022 var instance = this; 3023 var host = instance.get('host'); 3024 var roleName = _toAriaRole(host.constructor.NAME || ''); 3025 3026 return (instance.isValidRole(roleName) ? roleName : ''); 3027 }, 3028 validator: isString 3029 }, 3030 3031 /** 3032 * Node container for the ARIA role. 3033 * 3034 * @attribute roleNode 3035 * @writeOnce 3036 */ 3037 roleNode: { 3038 writeOnce: true, 3039 setter: A.one, 3040 valueFn: function() { 3041 return this.get('host').get('boundingBox'); 3042 } 3043 }, 3044 3045 /** 3046 * Checks if the attribute is valid with W3C rules. 3047 * 3048 * @attribute validateW3C 3049 * @default true 3050 * @type Boolean 3051 */ 3052 validateW3C: { 3053 value: true, 3054 validator: isBoolean 3055 } 3056 }, 3057 3058 /** 3059 * Static property used to define which component it extends. 3060 * 3061 * @property EXTENDS 3062 * @type Object 3063 * @static 3064 */ 3065 EXTENDS: A.Plugin.Base, 3066 3067 prototype: { 3068 3069 /** 3070 * Construction logic executed during Aria instantiation. Lifecycle. 3071 * 3072 * @method initializer 3073 * @protected 3074 */ 3075 initializer: function() { 3076 var instance = this; 3077 3078 instance.publish('aria:processAttribute', { 3079 defaultFn: instance._defProcessFn, 3080 queuable: false, 3081 emitFacade: true, 3082 bubbles: true, 3083 prefix: 'aria' 3084 }); 3085 3086 instance._uiSetRoleName( 3087 instance.get('roleName') 3088 ); 3089 3090 instance.after('roleNameChange', instance._afterRoleNameChange); 3091 3092 instance._bindHostAttributes(); 3093 }, 3094 3095 /** 3096 * Checks if the ARIA attribute is valid. 3097 * 3098 * @method isValidAttribute 3099 * @param attrName 3100 * @return {Boolean} 3101 */ 3102 isValidAttribute: function(attrName) { 3103 var instance = this; 3104 3105 return (instance.get('validateW3C') ? A.Plugin.Aria.W3C_ATTRIBUTES[attrName] : true); 3106 }, 3107 3108 /** 3109 * Checks if the ARIA role is valid. 3110 * 3111 * @method isValidRole 3112 * @param roleName 3113 * @return {Boolean} 3114 */ 3115 isValidRole: function(roleName) { 3116 var instance = this; 3117 3118 return (instance.get('validateW3C') ? A.Plugin.Aria.W3C_ROLES[roleName] : true); 3119 }, 3120 3121 /** 3122 * Set a single ARIA attribute. 3123 * 3124 * @method setAttribute 3125 * @param attrName 3126 * @param attrValue 3127 * @param node 3128 * @return {Boolean} 3129 */ 3130 setAttribute: function(attrName, attrValue, node) { 3131 var instance = this; 3132 3133 if (instance.isValidAttribute(attrName)) { 3134 (node || instance.get('attributeNode')).set('aria-' + attrName, attrValue); 3135 3136 return true; 3137 } 3138 3139 return false; 3140 }, 3141 3142 /** 3143 * Set a list of ARIA attributes. 3144 * 3145 * @method setAttributes 3146 * @param attributes 3147 */ 3148 setAttributes: function(attributes) { 3149 var instance = this; 3150 3151 A.Array.each(attributes, function(attribute) { 3152 instance.setAttribute(attribute.name, attribute.value, attribute.node); 3153 }); 3154 }, 3155 3156 /** 3157 * Set a single ARIA role. 3158 * 3159 * @method setRole 3160 * @param roleName 3161 * @param node 3162 * @return {Boolean} 3163 */ 3164 setRole: function(roleName, node) { 3165 var instance = this; 3166 3167 if (instance.isValidRole(roleName)) { 3168 (node || instance.get('roleNode')).set('role', roleName); 3169 3170 return true; 3171 } 3172 3173 return false; 3174 }, 3175 3176 /** 3177 * Set a list of ARIA roles. 3178 * 3179 * @method setRoles 3180 * @param roles 3181 */ 3182 setRoles: function(roles) { 3183 var instance = this; 3184 3185 A.Array.each(roles, function(role) { 3186 instance.setRole(role.name, role.node); 3187 }); 3188 }, 3189 3190 /** 3191 * Fires after a host attribute change. 3192 * 3193 * @method _afterHostAttributeChange 3194 * @param event 3195 * @protected 3196 */ 3197 _afterHostAttributeChange: function(event) { 3198 var instance = this; 3199 3200 instance._handleProcessAttribute(event); 3201 }, 3202 3203 /** 3204 * Triggers after `roleName` attribute change. 3205 * 3206 * @method _afterRoleNameChange 3207 * @param event 3208 * @protected 3209 */ 3210 _afterRoleNameChange: function(event) { 3211 var instance = this; 3212 3213 instance._uiSetRoleName(event.newVal); 3214 }, 3215 3216 /** 3217 * Bind the list of host attributes. 3218 * 3219 * @method _bindHostAttributes 3220 * @protected 3221 */ 3222 _bindHostAttributes: function() { 3223 var instance = this; 3224 var attributes = instance.get('attributes'); 3225 3226 A.each(attributes, function(aria, attrName) { 3227 var ariaAttr = instance._getAriaAttribute(aria, attrName); 3228 3229 instance._handleProcessAttribute({ 3230 aria: ariaAttr 3231 }); 3232 3233 instance.afterHostEvent(attrName + 'Change', function(event) { 3234 event.aria = ariaAttr; 3235 instance._afterHostAttributeChange(event); 3236 }); 3237 }); 3238 }, 3239 3240 /** 3241 * Calls the `_setAttribute` method. 3242 * 3243 * @method _defProcessFn 3244 * @param event 3245 * @protected 3246 */ 3247 _defProcessFn: function(event) { 3248 var instance = this; 3249 3250 instance._setAttribute(event.aria); 3251 }, 3252 3253 /** 3254 * Get the ARIA attribute. 3255 * 3256 * @method _getAriaAttribute 3257 * @param aria 3258 * @param attrName 3259 * @protected 3260 * @return {Object} 3261 */ 3262 _getAriaAttribute: function(aria, attrName) { 3263 var instance = this; 3264 var attributeValueFormat = instance.get('attributeValueFormat'); 3265 var prepared = {}; 3266 3267 if (isString(aria)) { 3268 prepared = A.merge(prepared, { 3269 ariaName: aria, 3270 attrName: attrName, 3271 format: attributeValueFormat, 3272 node: null 3273 }); 3274 } 3275 else if (isObject(aria)) { 3276 prepared = A.mix(aria, { 3277 ariaName: '', 3278 attrName: attrName, 3279 format: attributeValueFormat, 3280 node: null 3281 }); 3282 } 3283 3284 return prepared; 3285 }, 3286 3287 /** 3288 * Fires ARIA process attribute event handle. 3289 * 3290 * @method _handleProcessAttribute 3291 * @param event 3292 * @protected 3293 */ 3294 _handleProcessAttribute: function(event) { 3295 var instance = this; 3296 3297 instance.fire('aria:processAttribute', { 3298 aria: event.aria 3299 }); 3300 }, 3301 3302 /** 3303 * Set the attribute in the DOM. 3304 * 3305 * @method _setAttribute 3306 * @param ariaAttr 3307 * @protected 3308 */ 3309 _setAttribute: function(ariaAttr) { 3310 var instance = this; 3311 var host = instance.get('host'); 3312 var attrValue = host.get(ariaAttr.attrName); 3313 var attrNode = ariaAttr.node; 3314 3315 if (isFunction(attrNode)) { 3316 attrNode = attrNode.apply(instance, [ariaAttr]); 3317 } 3318 3319 instance.setAttribute( 3320 ariaAttr.ariaName, 3321 ariaAttr.format.apply(instance, [attrValue, ariaAttr]), 3322 attrNode 3323 ); 3324 }, 3325 3326 /** 3327 * Set the `roleName` attribute on the UI. 3328 * 3329 * @method _uiSetRoleName 3330 * @param val 3331 * @protected 3332 */ 3333 _uiSetRoleName: function(val) { 3334 var instance = this; 3335 3336 instance.setRole(val); 3337 } 3338 } 3339}); 3340 3341A.Plugin.Aria = Aria; 3342/** 3343 * Static property used to define [W3C's Roles Model](http://www.w3.org/TR/wai- 3344 * aria/roles). 3345 * 3346 * @property W3C_ROLES 3347 * @type Object 3348 * @static 3349 */ 3350A.Plugin.Aria.W3C_ROLES = { 3351 'alert': 1, 3352 'alertdialog': 1, 3353 'application': 1, 3354 'article': 1, 3355 'banner': 1, 3356 'button': 1, 3357 'checkbox': 1, 3358 'columnheader': 1, 3359 'combobox': 1, 3360 'command': 1, 3361 'complementary': 1, 3362 'composite': 1, 3363 'contentinfo': 1, 3364 'definition': 1, 3365 'dialog': 1, 3366 'directory': 1, 3367 'document': 1, 3368 'form': 1, 3369 'grid': 1, 3370 'gridcell': 1, 3371 'group': 1, 3372 'heading': 1, 3373 'img': 1, 3374 'input': 1, 3375 'landmark': 1, 3376 'link': 1, 3377 'list': 1, 3378 'listbox': 1, 3379 'listitem': 1, 3380 'log': 1, 3381 'main': 1, 3382 'marquee': 1, 3383 'math': 1, 3384 'menu': 1, 3385 'menubar': 1, 3386 'menuitem': 1, 3387 'menuitemcheckbox': 1, 3388 'menuitemradio': 1, 3389 'navigation': 1, 3390 'note': 1, 3391 'option': 1, 3392 'presentation': 1, 3393 'progressbar': 1, 3394 'radio': 1, 3395 'radiogroup': 1, 3396 'range': 1, 3397 'region': 1, 3398 'roletype': 1, 3399 'row': 1, 3400 'rowheader': 1, 3401 'scrollbar': 1, 3402 'search': 1, 3403 'section': 1, 3404 'sectionhead': 1, 3405 'select': 1, 3406 'separator': 1, 3407 'slider': 1, 3408 'spinbutton': 1, 3409 'status': 1, 3410 'structure': 1, 3411 'tab': 1, 3412 'tablist': 1, 3413 'tabpanel': 1, 3414 'textbox': 1, 3415 'timer': 1, 3416 'toolbar': 1, 3417 'tooltip': 1, 3418 'tree': 1, 3419 'treegrid': 1, 3420 'treeitem': 1, 3421 'widget': 1, 3422 'window': 1 3423}; 3424/**
3425 * Static property used to define [W3C's Supported States and 3426 * Properties](http://www.w3.org/TR/wai-aria/states_and_properties). 3427 * 3428 * @property W3C_ATTRIBUTES 3429 * @type Object 3430 * @static 3431 */ 3432A.Plugin.Aria.W3C_ATTRIBUTES = { 3433 'activedescendant': 1, 3434 'atomic': 1, 3435 'autocomplete': 1, 3436 'busy': 1, 3437 'checked': 1, 3438 'controls': 1, 3439 'describedby': 1, 3440 'disabled': 1, 3441 'dropeffect': 1, 3442 'expanded': 1, 3443 'flowto': 1, 3444 'grabbed': 1, 3445 'haspopup': 1, 3446 'hidden': 1, 3447 'invalid': 1, 3448 'label': 1, 3449 'labelledby': 1, 3450 'level': 1, 3451 'live': 1, 3452 'multiline': 1, 3453 'multiselectable': 1, 3454 'orientation': 1, 3455 'owns': 1, 3456 'posinset': 1, 3457 'pressed': 1, 3458 'readonly': 1, 3459 'relevant': 1, 3460 'required': 1, 3461 'selected': 1, 3462 'setsize': 1, 3463 'sort': 1, 3464 'valuemax': 1, 3465 'valuemin': 1, 3466 'valuenow': 1, 3467 'valuetext': 1 3468}; 3469 3470 3471}, '3.1.0-deprecated.52', {"requires": ["plugin", "aui-component"]}); 3472 3473YUI.add('aui-io-plugin-deprecated', function (A, NAME) { 3474 3475/** 3476 * The IOPlugin Utility - When plugged to a Node or Widget loads the content 3477 * of a URI and set as its content, parsing the <code>script</code> tags if 3478 * present on the code. 3479 * 3480 * @module aui-io 3481 * @submodule aui-io-plugin 3482 */ 3483 3484var L = A.Lang, 3485 isBoolean = L.isBoolean, 3486 isString = L.isString, 3487 3488 isNode = function(v) { 3489 return (v instanceof A.Node); 3490 }, 3491
3492 StdMod = A.WidgetStdMod, 3493 3494 TYPE_NODE = 'Node', 3495 TYPE_WIDGET = 'Widget', 3496 3497 EMPTY = '', 3498 FAILURE = 'failure', 3499 FAILURE_MESSAGE = 'failureMessage', 3500 HOST = 'host', 3501 ICON = 'icon', 3502 IO = 'io', 3503 IO_PLUGIN = 'IOPlugin', 3504 LOADING = 'loading', 3505 LOADING_MASK = 'loadingMask', 3506 NODE = 'node', 3507 OUTER = 'outer', 3508 PARSE_CONTENT = 'parseContent', 3509 QUEUE = 'queue', 3510 RENDERED = 'rendered', 3511 SECTION = 'section', 3512 SHOW_LOADING = 'showLoading', 3513 SUCCESS = 'success', 3514 TYPE = 'type', 3515 WHERE = 'where', 3516 3517 getCN = A.getClassName, 3518 3519 CSS_ICON_LOADING = getCN(ICON, LOADING); 3520 3521/** 3522 * A base class for IOPlugin, providing: 3523 * <ul> 3524 * <li>Loads the content of a URI as content of a Node or Widget</li> 3525 * <li>Use <a href="ParseContent.html">ParseContent</a> to parse the JavaScript tags from the content and evaluate them</li> 3526 * </ul> 3527 * 3528 * Quick Example:<br/> 3529 * 3530 * <pre><code>A.one('#content').plug(A.Plugin.IO, { uri: 'assets/content.html', method: 'GET' });</code></pre> 3531 * 3532 * Check the list of <a href="A.Plugin.IO.html#configattributes">Configuration Attributes</a> available for 3533 * IOPlugin. 3534 * 3535 * @param config {Object} Object literal specifying widget configuration properties. 3536 * 3537 * @class A.Plugin.IO 3538 * @constructor 3539 * @extends IORequest 3540 */ 3541var IOPlugin = A.Component.create({ 3542 /** 3543 * Static property provides a string to identify the class. 3544 * 3545 * @property A.Plugin.IO.NAME
3546 * @type String 3547 * @static 3548 */ 3549 NAME: IO_PLUGIN, 3550 3551 /** 3552 * Static property provides a string to identify the namespace. 3553 * 3554 * @property A.Plugin.IO.NS 3555 * @type String 3556 * @static 3557 */ 3558 NS: IO, 3559 3560 /** 3561 * Static property used to define the default attribute 3562 * configuration for the A.Plugin.IO. 3563 * 3564 * @property A.Plugin.IO.ATTRS 3565 * @type Object 3566 * @static 3567 */ 3568 ATTRS: { 3569 /** 3570 * Plug IO in any object we want, the setContent will use the node to 3571 * set the content. 3572 * 3573 * @attribute node 3574 * @default null 3575 * @type Node | String 3576 */ 3577 node: { 3578 value: null, 3579 getter: function(value) { 3580 var instance = this; 3581 3582 if (!value) { 3583 var host = instance.get(HOST); 3584 var type = instance.get(TYPE); 3585 3586 if (type == TYPE_NODE) { 3587 value = host; 3588 } 3589 else if (type == TYPE_WIDGET) { 3590 var section = instance.get(SECTION); 3591 3592 // if there is no node for the SECTION, forces creation 3593 if (!host.getStdModNode(section)) { 3594 host.setStdModContent(section, EMPTY); 3595 } 3596 3597 value = host.getStdModNode(section); 3598 } 3599 } 3600 3601 return A.one(value); 3602 }, 3603 validator: isNode 3604 }, 3605 3606 /** 3607 * Message to be set on the content when the transaction fails. 3608 * 3609 * @attribute failureMessage 3610 * @default 'Failed to retrieve content'
3611 * @type String 3612 */ 3613 failureMessage: { 3614 value: 'Failed to retrieve content', 3615 validator: isString 3616 }, 3617 3618 /** 3619 * Options passed to the <a href="LoadingMask.html">LoadingMask</a>. 3620 * 3621 * @attribute loadingMask 3622 * @default {} 3623 * @type Object 3624 */ 3625 loadingMask: { 3626 value: {} 3627 }, 3628 3629 /** 3630 * If true the <a href="ParseContent.html">ParseContent</a> plugin 3631 * will be plugged to the <a href="A.Plugin.IO.html#config_node">node</a>. 3632 * 3633 * @attribute parseContent 3634 * @default true 3635 * @type boolean 3636 */ 3637 parseContent: { 3638 value: true, 3639 validator: isBoolean 3640 }, 3641 3642 /** 3643 * Show the <a href="LoadingMask.html">LoadingMask</a> covering the <a 3644 * href="A.Plugin.IO.html#config_node">node</a> while loading. 3645 * 3646 * @attribute showLoading 3647 * @default true 3648 * @type boolean 3649 */ 3650 showLoading: { 3651 value: true, 3652 validator: isBoolean 3653 }, 3654 3655 /** 3656 * Section where the content will be set in case you are plugging it 3657 * on a instace of <a href="WidgetStdMod.html">WidgetStdMod</a>. 3658 * 3659 * @attribute section 3660 * @default StdMod.BODY
3661 * @type String 3662 */ 3663 section: { 3664 value: StdMod.BODY, 3665 validator: function(val) { 3666 return (!val || val == StdMod.BODY || val == StdMod.HEADER || val == StdMod.FOOTER); 3667 } 3668 }, 3669 3670 /** 3671 * Type of the <code>instance</code> we are pluggin the A.Plugin.IO. 3672 * Could be a Node, or a Widget. 3673 * 3674 * @attribute type 3675 * @default 'Node' 3676 * @readOnly 3677 * @type String 3678 */ 3679 type: { 3680 readOnly: true, 3681 valueFn: function() { 3682 var instance = this; 3683 // NOTE: default type 3684 var type = TYPE_NODE; 3685 3686 if (instance.get(HOST) instanceof A.Widget) { 3687 type = TYPE_WIDGET; 3688 } 3689 3690 return type; 3691 }, 3692 validator: isString 3693 }, 3694 3695 /** 3696 * Where to insert the content, AFTER, BEFORE or REPLACE. If you're plugging a Node, there is a fourth option called OUTER that will not only replace the entire node itself. This is different from REPLACE, in that REPLACE will replace the *contents* of the node, OUTER will replace the entire Node itself. 3697 * 3698 * @attribute where 3699 * @default StdMod.REPLACE
3700 * @type String 3701 */ 3702 where: { 3703 value: StdMod.REPLACE, 3704 validator: function(val) { 3705 return (!val || val == StdMod.AFTER || val == StdMod.BEFORE || val == StdMod.REPLACE || val == 3706 OUTER); 3707 } 3708 } 3709 }, 3710 3711 EXTENDS: A.IORequest, 3712 3713 prototype: { 3714 /** 3715 * Bind the events on the A.Plugin.IO UI. Lifecycle. 3716 * 3717 * @method bindUI 3718 * @protected 3719 */ 3720 bindUI: function() { 3721 var instance = this; 3722 3723 instance.on('activeChange', instance._onActiveChange); 3724 3725 instance.on(SUCCESS, instance._successHandler); 3726 instance.on(FAILURE, instance._failureHandler); 3727 3728 if ((instance.get(TYPE) == TYPE_WIDGET) && instance.get(SHOW_LOADING)) { 3729 var host = instance.get(HOST); 3730 3731 host.after('heightChange', instance._syncLoadingMaskUI, instance); 3732 host.after('widthChange', instance._syncLoadingMaskUI, instance); 3733 } 3734 }, 3735 3736 /** 3737 * Invoke the <code>start</code> method (autoLoad attribute). 3738 * 3739 * @method _autoStart 3740 * @protected 3741 */ 3742 _autoStart: function() { 3743 var instance = this; 3744 3745 instance.bindUI(); 3746 3747 IOPlugin.superclass._autoStart.apply(this, arguments); 3748 }, 3749 3750 /** 3751 * Bind the ParseContent plugin on the <code>instance</code>. 3752 * 3753 * @method _bindParseContent 3754 * @protected 3755 */ 3756 _bindParseContent: function() { 3757 var instance = this; 3758 var node = instance.get(NODE); 3759 3760 if (node && !node.ParseContent && instance.get(PARSE_CONTENT)) { 3761 node.plug(A.Plugin.ParseContent); 3762 } 3763 }, 3764 3765 /** 3766 * Invoke the <a href="OverlayMask.html#method_hide">OverlayMask hide</a> method. 3767 * 3768 * @method hideLoading 3769 */ 3770 hideLoading: function() { 3771 var instance = this; 3772 3773 var node = instance.get(NODE); 3774 3775 if (node.loadingmask) { 3776 node.loadingmask.hide(); 3777 } 3778 }, 3779 3780 /** 3781 * Set the content of the <a href="A.Plugin.IO.html#config_node">node</a>. 3782 * 3783 * @method setContent 3784 */ 3785 setContent: function(content) { 3786 var instance = this; 3787 3788 instance._bindParseContent(); 3789 3790 instance._getContentSetterByType().apply(instance, [content]); 3791 3792 if (instance.overlayMaskBoundingBox) { 3793 instance.overlayMaskBoundingBox.remove(); 3794 } 3795 }, 3796 3797 /** 3798 * Invoke the <a href="OverlayMask.html#method_show">OverlayMask show</a> method. 3799 * 3800 * @method showLoading 3801 */ 3802 showLoading: function() { 3803 var instance = this; 3804 var node = instance.get(NODE); 3805 3806 if (node.loadingmask) { 3807 if (instance.overlayMaskBoundingBox) { 3808 node.append(instance.overlayMaskBoundingBox); 3809 } 3810 } 3811 else { 3812 node.plug( 3813 A.LoadingMask, 3814 instance.get(LOADING_MASK) 3815 ); 3816 3817 instance.overlayMaskBoundingBox = node.loadingmask.overlayMask.get('boundingBox'); 3818 } 3819 3820 node.loadingmask.show(); 3821 }, 3822 3823 /** 3824 * Overload to the <a href="IORequest.html#method_start">IORequest 3825 * start</a> method. Check if the <code>host</code> is already rendered, 3826 * otherwise wait to after render phase and to show the LoadingMask. 3827 * 3828 * @method start 3829 */ 3830 start: function() { 3831 var instance = this; 3832 var host = instance.get(HOST); 3833 3834 if (!host.get(RENDERED)) { 3835 host.after('render', function() { 3836 instance._setLoadingUI(true); 3837 }); 3838 } 3839 3840 IOPlugin.superclass.start.apply(instance, arguments); 3841 }, 3842 3843 /** 3844 * Get the appropriated <a 3845 * href="A.Plugin.IO.html#method_setContent">setContent</a> function 3846 * implementation for each <a href="A.Plugin.IO.html#config_type">type</a>. 3847 * 3848 * @method _getContentSetterByType 3849 * @protected 3850 * @return {function} 3851 */ 3852 _getContentSetterByType: function() { 3853 var instance = this; 3854 3855 var setters = { 3856 // NOTE: default setter, see 'type' attribute definition 3857 Node: function(content) { 3858 var instance = this; 3859 // when this.get(HOST) is a Node instance the NODE is the host 3860 var node = instance.get(NODE); 3861 3862 if (content instanceof A.NodeList) { 3863 content = content.toFrag(); 3864 } 3865 3866 if (content instanceof A.Node) { 3867 content = content._node; 3868 } 3869 3870 var where = instance.get(WHERE); 3871 3872 if (where == OUTER) { 3873 node.replace(content); 3874 } 3875 else { 3876 node.insert(content, where); 3877 } 3878 }, 3879
3880 // Widget forces set the content on the SECTION node using setStdModContent method 3881 Widget: function(content) { 3882 var instance = this; 3883 var host = instance.get(HOST); 3884 3885 host.setStdModContent.apply(host, [ 3886 instance.get(SECTION), 3887 content, 3888 instance.get(WHERE) 3889 ]); 3890 } 3891 }; 3892 3893 return setters[this.get(TYPE)]; 3894 }, 3895 3896 /** 3897 * Whether the <code>show</code> is true show the LoadingMask. 3898 * 3899 * @method _setLoadingUI 3900 * @param {boolean} show 3901 * @protected 3902 */ 3903 _setLoadingUI: function(show) { 3904 var instance = this; 3905 3906 if (instance.get(SHOW_LOADING)) { 3907 if (show) { 3908 instance.showLoading(); 3909 } 3910 else { 3911 instance.hideLoading(); 3912 } 3913 } 3914 }, 3915 3916 /** 3917 * Sync the loading mask UI. 3918 * 3919 * @method _syncLoadingMaskUI 3920 * @protected 3921 */ 3922 _syncLoadingMaskUI: function() { 3923 var instance = this; 3924 3925 instance.get(NODE).loadingmask.refreshMask(); 3926 }, 3927 3928 /** 3929 * Internal success callback for the IO transaction. 3930 * 3931 * @method _successHandler 3932 * @param {EventFavade} event 3933 * @param {String} id Id of the IO transaction. 3934 * @param {Object} obj XHR transaction Object. 3935 * @protected 3936 */ 3937 _successHandler: function(event, id, xhr) { 3938 var instance = this; 3939 3940 instance.setContent( 3941 this.get('responseData') 3942 ); 3943 }, 3944 3945 /** 3946 * Internal failure callback for the IO transaction. 3947 * 3948 * @method _failureHandler 3949 * @param {EventFavade} event 3950 * @param {String} id Id of the IO transaction. 3951 * @param {Object} obj XHR transaction Object. 3952 * @protected 3953 */ 3954 _failureHandler: function(event, id, xhr) { 3955 var instance = this; 3956 3957 instance.setContent( 3958 instance.get(FAILURE_MESSAGE) 3959 ); 3960 }, 3961 3962 /** 3963 * Fires after the value of the 3964 * <a href="A.Plugin.IO.html#config_active">active</a> attribute change. 3965 * 3966 * @method _onActiveChange 3967 * @param {EventFacade} event 3968 * @protected 3969 */ 3970 _onActiveChange: function(event) { 3971 var instance = this; 3972 var host = instance.get(HOST); 3973 var widget = instance.get(TYPE) == TYPE_WIDGET; 3974 3975 if (!widget || (widget && host && host.get(RENDERED))) { 3976 instance._setLoadingUI(event.newVal); 3977 } 3978 } 3979 } 3980}); 3981 3982A.Node.prototype.load = function(uri, config, callback) { 3983 var instance = this; 3984 3985 var index = uri.indexOf(' '); 3986 var selector; 3987 3988 if (index > 0) { 3989 selector = uri.slice(index, uri.length); 3990 3991 uri = uri.slice(0, index); 3992 } 3993 3994 if (L.isFunction(config)) { 3995 callback = config; 3996 config = null; 3997 } 3998 3999 config = config || {}; 4000 4001 if (callback) { 4002 config.after = config.after || {}; 4003 4004 config.after.success = callback; 4005 } 4006 4007 var where = config.where; 4008 4009 config.uri = uri; 4010 config.where = where; 4011 4012 if (selector) { 4013 config.selector = selector; 4014 config.where = where || 'replace'; 4015 } 4016 4017 instance.plug(A.Plugin.IO, config); 4018 4019 return instance; 4020}; 4021 4022A.namespace('Plugin').IO = IOPlugin; 4023 4024 4025}, '3.1.0-deprecated.52', { 4026 "requires": [ 4027 "aui-overlay-base-deprecated", 4028 "aui-parse-content", 4029 "aui-io-request", 4030 "aui-loading-mask-deprecated" 4031 ] 4032}); 4033 4034YUI.add('aui-io-request', function (A, NAME) { 4035 4036/** 4037 * The IORequest Utility - Provides response data normalization for 'xml', 'json', 4038 * JavaScript and cache option. 4039 * 4040 * @module aui-io 4041 * @submodule aui-io-request 4042 */ 4043 4044var L = A.Lang, 4045 isBoolean = L.isBoolean, 4046 isFunction = L.isFunction, 4047 isString = L.isString, 4048 4049 defaults = A.namespace('config.io'), 4050 4051 getDefault = function(attr) { 4052 return function() { 4053 return defaults[attr]; 4054 }; 4055 }, 4056 4057 ACCEPTS = { 4058 all: '*/*', 4059 html: 'text/html', 4060 json: 'application/json, text/javascript', 4061 text: 'text/plain', 4062 xml: 'application/xml, text/xml' 4063 }; 4064 4065/** 4066 * A base class for IORequest, providing: 4067 * 4068 * - Response data normalization for XML, JSON, JavaScript 4069 * - Cache options 4070 * 4071 * Check the [live demo](http://alloyui.com/examples/io/). 4072 * 4073 * @class A.IORequest 4074 * @extends Plugin.Base 4075 * @param {Object} config Object literal specifying widget configuration 4076 * properties.
4077 * @uses io 4078 * @constructor 4079 * @include http://alloyui.com/examples/io/basic.js 4080 */ 4081var IORequest = A.Component.create({ 4082 /** 4083 * Static property provides a string to identify the class. 4084 * 4085 * @property NAME 4086 * @type String 4087 * @static 4088 */ 4089 NAME: 'IORequest', 4090 4091 /** 4092 * Static property used to define the default attribute 4093 * configuration for the IORequest. 4094 * 4095 * @property ATTRS 4096 * @type Object 4097 * @static 4098 */ 4099 ATTRS: { 4100 4101 /** 4102 * If `true` invoke the [start](A.IORequest.html#method_start) method 4103 * automatically, initializing the IO transaction. 4104 * 4105 * @attribute autoLoad 4106 * @default true 4107 * @type Boolean 4108 */ 4109 autoLoad: { 4110 value: true, 4111 validator: isBoolean 4112 }, 4113 4114 /** 4115 * If `false` the current timestamp will be appended to the 4116 * url, avoiding the url to be cached. 4117 * 4118 * @attribute cache 4119 * @default true 4120 * @type Boolean 4121 */ 4122 cache: { 4123 value: true, 4124 validator: isBoolean 4125 }, 4126 4127 /** 4128 * The type of the request (i.e., could be xml, json, javascript, text). 4129 * 4130 * @attribute dataType 4131 * @default null
4132 * @type String 4133 */ 4134 dataType: { 4135 setter: function(v) { 4136 return (v || '').toLowerCase(); 4137 }, 4138 value: null, 4139 validator: isString 4140 }, 4141 4142 /** 4143 * This is a normalized attribute for the response data. It's useful to 4144 * retrieve the correct type for the 4145 * [dataType](A.IORequest.html#attr_dataType) (i.e., in json requests 4146 * the `responseData`) is a JSONObject. 4147 * 4148 * @attribute responseData 4149 * @default null 4150 * @type String | JSONObject | XMLDocument 4151 */ 4152 responseData: { 4153 setter: function(v) { 4154 return this._setResponseData(v); 4155 }, 4156 value: null 4157 }, 4158 4159 /** 4160 * URI to be requested using AJAX. 4161 * 4162 * @attribute uri 4163 * @default null 4164 * @type String 4165 */ 4166 uri: { 4167 setter: function(v) { 4168 return this._parseURL(v); 4169 }, 4170 value: null, 4171 validator: isString 4172 }, 4173 4174 // User readOnly variables 4175 4176 /** 4177 * Whether the transaction is active or not. 4178 * 4179 * @attribute active 4180 * @default false 4181 * @type Boolean 4182 */ 4183 active: { 4184 value: false, 4185 validator: isBoolean 4186 }, 4187 4188 /** 4189 * Object containing all the [IO Configuration Attributes](A.io.html). 4190 * This Object is passed to the `A.io` internally. 4191 * 4192 * @attribute cfg 4193 * @default Object containing all the [IO Configuration 4194 * Attributes](A.io.html). 4195 * @readOnly
4196 * @type String 4197 */ 4198 cfg: { 4199 getter: function() { 4200 var instance = this; 4201 4202 // keep the current cfg object always synchronized with the 4203 // mapped public attributes when the user call .start() it 4204 // always retrieve the last set values for each mapped attr 4205 return { 4206 arguments: instance.get('arguments'), 4207 context: instance.get('context'), 4208 data: instance.getFormattedData(), 4209 form: instance.get('form'), 4210 headers: instance.get('headers'), 4211 method: instance.get('method'), 4212 on: { 4213 complete: A.bind(instance.fire, instance, 'complete'), 4214 end: A.bind(instance._end, instance), 4215 failure: A.bind(instance.fire, instance, 'failure'), 4216 start: A.bind(instance.fire, instance, 'start'), 4217 success: A.bind(instance._success, instance) 4218 }, 4219 sync: instance.get('sync'), 4220 timeout: instance.get('timeout'), 4221 xdr: instance.get('xdr') 4222 }; 4223 }, 4224 readOnly: true 4225 }, 4226 4227 /** 4228 * Stores the IO Object of the current transaction. 4229 * 4230 * @attribute transaction 4231 * @default null 4232 * @type Object 4233 */ 4234 transaction: { 4235 value: null 4236 }, 4237 4238 // Configuration Object mapping 4239 // To take advantages of the Attribute listeners of A.Base
4240 // See: http://yuilibrary.com/yui/docs/io/ 4241 4242 /** 4243 * See [IO 4244 * Configuration](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4245 * 4246 * @attribute arguments 4247 * @default Value mapped on YUI.AUI.defaults.io. 4248 * @type Object 4249 */ 4250 arguments: { 4251 valueFn: getDefault('arguments') 4252 }, 4253 4254 /** 4255 * See [IO 4256 * Configuration](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4257 * 4258 * @attribute context 4259 * @default Value mapped on YUI.AUI.defaults.io. 4260 * @type Object 4261 */ 4262 context: { 4263 valueFn: getDefault('context') 4264 }, 4265 4266 /** 4267 * See [IO 4268 * Configuration](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4269 * 4270 * @attribute data 4271 * @default Value mapped on YUI.AUI.defaults.io. 4272 * @type Object 4273 */ 4274 data: { 4275 valueFn: getDefault('data') 4276 }, 4277 4278 /** 4279 * See [IO
4280 * Configuration](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4281 * 4282 * @attribute form 4283 * @default Value mapped on YUI.AUI.defaults.io. 4284 * @type Object 4285 */ 4286 form: { 4287 valueFn: getDefault('form') 4288 }, 4289 4290 /** 4291 * Set the correct ACCEPT header based on the dataType. 4292 * 4293 * @attribute headers 4294 * @default Object 4295 * @type Object 4296 */ 4297 headers: { 4298 getter: function(value) { 4299 var header = []; 4300 var instance = this; 4301 var dataType = instance.get('dataType'); 4302 4303 if (dataType) { 4304 header.push( 4305 ACCEPTS[dataType] 4306 ); 4307 } 4308 4309 // always add *.* to the accept header 4310 header.push( 4311 ACCEPTS.all 4312 ); 4313 4314 return A.merge( 4315 value, { 4316 Accept: header.join(', ') 4317 } 4318 ); 4319 }, 4320 valueFn: getDefault('headers') 4321 }, 4322 4323 /** 4324 * See [IO
4325 * Configuration](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4326 * 4327 * @attribute method 4328 * @default Value mapped on YUI.AUI.defaults.io. 4329 * @type String 4330 */ 4331 method: { 4332 setter: function(val) { 4333 return val.toLowerCase(); 4334 }, 4335 valueFn: getDefault('method') 4336 }, 4337 4338 /** 4339 * A selector to be used to query against the response of the 4340 * request. Only works if the response is XML or HTML. 4341 * 4342 * @attribute selector 4343 * @default null 4344 * @type String 4345 */ 4346 selector: { 4347 value: null 4348 }, 4349 4350 /** 4351 * See [IO 4352 * Configuration](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4353 * 4354 * @attribute sync 4355 * @default Value mapped on YUI.AUI.defaults.io. 4356 * @type Boolean 4357 */ 4358 sync: { 4359 valueFn: getDefault('sync') 4360 }, 4361 4362 /** 4363 * See [IO
4364 * Configuration](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4365 * 4366 * @attribute timeout 4367 * @default Value mapped on YUI.AUI.defaults.io. 4368 * @type Number 4369 */ 4370 timeout: { 4371 valueFn: getDefault('timeout') 4372 }, 4373 4374 /** 4375 * See [IO 4376 * Configuration](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4377 * 4378 * @attribute xdr 4379 * @default Value mapped on YUI.AUI.defaults.io. 4380 * @type Object 4381 */ 4382 xdr: { 4383 valueFn: getDefault('xdr') 4384 } 4385 }, 4386 4387 /** 4388 * Static property used to define which component it extends. 4389 * 4390 * @property EXTENDS 4391 * @type Object 4392 * @static 4393 */ 4394 EXTENDS: A.Plugin.Base, 4395 4396 prototype: { 4397 4398 /** 4399 * Construction logic executed during IORequest instantiation. 4400 * Lifecycle. 4401 * 4402 * @method initializer 4403 * @param config 4404 * @protected 4405 */ 4406 init: function() { 4407 var instance = this; 4408 4409 IORequest.superclass.init.apply(this, arguments); 4410 4411 instance._autoStart(); 4412 }, 4413 4414 /** 4415 * Destructor lifecycle implementation for the `IORequest` class. 4416 * Purges events attached to the node (and all child nodes). 4417 * 4418 * @method destructor 4419 * @protected 4420 */ 4421 destructor: function() { 4422 var instance = this; 4423 4424 instance.stop(); 4425 4426 instance.set('transaction', null); 4427 }, 4428 4429 /** 4430 * Applies the `YUI.AUI.defaults.io.dataFormatter` if 4431 * defined and return the formatted data. 4432 * 4433 * @method getFormattedData 4434 * @return {String} 4435 */ 4436 getFormattedData: function() { 4437 var instance = this; 4438 var value = instance.get('data'); 4439 var dataFormatter = defaults.dataFormatter; 4440 4441 if (isFunction(dataFormatter)) { 4442 value = dataFormatter.call(instance, value); 4443 } 4444 4445 return value; 4446 }, 4447 4448 /** 4449 * Starts the IO transaction. Used to refresh the content also. 4450 * 4451 * @method start 4452 */ 4453 start: function() { 4454 var instance = this; 4455 4456 instance.destructor(); 4457 4458 instance.set('active', true); 4459 4460 var ioObj = instance._yuiIOObj; 4461 4462 if (!ioObj) { 4463 ioObj = new A.IO(); 4464 4465 instance._yuiIOObj = ioObj; 4466 } 4467 4468 var transaction = ioObj.send( 4469 instance.get('uri'), 4470 instance.get('cfg') 4471 ); 4472 4473 instance.set('transaction', transaction); 4474 }, 4475 4476 /** 4477 * Stops the IO transaction. 4478 * 4479 * @method stop 4480 */ 4481 stop: function() { 4482 var instance = this; 4483 var transaction = instance.get('transaction'); 4484 4485 if (transaction) { 4486 transaction.abort(); 4487 } 4488 }, 4489 4490 /** 4491 * Invoke the `start` method (autoLoad attribute). 4492 * 4493 * @method _autoStart 4494 * @protected 4495 */ 4496 _autoStart: function() { 4497 var instance = this; 4498 4499 if (instance.get('autoLoad')) { 4500 instance.start(); 4501 } 4502 }, 4503 4504 /** 4505 * Parse the [uri](A.IORequest.html#attr_uri) to add a 4506 * timestamp if [cache](A.IORequest.html#attr_cache) is 4507 * `true`. Also applies the `YUI.AUI.defaults.io.uriFormatter`. 4508 * 4509 * @method _parseURL 4510 * @param {String} url 4511 * @protected 4512 * @return {String} 4513 */ 4514 _parseURL: function(url) { 4515 var instance = this; 4516 var cache = instance.get('cache'); 4517 var method = instance.get('method'); 4518 4519 // reusing logic to add a timestamp on the url from jQuery 1.3.2 4520 if ((cache === false) && (method === 'get')) { 4521 var ts = +new Date(); 4522 // try replacing _= if it is there 4523 var ret = url.replace(/(\?|&)_=.*?(&|$)/, '$1_=' + ts + '$2'); 4524 // if nothing was replaced, add timestamp to the end 4525 url = ret + ((ret === url) ? (url.match(/\?/) ? '&' : '?') + '_=' + ts : ''); 4526 } 4527 4528 // formatting the URL with the default uriFormatter after the cache 4529 // timestamp was added 4530 var uriFormatter = defaults.uriFormatter; 4531 4532 if (isFunction(uriFormatter)) { 4533 url = uriFormatter.apply(instance, [url]); 4534 } 4535 4536 return url; 4537 }, 4538 4539 /** 4540 * Internal end callback for the IO transaction. 4541 * 4542 * @method _end 4543 * @param {Number} id ID of the IO transaction. 4544 * @param {Object} args Custom arguments, passed to the event handler.
4545 * See [IO](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4546 * @protected 4547 */ 4548 _end: function(id, args) { 4549 var instance = this; 4550 4551 instance.set('active', false); 4552 instance.set('transaction', null); 4553 4554 instance.fire('end', id, args); 4555 }, 4556 4557 /** 4558 * Internal success callback for the IO transaction. 4559 * 4560 * @method _success 4561 * @param {Number} id ID of the IO transaction. 4562 * @param {Object} obj IO transaction Object. 4563 * @param {Object} args Custom arguments, passed to the event handler. 4564 * See [IO](http://yuilibrary.com/yui/docs/io/#the-configuration-object). 4565 * @protected 4566 */ 4567 _success: function(id, obj, args) { 4568 var instance = this; 4569 4570 // update the responseData attribute with the new data from xhr 4571 instance.set('responseData', obj); 4572 4573 instance.fire('success', id, obj, args); 4574 }, 4575 4576 /** 4577 * Setter for [responseData](A.IORequest.html#attr_responseData). 4578 * 4579 * @method _setResponseData 4580 * @protected 4581 * @param {Object} xhr XHR Object. 4582 * @return {Object} 4583 */ 4584 _setResponseData: function(xhr) { 4585 var data = null; 4586 var instance = this; 4587 4588 if (xhr) { 4589 var dataType = instance.get('dataType'); 4590 var contentType = xhr.getResponseHeader('content-type') || ''; 4591 4592 // if the dataType or the content-type is XML... 4593 if ((dataType === 'xml') || 4594 (!dataType && contentType.indexOf('xml') >= 0)) { 4595 4596 // use responseXML 4597 data = xhr.responseXML; 4598 4599 // check if the XML was parsed correctly 4600 if (data.documentElement.tagName === 'parsererror') { 4601 throw 'Parser error: IO dataType is not correctly parsing'; 4602 } 4603 } 4604 else { 4605 // otherwise use the responseText 4606 data = xhr.responseText; 4607 } 4608 4609 // empty string is not a valid 'json', convert it to null 4610 if (data === '') { 4611 data = null; 4612 } 4613 4614 // trying to parse to JSON if dataType is a valid json 4615 if (dataType === 'json') { 4616 try { 4617 data = A.JSON.parse(data); 4618 } 4619 catch (e) { 4620 // throw 'Parser error: IO dataType is not correctly parsing'; 4621 } 4622 } 4623 else { 4624 var selector = instance.get('selector'); 4625 4626 if (data && selector) { 4627 var tempRoot; 4628 4629 if (data.documentElement) { 4630 tempRoot = A.one(data); 4631 } 4632 else { 4633 tempRoot = A.Node.create(data); 4634 } 4635 4636 data = tempRoot.all(selector); 4637 } 4638 } 4639 } 4640 4641 return data; 4642 } 4643 } 4644}); 4645 4646A.IORequest = IORequest; 4647 4648/** 4649 * Alloy IO extension 4650 * 4651 * @class A.io 4652 * @static 4653 */ 4654 4655/** 4656 * Static method to invoke the [IORequest](A.IORequest.html). 4657 * Likewise [IO](A.io.html). 4658 * 4659 * @method A.io.request 4660 * @for A.io 4661 * @param {String} uri URI to be requested. 4662 * @param {Object} config Configuration Object for the [IO](A.io.html). 4663 * @return {IORequest} 4664 */ 4665A.io.request = function(uri, config) { 4666 return new A.IORequest( 4667 A.merge(config, { 4668 uri: uri 4669 }) 4670 ); 4671}; 4672 4673 4674}, '3.1.0-deprecated.52', {"requires": ["io-base", "json", "plugin", "querystring-stringify", "aui-component"]}); 4675 4676YUI.add('aui-loading-mask-deprecated', function (A, NAME) { 4677 4678/** 4679 * The LoadingMask Utility 4680 * 4681 * @module aui-loading-mask 4682 */ 4683 4684var Lang = A.Lang, 4685 4686 BOUNDING_BOX = 'boundingBox', 4687 CONTENT_BOX = 'contentBox', 4688 HIDE = 'hide', 4689 HOST = 'host', 4690 MESSAGE_EL = 'messageEl', 4691 NAME = 'loadingmask', 4692 POSITION = 'position', 4693 SHOW = 'show', 4694 STATIC = 'static',
4695 STRINGS = 'strings', 4696 TARGET = 'target', 4697 TOGGLE = 'toggle', 4698 4699 getClassName = A.getClassName, 4700 4701 CSS_LOADINGMASK = getClassName(NAME), 4702 CSS_MASKED = getClassName(NAME, 'masked'), 4703 CSS_MASKED_RELATIVE = getClassName(NAME, 'masked', 'relative'), 4704 CSS_MESSAGE_LOADING = getClassName(NAME, 'message'), 4705 CSS_MESSAGE_LOADING_CONTENT = getClassName(NAME, 'message', 'content'), 4706 4707 TPL_MESSAGE_LOADING = '<div class="' + CSS_MESSAGE_LOADING + '"><div class="' + CSS_MESSAGE_LOADING_CONTENT + 4708 '">{0}</div></div>'; 4709 4710/** 4711 * <p><img src="assets/images/aui-loading-mask/main.png"/></p> 4712 * 4713 * A base class for LoadingMask, providing: 4714 * <ul> 4715 * <li>Cross browser mask functionality to cover an element or the entire page</li> 4716 * <li>Customizable mask (i.e., background, opacity)</li> 4717 * <li>Display a centered "loading" message on the masked node</li> 4718 * </ul> 4719 * 4720 * Quick Example:<br/> 4721 * 4722 * <pre><code>node.plug(A.LoadingMask, { background: '#000' });</code></pre> 4723 * 4724 * Check the list of <a href="LoadingMask.html#configattributes">Configuration Attributes</a> available for 4725 * LoadingMask. 4726 * 4727 * @param config {Object} Object literal specifying widget configuration properties. 4728 * 4729 * @class LoadingMask 4730 * @constructor 4731 * @extends Plugin.Base 4732 */ 4733var LoadingMask = A.Component.create({ 4734 4735 /** 4736 * Static property provides a string to identify the class. 4737 * 4738 * @property LoadingMask.NAME
4739 * @type String 4740 * @static 4741 */ 4742 NAME: NAME, 4743 4744 /** 4745 * Static property provides a string to identify the namespace. 4746 * 4747 * @property LoadingMask.NS 4748 * @type String 4749 * @static 4750 */ 4751 NS: NAME, 4752 4753 /** 4754 * Static property used to define the default attribute 4755 * configuration for the LoadingMask. 4756 * 4757 * @property LoadingMask.ATTRS 4758 * @type Object 4759 * @static 4760 */ 4761 ATTRS: { 4762 /** 4763 * Node element to display the message. 4764 * 4765 * @attribute messageEl 4766 * @default Generated HTML div element. 4767 * @type String 4768 */ 4769 messageEl: { 4770 valueFn: function(val) { 4771 var instance = this; 4772 var strings = instance.get(STRINGS); 4773 4774 return A.Node.create( 4775 Lang.sub(TPL_MESSAGE_LOADING, [strings.loading]) 4776 ); 4777 } 4778 }, 4779 4780 /** 4781 * Strings used on the LoadingMask. See 4782 * <a href="Widget.html#method_strings">strings</a>. 4783 * 4784 * @attribute strings 4785 * @default { loading: 'Loading…' } 4786 * @type Object 4787 */ 4788 strings: { 4789 value: { 4790 loading: 'Loading…' 4791 } 4792 }, 4793 4794 /** 4795 * Node where the mask will be positioned and re-dimensioned. 4796 * 4797 * @attribute target 4798 * @default null 4799 * @type Node | Widget 4800 */ 4801 target: { 4802 setter: function() { 4803 var instance = this; 4804 var target = instance.get(HOST); 4805 4806 if (target instanceof A.Widget) { 4807 target = target.get(CONTENT_BOX); 4808 } 4809 4810 return target; 4811 }, 4812 value: null 4813 } 4814 }, 4815 4816 EXTENDS: A.Plugin.Base, 4817 4818 prototype: { 4819 /** 4820 * Construction logic executed during LoadingMask instantiation. Lifecycle. 4821 * 4822 * @method initializer 4823 * @protected 4824 */ 4825 initializer: function(config) { 4826 var instance = this; 4827 4828 instance.IGNORED_ATTRS = A.merge({ 4829 host: true 4830 }, 4831 LoadingMask.ATTRS 4832 ); 4833 4834 instance.renderUI(); 4835 instance.bindUI(); 4836 4837 instance._createDynamicAttrs(config); 4838 }, 4839 4840 /** 4841 * Create the DOM structure for the LoadingMask. Lifecycle. 4842 * 4843 * @method renderUI 4844 * @protected 4845 */ 4846 renderUI: function() { 4847 var instance = this; 4848 var strings = instance.get(STRINGS); 4849 4850 instance._renderOverlayMask(); 4851 4852 instance.overlayMask.get(BOUNDING_BOX).append( 4853 instance.get(MESSAGE_EL) 4854 ); 4855 }, 4856 4857 /** 4858 * Bind the events on the LoadingMask UI. Lifecycle. 4859 * 4860 * @method bindUI 4861 * @protected 4862 */ 4863 bindUI: function() { 4864 var instance = this; 4865 4866 instance._bindOverlayMaskUI(); 4867 }, 4868 4869 destructor: function() { 4870 var instance = this; 4871 4872 instance.overlayMask.destroy(); 4873 4874 instance._visibleChangeHandle.detach(); 4875 }, 4876 4877 /** 4878 * Bind events to the 4879 * <a href="LoadingMask.html#property_overlayMask">overlayMask</a>. 4880 * 4881 * @method _bindOverlayMaskUI 4882 * @protected 4883 */ 4884 _bindOverlayMaskUI: function() { 4885 var instance = this; 4886 4887 instance._visibleChangeHandle = instance.overlayMask.after('visibleChange', instance._afterVisibleChange, instance); 4888 }, 4889 4890 /** 4891 * Center the 4892 * <a href="LoadingMask.html#config_messageEl">messageEl</a> with the 4893 * <a href="LoadingMask.html#config_target">target</a> node. 4894 * 4895 * @method centerMessage 4896 */ 4897 centerMessage: function() { 4898 var instance = this; 4899 4900 instance.get(MESSAGE_EL).center( 4901 instance.overlayMask.get(BOUNDING_BOX) 4902 ); 4903 }, 4904 4905 /** 4906 * Invoke the 4907 * <a href="LoadingMask.html#property_overlayMask">overlayMask</a> 4908 * <code>refreshMask</code> method. 4909 * 4910 * @method refreshMask 4911 */ 4912 refreshMask: function() { 4913 var instance = this; 4914 4915 instance.overlayMask.refreshMask(); 4916 4917 instance.centerMessage(); 4918 }, 4919 4920 /** 4921 * Fires after the value of the 4922 * <a href="LoadingMask.html#config_visible">visible</a> attribute change. 4923 * 4924 * @method _afterVisibleChange 4925 * @param {EventFacade} event 4926 * @protected 4927 */ 4928 _afterVisibleChange: function(event) { 4929 var instance = this; 4930 var target = instance.get(TARGET); 4931 var isStaticPositioned = (target.getStyle(POSITION) == STATIC); 4932 4933 target.toggleClass(CSS_MASKED, (event.newVal)); 4934 target.toggleClass(CSS_MASKED_RELATIVE, (event.newVal && isStaticPositioned)); 4935 4936 if (event.newVal) { 4937 instance.refreshMask(); 4938 } 4939 }, 4940 4941 /**
4942 * Render 4943 * <a href="LoadingMask.html#property_overlayMask">overlayMask</a> 4944 * instance. 4945 * 4946 * @method _renderOverlayMask 4947 * @protected 4948 */ 4949 _renderOverlayMask: function() { 4950 var instance = this; 4951 var target = instance.get(TARGET); 4952 4953 /** 4954 * Stores the <a href="OverlayMask.html">OverlayMask</a> used 4955 * internally. 4956 * 4957 * @property overlayMask 4958 * @type OverlayMask 4959 * @protected 4960 */ 4961 instance.overlayMask = new A.OverlayMask({ 4962 target: target, 4963 cssClass: CSS_LOADINGMASK 4964 }).render(target); 4965 }, 4966 4967 /** 4968 * Create dynamic attributes listeners to invoke the setter on 4969 * <a href="LoadingMask.html#property_overlayMask">overlayMask</a> after 4970 * the attribute is set on the LoadingMask instance. 4971 * 4972 * @method _createDynamicAttrs 4973 * @param {Object} config Object literal specifying widget configuration properties. 4974 * @protected 4975 */ 4976 _createDynamicAttrs: function(config) { 4977 var instance = this; 4978 4979 A.each(config, function(value, key) { 4980 var ignoredAttr = instance.IGNORED_ATTRS[key]; 4981 4982 if (!ignoredAttr) { 4983 instance.addAttr(key, { 4984 setter: function(val) { 4985 this.overlayMask.set(key, val); 4986 4987 return val; 4988 }, 4989 value: value 4990 }); 4991 } 4992 }); 4993 } 4994 } 4995}); 4996 4997A.each([HIDE, SHOW, TOGGLE], function(method) { 4998 /** 4999 * Invoke the 5000 * <a href="LoadingMask.html#property_overlayMask">overlayMask</a> 5001 * <code>hide</code> method. 5002 * 5003 * @method hide 5004 */ 5005 5006 /** 5007 * Invoke the 5008 * <a href="LoadingMask.html#property_overlayMask">overlayMask</a> 5009 * <code>show</code> method. 5010 * 5011 * @method show 5012 */ 5013 5014 /** 5015 * Invoke the 5016 * <a href="LoadingMask.html#property_overlayMask">overlayMask</a> 5017 * <code>toggle</code> method. 5018 * 5019 * @method toggle 5020 */ 5021 LoadingMask.prototype[method] = function() { 5022 this.overlayMask[method](); 5023 }; 5024}); 5025 5026A.LoadingMask = LoadingMask; 5027 5028 5029}, '3.1.0-deprecated.52', {"requires": ["plugin", "aui-overlay-mask-deprecated"], "skinnable": true}); 5030 5031YUI.add('aui-overlay-base-deprecated', function (A, NAME) { 5032 5033/** 5034 * Provides a basic Overlay widget, with Standard Module content support. The Overlay widget 5035 * provides Page XY positioning support, alignment and centering support along with basic 5036 * stackable support (z-index and shimming). 5037 * 5038 * @module aui-overlay 5039 * @submodule aui-overlay-base 5040 */ 5041 5042/** 5043 * A basic Overlay Widget, which can be positioned based on Page XY co-ordinates and is stackable (z-index support). 5044 * It also provides alignment and centering support and uses a standard module format for it's content, with header, 5045 * body and footer section support. 5046 * 5047 * @class OverlayBase 5048 * @constructor 5049 * @extends Component 5050 * @uses WidgetStdMod 5051 * @uses WidgetPosition 5052 * @uses WidgetStack 5053 * @uses WidgetPositionAlign 5054 * @uses WidgetPositionConstrain 5055 * @param {Object} object The user configuration for the instance. 5056 */ 5057A.OverlayBase = A.Component.create({ 5058 NAME: 'overlay', 5059 ATTRS: { 5060 hideClass: { 5061 value: false 5062 } 5063 }, 5064 AUGMENTS: [A.WidgetPosition, A.WidgetStack, A.WidgetPositionAlign, A.WidgetPositionConstrain, A.WidgetStdMod] 5065}); 5066 5067 5068}, '3.1.0-deprecated.52', { 5069 "requires": [ 5070 "widget-position", 5071 "widget-stack", 5072 "widget-position-align", 5073 "widget-position-constrain", 5074 "widget-stdmod", 5075 "aui-component" 5076 ] 5077}); 5078 5079YUI.add('aui-overlay-context-deprecated', function (A, NAME) { 5080 5081/** 5082 * The OverlayContext Utility 5083 * 5084 * @module aui-overlay 5085 * @submodule aui-overlay-context 5086 */ 5087 5088var L = A.Lang, 5089 isString = L.isString, 5090 isNumber = L.isNumber, 5091 isObject = L.isObject, 5092 isBoolean = L.isBoolean, 5093 5094 isNodeList = function(v) { 5095 return (v instanceof A.NodeList); 5096 }, 5097 5098 ALIGN = 'align', 5099 BL = 'bl', 5100 BOUNDING_BOX = 'boundingBox', 5101 CANCELLABLE_HIDE = 'cancellableHide', 5102 OVERLAY_CONTEXT = 'overlaycontext', 5103 CURRENT_NODE = 'currentNode', 5104 FOCUSED = 'focused', 5105 HIDE = 'hide', 5106 HIDE_DELAY = 'hideDelay',
5107 HIDE_ON = 'hideOn', 5108 HIDE_ON_DOCUMENT_CLICK = 'hideOnDocumentClick', 5109 MOUSEDOWN = 'mousedown', 5110 SHOW = 'show', 5111 SHOW_DELAY = 'showDelay', 5112 SHOW_ON = 'showOn', 5113 TL = 'tl', 5114 TRIGGER = 'trigger', 5115 USE_ARIA = 'useARIA', 5116 VISIBLE = 'visible'; 5117 5118/** 5119 * <p><img src="assets/images/aui-overlay-context/main.png"/></p> 5120 * 5121 * A base class for OverlayContext, providing: 5122 * <ul> 5123 * <li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li> 5124 * <li>Able to display an <a href="Overlay.html">Overlay</a> at a specified corner of an element <a href="OverlayContext.html#config_trigger">trigger</a></li> 5125 * </ul> 5126 * 5127 * Quick Example:<br/> 5128 * 5129 * <pre><code>var instance = new A.OverlayContext({ 5130 * boundingBox: '#OverlayBoundingBox', 5131 * hideOn: 'mouseleave', 5132 * showOn: 'mouseenter', 5133 * trigger: '.menu-trigger' 5134 * }).render(); 5135 * </code></pre> 5136 * 5137 * Check the list of <a href="OverlayContext.html#configattributes">Configuration Attributes</a> available for 5138 * OverlayContext. 5139 * 5140 * @class OverlayContext 5141 * @constructor 5142 * @extends OverlayBase 5143 * @param config {Object} Object literal specifying widget configuration properties. 5144 */ 5145var OverlayContext = A.Component.create({ 5146 /** 5147 * Static property provides a string to identify the class. 5148 * 5149 * @property OverlayContext.NAME
5150 * @type String 5151 * @static 5152 */ 5153 NAME: OVERLAY_CONTEXT, 5154 5155 /** 5156 * Static property used to define the default attribute 5157 * configuration for the OverlayContext. 5158 * 5159 * @property OverlayContext.ATTRS 5160 * @type Object 5161 * @static 5162 */ 5163 ATTRS: { 5164 /** 5165 * Inherited from <a href="Overlay.html#config_align">Overlay</a>. 5166 * 5167 * @attribute align 5168 * @default { node: null, points: [ TL, BL ] } 5169 * @type Object 5170 */ 5171 align: { 5172 value: { 5173 node: null, 5174 points: [TL, BL] 5175 } 5176 }, 5177 5178 /** 5179 * Cancel auto hide delay if the user interact with the Overlay 5180 * (focus, click, mouseover) 5181 * 5182 * @attribute cancellableHide 5183 * @default true 5184 * @type boolean 5185 */ 5186 cancellableHide: { 5187 value: true, 5188 validator: isBoolean 5189 }, 5190 5191 /** 5192 * OverlayContext allow multiple elements to be the 5193 * <a href="OverlayContext.html#config_trigger">trigger</a>, the 5194 * currentNode stores the current active one. 5195 * 5196 * @attribute currentNode 5197 * @default First item of the 5198 * <a href="OverlayContext.html#config_trigger">trigger</a> NodeList. 5199 * @type Node 5200 */ 5201 currentNode: { 5202 valueFn: function() { 5203 // define default currentNode as the first item from trigger 5204 return this.get(TRIGGER).item(0); 5205 } 5206 }, 5207 5208 delay: { 5209 value: null, 5210 validator: isObject 5211 }, 5212 5213 /** 5214 * The event which is responsible to hide the OverlayContext. 5215 * 5216 * @attribute hideOn 5217 * @default mouseout
5218 * @type String 5219 */ 5220 hideOn: { 5221 lazyAdd: false, 5222 value: 'mouseout', 5223 setter: function(v) { 5224 return this._setHideOn(v); 5225 } 5226 }, 5227 5228 /** 5229 * If true the instance is registered on the 5230 * <a href="OverlayContextManager.html">OverlayContextManager</a> static 5231 * class and will be hide when the user click on document. 5232 * 5233 * @attribute hideOnDocumentClick 5234 * @default true 5235 * @type boolean 5236 */ 5237 hideOnDocumentClick: { 5238 lazyAdd: false, 5239 setter: function(v) { 5240 return this._setHideOnDocumentClick(v); 5241 }, 5242 value: true, 5243 validator: isBoolean 5244 }, 5245 5246 /** 5247 * Number of milliseconds after the hide method is invoked to hide the 5248 * OverlayContext. 5249 * 5250 * @attribute hideDelay 5251 * @default 0 5252 * @type Number 5253 */ 5254 hideDelay: { 5255 lazyAdd: false, 5256 setter: '_setHideDelay', 5257 value: 0, 5258 validator: isNumber 5259 }, 5260 5261 /** 5262 * The event which is responsible to show the OverlayContext. 5263 * 5264 * @attribute showOn 5265 * @default mouseover
5266 * @type String 5267 */ 5268 showOn: { 5269 lazyAdd: false, 5270 value: 'mouseover', 5271 setter: function(v) { 5272 return this._setShowOn(v); 5273 } 5274 }, 5275 5276 /** 5277 * Number of milliseconds after the show method is invoked to show the 5278 * OverlayContext. 5279 * 5280 * @attribute showDelay 5281 * @default 0 5282 * @type Number 5283 */ 5284 showDelay: { 5285 lazyAdd: false, 5286 setter: '_setShowDelay', 5287 value: 0, 5288 validator: isNumber 5289 }, 5290 5291 /** 5292 * Node, NodeList or Selector which will be used as trigger elements 5293 * to show or hide the OverlayContext. 5294 * 5295 * @attribute trigger 5296 * @default null 5297 * @type {Node | NodeList | String} 5298 */ 5299 trigger: { 5300 lazyAdd: false, 5301 setter: function(v) { 5302 if (isNodeList(v)) { 5303 return v; 5304 } 5305 else if (isString(v)) { 5306 return A.all(v); 5307 } 5308 5309 return new A.NodeList([v]); 5310 } 5311 }, 5312 5313 /** 5314 * True if Overlay should use ARIA plugin 5315 * 5316 * @attribute useARIA 5317 * @default true 5318 * @type Boolean 5319 */ 5320 useARIA: { 5321 value: true 5322 }, 5323 5324 /** 5325 * If true the OverlayContext is visible by default after the render phase. 5326 * Inherited from <a href="Overlay.html">Overlay</a>. 5327 * 5328 * @attribute visible 5329 * @default false 5330 * @type boolean 5331 */ 5332 visible: { 5333 value: false 5334 } 5335 }, 5336 5337 EXTENDS: A.OverlayBase, 5338 5339 constructor: function(config) { 5340 var instance = this; 5341 5342 instance._showCallback = null; 5343 instance._hideCallback = null; 5344 5345 OverlayContext.superclass.constructor.apply(this, arguments); 5346 }, 5347 5348 prototype: { 5349 /** 5350 * Construction logic executed during OverlayContext instantiation. Lifecycle. 5351 * 5352 * @method initializer 5353 * @protected 5354 */ 5355 initializer: function() { 5356 var instance = this; 5357 5358 var trigger = instance.get(TRIGGER); 5359 5360 if (trigger && trigger.size()) { 5361 instance.set('align.node', trigger.item(0)); 5362 } 5363 }, 5364 5365 /** 5366 * Bind the events on the OverlayContext UI. Lifecycle. 5367 * 5368 * @method bindUI 5369 * @protected 5370 */ 5371 bindUI: function() { 5372 var instance = this; 5373 var boundingBox = instance.get(BOUNDING_BOX); 5374 5375 boundingBox.on(MOUSEDOWN, instance._stopTriggerEventPropagation); 5376 5377 instance.before('triggerChange', instance._beforeTriggerChange); 5378 instance.before('showOnChange', instance._beforeShowOnChange); 5379 instance.before('hideOnChange', instance._beforeHideOnChange); 5380 5381 instance.after('triggerChange', instance._afterTriggerChange); 5382 instance.after('showOnChange', instance._afterShowOnChange); 5383 instance.after('hideOnChange', instance._afterHideOnChange); 5384 5385 boundingBox.on('click', A.bind(instance._cancelAutoHide, instance)); 5386 boundingBox.on('mouseenter', A.bind(instance._cancelAutoHide, instance)); 5387 boundingBox.on('mouseleave', A.bind(instance._invokeHideTaskOnInteraction, instance)); 5388 instance.after('focusedChange', A.bind(instance._invokeHideTaskOnInteraction, instance)); 5389 5390 instance.on('visibleChange', instance._onVisibleChangeOverlayContext); 5391 }, 5392 5393 /** 5394 * Hides the OverlayContext. 5395 * 5396 * @method hide 5397 */ 5398 hide: function() { 5399 var instance = this; 5400 5401 instance.clearIntervals(); 5402 5403 instance.fire('hide'); 5404 5405 OverlayContext.superclass.hide.apply(instance, arguments); 5406 }, 5407 5408 /** 5409 * Shows the OverlayContext. 5410 * 5411 * @method hide 5412 */ 5413 show: function(event) { 5414 var instance = this; 5415 5416 instance.clearIntervals(); 5417 5418 instance.updateCurrentNode(event); 5419 5420 instance.fire('show'); 5421 5422 OverlayContext.superclass.show.apply(instance, arguments); 5423 5424 instance.refreshAlign(); 5425 }, 5426 5427 /** 5428 * Refreshes the rendered UI, based on Widget State 5429 * 5430 * @method syncUI 5431 * @protected 5432 * 5433 */ 5434 syncUI: function() { 5435 var instance = this; 5436 5437 if (instance.get(USE_ARIA)) { 5438 instance.plug(A.Plugin.Aria, { 5439 attributes: { 5440 trigger: { 5441 ariaName: 'controls', 5442 format: function(value) { 5443 var id = instance.get(BOUNDING_BOX).generateID(); 5444 5445 return id; 5446 }, 5447 node: function() { 5448 return instance.get(TRIGGER); 5449 } 5450 }, 5451 visible: { 5452 ariaName: 'hidden', 5453 format: function(value) { 5454 return !value; 5455 } 5456 } 5457 }, 5458 roleName: 'dialog' 5459 }); 5460 } 5461 }, 5462 5463 /** 5464 * Toggles visibility of the OverlayContext. 5465 * 5466 * @method toggle 5467 * @param {EventFacade} event 5468 */ 5469 toggle: function(event) { 5470 var instance = this; 5471 5472 if (instance.get(VISIBLE)) { 5473 instance._hideTask(event); 5474 } 5475 else { 5476 instance._showTask(event); 5477 } 5478 }, 5479 5480 /**
5481 * Clear the intervals to show or hide the OverlayContext. See 5482 * <a href="OverlayContext.html#config_hideDelay">hideDelay</a> and 5483 * <a href="OverlayContext.html#config_showDelay">showDelay</a>. 5484 * 5485 * @method clearIntervals 5486 */ 5487 clearIntervals: function() { 5488 this._hideTask.cancel(); 5489 this._showTask.cancel(); 5490 }, 5491 5492 /** 5493 * Refreshes the alignment of the OverlayContext with the 5494 * <a href="OverlayContext.html#config_currentNode">currentNode</a>. See 5495 * also <a href="OverlayContext.html#config_align">align</a>. 5496 * 5497 * @method refreshAlign 5498 */ 5499 refreshAlign: function() { 5500 var instance = this; 5501 var align = instance.get(ALIGN); 5502 var currentNode = instance.get(CURRENT_NODE); 5503 5504 if (currentNode) { 5505 instance._uiSetAlign(currentNode, align.points); 5506 } 5507 }, 5508 5509 /** 5510 * Update the 5511 * <a href="OverlayContext.html#config_currentNode">currentNode</a> with the 5512 * <a href="OverlayContext.html#config_align">align</a> node or the 5513 * event.currentTarget and in last case with the first item of the 5514 * <a href="OverlayContext.html#config_trigger">trigger</a>. 5515 * 5516 * @method updateCurrentNode 5517 * @param {EventFacade} event 5518 */ 5519 updateCurrentNode: function(event) { 5520 var instance = this; 5521 var align = instance.get(ALIGN); 5522 var trigger = instance.get(TRIGGER); 5523 var currentTarget = null; 5524 5525 if (event) { 5526 currentTarget = event.currentTarget; 5527 } 5528 5529 var node = currentTarget || trigger.item(0) || align.node; 5530 5531 if (node) { 5532 instance.set(CURRENT_NODE, node); 5533 } 5534 }, 5535 5536 /** 5537 * Handles the logic for the 5538 * <a href="OverlayContext.html#method_toggle">toggle</a>. 5539 * 5540 * @method _toggle 5541 * @param {EventFacade} event 5542 * @protected 5543 */ 5544 _toggle: function(event) { 5545 var instance = this; 5546 5547 if (instance.get('disabled')) { 5548 return; 5549 } 5550 5551 var currentTarget = event.currentTarget; 5552 5553 // check if the target is different and simulate a .hide() before toggle 5554 if (instance._lastTarget != currentTarget) { 5555 instance.hide(); 5556 } 5557 5558 instance.toggle(event); 5559 5560 event.stopPropagation(); 5561 5562 instance._lastTarget = currentTarget; 5563 }, 5564 5565 /** 5566 * Fires after the <a href="OverlayContext.html#config_showOn">showOn</a> 5567 * attribute change. 5568 * 5569 * @method _afterShowOnChange 5570 * @param {EventFacade} event 5571 * @protected 5572 */ 5573 _afterShowOnChange: function(event) { 5574 var instance = this; 5575 var wasToggle = event.prevVal == instance.get(HIDE_ON); 5576 5577 if (wasToggle) { 5578 var trigger = instance.get(TRIGGER); 5579 5580 // if wasToggle remove the toggle callback 5581 trigger.detach(event.prevVal, instance._hideCallback); 5582 // and re attach the hide event 5583 instance._setHideOn(instance.get(HIDE_ON)); 5584 } 5585 }, 5586 5587 /** 5588 * Fires after the <a href="OverlayContext.html#config_hideOn">hideOn</a> 5589 * attribute change. 5590 * 5591 * @method _afterHideOnChange 5592 * @param {EventFacade} event 5593 * @protected 5594 */ 5595 _afterHideOnChange: function(event) { 5596 var instance = this; 5597 var wasToggle = event.prevVal == instance.get(SHOW_ON); 5598 5599 if (wasToggle) { 5600 var trigger = instance.get(TRIGGER); 5601 5602 // if wasToggle remove the toggle callback 5603 trigger.detach(event.prevVal, instance._showCallback); 5604 // and re attach the show event 5605 instance._setShowOn(instance.get(SHOW_ON)); 5606 } 5607 }, 5608 5609 /** 5610 * Fires after the <a href="OverlayContext.html#config_trigger">trigger</a> 5611 * attribute change. 5612 * 5613 * @method _afterTriggerChange 5614 * @param {EventFacade} event 5615 * @protected 5616 */ 5617 _afterTriggerChange: function(event) { 5618 var instance = this; 5619 5620 instance._setShowOn(instance.get(SHOW_ON)); 5621 instance._setHideOn(instance.get(HIDE_ON)); 5622 }, 5623 5624 /** 5625 * Fires before the <a href="OverlayContext.html#config_showOn">showOn</a> 5626 * attribute change. 5627 * 5628 * @method _beforeShowOnChange 5629 * @param {EventFacade} event 5630 * @protected 5631 */ 5632 _beforeShowOnChange: function(event) { 5633 var instance = this; 5634 var trigger = instance.get(TRIGGER); 5635 5636 // detach the old callback 5637 trigger.detach(event.prevVal, instance._showCallback); 5638 }, 5639 5640 /** 5641 * Fires before the <a href="OverlayContext.html#config_hideOn">hideOn</a> 5642 * attribute change. 5643 * 5644 * @method _beforeHideOnChange 5645 * @param {EventFacade} event 5646 * @protected 5647 */ 5648 _beforeHideOnChange: function(event) { 5649 var instance = this; 5650 var trigger = instance.get(TRIGGER); 5651 5652 // detach the old callback 5653 trigger.detach(event.prevVal, instance._hideCallback); 5654 }, 5655 5656 /** 5657 * Fires before the <a href="OverlayContext.html#config_trigger">trigger</a> 5658 * attribute change. 5659 * 5660 * @method _beforeTriggerChange 5661 * @param {EventFacade} event 5662 * @protected 5663 */ 5664 _beforeTriggerChange: function(event) { 5665 var instance = this; 5666 var trigger = instance.get(TRIGGER); 5667 var showOn = instance.get(SHOW_ON); 5668 var hideOn = instance.get(HIDE_ON); 5669 5670 trigger.detach(showOn, instance._showCallback); 5671 trigger.detach(hideOn, instance._hideCallback); 5672 trigger.detach(MOUSEDOWN, instance._stopTriggerEventPropagation); 5673 }, 5674 5675 /** 5676 * Cancel hide event if the user does some interaction with the 5677 * OverlayContext (focus, click or mouseover). 5678 *
5679 * @method _cancelAutoHide 5680 * @param {EventFacade} event 5681 * @protected 5682 */ 5683 _cancelAutoHide: function(event) { 5684 var instance = this; 5685 5686 if (instance.get(CANCELLABLE_HIDE)) { 5687 instance.clearIntervals(); 5688 } 5689 5690 event.stopPropagation(); 5691 }, 5692 5693 /** 5694 * Invoke the hide event when the OverlayContext looses the focus. 5695 * 5696 * @method _invokeHideTaskOnInteraction 5697 * @param {EventFacade} event 5698 * @protected 5699 */ 5700 _invokeHideTaskOnInteraction: function(event) { 5701 var instance = this; 5702 var cancellableHide = instance.get(CANCELLABLE_HIDE); 5703 var focused = instance.get(FOCUSED); 5704 5705 if (!focused && !cancellableHide) { 5706 instance._hideTask(); 5707 } 5708 }, 5709 5710 /** 5711 * Fires when the <a href="OverlayContext.html#config_visible">visible</a> 5712 * attribute changes. 5713 * 5714 * @method _onVisibleChangeOverlayContext 5715 * @param {EventFacade} event 5716 * @protected 5717 */ 5718 _onVisibleChangeOverlayContext: function(event) { 5719 var instance = this; 5720 5721 if (event.newVal && instance.get('disabled')) { 5722 event.preventDefault(); 5723 } 5724 }, 5725 5726 /** 5727 * Helper method to invoke event.stopPropagation(). 5728 * 5729 * @method _stopTriggerEventPropagation 5730 * @param {EventFacade} event 5731 * @protected 5732 */ 5733 _stopTriggerEventPropagation: function(event) { 5734 event.stopPropagation(); 5735 }, 5736 5737 /** 5738 * Setter for the 5739 * <a href="OverlayContext.html#config_hideDelay">hideDelay</a> 5740 * attribute. 5741 * 5742 * @method _setHideDelay 5743 * @param {number} val 5744 * @protected 5745 * @return {number} 5746 */ 5747 _setHideDelay: function(val) { 5748 var instance = this; 5749 5750 instance._hideTask = A.debounce(instance.hide, val, instance); 5751 5752 return val; 5753 }, 5754 5755 /** 5756 * Setter for the <a href="OverlayContext.html#config_hideOn">hideOn</a> 5757 * attribute. 5758 * 5759 * @method _setHideOn 5760 * @param {String} eventType Event type 5761 * @protected 5762 * @return {String} 5763 */ 5764 _setHideOn: function(eventType) { 5765 var instance = this; 5766 var trigger = instance.get(TRIGGER); 5767 var toggle = eventType == instance.get(SHOW_ON); 5768 5769 if (toggle) { 5770 instance._hideCallback = A.bind(instance._toggle, instance); 5771 5772 // only one attached event is enough for toggle 5773 trigger.detach(eventType, instance._showCallback); 5774 } 5775 else { 5776 var delay = instance.get(HIDE_DELAY); 5777 5778 instance._hideCallback = function(event) { 5779 instance._hideTask(event); 5780 5781 event.stopPropagation(); 5782 }; 5783 } 5784 5785 trigger.on(eventType, instance._hideCallback); 5786 5787 return eventType; 5788 }, 5789 5790 /** 5791 * Setter for the 5792 * <a href="OverlayContext.html#config_hideOnDocumentClick">hideOnDocumentClick</a> 5793 * attribute. 5794 * 5795 * @method _setHideOn 5796 * @param {boolean} value 5797 * @protected 5798 * @return {boolean} 5799 */ 5800 _setHideOnDocumentClick: function(value) { 5801 var instance = this; 5802 5803 if (value) { 5804 A.OverlayContextManager.register(instance); 5805 } 5806 else { 5807 A.OverlayContextManager.remove(instance); 5808 } 5809 5810 return value; 5811 }, 5812 5813 /** 5814 * Setter for the 5815 * <a href="OverlayContext.html#config_showDelay">showDelay</a> 5816 * attribute. 5817 * 5818 * @method _setShowDelay 5819 * @param {number} val 5820 * @protected 5821 * @return {number} 5822 */ 5823 _setShowDelay: function(val) { 5824 var instance = this; 5825 5826 instance._showTask = A.debounce(instance.show, val, instance); 5827 5828 return val; 5829 }, 5830 5831 /** 5832 * Setter for the <a href="OverlayContext.html#config_showOn">showOn</a> 5833 * attribute. 5834 * 5835 * @method _setShowOn 5836 * @param {String} eventType Event type 5837 * @protected 5838 * @return {String} 5839 */ 5840 _setShowOn: function(eventType) { 5841 var instance = this; 5842 var trigger = instance.get(TRIGGER); 5843 var toggle = eventType == instance.get(HIDE_ON); 5844 5845 if (toggle) { 5846 instance._showCallback = A.bind(instance._toggle, instance); 5847 5848 // only one attached event is enough for toggle 5849 trigger.detach(eventType, instance._hideCallback); 5850 } 5851 else {
5852 var delay = instance.get(SHOW_DELAY); 5853 5854 instance._showCallback = function(event) { 5855 instance._showTask(event); 5856 5857 event.stopPropagation(); 5858 }; 5859 } 5860 5861 if (eventType != MOUSEDOWN) { 5862 trigger.on(MOUSEDOWN, instance._stopTriggerEventPropagation); 5863 } 5864 else { 5865 trigger.detach(MOUSEDOWN, instance._stopTriggerEventPropagation); 5866 } 5867 5868 trigger.on(eventType, instance._showCallback); 5869 5870 return eventType; 5871 } 5872 } 5873}); 5874 5875A.OverlayContext = OverlayContext; 5876 5877/** 5878 * A base class for OverlayContextManager: 5879 * 5880 * @param config {Object} Object literal specifying widget configuration properties. 5881 * 5882 * @class OverlayContextManager 5883 * @constructor 5884 * @extends OverlayManager 5885 * @static 5886 */ 5887A.OverlayContextManager = new A.OverlayManager({}); 5888 5889A.on(MOUSEDOWN, function() { 5890 A.OverlayContextManager.hideAll(); 5891}, A.getDoc()); 5892 5893 5894}, '3.1.0-deprecated.52', {"requires": ["aui-overlay-manager-deprecated", "aui-delayed-task-deprecated", "aui-aria"]}); 5895 5896YUI.add('aui-overlay-manager-deprecated', function (A, NAME) { 5897 5898/** 5899 * The OverlayManager Utility 5900 * 5901 * @module aui-overlay 5902 * @submodule aui-overlay-manager 5903 */ 5904 5905var Lang = A.Lang, 5906 isArray = Lang.isArray, 5907 isBoolean = Lang.isBoolean, 5908 isNumber = Lang.isNumber, 5909 isString = Lang.isString, 5910 5911 BOUNDING_BOX = 'boundingBox', 5912 DEFAULT = 'default', 5913 HOST = 'host', 5914 OVERLAY_MANAGER = 'OverlayManager', 5915 GROUP = 'group', 5916 Z_INDEX = 'zIndex', 5917 Z_INDEX_BASE = 'zIndexBase'; 5918 5919/** 5920 * <p><img src="assets/images/aui-overlay-manager/main.png"/></p> 5921 * 5922 * A base class for OverlayManager, providing: 5923 * <ul> 5924 * <li>Grouping overlays</li> 5925 * <li>Show or hide the entire group of registered overlays</li> 5926 * <li>Basic Overlay Stackability (zIndex support)</li> 5927 * </ul> 5928 * 5929 * Quick Example:<br/> 5930 * 5931 * <pre><code>var groupOverlayManager = new A.OverlayManager(); 5932 * groupOverlayManager.register([overlay1, overlay2, overlay3]); 5933 * groupOverlayManager.hideAll(); 5934 * </code></pre> 5935 * 5936 * Check the list of <a href="OverlayManager.html#configattributes">Configuration Attributes</a> available for 5937 * OverlayManager. 5938 * 5939 * @param config {Object} Object literal specifying widget configuration properties. 5940 * 5941 * @class OverlayManager 5942 * @constructor 5943 * @extends Base 5944 */ 5945var OverlayManager = A.Component.create({ 5946 /** 5947 * Static property provides a string to identify the class. 5948 * 5949 * @property OverlayManager.NAME
5950 * @type String 5951 * @static 5952 */ 5953 NAME: OVERLAY_MANAGER.toLowerCase(), 5954 5955 /** 5956 * Static property used to define the default attribute 5957 * configuration for the OverlayManager. 5958 * 5959 * @property OverlayManager.ATTRS 5960 * @type Object 5961 * @static 5962 */ 5963 ATTRS: { 5964 /** 5965 * The zIndex base to be used on the stacking for all overlays 5966 * registered on the OverlayManager. 5967 * 5968 * @attribute zIndexBase 5969 * @default 1000 5970 * @type Number 5971 */ 5972 zIndexBase: { 5973 value: 1000, 5974 validator: isNumber, 5975 setter: Lang.toInt 5976 } 5977 }, 5978 5979 EXTENDS: A.Base, 5980 5981 prototype: { 5982 /** 5983 * Construction logic executed during OverlayManager instantiation. Lifecycle. 5984 * 5985 * @method initializer 5986 * @protected 5987 */ 5988 initializer: function() { 5989 var instance = this; 5990 5991 instance._overlays = []; 5992 }, 5993 5994 /** 5995 * Set the passed overlay zIndex to the highest value. 5996 * 5997 * @method bringToTop 5998 * @param {Overlay} overlay Instance of 5999 * <a href="Overlay.html">Overlay</a>. 6000 */ 6001 bringToTop: function(overlay) { 6002 var instance = this; 6003 6004 var overlays = instance._overlays.sort(instance.sortByZIndexDesc); 6005 6006 var highest = overlays[0]; 6007 6008 if (highest !== overlay) { 6009 var overlayZ = overlay.get(Z_INDEX); 6010 var highestZ = highest.get(Z_INDEX); 6011 6012 overlay.set(Z_INDEX, highestZ + 1); 6013 6014 overlay.set('focused', true); 6015 } 6016 }, 6017 6018 /** 6019 * Destructor lifecycle implementation for the OverlayManager class. 6020 * Purges events attached to the node (and all child nodes). 6021 * 6022 * @method destructor 6023 * @protected 6024 */ 6025 destructor: function() { 6026 var instance = this; 6027 6028 instance._overlays = []; 6029 }, 6030 6031 /** 6032 * Register the passed <a href="Overlay.html">Overlay</a> to this 6033 * OverlayManager. 6034 * 6035 * @method register 6036 * @param {Overlay} overlay <a href="Overlay.html">Overlay</a> instance to be registered 6037 * @return {Array} Registered overlays 6038 */ 6039 register: function(overlay) { 6040 var instance = this; 6041 6042 var overlays = instance._overlays; 6043 6044 if (isArray(overlay)) { 6045 A.Array.each(overlay, function(o) { 6046 instance.register(o); 6047 }); 6048 } 6049 else { 6050 var zIndexBase = instance.get(Z_INDEX_BASE); 6051 var registered = instance._registered(overlay); 6052 6053 if (!registered && overlay && 6054 ((overlay instanceof A.Overlay) || 6055 (A.Component && overlay instanceof A.Component)) 6056 ) { 6057 var boundingBox = overlay.get(BOUNDING_BOX); 6058 6059 overlays.push(overlay); 6060 6061 var zIndex = overlay.get(Z_INDEX) || 0; 6062 var newZIndex = overlays.length + zIndex + zIndexBase; 6063 6064 overlay.set(Z_INDEX, newZIndex); 6065 6066 overlay.on('focusedChange', instance._onFocusedChange, instance); 6067 boundingBox.on('mousedown', instance._onMouseDown, instance); 6068 } 6069 } 6070 6071 return overlays; 6072 }, 6073 6074 /** 6075 * Remove the passed <a href="Overlay.html">Overlay</a> from this 6076 * OverlayManager. 6077 * 6078 * @method remove 6079 * @param {Overlay} overlay <a href="Overlay.html">Overlay</a> instance to be removed 6080 * @return {null} 6081 */ 6082 remove: function(overlay) { 6083 var instance = this; 6084 6085 var overlays = instance._overlays; 6086 6087 if (overlays.length) { 6088 return A.Array.removeItem(overlays, overlay); 6089 } 6090 6091 return null; 6092 }, 6093 6094 /** 6095 * Loop through all registered <a href="Overlay.html">Overlay</a> and 6096 * execute a callback. 6097 * 6098 * @method each 6099 * @param {function} fn Callback to be executed on the 6100 * <a href="Array.html#method_each">Array.each</a> 6101 * @return {null} 6102 */ 6103 each: function(fn) { 6104 var instance = this; 6105 6106 var overlays = instance._overlays; 6107 6108 A.Array.each(overlays, fn); 6109 }, 6110 6111 /** 6112 * Invoke the <a href="Overlay.html#method_show">show</a> method from 6113 * all registered Overlays. 6114 * 6115 * @method showAll 6116 */ 6117 showAll: function() { 6118 this.each( 6119 function(overlay) { 6120 overlay.show(); 6121 } 6122 ); 6123 }, 6124 6125 /** 6126 * Invoke the <a href="Overlay.html#method_hide">hide</a> method from 6127 * all registered Overlays. 6128 * 6129 * @method hideAll 6130 */ 6131 hideAll: function() { 6132 this.each( 6133 function(overlay) { 6134 overlay.hide(); 6135 } 6136 ); 6137 }, 6138 6139 /** 6140 * zIndex comparator. Used on Array.sort. 6141 * 6142 * @method sortByZIndexDesc 6143 * @param {Overlay} a Overlay 6144 * @param {Overlay} b Overlay 6145 * @return {Number} 6146 */ 6147 sortByZIndexDesc: function(a, b) { 6148 if (!a || !b || !a.hasImpl(A.WidgetStack) || !b.hasImpl(A.WidgetStack)) { 6149 return 0; 6150 } 6151 else { 6152 var aZ = a.get(Z_INDEX); 6153 var bZ = b.get(Z_INDEX); 6154 6155 if (aZ > bZ) { 6156 return -1; 6157 } 6158 else if (aZ < bZ) { 6159 return 1; 6160 } 6161 else { 6162 return 0; 6163 } 6164 } 6165 }, 6166 6167 /** 6168 * Check if the overlay is registered. 6169 * 6170 * @method _registered 6171 * @param {Overlay} overlay Overlay 6172 * @protected 6173 * @return {boolean} 6174 */ 6175 _registered: function(overlay) { 6176 var instance = this; 6177 6178 return A.Array.indexOf(instance._overlays, overlay) != -1; 6179 }, 6180 6181 /** 6182 * Mousedown event handler, used to invoke 6183 * <a href="OverlayManager.html#method_bringToTop">bringToTop</a>. 6184 * 6185 * @method _onMouseDown 6186 * @param {EventFacade} event 6187 * @protected 6188 */ 6189 _onMouseDown: function(event) { 6190 var instance = this;
6191 var overlay = A.Widget.getByNode(event.currentTarget || event.target); 6192 var registered = instance._registered(overlay); 6193 6194 if (overlay && registered) { 6195 instance.bringToTop(overlay); 6196 } 6197 }, 6198 6199 /** 6200 * Fires when the <a href="Widget.html#config_focused">focused</a> 6201 * attribute change. Used to invoke 6202 * <a href="OverlayManager.html#method_bringToTop">bringToTop</a>. 6203 * 6204 * @method _onFocusedChange 6205 * @param {EventFacade} event 6206 * @protected 6207 */ 6208 _onFocusedChange: function(event) { 6209 var instance = this; 6210 6211 if (event.newVal) { 6212 var overlay = event.currentTarget || event.target; 6213 var registered = instance._registered(overlay); 6214 6215 if (overlay && registered) { 6216 instance.bringToTop(overlay); 6217 } 6218 } 6219 } 6220 } 6221}); 6222 6223A.OverlayManager = OverlayManager; 6224 6225 6226}, '3.1.0-deprecated.52', {"requires": ["overlay", "plugin", "aui-base-deprecated", "aui-overlay-base-deprecated"]}); 6227 6228YUI.add('aui-overlay-mask-deprecated', function (A, NAME) { 6229 6230/** 6231 * The OverlayMask Utility 6232 * 6233 * @module aui-overlay 6234 * @submodule aui-overlay-mask 6235 */ 6236 6237var L = A.Lang, 6238 isArray = L.isArray, 6239 isString = L.isString, 6240 isNumber = L.isNumber, 6241 isValue = L.isValue, 6242 6243 CONFIG = A.config, 6244 6245 UA = A.UA, 6246 6247 IE6 = (UA.ie <= 6), 6248 6249 ABSOLUTE = 'absolute', 6250 ALIGN_POINTS = 'alignPoints', 6251 BACKGROUND = 'background', 6252 BOUNDING_BOX = 'boundingBox', 6253 CONTENT_BOX = 'contentBox', 6254 FIXED = 'fixed', 6255 HEIGHT = 'height', 6256 OFFSET_HEIGHT = 'offsetHeight', 6257 OFFSET_WIDTH = 'offsetWidth', 6258 OPACITY = 'opacity', 6259 OVERLAY_MASK = 'overlaymask', 6260 POSITION = 'position', 6261 TARGET = 'target', 6262 WIDTH = 'width'; 6263 6264/** 6265 * A base class for OverlayMask, providing: 6266 * <ul> 6267 * <li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li> 6268 * <li>Cross browser mask functionality to cover an element or the entire page</li> 6269 * <li>Customizable mask (i.e., background, opacity)</li> 6270 * </ul> 6271 * 6272 * Quick Example:<br/> 6273 * 6274 * <pre><code>var instance = new A.OverlayMask().render();</code></pre> 6275 * 6276 * Check the list of <a href="OverlayMask.html#configattributes">Configuration Attributes</a> available for 6277 * OverlayMask. 6278 * 6279 * @param config {Object} Object literal specifying widget configuration properties. 6280 * 6281 * @class OverlayMask 6282 * @constructor 6283 * @extends OverlayBase 6284 */ 6285var OverlayMask = A.Component.create({ 6286 /** 6287 * Static property provides a string to identify the class. 6288 * 6289 * @property OverlayMask.NAME
6290 * @type String 6291 * @static 6292 */ 6293 NAME: OVERLAY_MASK, 6294 6295 /** 6296 * Static property used to define the default attribute 6297 * configuration for the OverlayMask. 6298 * 6299 * @property OverlayMask.ATTRS 6300 * @type Object 6301 * @static 6302 */ 6303 ATTRS: { 6304 /** 6305 * Points to align the <a href="Overlay.html">Overlay</a> used as 6306 * mask. 6307 * 6308 * @attribute alignPoints 6309 * @default [ 'tl', 'tl' ] 6310 * @type Array 6311 */ 6312 alignPoints: { 6313 value: ['tl', 'tl'], 6314 validator: isArray 6315 }, 6316 6317 /** 6318 * Background color of the mask. 6319 * 6320 * @attribute background 6321 * @default null 6322 * @type String 6323 */ 6324 background: { 6325 lazyAdd: false, 6326 value: null, 6327 validator: isString, 6328 setter: function(v) { 6329 if (v) { 6330 this.get(CONTENT_BOX).setStyle(BACKGROUND, v); 6331 } 6332 6333 return v; 6334 } 6335 }, 6336 6337 /** 6338 * Node where the mask will be positioned and re-dimensioned. The 6339 * default is the document, which means that if not specified the mask 6340 * takes the full screen. 6341 * 6342 * @attribute target 6343 * @default document 6344 * @type Node | String 6345 */ 6346 target: { 6347 cloneDefaultValue: false, 6348 lazyAdd: false, 6349 value: CONFIG.doc, 6350 setter: function(v) { 6351 var instance = this; 6352 6353 var target = A.one(v); 6354 6355 var isDoc = instance._isDoc = target.compareTo(CONFIG.doc); 6356 var isWin = instance._isWin = target.compareTo(CONFIG.win); 6357 6358 instance._fullPage = isDoc || isWin; 6359 6360 return target; 6361 } 6362 }, 6363 6364 /** 6365 * CSS opacity of the mask. 6366 * 6367 * @attribute opacity 6368 * @default .5 6369 * @type Number 6370 */ 6371 opacity: { 6372 value: 0.5, 6373 validator: isNumber, 6374 setter: function(v) { 6375 return this._setOpacity(v); 6376 } 6377 }, 6378 6379 /** 6380 * Use shim option. 6381 * 6382 * @attribute shim 6383 * @default True on IE. 6384 * @type boolean 6385 */ 6386 shim: { 6387 value: A.UA.ie 6388 }, 6389 6390 /** 6391 * If true the Overlay is visible by default after the render phase. 6392 * Inherited from <a href="Overlay.html">Overlay</a>. 6393 * 6394 * @attribute visible 6395 * @default false 6396 * @type boolean 6397 */ 6398 visible: { 6399 value: false 6400 }, 6401 6402 /** 6403 * zIndex of the OverlayMask. 6404 * 6405 * @attribute zIndex 6406 * @default 1000 6407 * @type Number 6408 */ 6409 zIndex: { 6410 value: 1000 6411 } 6412 }, 6413 6414 EXTENDS: A.OverlayBase, 6415 6416 prototype: { 6417 /** 6418 * Bind the events on the OverlayMask UI. Lifecycle. 6419 * 6420 * @method bindUI 6421 * @protected 6422 */ 6423 bindUI: function() { 6424 var instance = this; 6425 6426 OverlayMask.superclass.bindUI.apply(this, arguments); 6427 6428 instance._eventHandles = [ 6429 instance.after('targetChange', instance._afterTargetChange), 6430 instance.after('visibleChange', instance._afterVisibleChange), 6431 6432 // window:resize YUI normalized event is not working, bug? 6433 A.on('windowresize', A.bind(instance.refreshMask, instance)) 6434 ]; 6435 }, 6436 6437 /** 6438 * Sync the OverlayMask UI. Lifecycle. 6439 * 6440 * @method syncUI 6441 * @protected 6442 */ 6443 syncUI: function() { 6444 var instance = this; 6445 6446 instance.refreshMask(); 6447 }, 6448 6449 destructor: function() { 6450 var instance = this; 6451 6452 (new A.EventHandle(instance._eventHandles)).detach(); 6453 }, 6454 6455 /** 6456 * Get the size of the 6457 * <a href="OverlayMask.html#config_target">target</a>. Used to dimension 6458 * the mask node. 6459 * 6460 * @method getTargetSize 6461 * @return {Object} Object containing the { height: height, width: width }. 6462 */ 6463 getTargetSize: function() { 6464 var instance = this; 6465 var target = instance.get(TARGET); 6466 6467 var isDoc = instance._isDoc; 6468 var isWin = instance._isWin; 6469 6470 var height = target.get(OFFSET_HEIGHT); 6471 var width = target.get(OFFSET_WIDTH); 6472 6473 if (IE6) { 6474 // IE6 doesn't support height/width 100% on doc/win 6475 if (isWin) { 6476 width = A.DOM.winWidth(); 6477 height = A.DOM.winHeight(); 6478 } 6479 else if (isDoc) { 6480 width = A.DOM.docWidth(); 6481 height = A.DOM.docHeight(); 6482 } 6483 } 6484 // good browsers... 6485 else if (instance._fullPage) { 6486 height = '100%'; 6487 width = '100%'; 6488 } 6489 6490 return { 6491 height: height, 6492 width: width 6493 }; 6494 }, 6495 6496 /** 6497 * Repaint the OverlayMask UI, respecting the 6498 * <a href="OverlayMask.html#config_target">target</a> size and the 6499 * <a href="OverlayMask.html#config_alignPoints">alignPoints</a>. 6500 * 6501 * @method refreshMask 6502 */ 6503 refreshMask: function() { 6504 var instance = this; 6505 var alignPoints = instance.get(ALIGN_POINTS); 6506 var target = instance.get(TARGET); 6507 var boundingBox = instance.get(BOUNDING_BOX); 6508 var targetSize = instance.getTargetSize(); 6509 6510 var fullPage = instance._fullPage; 6511 6512 boundingBox.setStyles({ 6513 position: (IE6 || !fullPage) ? ABSOLUTE : FIXED, 6514 left: 0, 6515 top: 0 6516 }); 6517 6518 var height = targetSize.height; 6519 var width = targetSize.width; 6520 6521 if (isValue(height)) { 6522 instance.set(HEIGHT, height); 6523 } 6524 6525 if (isValue(width)) { 6526 instance.set(WIDTH, width); 6527 } 6528 6529 // if its not a full mask... 6530 if (!fullPage) { 6531 // if the target is not document|window align the overlay 6532 instance.align(target, alignPoints); 6533 } 6534 }, 6535 6536 /** 6537 * Setter for <a href="Paginator.html#config_opacity">opacity</a>. 6538 * 6539 * @method _setOpacity 6540 * @protected 6541 * @param {Number} v 6542 * @return {Number} 6543 */ 6544 _setOpacity: function(v) { 6545 var instance = this; 6546 6547 instance.get(CONTENT_BOX).setStyle(OPACITY, v); 6548 6549 return v; 6550 }, 6551 6552 /** 6553 * Invoke the <code>OverlayMask.superclass._uiSetVisible</code>. Used to 6554 * reset the <code>opacity</code> to work around IE bugs when set opacity 6555 * of hidden elements. 6556 * 6557 * @method _uiSetVisible 6558 * @param {boolean} val 6559 * @protected 6560 */ 6561 _uiSetVisible: function(val) { 6562 var instance = this; 6563 6564 OverlayMask.superclass._uiSetVisible.apply(this, arguments); 6565 6566 if (val) { 6567 instance._setOpacity( 6568 instance.get(OPACITY) 6569 ); 6570 } 6571 }, 6572 6573 /** 6574 * Fires after the value of the 6575 * <a href="Paginator.html#config_target">target</a> attribute change. 6576 * 6577 * @method _afterTargetChange 6578 * @param {EventFacade} event 6579 * @protected 6580 */ 6581 _afterTargetChange: function(event) { 6582 var instance = this; 6583 6584 instance.refreshMask(); 6585 }, 6586 6587 /** 6588 * Fires after the value of the 6589 * <a href="Paginator.html#config_visible">visible</a> attribute change. 6590 * 6591 * @method _afterVisibleChange 6592 * @param {EventFacade} event 6593 * @protected 6594 */ 6595 _afterVisibleChange: function(event) { 6596 var instance = this; 6597 6598 instance._uiSetVisible(event.newVal); 6599 }, 6600 6601 /** 6602 * UI Setter for the 6603 * <a href="Paginator.html#config_xy">XY</a> attribute. 6604 * 6605 * @method _uiSetXY 6606 * @param {EventFacade} event 6607 * @protected 6608 */ 6609 _uiSetXY: function() { 6610 var instance = this; 6611 6612 if (!instance._fullPage || IE6) { 6613 OverlayMask.superclass._uiSetXY.apply(instance, arguments); 6614 } 6615 } 6616 } 6617}); 6618 6619A.OverlayMask = OverlayMask; 6620 6621 6622}, '3.1.0-deprecated.52', {"requires": ["event-resize", "aui-base-deprecated", "aui-overlay-base-deprecated"], "skinnable": true}); 6623 6624YUI.add('aui-parse-content', function (A, NAME) { 6625 6626/** 6627 * The ParseContent Utility - Parse the content of a Node so that all of the 6628 * javascript contained in that Node will be executed according to the order 6629 * that it appears. 6630 * 6631 * @module aui-parse-content 6632 */ 6633 6634/* 6635 * NOTE: The inspiration of ParseContent cames from the "Caridy Patino" Node 6636 * Dispatcher Plugin http://github.com/caridy/yui3-gallery/blob/master/src 6637 * /gallery-dispatcher/ 6638 */ 6639 6640var L = A.Lang, 6641 isString = L.isString, 6642 6643 DOC = A.config.doc, 6644 PADDING_NODE = '<div>_</div>', 6645 6646 SCRIPT_TYPES = { 6647 '': 1, 6648 'text/javascript': 1, 6649 'text/parsed': 1 6650 }; 6651 6652/** 6653 * A base class for ParseContent, providing: 6654 * 6655 * - After plug ParseContent on a A.Node instance the javascript chunks will be 6656 * executed (remote and inline scripts) 6657 * - All the javascripts within a content will be executed according to the 6658 * order of apparition 6659 * 6660 * **NOTE:** For performance reasons on DOM manipulation, 6661 * ParseContent only parses the content passed to the 6662 * [setContent](Node.html#method_setContent), 6663 * [prepend](Node.html#method_prepend) and 6664 * [append](Node.html#method_append) methods. 6665 * 6666 * Quick Example: 6667 * 6668 * ``` 6669 * node.plug(A.Plugin.ParseContent); 6670 * ``` 6671 * 6672 * @class A.ParseContent 6673 * @extends Plugin.Base 6674 * @param {Object} config Object literal specifying widget configuration 6675 * properties. 6676 * @constructor 6677 */ 6678var ParseContent = A.Component.create({ 6679 /** 6680 * Static property provides a string to identify the class. 6681 * 6682 * @property NAME
6683 * @type String 6684 * @static 6685 */ 6686 NAME: 'ParseContent', 6687 6688 /** 6689 * Static property provides a string to identify the namespace. 6690 * 6691 * @property NS 6692 * @type String 6693 * @static 6694 */ 6695 NS: 'ParseContent', 6696 6697 /** 6698 * Static property used to define the default attribute 6699 * configuration for the ParseContent. 6700 * 6701 * @property ATTRS 6702 * @type Object 6703 * @static 6704 */ 6705 ATTRS: { 6706 /** 6707 * A queue of elements to be parsed. 6708 * 6709 * @attribute queue 6710 * @default null 6711 */ 6712 queue: { 6713 value: null 6714 }, 6715 6716 /** 6717 * When true, script nodes will not be removed from original content, 6718 * instead the script type attribute will be set to `text/plain`. 6719 * 6720 * @attribute preserveScriptNodes 6721 * @default false 6722 */ 6723 preserveScriptNodes: { 6724 validator: L.isBoolean, 6725 value: false 6726 } 6727 }, 6728 6729 /** 6730 * Static property used to define which component it extends. 6731 * 6732 * @property EXTENDS 6733 * @type Object 6734 * @static 6735 */ 6736 EXTENDS: A.Plugin.Base, 6737 6738 prototype: { 6739 6740 /** 6741 * Construction logic executed during ParseContent instantiation. 6742 * Lifecycle. 6743 * 6744 * @method initializer 6745 * @protected 6746 */ 6747 initializer: function() { 6748 var instance = this; 6749 6750 ParseContent.superclass.initializer.apply(this, arguments); 6751 6752 instance.set( 6753 'queue', 6754 new A.AsyncQueue() 6755 ); 6756 6757 instance._bindAOP(); 6758 }, 6759 6760 /** 6761 * Global eval the <data>data</data> passed. 6762 * 6763 * @method globalEval 6764 * @param {String} data JavaScript String. 6765 */ 6766 globalEval: function(data) { 6767 var doc = A.getDoc(); 6768 var head = doc.one('head') || doc.get('documentElement'); 6769 6770 // NOTE: A.Node.create('<script></script>') doesn't work correctly 6771 // on Opera 6772 var newScript = DOC.createElement('script'); 6773 6774 newScript.type = 'text/javascript'; 6775 6776 if (data) { 6777 // NOTE: newScript.set(TEXT, data) breaks on IE, YUI BUG. 6778 newScript.text = L.trim(data); 6779 } 6780 6781 //removes the script node immediately after executing it 6782 head.appendChild(newScript).remove(); 6783 }, 6784 6785 /** 6786 * Extract the `script` tags from the string content and 6787 * evaluate the chunks. 6788 * 6789 * @method parseContent 6790 * @param {String} content HTML string 6791 * @return {String} 6792 */ 6793 parseContent: function(content) { 6794 var instance = this; 6795 6796 var output = instance._extractScripts(content); 6797 6798 instance._dispatch(output); 6799 6800 return output; 6801 }, 6802 6803 /** 6804 * Add inline script data to the queue. 6805 * 6806 * @method _addInlineScript 6807 * @param {String} data The script content which should be added to the 6808 * queue 6809 * @protected 6810 */ 6811 _addInlineScript: function(data) { 6812 var instance = this; 6813 6814 instance.get('queue').add({ 6815 args: data, 6816 context: instance, 6817 fn: instance.globalEval, 6818 timeout: 0 6819 }); 6820 }, 6821 6822 /** 6823 * Bind listeners on the `insert` and `setContent` methods of the Node 6824 * instance where you are plugging the ParseContent. These listeners are 6825 * responsible for intercept the HTML passed and parse them. 6826 * 6827 * @method _bindAOP 6828 * @protected 6829 */ 6830 _bindAOP: function() { 6831 var instance = this; 6832 6833 var cleanFirstArg = function(content) { 6834 var args = Array.prototype.slice.call(arguments); 6835 var output = instance.parseContent(content); 6836 6837 // replace the first argument with the clean fragment 6838 args.splice(0, 1, output.fragment); 6839
6840 return new A.Do.AlterArgs(null, args); 6841 }; 6842 6843 this.doBefore('insert', cleanFirstArg); 6844 this.doBefore('replaceChild', cleanFirstArg); 6845 6846 var cleanArgs = function(content) { 6847 var output = instance.parseContent(content); 6848 6849 return new A.Do.AlterArgs(null, [output.fragment]); 6850 }; 6851 6852 this.doBefore('replace', cleanArgs); 6853 this.doBefore('setContent', cleanArgs); 6854 }, 6855 6856 /** 6857 * Create an HTML fragment with the String passed, extract all the 6858 * script tags and return an Object with a reference for the extracted 6859 * scripts and the fragment. 6860 * 6861 * @method clean 6862 * @param {String} content HTML content. 6863 * @protected 6864 * @return {Object} 6865 */ 6866 _extractScripts: function(content) { 6867 var instance = this, 6868 fragment = A.Node.create('<div></div>'), 6869 output = {}, 6870 preserveScriptNodes = instance.get('preserveScriptNodes'); 6871 6872 // For PADDING_NODE, instead of fixing all tags in the content to be 6873 // "XHTML"-style, we make the firstChild be a valid non-empty tag, 6874 // then we remove it later 6875 6876 if (isString(content)) { 6877 content = PADDING_NODE + content; 6878 6879 // create fragment from {String} 6880 A.DOM.addHTML(fragment, content, 'append'); 6881 } 6882 else { 6883 fragment.append(PADDING_NODE); 6884 6885 // create fragment from {Y.Node | HTMLElement} 6886 fragment.append(content); 6887 } 6888 6889 output.js = fragment.all('script').filter(function(script) { 6890 var includeScript = SCRIPT_TYPES[script.getAttribute('type').toLowerCase()]; 6891 if (preserveScriptNodes) { 6892 script.setAttribute('type', 'text/parsed'); 6893 } 6894 return includeScript; 6895 }); 6896 6897 if (!preserveScriptNodes) { 6898 output.js.each( 6899 function(node) { 6900 node.remove(); 6901 } 6902 ); 6903 } 6904 6905 // remove PADDING_NODE 6906 fragment.get('firstChild').remove(); 6907 6908 output.fragment = fragment.get('childNodes').toFrag(); 6909 6910 return output; 6911 }, 6912 6913 /** 6914 * Loop trough all extracted `script` tags and evaluate them. 6915 * 6916 * @method _dispatch 6917 * @param {Object} output Object containing the reference for the 6918 * fragment and the extracted `script` tags. 6919 * @protected 6920 * @return {String} 6921 */ 6922 _dispatch: function(output) { 6923 var instance = this; 6924 6925 var queue = instance.get('queue'); 6926 6927 var scriptContent = []; 6928 6929 output.js.each(function(node) { 6930 var src = node.get('src'); 6931 6932 if (src) { 6933 if (scriptContent.length) { 6934 instance._addInlineScript(scriptContent.join(';')); 6935 6936 scriptContent.length = 0; 6937 } 6938 6939 queue.add({ 6940 autoContinue: false, 6941 fn: function() { 6942 A.Get.script(src, { 6943 onEnd: function(o) { 6944 //removes the script node immediately after 6945 //executing it 6946 o.purge(); 6947 queue.run(); 6948 } 6949 }); 6950 }, 6951 timeout: 0 6952 }); 6953 } 6954 else { 6955 var dom = node._node; 6956 6957 scriptContent.push(dom.text || dom.textContent || dom.innerHTML || ''); 6958 } 6959 }); 6960 6961 if (scriptContent.length) { 6962 instance._addInlineScript(scriptContent.join(';')); 6963 } 6964 6965 queue.run(); 6966 } 6967 } 6968}); 6969 6970A.namespace('Plugin').ParseContent = ParseContent; 6971 6972 6973}, '3.1.0-deprecated.52', {"requires": ["async-queue", "plugin", "io-base", "aui-component", "aui-node-base"]}); 6974 6975'use strict'; 6976 6977;(function (A, Liferay) { 6978 var LayoutExporter = { 6979 icons: { 6980 minus: themeDisplay.getPathThemeImages() + '/arrows/01_minus.png', 6981 plus: themeDisplay.getPathThemeImages() + '/arrows/01_plus.png' 6982 }, 6983 6984 publishToLive: function publishToLive(options) { 6985 options = options || {}; 6986 6987 Liferay.Util.openWindow({ 6988 dialog: { 6989 constrain: true, 6990 modal: true, 6991 on: { 6992 visibleChange: function visibleChange(event) { 6993 var instance = this; 6994 6995 if (!event.newVal) { 6996 instance.destroy(); 6997 } 6998 } 6999 } 7000 }, 7001 title: options.title, 7002 uri: options.url 7003 }); 7004 } 7005 }; 7006 7007 Liferay.provide(LayoutExporter, 'all', function (options) { 7008 options = options || {}; 7009 7010 var obj = options.obj; 7011 var pane = options.pane; 7012 7013 if (obj && obj.checked) { 7014 pane = A.one(pane); 7015 7016 if (pane) { 7017 pane.hide(); 7018 } 7019 } 7020 }, ['aui-base']); 7021 7022 Liferay.provide(LayoutExporter, 'details', function (options) { 7023 options = options || {}; 7024 7025 var detail = A.one(options.detail); 7026 var img = A.one(options.toggle); 7027 7028 if (detail && img) { 7029 var icon = LayoutExporter.icons.plus; 7030 7031 if (detail.hasClass('hide')) { 7032 detail.show(); 7033 icon = LayoutExporter.icons.minus; 7034 } else { 7035 detail.hide(); 7036 } 7037 7038 img.attr('src', icon); 7039 } 7040 }, ['aui-base']); 7041 7042 Liferay.provide(LayoutExporter, 'proposeLayout', function (options) { 7043 options = options || {}; 7044 7045 var namespace = options.namespace; 7046 var reviewers = options.reviewers; 7047 7048 var contents = '<div>' + '<form action="' + options.url + '" method="post">'; 7049 7050 if (reviewers.length > 0) { 7051 contents += '<textarea name="' + namespace + 'description" style="height: 100px; width: 284px;"></textarea><br /><br />' + 'Revisor' + ' <select name="' + namespace + 'reviewUserId">'; 7052 7053 for (var i = 0; i < reviewers.length; i++) { 7054 contents += '<option value="' + reviewers[i].userId + '">' + reviewers[i].fullName + '</option>'; 7055 } 7056 7057 contents += '</select><br /><br />' + '<input type="submit" value="' + 'Continuar' + '" />'; 7058 } else {
7059 contents += 'No\x20se\x20ha\x20encontrado\x20ningún\x20revisor\x2e' + '<br />' + 'Por\x20favor\x2c\x20póngase\x20en\x20contacto\x20con\x20el\x20administrador\x20para\x20asignar\x20revisores\x2e' + '<br /><br />'; 7060 } 7061 7062 contents += '</form>' + '</div>'; 7063 7064 Liferay.Util.openWindow({ 7065 dialog: { 7066 destroyOnHide: true 7067 }, 7068 title: contents 7069 }); 7070 }, ['liferay-util-window']); 7071 7072 Liferay.provide(LayoutExporter, 'selected', function (options) { 7073 options = options || {}; 7074 7075 var obj = options.obj; 7076 var pane = options.pane; 7077 7078 if (obj && obj.checked) { 7079 pane = A.one(pane); 7080 7081 if (pane) { 7082 pane.show(); 7083 } 7084 } 7085 }, ['aui-base']); 7086 7087 Liferay.LayoutExporter = LayoutExporter; 7088})(AUI(), Liferay); 7089AUI.add( 7090 'liferay-session', 7091 function(A) { 7092 var Lang = A.Lang; 7093 7094 var BUFFER_TIME = []; 7095 7096 var CONFIG = A.config; 7097 7098 var DOC = CONFIG.doc; 7099 7100 var MAP_SESSION_STATE_EVENTS = { 7101 active: 'activated' 7102 }; 7103 7104 var SRC = {}; 7105 7106 var SRC_EVENT_OBJ = { 7107 src: SRC 7108 }; 7109 7110 var URL_BASE = themeDisplay.getPathMain() + '/portal/'; 7111 7112 var SessionBase = A.Component.create( 7113 { 7114 ATTRS: { 7115 autoExtend: { 7116 value: false 7117 }, 7118 redirectOnExpire: { 7119 value: true 7120 }, 7121 redirectUrl: { 7122 value: '' 7123 }, 7124 sessionLength: { 7125 getter: '_getLengthInMillis', 7126 value: 0 7127 }, 7128 sessionState: { 7129 value: 'active' 7130 }, 7131 timestamp: { 7132 getter: '_getTimestamp', 7133 setter: '_setTimestamp', 7134 value: 0 7135 }, 7136 warningLength: { 7137 getter: '_getLengthInMillis', 7138 setter: '_setWarningLength', 7139 value: 0 7140 }, 7141 warningTime: { 7142 getter: '_getWarningTime', 7143 value: 0 7144 } 7145 }, 7146 EXTENDS: A.Base, 7147 NAME: 'liferaysession', 7148 prototype: { 7149 initializer: function(config) { 7150 var instance = this; 7151 7152 instance._cookieOptions = { 7153 path: '/', 7154 secure: A.UA.secure 7155 }; 7156 7157 instance._registered = {}; 7158 7159 instance.set('timestamp'); 7160 7161 instance._initEvents(); 7162 7163 instance._startTimer(); 7164 }, 7165 7166 destructor: function() { 7167 var instance = this; 7168 7169 (new A.EventHandle(instance._eventHandlers)).detach(); 7170 7171 instance._stopTimer(); 7172 }, 7173 7174 expire: function() { 7175 var instance = this; 7176 7177 instance.set('sessionState', 'expired', SRC_EVENT_OBJ); 7178 }, 7179 7180 extend: function() { 7181 var instance = this; 7182 7183 instance.set('sessionState', 'active', SRC_EVENT_OBJ); 7184 }, 7185 7186 registerInterval: function(fn) { 7187 var instance = this; 7188 7189 var fnId; 7190 var registered = instance._registered; 7191 7192 if (Lang.isFunction(fn)) { 7193 fnId = A.stamp(fn); 7194 7195 registered[fnId] = fn; 7196 } 7197 7198 return fnId; 7199 }, 7200 7201 resetInterval: function() { 7202 var instance = this; 7203 7204 instance._stopTimer(); 7205 instance._startTimer(); 7206 }, 7207 7208 unregisterInterval: function(fnId) { 7209 var instance = this; 7210 7211 var registered = instance._registered; 7212 7213 if (registered.hasOwnProperty(fnId)) { 7214 delete registered[fnId]; 7215 } 7216 7217 return fnId; 7218 }, 7219 7220 warn: function() { 7221 var instance = this; 7222 7223 instance.set('sessionState', 'warned', SRC_EVENT_OBJ); 7224 }, 7225 7226 _afterSessionStateChange: function(event) { 7227 var instance = this; 7228 7229 var details = event.details; 7230 var newVal = event.newVal; 7231 7232 var src = null; 7233 7234 if ('src' in event && details.length) { 7235 src = details[0]; 7236 } 7237 7238 instance.fire(MAP_SESSION_STATE_EVENTS[newVal] || newVal, src); 7239 }, 7240 7241 _defActivatedFn: function(event) { 7242 var instance = this; 7243 7244 instance.set('timestamp'); 7245 7246 if (event.src == SRC) { 7247 instance._getExtendIO().start(); 7248 } 7249 }, 7250 7251 _defExpiredFn: function(event) { 7252 var instance = this; 7253 7254 A.clearInterval(instance._intervalId); 7255 7256 instance.set('timestamp', 'expired'); 7257 7258 if (event.src === SRC) { 7259 instance._getExpireIO().start(); 7260 } 7261 }, 7262 7263 _getExpireIO: function() { 7264 var instance = this; 7265 7266 var expireIO = instance._expireIO; 7267 7268 if (!expireIO) { 7269 expireIO = A.io.request( 7270 URL_BASE + 'expire_session', 7271 { 7272 autoLoad: false, 7273 on: { 7274 failure: function(event, id, obj) { 7275 instance._expireIO = null; 7276 7277 A.setTimeout( 7278 function() { 7279 instance._getExpireIO().start(); 7280 }, 7281 1000 7282 ); 7283 }, 7284 success: function(event, id, obj) { 7285 Liferay.fire('sessionExpired'); 7286 7287 if (instance.get('redirectOnExpire')) { 7288 location.href = instance.get('redirectUrl'); 7289 } 7290 } 7291 } 7292 } 7293 ); 7294 7295 instance._expireIO = expireIO; 7296 } 7297 7298 return expireIO; 7299 }, 7300 7301 _getExtendIO: function() { 7302 var instance = this; 7303 7304 var extendIO = instance._extendIO; 7305 7306 if (!extendIO) { 7307 extendIO = A.io.request( 7308 URL_BASE + 'extend_session', 7309 { 7310 autoLoad: false 7311 } 7312 ); 7313 7314 instance._extendIO = extendIO; 7315 } 7316 7317 return extendIO; 7318 }, 7319 7320 _getLengthInMillis: function(value) { 7321 var instance = this; 7322 7323 return value * 1000; 7324 }, 7325 7326 _getTimestamp: function(value) { 7327 var instance = this; 7328
7329 return A.Cookie.get(instance._cookieKey, instance._cookieOptions) || instance._initTimestamp; 7330 }, 7331 7332 _getWarningTime: function() { 7333 var instance = this; 7334 7335 return instance.get('sessionLength') - instance.get('warningLength'); 7336 }, 7337 7338 _initEvents: function() { 7339 var instance = this; 7340 7341 instance.publish( 7342 'activated', 7343 { 7344 defaultFn: A.bind('_defActivatedFn', instance) 7345 } 7346 ); 7347 7348 instance.publish( 7349 'expired', 7350 { 7351 defaultFn: A.bind('_defExpiredFn', instance) 7352 } 7353 ); 7354 7355 instance.publish('warned'); 7356 7357 instance._eventHandlers = [ 7358 instance.on('sessionStateChange', instance._onSessionStateChange), 7359 instance.after('sessionStateChange', instance._afterSessionStateChange), 7360 A.on( 7361 'io:complete', 7362 function(transactionId, response, args) { 7363 if (!args || args && args.sessionExtend || !Lang.isBoolean(args.sessionExtend)) { 7364 instance.resetInterval(); 7365 } 7366 } 7367 ), 7368 Liferay.once( 7369 'screenLoad', 7370 function() { 7371 instance.destroy(); 7372 } 7373 ) 7374 ]; 7375 }, 7376 7377 _onSessionStateChange: function(event) { 7378 var instance = this; 7379 7380 var newVal = event.newVal; 7381 var prevVal = event.prevVal; 7382 7383 if (prevVal == 'expired' && prevVal != newVal) { 7384 event.preventDefault(); 7385 } 7386 else if (prevVal == 'active' && prevVal == newVal) { 7387 instance._afterSessionStateChange(event); 7388 } 7389 }, 7390 7391 _setTimestamp: function(value) { 7392 var instance = this; 7393 7394 value = String(value || Date.now()); 7395 7396 instance._initTimestamp = value; 7397 7398 if (navigator.cookieEnabled) { 7399 A.Cookie.set(instance._cookieKey, value, instance._cookieOptions); 7400 } 7401 }, 7402 7403 _setWarningLength: function(value) { 7404 var instance = this; 7405 7406 return Math.min(instance.get('sessionLength'), value); 7407 }, 7408 7409 _startTimer: function() { 7410 var instance = this; 7411 7412 var sessionLength = instance.get('sessionLength'); 7413 var warningTime = instance.get('warningTime'); 7414 7415 var registered = instance._registered; 7416 7417 var interval = 1000; 7418 7419 instance._intervalId = A.setInterval( 7420 function() { 7421 var timeOffset; 7422 7423 var timestamp = instance.get('timestamp'); 7424 7425 var elapsed = sessionLength; 7426 7427 if (Lang.toInt(timestamp)) { 7428 timeOffset = Math.floor((Date.now() - timestamp) / 1000) * 1000; 7429 7430 elapsed = timeOffset; 7431 7432 if (instance._initTimestamp !== timestamp) { 7433 instance.set('timestamp', timestamp); 7434 7435 var sessionState = instance.get('sessionState'); 7436 7437 if (sessionState != 'active') { 7438 instance.set('sessionState', 'active', SRC_EVENT_OBJ); 7439 } 7440 } 7441 } 7442 else { 7443 timestamp = 'expired'; 7444 } 7445 7446 var extend = instance.get('autoExtend'); 7447 7448 var expirationMoment = false; 7449 var warningMoment = false; 7450 7451 var hasExpired = elapsed >= sessionLength; 7452 var hasWarned = elapsed >= warningTime; 7453 7454 if (hasWarned) { 7455 if (timestamp == 'expired') { 7456 expirationMoment = true; 7457 extend = false; 7458 hasExpired = true; 7459 } 7460 7461 var sessionState = instance.get('sessionState'); 7462 7463 if (hasExpired && sessionState != 'expired') { 7464 if (extend) { 7465 expirationMoment = false; 7466 hasExpired = false; 7467 hasWarned = false; 7468 warningMoment = false; 7469 7470 instance.extend(); 7471 } 7472 else { 7473 instance.expire(); 7474 7475 expirationMoment = true; 7476 } 7477 } 7478 else if (hasWarned && !hasExpired && !extend && sessionState != 'warned') { 7479 instance.warn(); 7480 7481 warningMoment = true; 7482 } 7483 } 7484 7485 for (var i in registered) { 7486 registered[i](elapsed, interval, hasWarned, hasExpired, warningMoment, expirationMoment); 7487 } 7488 }, 7489 interval 7490 ); 7491 }, 7492 7493 _stopTimer: function() { 7494 var instance = this; 7495 7496 A.clearInterval(instance._intervalId); 7497 }, 7498 7499 _cookieKey: 'LFR_SESSION_STATE_' + themeDisplay.getUserId() 7500 } 7501 } 7502 ); 7503 7504 SessionBase.SRC = SRC; 7505 7506 var SessionDisplay = A.Component.create( 7507 { 7508 ATTRS: { 7509 pageTitle: { 7510 value: DOC.title 7511 } 7512 }, 7513 EXTENDS: A.Plugin.Base, 7514 NAME: 'liferaysessiondisplay', 7515 NS: 'display', 7516 prototype: { 7517 initializer: function(config) { 7518 var instance = this; 7519 7520 var host = instance.get('host'); 7521 7522 if (Liferay.Util.getTop() == CONFIG.win) { 7523 instance._host = host; 7524 7525 instance._toggleText = { 7526 hide: 'Ocultar', 7527 show: 'Mostrar' 7528 }; 7529 7530 instance._expiredText = 'La\x20sesión\x20expiró\x20por\x20inactividad\x2e\x20Guarde\x20los\x20datos\x20que\x20introdujo\x20antes\x20de\x20actualizar\x20la\x20página\x2e'; 7531 7532 instance._warningText = 'La\x20sesión\x20expirará\x20en\x20\x7b0\x7d\x20por\x20inactividad\x2e\x20Para\x20prolongar\x20la\x20sesión\x20otros\x20\x7b1\x7d\x20minuto\x28s\x29\x2c\x20presione\x20el\x20botón\x20\x3cem\x3eExtender\x3c\x2fem\x3e\x2e\x20\x7b2\x7d'; 7533 instance._warningText = Lang.sub( 7534 instance._warningText, 7535 [ 7536 '<span class="countdown-timer">{0}</span>', 7537 host.get('sessionLength') / 60000, 7538 '<a class="alert-link" href="#">
7538' + 'Extender' + '</a>' 7539 ] 7540 ); 7541 7542 host.on('sessionStateChange', instance._onHostSessionStateChange, instance); 7543 7544 instance.afterHostMethod('_defActivatedFn', instance._afterDefActivatedFn); 7545 instance.afterHostMethod('_defExpiredFn', instance._afterDefExpiredFn); 7546 } 7547 else { 7548 host.unplug(instance); 7549 } 7550 }, 7551 7552 destructor: function() { 7553 var instance = this; 7554 7555 if (instance._banner) { 7556 instance._banner.destroy(); 7557 } 7558 }, 7559 7560 _afterDefActivatedFn: function(event) { 7561 var instance = this; 7562 7563 instance._uiSetActivated(); 7564 }, 7565 7566 _afterDefExpiredFn: function(event) { 7567 var instance = this; 7568 7569 instance._host.unregisterInterval(instance._intervalId); 7570 7571 instance._uiSetExpired(); 7572 }, 7573 7574 _beforeHostWarned: function(event) { 7575 var instance = this; 7576 7577 var host = instance._host; 7578 7579 var sessionLength = host.get('sessionLength'); 7580 var timestamp = host.get('timestamp'); 7581 var warningLength = host.get('warningLength'); 7582 7583 var elapsed = sessionLength; 7584 7585 if (Lang.toInt(timestamp)) { 7586 elapsed = Math.floor((Date.now() - timestamp) / 1000) * 1000; 7587 } 7588 7589 var remainingTime = sessionLength - elapsed; 7590 7591 if (remainingTime > warningLength) { 7592 remainingTime = warningLength; 7593 } 7594 7595 var banner = instance._getBanner(); 7596 7597 var counterTextNode = banner.one('.countdown-timer'); 7598 7599 instance._uiSetRemainingTime(remainingTime, counterTextNode); 7600 7601 banner.show(); 7602 7603 instance._intervalId = host.registerInterval( 7604 function(elapsed, interval, hasWarned, hasExpired, warningMoment, expirationMoment) { 7605 if (!hasWarned) { 7606 instance._uiSetActivated(); 7607 } 7608 else if (!hasExpired) { 7609 if (warningMoment) { 7610 if (remainingTime <= 0) { 7611 remainingTime = warningLength; 7612 } 7613 7614 banner.show(); 7615 } 7616 7617 elapsed = Math.floor((Date.now() - timestamp) / 1000) * 1000; 7618 7619 remainingTime = sessionLength - elapsed; 7620 7621 instance._uiSetRemainingTime(remainingTime, counterTextNode); 7622 7623 } 7624 7625 remainingTime -= interval; 7626 } 7627 ); 7628 }, 7629 7630 _destroyBanner: function() { 7631 var instance = this; 7632 7633 instance._banner = false; 7634 7635 var notificationContainer = A.one('.lfr-notification-container'); 7636 7637 if (notificationContainer) { 7638 notificationContainer.remove(); 7639 } 7640 }, 7641 7642 _formatNumber: function(value) { 7643 var instance = this; 7644 7645 return Lang.String.padNumber(Math.floor(value), 2); 7646 }, 7647 7648 _formatTime: function(time) { 7649 var instance = this; 7650 7651 time = Number(time); 7652 7653 if (Lang.isNumber(time) && time > 0) { 7654 time /= 1000; 7655 7656 BUFFER_TIME[0] = instance._formatNumber(time / 3600); 7657 7658 time %= 3600; 7659 7660 BUFFER_TIME[1] = instance._formatNumber(time / 60); 7661 7662 time %= 60; 7663 7664 BUFFER_TIME[2] = instance._formatNumber(time); 7665 7666 time = BUFFER_TIME.join(':'); 7667 } 7668 else { 7669 time = 0; 7670 } 7671 7672 return time; 7673 }, 7674 7675 _getBanner: function() { 7676 var instance = this; 7677 7678 var banner = instance._banner; 7679 7680 if (!banner) { 7681 banner = new Liferay.Notification( 7682 { 7683 closeable: true, 7684 delay: { 7685 hide: 0, 7686 show: 0 7687 }, 7688 duration: 500, 7689 message: instance._warningText, 7690 on: { 7691 click: function(event) { 7692 if (event.domEvent.target.test('.alert-link')) { 7693 event.domEvent.preventDefault(); 7694 instance._host.extend(); 7695 } 7696 else if (event.domEvent.target.test('.close')) { 7697 instance._destroyBanner(); 7698 instance._alertClosed = true; 7699 } 7700 } 7701 }, 7702 title: 'Advertencia', 7703 type: 'warning' 7704 } 7705 ).render('body'); 7706 7707 instance._banner = banner; 7708 } 7709 7710 return banner; 7711 }, 7712 7713 _onHostSessionStateChange: function(event) { 7714 var instance = this; 7715 7716 if (event.newVal == 'warned') { 7717 instance._beforeHostWarned(event); 7718 } 7719 }, 7720 7721 _uiSetActivated: function() { 7722 var instance = this; 7723 7724 DOC.title = instance.reset('pageTitle').get('pageTitle'); 7725 7726 instance._host.unregisterInterval(instance._intervalId); 7727 7728 var banner = instance._getBanner(); 7729 7730 if (banner) { 7731 instance._destroyBanner(); 7732 } 7733 }, 7734 7735 _uiSetExpired: function() { 7736 var instance = this; 7737 7738 var banner = instance._getBanner(); 7739 7740 banner.setAttrs( 7741 { 7742 message: instance._expiredText, 7743 title: 'Peligro', 7744 type: 'danger' 7745 } 7746 ); 7747 7748 DOC.title = instance.get('pageTitle'); 7749 }, 7750 7751 _uiSetRemainingTime: function(remainingTime) { 7752 var instance = this; 7753 7754 remainingTime = instance._formatTime(remainingTime); 7755 7756 if (!instance._alertClosed) { 7757 var banner = instance._getBanner(); 7758 7759 banner.set( 7760 'message', 7761 Lang.sub( 7762 instance._warningText, 7763 [ 7764 remainingTime 7765 ] 7766 ) 7767 ); 7768 } 7769 7770 DOC.title = Lang.sub('La\x20sesión\x20expira\x20en\x20\x7b0\x7d\x2e', [remainingTime]) + ' | ' + instance.get('pageTitle'); 7771 } 7772 } 7773 } 7774 ); 7775 7776 Liferay.SessionBase = SessionBase; 7777 Liferay.SessionDisplay = SessionDisplay; 7778 }, 7779 '', 7780 { 7781 requires: ['aui-io-request', 'aui-timer', 'cookie', 'liferay-notification'] 7782 } 7783); 7784// For details about this file see: LPS-2155 7785 7786;(function(A, Liferay) { 7787 var Util = Liferay.namespace('Util'); 7788 7789 var Lang = A.Lang; 7790 7791 var AArray = A.Array; 7792 var AObject = A.Object; 7793 var AString = A.Lang.String; 7794 7795 var htmlEscapedValues = []; 7796 var htmlUnescapedValues = []; 7797 7798 var MAP_HTML_CHARS_ESCAPED = { 7799 '"': '"', 7800 '&': '&', 7801 '\'': ''', 7802 '/': '/', 7803 '<': '<', 7804 '>': '>', 7805 '`': '`' 7806 }; 7807 7808 var MAP_HTML_CHARS_UNESCAPED = {}; 7809 7810 AObject.each( 7811 MAP_HTML_CHARS_ESCAPED, 7812 function(item, index) { 7813 MAP_HTML_CHARS_UNESCAPED[item] = index; 7814 7815 htmlEscapedValues.push(item); 7816 htmlUnescapedValues.push(index); 7817 } 7818 ); 7819 7820 var REGEX_DASH = /-([a-z])/gi; 7821 7822 var STR_LEFT_SQUARE_BRACKET = '['; 7823 7824 var STR_RIGHT_SQUARE_BRACKET = ']'; 7825 7826 var REGEX_HTML_ESCAPE = new RegExp(STR_LEFT_SQUARE_BRACKET + htmlUnescapedValues.join('') + STR_RIGHT_SQUARE_BRACKET, 'g'); 7827 7828 var REGEX_HTML_UNESCAPE = new RegExp(htmlEscapedValues.join('|'), 'gi'); 7829 7830 Util.MAP_HTML_CHARS_ESCAPED = MAP_HTML_CHARS_ESCAPED; 7831 7832 Util.actsAsAspect = function(object) { 7833 object.yield = null; 7834 object.rv = {}; 7835 7836 object.before = function(method, f) { 7837 var original = eval('this.' + method); 7838 7839 this[method] = function() { 7840 f.apply(this, arguments); 7841 7842 return original.apply(this, arguments); 7843 }; 7844 }; 7845 7846 object.after = function(method, f) { 7847 var original = eval('this.' + method); 7848 7849 this[method] = function() { 7850 this.rv[method] = original.apply(this, arguments); 7851 7852 return f.apply(this, arguments); 7853 }; 7854 }; 7855 7856 object.around = function(method, f) { 7857 var original = eval('this.' + method); 7858 7859 this[method] = function() { 7860 this.yield = original; 7861 7862 return f.apply(this, arguments); 7863 }; 7864 }; 7865 }; 7866 7867 Util.addInputFocus = function() { 7868 A.use( 7869 'aui-base', 7870 function(A) { 7871 var handleFocus = function(event) { 7872 var target = event.target; 7873 7874 var tagName = target.get('tagName'); 7875 7876 if (tagName) { 7877 tagName = tagName.toLowerCase(); 7878 } 7879 7880 var nodeType = target.get('type'); 7881 7882 if (tagName == 'input' && (/text|password/).test(nodeType) || tagName == 'textarea') { 7883 var action = 'addClass'; 7884 7885 if (/blur|focusout/.test(event.type)) { 7886 action = 'removeClass'; 7887 } 7888 7889 target[action]('focus'); 7890 } 7891 }; 7892 7893 A.on('focus', handleFocus, document); 7894 A.on('blur', handleFocus, document); 7895 } 7896 ); 7897 7898 Util.addInputFocus = function() { 7899 }; 7900 }; 7901 7902 Util.addInputType = function(el) { 7903 Util.addInputType = Lang.emptyFn; 7904 7905 if (Liferay.Browser.isIe() && Liferay.Browser.getMajorVersion() < 7) { 7906 Util.addInputType = function(el) { 7907 if (el) { 7908 el = A.one(el); 7909 } 7910 else { 7911 el = A.one(document.body); 7912 } 7913 7914 var defaultType = 'text'; 7915 7916 el.all('input').each( 7917 function(item, index) { 7918 var type = item.get('type') || defaultType; 7919 7920 item.addClass(type); 7921 } 7922 ); 7923 }; 7924 } 7925 7926 return Util.addInputType(el); 7927 }; 7928 7929 Util.camelize = function(value, separator) { 7930 var regex = REGEX_DASH; 7931 7932 if (separator) { 7933 regex = new RegExp(separator + '([a-z])', 'gi'); 7934 } 7935 7936 value = value.replace( 7937 regex, 7938 function(match0, match1) { 7939 return match1.toUpperCase(); 7940 } 7941 ); 7942 7943 return value; 7944 }; 7945 7946 Util.clamp = function(value, min, max) { 7947 return Math.min(Math.max(value, min), max); 7948 }; 7949 7950 Util.escapeHTML = function(str, preventDoubleEscape, entities) { 7951 var regex = REGEX_HTML_ESCAPE; 7952 7953 var entitiesList = []; 7954 7955 var entitiesValues; 7956 7957 if (Lang.isObject(entities)) { 7958 entitiesValues = []; 7959 7960 AObject.each( 7961 entities, 7962 function(item, index) { 7963 entitiesList.push(index); 7964 7965 entitiesValues.push(item); 7966 } 7967 ); 7968 7969 regex = new RegExp(STR_LEFT_SQUARE_BRACKET + AString.escapeRegEx(entitiesList.join('')) + STR_RIGHT_SQUARE_BRACKET, 'g'); 7970 } 7971 else { 7972 entities = MAP_HTML_CHARS_ESCAPED; 7973 7974 entitiesValues = htmlEscapedValues; 7975 } 7976 7977 return str.replace(regex, A.bind('_escapeHTML', Util, !!preventDoubleEscape, entities, entitiesValues)); 7978 }; 7979 7980 Util.isEditorPresent = function(editorName) { 7981 return Liferay.EDITORS && Liferay.EDITORS[editorName]; 7982 }; 7983 7984 Util.randomMinMax = function(min, max) { 7985 return Math.round(Math.random() * (max - min)) + min; 7986 }; 7987 7988 Util.selectAndCopy = function(el) { 7989 el.focus(); 7990 el.select(); 7991 7992 if (document.all) { 7993 var textRange = el.createTextRange(); 7994 7995 textRange.execCommand('copy'); 7996 } 7997 }; 7998 7999 Util.setBox = function(oldBox, newBox) { 8000 for (var i = oldBox.length - 1; i > -1; i--) { 8001 oldBox.options[i] = null; 8002 } 8003 8004 for (i = 0; i < newBox.length; i++) { 8005 oldBox.options[i] = new Option(newBox[i].value, i); 8006 } 8007 8008 oldBox.options[0].selected = true; 8009 }; 8010 8011 Util.startsWith = function(str, x) { 8012 return str.indexOf(x) === 0; 8013 }; 8014 8015 Util.textareaTabs = function(event) { 8016 var el = event.currentTarget.getDOM(); 8017 8018 if (event.isKey('TAB')) { 8019 event.halt(); 8020 8021 var oldscroll = el.scrollTop; 8022 8023 if (el.setSelectionRange) { 8024 var caretPos = el.selectionStart + 1; 8025 var elValue = el.value; 8026 8027 el.value = elValue.substring(0, el.selectionStart) + '\t' + elValue.substring(el.selectionEnd, elValue.length); 8028 8029 setTimeout( 8030 function() { 8031 el.focus(); 8032 el.setSelectionRange(caretPos, caretPos); 8033 }, 8034 0 8035 ); 8036 8037 } 8038 else { 8039 document.selection.createRange().text = '\t'; 8040 } 8041 8042 el.scrollTop = oldscroll; 8043 8044 return false;
8045 } 8046 }; 8047 8048 Util.uncamelize = function(value, separator) { 8049 separator = separator || ' '; 8050 8051 value = value.replace(/([a-zA-Z][a-zA-Z])([A-Z])([a-z])/g, '$1' + separator + '$2$3'); 8052 value = value.replace(/([a-z])([A-Z])/g, '$1' + separator + '$2'); 8053 8054 return value; 8055 }; 8056 8057 Util.unescapeHTML = function(str, entities) { 8058 var regex = REGEX_HTML_UNESCAPE; 8059 8060 var entitiesMap = MAP_HTML_CHARS_UNESCAPED; 8061 8062 if (entities) { 8063 var entitiesValues = []; 8064 8065 entitiesMap = {}; 8066 8067 AObject.each( 8068 entities, 8069 function(item, index) { 8070 entitiesMap[item] = index; 8071 8072 entitiesValues.push(item); 8073 } 8074 ); 8075 8076 regex = new RegExp(entitiesValues.join('|'), 'gi'); 8077 } 8078 8079 return str.replace(regex, A.bind('_unescapeHTML', Util, entitiesMap)); 8080 }; 8081 8082 Util._escapeHTML = function(preventDoubleEscape, entities, entitiesValues, match) { 8083 var result; 8084 8085 if (preventDoubleEscape) { 8086 var arrayArgs = AArray(arguments); 8087 8088 var length = arrayArgs.length; 8089 8090 var offset = arrayArgs[length - 2]; 8091 var string = arrayArgs[length - 1]; 8092 8093 var nextSemicolonIndex = string.indexOf(';', offset); 8094 8095 if (nextSemicolonIndex >= 0) { 8096 var entity = string.substring(offset, nextSemicolonIndex + 1); 8097 8098 if (entitiesValues.indexOf(entity) >= 0) { 8099 result = match; 8100 } 8101 } 8102 } 8103 8104 if (!result) { 8105 result = entities[match]; 8106 } 8107 8108 return result; 8109 }; 8110 8111 Util._unescapeHTML = function(entities, match) { 8112 return entities[match]; 8113 }; 8114 8115 Liferay.provide( 8116 Util, 8117 'check', 8118 function(form, name, checked) { 8119 var checkbox = A.one(form[name]); 8120 8121 if (checkbox) { 8122 checkbox.attr('checked', checked); 8123 } 8124 }, 8125 ['aui-base'] 8126 ); 8127 8128 Liferay.provide( 8129 Util, 8130 'disableSelectBoxes', 8131 function(toggleBoxId, value, selectBoxId) { 8132 var selectBox = A.one('#' + selectBoxId); 8133 var toggleBox = A.one('#' + toggleBoxId); 8134 8135 if (selectBox && toggleBox) { 8136 var dynamicValue = Lang.isFunction(value); 8137 8138 var disabled = function() { 8139 var currentValue = selectBox.val(); 8140 8141 var visible = value == currentValue; 8142 8143 if (dynamicValue) { 8144 visible = value(currentValue, value); 8145 } 8146 8147 toggleBox.attr('disabled', !visible); 8148 }; 8149 8150 disabled(); 8151 8152 selectBox.on('change', disabled); 8153 } 8154 }, 8155 ['aui-base'] 8156 ); 8157 8158 Liferay.provide( 8159 Util, 8160 'disableTextareaTabs', 8161 function(textarea) { 8162 textarea = A.one(textarea); 8163 8164 if (textarea && textarea.attr('textareatabs') != 'enabled') { 8165 textarea.attr('textareatabs', 'disabled'); 8166 8167 textarea.detach('keydown', Util.textareaTabs); 8168 } 8169 }, 8170 ['aui-base'] 8171 ); 8172 8173 Liferay.provide( 8174 Util, 8175 'enableTextareaTabs', 8176 function(textarea) { 8177 textarea = A.one(textarea); 8178 8179 if (textarea && textarea.attr('textareatabs') != 'enabled') { 8180 textarea.attr('textareatabs', 'disabled'); 8181 8182 textarea.on('keydown', Util.textareaTabs); 8183 } 8184 }, 8185 ['aui-base'] 8186 ); 8187 8188 Liferay.provide( 8189 Util, 8190 'removeItem', 8191 function(box, value) { 8192 box = A.one(box); 8193 8194 var selectedIndex = box.get('selectedIndex'); 8195 8196 if (!value) { 8197 box.all('option').item(selectedIndex).remove(true); 8198 } 8199 else { 8200 box.all('option[value=' + value + STR_RIGHT_SQUARE_BRACKET).item(selectedIndex).remove(true); 8201 } 8202 }, 8203 ['aui-base'] 8204 ); 8205 8206 Liferay.provide( 8207 Util, 8208 'resizeTextarea', 8209 function(elString, usingRichEditor) { 8210 var el = A.one('#' + elString); 8211 8212 if (!el) { 8213 el = A.one('textarea[name=' + elString + STR_RIGHT_SQUARE_BRACKET); 8214 } 8215 8216 if (el) { 8217 var pageBody = A.getBody(); 8218 8219 var diff; 8220 8221 var resize = function(event) { 8222 var pageBodyHeight = pageBody.get('winHeight'); 8223 8224 if (usingRichEditor) { 8225 try { 8226 if (el.get('nodeName').toLowerCase() != 'iframe') { 8227 el = window[elString]; 8228 } 8229 } 8230 catch (e) { 8231 } 8232 } 8233 8234 if (!diff) { 8235 var buttonRow = pageBody.one('.button-holder'); 8236 var templateEditor = pageBody.one('.lfr-template-editor'); 8237 8238 if (buttonRow && templateEditor) { 8239 var region = templateEditor.getXY(); 8240 8241 diff = buttonRow.outerHeight(true) + region[1] + 25; 8242 } 8243 else { 8244 diff = 170; 8245 } 8246 } 8247 8248 el = A.one(el); 8249 8250 var styles = { 8251 width: '98%' 8252 }; 8253 8254 if (event) { 8255 styles.height = pageBodyHeight - diff; 8256 } 8257 8258 if (usingRichEditor) { 8259 if (!el || !A.DOM.inDoc(el)) { 8260 A.on( 8261 'available', 8262 function(event) { 8263 el = A.one(window[elString]); 8264 8265 if (el) { 8266 el.setStyles(styles); 8267 } 8268 }, 8269 '#' + elString + '_cp' 8270 ); 8271 8272 return; 8273 } 8274 } 8275 8276 if (el) { 8277 el.setStyles(styles); 8278 } 8279 }; 8280 8281 resize(); 8282 8283 var dialog = Liferay.Util.getWindow(); 8284 8285 if (dialog) { 8286 var resizeEventHandle = dialog.iframe.after('resizeiframe:heightChange', resize); 8287 8288 A.getWin().on('unload', resizeEventHandle.detach, resizeEventHandle); 8289 } 8290 } 8291 }, 8292 ['aui-base'] 8293 ); 8294 8295 Liferay.provide( 8296 Util, 8297 'setSelectedValue', 8298 function(col, value) { 8299 var option = A.one(col).one('option[value=' + value + STR_RIGHT_SQUARE_BRACKET); 8300 8301 if (option) { 8302 option.attr('selected', true); 8303 } 8304 }, 8305 ['aui-base'] 8306 ); 8307 8308 Liferay.provide( 8309 Util, 8310 'switchEditor', 8311 function(options) { 8312 var uri = options.uri; 8313 8314 var windowName = Liferay.Util.getWindowName(); 8315 8316 var dialog = Liferay.Util.getWindow(windowName); 8317 8318 if (dialog) {
8319 dialog.iframe.set('uri', uri); 8320 } 8321 }, 8322 ['aui-io'] 8323 ); 8324})(AUI(), Liferay);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.