dojox
Version:
Dojo eXtensions, a rollup of many useful sub-projects and varying states of maturity – from very stable and robust, to alpha and experimental. See individual projects contain README files for details.
188 lines (175 loc) • 6.5 kB
JavaScript
dojo.provide("dojox.rails.tests.plugd.trigger");
(function(d){
var isfn = d.isFunction,
leaveRe = /mouse(enter|leave)/,
_fix = function(_, p){
return "mouse" + (p == "enter" ? "over" : "out");
},
mix = d._mixin,
// the guts of the node triggering logic:
// the function accepts node (not string|node), "on"-less event name,
// and an object of args to mix into the event.
realTrigger = d.doc.createEvent ?
function(n, e, a){
// the sane branch
var ev = d.doc.createEvent("HTMLEvents");
e = e.replace(leaveRe, _fix);
ev.initEvent(e, true, true);
a && mix(ev, a);
n.dispatchEvent(ev);
} :
function(n, e, a){
// the janktastic branch
var ev = "on" + e, stop = false, lc = e.toLowerCase(), node = n;
try{
// FIXME: is this worth it? for mixed-case native event support:? Opera ends up in the
// createEvent path above, and also fails on _some_ native-named events.
// if(lc !== e && d.indexOf(d.NodeList.events, lc) >= 0){
// // if the event is one of those listed in our NodeList list
// // in lowercase form but is mixed case, throw to avoid
// // fireEvent. /me sighs. http://gist.github.com/315318
// throw("janktastic");
// }
n.fireEvent(ev);
}catch(er){
console.warn("in catch", er);
// a lame duck to work with. we're probably a 'custom event'
var evdata = mix({
type: e, target: n, faux: true,
// HACK: [needs] added support for customStopper to _base/event.js
// some tests will fail until del._stopPropagation has support.
_stopper: function(){ stop = this.cancelBubble; }
}, a);
isfn(n[ev]) && n[ev](evdata);
// handle bubbling of custom events, unless the event was stopped.
while(!stop && n !== d.doc && n.parentNode){
n = n.parentNode;
isfn(n[ev]) && n[ev](evdata);
}
}
}
;
d._trigger = function(/* DomNode|String */node, /* String */event, extraArgs){
// summary:
// Helper for `dojo.trigger`, which handles the DOM cases. We should never
// be here without a domNode reference and a string eventname.
var n = d.byId(node), ev = event && event.slice(0, 2) == "on" ? event.slice(2) : event;
realTrigger(n, ev, extraArgs);
};
d.trigger = function(obj, event, extraArgs){
// summary:
// Trigger some event. It can be either a Dom Event, Custom Event,
// or direct function call.
//
// description:
// Trigger some event. It can be either a Dom Event, Custom Event,
// or direct function call. NOTE: This function does not trigger
// default behavior, only triggers bound event listeneres. eg:
// one cannot trigger("anchorNode", "onclick") and expect the browser
// to follow the href="" attribute naturally.
//
// obj: String|DomNode|Object|Function
// An ID, or DomNode reference, from which to trigger the event.
// If an Object, fire the `event` in the scope of this object,
// similar to calling dojo.hitch(obj, event)(). The return value
// in this case is returned from `dojo.trigger`
//
// event: String|Function
// The name of the event to trigger. Can be any DOM level 2 event
// and can be in either form: "onclick" or "click" for instance.
// In the object-firing case, this method can be a function or
// a string version of a member function, just like `dojo.hitch`.
//
// extraArgs: Object?
// An object to mix into the `event` object passed to any bound
// listeners. Be careful not to override important members, like
// `type`, or `preventDefault`. It will likely error.
//
// Additionally, extraArgs is moot in the object-triggering case,
// as all arguments beyond the `event` are curried onto the triggered
// function.
//
// example:
// | dojo.connect(node, "onclick", function(e){ /* stuff */ });
// | // later:
// | dojo.trigger(node, "onclick");
//
// example:
// | // or from within dojo.query: (requires dojo.NodeList)
// | dojo.query("a").onclick(function(){}).trigger("onclick");
//
// example:
// | // fire obj.method() in scope of obj
// | dojo.trigger(obj, "method");
//
// example:
// | // fire an anonymous function:
// | dojo.trigger(d.global, function(){ /* stuff */ });
//
// example:
// | // fire and anonymous function in the scope of obj
// | dojo.trigger(obj, function(){ this == obj; });
//
// example:
// | // with a connected function like:
// | dojo.connect(dojo.doc, "onclick", function(e){
// | if(e && e.manuallydone){
// | console.log("this was a triggered onclick, not natural");
// | }
// | });
// | // fire onclick, passing in a custom bit of info
// | dojo.trigger("someId", "onclick", { manuallydone:true });
//
// returns: Anything
// Will not return anything in the Dom event case, but will return whatever
// return value is received from the triggered event.
return (isfn(obj) || isfn(event) || isfn(obj[event])) ?
d.hitch.apply(d, arguments)() : d._trigger.apply(d, arguments);
};
// adapt for dojo.query:
/*=====
dojo.extend(dojo.NodeList, {
trigger: function(event, data){
// summary:
// Trigger some Event originating from each of the nodes in this
// `dojo.NodeList`.
//
// event: String
// Any strig identifier for the event.type to be triggered.
//
// data: Object
// Just like `extraArgs` for `dojo.trigger`, additional data
// to mix into the event object.
//
// example:
// | dojo.query("a").trigger("onclick");
return this; // dojo.NodeList
}
});
=====*/
d.NodeList.prototype.trigger = d.NodeList._adaptAsForEach(d._trigger);
// if the node.js module is available, extend trigger into that.
if(d._Node && !d._Node.prototype.trigger){
d.extend(d._Node, {
trigger: function(ev, data){
// summary:
// Fire some some event originating from this node.
// Only available if both the `dojo.trigger` and `dojo.node` plugin
// are enabled. Allows chaining as all `dojo._Node` methods do.
//
// ev: String
// Some string event name to fire. eg: "onclick", "submit"
//
// data: Object
// Just like `extraArgs` for `dojo.trigger`, additional data
// to mix into the event object.
//
// example:
// | // fire onlick orginiating from a node with id="someAnchorId"
// | dojo.node("someAnchorId").trigger("click");
d._trigger(this, ev, data);
return this; // dojo._Node
}
});
}
})(dojo);