/**
* Events abstraction for browsers that may not support it, but which we want to be suported.
*/
(function(global, scope){
/**
* Pseudo event handler to be fired after the DOM was parsed or
* on window load at last.
*
* @author based upon some code by Dean Edwards
* @author Dean Edwards
* @link http://dean.edwards.name/weblog/2006/06/again/
* @private
*/
global.fireoninit = function () {
// quit if this function has already been called
if (arguments['callee'].done) return;
// flag this function so we don't do the same thing twice
arguments['callee'].done = true;
// kill the timer
_timer && clearInterval(_timer);
_timer = null;
if (typeof global.oninit == 'function') {
global.oninit();
}
};
/***
* Run the fireoninit function as soon as possible after
* the DOM was loaded, using different methods for different
* Browsers
*
* @author Dean Edwards
* @link http://dean.edwards.name/weblog/2006/06/again/
*/
// for Mozilla
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", global.fireoninit, null);
}
// for Internet Explorer (using conditional comments)
/*@cc_on
@if (@_win32)
document.write("<scr" + "ipt id=\"__ie_init\" defer=\"true\" src=\"//:\"><\/script>");
var script = document.getElementById("__ie_init");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
global.fireoninit(); // call the onload handler
}
};
@end @*/
// for Safari
if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function () {
if (/loaded|complete/.test(document.readyState)) {
global.fireoninit(); // call the onload handler
}
}, 10);
}
// for other browsers
global.onload = global.fireoninit;
/**
* This is a pseudo Event that will be fired by the fireoninit
* function above.
*
* Use addInitEvent to bind to this event!
*
* @author Andreas Gohr <andi@splitbrain.org>
* @see fireoninit()
* @private
*/
global.oninit = function () {};
scope.Events = {
/**
* Add an event to a given object
*
* @param {Element} obj the Element object to add the event to
* @param {string} type the event name to add a handler for
* @param {function} fn the function to run when the event triggers
* @param {object} opt additional options to send along the event
*/
addEvent: function( obj, type, fn, opt, eventOpts ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){ obj['e'+type+fn]( global.event, opt ); }
if ( obj.attachEvent ) {
obj.attachEvent( 'on'+type, obj[type+fn] );
} else {
obj.addEventListener( type, opt?function(e){fn(e,opt)}:fn, eventOpts || false );
}
},
/**
* Remove an event from a given object
*
* @param {Element} obj the Element to object to remove an event from
* @param {string} type the event name to remove from the handler
* @param {function} fn the function that needs to be removed
*/
removeEvent: function( obj, type, fn, eventOpts ) {
if ( obj.detachEvent ) {
obj.detachEvent( 'on'+type, obj[type+fn] );
} else {
obj.removeEventListener( type, fn, eventOpts || false );
}
obj[type+fn] = null;
obj['e'+type+fn] = null;
},
/**
* Clear all events of a type from an element
* @param {object} element the element to clear an event type from
* @param {string} type the event type
*/
clearEvents: function (obj, type) {
Object.keys(obj).forEach(function(_type){
_type.indexOf(type) == 0 && obj.removeEvent(type, obj[_type]);
});
},
/**
* Bind a function to the global.init pseudo event
*
* @author Simon Willison
* @see http://simon.incutio.com/archive/2004/05/26/addLoadEvent
* @param {function} the function to add to the init handler
*/
addInitEvent: function( fn ) {
var oldoninit = global.oninit;
if (typeof global.oninit != 'function') {
global.oninit = fn;
} else {
global.oninit = function () {
oldoninit();
fn();
};
}
},
/**
* Fire an event on a given object
*
* @param {Element} el the element to fire an event on
* @param {string} eventName the event name to fire
* @param {object} options options to send along
*/
fireEvent: function(el, eventName, options) {
var event;
if (window.CustomEvent) {
try {
// Set cancelable and bubble options, otherwise e.g FF will not stop the event
options = options || {};
options.cancelable = true;
options.bubbles = true;
event = new CustomEvent( eventName, options);
} catch ( e ) {
// IE is really a bad person!
}
}
if ( !event ) {
event = document.createEvent('CustomEvent');
event.initCustomEvent( eventName, true, true, options);
}
return !el.dispatchEvent(event);
},
/**
* Prevent further interaction with the given event
*
* @param {Event} e the event to stop
*/
stopEvent: function( event, returnValue ) {
event = event || window.event;
if (event) {
event.cancelBubble = true;
event.returnValue = !!returnValue;
if (event.stopPropagation) {
event.stopPropagation();
}
if (event.preventDefault) {
event.preventDefault();
}
}
return !!returnValue;
}
};
var create = function(_){
var handleEvent = function( event, argument ) {
var args = [].slice.call(argument);
args.splice( 0, 0, this );
event.apply( null, args );
return this;
};
_.addEvent || ( _.addEvent = function() {
return handleEvent.call( this, scope.Events.addEvent, arguments );
});
_.removeEvent || ( _.removeEvent = function() {
return handleEvent.call( this, scope.Events.removeEvent, arguments );
});
_.clearEvents || ( _.clearEvents = function() {
return handleEvent.call( this, scope.Events.clearEvents, arguments );
});
_.fireEvent || ( _.fireEvent = function() {
return handleEvent.call( this, scope.Events.fireEvent, arguments );
});
_.addInputListener || ( _.addInputListener = function( listener ) {
return this.addEvent( 'input', listener)
.addEvent( 'change', listener)
.addEvent( 'cut', listener)
.addEvent( 'paste', listener)
.addEvent( 'drop', listener)
.addEvent( 'keydown', listener)
.addEvent( 'focus', listener);
});
};
create(Element.prototype);
create(global);
})(window, window.htmlviewer || window.$ || (window.$ = {}));