~andreserl/maas/packaging_precise_rebase

« back to all changes in this revision

Viewing changes to debian/extras/jslibs/yui/widget-position-align/widget-position-align.js

  • Committer: Andres Rodriguez
  • Date: 2013-03-20 18:12:30 UTC
  • mfrom: (145.2.22 precise.sru)
  • Revision ID: andreserl@ubuntu.com-20130320181230-6l5guc0nhlv2z4p7
Re-base againts latest quantal released branch towards SRU

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
YUI 3.5.1 (build 22)
 
3
Copyright 2012 Yahoo! Inc. All rights reserved.
 
4
Licensed under the BSD License.
 
5
http://yuilibrary.com/license/
 
6
*/
 
7
YUI.add('widget-position-align', function(Y) {
 
8
 
 
9
/**
 
10
Provides extended/advanced XY positioning support for Widgets, through an
 
11
extension.
 
12
 
 
13
It builds on top of the `widget-position` module, to provide alignment and
 
14
centering support. Future releases aim to add constrained and fixed positioning
 
15
support.
 
16
 
 
17
@module widget-position-align
 
18
**/
 
19
var Lang = Y.Lang,
 
20
 
 
21
    ALIGN        = 'align',
 
22
    ALIGN_ON     = 'alignOn',
 
23
 
 
24
    VISIBLE      = 'visible',
 
25
    BOUNDING_BOX = 'boundingBox',
 
26
 
 
27
    OFFSET_WIDTH    = 'offsetWidth',
 
28
    OFFSET_HEIGHT   = 'offsetHeight',
 
29
    REGION          = 'region',
 
30
    VIEWPORT_REGION = 'viewportRegion';
 
31
 
 
32
/**
 
33
Widget extension, which can be used to add extended XY positioning support to
 
34
the base Widget class, through the `Base.create` method.
 
35
 
 
36
**Note:** This extension requires that the `WidgetPosition` extension be added
 
37
to the Widget (before `WidgetPositionAlign`, if part of the same extension list
 
38
passed to `Base.build`).
 
39
 
 
40
@class WidgetPositionAlign
 
41
@param {Object} config User configuration object.
 
42
@constructor
 
43
**/
 
44
function PositionAlign (config) {
 
45
    if ( ! this._posNode) {
 
46
        Y.error('WidgetPosition needs to be added to the Widget, ' + 
 
47
            'before WidgetPositionAlign is added'); 
 
48
    }
 
49
 
 
50
    Y.after(this._bindUIPosAlign, this, 'bindUI');
 
51
    Y.after(this._syncUIPosAlign, this, 'syncUI');
 
52
}
 
53
 
 
54
PositionAlign.ATTRS = {
 
55
 
 
56
    /**
 
57
    The alignment configuration for this widget.
 
58
 
 
59
    The `align` attribute is used to align a reference point on the widget, with
 
60
    the reference point on another `Node`, or the viewport. The object which
 
61
    `align` expects has the following properties:
 
62
 
 
63
      * __`node`__: The `Node` to which the widget is to be aligned. If set to
 
64
        `null`, or not provided, the widget is aligned to the viewport.
 
65
    
 
66
      * __`points`__: A two element Array, defining the two points on the widget
 
67
        and `Node`/viewport which are to be aligned. The first element is the
 
68
        point on the widget, and the second element is the point on the
 
69
        `Node`/viewport. Supported alignment points are defined as static
 
70
        properties on `WidgetPositionAlign`.
 
71
    
 
72
    @example Aligns the top-right corner of the widget with the top-left corner 
 
73
    of the viewport:
 
74
 
 
75
        myWidget.set('align', {
 
76
            points: [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.TL]
 
77
        });
 
78
    
 
79
    @attribute align
 
80
    @type Object
 
81
    @default null
 
82
    **/
 
83
    align: {
 
84
        value: null
 
85
    },
 
86
 
 
87
    /**
 
88
    A convenience Attribute, which can be used as a shortcut for the `align` 
 
89
    Attribute.
 
90
    
 
91
    If set to `true`, the widget is centered in the viewport. If set to a `Node` 
 
92
    reference or valid selector String, the widget will be centered within the 
 
93
    `Node`. If set to `false`, no center positioning is applied.
 
94
 
 
95
    @attribute centered
 
96
    @type Boolean|Node
 
97
    @default false
 
98
    **/
 
99
    centered: {
 
100
        setter : '_setAlignCenter',
 
101
        lazyAdd:false,
 
102
        value  :false
 
103
    },
 
104
 
 
105
    /**
 
106
    An Array of Objects corresponding to the `Node`s and events that will cause
 
107
    the alignment of this widget to be synced to the DOM.
 
108
 
 
109
    The `alignOn` Attribute is expected to be an Array of Objects with the 
 
110
    following properties:
 
111
 
 
112
      * __`eventName`__: The String event name to listen for.
 
113
 
 
114
      * __`node`__: The optional `Node` that will fire the event, it can be a 
 
115
        `Node` reference or a selector String. This will default to the widget's 
 
116
        `boundingBox`.
 
117
 
 
118
    @example Sync this widget's alignment on window resize:
 
119
 
 
120
        myWidget.set('alignOn', [
 
121
            {
 
122
                node     : Y.one('win'),
 
123
                eventName: 'resize'
 
124
            }
 
125
        ]);
 
126
 
 
127
    @attribute alignOn
 
128
    @type Array
 
129
    @default []
 
130
    **/
 
131
    alignOn: {
 
132
        value    : [],
 
133
        validator: Y.Lang.isArray
 
134
    }
 
135
};
 
136
 
 
137
/**
 
138
Constant used to specify the top-left corner for alignment
 
139
 
 
140
@property TL
 
141
@type String
 
142
@value 'tl'
 
143
@static
 
144
**/
 
145
PositionAlign.TL = 'tl';
 
146
 
 
147
/**
 
148
Constant used to specify the top-right corner for alignment
 
149
 
 
150
@property TR
 
151
@type String
 
152
@value 'tr'
 
153
@static
 
154
**/
 
155
PositionAlign.TR = 'tr';
 
156
 
 
157
/**
 
158
Constant used to specify the bottom-left corner for alignment
 
159
 
 
160
@property BL
 
161
@type String
 
162
@value 'bl'
 
163
@static
 
164
**/
 
165
PositionAlign.BL = 'bl';
 
166
 
 
167
/**
 
168
Constant used to specify the bottom-right corner for alignment
 
169
 
 
170
@property BR
 
171
@type String
 
172
@value 'br'
 
173
@static
 
174
**/
 
175
PositionAlign.BR = 'br';
 
176
 
 
177
/**
 
178
Constant used to specify the top edge-center point for alignment
 
179
 
 
180
@property TC
 
181
@type String
 
182
@value 'tc'
 
183
@static
 
184
**/
 
185
PositionAlign.TC = 'tc';
 
186
 
 
187
/**
 
188
Constant used to specify the right edge, center point for alignment
 
189
 
 
190
@property RC
 
191
@type String
 
192
@value 'rc'
 
193
@static
 
194
**/
 
195
PositionAlign.RC = 'rc';
 
196
 
 
197
/**
 
198
Constant used to specify the bottom edge, center point for alignment
 
199
 
 
200
@property BC
 
201
@type String
 
202
@value 'bc'
 
203
@static
 
204
**/
 
205
PositionAlign.BC = 'bc';
 
206
 
 
207
/**
 
208
Constant used to specify the left edge, center point for alignment
 
209
 
 
210
@property LC
 
211
@type String
 
212
@value 'lc'
 
213
@static
 
214
**/
 
215
PositionAlign.LC = 'lc';
 
216
 
 
217
/**
 
218
Constant used to specify the center of widget/node/viewport for alignment
 
219
 
 
220
@property CC
 
221
@type String
 
222
@value 'cc'
 
223
@static
 
224
*/
 
225
PositionAlign.CC = 'cc';
 
226
 
 
227
PositionAlign.prototype = {
 
228
    // -- Protected Properties -------------------------------------------------
 
229
 
 
230
    /**
 
231
    Holds the alignment-syncing event handles.
 
232
 
 
233
    @property _posAlignUIHandles
 
234
    @type Array
 
235
    @default null
 
236
    @protected
 
237
    **/
 
238
    _posAlignUIHandles: null,
 
239
 
 
240
    // -- Lifecycle Methods ----------------------------------------------------
 
241
 
 
242
    destructor: function () {
 
243
        this._detachPosAlignUIHandles();
 
244
    },
 
245
 
 
246
    /**
 
247
    Bind event listeners responsible for updating the UI state in response to
 
248
    the widget's position-align related state changes.
 
249
 
 
250
    This method is invoked after `bindUI` has been invoked for the `Widget`
 
251
    class using the AOP infrastructure.
 
252
 
 
253
    @method _bindUIPosAlign
 
254
    @protected
 
255
    **/
 
256
    _bindUIPosAlign: function () {
 
257
        this.after('alignChange', this._afterAlignChange);
 
258
        this.after('alignOnChange', this._afterAlignOnChange);
 
259
        this.after('visibleChange', this._syncUIPosAlign);
 
260
    },
 
261
 
 
262
    /**
 
263
    Synchronizes the current `align` Attribute value to the DOM.
 
264
 
 
265
    This method is invoked after `syncUI` has been invoked for the `Widget`
 
266
    class using the AOP infrastructure.
 
267
 
 
268
    @method _syncUIPosAlign
 
269
    @protected
 
270
    **/
 
271
    _syncUIPosAlign: function () {
 
272
        var align = this.get(ALIGN);
 
273
 
 
274
        this._uiSetVisiblePosAlign(this.get(VISIBLE));
 
275
 
 
276
        if (align) {
 
277
            this._uiSetAlign(align.node, align.points);
 
278
        }
 
279
    },
 
280
 
 
281
    // -- Public Methods -------------------------------------------------------
 
282
 
 
283
    /**
 
284
    Aligns this widget to the provided `Node` (or viewport) using the provided
 
285
    points. This method can be invoked with no arguments which will cause the 
 
286
    widget's current `align` Attribute value to be synced to the DOM.
 
287
 
 
288
    @example Aligning to the top-left corner of the `<body>`:
 
289
 
 
290
        myWidget.align('body',
 
291
            [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.TR]);
 
292
 
 
293
    @method align
 
294
    @param {Node|String|null} [node] A reference (or selector String) for the
 
295
      `Node` which with the widget is to be aligned. If null is passed in, the
 
296
      widget will be aligned with the viewport.
 
297
    @param {Array[2]} [points] A two item array specifying the points on the 
 
298
      widget and `Node`/viewport which will to be aligned. The first entry is 
 
299
      the point on the widget, and the second entry is the point on the 
 
300
      `Node`/viewport. Valid point references are defined as static constants on 
 
301
      the `WidgetPositionAlign` extension.
 
302
    @chainable
 
303
    **/
 
304
    align: function (node, points) {
 
305
        if (arguments.length) {
 
306
            // Set the `align` Attribute.
 
307
            this.set(ALIGN, {
 
308
                node  : node,
 
309
                points: points
 
310
            });
 
311
        } else {
 
312
            // Sync the current `align` Attribute value to the DOM.
 
313
            this._syncUIPosAlign();
 
314
        }
 
315
 
 
316
        return this;
 
317
    },
 
318
 
 
319
    /**
 
320
    Centers the widget in the viewport, or if a `Node` is passed in, it will 
 
321
    be centered to that `Node`.
 
322
 
 
323
    @method centered
 
324
    @param {Node|String} [node] A `Node` reference or selector String defining 
 
325
      the `Node` which the widget should be centered. If a `Node` is not  passed
 
326
      in, then the widget will be centered to the viewport.
 
327
    @chainable
 
328
    **/
 
329
    centered: function (node) {
 
330
        return this.align(node, [PositionAlign.CC, PositionAlign.CC]);
 
331
    },
 
332
 
 
333
    // -- Protected Methods ----------------------------------------------------
 
334
 
 
335
    /**
 
336
    Default setter for `center` Attribute changes. Sets up the appropriate
 
337
    value, and passes it through the to the align attribute.
 
338
 
 
339
    @method _setAlignCenter
 
340
    @param {Boolean|Node} val The Attribute value being set.
 
341
    @return {Boolean|Node} the value passed in.
 
342
    @protected
 
343
    **/
 
344
    _setAlignCenter: function (val) {
 
345
        if (val) {
 
346
            this.set(ALIGN, {
 
347
                node  : val === true ? null : val,
 
348
                points: [PositionAlign.CC, PositionAlign.CC]
 
349
            });
 
350
        }
 
351
 
 
352
        return val;
 
353
    },
 
354
 
 
355
    /**
 
356
    Updates the UI to reflect the `align` value passed in.
 
357
 
 
358
    **Note:** See the `align` Attribute documentation, for the Object structure
 
359
    expected.
 
360
 
 
361
    @method _uiSetAlign
 
362
    @param {Node|String|null} [node] The node to align to, or null to indicate
 
363
      the viewport.
 
364
    @param {Array} points The alignment points.
 
365
    @protected
 
366
    **/
 
367
    _uiSetAlign: function (node, points) {
 
368
        if ( ! Lang.isArray(points) || points.length !== 2) {
 
369
            Y.error('align: Invalid Points Arguments');
 
370
            return;
 
371
        }
 
372
 
 
373
        var nodeRegion = this._getRegion(node), 
 
374
            widgetPoint, nodePoint, xy;
 
375
 
 
376
        if ( ! nodeRegion) {
 
377
            // No-op, nothing to align to.
 
378
            return;
 
379
        }
 
380
 
 
381
        widgetPoint = points[0];
 
382
        nodePoint   = points[1];
 
383
 
 
384
        // TODO: Optimize KWeight - Would lookup table help?
 
385
        switch (nodePoint) {
 
386
        case PositionAlign.TL:
 
387
            xy = [nodeRegion.left, nodeRegion.top];
 
388
            break;
 
389
 
 
390
        case PositionAlign.TR:
 
391
            xy = [nodeRegion.right, nodeRegion.top];
 
392
            break;
 
393
 
 
394
        case PositionAlign.BL:
 
395
            xy = [nodeRegion.left, nodeRegion.bottom];
 
396
            break;
 
397
 
 
398
        case PositionAlign.BR:
 
399
            xy = [nodeRegion.right, nodeRegion.bottom];
 
400
            break;
 
401
 
 
402
        case PositionAlign.TC:
 
403
            xy = [
 
404
                nodeRegion.left + Math.floor(nodeRegion.width / 2),
 
405
                nodeRegion.top
 
406
            ];
 
407
            break;
 
408
 
 
409
        case PositionAlign.BC:
 
410
            xy = [
 
411
                nodeRegion.left + Math.floor(nodeRegion.width / 2),
 
412
                nodeRegion.bottom
 
413
            ];
 
414
            break;
 
415
 
 
416
        case PositionAlign.LC:
 
417
            xy = [
 
418
                nodeRegion.left,
 
419
                nodeRegion.top + Math.floor(nodeRegion.height / 2)
 
420
            ];
 
421
            break;
 
422
 
 
423
        case PositionAlign.RC:
 
424
            xy = [
 
425
                nodeRegion.right,
 
426
                nodeRegion.top + Math.floor(nodeRegion.height / 2)
 
427
            ];
 
428
            break;
 
429
 
 
430
        case PositionAlign.CC:
 
431
            xy = [
 
432
                nodeRegion.left + Math.floor(nodeRegion.width / 2),
 
433
                nodeRegion.top + Math.floor(nodeRegion.height / 2)
 
434
            ];
 
435
            break;
 
436
 
 
437
        default:
 
438
            break;
 
439
 
 
440
        }
 
441
 
 
442
        if (xy) {
 
443
            this._doAlign(widgetPoint, xy[0], xy[1]);
 
444
        }
 
445
    },
 
446
 
 
447
    /**
 
448
    Attaches or detaches alignment-syncing event handlers based on the widget's
 
449
    `visible` Attribute state.
 
450
 
 
451
    @method _uiSetVisiblePosAlign
 
452
    @param {Boolean} visible The current value of the widget's `visible`
 
453
      Attribute.
 
454
    @protected
 
455
    **/
 
456
    _uiSetVisiblePosAlign: function (visible) {
 
457
        if (visible) {
 
458
            this._attachPosAlignUIHandles();
 
459
        } else {
 
460
            this._detachPosAlignUIHandles();
 
461
        }
 
462
    },
 
463
 
 
464
    /**
 
465
    Attaches the alignment-syncing event handlers.
 
466
 
 
467
    @method _attachPosAlignUIHandles
 
468
    @protected
 
469
    **/
 
470
    _attachPosAlignUIHandles: function () {
 
471
        if (this._posAlignUIHandles) {
 
472
            // No-op if we have already setup the event handlers.
 
473
            return;
 
474
        }
 
475
 
 
476
        var bb        = this.get(BOUNDING_BOX),
 
477
            syncAlign = Y.bind(this._syncUIPosAlign, this),
 
478
            handles   = [];
 
479
 
 
480
        Y.Array.each(this.get(ALIGN_ON), function (o) {
 
481
            var event = o.eventName,
 
482
                node  = Y.one(o.node) || bb;
 
483
            
 
484
            if (event) {
 
485
                handles.push(node.on(event, syncAlign));
 
486
            }
 
487
        });
 
488
 
 
489
        this._posAlignUIHandles = handles;
 
490
    },
 
491
 
 
492
    /**
 
493
    Detaches the alignment-syncing event handlers.
 
494
 
 
495
    @method _detachPosAlignUIHandles
 
496
    @protected
 
497
    **/
 
498
    _detachPosAlignUIHandles: function () {
 
499
        var handles = this._posAlignUIHandles;
 
500
        if (handles) {
 
501
            new Y.EventHandle(handles).detach();
 
502
            this._posAlignUIHandles = null;
 
503
        }
 
504
    },
 
505
 
 
506
    // -- Private Methods ------------------------------------------------------
 
507
 
 
508
    /**
 
509
    Helper method, used to align the given point on the widget, with the XY page
 
510
    coordinates provided.
 
511
 
 
512
    @method _doAlign
 
513
    @param {String} widgetPoint Supported point constant
 
514
      (e.g. WidgetPositionAlign.TL)
 
515
    @param {Number} x X page coordinate to align to.
 
516
    @param {Number} y Y page coordinate to align to.
 
517
    @private
 
518
    **/
 
519
    _doAlign: function (widgetPoint, x, y) {
 
520
        var widgetNode = this._posNode,
 
521
            xy;
 
522
 
 
523
        switch (widgetPoint) {
 
524
        case PositionAlign.TL:
 
525
            xy = [x, y];
 
526
            break;
 
527
 
 
528
        case PositionAlign.TR:
 
529
            xy = [
 
530
                x - widgetNode.get(OFFSET_WIDTH),
 
531
                y
 
532
            ];
 
533
            break;
 
534
 
 
535
        case PositionAlign.BL:
 
536
            xy = [
 
537
                x,
 
538
                y - widgetNode.get(OFFSET_HEIGHT)
 
539
            ];
 
540
            break;
 
541
 
 
542
        case PositionAlign.BR:
 
543
            xy = [
 
544
                x - widgetNode.get(OFFSET_WIDTH),
 
545
                y - widgetNode.get(OFFSET_HEIGHT)
 
546
            ];
 
547
            break;
 
548
 
 
549
        case PositionAlign.TC:
 
550
            xy = [
 
551
                x - (widgetNode.get(OFFSET_WIDTH) / 2),
 
552
                y
 
553
            ];
 
554
            break;
 
555
 
 
556
        case PositionAlign.BC:
 
557
            xy = [
 
558
                x - (widgetNode.get(OFFSET_WIDTH) / 2),
 
559
                y - widgetNode.get(OFFSET_HEIGHT)
 
560
            ];
 
561
            break;
 
562
 
 
563
        case PositionAlign.LC:
 
564
            xy = [
 
565
                x,
 
566
                y - (widgetNode.get(OFFSET_HEIGHT) / 2)
 
567
            ];
 
568
            break;
 
569
 
 
570
        case PositionAlign.RC:
 
571
            xy = [
 
572
                x - widgetNode.get(OFFSET_WIDTH),
 
573
                y - (widgetNode.get(OFFSET_HEIGHT) / 2)
 
574
            ];
 
575
            break;
 
576
 
 
577
        case PositionAlign.CC:
 
578
            xy = [
 
579
                x - (widgetNode.get(OFFSET_WIDTH) / 2),
 
580
                y - (widgetNode.get(OFFSET_HEIGHT) / 2)
 
581
            ];
 
582
            break;
 
583
 
 
584
        default:
 
585
            break;
 
586
 
 
587
        }
 
588
 
 
589
        if (xy) {
 
590
            this.move(xy);
 
591
        }
 
592
    },
 
593
 
 
594
    /**
 
595
    Returns the region of the passed-in `Node`, or the viewport region if
 
596
    calling with passing in a `Node`.
 
597
 
 
598
    @method _getRegion
 
599
    @param {Node} [node] The node to get the region of.
 
600
    @return {Object} The node's region.
 
601
    @private
 
602
    **/
 
603
    _getRegion: function (node) {
 
604
        var nodeRegion;
 
605
 
 
606
        if ( ! node) {
 
607
            nodeRegion = this._posNode.get(VIEWPORT_REGION);
 
608
        } else {
 
609
            node = Y.Node.one(node);
 
610
            if (node) {
 
611
                nodeRegion = node.get(REGION);
 
612
            }
 
613
        }
 
614
 
 
615
        return nodeRegion;
 
616
    },
 
617
 
 
618
    // -- Protected Event Handlers ---------------------------------------------
 
619
 
 
620
    /**
 
621
    Handles `alignChange` events by updating the UI in response to `align`
 
622
    Attribute changes.
 
623
 
 
624
    @method _afterAlignChange
 
625
    @param {EventFacade} e
 
626
    @protected
 
627
    **/
 
628
    _afterAlignChange: function (e) {
 
629
        var align = e.newVal;
 
630
        if (align) {
 
631
            this._uiSetAlign(align.node, align.points);               
 
632
        }
 
633
    },
 
634
 
 
635
    /**
 
636
    Handles `alignOnChange` events by updating the alignment-syncing event
 
637
    handlers.
 
638
 
 
639
    @method _afterAlignOnChange
 
640
    @param {EventFacade} e
 
641
    @protected
 
642
    **/
 
643
    _afterAlignOnChange: function(e) {
 
644
        this._detachPosAlignUIHandles();
 
645
 
 
646
        if (this.get(VISIBLE)) {
 
647
            this._attachPosAlignUIHandles();
 
648
        }
 
649
    }
 
650
};
 
651
 
 
652
Y.WidgetPositionAlign = PositionAlign;
 
653
 
 
654
 
 
655
}, '3.5.1' ,{requires:['widget-position']});