| /* |
| Copyright (c) 2007, Caridy Patiño. All rights reserved. |
| Portions Copyright (c) 2007, Yahoo!, Inc. All rights reserved. |
| Code licensed under the BSD License: |
| http://www.bubbling-library.com/eng/licence |
| version: 1.5.0 |
| */ |
| YAHOO.namespace("plugin","behavior"); |
| (function() { |
| var $Y = YAHOO.util, |
| $E = YAHOO.util.Event, |
| $D = YAHOO.util.Dom, |
| $L = YAHOO.lang, |
| $ = YAHOO.util.Dom.get; |
| |
| /** |
| * @class Bubbling |
| */ |
| YAHOO.Bubbling = function () { |
| var obj = {}, |
| ua = navigator.userAgent.toLowerCase(), |
| isOpera = (ua.indexOf('opera') > -1); |
| // private stuff |
| var navRelExternal = function (layer, args) { |
| var el = args[1].anchor; |
| if (!(args[1].flagged || args[1].decrepitate) && el) { |
| var r = el.getAttribute("rel"), |
| t = el.getAttribute("target"); |
| if ((!t || (t === '')) && (r == 'external')) { |
| el.setAttribute("target", "blank"); |
| } |
| } |
| }; |
| var defaultActionsControl = function (layer, args) { |
| obj.processingAction (layer, args, obj.defaultActions); |
| }; |
| var _searchYUIButton = function (t) { |
| var el = obj.getOwnerByClassName( t, 'yui-button' ), bt = null, id = null; |
| if ($L.isObject(el) && YAHOO.widget.Button) { |
| bt = YAHOO.widget.Button.getButton(el.id); |
| } |
| return bt; |
| }; |
| |
| // public vars |
| obj.ready = false; |
| obj.force2alfa = false; |
| obj.bubble = {}; // CustomEvent Handles |
| obj.onReady = new $Y.CustomEvent('bubblingOnReady', obj, true); |
| |
| // mapping external methods... |
| obj.getOwnerByClassName = function(node, className) { |
| return ($D.hasClass(node, className)?node:$D.getAncestorByClassName (node, className)); |
| }; |
| obj.getOwnerByTagName = function(node, tagName) { |
| node = $D.get(node); |
| if (!node) { |
| return null; |
| } |
| return (node.tagName && node.tagName.toUpperCase() == tagName.toUpperCase()?node:$D.getAncestorByTagName (node, tagName)); |
| }; |
| // Deprecated in favor of getOwnerByClassName and getOwnerByTagName |
| obj.getAncestorByClassName = obj.getOwnerByClassName; |
| obj.getAncestorByTagName = obj.getOwnerByTagName; |
| |
| // public methods |
| obj.onKeyPressedTrigger = function(args, e, m){ |
| var b = 'key'; |
| e = e || $E.getEvent(); |
| m = m || {}; |
| m.action = b; |
| m.target = args.target || (e?$E.getTarget(e):null); |
| m.flagged = false; m.decrepitate = false; |
| m.event = e; |
| m.stop = false; |
| m.type = args.type; |
| m.keyCode = args.keyCode; |
| m.charCode = args.charCode; |
| m.ctrlKey = args.ctrlKey; |
| m.shiftKey = args.shiftKey; |
| m.altKey = args.altKey; |
| this.bubble.key.fire(e, m); |
| if (m.stop) { |
| $E.stopEvent(e); |
| } |
| return m.stop; |
| }; |
| obj.onEventTrigger = function(b, e, m){ |
| e = e || $E.getEvent(); |
| m = m || {}; |
| m.action = b; |
| m.target = (e?$E.getTarget(e):null); |
| m.flagged = false; m.decrepitate = false; |
| m.event = e; |
| m.stop = false; |
| this.bubble[b].fire(e, m); |
| if (m.stop) { |
| $E.stopEvent(e); |
| } |
| return m.stop; |
| }; |
| obj.onNavigate = function(e){ |
| var conf = { |
| anchor: this.getOwnerByTagName( $E.getTarget(e), 'A' ), |
| button: _searchYUIButton($E.getTarget(e)) |
| }; |
| if (!conf.anchor && !conf.button) { |
| conf.input = this.getOwnerByTagName( $E.getTarget(e), 'INPUT' ); |
| } |
| if (conf.button) { |
| conf.value = conf.button.get('value'); |
| } else if (conf.input) { |
| conf.value = conf.input.getAttribute('value'); |
| } |
| if (!this.onEventTrigger ('navigate', e, conf)) { |
| this.onEventTrigger ('god', e, conf); // if nobody claim the event, god can handle it... |
| } |
| }; |
| obj.onProperty = function(e){ |
| this.onEventTrigger ('property', e, { |
| anchor: this.getOwnerByTagName( $E.getTarget(e), 'A' ), |
| button: _searchYUIButton($E.getTarget(e)) |
| }); |
| }; |
| obj._timeoutId = 0; |
| obj.onRepaint = function(e){ |
| // Downshift Your Code (cant let something happen multiple times in a second) |
| // http://yuiblog.com/blog/2007/07/09/downshift-your-code/ |
| clearTimeout(obj._timeoutId); |
| obj._timeoutId = setTimeout(function(){ |
| var b = 'repaint', |
| e = {target:document.body}, |
| m = { |
| action: b, |
| target: null, |
| event: e, |
| flagged: false, |
| decrepitate: false, |
| stop: false |
| }; |
| obj.bubble[b].fire(e, m); |
| if (m.stop) { |
| $E.stopEvent(e); |
| } |
| }, 150 |
| ); |
| }; |
| obj.onRollOver = function(e){ |
| this.onEventTrigger ('rollover', e, { |
| anchor: this.getOwnerByTagName( $E.getTarget(e), 'A' ) |
| }); |
| }; |
| obj.onRollOut = function(e){ |
| this.onEventTrigger ('rollout', e, { |
| anchor: this.getOwnerByTagName( $E.getTarget(e), 'A' ) |
| }); |
| }; |
| obj.onKeyPressed = function(args){ |
| this.onKeyPressedTrigger(args); |
| }; |
| /** |
| * * Este método determina la acción por defecto para un elemento |
| * @public |
| * @param {object} el element reference |
| * @param {object} actions object with the list of posibles actions |
| * @return void |
| */ |
| obj.getActionName = function (el, depot) { |
| depot = depot || {}; |
| var b = null, r = null, |
| f = ($D.inDocument(el)?function(b){return $D.hasClass(el, b)}:function(b){return el.hasClass(b);}); // f: check is certain object has a classname |
| if (el && ($L.isObject(el) || (el = $( el )))) { |
| try{ |
| r = el.getAttribute("rel"); // if rel is available... |
| }catch(e){}; |
| for (b in depot) { // behaviors in the depot... |
| if ((depot.hasOwnProperty(b)) && (f(b) || (b === r))) { |
| return b; |
| } |
| } |
| } |
| return null; |
| }; |
| /** |
| * * Este método determina el primer tab hijo basado en el tabName |
| * @public |
| * @param {object} el Child element reference |
| * @param {object} c ClassName of the Ancestor |
| * @return void |
| */ |
| obj.getFirstChildByTagName = function (el, t) { |
| if (el && ($L.isObject(el) || (el = $( el ))) && t) { |
| var l = el.getElementsByTagName(t); |
| if (l.length > 0) { |
| return l[0]; |
| } |
| } |
| return null; |
| }; |
| /** |
| * * Este método determina si un evento es interno o no a un contenedor... |
| * @public |
| * @param {object} e Referencia al evento |
| * @param {object} el Referencia al contendor |
| * @return void |
| */ |
| obj.virtualTarget = function (e, el) { |
| if (el && ($L.isObject(el) || (el = $( el ))) && $L.isObject(e)) { |
| var t = $E.getRelatedTarget ( e ); // target element |
| if ($L.isObject(t)) { |
| while((t.parentNode) && $L.isObject(t.parentNode) && (t.parentNode.tagName !== "BODY")) { |
| if (t.parentNode === el) { |
| return true; |
| } |
| t = t.parentNode; |
| } |
| } |
| } |
| return false; |
| }; |
| |
| /** |
| * * Creating a new behaviors layer... |
| * @public |
| * @param {string||array} layers Behaviors layers GUID |
| * @param {object} scope Custom Event default execution scope |
| * @return boolean if not exists... |
| */ |
| obj.addLayer = function (layers, scope) { |
| var result = false; |
| layers = ($L.isArray(layers)?layers:[layers]); |
| scope = scope || window; |
| for (var i = 0; i < layers.length; ++i) { |
| if (layers[i] && !this.bubble.hasOwnProperty(layers[i])) { |
| this.bubble[layers[i]] = new $Y.CustomEvent(layers[i], scope, true); |
| result = true; |
| } |
| } |
| return result; |
| }; |
| /** |
| * * Subcribing an bahavior to certain bahaviors layer... |
| * @public |
| * @param {string} layer Behavior layer GUID |
| * @param {object} bh The function that represent the behavior |
| * @return boolean if it is the first listener |
| */ |
| obj.subscribe = function (layer, bh, scope) { |
| var first = this.addLayer(layer); // return true if it's the first listener |
| if (layer) { |
| if ($L.isObject(scope)) { |
| this.bubble[layer].subscribe(bh, scope, true); // correcting the default scope |
| } else { |
| this.bubble[layer].subscribe(bh); // use the default scope |
| } |
| } |
| return first; |
| }; |
| obj.on = obj.subscribe; // defining an alias... |
| /** |
| * * Broadcasting the message in the corresponding behavior layer... |
| * @public |
| * @param {string} layer Behavior layer GUID |
| * @param {object} obj The function that represent the behavior |
| * @return boolean if someone has claim the event |
| */ |
| obj.fire = function (layer, obj) { |
| obj = obj || {}; |
| obj.action = layer; |
| obj.flagged = false; obj.decrepitate = false; |
| obj.stop = false; |
| if (this.bubble.hasOwnProperty(layer)) { |
| this.bubble[layer].fire(null, obj); |
| } |
| return obj.stop; |
| }; |
| /** |
| * * Processing an action based on the classname of the target element... |
| * @public |
| * @param {string} layer Behavior layer GUID |
| * @param {object} args Event object (extended) |
| * @param {object} actions List of availables behaviors... |
| * @param {boolean} force Proccess the actions without worry about the flagged value... |
| * @return void |
| */ |
| obj.processingAction = function (layer, args, actions, force) { |
| var behavior = null, t; |
| if (!(args[1].flagged || args[1].decrepitate) || force) { |
| // checking for anchor, input or button |
| t = args[1].anchor || args[1].input || args[1].button; |
| if (t) { |
| behavior = this.getActionName ( t, actions ); |
| args[1].el = t; |
| } |
| if (behavior && (actions[behavior].apply(args[1], [layer, args]))) { |
| $E.stopEvent(args[0]); |
| args[1].flagged = true; |
| args[1].decrepitate = true; |
| args[1].stop = true; |
| } |
| } |
| }; |
| obj.defaultActions = {}; |
| obj.addDefaultAction = function (n, f, force) { |
| if (n && f && (!this.defaultActions.hasOwnProperty(n) || force)) { |
| this.defaultActions[n] = f; |
| } |
| }; |
| |
| // default behaviors |
| $E.addListener(window, "resize", obj.onRepaint, obj, true); |
| |
| // default Suscriptions |
| obj.on('navigate', navRelExternal); |
| obj.on('navigate', defaultActionsControl); |
| |
| // initialization of the font and scroll monitors |
| obj.initMonitors = function ( config ) { |
| var fMonitors = function () { |
| var oMonitors = new YAHOO.widget.Module('yui-cms-font-monitor', { |
| monitorresize:true, |
| visible:false |
| }); |
| oMonitors.render(document.body); |
| // monitoring font-size... |
| YAHOO.widget.Module.textResizeEvent.subscribe(obj.onRepaint, obj, true); |
| // monitoring scroll actions... |
| YAHOO.widget.Overlay.windowScrollEvent.subscribe(obj.onRepaint, obj, true); |
| }; |
| if ($L.isFunction(YAHOO.widget.Module)) { |
| $E.onDOMReady (fMonitors, obj, true); |
| } |
| }; |
| // initialization inside the selfconstructor |
| obj.init = function () { |
| if (!this.ready) { |
| var el = document.body; |
| $E.addListener(el, |
| "click", |
| obj.onNavigate, |
| obj, |
| true |
| ); |
| /* |
| Listen for the "mousedown" event in Opera b/c it does not |
| support the "contextmenu" event |
| */ |
| $E.addListener( |
| el, |
| (isOpera ? "mousedown" : "contextmenu"), |
| obj.onProperty, |
| obj, |
| true |
| ); |
| /* |
| Assign a "click" event handler to the trigger element(s) for |
| Opera to prevent default browser behaviors. |
| */ |
| if(isOpera) { |
| $E.addListener( |
| el, |
| "click", |
| obj.onProperty, |
| obj, |
| true |
| ); |
| } |
| $E.addListener(el, "mouseover", obj.onRollOver, obj, true); |
| $E.addListener(el, "mouseout", obj.onRollOut, obj, true); |
| |
| // keys... |
| $E.addListener(document, "keyup", obj.onKeyPressed, obj, true); |
| $E.addListener(document, "keydown", obj.onKeyPressed, obj, true); |
| |
| this.ready = true; |
| obj.onReady.fire(); |
| } |
| }; |
| $E.onDOMReady(obj.init, obj, true); |
| |
| // creating the default layers... |
| obj.addLayer (['navigate','god','property','key','repaint','rollover', 'rollout']); // god layer - hack: the layer after the common navigate layer... |
| |
| return obj; |
| }(); |
| })(); |
| YAHOO.register("bubbling", YAHOO.Bubbling, {version: "1.5.0", build: "222"}); |