;(function($) {\r
\r
$.fn.extend({\r
- simulate: function(type, options, complete) {\r
+ simulate: function(type, options) {\r
return this.each(function() {\r
- var opt = $.extend({ complete: complete }, options);\r
+ var opt = $.extend({}, $.simulate.defaults, options || {});\r
new $.simulate(this, type, opt);\r
});\r
}\r
\r
$.simulate = function(el, type, options) {\r
this.target = el;\r
- if (/^drag$/.test(type)) {\r
+ this.options = options;\r
+ \r
+ if (/^drag$/i.test(type)) {\r
this[type].apply(this, [this.target, options]);\r
} else {\r
- this.simulateEvent(type, options);\r
+ this.simulateEvent(el, type, options);\r
}\r
}\r
\r
$.extend($.simulate.prototype, {\r
simulateEvent: function(el, type, options) {\r
+ // creates a individual option for each simulation inside this instance\r
+ options = $.extend({}, this.options, options);\r
var evt = this.createEvent(type, options);\r
- this.dispatchEvent(el, type, evt);\r
+ return this.dispatchEvent(el, type, evt, options);\r
},\r
createEvent: function(type, options) {\r
- if (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {\r
+ if (/^mouse(over|out|down|up|move)|(dbl)?click$/i.test(type)) {\r
return this.mouseEvent(type, options);\r
- } else if (/^key(up|down|press)$/.test(type)) {\r
+ } else if (/^key(up|down|press)$/i.test(type)) {\r
return this.keyboardEvent(type, options);\r
}\r
},\r
var evt;\r
var e = $.extend({\r
bubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,\r
- screenX: 0, screenY: 0, clientX: 0, clientY: 0,\r
+ screenX: 0, screenY: 0, clientX: options.x || 0, clientY: options.y || 0,\r
ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,\r
button: 0, relatedTarget: null\r
}, options);\r
+ \r
+ var relatedTarget = $(e.relatedTarget)[0];\r
+ \r
if ($.isFunction(document.createEvent)) {\r
evt = document.createEvent("MouseEvents");\r
evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,\r
e.screenX, e.screenY, e.clientX, e.clientY,\r
e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,\r
- e.button, e.relatedTarget);\r
+ e.button, relatedTarget);\r
+ \r
+ // check to see if relatedTarget has been assigned\r
+ if (relatedTarget && !evt.relatedTarget) {\r
+ if (/^mouseout$/i.test(type)) evt.toElement = relatedTarget;\r
+ else if (/^mouseover$/i.test(type)) evt.fromElement = relatedTarget;\r
+ }\r
+ \r
} else if (document.createEventObject) {\r
evt = document.createEventObject();\r
$.extend(evt, e);\r
},\r
keyboardEvent: function(type, options) {\r
var evt;\r
+ \r
var e = $.extend({ bubbles: true, cancelable: true, view: window,\r
ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,\r
keyCode: 0, charCode: 0\r
}, options);\r
+ \r
if ($.isFunction(document.createEvent)) {\r
try {\r
evt = document.createEvent("KeyEvents");\r
}\r
return evt;\r
},\r
- dispatchEvent: function(el, type, evt) {\r
+ \r
+ dispatchEvent: function(el, type, evt, options) {\r
if (el.dispatchEvent) {\r
el.dispatchEvent(evt);\r
} else if (el.fireEvent) {\r
el.fireEvent('on' + type, evt);\r
}\r
+ // trigget complete for all events - not drag.\r
+ this.triggerComplete(evt, options);\r
+ return evt;\r
+ },\r
+ \r
+ drag: function(el) {\r
+ var self = this, center = this.findCenter(this.target), \r
+ options = this.options, x = center.x, y = center.y, \r
+ dx = options.dx || 0, dy = options.dy || 0, target = this.target;\r
+\r
+ var coord = { x: x, y: y, complete: null }, evt;\r
+ this.simulateEvent(target, "mouseover", coord);\r
+ this.simulateEvent(target, "mousedown", coord);\r
+ this.simulateEvent(target, "mousemove", coord);\r
+ \r
+ var drag = function(x, y) {\r
+ evt = self.simulateEvent(target, "mousemove", $.extend(coord, { x: x, y: y }));\r
+ // triggering drag callback\r
+ (self.options.drag && self.options.drag($.event.fix(evt)));\r
+ };\r
+ \r
+ if (/^sync$/i.test(options.speed)) {\r
+ // trigger synchronous simulation\r
+ this.triggerSync(center, dx, dy, drag);\r
+ }\r
+ else {\r
+ // trigger asynchronous simulation - animated\r
+ this.triggerAsync(center, dx, dy, drag);\r
+ }\r
+ \r
+ this.simulateEvent(target, "mouseup", coord);\r
+ this.simulateEvent(target, "mouseout", coord);\r
+ this.triggerComplete(evt, options);\r
+ },\r
+ \r
+ triggerComplete: function(evt, options) {\r
+ evt = $.event.fix(evt);\r
+ (options.complete && options.complete(evt)); return evt;\r
+ },\r
+ \r
+ triggerSync: function(center, dx, dy, fn) {\r
+ var x = center.x, y = center.y, mdx = Math.abs(dx) || 0, mdy = Math.abs(dy) || 0;\r
+ var range = Math.max(mdx, mdy), sigx = dx/mdx || 1, sigy = dy/mdy || 1;\r
+ \r
+ for (var dt = 1; dt <= range; dt++) {\r
+ if (dt <= mdx) x = center.x + sigx*dt;\r
+ if (dt <= mdy) y = center.y + sigy*dt;\r
+ (fn && fn(x, y));\r
+ }\r
+ },\r
+ \r
+ triggerAsync: function(center, dx, dy, fn) {\r
+ /*TODO*/\r
},\r
\r
findCenter: function(el) {\r
x: o.left + el.outerWidth() / 2,\r
y: o.top + el.outerHeight() / 2\r
};\r
- },\r
- drag: function(el, options) {\r
- var center = this.findCenter(this.target),\r
- x = center.x, y = center.y,\r
- dx = options.dx || 0,\r
- dy = options.dy || 0;\r
- this.simulateEvent(this.target, "mouseover");\r
- this.simulateEvent(this.target, "mousedown", { clientX: x, clientY: y });\r
- this.simulateEvent(this.target, "mousemove", { clientX: x, clientY: y });\r
- this.simulateEvent(this.target, "mousemove", { clientX: x, clientY: y });\r
- this.simulateEvent(this.target, "mousemove", { clientX: x, clientY: y });\r
- this.simulateEvent(document, "mousemove", { clientX: x + dx, clientY: y + dy });\r
- this.simulateEvent(document, "mousemove", { clientX: x + dx, clientY: y + dy });\r
- this.simulateEvent(document, "mousemove", { clientX: x + dx, clientY: y + dy });\r
- this.simulateEvent(this.target, "mouseup", { clientX: x + dx, clientY: y + dy });\r
- this.simulateEvent(this.target, "click", { clientX: x + dx, clientY: y + dy });\r
- this.simulateEvent(this.target, "mouseout");\r
- (options.complete && options.complete());\r
}\r
+});\r
\r
+$.extend($.simulate, {\r
+ defaults: {\r
+ speed: 'sync'\r
+ }\r
});\r
\r
})(jQuery);\r