src/cm/media/js/lib/yui/yui3.0.0/examples/widget/widget-tooltip_clean.html
changeset 0 40c8f766c9b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui3.0.0/examples/widget/widget-tooltip_clean.html	Mon Nov 23 15:14:29 2009 +0100
@@ -0,0 +1,574 @@
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>Creating a simple Tooltip widget</title>
+
+<style type="text/css">
+/*margin and padding on body element
+  can introduce errors in determining
+  element position and are not recommended;
+  we turn them off as a foundation for YUI
+  CSS treatments. */
+body {
+	margin:0;
+	padding:0;
+}
+</style>
+
+<link type="text/css" rel="stylesheet" href="../../build/cssfonts/fonts-min.css" />
+<script type="text/javascript" src="../../build/yui/yui-min.js"></script>
+
+
+<!--begin custom header content for this example-->
+<style type="text/css">
+    .yui-tooltip {
+        position:absolute;
+    }
+
+    .yui-tooltip-content {
+        color: #000;
+        padding: 2px 5px;
+        border-color: #D4C237 #A6982B #A6982B #A6982B;
+        border-width: 1px;
+        border-style: solid;
+        background-color: #FFEE69;
+    }
+
+    .yui-tooltip-hidden {
+        visibility:hidden;
+    }
+
+    div.yui-hastooltip {
+        border:1px solid #243356;
+        background-color:#406ED9;
+        color:#ffffff;
+        width:25em;
+        margin:20px 0px;
+        padding:5px;
+        cursor:default;
+    }
+
+    div.yui-hastooltip span {
+        font-style:italic;
+        font-weight:bold;
+        color:#ABCEFF;
+    }
+
+    .yui-tooltip-content strong {
+        font-weight:bold;
+    }
+</style>
+
+<!--end custom header content for this example-->
+
+</head>
+
+<body class=" yui-skin-sam">
+
+<h1>Creating a simple Tooltip widget</h1>
+
+<div class="exampleIntro">
+	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>.			
+</div>
+
+<!--BEGIN SOURCE CODE FOR EXAMPLE =============================== -->
+
+<div id="delegate">
+    <div class="yui-hastooltip" title="Tooltip 1" id="tt1">Tooltip One <span>(content from title)</span></div>
+    <div class="yui-hastooltip" title="Tooltip 2" id="tt2">Tooltip Two <span>(content set in event listener)</span></div>
+    <div class="yui-hastooltip" title="Tooltip 3" id="tt3">Tooltip Three <span>(content from lookup)</span></div>
+    <div class="yui-hastooltip" title="Tooltip 4" id="tt4">Tooltip Four <span>(content from title)</span></div>
+    <label><input type="checkbox" id="prevent" /> Prevent Tooltip Four</label>
+</div>
+
+<script type="text/javascript">
+YUI({base:"../../build/", timeout: 10000}).use("widget", "widget-position", "widget-stack", function(Y) {
+    var Lang = Y.Lang,
+        Node = Y.Node;
+
+    /* Tooltip constructor */
+    function Tooltip(config) {
+        Tooltip.superclass.constructor.apply(this, arguments);
+    }
+
+    /* 
+       Required NAME static field, used to identify the Widget class and 
+       used as an event prefix, to generate class names etc. (set to the 
+       class name in camel case). 
+    */
+    Tooltip.NAME = "tooltip";
+
+    /* Static constants */
+    Tooltip.OFFSET_X = 15;
+    Tooltip.OFFSET_Y = 15;
+    Tooltip.OFFSCREEN_X = -10000;
+    Tooltip.OFFSCREEN_Y = -10000;
+
+    /* Default Tooltip Attributes */
+    Tooltip.ATTRS = {
+
+        /* 
+         * The tooltip content. This can either be a fixed content value, 
+         * or a map of id-to-values, designed to be used when a single
+         * tooltip is mapped to multiple trigger elements.
+         */
+        content : {
+            value: null
+        },
+
+        /* 
+         * The set of nodes to bind to the tooltip instance. Can be a string, 
+         * or a node instance.
+         */
+        triggerNodes : {
+            value: null,
+            setter: function(val) {
+                if (val && Lang.isString(val)) {
+                    val = Node.all(val);
+                }
+                return val;
+            }
+        },
+
+        /*
+         * The delegate node to which event listeners should be attached.
+         * This node should be an ancestor of all trigger nodes bound
+         * to the instance. By default the document is used.
+         */
+        delegate : {
+            value: null,
+            setter: function(val) {
+                return Y.one(val) || Y.one("document");
+            }
+        },
+
+        /*
+         * The time to wait, after the mouse enters the trigger node,
+         * to display the tooltip
+         */
+        showDelay : {
+            value:250
+        },
+
+        /*
+         * The time to wait, after the mouse leaves the trigger node,
+         * to hide the tooltip
+         */
+        hideDelay : {
+            value:10
+        },
+
+        /*
+         * The time to wait, after the tooltip is first displayed for 
+         * a trigger node, to hide it, if the mouse has not left the 
+         * trigger node
+         */
+        autoHideDelay : {
+            value:2000
+        },
+
+        /*
+         * Override the default visibility set by the widget base class
+         */
+        visible : {
+            value:false
+        },
+
+        /*
+         * Override the default XY value set by the widget base class,
+         * to position the tooltip offscreen
+         */
+        xy: {
+            value:[Tooltip.OFFSCREEN_X, Tooltip.OFFSCREEN_Y]
+        }
+    };
+
+    /* Extend the base Widget class */
+    Y.extend(Tooltip, Y.Widget, {
+
+        /*
+         * Initialization Code: Sets up privately used state
+         * properties, and publishes the events Tooltip introduces
+         */
+        initializer : function(config) {
+
+            this._triggerClassName = this.getClassName("trigger");
+
+            // Currently bound trigger node information
+            this._currTrigger = {
+                node: null,
+                title: null,
+                mouseX: Tooltip.OFFSCREEN_X,
+                mouseY: Tooltip.OFFSCREEN_Y
+            };
+
+            // Event handles - mouse over is set on the delegate
+            // element, mousemove and mouseout are set on the trigger node
+            this._eventHandles = {
+                delegate: null,
+                trigger: {
+                    mouseMove : null,
+                    mouseOut: null
+                }
+            };
+
+            // Show/hide timers
+            this._timers = {
+                show: null,
+                hide: null
+            };
+
+            // Publish events introduced by Tooltip. Note the triggerEnter event is preventable,
+            // with the default behavior defined in the _defTriggerEnterFn method 
+            this.publish("triggerEnter", {defaultFn: this._defTriggerEnterFn, preventable:true});
+            this.publish("triggerLeave", {preventable:false});
+        },
+
+        /*
+         * Destruction Code: Clears event handles, timers,
+         * and current trigger information
+         */
+        destructor : function() {
+            this._clearCurrentTrigger();
+            this._clearTimers();
+            this._clearHandles();
+        },
+
+        /*
+         * bindUI is used to bind attribute change and dom event
+         * listeners
+         */
+        bindUI : function() {
+            this.after("delegateChange", this._afterSetDelegate);
+            this.after("nodesChange", this._afterSetNodes);
+
+            this._bindDelegate();
+        },
+
+        /*
+         * syncUI is used to update the rendered DOM, based on the current
+         * Tooltip state
+         */
+        syncUI : function() {
+            this._uiSetNodes(this.get("triggerNodes"));
+        },
+
+        /*
+         * Public method, which can be used by triggerEvent event listeners
+         * to set the content of the tooltip for the current trigger node
+         */
+        setTriggerContent : function(content) {
+            var contentBox = this.get("contentBox");
+            contentBox.set("innerHTML", "");
+
+            if (content) {
+                if (content instanceof Node) {
+                    for (var i = 0, l = content.size(); i < l; ++i) {
+                        contentBox.appendChild(content.item(i));
+                    }
+                } else if (Lang.isString(content)) {
+                    contentBox.set("innerHTML", content);
+                }
+            }
+        },
+
+        /*
+         * Gets the closest ancestor of the given node,
+         * which is a tooltip trigger node
+         */
+        getParentTrigger : function(node) {
+            var cn = this._triggerClassName;
+            return (node.hasClass(cn)) ? node : node.ancestor(function(node) {return node.hasClass(cn)});
+        },
+
+        /*
+         * Default attribute change listener for 
+         * the triggerNodes attribute
+         */
+        _afterSetNodes : function(e) {
+            this._uiSetNodes(e.newVal);
+        },
+
+        /*
+         * Default attribute change listener for 
+         * the delegate attribute
+         */
+        _afterSetDelegate : function(e) {
+            this._bindDelegate(e.newVal);
+        },
+
+        /*
+         * Updates the rendered DOM to reflect the
+         * set of trigger nodes passed in
+         */
+        _uiSetNodes : function(nodes) {
+            if (this._triggerNodes) {
+                this._triggerNodes.removeClass(this._triggerClassName);
+            }
+
+            if (nodes) {
+                this._triggerNodes = nodes;
+                this._triggerNodes.addClass(this._triggerClassName);
+            }
+        },
+
+        /*
+         * Attaches the default mouseover DOM listener to the 
+         * current delegate node
+         */
+        _bindDelegate : function() {
+            var eventHandles = this._eventHandles;
+
+            if (eventHandles.delegate) {
+                eventHandles.delegate.detach();
+                eventHandles.delegate = null;
+            }
+            eventHandles.delegate = Y.on("mouseover", Y.bind(this._onDelegateMouseOver, this), this.get("delegate"));
+        },
+
+        /*
+         * Default mouse over DOM event listener.
+         * 
+         * Delegates to the _enterTrigger method,
+         * if the mouseover enters a trigger node.
+         */
+        _onDelegateMouseOver : function(e) {
+            var node = this.getParentTrigger(e.target);
+            if (node && (!this._currTrigger.node || !node.compareTo(this._currTrigger.node))) {
+                this._enterTrigger(node, e.pageX, e.pageY);
+            }
+        },
+
+        /*
+         * Default mouse out DOM event listener
+         * 
+         * Delegates to _leaveTrigger if the mouseout
+         * leaves the current trigger node
+         */
+        _onNodeMouseOut : function(e) {
+            var to = e.relatedTarget;
+            var trigger = e.currentTarget;
+
+            if (!trigger.contains(to)) {
+                this._leaveTrigger(trigger);
+            }
+        },
+
+        /*
+         * Default mouse move DOM event listener
+         */
+        _onNodeMouseMove : function(e) {
+            this._overTrigger(e.pageX, e.pageY);
+        },
+
+        /*
+         * Default handler invoked when the mouse enters
+         * a trigger node. Fires the triggerEnter
+         * event which can be prevented by listeners to 
+         * show the tooltip from being displayed.
+         */
+        _enterTrigger : function(node, x, y) {
+            this._setCurrentTrigger(node, x, y);
+            this.fire("triggerEnter", {node:node, pageX:x, pageY:y});
+        },
+
+        /*
+         * Default handler for the triggerEvent event,
+         * which will setup the timer to display the tooltip,
+         * if the default handler has not been prevented.
+         */
+        _defTriggerEnterFn : function(e) {
+            var node = e.node;
+            if (!this.get("disabled")) {
+                this._clearTimers();
+                var delay = (this.get("visible")) ? 0 : this.get("showDelay");
+                this._timers.show = Y.later(delay, this, this._showTooltip, [node]);
+            }
+        },
+
+        /*
+         * Default handler invoked when the mouse leaves
+         * the current trigger node. Fires the triggerLeave
+         * event and sets up the hide timer
+         */
+        _leaveTrigger : function(node) {
+            this.fire("triggerLeave");
+
+            this._clearCurrentTrigger();
+            this._clearTimers();
+
+            this._timers.hide = Y.later(this.get("hideDelay"), this, this._hideTooltip);
+        },
+
+        /*
+         * Default handler invoked for mousemove events
+         * on the trigger node. Stores the current mouse 
+         * x, y positions
+         */
+        _overTrigger : function(x, y) {
+            this._currTrigger.mouseX = x;
+            this._currTrigger.mouseY = y;
+        },
+
+        /*
+         * Shows the tooltip, after moving it to the current mouse
+         * position.
+         */
+        _showTooltip : function(node) {
+            var x = this._currTrigger.mouseX;
+            var y = this._currTrigger.mouseY;
+
+            this.move(x + Tooltip.OFFSET_X, y + Tooltip.OFFSET_Y);
+
+            this.show();
+            this._clearTimers();
+
+            this._timers.hide = Y.later(this.get("autoHideDelay"), this, this._hideTooltip);
+        },
+
+        /*
+         * Hides the tooltip, after clearing existing timers.
+         */
+        _hideTooltip : function() {
+            this._clearTimers();
+            this.hide();
+        },
+
+        /*
+         * Set the rendered content of the tooltip for the current
+         * trigger, based on (in order of precedence):
+         * 
+         * a). The string/node content attribute value
+         * b). From the content lookup map if it is set, or 
+         * c). From the title attribute if set.
+         */
+        _setTriggerContent : function(node) {
+            var content = this.get("content");
+            if (content && !(content instanceof Node || Lang.isString(content))) {
+                content = content[node.get("id")] || node.getAttribute("title");
+            }
+            this.setTriggerContent(content);
+        },
+
+        /*
+         * Set the currently bound trigger node information, clearing 
+         * out the title attribute if set and setting up mousemove/out 
+         * listeners.
+         */
+        _setCurrentTrigger : function(node, x, y) {
+
+            var currTrigger = this._currTrigger,
+                triggerHandles = this._eventHandles.trigger;
+
+            this._setTriggerContent(node);
+
+            triggerHandles.mouseMove = Y.on("mousemove", Y.bind(this._onNodeMouseMove, this), node);
+            triggerHandles.mouseOut = Y.on("mouseout", Y.bind(this._onNodeMouseOut, this), node);
+
+            var title = node.getAttribute("title");
+            node.setAttribute("title", "");
+
+            currTrigger.mouseX = x;
+            currTrigger.mouseY = y;
+            currTrigger.node = node;
+            currTrigger.title = title;
+        },
+
+        /*
+         * Clear out the current trigger state, restoring
+         * the title attribute on the trigger node, 
+         * if it was originally set.
+         */
+        _clearCurrentTrigger : function() {
+
+            var currTrigger = this._currTrigger,
+                triggerHandles = this._eventHandles.trigger;
+
+            if (currTrigger.node) {
+                var node = currTrigger.node;
+                var title = currTrigger.title || "";
+
+                currTrigger.node = null;
+                currTrigger.title = "";
+
+                triggerHandles.mouseMove.detach();
+                triggerHandles.mouseOut.detach();
+                triggerHandles.mouseMove = null;
+                triggerHandles.mouseOut = null;
+
+                node.setAttribute("title", title);
+            }
+        },
+
+        /*
+         * Cancel any existing show/hide timers
+         */
+        _clearTimers : function() {
+            var timers = this._timers;
+            if (timers.hide) {
+                timers.hide.cancel();
+                timers.hide = null;
+            }
+            if (timers.show) {
+              timers.show.cancel();
+              timers.show = null;
+            }
+        },
+
+        /*
+         * Detach any stored event handles
+         */
+        _clearHandles : function() {
+            var eventHandles = this._eventHandles;
+
+            if (eventHandles.delegate) {
+                this._eventHandles.delegate.detach();
+            }
+            if (eventHandles.trigger.mouseOut) {
+                eventHandles.trigger.mouseOut.detach();
+            }
+            if (eventHandles.trigger.mouseMove) {
+                eventHandles.trigger.mouseMove.detach();
+            }
+        }
+    });
+
+    // dynamic:false = Modify the existing Tooltip class
+    Tooltip = Y.Base.build(Tooltip.NAME, Tooltip, [Y.WidgetPosition, Y.WidgetStack], {dynamic:false});
+
+    var tt = new Tooltip({
+        triggerNodes:".yui-hastooltip",
+        delegate: "#delegate",
+        content: {
+            tt3: "Tooltip 3 (from lookup)"
+        },
+        shim:false,
+        zIndex:2
+    });
+    tt.render();
+
+    tt.on("triggerEnter", function(e) {
+        var node = e.node;
+        if (node && node.get("id") == "tt2") {
+            this.setTriggerContent("Tooltip 2 (from triggerEvent)");
+        }
+    });
+
+    var prevent = Y.one("#prevent");
+    tt.on("triggerEnter", function(e) {
+        var node = e.node;
+        if (prevent.get("checked")) {
+            if (node && node.get("id") == "tt4") {
+                e.preventDefault();
+            }
+        }
+    });
+});
+</script>
+
+<!--END SOURCE CODE FOR EXAMPLE =============================== -->
+
+</body>
+</html>