~bac/juju-gui/trunkcopy

« back to all changes in this revision

Viewing changes to lib/yui/docs/widget/widget-tooltip.html

  • Committer: kapil.foss at gmail
  • Date: 2012-07-13 18:45:59 UTC
  • Revision ID: kapil.foss@gmail.com-20120713184559-2xl7be17egsrz0c9
reshape

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<!DOCTYPE html>
2
 
<html lang="en">
3
 
<head>
4
 
    <meta charset="utf-8">
5
 
    <title>Example: Creating a Simple Tooltip Widget With Extensions</title>
6
 
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Maven+Pro:400,700">
7
 
    <link rel="stylesheet" href="../../build/cssgrids/grids-min.css">
8
 
    <link rel="stylesheet" href="../assets/css/main.css">
9
 
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
10
 
    <script src="../../build/yui/yui-min.js"></script>
11
 
</head>
12
 
<body>
13
 
 
14
 
<div id="doc">
15
 
    <h1>Example: Creating a Simple Tooltip Widget With Extensions</h1>
16
 
 
17
 
    
18
 
 
19
 
    <div class="yui3-g">
20
 
        <div class="yui3-u-3-4">
21
 
            <div id="main">
22
 
                <div class="content"><style type="text/css" scoped>
23
 
    .yui3-tooltip {
24
 
        position:absolute;
25
 
    }
26
 
 
27
 
    .yui3-tooltip-content {
28
 
        color: #000;
29
 
        padding: 2px 5px;
30
 
        border-color: #D4C237 #A6982B #A6982B #A6982B;
31
 
        border-width: 1px;
32
 
        border-style: solid;
33
 
        background-color: #FFEE69;
34
 
    }
35
 
 
36
 
    .yui3-tooltip-hidden {
37
 
        visibility:hidden;
38
 
    }
39
 
 
40
 
    div.yui3-hastooltip {
41
 
        border:1px solid #243356;
42
 
        background-color:#406ED9;
43
 
        color:#ffffff;
44
 
        width:25em;
45
 
        margin:20px 0px;
46
 
        padding:5px;
47
 
        cursor:default;
48
 
    }
49
 
 
50
 
    div.yui3-hastooltip span {
51
 
        font-style:italic;
52
 
        font-weight:bold;
53
 
        color:#ABCEFF;
54
 
    }
55
 
 
56
 
    .yui3-tooltip-content strong {
57
 
        font-weight:bold;
58
 
    }
59
 
</style>
60
 
 
61
 
<div class="intro">
62
 
    <p>This is an advanced example, in which we create a Tooltip widget, by extending the base <code>Widget</code> class, and adding <code>WidgetStack</code> and <code>WidgetPosition</code> extensions, through <code>Base.build</code>.</p>
63
 
</div>
64
 
 
65
 
<div class="example">
66
 
    <div id="delegate">
67
 
    <div class="yui3-hastooltip" title="Tooltip 1" id="tt1">Tooltip One <span>(content from title)</span></div>
68
 
    <div class="yui3-hastooltip" title="Tooltip 2" id="tt2">Tooltip Two <span>(content set in event listener)</span></div>
69
 
    <div class="yui3-hastooltip" title="Tooltip 3" id="tt3">Tooltip Three <span>(content from lookup)</span></div>
70
 
    <div class="yui3-hastooltip" title="Tooltip 4" id="tt4">Tooltip Four <span>(content from title)</span></div>
71
 
    <label><input type="checkbox" id="prevent" /> Prevent Tooltip Four</label>
72
 
</div>
73
 
 
74
 
<script type="text/javascript">
75
 
YUI().use("event-mouseenter", "widget", "widget-position", "widget-stack", function(Y) {
76
 
    var Lang = Y.Lang,
77
 
        Node = Y.Node,
78
 
        OX = -10000,
79
 
        OY = -10000;
80
 
 
81
 
    var Tooltip = Y.Base.create("tooltip", Y.Widget, [Y.WidgetPosition, Y.WidgetStack], {
82
 
 
83
 
        // PROTOTYPE METHODS/PROPERTIES
84
 
 
85
 
        /*
86
 
         * Initialization Code: Sets up privately used state
87
 
         * properties, and publishes the events Tooltip introduces
88
 
         */
89
 
        initializer : function(config) {
90
 
 
91
 
            this._triggerClassName = this.getClassName("trigger");
92
 
 
93
 
            // Currently bound trigger node information
94
 
            this._currTrigger = {
95
 
                node: null,
96
 
                title: null,
97
 
                mouseX: Tooltip.OFFSCREEN_X,
98
 
                mouseY: Tooltip.OFFSCREEN_Y
99
 
            };
100
 
 
101
 
            // Event handles - mouse over is set on the delegate
102
 
            // element, mousemove and mouseleave are set on the trigger node
103
 
            this._eventHandles = {
104
 
                delegate: null,
105
 
                trigger: {
106
 
                    mouseMove : null,
107
 
                    mouseOut: null
108
 
                }
109
 
            };
110
 
 
111
 
            // Show/hide timers
112
 
            this._timers = {
113
 
                show: null,
114
 
                hide: null
115
 
            };
116
 
 
117
 
            // Publish events introduced by Tooltip. Note the triggerEnter event is preventable,
118
 
            // with the default behavior defined in the _defTriggerEnterFn method 
119
 
            this.publish("triggerEnter", {defaultFn: this._defTriggerEnterFn, preventable:true});
120
 
            this.publish("triggerLeave", {preventable:false});
121
 
        },
122
 
 
123
 
        /*
124
 
         * Destruction Code: Clears event handles, timers,
125
 
         * and current trigger information
126
 
         */
127
 
        destructor : function() {
128
 
            this._clearCurrentTrigger();
129
 
            this._clearTimers();
130
 
            this._clearHandles();
131
 
        },
132
 
 
133
 
        /*
134
 
         * bindUI is used to bind attribute change and dom event
135
 
         * listeners
136
 
         */
137
 
        bindUI : function() {
138
 
            this.after("delegateChange", this._afterSetDelegate);
139
 
            this.after("nodesChange", this._afterSetNodes);
140
 
 
141
 
            this._bindDelegate();
142
 
        },
143
 
 
144
 
        /*
145
 
         * syncUI is used to update the rendered DOM, based on the current
146
 
         * Tooltip state
147
 
         */
148
 
        syncUI : function() {
149
 
            this._uiSetNodes(this.get("triggerNodes"));
150
 
        },
151
 
 
152
 
        /*
153
 
         * Public method, which can be used by triggerEvent event listeners
154
 
         * to set the content of the tooltip for the current trigger node
155
 
         */
156
 
        setTriggerContent : function(content) {
157
 
            var contentBox = this.get("contentBox");
158
 
            contentBox.set("innerHTML", "");
159
 
 
160
 
            if (content) {
161
 
                if (content instanceof Node) {
162
 
                    for (var i = 0, l = content.size(); i < l; ++i) {
163
 
                        contentBox.appendChild(content.item(i));
164
 
                    }
165
 
                } else if (Lang.isString(content)) {
166
 
                    contentBox.set("innerHTML", content);
167
 
                }
168
 
            }
169
 
        },
170
 
 
171
 
        /*
172
 
         * Default attribute change listener for 
173
 
         * the triggerNodes attribute
174
 
         */
175
 
        _afterSetNodes : function(e) {
176
 
            this._uiSetNodes(e.newVal);
177
 
        },
178
 
 
179
 
        /*
180
 
         * Default attribute change listener for 
181
 
         * the delegate attribute
182
 
         */
183
 
        _afterSetDelegate : function(e) {
184
 
            this._bindDelegate(e.newVal);
185
 
        },
186
 
 
187
 
        /*
188
 
         * Updates the rendered DOM to reflect the
189
 
         * set of trigger nodes passed in
190
 
         */
191
 
        _uiSetNodes : function(nodes) {
192
 
            if (this._triggerNodes) {
193
 
                this._triggerNodes.removeClass(this._triggerClassName);
194
 
            }
195
 
 
196
 
            if (nodes) {
197
 
                this._triggerNodes = nodes;
198
 
                this._triggerNodes.addClass(this._triggerClassName);
199
 
            }
200
 
        },
201
 
 
202
 
        /*
203
 
         * Attaches the default mouseover DOM listener to the 
204
 
         * current delegate node
205
 
         */
206
 
        _bindDelegate : function() {
207
 
            var eventHandles = this._eventHandles;
208
 
 
209
 
            if (eventHandles.delegate) {
210
 
                eventHandles.delegate.detach();
211
 
                eventHandles.delegate = null;
212
 
            }
213
 
            eventHandles.delegate = Y.delegate("mouseenter", Y.bind(this._onNodeMouseEnter, this), this.get("delegate"), "." + this._triggerClassName);
214
 
        },
215
 
 
216
 
        /*
217
 
         * Default mouse enter DOM event listener.
218
 
         * 
219
 
         * Delegates to the _enterTrigger method,
220
 
         * if the mouseover enters a trigger node.
221
 
         */
222
 
        _onNodeMouseEnter : function(e) {
223
 
            var node = e.currentTarget;
224
 
            if (node && (!this._currTrigger.node || !node.compareTo(this._currTrigger.node))) {
225
 
                this._enterTrigger(node, e.pageX, e.pageY);
226
 
            }
227
 
        },
228
 
 
229
 
        /*
230
 
         * Default mouse leave DOM event listener
231
 
         * 
232
 
         * Delegates to _leaveTrigger if the mouse
233
 
         * leaves the current trigger node
234
 
         */
235
 
        _onNodeMouseLeave : function(e) {
236
 
            this._leaveTrigger(e.currentTarget);
237
 
        },
238
 
 
239
 
        /*
240
 
         * Default mouse move DOM event listener
241
 
         */
242
 
        _onNodeMouseMove : function(e) {
243
 
            this._overTrigger(e.pageX, e.pageY);
244
 
        },
245
 
 
246
 
        /*
247
 
         * Default handler invoked when the mouse enters
248
 
         * a trigger node. Fires the triggerEnter
249
 
         * event which can be prevented by listeners to 
250
 
         * show the tooltip from being displayed.
251
 
         */
252
 
        _enterTrigger : function(node, x, y) {
253
 
            this._setCurrentTrigger(node, x, y);
254
 
            this.fire("triggerEnter", {node:node, pageX:x, pageY:y});
255
 
        },
256
 
 
257
 
        /*
258
 
         * Default handler for the triggerEvent event,
259
 
         * which will setup the timer to display the tooltip,
260
 
         * if the default handler has not been prevented.
261
 
         */
262
 
        _defTriggerEnterFn : function(e) {
263
 
            var node = e.node;
264
 
            if (!this.get("disabled")) {
265
 
                this._clearTimers();
266
 
                var delay = (this.get("visible")) ? 0 : this.get("showDelay");
267
 
                this._timers.show = Y.later(delay, this, this._showTooltip, [node]);
268
 
            }
269
 
        },
270
 
 
271
 
        /*
272
 
         * Default handler invoked when the mouse leaves
273
 
         * the current trigger node. Fires the triggerLeave
274
 
         * event and sets up the hide timer
275
 
         */
276
 
        _leaveTrigger : function(node) {
277
 
            this.fire("triggerLeave");
278
 
 
279
 
            this._clearCurrentTrigger();
280
 
            this._clearTimers();
281
 
 
282
 
            this._timers.hide = Y.later(this.get("hideDelay"), this, this._hideTooltip);
283
 
        },
284
 
 
285
 
        /*
286
 
         * Default handler invoked for mousemove events
287
 
         * on the trigger node. Stores the current mouse 
288
 
         * x, y positions
289
 
         */
290
 
        _overTrigger : function(x, y) {
291
 
            this._currTrigger.mouseX = x;
292
 
            this._currTrigger.mouseY = y;
293
 
        },
294
 
 
295
 
        /*
296
 
         * Shows the tooltip, after moving it to the current mouse
297
 
         * position.
298
 
         */
299
 
        _showTooltip : function(node) {
300
 
            var x = this._currTrigger.mouseX;
301
 
            var y = this._currTrigger.mouseY;
302
 
 
303
 
            this.move(x + Tooltip.OFFSET_X, y + Tooltip.OFFSET_Y);
304
 
 
305
 
            this.show();
306
 
            this._clearTimers();
307
 
 
308
 
            this._timers.hide = Y.later(this.get("autoHideDelay"), this, this._hideTooltip);
309
 
        },
310
 
 
311
 
        /*
312
 
         * Hides the tooltip, after clearing existing timers.
313
 
         */
314
 
        _hideTooltip : function() {
315
 
            this._clearTimers();
316
 
            this.hide();
317
 
        },
318
 
 
319
 
        /*
320
 
         * Set the rendered content of the tooltip for the current
321
 
         * trigger, based on (in order of precedence):
322
 
         * 
323
 
         * a). The string/node content attribute value
324
 
         * b). From the content lookup map if it is set, or 
325
 
         * c). From the title attribute if set.
326
 
         */
327
 
        _setTriggerContent : function(node) {
328
 
            var content = this.get("content");
329
 
            if (content && !(content instanceof Node || Lang.isString(content))) {
330
 
                content = content[node.get("id")] || node.getAttribute("title");
331
 
            }
332
 
            this.setTriggerContent(content);
333
 
        },
334
 
 
335
 
        /*
336
 
         * Set the currently bound trigger node information, clearing 
337
 
         * out the title attribute if set and setting up mousemove/out 
338
 
         * listeners.
339
 
         */
340
 
        _setCurrentTrigger : function(node, x, y) {
341
 
 
342
 
            var currTrigger = this._currTrigger,
343
 
                triggerHandles = this._eventHandles.trigger;
344
 
 
345
 
            this._setTriggerContent(node);
346
 
 
347
 
            triggerHandles.mouseMove = Y.on("mousemove", Y.bind(this._onNodeMouseMove, this), node);
348
 
            triggerHandles.mouseOut = Y.on("mouseleave", Y.bind(this._onNodeMouseLeave, this), node);
349
 
 
350
 
            var title = node.getAttribute("title");
351
 
            node.setAttribute("title", "");
352
 
 
353
 
            currTrigger.mouseX = x;
354
 
            currTrigger.mouseY = y;
355
 
            currTrigger.node = node;
356
 
            currTrigger.title = title;
357
 
        },
358
 
 
359
 
        /*
360
 
         * Clear out the current trigger state, restoring
361
 
         * the title attribute on the trigger node, 
362
 
         * if it was originally set.
363
 
         */
364
 
        _clearCurrentTrigger : function() {
365
 
 
366
 
            var currTrigger = this._currTrigger,
367
 
                triggerHandles = this._eventHandles.trigger;
368
 
 
369
 
            if (currTrigger.node) {
370
 
                var node = currTrigger.node;
371
 
                var title = currTrigger.title || "";
372
 
 
373
 
                currTrigger.node = null;
374
 
                currTrigger.title = "";
375
 
 
376
 
                triggerHandles.mouseMove.detach();
377
 
                triggerHandles.mouseOut.detach();
378
 
                triggerHandles.mouseMove = null;
379
 
                triggerHandles.mouseOut = null;
380
 
 
381
 
                node.setAttribute("title", title);
382
 
            }
383
 
        },
384
 
 
385
 
        /*
386
 
         * Cancel any existing show/hide timers
387
 
         */
388
 
        _clearTimers : function() {
389
 
            var timers = this._timers;
390
 
            if (timers.hide) {
391
 
                timers.hide.cancel();
392
 
                timers.hide = null;
393
 
            }
394
 
            if (timers.show) {
395
 
              timers.show.cancel();
396
 
              timers.show = null;
397
 
            }
398
 
        },
399
 
 
400
 
        /*
401
 
         * Detach any stored event handles
402
 
         */
403
 
        _clearHandles : function() {
404
 
            var eventHandles = this._eventHandles;
405
 
 
406
 
            if (eventHandles.delegate) {
407
 
                this._eventHandles.delegate.detach();
408
 
            }
409
 
            if (eventHandles.trigger.mouseOut) {
410
 
                eventHandles.trigger.mouseOut.detach();
411
 
            }
412
 
            if (eventHandles.trigger.mouseMove) {
413
 
                eventHandles.trigger.mouseMove.detach();
414
 
            }
415
 
        }
416
 
    }, {
417
 
    
418
 
        // STATIC METHODS/PROPERTIES
419
 
       
420
 
        OFFSET_X : 15,
421
 
        OFFSET_Y : 15,
422
 
        OFFSCREEN_X : OX,
423
 
        OFFSCREEN_Y : OY,
424
 
 
425
 
        ATTRS : {
426
 
    
427
 
            /* 
428
 
             * The tooltip content. This can either be a fixed content value, 
429
 
             * or a map of id-to-values, designed to be used when a single
430
 
             * tooltip is mapped to multiple trigger elements.
431
 
             */
432
 
            content : {
433
 
                value: null
434
 
            },
435
 
    
436
 
            /* 
437
 
             * The set of nodes to bind to the tooltip instance. Can be a string, 
438
 
             * or a node instance.
439
 
             */
440
 
            triggerNodes : {
441
 
                value: null,
442
 
                setter: function(val) {
443
 
                    if (val && Lang.isString(val)) {
444
 
                        val = Node.all(val);
445
 
                    }
446
 
                    return val;
447
 
                }
448
 
            },
449
 
    
450
 
            /*
451
 
             * The delegate node to which event listeners should be attached.
452
 
             * This node should be an ancestor of all trigger nodes bound
453
 
             * to the instance. By default the document is used.
454
 
             */
455
 
            delegate : {
456
 
                value: null,
457
 
                setter: function(val) {
458
 
                    return Y.one(val) || Y.one("document");
459
 
                }
460
 
            },
461
 
    
462
 
            /*
463
 
             * The time to wait, after the mouse enters the trigger node,
464
 
             * to display the tooltip
465
 
             */
466
 
            showDelay : {
467
 
                value:250
468
 
            },
469
 
    
470
 
            /*
471
 
             * The time to wait, after the mouse leaves the trigger node,
472
 
             * to hide the tooltip
473
 
             */
474
 
            hideDelay : {
475
 
                value:10
476
 
            },
477
 
    
478
 
            /*
479
 
             * The time to wait, after the tooltip is first displayed for 
480
 
             * a trigger node, to hide it, if the mouse has not left the 
481
 
             * trigger node
482
 
             */
483
 
            autoHideDelay : {
484
 
                value:2000
485
 
            },
486
 
    
487
 
            /*
488
 
             * Override the default visibility set by the widget base class
489
 
             */
490
 
            visible : {
491
 
                value:false
492
 
            },
493
 
    
494
 
            /*
495
 
             * Override the default XY value set by the widget base class,
496
 
             * to position the tooltip offscreen
497
 
             */
498
 
            xy: {
499
 
                value:[OX, OY]
500
 
            }
501
 
        }
502
 
    });
503
 
 
504
 
    var tt = new Tooltip({
505
 
        triggerNodes:".yui3-hastooltip",
506
 
        delegate: "#delegate",
507
 
        content: {
508
 
            tt3: "Tooltip 3 (from lookup)"
509
 
        },
510
 
        shim:false,
511
 
        zIndex:2
512
 
    });
513
 
    tt.render();
514
 
 
515
 
    tt.on("triggerEnter", function(e) {
516
 
        var node = e.node;
517
 
        if (node && node.get("id") == "tt2") {
518
 
            this.setTriggerContent("Tooltip 2 (from triggerEvent)");
519
 
        }
520
 
    });
521
 
 
522
 
    var prevent = Y.one("#prevent");
523
 
    tt.on("triggerEnter", function(e) {
524
 
        var node = e.node;
525
 
        if (prevent.get("checked")) {
526
 
            if (node && node.get("id") == "tt4") {
527
 
                e.preventDefault();
528
 
            }
529
 
        }
530
 
    });
531
 
});
532
 
</script>
533
 
 
534
 
</div>
535
 
 
536
 
<h2>Creating A Tooltip Widget Class</h2>
537
 
 
538
 
<h3>Basic Class Structure</h3>
539
 
 
540
 
<p>As with the basic <a href="widget-extend.html">"Extending Widget"</a> example, the <code>Tooltip</code> class will extend the <code>Widget</code> base class and follows the same pattern we use for other classes which extend Base.</p>
541
 
 
542
 
<p>Namely:</p>
543
 
 
544
 
<ul>
545
 
    <li>Set up the constructor to invoke the superclass constructor</li>
546
 
    <li>Define a <code>NAME</code> property, to identify the class</li>
547
 
    <li>Define the default attribute configuration, using the <code>ATTRS</code> property</li>
548
 
    <li>Implement prototype methods</li>
549
 
</ul>
550
 
 
551
 
<p>This basic structure is shown below:</p>
552
 
 
553
 
<pre class="code prettyprint">&#x2F;* 
554
 
 *  Required NAME static field, used to identify the Widget class and 
555
 
 *  used as an event prefix, to generate class names etc. (set to the 
556
 
 *  class name in camel case). 
557
 
 *&#x2F;
558
 
Tooltip.NAME = &quot;tooltip&quot;;
559
 
 
560
 
&#x2F;* Default Tooltip Attributes *&#x2F;
561
 
Tooltip.ATTRS = {
562
 
 
563
 
    &#x2F;* 
564
 
     * The tooltip content. This can either be a fixed content value, 
565
 
     * or a map of id-to-values, designed to be used when a single
566
 
     * tooltip is mapped to multiple trigger elements.
567
 
     *&#x2F;
568
 
    content : {
569
 
        value: null
570
 
    },
571
 
 
572
 
    &#x2F;* 
573
 
     * The set of nodes to bind to the tooltip instance. Can be a string, 
574
 
     * or a node instance.
575
 
     *&#x2F;
576
 
    triggerNodes : {
577
 
        value: null,
578
 
        setter: function(val) {
579
 
            if (val &amp;&amp; Lang.isString(val)) {
580
 
                val = Node.all(val);
581
 
            }
582
 
            return val;
583
 
        }
584
 
    },
585
 
 
586
 
    &#x2F;*
587
 
     * The delegate node to which event listeners should be attached.
588
 
     * This node should be an ancestor of all trigger nodes bound
589
 
     * to the instance. By default the document is used.
590
 
     *&#x2F;
591
 
    delegate : {
592
 
        value: null,
593
 
        setter: function(val) {
594
 
            return Y.one(val) || Y.one(&quot;document&quot;);
595
 
        }
596
 
    },
597
 
 
598
 
    &#x2F;*
599
 
     * The time to wait, after the mouse enters the trigger node,
600
 
     * to display the tooltip
601
 
     *&#x2F;
602
 
    showDelay : {
603
 
        value:250
604
 
    },
605
 
 
606
 
    &#x2F;*
607
 
     * The time to wait, after the mouse leaves the trigger node,
608
 
     * to hide the tooltip
609
 
     *&#x2F;
610
 
    hideDelay : {
611
 
        value:10
612
 
    },
613
 
 
614
 
    &#x2F;*
615
 
     * The time to wait, after the tooltip is first displayed for 
616
 
     * a trigger node, to hide it, if the mouse has not left the 
617
 
     * trigger node
618
 
     *&#x2F;
619
 
    autoHideDelay : {
620
 
        value:2000
621
 
    },
622
 
 
623
 
    &#x2F;*
624
 
     * Override the default visibility set by the widget base class
625
 
     *&#x2F;
626
 
    visible : {
627
 
        value:false
628
 
    },
629
 
 
630
 
    &#x2F;*
631
 
     * Override the default XY value set by the widget base class,
632
 
     * to position the tooltip offscreen
633
 
     *&#x2F;
634
 
    xy: {
635
 
        value:[Tooltip.OFFSCREEN_X, Tooltip.OFFSCREEN_Y]
636
 
    }
637
 
};
638
 
 
639
 
Y.extend(Tooltip, Y.Widget, { 
640
 
    &#x2F;&#x2F; Prototype methods&#x2F;properties
641
 
});</pre>
642
 
 
643
 
 
644
 
<h3>Adding WidgetPosition and WidgetStack Extension Support</h3>
645
 
 
646
 
<p>The Tooltip class also needs basic positioning and stacking (z-index, shimming) support. As with the <a href="widget-build.html">Custom Widget Classes</a> example, we use
647
 
<code>Base.create</code> to create a new <code>Tooltip</code> class with this support:</p>
648
 
 
649
 
<pre class="code prettyprint">var Tooltip = Y.Base.create(&quot;tooltip&quot;, Y.Widget, [Y.WidgetPosition, Y.WidgetStack], 
650
 
                                  { ... prototype properties ... },
651
 
                                  { ... static properties ... },</pre>
652
 
 
653
 
 
654
 
<h3>Lifecycle Methods: initializer, destructor</h3>
655
 
 
656
 
<p>The <code>initializer</code> method is invoked during the <code>init</code> lifecycle phase, after the attributes are configured for each class. <code>Tooltip</code> uses it 
657
 
to setup the private state variables it will use to store the trigger node currently being serviced by the tooltip instance, event handles and show/hide timers.</p>
658
 
 
659
 
<pre class="code prettyprint">initializer : function(config) {
660
 
 
661
 
    this._triggerClassName = this.getClassName(&quot;trigger&quot;);
662
 
 
663
 
    &#x2F;&#x2F; Currently bound trigger node information
664
 
    this._currTrigger = {
665
 
        node: null,
666
 
        title: null,
667
 
        mouseX: Tooltip.OFFSCREEN_X,
668
 
        mouseY: Tooltip.OFFSCREEN_Y
669
 
    };
670
 
 
671
 
    &#x2F;&#x2F; Event handles - mouse over is set on the delegate
672
 
    &#x2F;&#x2F; element, mousemove and mouseleave are set on the trigger node
673
 
    this._eventHandles = {
674
 
        delegate: null,
675
 
        trigger: {
676
 
            mouseMove : null,
677
 
            mouseOut: null
678
 
        }
679
 
    };
680
 
 
681
 
    &#x2F;&#x2F; Show&#x2F;hide timers
682
 
    this._timers = {
683
 
        show: null,
684
 
        hide: null
685
 
    };
686
 
 
687
 
    &#x2F;&#x2F; Publish events introduced by Tooltip. Note the triggerEnter event is preventable,
688
 
    &#x2F;&#x2F; with the default behavior defined in the _defTriggerEnterFn method 
689
 
    this.publish(&quot;triggerEnter&quot;, {defaultFn: this._defTriggerEnterFn, preventable:true});
690
 
    this.publish(&quot;triggerLeave&quot;, {preventable:false});
691
 
}</pre>
692
 
 
693
 
 
694
 
<p>The <code>destructor</code> is used to clear out stored state, detach any event handles and clear out the show/hide timers:</p>
695
 
 
696
 
<pre class="code prettyprint">destructor : function() {
697
 
    this._clearCurrentTrigger();
698
 
    this._clearTimers();
699
 
    this._clearHandles();
700
 
}</pre>
701
 
 
702
 
 
703
 
<h3>Lifecycle Methods: bindUI, syncUI</h3>
704
 
 
705
 
<p>The <code>bindUI</code> and <code>syncUI</code> are invoked by the base Widget class' <code>renderer</code> method.</p>
706
 
 
707
 
<p><code>bindUI</code> is used to bind the attribute change listeners used to update the rendered UI from the current state of the widget and also to bind
708
 
the DOM listeners required to enable the UI for interaction.</p>
709
 
 
710
 
<p><code>syncUI</code> is used to sync the UI state from the current widget state, when initially rendered.</p>
711
 
 
712
 
<p><em>NOTE:</em> Widget's <code>renderer</code> method also invokes the <code>renderUI</code> method, which is responsible for laying down any additional content elements a widget requires. However
713
 
tooltip does not have any additional elements in needs to add to the DOM, outside of the default Widget boundingBox and contentBox.</p>
714
 
 
715
 
<pre class="code prettyprint">bindUI : function() {
716
 
    this.after(&quot;delegateChange&quot;, this._afterSetDelegate);
717
 
    this.after(&quot;nodesChange&quot;, this._afterSetNodes);
718
 
 
719
 
    this._bindDelegate();
720
 
},
721
 
 
722
 
syncUI : function() {
723
 
    this._uiSetNodes(this.get(&quot;triggerNodes&quot;));
724
 
}</pre>
725
 
 
726
 
 
727
 
<h3>Attribute Supporting Methods</h3>
728
 
 
729
 
<p>Tooltip's <code>triggerNodes</code>, which defines the set of nodes which should trigger this tooltip instance,
730
 
has a couple of supporting methods associated with it.</p>
731
 
 
732
 
<p>The <code>_afterSetNodes</code> method is the default attribute change event handler for the <code>triggerNodes</code>
733
 
attribute. It invokes the <code>_uiSetNodes</code> method, which marks all trigger nodes with a trigger class name (<code>yui-tooltip-trigger</code>) when set.</p>
734
 
 
735
 
<pre class="code prettyprint">_afterSetNodes : function(e) {
736
 
    this._uiSetNodes(e.newVal);
737
 
},
738
 
 
739
 
_uiSetNodes : function(nodes) {
740
 
    if (this._triggerNodes) {
741
 
        this._triggerNodes.removeClass(this._triggerClassName);
742
 
    }
743
 
 
744
 
    if (nodes) {
745
 
        this._triggerNodes = nodes;
746
 
        this._triggerNodes.addClass(this._triggerClassName);
747
 
    }
748
 
},</pre>
749
 
 
750
 
 
751
 
<p>Similarly the <code>_afterSetDelegate</code> method is the default attribute change listener for the <code>delegate</code> attribute,
752
 
and invokes <code>_bindDelegate</code> to set up the listeners when a new delegate node is set. We use <code>Y.delegate</code> support, along with Event's <code>mouseenter</code> support, 
753
 
which means the only thing we need to do is tell delegate which node we want to act as the delegate, and which elements we want to target using the <code>&quot;.&quot; + this._triggerClassName</code> selector.</p>
754
 
 
755
 
<pre class="code prettyprint">_afterSetDelegate : function(e) {
756
 
    this._bindDelegate(e.newVal);
757
 
},
758
 
 
759
 
_bindDelegate : function() {
760
 
    var eventHandles = this._eventHandles;
761
 
 
762
 
    if (eventHandles.delegate) {
763
 
        eventHandles.delegate.detach();
764
 
        eventHandles.delegate = null;
765
 
    }
766
 
    eventHandles.delegate = Y.delegate(&quot;mouseenter&quot;, Y.bind(this._onNodeMouseEnter, this), this.get(&quot;delegate&quot;), &quot;.&quot; + this._triggerClassName);
767
 
},</pre>
768
 
 
769
 
 
770
 
<h3>DOM Event Handlers</h3>
771
 
 
772
 
<p>Tooltips interaction revolves around the <code>mouseenter</code>, <code>mousemove</code> and <code>mouseleave</code> DOM events. The mousenter listener is the only listener set up initially, on the <code>delegate</code> node:</p>
773
 
 
774
 
<pre class="code prettyprint">_onNodeMouseEnter : function(e) {
775
 
    var node = e.currentTarget;
776
 
    if (node &amp;&amp; (!this._currTrigger.node || !node.compareTo(this._currTrigger.node))) {
777
 
        this._enterTrigger(node, e.pageX, e.pageY);
778
 
    }
779
 
}</pre>
780
 
 
781
 
 
782
 
<p>Since the <code>mouseenter</code> implementation doesn't invoke it's listeners for <code>mouseover</code> events generated from elements nested 
783
 
inside the targeted node (for example when mousing out of a child element of a trigger node), there are no additional checks we need to perform other than to see if the node is the current trigger, before handing off to 
784
 
the <code>_enterTrigger</code> method to setup the current trigger state and attach mousemove and mouseleave listeners on the current trigger node.</p>
785
 
 
786
 
<p>The mouseleave listener delegates to the <code>_leaveTrigger</code> method, and again, since the <code>mouseleave</code> implementation deals with nested elements, we don't need to perform any additional target checks:</p>
787
 
 
788
 
<pre class="code prettyprint">_onNodeMouseLeave : function(e) {
789
 
    this._leaveTrigger(e.currentTarget);
790
 
}</pre>
791
 
 
792
 
 
793
 
<p>The mouse move listener delegates to the <code>_overTrigger</code> method to store the current mouse XY co-ordinates (used to position the Tooltip when it is displayed after the <code>showDelay</code>):</p>
794
 
 
795
 
<pre class="code prettyprint">_onNodeMouseMove : function(e) {
796
 
    this._overTrigger(e.pageX, e.pageY);
797
 
}</pre>
798
 
 
799
 
 
800
 
<h3>Trigger Event Delegates: _enterTrigger, _leaveTrigger, _overTrigger</h3>
801
 
 
802
 
<p>As seen above, the DOM event handlers delegate to the <code>_enterTrigger, _leaveTrigger and _overTrigger</code> methods to update the 
803
 
Tooltip state based on the currently active trigger node.</p>
804
 
 
805
 
<p>The <code>_enterTrigger</code> method sets the current trigger state (which node is the current tooltip trigger, 
806
 
what the current mouse XY position is, etc.). The method also fires the <code>triggerEnter</code> event, whose default function actually handles 
807
 
showing the tooltip after the configured <code>showDelay</code> period. The <code>triggerEnter</code> event can be prevented by listeners, allowing 
808
 
users to prevent the tooltip from being shown if required. (<code>triggerEnter</code> listeners are passed the current trigger node and pageX, pageY mouse co-ordinates as event facade properties):</p>
809
 
 
810
 
<pre class="code prettyprint">_enterTrigger : function(node, x, y) {
811
 
    this._setCurrentTrigger(node, x, y);
812
 
    this.fire(&quot;triggerEnter&quot;, null, node, x, y);
813
 
},
814
 
 
815
 
_defTriggerEnterFn : function(e) {
816
 
    var node = e.node;
817
 
    if (!this.get(&quot;disabled&quot;)) {
818
 
        this._clearTimers();
819
 
        var delay = (this.get(&quot;visible&quot;)) ? 0 : this.get(&quot;showDelay&quot;);
820
 
        this._timers.show = Y.later(delay, this, this._showTooltip, [node]);
821
 
    }
822
 
},</pre>
823
 
 
824
 
 
825
 
<p>Similarly the <code>_leaveTrigger</code> method is invoked when the mouse leaves a trigger node, and clears any stored state, timers and listeners before setting up
826
 
the <code>hideDelay</code> timer. It fires a <code>triggerLeave</code> event, but cannot be prevented, and has no default behavior to prevent:</p>
827
 
 
828
 
<pre class="code prettyprint">_leaveTrigger : function(node) {
829
 
    this.fire(&quot;triggerLeave&quot;);
830
 
 
831
 
    this._clearCurrentTrigger();
832
 
    this._clearTimers();
833
 
 
834
 
    this._timers.hide = Y.later(this.get(&quot;hideDelay&quot;), this, this._hideTooltip);
835
 
},</pre>
836
 
 
837
 
 
838
 
<p>As mentioned previously, the <code>_overTrigger</code> method simply stores the current mouse XY co-ordinates for use when the tooltip is shown:</p>
839
 
 
840
 
<pre class="code prettyprint">_overTrigger : function(x, y) {
841
 
    this._currTrigger.mouseX = x;
842
 
    this._currTrigger.mouseY = y;
843
 
}</pre>
844
 
 
845
 
 
846
 
<h3>Setting Tooltip Content</h3>
847
 
 
848
 
<p>Since the content for a tooltip is usually a function of the trigger node and not constant, <code>Tooltip</code> provides a number of ways to set the content.</p>
849
 
 
850
 
<ol>
851
 
    <li>Setting the <code>content</code> attribute to a string or node. In this case, the value of the <code>content</code> attribute is used
852
 
    for all triggerNodes</li>
853
 
    <li>Setting the <code>content</code> attribute to an object literal, containing a map of triggerNode id to content. The content for a trigger node
854
 
    will be set using the map, when the tooltip is triggered for the node.</li>
855
 
    <li>Setting the title attribute on the trigger node. The value of the title attribute is used to set the tooltip content,
856
 
    when triggered for the node.</li>
857
 
    <li>By calling the <code>setTriggerContent</code> method to set content for a specific trigger node, in a <code>triggerEnter</code> event listener.</li>
858
 
</ol>
859
 
 
860
 
<p>The precedence of these methods is handled in the <code>_setTriggerContent</code> method, invoked when the mouse enters a trigger:</p>
861
 
 
862
 
<pre class="code prettyprint">_setTriggerContent : function(node) {
863
 
    var content = this.get(&quot;content&quot;);
864
 
    if (content &amp;&amp; !(content instanceof Node || Lang.isString(content))) {
865
 
        content = content[node.get(&quot;id&quot;)] || node.getAttribute(&quot;title&quot;);
866
 
    }
867
 
    this.setTriggerContent(content);
868
 
},
869
 
 
870
 
setTriggerContent : function(content) {
871
 
    var contentBox = this.get(&quot;contentBox&quot;);
872
 
    contentBox.set(&quot;innerHTML&quot;, &quot;&quot;);
873
 
 
874
 
    if (content) {
875
 
        if (content instanceof Node) {
876
 
            for (var i = 0, l = content.size(); i &lt; l; ++i) {
877
 
                contentBox.appendChild(content.item(i));
878
 
            }
879
 
        } else if (Lang.isString(content)) {
880
 
            contentBox.set(&quot;innerHTML&quot;, content);
881
 
        }
882
 
    }
883
 
}</pre>
884
 
 
885
 
 
886
 
<p>Calling the public <code>setTriggerContent</code> in a <code>triggerEvent</code> listener will over-ride content set using the <code>content</code> attribute or the trigger node's title value.</p>
887
 
 
888
 
<h3>Using Tooltip</h3>
889
 
 
890
 
<p>For this example, we set up 4 DIV elements which will act as tooltip triggers. They are all marked using a <code>yui-hastooltip</code> class, so that they can be queried using a simple selector, passed as the value for the <code>triggerNodes</code> attribute in the tooltip's constructor Also all 4 trigger nodes are contained in a wrapper DIV with <code>id=&quot;delegate&quot;</code> which will act as the <code>delegate</code> node.</p>
891
 
 
892
 
<pre class="code prettyprint">var tt = new Tooltip({
893
 
    triggerNodes:&quot;.yui3-hastooltip&quot;,
894
 
    delegate: &quot;#delegate&quot;,
895
 
    content: {
896
 
        tt3: &quot;Tooltip 3 (from lookup)&quot;
897
 
    },
898
 
    shim:false,
899
 
    zIndex:2
900
 
});
901
 
tt.render();</pre>
902
 
 
903
 
 
904
 
<p>The tooltip content for each of the trigger nodes is setup differently. The first trigger node uses the title attribute to set it's content. The third trigger node's content is set using the content map set in the constructor above. The second trigger node's content is set using a <code>triggerEnter</code> event listener and the <code>setTriggerContent</code> method as shown below:</p>
905
 
 
906
 
<pre class="code prettyprint">tt.on(&quot;triggerEnter&quot;, function(e) {
907
 
    var node = e.node;
908
 
    if (node &amp;&amp; node.get(&quot;id&quot;) == &quot;tt2&quot;) {
909
 
        this.setTriggerContent(&quot;Tooltip 2 (from triggerEvent)&quot;);
910
 
    }
911
 
});</pre>
912
 
 
913
 
 
914
 
<p>The fourth trigger node's content is set using it's title attribute, however it also has a <code>triggerEvent</code> listener which prevents the tooltip from being displayed for it, if the checkbox is checked.</p>
915
 
 
916
 
<pre class="code prettyprint">var prevent = Y.one(&quot;#prevent&quot;);
917
 
tt.on(&quot;triggerEnter&quot;, function(e) {
918
 
    var node = e.node;
919
 
    if (prevent.get(&quot;checked&quot;)) {
920
 
        if (node &amp;&amp; node.get(&quot;id&quot;) == &quot;tt4&quot;) {
921
 
            e.preventDefault();
922
 
        }
923
 
    }
924
 
});</pre>
925
 
 
926
 
 
927
 
<h2>Complete Example Source</h2>
928
 
<pre class="code prettyprint">&lt;div id=&quot;delegate&quot;&gt;
929
 
    &lt;div class=&quot;yui3-hastooltip&quot; title=&quot;Tooltip 1&quot; id=&quot;tt1&quot;&gt;Tooltip One &lt;span&gt;(content from title)&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
930
 
    &lt;div class=&quot;yui3-hastooltip&quot; title=&quot;Tooltip 2&quot; id=&quot;tt2&quot;&gt;Tooltip Two &lt;span&gt;(content set in event listener)&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
931
 
    &lt;div class=&quot;yui3-hastooltip&quot; title=&quot;Tooltip 3&quot; id=&quot;tt3&quot;&gt;Tooltip Three &lt;span&gt;(content from lookup)&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
932
 
    &lt;div class=&quot;yui3-hastooltip&quot; title=&quot;Tooltip 4&quot; id=&quot;tt4&quot;&gt;Tooltip Four &lt;span&gt;(content from title)&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
933
 
    &lt;label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;prevent&quot; &#x2F;&gt; Prevent Tooltip Four&lt;&#x2F;label&gt;
934
 
&lt;&#x2F;div&gt;
935
 
 
936
 
&lt;script type=&quot;text&#x2F;javascript&quot;&gt;
937
 
YUI().use(&quot;event-mouseenter&quot;, &quot;widget&quot;, &quot;widget-position&quot;, &quot;widget-stack&quot;, function(Y) {
938
 
    var Lang = Y.Lang,
939
 
        Node = Y.Node,
940
 
        OX = -10000,
941
 
        OY = -10000;
942
 
 
943
 
    var Tooltip = Y.Base.create(&quot;tooltip&quot;, Y.Widget, [Y.WidgetPosition, Y.WidgetStack], {
944
 
 
945
 
        &#x2F;&#x2F; PROTOTYPE METHODS&#x2F;PROPERTIES
946
 
 
947
 
        &#x2F;*
948
 
         * Initialization Code: Sets up privately used state
949
 
         * properties, and publishes the events Tooltip introduces
950
 
         *&#x2F;
951
 
        initializer : function(config) {
952
 
 
953
 
            this._triggerClassName = this.getClassName(&quot;trigger&quot;);
954
 
 
955
 
            &#x2F;&#x2F; Currently bound trigger node information
956
 
            this._currTrigger = {
957
 
                node: null,
958
 
                title: null,
959
 
                mouseX: Tooltip.OFFSCREEN_X,
960
 
                mouseY: Tooltip.OFFSCREEN_Y
961
 
            };
962
 
 
963
 
            &#x2F;&#x2F; Event handles - mouse over is set on the delegate
964
 
            &#x2F;&#x2F; element, mousemove and mouseleave are set on the trigger node
965
 
            this._eventHandles = {
966
 
                delegate: null,
967
 
                trigger: {
968
 
                    mouseMove : null,
969
 
                    mouseOut: null
970
 
                }
971
 
            };
972
 
 
973
 
            &#x2F;&#x2F; Show&#x2F;hide timers
974
 
            this._timers = {
975
 
                show: null,
976
 
                hide: null
977
 
            };
978
 
 
979
 
            &#x2F;&#x2F; Publish events introduced by Tooltip. Note the triggerEnter event is preventable,
980
 
            &#x2F;&#x2F; with the default behavior defined in the _defTriggerEnterFn method 
981
 
            this.publish(&quot;triggerEnter&quot;, {defaultFn: this._defTriggerEnterFn, preventable:true});
982
 
            this.publish(&quot;triggerLeave&quot;, {preventable:false});
983
 
        },
984
 
 
985
 
        &#x2F;*
986
 
         * Destruction Code: Clears event handles, timers,
987
 
         * and current trigger information
988
 
         *&#x2F;
989
 
        destructor : function() {
990
 
            this._clearCurrentTrigger();
991
 
            this._clearTimers();
992
 
            this._clearHandles();
993
 
        },
994
 
 
995
 
        &#x2F;*
996
 
         * bindUI is used to bind attribute change and dom event
997
 
         * listeners
998
 
         *&#x2F;
999
 
        bindUI : function() {
1000
 
            this.after(&quot;delegateChange&quot;, this._afterSetDelegate);
1001
 
            this.after(&quot;nodesChange&quot;, this._afterSetNodes);
1002
 
 
1003
 
            this._bindDelegate();
1004
 
        },
1005
 
 
1006
 
        &#x2F;*
1007
 
         * syncUI is used to update the rendered DOM, based on the current
1008
 
         * Tooltip state
1009
 
         *&#x2F;
1010
 
        syncUI : function() {
1011
 
            this._uiSetNodes(this.get(&quot;triggerNodes&quot;));
1012
 
        },
1013
 
 
1014
 
        &#x2F;*
1015
 
         * Public method, which can be used by triggerEvent event listeners
1016
 
         * to set the content of the tooltip for the current trigger node
1017
 
         *&#x2F;
1018
 
        setTriggerContent : function(content) {
1019
 
            var contentBox = this.get(&quot;contentBox&quot;);
1020
 
            contentBox.set(&quot;innerHTML&quot;, &quot;&quot;);
1021
 
 
1022
 
            if (content) {
1023
 
                if (content instanceof Node) {
1024
 
                    for (var i = 0, l = content.size(); i &lt; l; ++i) {
1025
 
                        contentBox.appendChild(content.item(i));
1026
 
                    }
1027
 
                } else if (Lang.isString(content)) {
1028
 
                    contentBox.set(&quot;innerHTML&quot;, content);
1029
 
                }
1030
 
            }
1031
 
        },
1032
 
 
1033
 
        &#x2F;*
1034
 
         * Default attribute change listener for 
1035
 
         * the triggerNodes attribute
1036
 
         *&#x2F;
1037
 
        _afterSetNodes : function(e) {
1038
 
            this._uiSetNodes(e.newVal);
1039
 
        },
1040
 
 
1041
 
        &#x2F;*
1042
 
         * Default attribute change listener for 
1043
 
         * the delegate attribute
1044
 
         *&#x2F;
1045
 
        _afterSetDelegate : function(e) {
1046
 
            this._bindDelegate(e.newVal);
1047
 
        },
1048
 
 
1049
 
        &#x2F;*
1050
 
         * Updates the rendered DOM to reflect the
1051
 
         * set of trigger nodes passed in
1052
 
         *&#x2F;
1053
 
        _uiSetNodes : function(nodes) {
1054
 
            if (this._triggerNodes) {
1055
 
                this._triggerNodes.removeClass(this._triggerClassName);
1056
 
            }
1057
 
 
1058
 
            if (nodes) {
1059
 
                this._triggerNodes = nodes;
1060
 
                this._triggerNodes.addClass(this._triggerClassName);
1061
 
            }
1062
 
        },
1063
 
 
1064
 
        &#x2F;*
1065
 
         * Attaches the default mouseover DOM listener to the 
1066
 
         * current delegate node
1067
 
         *&#x2F;
1068
 
        _bindDelegate : function() {
1069
 
            var eventHandles = this._eventHandles;
1070
 
 
1071
 
            if (eventHandles.delegate) {
1072
 
                eventHandles.delegate.detach();
1073
 
                eventHandles.delegate = null;
1074
 
            }
1075
 
            eventHandles.delegate = Y.delegate(&quot;mouseenter&quot;, Y.bind(this._onNodeMouseEnter, this), this.get(&quot;delegate&quot;), &quot;.&quot; + this._triggerClassName);
1076
 
        },
1077
 
 
1078
 
        &#x2F;*
1079
 
         * Default mouse enter DOM event listener.
1080
 
         * 
1081
 
         * Delegates to the _enterTrigger method,
1082
 
         * if the mouseover enters a trigger node.
1083
 
         *&#x2F;
1084
 
        _onNodeMouseEnter : function(e) {
1085
 
            var node = e.currentTarget;
1086
 
            if (node &amp;&amp; (!this._currTrigger.node || !node.compareTo(this._currTrigger.node))) {
1087
 
                this._enterTrigger(node, e.pageX, e.pageY);
1088
 
            }
1089
 
        },
1090
 
 
1091
 
        &#x2F;*
1092
 
         * Default mouse leave DOM event listener
1093
 
         * 
1094
 
         * Delegates to _leaveTrigger if the mouse
1095
 
         * leaves the current trigger node
1096
 
         *&#x2F;
1097
 
        _onNodeMouseLeave : function(e) {
1098
 
            this._leaveTrigger(e.currentTarget);
1099
 
        },
1100
 
 
1101
 
        &#x2F;*
1102
 
         * Default mouse move DOM event listener
1103
 
         *&#x2F;
1104
 
        _onNodeMouseMove : function(e) {
1105
 
            this._overTrigger(e.pageX, e.pageY);
1106
 
        },
1107
 
 
1108
 
        &#x2F;*
1109
 
         * Default handler invoked when the mouse enters
1110
 
         * a trigger node. Fires the triggerEnter
1111
 
         * event which can be prevented by listeners to 
1112
 
         * show the tooltip from being displayed.
1113
 
         *&#x2F;
1114
 
        _enterTrigger : function(node, x, y) {
1115
 
            this._setCurrentTrigger(node, x, y);
1116
 
            this.fire(&quot;triggerEnter&quot;, {node:node, pageX:x, pageY:y});
1117
 
        },
1118
 
 
1119
 
        &#x2F;*
1120
 
         * Default handler for the triggerEvent event,
1121
 
         * which will setup the timer to display the tooltip,
1122
 
         * if the default handler has not been prevented.
1123
 
         *&#x2F;
1124
 
        _defTriggerEnterFn : function(e) {
1125
 
            var node = e.node;
1126
 
            if (!this.get(&quot;disabled&quot;)) {
1127
 
                this._clearTimers();
1128
 
                var delay = (this.get(&quot;visible&quot;)) ? 0 : this.get(&quot;showDelay&quot;);
1129
 
                this._timers.show = Y.later(delay, this, this._showTooltip, [node]);
1130
 
            }
1131
 
        },
1132
 
 
1133
 
        &#x2F;*
1134
 
         * Default handler invoked when the mouse leaves
1135
 
         * the current trigger node. Fires the triggerLeave
1136
 
         * event and sets up the hide timer
1137
 
         *&#x2F;
1138
 
        _leaveTrigger : function(node) {
1139
 
            this.fire(&quot;triggerLeave&quot;);
1140
 
 
1141
 
            this._clearCurrentTrigger();
1142
 
            this._clearTimers();
1143
 
 
1144
 
            this._timers.hide = Y.later(this.get(&quot;hideDelay&quot;), this, this._hideTooltip);
1145
 
        },
1146
 
 
1147
 
        &#x2F;*
1148
 
         * Default handler invoked for mousemove events
1149
 
         * on the trigger node. Stores the current mouse 
1150
 
         * x, y positions
1151
 
         *&#x2F;
1152
 
        _overTrigger : function(x, y) {
1153
 
            this._currTrigger.mouseX = x;
1154
 
            this._currTrigger.mouseY = y;
1155
 
        },
1156
 
 
1157
 
        &#x2F;*
1158
 
         * Shows the tooltip, after moving it to the current mouse
1159
 
         * position.
1160
 
         *&#x2F;
1161
 
        _showTooltip : function(node) {
1162
 
            var x = this._currTrigger.mouseX;
1163
 
            var y = this._currTrigger.mouseY;
1164
 
 
1165
 
            this.move(x + Tooltip.OFFSET_X, y + Tooltip.OFFSET_Y);
1166
 
 
1167
 
            this.show();
1168
 
            this._clearTimers();
1169
 
 
1170
 
            this._timers.hide = Y.later(this.get(&quot;autoHideDelay&quot;), this, this._hideTooltip);
1171
 
        },
1172
 
 
1173
 
        &#x2F;*
1174
 
         * Hides the tooltip, after clearing existing timers.
1175
 
         *&#x2F;
1176
 
        _hideTooltip : function() {
1177
 
            this._clearTimers();
1178
 
            this.hide();
1179
 
        },
1180
 
 
1181
 
        &#x2F;*
1182
 
         * Set the rendered content of the tooltip for the current
1183
 
         * trigger, based on (in order of precedence):
1184
 
         * 
1185
 
         * a). The string&#x2F;node content attribute value
1186
 
         * b). From the content lookup map if it is set, or 
1187
 
         * c). From the title attribute if set.
1188
 
         *&#x2F;
1189
 
        _setTriggerContent : function(node) {
1190
 
            var content = this.get(&quot;content&quot;);
1191
 
            if (content &amp;&amp; !(content instanceof Node || Lang.isString(content))) {
1192
 
                content = content[node.get(&quot;id&quot;)] || node.getAttribute(&quot;title&quot;);
1193
 
            }
1194
 
            this.setTriggerContent(content);
1195
 
        },
1196
 
 
1197
 
        &#x2F;*
1198
 
         * Set the currently bound trigger node information, clearing 
1199
 
         * out the title attribute if set and setting up mousemove&#x2F;out 
1200
 
         * listeners.
1201
 
         *&#x2F;
1202
 
        _setCurrentTrigger : function(node, x, y) {
1203
 
 
1204
 
            var currTrigger = this._currTrigger,
1205
 
                triggerHandles = this._eventHandles.trigger;
1206
 
 
1207
 
            this._setTriggerContent(node);
1208
 
 
1209
 
            triggerHandles.mouseMove = Y.on(&quot;mousemove&quot;, Y.bind(this._onNodeMouseMove, this), node);
1210
 
            triggerHandles.mouseOut = Y.on(&quot;mouseleave&quot;, Y.bind(this._onNodeMouseLeave, this), node);
1211
 
 
1212
 
            var title = node.getAttribute(&quot;title&quot;);
1213
 
            node.setAttribute(&quot;title&quot;, &quot;&quot;);
1214
 
 
1215
 
            currTrigger.mouseX = x;
1216
 
            currTrigger.mouseY = y;
1217
 
            currTrigger.node = node;
1218
 
            currTrigger.title = title;
1219
 
        },
1220
 
 
1221
 
        &#x2F;*
1222
 
         * Clear out the current trigger state, restoring
1223
 
         * the title attribute on the trigger node, 
1224
 
         * if it was originally set.
1225
 
         *&#x2F;
1226
 
        _clearCurrentTrigger : function() {
1227
 
 
1228
 
            var currTrigger = this._currTrigger,
1229
 
                triggerHandles = this._eventHandles.trigger;
1230
 
 
1231
 
            if (currTrigger.node) {
1232
 
                var node = currTrigger.node;
1233
 
                var title = currTrigger.title || &quot;&quot;;
1234
 
 
1235
 
                currTrigger.node = null;
1236
 
                currTrigger.title = &quot;&quot;;
1237
 
 
1238
 
                triggerHandles.mouseMove.detach();
1239
 
                triggerHandles.mouseOut.detach();
1240
 
                triggerHandles.mouseMove = null;
1241
 
                triggerHandles.mouseOut = null;
1242
 
 
1243
 
                node.setAttribute(&quot;title&quot;, title);
1244
 
            }
1245
 
        },
1246
 
 
1247
 
        &#x2F;*
1248
 
         * Cancel any existing show&#x2F;hide timers
1249
 
         *&#x2F;
1250
 
        _clearTimers : function() {
1251
 
            var timers = this._timers;
1252
 
            if (timers.hide) {
1253
 
                timers.hide.cancel();
1254
 
                timers.hide = null;
1255
 
            }
1256
 
            if (timers.show) {
1257
 
              timers.show.cancel();
1258
 
              timers.show = null;
1259
 
            }
1260
 
        },
1261
 
 
1262
 
        &#x2F;*
1263
 
         * Detach any stored event handles
1264
 
         *&#x2F;
1265
 
        _clearHandles : function() {
1266
 
            var eventHandles = this._eventHandles;
1267
 
 
1268
 
            if (eventHandles.delegate) {
1269
 
                this._eventHandles.delegate.detach();
1270
 
            }
1271
 
            if (eventHandles.trigger.mouseOut) {
1272
 
                eventHandles.trigger.mouseOut.detach();
1273
 
            }
1274
 
            if (eventHandles.trigger.mouseMove) {
1275
 
                eventHandles.trigger.mouseMove.detach();
1276
 
            }
1277
 
        }
1278
 
    }, {
1279
 
    
1280
 
        &#x2F;&#x2F; STATIC METHODS&#x2F;PROPERTIES
1281
 
       
1282
 
        OFFSET_X : 15,
1283
 
        OFFSET_Y : 15,
1284
 
        OFFSCREEN_X : OX,
1285
 
        OFFSCREEN_Y : OY,
1286
 
 
1287
 
        ATTRS : {
1288
 
    
1289
 
            &#x2F;* 
1290
 
             * The tooltip content. This can either be a fixed content value, 
1291
 
             * or a map of id-to-values, designed to be used when a single
1292
 
             * tooltip is mapped to multiple trigger elements.
1293
 
             *&#x2F;
1294
 
            content : {
1295
 
                value: null
1296
 
            },
1297
 
    
1298
 
            &#x2F;* 
1299
 
             * The set of nodes to bind to the tooltip instance. Can be a string, 
1300
 
             * or a node instance.
1301
 
             *&#x2F;
1302
 
            triggerNodes : {
1303
 
                value: null,
1304
 
                setter: function(val) {
1305
 
                    if (val &amp;&amp; Lang.isString(val)) {
1306
 
                        val = Node.all(val);
1307
 
                    }
1308
 
                    return val;
1309
 
                }
1310
 
            },
1311
 
    
1312
 
            &#x2F;*
1313
 
             * The delegate node to which event listeners should be attached.
1314
 
             * This node should be an ancestor of all trigger nodes bound
1315
 
             * to the instance. By default the document is used.
1316
 
             *&#x2F;
1317
 
            delegate : {
1318
 
                value: null,
1319
 
                setter: function(val) {
1320
 
                    return Y.one(val) || Y.one(&quot;document&quot;);
1321
 
                }
1322
 
            },
1323
 
    
1324
 
            &#x2F;*
1325
 
             * The time to wait, after the mouse enters the trigger node,
1326
 
             * to display the tooltip
1327
 
             *&#x2F;
1328
 
            showDelay : {
1329
 
                value:250
1330
 
            },
1331
 
    
1332
 
            &#x2F;*
1333
 
             * The time to wait, after the mouse leaves the trigger node,
1334
 
             * to hide the tooltip
1335
 
             *&#x2F;
1336
 
            hideDelay : {
1337
 
                value:10
1338
 
            },
1339
 
    
1340
 
            &#x2F;*
1341
 
             * The time to wait, after the tooltip is first displayed for 
1342
 
             * a trigger node, to hide it, if the mouse has not left the 
1343
 
             * trigger node
1344
 
             *&#x2F;
1345
 
            autoHideDelay : {
1346
 
                value:2000
1347
 
            },
1348
 
    
1349
 
            &#x2F;*
1350
 
             * Override the default visibility set by the widget base class
1351
 
             *&#x2F;
1352
 
            visible : {
1353
 
                value:false
1354
 
            },
1355
 
    
1356
 
            &#x2F;*
1357
 
             * Override the default XY value set by the widget base class,
1358
 
             * to position the tooltip offscreen
1359
 
             *&#x2F;
1360
 
            xy: {
1361
 
                value:[OX, OY]
1362
 
            }
1363
 
        }
1364
 
    });
1365
 
 
1366
 
    var tt = new Tooltip({
1367
 
        triggerNodes:&quot;.yui3-hastooltip&quot;,
1368
 
        delegate: &quot;#delegate&quot;,
1369
 
        content: {
1370
 
            tt3: &quot;Tooltip 3 (from lookup)&quot;
1371
 
        },
1372
 
        shim:false,
1373
 
        zIndex:2
1374
 
    });
1375
 
    tt.render();
1376
 
 
1377
 
    tt.on(&quot;triggerEnter&quot;, function(e) {
1378
 
        var node = e.node;
1379
 
        if (node &amp;&amp; node.get(&quot;id&quot;) == &quot;tt2&quot;) {
1380
 
            this.setTriggerContent(&quot;Tooltip 2 (from triggerEvent)&quot;);
1381
 
        }
1382
 
    });
1383
 
 
1384
 
    var prevent = Y.one(&quot;#prevent&quot;);
1385
 
    tt.on(&quot;triggerEnter&quot;, function(e) {
1386
 
        var node = e.node;
1387
 
        if (prevent.get(&quot;checked&quot;)) {
1388
 
            if (node &amp;&amp; node.get(&quot;id&quot;) == &quot;tt4&quot;) {
1389
 
                e.preventDefault();
1390
 
            }
1391
 
        }
1392
 
    });
1393
 
});
1394
 
&lt;&#x2F;script&gt;</pre>
1395
 
 
1396
 
</div>
1397
 
            </div>
1398
 
        </div>
1399
 
 
1400
 
        <div class="yui3-u-1-4">
1401
 
            <div class="sidebar">
1402
 
                
1403
 
 
1404
 
                
1405
 
                    <div class="sidebox">
1406
 
                        <div class="hd">
1407
 
                            <h2 class="no-toc">Examples</h2>
1408
 
                        </div>
1409
 
 
1410
 
                        <div class="bd">
1411
 
                            <ul class="examples">
1412
 
                                
1413
 
                                    
1414
 
                                        <li data-description="Shows how to extend the base widget class, to create your own Widgets.">
1415
 
                                            <a href="widget-extend.html">Extending the Base Widget Class</a>
1416
 
                                        </li>
1417
 
                                    
1418
 
                                
1419
 
                                    
1420
 
                                        <li data-description="Shows how to use Base.create and mix/match extensions to create custom Widget classes.">
1421
 
                                            <a href="widget-build.html">Creating Custom Widget Classes With Extensions</a>
1422
 
                                        </li>
1423
 
                                    
1424
 
                                
1425
 
                                    
1426
 
                                        <li data-description="Shows how to create an IO plugin for Widget.">
1427
 
                                            <a href="widget-plugin.html">Creating a Widget Plugin</a>
1428
 
                                        </li>
1429
 
                                    
1430
 
                                
1431
 
                                    
1432
 
                                        <li data-description="Shows how to extend the Widget class, and add WidgetPosition and WidgetStack to create a Tooltip widget class.">
1433
 
                                            <a href="widget-tooltip.html">Creating a Simple Tooltip Widget With Extensions</a>
1434
 
                                        </li>
1435
 
                                    
1436
 
                                
1437
 
                                    
1438
 
                                        <li data-description="Shows how to extend the Widget class, and add WidgetParent and WidgetChild to create a simple ListBox widget.">
1439
 
                                            <a href="widget-parentchild-listbox.html">Creating a Hierarchical ListBox Widget</a>
1440
 
                                        </li>
1441
 
                                    
1442
 
                                
1443
 
                            </ul>
1444
 
                        </div>
1445
 
                    </div>
1446
 
                
1447
 
 
1448
 
                
1449
 
            </div>
1450
 
        </div>
1451
 
    </div>
1452
 
</div>
1453
 
 
1454
 
<script src="../assets/vendor/prettify/prettify-min.js"></script>
1455
 
<script>prettyPrint();</script>
1456
 
 
1457
 
</body>
1458
 
</html>