Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* This class manages the playback of an array of "event descriptors". For details on the
* contents of an "event descriptor", see {@link Ext.ux.event.Recorder}. The events recorded by the
* {@link Ext.ux.event.Recorder} class are designed to serve as input for this class.
*
* The simplest use of this class is to instantiate it with an {@link #eventQueue} and call
* {@link #method-start}. Like so:
*
* var player = Ext.create('Ext.ux.event.Player', {
* eventQueue: [ ... ],
* speed: 2, // play at 2x speed
* listeners: {
* stop: function () {
* player = null; // all done
* }
* }
* });
*
* player.start();
*
* A more complex use would be to incorporate keyframe generation after playing certain
* events.
*
* var player = Ext.create('Ext.ux.event.Player', {
* eventQueue: [ ... ],
* keyFrameEvents: {
* click: true
* },
* listeners: {
* stop: function () {
* // play has completed... probably time for another keyframe...
* player = null;
* },
* keyframe: onKeyFrame
* }
* });
*
* player.start();
*
* If a keyframe can be handled immediately (synchronously), the listener would be:
*
* function onKeyFrame () {
* handleKeyFrame();
* }
*
* If the keyframe event is always handled asynchronously, then the event listener is only
* a bit more:
*
* function onKeyFrame (p, eventDescriptor) {
* eventDescriptor.defer(); // pause event playback...
*
* handleKeyFrame(function () {
* eventDescriptor.finish(); // ...resume event playback
* });
* }
*
* Finally, if the keyframe could be either handled synchronously or asynchronously (perhaps
* differently by browser), a slightly more complex listener is required.
*
* function onKeyFrame (p, eventDescriptor) {
* var async;
*
* handleKeyFrame(function () {
* // either this callback is being called immediately by handleKeyFrame (in
* // which case async is undefined) or it is being called later (in which case
* // async will be true).
*
* if (async) {
* eventDescriptor.finish();
* } else {
* async = false;
* }
* });
*
* // either the callback was called (and async is now false) or it was not
* // called (and async remains undefined).
*
* if (async !== false) {
* eventDescriptor.defer();
* async = true; // let the callback know that we have gone async
* }
* }
*/
Ext.define('Ext.ux.event.Player', function (Player) {
var defaults = {},
mouseEvents = {},
keyEvents = {},
doc,
//HTML events supported
uiEvents = {},
//events that bubble by default
bubbleEvents = {
//scroll: 1,
resize: 1,
reset: 1,
submit: 1,
change: 1,
select: 1,
error: 1,
abort: 1
};
Ext.each([ 'click', 'dblclick', 'mouseover', 'mouseout', 'mousedown', 'mouseup', 'mousemove' ],
function (type) {
bubbleEvents[type] = defaults[type] = mouseEvents[type] = {
bubbles: true,
cancelable: (type != "mousemove"), // mousemove cannot be cancelled
detail: 1,
screenX: 0,
screenY: 0,
clientX: 0,
clientY: 0,
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false,
button: 0
};
});
Ext.each([ 'keydown', 'keyup', 'keypress' ],
function (type) {
bubbleEvents[type] = defaults[type] = keyEvents[type] = {
bubbles: true,
cancelable: true,
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false,
keyCode: 0,
charCode: 0
};
});
Ext.each([ 'blur', 'change', 'focus', 'resize', 'scroll', 'select' ],
function (type) {
defaults[type] = uiEvents[type] = {
bubbles: (type in bubbleEvents),
cancelable: false,
detail: 1
};
});
var inputSpecialKeys = {
8: function (target, start, end) { // backspace: 8,
if (start < end) {
target.value = target.value.substring(0, start) +
target.value.substring(end);
} else if (start > 0) {
target.value = target.value.substring(0, --start) +
target.value.substring(end);
}
this.setTextSelection(target, start, start);
},
46: function (target, start, end) { // delete: 46
if (start < end) {
target.value = target.value.substring(0, start) +
target.value.substring(end);
} else if (start < target.value.length - 1) {
target.value = target.value.substring(0, start) +
target.value.substring(start+1);
}
this.setTextSelection(target, start, start);
}
};
return {
extend: 'Ext.ux.event.Driver',
/**
* @cfg {Array} eventQueue The event queue to playback. This must be provided before
* the {@link #method-start} method is called.
*/
/**
* @cfg {Object} keyFrameEvents An object that describes the events that should generate
* keyframe events. For example, `{ click: true }` would generate keyframe events after
* each `click` event.
*/
keyFrameEvents: {
click: true
},
/**
* @cfg {Boolean} pauseForAnimations True to pause event playback during animations, false
* to ignore animations. Default is true.
*/
pauseForAnimations: true,
/**
* @cfg {Number} speed The playback speed multiplier. Default is 1.0 (to playback at the
* recorded speed). A value of 2 would playback at 2x speed.
*/
speed: 1.0,
stallTime: 0,
_inputSpecialKeys: {
INPUT: inputSpecialKeys,
TEXTAREA: Ext.apply({
//13: function (target, start, end) { // enter: 8,
//TODO ?
//}
}, inputSpecialKeys)
},
tagPathRegEx: /(\w+)(?:\[(\d+)\])?/,
/**
* @event beforeplay
* Fires before an event is played.
* @param {Ext.ux.event.Player} this
* @param {Object} eventDescriptor The event descriptor about to be played.
*/
/**
* @event keyframe
* Fires when this player reaches a keyframe. Typically, this is after events
* like `click` are injected and any resulting animations have been completed.
* @param {Ext.ux.event.Player} this
* @param {Object} eventDescriptor The keyframe event descriptor.
*/
constructor: function (config) {
var me = this;
me.callParent(arguments);
me.timerFn = function () {
me.onTick();
};
me.attachTo = me.attachTo || window;
doc = me.attachTo.document;
},
/**
* Returns the element given is XPath-like description.
* @param {String} xpath The XPath-like description of the element.
* @return {HTMLElement}
*/
getElementFromXPath: function (xpath) {
var me = this,
parts = xpath.split('/'),
regex = me.tagPathRegEx,
i, n, m, count, tag, child,
el = me.attachTo.document;
el = (parts[0] == '~') ? el.body
: el.getElementById(parts[0].substring(1)); // remove '#'
for (i = 1, n = parts.length; el && i < n; ++i) {
m = regex.exec(parts[i]);
count = m[2] ? parseInt(m[2], 10) : 1;
tag = m[1].toUpperCase();
for (child = el.firstChild; child; child = child.nextSibling) {
if (child.tagName == tag) {
if (count == 1) {
break;
}
--count;
}
}
el = child;
}
return el;
},
// Moving across a line break only counts as moving one character in a TextRange, whereas a line break in
// the textarea value is two characters. This function corrects for that by converting a text offset into a
// range character offset by subtracting one character for every line break in the textarea prior to the
// offset
offsetToRangeCharacterMove: function(el, offset) {
return offset - (el.value.slice(0, offset).split("\r\n").length - 1);
},
setTextSelection: function (el, startOffset, endOffset) {
// See https://code.google.com/p/rangyinputs/source/browse/trunk/rangyinputs_jquery.js
if (startOffset < 0) {
startOffset += el.value.length;
}
if (endOffset == null) {
endOffset = startOffset;
}
if (endOffset < 0) {
endOffset += el.value.length;
}
if (typeof el.selectionStart === "number") {
el.selectionStart = startOffset;
el.selectionEnd = endOffset;
} else {
var range = el.createTextRange();
var startCharMove = this.offsetToRangeCharacterMove(el, startOffset);
range.collapse(true);
if (startOffset == endOffset) {
range.move("character", startCharMove);
} else {
range.moveEnd("character", this.offsetToRangeCharacterMove(el, endOffset));
range.moveStart("character", startCharMove);
}
range.select();
}
},
getTimeIndex: function () {
var t = this.getTimestamp() - this.stallTime;
return t * this.speed;
},
makeToken: function (eventDescriptor, signal) {
var me = this,
t0;
eventDescriptor[signal] = true;
eventDescriptor.defer = function () {
eventDescriptor[signal] = false;
t0 = me.getTime();
};
eventDescriptor.finish = function () {
eventDescriptor[signal] = true;
me.stallTime += me.getTime() - t0;
me.schedule();
};
},
/**
* This method is called after an event has been played to prepare for the next event.
* @param {Object} eventDescriptor The descriptor of the event just played.
*/
nextEvent: function (eventDescriptor) {
var me = this,
index = ++me.queueIndex;
// keyframe events are inserted after a keyFrameEvent is played.
if (me.keyFrameEvents[eventDescriptor.type]) {
Ext.Array.insert(me.eventQueue, index, [
{keyframe: true, ts: eventDescriptor.ts}
]);
}
},
/**
* This method returns the event descriptor at the front of the queue. This does not
* dequeue the event. Repeated calls return the same object (until {@link #nextEvent}
* is called).
*/
peekEvent: function () {
return this.eventQueue[this.queueIndex] || null;
},
/**
* Replaces an event in the queue with an array of events. This is often used to roll
* up a multi-step pseudo-event and expand it just-in-time to be played. The process
* for doing this in a derived class would be this:
*
* Ext.define('My.Player', {
* extend: 'Ext.ux.event.Player',
*
* peekEvent: function () {
* var event = this.callParent();
*
* if (event.multiStepSpecial) {
* this.replaceEvent(null, [
* ... expand to actual events
* ]);
*
* event = this.callParent(); // get the new next event
* }
*
* return event;
* }
* });
*
* This method ensures that the `beforeplay` hook (if any) from the replaced event is
* placed on the first new event and the `afterplay` hook (if any) is placed on the
* last new event.
*
* @param {Number} index The queue index to replace. Pass `null` to replace the event
* at the current `queueIndex`.
* @param {Event[]} events The array of events with which to replace the specified
* event.
*/
replaceEvent: function (index, events) {
for (var t, i = 0, n = events.length; i < n; ++i) {
if (i) {
t = events[i-1];
delete t.afterplay;
delete t.screenshot;
delete events[i].beforeplay;
}
}
Ext.Array.replace(this.eventQueue, (index == null) ? this.queueIndex : index,
1, events);
},
/**
* This method dequeues and injects events until it has arrived at the time index. If
* no events are ready (based on the time index), this method does nothing.
* @return {Boolean} True if there is more to do; false if not (at least for now).
*/
processEvents: function () {
var me = this,
animations = me.pauseForAnimations && me.attachTo.Ext.fx.Manager.items,
eventDescriptor;
while ((eventDescriptor = me.peekEvent()) !== null) {
if (animations && animations.getCount()) {
return true;
}
if (eventDescriptor.keyframe) {
if (!me.processKeyFrame(eventDescriptor)) {
return false;
}
me.nextEvent(eventDescriptor);
} else if (eventDescriptor.ts <= me.getTimeIndex() &&
me.fireEvent('beforeplay', me, eventDescriptor) !== false &&
me.playEvent(eventDescriptor)) {
me.nextEvent(eventDescriptor);
} else {
return true;
}
}
me.stop();
return false;
},
/**
* This method is called when a keyframe is reached. This will fire the keyframe event.
* If the keyframe has been handled, true is returned. Otherwise, false is returned.
* @param {Object} eventDescriptor The event descriptor of the keyframe.
* @return {Boolean} True if the keyframe was handled, false if not.
*/
processKeyFrame: function (eventDescriptor) {
var me = this;
// only fire keyframe event (and setup the eventDescriptor) once...
if (!eventDescriptor.defer) {
me.makeToken(eventDescriptor, 'done');
me.fireEvent('keyframe', me, eventDescriptor);
}
return eventDescriptor.done;
},
/**
* Called to inject the given event on the specified target.
* @param {HTMLElement} target The target of the event.
* @param {Object} event The event to inject. The properties of this object should be
* those of standard DOM events but vary based on the `type` property. For details on
* event types and their properties, see the class documentation.
*/
injectEvent: function (target, event) {
var me = this,
type = event.type,
options = Ext.apply({}, event, defaults[type]),
handler;
if (type === 'type') {
handler = me._inputSpecialKeys[target.tagName];
if (handler) {
return me.injectTypeInputEvent(target, event, handler);
}
return me.injectTypeEvent(target, event);
}
if (type === 'focus' && target.focus) {
target.focus();
return true;
}
if (type === 'blur' && target.blur) {
target.blur();
return true;
}
if (type === 'scroll') {
target.scrollLeft = event.pos[0];
target.scrollTop = event.pos[1];
return true;
}
if (type === 'mduclick') {
return me.injectEvent(target, Ext.applyIf({ type: 'mousedown' }, event)) &&
me.injectEvent(target, Ext.applyIf({ type: 'mouseup' }, event)) &&
me.injectEvent(target, Ext.applyIf({ type: 'click' }, event));
}
if (mouseEvents[type]){
return Player.injectMouseEvent(target, options, me.attachTo);
}
if (keyEvents[type]){
return Player.injectKeyEvent(target, options, me.attachTo);
}
if (uiEvents[type]){
return Player.injectUIEvent(target, type,
options.bubbles,
options.cancelable,
options.view || me.attachTo,
options.detail);
}
return false;
},
injectTypeEvent: function (target, event) {
var me = this,
text = event.text,
xlat = [],
ch, chUp, i, n, sel, upper, isInput;
if (text) {
delete event.text;
upper = text.toUpperCase();
for (i = 0, n = text.length; i < n; ++i) {
ch = text.charCodeAt(i);
chUp = upper.charCodeAt(i);
xlat.push(
Ext.applyIf({type: 'keydown', charCode: chUp, keyCode: chUp}, event),
Ext.applyIf({type: 'keypress', charCode: ch, keyCode: ch}, event),
Ext.applyIf({type: 'keyup', charCode: chUp, keyCode: chUp}, event)
);
}
} else {
xlat.push(
Ext.applyIf({type: 'keydown', charCode: event.keyCode}, event),
Ext.applyIf({type: 'keyup', charCode: event.keyCode}, event)
);
}
for (i = 0, n = xlat.length; i < n; ++i) {
me.injectEvent(target, xlat[i]);
}
return true;
},
injectTypeInputEvent: function (target, event, handler) {
var me = this,
text = event.text,
sel, n;
if (handler) {
sel = me.getTextSelection(target);
if (text) {
n = sel[0];
target.value = target.value.substring(0, n) + text +
target.value.substring(sel[1]);
n += text.length;
me.setTextSelection(target, n, n);
} else {
if (!(handler = handler[event.keyCode])) {
// no handler for the special key for this element
if ('caret' in event) {
me.setTextSelection(target, event.caret, event.caret);
} else if (event.selection) {
me.setTextSelection(target, event.selection[0], event.selection[1]);
}
return me.injectTypeEvent(target, event);
}
handler.call(this, target, sel[0], sel[1]);
return true;
}
}
return true;
},
playEvent: function (eventDescriptor) {
var me = this,
target = me.getElementFromXPath(eventDescriptor.target),
event;
if (!target) {
// not present (yet)... wait for element present...
// TODO - need a timeout here
return false;
}
if (!me.playEventHook(eventDescriptor, 'beforeplay')) {
return false;
}
if (!eventDescriptor.injected) {
eventDescriptor.injected = true;
event = me.translateEvent(eventDescriptor, target);
me.injectEvent(target, event);
}
return me.playEventHook(eventDescriptor, 'afterplay');
},
playEventHook: function (eventDescriptor, hookName) {
var me = this,
doneName = hookName + '.done',
firedName = hookName + '.fired',
hook = eventDescriptor[hookName];
if (hook && !eventDescriptor[doneName]) {
if (!eventDescriptor[firedName]) {
eventDescriptor[firedName] = true;
me.makeToken(eventDescriptor, doneName);
if (me.eventScope && Ext.isString(hook)) {
hook = me.eventScope[hook];
}
if (hook) {
hook.call(me.eventScope || me, eventDescriptor);
}
}
return false;
}
return true;
},
schedule: function () {
var me = this;
if (!me.timer) {
me.timer = setTimeout(me.timerFn, 10);
}
},
_translateAcross: [
'type',
'button',
'charCode',
'keyCode',
'caret',
'pos',
'text',
'selection'
],
translateEvent: function (eventDescriptor, target) {
var me = this,
event = {},
modKeys = eventDescriptor.modKeys || '',
names = me._translateAcross,
i = names.length,
name, xy;
while (i--) {
name = names[i];
if (name in eventDescriptor) {
event[name] = eventDescriptor[name];
}
}
event.altKey = modKeys.indexOf('A') > 0;
event.ctrlKey = modKeys.indexOf('C') > 0;
event.metaKey = modKeys.indexOf('M') > 0;
event.shiftKey = modKeys.indexOf('S') > 0;
if (target && 'x' in eventDescriptor) {
xy = Ext.fly(target).getXY();
xy[0] += eventDescriptor.x;
xy[1] += eventDescriptor.y;
} else if ('x' in eventDescriptor) {
xy = [ eventDescriptor.x, eventDescriptor.y ];
} else if ('px' in eventDescriptor) {
xy = [ eventDescriptor.px, eventDescriptor.py ];
}
if (xy) {
event.clientX = event.screenX = xy[0];
event.clientY = event.screenY = xy[1];
}
if (eventDescriptor.key) {
event.keyCode = me.specialKeysByName[eventDescriptor.key];
}
if (eventDescriptor.type === 'wheel') {
if ('onwheel' in me.attachTo.document) {
event.wheelX = eventDescriptor.dx;
event.wheelY = eventDescriptor.dy;
} else {
event.type = 'mousewheel';
event.wheelDeltaX = -40 * eventDescriptor.dx;
event.wheelDeltaY = event.wheelDelta = -40 * eventDescriptor.dy;
}
}
return event;
},
//---------------------------------
// Driver overrides
onStart: function () {
var me = this;
me.queueIndex = 0;
me.schedule();
},
onStop: function () {
var me = this;
if (me.timer) {
clearTimeout(me.timer);
me.timer = null;
}
},
//---------------------------------
onTick: function () {
var me = this;
me.timer = null;
if (me.processEvents()) {
me.schedule();
}
},
statics: {
ieButtonCodeMap: {
0: 1,
1: 4,
2: 2
},
/*
* Injects a key event using the given event information to populate the event
* object.
*
* **Note:** `keydown` causes Safari 2.x to crash.
*
* @param {HTMLElement} target The target of the given event.
* @param {Object} options Object object containing all of the event injection
* options.
* @param {String} options.type The type of event to fire. This can be any one of
* the following: `keyup`, `keydown` and `keypress`.
* @param {Boolean} [options.bubbles=true] `tru` if the event can be bubbled up.
* DOM Level 3 specifies that all key events bubble by default.
* @param {Boolean} [options.cancelable=true] `true` if the event can be canceled
* using `preventDefault`. DOM Level 3 specifies that all key events can be
* cancelled.
* @param {Boolean} [options.ctrlKey=false] `true` if one of the CTRL keys is
* pressed while the event is firing.
* @param {Boolean} [options.altKey=false] `true` if one of the ALT keys is
* pressed while the event is firing.
* @param {Boolean} [options.shiftKey=false] `true` if one of the SHIFT keys is
* pressed while the event is firing.
* @param {Boolean} [options.metaKey=false] `true` if one of the META keys is
* pressed while the event is firing.
* @param {int} [options.keyCode=0] The code for the key that is in use.
* @param {int} [options.charCode=0] The Unicode code for the character associated
* with the key being used.
* @param {Window} [view=window] The view containing the target. This is typically
* the window object.
* @private
*/
injectKeyEvent: function (target, options, view) {
var type = options.type,
customEvent = null;
if (type === 'textevent') {
type = 'keypress';
}
view = view || window;
//check for DOM-compliant browsers first
if (doc.createEvent){
try {
customEvent = doc.createEvent("KeyEvents");
// Interesting problem: Firefox implemented a non-standard
// version of initKeyEvent() based on DOM Level 2 specs.
// Key event was removed from DOM Level 2 and re-introduced
// in DOM Level 3 with a different interface. Firefox is the
// only browser with any implementation of Key Events, so for
// now, assume it's Firefox if the above line doesn't error.
// @TODO: Decipher between Firefox's implementation and a correct one.
customEvent.initKeyEvent(type, options.bubbles, options.cancelable,
view, options.ctrlKey, options.altKey, options.shiftKey,
options.metaKey, options.keyCode, options.charCode);
} catch (ex) {
// If it got here, that means key events aren't officially supported.
// Safari/WebKit is a real problem now. WebKit 522 won't let you
// set keyCode, charCode, or other properties if you use a
// UIEvent, so we first must try to create a generic event. The
// fun part is that this will throw an error on Safari 2.x. The
// end result is that we need another try...catch statement just to
// deal with this mess.
try {
//try to create generic event - will fail in Safari 2.x
customEvent = doc.createEvent("Events");
} catch (uierror) {
//the above failed, so create a UIEvent for Safari 2.x
customEvent = doc.createEvent("UIEvents");
} finally {
customEvent.initEvent(type, options.bubbles, options.cancelable);
customEvent.view = view;
customEvent.altKey = options.altKey;
customEvent.ctrlKey = options.ctrlKey;
customEvent.shiftKey = options.shiftKey;
customEvent.metaKey = options.metaKey;
customEvent.keyCode = options.keyCode;
customEvent.charCode = options.charCode;
}
}
target.dispatchEvent(customEvent);
} else if (doc.createEventObject) { //IE
customEvent = doc.createEventObject();
customEvent.bubbles = options.bubbles;
customEvent.cancelable = options.cancelable;
customEvent.view = view;
customEvent.ctrlKey = options.ctrlKey;
customEvent.altKey = options.altKey;
customEvent.shiftKey = options.shiftKey;
customEvent.metaKey = options.metaKey;
// IE doesn't support charCode explicitly. CharCode should
// take precedence over any keyCode value for accurate
// representation.
customEvent.keyCode = (options.charCode > 0) ? options.charCode : options.keyCode;
target.fireEvent("on" + type, customEvent);
} else {
return false;
}
return true;
},
/*
* Injects a mouse event using the given event information to populate the event
* object.
*
* @param {HTMLElement} target The target of the given event.
* @param {Object} options Object object containing all of the event injection
* options.
* @param {String} options.type The type of event to fire. This can be any one of
* the following: `click`, `dblclick`, `mousedown`, `mouseup`, `mouseout`,
* `mouseover` and `mousemove`.
* @param {Boolean} [options.bubbles=true] `tru` if the event can be bubbled up.
* DOM Level 2 specifies that all mouse events bubble by default.
* @param {Boolean} [options.cancelable=true] `true` if the event can be canceled
* using `preventDefault`. DOM Level 2 specifies that all mouse events except
* `mousemove` can be cancelled. This defaults to `false` for `mousemove`.
* @param {Boolean} [options.ctrlKey=false] `true` if one of the CTRL keys is
* pressed while the event is firing.
* @param {Boolean} [options.altKey=false] `true` if one of the ALT keys is
* pressed while the event is firing.
* @param {Boolean} [options.shiftKey=false] `true` if one of the SHIFT keys is
* pressed while the event is firing.
* @param {Boolean} [options.metaKey=false] `true` if one of the META keys is
* pressed while the event is firing.
* @param {int} [options.detail=1] The number of times the mouse button has been
* used.
* @param {int} [options.screenX=0] The x-coordinate on the screen at which point
* the event occured.
* @param {int} [options.screenY=0] The y-coordinate on the screen at which point
* the event occured.
* @param {int} [options.clientX=0] The x-coordinate on the client at which point
* the event occured.
* @param {int} [options.clientY=0] The y-coordinate on the client at which point
* the event occured.
* @param {int} [options.button=0] The button being pressed while the event is
* executing. The value should be 0 for the primary mouse button (typically the
* left button), 1 for the terciary mouse button (typically the middle button),
* and 2 for the secondary mouse button (typically the right button).
* @param {HTMLElement} [options.relatedTarget=null] For `mouseout` events, this
* is the element that the mouse has moved to. For `mouseover` events, this is
* the element that the mouse has moved from. This argument is ignored for all
* other events.
* @param {Window} [view=window] The view containing the target. This is typically
* the window object.
* @private
*/
injectMouseEvent: function (target, options, view) {
var type = options.type,
customEvent = null;
view = view || window;
//check for DOM-compliant browsers first
if (doc.createEvent){
customEvent = doc.createEvent("MouseEvents");
//Safari 2.x (WebKit 418) still doesn't implement initMouseEvent()
if (customEvent.initMouseEvent){
customEvent.initMouseEvent(type, options.bubbles, options.cancelable,
view, options.detail, options.screenX, options.screenY,
options.clientX, options.clientY, options.ctrlKey,
options.altKey, options.shiftKey, options.metaKey,
options.button, options.relatedTarget);
} else { //Safari
//the closest thing available in Safari 2.x is UIEvents
customEvent = doc.createEvent("UIEvents");
customEvent.initEvent(type, options.bubbles, options.cancelable);
customEvent.view = view;
customEvent.detail = options.detail;
customEvent.screenX = options.screenX;
customEvent.screenY = options.screenY;
customEvent.clientX = options.clientX;
customEvent.clientY = options.clientY;
customEvent.ctrlKey = options.ctrlKey;
customEvent.altKey = options.altKey;
customEvent.metaKey = options.metaKey;
customEvent.shiftKey = options.shiftKey;
customEvent.button = options.button;
customEvent.relatedTarget = options.relatedTarget;
}
/*
* Check to see if relatedTarget has been assigned. Firefox
* versions less than 2.0 don't allow it to be assigned via
* initMouseEvent() and the property is readonly after event
* creation, so in order to keep YAHOO.util.getRelatedTarget()
* working, assign to the IE proprietary toElement property
* for mouseout event and fromElement property for mouseover
* event.
*/
if (options.relatedTarget && !customEvent.relatedTarget){
if (type == "mouseout"){
customEvent.toElement = options.relatedTarget;
} else if (type == "mouseover"){
customEvent.fromElement = options.relatedTarget;
}
}
target.dispatchEvent(customEvent);
} else if (doc.createEventObject) { //IE
customEvent = doc.createEventObject();
customEvent.bubbles = options.bubbles;
customEvent.cancelable = options.cancelable;
customEvent.view = view;
customEvent.detail = options.detail;
customEvent.screenX = options.screenX;
customEvent.screenY = options.screenY;
customEvent.clientX = options.clientX;
customEvent.clientY = options.clientY;
customEvent.ctrlKey = options.ctrlKey;
customEvent.altKey = options.altKey;
customEvent.metaKey = options.metaKey;
customEvent.shiftKey = options.shiftKey;
customEvent.button = Player.ieButtonCodeMap[options.button] || 0;
/*
* Have to use relatedTarget because IE won't allow assignment
* to toElement or fromElement on generic events. This keeps
* YAHOO.util.customEvent.getRelatedTarget() functional.
*/
customEvent.relatedTarget = options.relatedTarget;
target.fireEvent('on' + type, customEvent);
} else {
return false;
}
return true;
},
/*
* Injects a UI event using the given event information to populate the event
* object.
*
* @param {HTMLElement} target The target of the given event.
* @param {String} options.type The type of event to fire. This can be any one of
* the following: `click`, `dblclick`, `mousedown`, `mouseup`, `mouseout`,
* `mouseover` and `mousemove`.
* @param {Boolean} [options.bubbles=true] `tru` if the event can be bubbled up.
* DOM Level 2 specifies that all mouse events bubble by default.
* @param {Boolean} [options.cancelable=true] `true` if the event can be canceled
* using `preventDefault`. DOM Level 2 specifies that all mouse events except
* `mousemove` can be cancelled. This defaults to `false` for `mousemove`.
* @param {int} [options.detail=1] The number of times the mouse button has been
* used.
* @param {Window} [view=window] The view containing the target. This is typically
* the window object.
* @private
*/
injectUIEvent: function (target, options, view) {
var customEvent = null;
view = view || window;
//check for DOM-compliant browsers first
if (doc.createEvent){
//just a generic UI Event object is needed
customEvent = doc.createEvent("UIEvents");
customEvent.initUIEvent(options.type, options.bubbles, options.cancelable,
view, options.detail);
target.dispatchEvent(customEvent);
} else if (doc.createEventObject){ //IE
customEvent = doc.createEventObject();
customEvent.bubbles = options.bubbles;
customEvent.cancelable = options.cancelable;
customEvent.view = view;
customEvent.detail = options.detail;
target.fireEvent("on" + options.type, customEvent);
} else {
return false;
}
return true;
}
} // statics
}});