src/cm/media/js/lib/yui/yui_3.0.0b1/examples/widget/widget-tooltip.html
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     1 
       
     2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
       
     3 <html>
       
     4 <head>
       
     5 	<title>YUI Library Examples: Widget: Creating a simple Tooltip widget</title>
       
     6     <meta http-equiv="content-type" content="text/html; charset=utf-8">
       
     7     	<link rel="stylesheet" type="text/css" href="../../assets/yui.css" >
       
     8 
       
     9 <style>
       
    10     /*Supplemental CSS for the YUI distribution*/
       
    11     #custom-doc { width: 95%; min-width: 950px; }
       
    12     #pagetitle {background-image: url(../../assets/bg_hd.gif);}
       
    13 /*    #pagetitle h1 {background-image: url(../../assets/title_h_bg.gif);}*/
       
    14 </style>
       
    15 
       
    16 <link rel="stylesheet" type="text/css" href="../../assets/dpSyntaxHighlighter.css">
       
    17 <link type="text/css" rel="stylesheet" href="../../build/cssfonts/fonts-min.css" />
       
    18 <script type="text/javascript" src="../../build/yui/yui-min.js"></script>
       
    19 <style type="text/css">
       
    20     .yui-tooltip {
       
    21         position:absolute;
       
    22     }
       
    23 
       
    24     .yui-tooltip-content {
       
    25         color: #000;
       
    26         padding: 2px 5px;
       
    27         border-color: #D4C237 #A6982B #A6982B #A6982B;
       
    28         border-width: 1px;
       
    29         border-style: solid;
       
    30         background-color: #FFEE69;
       
    31     }
       
    32 
       
    33     .yui-tooltip-hidden {
       
    34         visibility:hidden;
       
    35     }
       
    36 
       
    37     div.yui-hastooltip {
       
    38         border:1px solid #243356;
       
    39         background-color:#406ED9;
       
    40         color:#ffffff;
       
    41         width:25em;
       
    42         margin:20px 0px;
       
    43         padding:5px;
       
    44         cursor:default;
       
    45     }
       
    46 
       
    47     div.yui-hastooltip span {
       
    48         font-style:italic;
       
    49         font-weight:bold;
       
    50         color:#ABCEFF;
       
    51     }
       
    52 
       
    53     .yui-tooltip-content strong {
       
    54         font-weight:bold;
       
    55     }
       
    56 </style>
       
    57 
       
    58 </head>
       
    59 <body id="yahoo-com" class=" yui-skin-sam">
       
    60 <div id="custom-doc" class="yui-t2">
       
    61 <div id="hd">
       
    62 	<div id="ygunav">
       
    63 		<p>
       
    64             <em>
       
    65                 <a href="http://developer.yahoo.com/yui/3/">YUI 3.x Home</a> <i> - </i>	
       
    66             </em>
       
    67 		</p>
       
    68 		<form action="http://search.yahoo.com/search" id="sitesearchform">
       
    69             <input name="vs" type="hidden" value="developer.yahoo.com">
       
    70             <input name="vs" type="hidden" value="yuiblog.com">
       
    71 		    <div id="sitesearch">
       
    72 		    	<label for="searchinput">Site Search (YDN &amp; YUIBlog): </label>
       
    73 			    <input type="text" id="searchinput" name="p">
       
    74 			    <input type="submit" value="Search" id="searchsubmit" class="ygbt">
       
    75 		    </div>
       
    76 		</form>
       
    77     </div>
       
    78 	<div id="ygma"><a href="../../"><img src="../../assets/logo.gif"  border="0" width="200" height="93"></a></div>
       
    79 	<div id="pagetitle"><h1>YUI Library Examples: Widget: Creating a simple Tooltip widget</h1></div>
       
    80 </div>
       
    81 <div id="bd">
       
    82 
       
    83 	<div id="bar-note"><p><strong>Note:</strong> This is YUI 3.x. Looking for <a href="http://developer.yahoo.com/yui/">YUI 2.x</a>?</p></div>
       
    84 
       
    85 	<div id="yui-main">
       
    86 		<div class="yui-b">
       
    87 		  <div class="yui-ge">
       
    88 			  <div class="yui-u first example" id="main">
       
    89 
       
    90 	<h2>Widget: Creating a simple Tooltip widget</h2>
       
    91 
       
    92 	<div id="example" class="promo">
       
    93 	<p>
       
    94 	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>	
       
    95 
       
    96 	<div class="module example-container ">
       
    97 			<div class="hd exampleHd">
       
    98 			<p class="newWindowButton yui-skin-sam">
       
    99                 <a href="widget-tooltip_clean.html" target="_blank">View example in new window.</a>
       
   100             </p>
       
   101 		</div>		<div id="example-canvas" class="bd">
       
   102 
       
   103 		
       
   104 	<!--BEGIN SOURCE CODE FOR EXAMPLE =============================== -->
       
   105 	
       
   106 	<div id="delegate">
       
   107     <div class="yui-hastooltip" title="Tooltip 1" id="tt1">Tooltip One <span>(content from title)</span></div>
       
   108     <div class="yui-hastooltip" title="Tooltip 2" id="tt2">Tooltip Two <span>(content set in event listener)</span></div>
       
   109     <div class="yui-hastooltip" title="Tooltip 3" id="tt3">Tooltip Three <span>(content from lookup)</span></div>
       
   110     <div class="yui-hastooltip" title="Tooltip 4" id="tt4">Tooltip Four <span>(content from title)</span><label></div>
       
   111     <input type="checkbox" id="prevent" /> Prevent Tooltip Four</label>
       
   112 </div>
       
   113 
       
   114 <script type="text/javascript">
       
   115 YUI({base:"../../build/", timeout: 10000}).use("widget", "widget-position", "widget-stack", function(Y) {
       
   116     var Lang = Y.Lang,
       
   117         Node = Y.Node;
       
   118 
       
   119     /* Tooltip constructor */
       
   120     function Tooltip(config) {
       
   121         Tooltip.superclass.constructor.apply(this, arguments);
       
   122     }
       
   123 
       
   124     /* 
       
   125        Required NAME static field, used to identify the Widget class and 
       
   126        used as an event prefix, to generate class names etc. (set to the 
       
   127        class name in camel case). 
       
   128     */
       
   129     Tooltip.NAME = "tooltip";
       
   130 
       
   131     /* Static constants */
       
   132     Tooltip.OFFSET_X = 15;
       
   133     Tooltip.OFFSET_Y = 15;
       
   134     Tooltip.OFFSCREEN_X = -10000;
       
   135     Tooltip.OFFSCREEN_Y = -10000;
       
   136 
       
   137     /* Default Tooltip Attributes */
       
   138     Tooltip.ATTRS = {
       
   139 
       
   140         /* 
       
   141          * The tooltip content. This can either be a fixed content value, 
       
   142          * or a map of id-to-values, designed to be used when a single
       
   143          * tooltip is mapped to multiple trigger elements.
       
   144          */
       
   145         content : {
       
   146             value: null
       
   147         },
       
   148 
       
   149         /* 
       
   150          * The set of nodes to bind to the tooltip instance. Can be a string, 
       
   151          * or a node instance.
       
   152          */
       
   153         triggerNodes : {
       
   154             value: null,
       
   155             setter: function(val) {
       
   156                 if (val && Lang.isString(val)) {
       
   157                     val = Node.all(val);
       
   158                 }
       
   159                 return val;
       
   160             }
       
   161         },
       
   162 
       
   163         /*
       
   164          * The delegate node to which event listeners should be attached.
       
   165          * This node should be an ancestor of all trigger nodes bound
       
   166          * to the instance. By default the document is used.
       
   167          */
       
   168         delegate : {
       
   169             value: null,
       
   170             setter: function(val) {
       
   171                 return Node.get(val) || Node.get("document");
       
   172             }
       
   173         },
       
   174 
       
   175         /*
       
   176          * The time to wait, after the mouse enters the trigger node,
       
   177          * to display the tooltip
       
   178          */
       
   179         showDelay : {
       
   180             value:250
       
   181         },
       
   182 
       
   183         /*
       
   184          * The time to wait, after the mouse leaves the trigger node,
       
   185          * to hide the tooltip
       
   186          */
       
   187         hideDelay : {
       
   188             value:10
       
   189         },
       
   190 
       
   191         /*
       
   192          * The time to wait, after the tooltip is first displayed for 
       
   193          * a trigger node, to hide it, if the mouse has not left the 
       
   194          * trigger node
       
   195          */
       
   196         autoHideDelay : {
       
   197             value:2000
       
   198         },
       
   199 
       
   200         /*
       
   201          * Override the default visibility set by the widget base class
       
   202          */
       
   203         visible : {
       
   204             value:false
       
   205         },
       
   206 
       
   207         /*
       
   208          * Override the default XY value set by the widget base class,
       
   209          * to position the tooltip offscreen
       
   210          */
       
   211         xy: {
       
   212             value:[Tooltip.OFFSCREEN_X, Tooltip.OFFSCREEN_Y]
       
   213         }
       
   214     };
       
   215 
       
   216     /* Extend the base Widget class */
       
   217     Y.extend(Tooltip, Y.Widget, {
       
   218 
       
   219         /*
       
   220          * Initialization Code: Sets up privately used state
       
   221          * properties, and publishes the events Tooltip introduces
       
   222          */
       
   223         initializer : function(config) {
       
   224 
       
   225             this._triggerClassName = this.getClassName("trigger");
       
   226 
       
   227             // Currently bound trigger node information
       
   228             this._currTrigger = {
       
   229                 node: null,
       
   230                 title: null,
       
   231                 mouseX: Tooltip.OFFSCREEN_X,
       
   232                 mouseY: Tooltip.OFFSCREEN_Y
       
   233             };
       
   234 
       
   235             // Event handles - mouse over is set on the delegate
       
   236             // element, mousemove and mouseout are set on the trigger node
       
   237             this._eventHandles = {
       
   238                 delegate: null,
       
   239                 trigger: {
       
   240                     mouseMove : null,
       
   241                     mouseOut: null
       
   242                 }
       
   243             };
       
   244 
       
   245             // Show/hide timers
       
   246             this._timers = {
       
   247                 show: null,
       
   248                 hide: null
       
   249             };
       
   250 
       
   251             // Publish events introduced by Tooltip. Note the triggerEnter event is preventable,
       
   252             // with the default behavior defined in the _defTriggerEnterFn method 
       
   253             this.publish("triggerEnter", {defaultFn: this._defTriggerEnterFn, preventable:true});
       
   254             this.publish("triggerLeave", {preventable:false});
       
   255         },
       
   256 
       
   257         /*
       
   258          * Destruction Code: Clears event handles, timers,
       
   259          * and current trigger information
       
   260          */
       
   261         destructor : function() {
       
   262             this._clearCurrentTrigger();
       
   263             this._clearTimers();
       
   264             this._clearHandles();
       
   265         },
       
   266 
       
   267         /*
       
   268          * bindUI is used to bind attribute change and dom event
       
   269          * listeners
       
   270          */
       
   271         bindUI : function() {
       
   272             this.after("delegateChange", this._afterSetDelegate);
       
   273             this.after("nodesChange", this._afterSetNodes);
       
   274 
       
   275             this._bindDelegate();
       
   276         },
       
   277 
       
   278         /*
       
   279          * syncUI is used to update the rendered DOM, based on the current
       
   280          * Tooltip state
       
   281          */
       
   282         syncUI : function() {
       
   283             this._uiSetNodes(this.get("triggerNodes"));
       
   284         },
       
   285 
       
   286         /*
       
   287          * Public method, which can be used by triggerEvent event listeners
       
   288          * to set the content of the tooltip for the current trigger node
       
   289          */
       
   290         setTriggerContent : function(content) {
       
   291             var contentBox = this.get("contentBox");
       
   292             contentBox.set("innerHTML", "");
       
   293 
       
   294             if (content) {
       
   295                 if (content instanceof Node) {
       
   296                     for (var i = 0, l = content.size(); i < l; ++i) {
       
   297                         contentBox.appendChild(content.item(i));
       
   298                     }
       
   299                 } else if (Lang.isString(content)) {
       
   300                     contentBox.set("innerHTML", content);
       
   301                 }
       
   302             }
       
   303         },
       
   304 
       
   305         /*
       
   306          * Gets the closest ancestor of the given node,
       
   307          * which is a tooltip trigger node
       
   308          */
       
   309         getParentTrigger : function(node) {
       
   310             var cn = this._triggerClassName;
       
   311             return (node.hasClass(cn)) ? node : node.ancestor(function(node) {node.hasClass(cn)});
       
   312         },
       
   313 
       
   314         /*
       
   315          * Default attribute change listener for 
       
   316          * the triggerNodes attribute
       
   317          */
       
   318         _afterSetNodes : function(e) {
       
   319             this._uiSetNodes(e.newVal);
       
   320         },
       
   321 
       
   322         /*
       
   323          * Default attribute change listener for 
       
   324          * the delegate attribute
       
   325          */
       
   326         _afterSetDelegate : function(e) {
       
   327             this._bindDelegate(e.newVal);
       
   328         },
       
   329 
       
   330         /*
       
   331          * Updates the rendered DOM to reflect the
       
   332          * set of trigger nodes passed in
       
   333          */
       
   334         _uiSetNodes : function(nodes) {
       
   335             if (this._triggerNodes) {
       
   336                 this._triggerNodes.removeClass(this._triggerClassName);
       
   337             }
       
   338 
       
   339             if (nodes) {
       
   340                 this._triggerNodes = nodes;
       
   341                 this._triggerNodes.addClass(this._triggerClassName);
       
   342             }
       
   343         },
       
   344 
       
   345         /*
       
   346          * Attaches the default mouseover DOM listener to the 
       
   347          * current delegate node
       
   348          */
       
   349         _bindDelegate : function() {
       
   350             var eventHandles = this._eventHandles;
       
   351 
       
   352             if (eventHandles.delegate) {
       
   353                 eventHandles.delegate.detach();
       
   354                 eventHandles.delegate = null;
       
   355             }
       
   356             eventHandles.delegate = Y.on("mouseover", Y.bind(this._onDelegateMouseOver, this), this.get("delegate"));
       
   357         },
       
   358 
       
   359         /*
       
   360          * Default mouse over DOM event listener.
       
   361          * 
       
   362          * Delegates to the _enterTrigger method,
       
   363          * if the mouseover enters a trigger node.
       
   364          */
       
   365         _onDelegateMouseOver : function(e) {
       
   366             var node = this.getParentTrigger(e.target);
       
   367             if (node && (!this._currTrigger.node || !node.compareTo(this._currTrigger.node))) {
       
   368                 this._enterTrigger(node, e.pageX, e.pageY);
       
   369             }
       
   370         },
       
   371 
       
   372         /*
       
   373          * Default mouse out DOM event listener
       
   374          * 
       
   375          * Delegates to _leaveTrigger if the mouseout
       
   376          * leaves the current trigger node
       
   377          */
       
   378         _onNodeMouseOut : function(e) {
       
   379             var to = e.relatedTarget;
       
   380             var trigger = e.currentTarget;
       
   381 
       
   382             if (!trigger.contains(to)) {
       
   383                 this._leaveTrigger(trigger);
       
   384             }
       
   385         },
       
   386 
       
   387         /*
       
   388          * Default mouse move DOM event listener
       
   389          */
       
   390         _onNodeMouseMove : function(e) {
       
   391             this._overTrigger(e.pageX, e.pageY);
       
   392         },
       
   393 
       
   394         /*
       
   395          * Default handler invoked when the mouse enters
       
   396          * a trigger node. Fires the triggerEnter
       
   397          * event which can be prevented by listeners to 
       
   398          * show the tooltip from being displayed.
       
   399          */
       
   400         _enterTrigger : function(node, x, y) {
       
   401             this._setCurrentTrigger(node, x, y);
       
   402             this.fire("triggerEnter", {node:node, pageX:x, pageY:y});
       
   403         },
       
   404 
       
   405         /*
       
   406          * Default handler for the triggerEvent event,
       
   407          * which will setup the timer to display the tooltip,
       
   408          * if the default handler has not been prevented.
       
   409          */
       
   410         _defTriggerEnterFn : function(e) {
       
   411             var node = e.node;
       
   412             if (!this.get("disabled")) {
       
   413                 this._clearTimers();
       
   414                 var delay = (this.get("visible")) ? 0 : this.get("showDelay");
       
   415                 this._timers.show = Y.later(delay, this, this._showTooltip, [node]);
       
   416             }
       
   417         },
       
   418 
       
   419         /*
       
   420          * Default handler invoked when the mouse leaves
       
   421          * the current trigger node. Fires the triggerLeave
       
   422          * event and sets up the hide timer
       
   423          */
       
   424         _leaveTrigger : function(node) {
       
   425             this.fire("triggerLeave");
       
   426 
       
   427             this._clearCurrentTrigger();
       
   428             this._clearTimers();
       
   429 
       
   430             this._timers.hide = Y.later(this.get("hideDelay"), this, this._hideTooltip);
       
   431         },
       
   432 
       
   433         /*
       
   434          * Default handler invoked for mousemove events
       
   435          * on the trigger node. Stores the current mouse 
       
   436          * x, y positions
       
   437          */
       
   438         _overTrigger : function(x, y) {
       
   439             this._currTrigger.mouseX = x;
       
   440             this._currTrigger.mouseY = y;
       
   441         },
       
   442 
       
   443         /*
       
   444          * Shows the tooltip, after moving it to the current mouse
       
   445          * position.
       
   446          */
       
   447         _showTooltip : function(node) {
       
   448             var x = this._currTrigger.mouseX;
       
   449             var y = this._currTrigger.mouseY;
       
   450 
       
   451             this.move(x + Tooltip.OFFSET_X, y + Tooltip.OFFSET_Y);
       
   452 
       
   453             this.show();
       
   454             this._clearTimers();
       
   455 
       
   456             this._timers.hide = Y.later(this.get("autoHideDelay"), this, this._hideTooltip);
       
   457         },
       
   458 
       
   459         /*
       
   460          * Hides the tooltip, after clearing existing timers.
       
   461          */
       
   462         _hideTooltip : function() {
       
   463             this._clearTimers();
       
   464             this.hide();
       
   465         },
       
   466 
       
   467         /*
       
   468          * Set the rendered content of the tooltip for the current
       
   469          * trigger, based on (in order of precedence):
       
   470          * 
       
   471          * a). The string/node content attribute value
       
   472          * b). From the content lookup map if it is set, or 
       
   473          * c). From the title attribute if set.
       
   474          */
       
   475         _setTriggerContent : function(node) {
       
   476             var content = this.get("content");
       
   477             if (content && !(content instanceof Node || Lang.isString(content))) {
       
   478                 content = content[node.get("id")] || node.getAttribute("title");
       
   479             }
       
   480             this.setTriggerContent(content);
       
   481         },
       
   482 
       
   483         /*
       
   484          * Set the currently bound trigger node information, clearing 
       
   485          * out the title attribute if set and setting up mousemove/out 
       
   486          * listeners.
       
   487          */
       
   488         _setCurrentTrigger : function(node, x, y) {
       
   489 
       
   490             var currTrigger = this._currTrigger,
       
   491                 triggerHandles = this._eventHandles.trigger;
       
   492 
       
   493             this._setTriggerContent(node);
       
   494 
       
   495             triggerHandles.mouseMove = Y.on("mousemove", Y.bind(this._onNodeMouseMove, this), node);
       
   496             triggerHandles.mouseOut = Y.on("mouseout", Y.bind(this._onNodeMouseOut, this), node);
       
   497 
       
   498             var title = node.getAttribute("title");
       
   499             node.setAttribute("title", "");
       
   500 
       
   501             currTrigger.mouseX = x;
       
   502             currTrigger.mouseY = y;
       
   503             currTrigger.node = node;
       
   504             currTrigger.title = title;
       
   505         },
       
   506 
       
   507         /*
       
   508          * Clear out the current trigger state, restoring
       
   509          * the title attribute on the trigger node, 
       
   510          * if it was originally set.
       
   511          */
       
   512         _clearCurrentTrigger : function() {
       
   513 
       
   514             var currTrigger = this._currTrigger,
       
   515                 triggerHandles = this._eventHandles.trigger;
       
   516 
       
   517             if (currTrigger.node) {
       
   518                 var node = currTrigger.node;
       
   519                 var title = currTrigger.title || "";
       
   520 
       
   521                 currTrigger.node = null;
       
   522                 currTrigger.title = "";
       
   523 
       
   524                 triggerHandles.mouseMove.detach();
       
   525                 triggerHandles.mouseOut.detach();
       
   526                 triggerHandles.mouseMove = null;
       
   527                 triggerHandles.mouseOut = null;
       
   528 
       
   529                 node.setAttribute("title", title);
       
   530             }
       
   531         },
       
   532 
       
   533         /*
       
   534          * Cancel any existing show/hide timers
       
   535          */
       
   536         _clearTimers : function() {
       
   537             var timers = this._timers;
       
   538             if (timers.hide) {
       
   539                 timers.hide.cancel();
       
   540                 timers.hide = null;
       
   541             }
       
   542             if (timers.show) {
       
   543               timers.show.cancel();
       
   544               timers.show = null;
       
   545             }
       
   546         },
       
   547 
       
   548         /*
       
   549          * Detach any stored event handles
       
   550          */
       
   551         _clearHandles : function() {
       
   552             var eventHandles = this._eventHandles;
       
   553 
       
   554             if (eventHandles.delegate) {
       
   555                 this._eventHandles.delegate.detach();
       
   556             }
       
   557             if (eventHandles.trigger.mouseOut) {
       
   558                 eventHandles.trigger.mouseOut.detach();
       
   559             }
       
   560             if (eventHandles.trigger.mouseMove) {
       
   561                 eventHandles.trigger.mouseMove.detach();
       
   562             }
       
   563         }
       
   564     });
       
   565 
       
   566     // dynamic:false = Modify the existing Tooltip class
       
   567     Tooltip = Y.Base.build(Tooltip.NAME, Tooltip, [Y.WidgetPosition, Y.WidgetStack], {dynamic:false});
       
   568 
       
   569     var tt = new Tooltip({
       
   570         triggerNodes:".yui-hastooltip",
       
   571         delegate: "#delegate",
       
   572         content: {
       
   573             tt3: "Tooltip 3 (from lookup)"
       
   574         },
       
   575         shim:false,
       
   576         zIndex:2
       
   577     });
       
   578     tt.render();
       
   579 
       
   580     tt.on("triggerEnter", function(e) {
       
   581         var node = e.node;
       
   582         if (node && node.get("id") == "tt2") {
       
   583             this.setTriggerContent("Tooltip 2 (from triggerEvent)");
       
   584         }
       
   585     });
       
   586 
       
   587     var prevent = Y.Node.get("#prevent");
       
   588     tt.on("triggerEnter", function(e) {
       
   589         var node = e.node;
       
   590         if (prevent.get("checked")) {
       
   591             if (node && node.get("id") == "tt4") {
       
   592                 e.preventDefault();
       
   593             }
       
   594         }
       
   595     });
       
   596 });
       
   597 </script>
       
   598 	
       
   599 	<!--END SOURCE CODE FOR EXAMPLE =============================== -->
       
   600 	
       
   601 		
       
   602 		</div>
       
   603 	</div>			
       
   604 	</div>
       
   605 		
       
   606 	<h3>Creating A Tooltip Widget Class</h3>
       
   607 
       
   608 <h4>Basic Class Structure</h4>
       
   609 
       
   610 <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>
       
   611 
       
   612 <p>Namely:</p>
       
   613 
       
   614 <ul>
       
   615     <li>Set up the constructor to invoke the superclass constructor</li>
       
   616     <li>Define a <code>NAME</code> property, to identify the class</li>
       
   617     <li>Define the default attribute configuration, using the <code>ATTRS</code> property</li>
       
   618     <li>Implement prototype methods</li>
       
   619 </ul>
       
   620 
       
   621 <p>This basic structure is shown below:</p>
       
   622 
       
   623 <textarea name="code" class="JScript" rows="1" cols="60">
       
   624     /* 
       
   625      *  Required NAME static field, used to identify the Widget class and 
       
   626      *  used as an event prefix, to generate class names etc. (set to the 
       
   627      *  class name in camel case). 
       
   628      */
       
   629     Tooltip.NAME = "tooltip";
       
   630 
       
   631     /* Default Tooltip Attributes */
       
   632     Tooltip.ATTRS = {
       
   633 
       
   634         /* 
       
   635          * The tooltip content. This can either be a fixed content value, 
       
   636          * or a map of id-to-values, designed to be used when a single
       
   637          * tooltip is mapped to multiple trigger elements.
       
   638          */
       
   639         content : {
       
   640             value: null
       
   641         },
       
   642 
       
   643         /* 
       
   644          * The set of nodes to bind to the tooltip instance. Can be a string, 
       
   645          * or a node instance.
       
   646          */
       
   647         triggerNodes : {
       
   648             value: null,
       
   649             setter: function(val) {
       
   650                 if (val && Lang.isString(val)) {
       
   651                     val = Node.all(val);
       
   652                 }
       
   653                 return val;
       
   654             }
       
   655         },
       
   656 
       
   657         /*
       
   658          * The delegate node to which event listeners should be attached.
       
   659          * This node should be an ancestor of all trigger nodes bound
       
   660          * to the instance. By default the document is used.
       
   661          */
       
   662         delegate : {
       
   663             value: null,
       
   664             setter: function(val) {
       
   665                 return Node.get(val) || Node.get("document");
       
   666             }
       
   667         },
       
   668 
       
   669         /*
       
   670          * The time to wait, after the mouse enters the trigger node,
       
   671          * to display the tooltip
       
   672          */
       
   673         showDelay : {
       
   674             value:250
       
   675         },
       
   676 
       
   677         /*
       
   678          * The time to wait, after the mouse leaves the trigger node,
       
   679          * to hide the tooltip
       
   680          */
       
   681         hideDelay : {
       
   682             value:10
       
   683         },
       
   684 
       
   685         /*
       
   686          * The time to wait, after the tooltip is first displayed for 
       
   687          * a trigger node, to hide it, if the mouse has not left the 
       
   688          * trigger node
       
   689          */
       
   690         autoHideDelay : {
       
   691             value:2000
       
   692         },
       
   693 
       
   694         /*
       
   695          * Override the default visibility set by the widget base class
       
   696          */
       
   697         visible : {
       
   698             value:false
       
   699         },
       
   700 
       
   701         /*
       
   702          * Override the default XY value set by the widget base class,
       
   703          * to position the tooltip offscreen
       
   704          */
       
   705         xy: {
       
   706             value:[Tooltip.OFFSCREEN_X, Tooltip.OFFSCREEN_Y]
       
   707         }
       
   708     };
       
   709 
       
   710     Y.extend(Tooltip, Y.Widget, { 
       
   711         // Prototype methods/properties
       
   712     });
       
   713 </textarea>
       
   714 
       
   715 <h4>Adding WidgetPosition and WidgetStack Extension Support</h4>
       
   716 
       
   717 <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
       
   718 <code>Base.build</code> to add this support to the <code>Tooltip</code> class. However in this case, we want to modify the Tooltip class, as opposed to extending it 
       
   719 to create a completely new class, hence we set the <code>dynamic</code> configuration property to <code>false</code>:</p>
       
   720 
       
   721 <textarea name="code" class="JScript" rows="1" cols="60">
       
   722     // dynamic:false = Modify the existing Tooltip class
       
   723     Tooltip = Y.Base.build("tooltip", Tooltip, [Y.WidgetPosition, Y.WidgetStack], {dynamic:false});
       
   724 </textarea>
       
   725 
       
   726 <h4>Lifecycle Methods: initializer, destructor</h4>
       
   727 
       
   728 <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 
       
   729 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>
       
   730 
       
   731 <textarea name="code" class="JScript" rows="1" cols="60">
       
   732 
       
   733     initializer : function(config) {
       
   734 
       
   735         this._triggerClassName = this.getClassName("trigger");
       
   736 
       
   737         // Currently bound trigger node information
       
   738         this._currTrigger = {
       
   739             node: null,
       
   740             title: null,
       
   741             mouseX: Tooltip.OFFSCREEN_X,
       
   742             mouseY: Tooltip.OFFSCREEN_Y
       
   743         };
       
   744 
       
   745         // Event handles - mouse over is set on the delegate
       
   746         // element, mousemove and mouseout are set on the trigger node
       
   747         this._eventHandles = {
       
   748             delegate: null,
       
   749             trigger: {
       
   750                 mouseMove : null,
       
   751                 mouseOut: null
       
   752             }
       
   753         };
       
   754 
       
   755         // Show/hide timers
       
   756         this._timers = {
       
   757             show: null,
       
   758             hide: null
       
   759         };
       
   760 
       
   761         // Publish events introduced by Tooltip. Note the triggerEnter event is preventable,
       
   762         // with the default behavior defined in the _defTriggerEnterFn method 
       
   763         this.publish("triggerEnter", {defaultFn: this._defTriggerEnterFn, preventable:true});
       
   764         this.publish("triggerLeave", {preventable:false});
       
   765     }
       
   766 </textarea>
       
   767 
       
   768 <p>The <code>destructor</code> is used to clear out stored state, detach any event handles and clear out the show/hide timers:</p>
       
   769 
       
   770 <textarea name="code" class="JScript" rows="1" cols="60">
       
   771     destructor : function() {
       
   772         this._clearCurrentTrigger();
       
   773         this._clearTimers();
       
   774         this._clearHandles();
       
   775     }
       
   776 </textarea>
       
   777 
       
   778 <h4>Lifecycle Methods: bindUI, syncUI</h4>
       
   779 
       
   780 <p>The <code>bindUI</code> and <code>syncUI</code> are invoked by the base Widget class' <code>renderer</code> method.</p>
       
   781 
       
   782 <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
       
   783 the DOM listeners required to enable the UI for interaction.</p>
       
   784 
       
   785 <p><code>syncUI</code> is used to sync the UI state from the current widget state, when initially rendered.</p>
       
   786 
       
   787 <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
       
   788 tooltip does not have any additional elements in needs to add to the DOM, outside of the default Widget boundingBox and contentBox.</p>
       
   789 
       
   790 <textarea name="code" class="JScript" rows="1" cols="60">
       
   791     bindUI : function() {
       
   792         this.after("delegateChange", this._afterSetDelegate);
       
   793         this.after("nodesChange", this._afterSetNodes);
       
   794 
       
   795         this._bindDelegate();
       
   796     },
       
   797 
       
   798     syncUI : function() {
       
   799         this._uiSetNodes(this.get("triggerNodes"));
       
   800     }
       
   801 </textarea>
       
   802 
       
   803 <h4>Attribute Supporting Methods</h4>
       
   804 
       
   805 <p>Tooltip's <code>triggerNodes</code>, which defines the set of nodes which should trigger this tooltip instance,
       
   806 has a couple of supporting methods associated with it.</p>
       
   807 
       
   808 <p>The <code>_afterSetNodes</code> method is the default attribute change event handler for the <code>triggerNodes</code>
       
   809 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>
       
   810 
       
   811 <textarea name="code" class="JScript" rows="1" cols="60">
       
   812     _afterSetNodes : function(e) {
       
   813         this._uiSetNodes(e.newVal);
       
   814     },
       
   815 
       
   816     _uiSetNodes : function(nodes) {
       
   817         if (this._triggerNodes) {
       
   818             this._triggerNodes.removeClass(this._triggerClassName);
       
   819         }
       
   820 
       
   821         if (nodes) {
       
   822             this._triggerNodes = nodes;
       
   823             this._triggerNodes.addClass(this._triggerClassName);
       
   824         }
       
   825     },
       
   826 </textarea>
       
   827 
       
   828 <p>Similarly the <code>_afterSetDelegate</code> method is the default attributechange listener for the <code>delegate</code> attribute,
       
   829 and invokes <code>_bindDelegate</code> to set up the listeners when a new delegate node is set.</p>
       
   830 
       
   831 <textarea name="code" class="JScript" rows="1" cols="60">
       
   832     _afterSetDelegate : function(e) {
       
   833         this._bindDelegate(e.newVal);
       
   834     },
       
   835 
       
   836     _bindDelegate : function() {
       
   837         var eventHandles = this._eventHandles;
       
   838 
       
   839         if (eventHandles.delegate) {
       
   840             eventHandles.delegate.detach();
       
   841             eventHandles.delegate = null;
       
   842         }
       
   843         eventHandles.delegate = Y.on("mouseover", Y.bind(this._onDelegateMouseOver, this), this.get("delegate"));
       
   844     },
       
   845 </textarea>
       
   846 
       
   847 <h4>DOM Event Handlers</h4>
       
   848 
       
   849 <p>Tooltips interaction revolves around the <code>mouseover</code>, <code>mousemove</code> and <code>mouseout</code> DOM events. The mouseover listener is the only listener set up initially, on the <code>delegate</code> node:</p>
       
   850 
       
   851 <textarea name="code" class="JScript" rows="1" cols="60">
       
   852     _onDelegateMouseOver : function(e) {
       
   853         var node = this.getParentTrigger(e.target);
       
   854         if (node && (!this._currTrigger.node || !node.compareTo(this._currTrigger.node))) {
       
   855             this._enterTrigger(node, e.pageX, e.pageY);
       
   856         }
       
   857     }
       
   858 </textarea>
       
   859 
       
   860 <p>It attempts to determine if the mouse is entering a trigger node. It ignores mouseover events generated from elements 
       
   861 inside the current trigger node (for example when mousing out of a child element of a trigger node). If it determines that the mouse is entering a trigger node,
       
   862 the delegates to the <code>_enterTrigger</code> method to setup the current trigger state and attaches mousemove and mouseout listeners on the current trigger node.</p>
       
   863 
       
   864 <p>The mouse out listener delegates to the <code>_leaveTrigger</code> method, if it determines the mouse is leaving the trigger node:</p>
       
   865 
       
   866 <textarea name="code" class="JScript" rows="1" cols="60">
       
   867     _onNodeMouseOut : function(e) {
       
   868         var to = e.relatedTarget;
       
   869         var trigger = e.currentTarget;
       
   870 
       
   871         if (!trigger.contains(to)) {
       
   872             this._leaveTrigger(trigger);
       
   873         }
       
   874     }
       
   875 </textarea>
       
   876 
       
   877 <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>
       
   878 
       
   879 <textarea name="code" class="JScript" rows="1" cols="60">
       
   880     _onNodeMouseMove : function(e) {
       
   881         this._overTrigger(e.pageX, e.pageY);
       
   882     }
       
   883 </textarea>
       
   884 
       
   885 <h4>Trigger Event Delegates: _enterTrigger, _leaveTrigger, _overTrigger</h4>
       
   886 
       
   887 <p>As seen above, the DOM event handlers delegate to the <code>_enterTrigger, _leaveTrigger and _overTrigger</code> methods to update the 
       
   888 Tooltip state based on the currently active trigger node.</p>
       
   889 
       
   890 <p>The <code>_enterTrigger</code> method sets the current trigger state (which node is the current tooltip trigger, 
       
   891 what the current mouse XY position is, etc.). The method also fires the <code>triggerEnter</code> event, whose default function actually handles 
       
   892 showing the tooltip after the configured <code>showDelay</code> period. The <code>triggerEnter</code> event can be prevented by listeners, allowing 
       
   893 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>
       
   894 
       
   895 <textarea name="code" class="JScript" rows="1" cols="60">
       
   896     _enterTrigger : function(node, x, y) {
       
   897         this._setCurrentTrigger(node, x, y);
       
   898         this.fire("triggerEnter", null, node, x, y);
       
   899     },
       
   900 
       
   901     _defTriggerEnterFn : function(e) {
       
   902         var node = e.node;
       
   903         if (!this.get("disabled")) {
       
   904             this._clearTimers();
       
   905             var delay = (this.get("visible")) ? 0 : this.get("showDelay");
       
   906             this._timers.show = Y.later(delay, this, this._showTooltip, [node]);
       
   907         }
       
   908     },
       
   909 </textarea>
       
   910 
       
   911 <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
       
   912 the <code>hideDelay</code> timer. It fires a <code>triggerLeave</code> event, but cannot be prevented, and has no default behavior to prevent:</p>
       
   913 
       
   914 <textarea name="code" class="JScript" rows="1" cols="60">
       
   915     _leaveTrigger : function(node) {
       
   916         this.fire("triggerLeave");
       
   917 
       
   918         this._clearCurrentTrigger();
       
   919         this._clearTimers();
       
   920 
       
   921         this._timers.hide = Y.later(this.get("hideDelay"), this, this._hideTooltip);
       
   922     },
       
   923 </textarea>
       
   924 
       
   925 <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>
       
   926 
       
   927 <textarea name="code" class="JScript" rows="1" cols="60">
       
   928     _overTrigger : function(x, y) {
       
   929         this._currTrigger.mouseX = x;
       
   930         this._currTrigger.mouseY = y;
       
   931     }
       
   932 </textarea>
       
   933 
       
   934 <h4>Setting Tooltip Content</h4>
       
   935 
       
   936 <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>
       
   937 
       
   938 <ol>
       
   939     <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
       
   940     for all triggerNodes</li>
       
   941     <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
       
   942     will be set using the map, when the tooltip is triggered for the node.</li>
       
   943     <li>Setting the title attribute on the trigger node. The value of the title attribute is used to set the tooltip content,
       
   944     when triggered for the node.</li>
       
   945     <li>By calling the <code>setTriggerContent</code> method to set content for a specific trigger node, in a <code>triggerEnter</code> event listener.</li>
       
   946 </ol>
       
   947 
       
   948 <p>The precedence of these methods is handled in the <code>_setTriggerContent</code> method, invoked when the mouse enters a trigger:</p>
       
   949 
       
   950 <textarea name="code" class="JScript" rows="1" cols="60">
       
   951     _setTriggerContent : function(node) {
       
   952         var content = this.get("content");
       
   953         if (content && !(content instanceof Node || Lang.isString(content))) {
       
   954             content = content[node.get("id")] || node.getAttribute("title");
       
   955         }
       
   956         this.setTriggerContent(content);
       
   957     },
       
   958 
       
   959     setTriggerContent : function(content) {
       
   960         var contentBox = this.get("contentBox");
       
   961         contentBox.set("innerHTML", "");
       
   962 
       
   963         if (content) {
       
   964             if (content instanceof Node) {
       
   965                 for (var i = 0, l = content.size(); i < l; ++i) {
       
   966                     contentBox.appendChild(content.item(i));
       
   967                 }
       
   968             } else if (Lang.isString(content)) {
       
   969                 contentBox.set("innerHTML", content);
       
   970             }
       
   971         }
       
   972     }
       
   973 </textarea>
       
   974 
       
   975 <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>
       
   976 
       
   977 <h4>Using Tooltip</h4>
       
   978 
       
   979 <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="delegate"</code> which will act as the <code>delegate</code> node.</p>
       
   980 
       
   981 <textarea name="code" class="JScript" rows="1" cols="60">
       
   982     var tt = new Tooltip({
       
   983         triggerNodes:".yui-hastooltip",
       
   984         delegate: "#delegate",
       
   985         content: {
       
   986             tt3: "Tooltip 3 (from lookup)"
       
   987         },
       
   988         shim:false,
       
   989         zIndex:2
       
   990     });
       
   991     tt.render();
       
   992 </textarea>
       
   993 
       
   994 <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>
       
   995 
       
   996 <textarea name="code" class="JScript" rows="1" cols="60">
       
   997     tt.on("triggerEnter", function(e) {
       
   998         var node = e.node;
       
   999         if (node && node.get("id") == "tt2") {
       
  1000             this.setTriggerContent("Tooltip 2 (from triggerEvent)");
       
  1001         }
       
  1002     });
       
  1003 </textarea>
       
  1004 
       
  1005 <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>
       
  1006 
       
  1007 <textarea name="code" class="JScript" rows="1" cols="60">
       
  1008     var prevent = Y.Node.get("#prevent");
       
  1009     tt.on("triggerEnter", function(e) {
       
  1010         var node = e.node;
       
  1011         if (prevent.get("checked")) {
       
  1012             if (node && node.get("id") == "tt4") {
       
  1013                 e.preventDefault();
       
  1014             }
       
  1015         }
       
  1016     });
       
  1017 </textarea>
       
  1018 				</div>
       
  1019 				<div class="yui-u sidebar">
       
  1020 					
       
  1021 				
       
  1022 					<div id="examples" class="mod box4">
       
  1023                         <div class="hd">
       
  1024 						<h4>
       
  1025     Widget Examples:</h4>
       
  1026                         </div>
       
  1027 						<div class="bd">
       
  1028 							<ul>
       
  1029 								<li><a href='../widget/widget-extend.html'>Extending the base widget class</a></li><li><a href='../widget/widget-build.html'>Creating custom widget classes</a></li><li class='selected'><a href='../widget/widget-tooltip.html'>Creating a simple Tooltip widget</a></li>							</ul>
       
  1030 						</div>
       
  1031 					</div>
       
  1032 					
       
  1033 					<div class="mod box4">
       
  1034                         <div class="hd">
       
  1035 						<h4>More Widget Resources:</h4>
       
  1036                         </div>
       
  1037                         <div class="bd">
       
  1038 						<ul>
       
  1039 							<!-- <li><a href="http://developer.yahoo.com/yui/widget/">User's Guide</a> (external)</li> -->
       
  1040 						<li><a href="../../api/module_widget.html">API Documentation</a></li>
       
  1041 </ul>
       
  1042                         </div>
       
  1043 					</div>
       
  1044 			  </div>
       
  1045 		</div>
       
  1046 		
       
  1047 		</div>
       
  1048 	</div>
       
  1049 
       
  1050 
       
  1051 <div class="yui-b toc3" id="tocWrapper">
       
  1052 <!-- TABLE OF CONTENTS -->
       
  1053 <div id="toc">
       
  1054 	
       
  1055 <ul>
       
  1056 <li class="sect first">YUI 3.x Project</li><li class="item"><a title="The Yahoo! User Interface (YUI) Library, 3.x Branch, " href="http://developer.yahoo.com/yui/3/">YUI 3 Web Site (external)</a></li><li class="item"><a title="Examples of every YUI utility and control in action" href="../../examples/">YUI 3 Examples</a></li><li class="item"><a title="Instantly searchable API documentation for the entire YUI library." href="../../api/">YUI 3 API Docs</a></li><li class="item"><a title="The YUI Library can be downloaded from SourceForge" href="http://sourceforge.net/projects/yui/">YUI 3 on Sourceforge (external)</a></li><li class="item"><a title="YUI is free and open, offered under a BSD license." href="http://developer.yahoo.com/yui/3/license.html">YUI License (external)</a></li><li class="sect">YUI 3 Core - Examples</li><li class="item"><a title="YUI (Global Prerequisite) - Functional Examples" href="../../examples/yui/index.html">YUI (Global Prerequisite)</a></li><li class="item"><a title="Event - Functional Examples" href="../../examples/event/index.html">Event</a></li><li class="item"><a title="Node - Functional Examples" href="../../examples/node/index.html">Node</a></li><li class="sect">YUI 3 Component Infrastructure - Examples</li><li class="item"><a title="Attribute - Functional Examples" href="../../examples/attribute/index.html">Attribute</a></li><li class="item"><a title="Plugin - Functional Examples" href="../../examples/plugin/index.html">Plugin</a></li><li class="selected "><a title="Widget - Functional Examples" href="../../examples/widget/index.html">Widget</a></li><li class="sect">YUI 3 Utilities - Examples</li><li class="item"><a title="Animation - Functional Examples" href="../../examples/anim/index.html">Animation</a></li><li class="item"><a title="Cache - Functional Examples" href="../../examples/cache/index.html">Cache</a></li><li class="item"><a title="Cookie - Functional Examples" href="../../examples/cookie/index.html">Cookie</a></li><li class="item"><a title="DataSchema - Functional Examples" href="../../examples/dataschema/index.html">DataSchema</a></li><li class="item"><a title="DataSource - Functional Examples" href="../../examples/datasource/index.html">DataSource</a></li><li class="item"><a title="DataType - Functional Examples" href="../../examples/datatype/index.html">DataType</a></li><li class="item"><a title="Drag &amp; Drop - Functional Examples" href="../../examples/dd/index.html">Drag &amp; Drop</a></li><li class="item"><a title="Get - Functional Examples" href="../../examples/get/index.html">Get</a></li><li class="item"><a title="History - Functional Examples" href="../../examples/history/index.html">History</a></li><li class="item"><a title="ImageLoader - Functional Examples" href="../../examples/imageloader/index.html">ImageLoader</a></li><li class="item"><a title="IO - Functional Examples" href="../../examples/io/index.html">IO</a></li><li class="item"><a title="JSON (JavaScript Object Notation) - Functional Examples" href="../../examples/json/index.html">JSON</a></li><li class="item"><a title="Queue - Functional Examples" href="../../examples/queue/index.html">Queue</a></li><li class="item"><a title="Stylesheet - Functional Examples" href="../../examples/stylesheet/index.html">Stylesheet</a></li><li class="sect">YUI 3 Widgets - Examples</li><li class="item"><a title="Overlay - Functional Examples" href="../../examples/overlay/index.html">Overlay</a></li><li class="item"><a title="Slider - Functional Examples" href="../../examples/slider/index.html">Slider</a></li><li class="sect">YUI 3 Node Plugins - Examples</li><li class="item"><a title="FocusManager Node Plugin - Functional Examples" href="../../examples/node-focusmanager/index.html">FocusManager Node Plugin</a></li><li class="item"><a title="MenuNav Node Plugin - Functional Examples" href="../../examples/node-menunav/index.html">MenuNav Node Plugin</a></li><li class="sect">YUI 3 CSS - Examples</li><li class="item"><a title="YUI CSS Reset - Functional Examples" href="../../examples/cssreset/index.html">CSS Reset</a></li><li class="item"><a title="YUI Fonts - Functional Examples" href="../../examples/cssfonts/index.html">CSS Fonts</a></li><li class="item"><a title="YUI Base - Functional Examples" href="../../examples/cssbase/index.html">CSS Base</a></li><li class="sect">YUI 3 Developer Tools - Examples</li><li class="item"><a title="Console - Functional Examples" href="../../examples/console/index.html">Console</a></li><li class="item"><a title="Profiler - Functional Examples" href="../../examples/profiler/index.html">Profiler</a></li><li class="item"><a title="Test - Functional Examples" href="../../examples/test/index.html">Test</a></li><li class="sect">The YUI Community</li><li class="item"><a title="The Yahoo! User Interface Blog" href="http://yuiblog.com">YUI Blog (external)</a></li><li class="item"><a title="The Yahoo! Group YDN-JavaScript hosts the YUI community forum" href="http://tech.groups.yahoo.com/group/ydn-javascript/">YUI Forum (external)</a></li><li class="item"><a title="The Yahoo! Group yui3 is dedicated to the 3.x branch of the Yahoo! User Interface (YUI) Library." href="http://tech.groups.yahoo.com/group/yui3/">YUI 3 Forum (external)</a></li><li class="item"><a title="YUI is used by Yahoo! and by hundreds of other sites, including many you know and love." href="/yui/poweredby/">YUI Sightings (external)</a></li><li class="item"><a title="Videos and podcasts from the YUI Team and from the Yahoo! frontend engineering community." href="http://developer.yahoo.com/yui/theater/">YUI Theater (external)</a></li><li class="sect">YUI Articles on the YUI Website</li><li class="item"><a title="Answers to Frequently Asked Questions about the YUI Library" href="http://developer.yahoo.com/yui/articles/faq/">YUI FAQ (external)</a></li><li class="item"><a title="Yahoo!'s philosophy of Graded Browser Support" href="http://developer.yahoo.com/yui/articles/gbs/">Graded Browser Support (external)</a></li><li class="item"><a title="Reporting Bugs and Making Feature Requests for YUI Components" href="http://developer.yahoo.com/yui/articles/reportingbugs/">Bug Reports/Feature Requests (external)</a></li><li class="item"><a title="Serve YUI source files from Yahoo! -- free, fast, and simple" href="http://developer.yahoo.com/yui/3/articles/hosting/">Serving YUI Files from Yahoo! (external)</a></li></ul>
       
  1057 </div>
       
  1058 </div>
       
  1059 	</div><!--closes bd-->
       
  1060 
       
  1061 	<div id="ft">
       
  1062         <p class="first">Copyright &copy; 2009 Yahoo! Inc. All rights reserved.</p>
       
  1063         <p><a href="http://privacy.yahoo.com/privacy/us/devel/index.html">Privacy Policy</a> - 
       
  1064             <a href="http://docs.yahoo.com/info/terms/">Terms of Service</a> - 
       
  1065             <a href="http://docs.yahoo.com/info/copyright/copyright.html">Copyright Policy</a> - 
       
  1066             <a href="http://careers.yahoo.com/">Job Openings</a></p>
       
  1067 	</div>
       
  1068 </div>
       
  1069 <script src="../../assets/dpSyntaxHighlighter.js"></script>
       
  1070 <script language="javascript"> 
       
  1071 dp.SyntaxHighlighter.HighlightAll('code'); 
       
  1072 </script>
       
  1073 </body>
       
  1074 </html>