<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js"><span id='Ext-ux-event-Recorder'>/**
|
</span> * @extends Ext.ux.event.Driver
|
* Event recorder.
|
*/
|
Ext.define('Ext.ux.event.Recorder', function () {
|
function samePt (pt1, pt2) {
|
return pt1.x == pt2.x && pt1.y == pt2.y;
|
}
|
|
return {
|
extend: 'Ext.ux.event.Driver',
|
|
eventsToRecord: function () {
|
var key = { kind: 'keyboard', modKeys: true, key: true, bubbles: true },
|
mouse = { kind: 'mouse', button: true, modKeys: true, xy: true, bubbles: true };
|
|
return {
|
keydown: key,
|
keypress: key,
|
keyup: key,
|
|
mousemove: mouse,
|
mouseover: mouse,
|
mouseout: mouse,
|
click: mouse,
|
//mousewheel: Ext.apply({ wheel: true }, mouse),
|
mousedown: mouse,
|
mouseup: mouse,
|
|
scroll: { kind: 'misc', bubbles: false }
|
};
|
}(),
|
|
ignoreIdRegEx: /ext-gen(?:\d+)/,
|
|
constructor: function (config) {
|
var me = this,
|
events = config && config.eventsToRecord;
|
|
if (events) {
|
me.eventsToRecord = Ext.apply(Ext.apply({}, me.eventsToRecord), // duplicate
|
events); // and merge
|
delete config.eventsToRecord; // don't smash
|
}
|
|
me.callParent(arguments);
|
|
me.addEvents(
|
<span id='Ext-ux-event-Recorder-event-add'> /**
|
</span> * @event add
|
* Fires when an event is added to the recording.
|
* @param {Ext.ux.event.Recorder} this
|
* @param {Object} eventDescriptor The event descriptor.
|
*/
|
'add',
|
|
<span id='Ext-ux-event-Recorder-event-coalesce'> /**
|
</span> * @event coalesce
|
* Fires when an event is coalesced. This edits the tail of the recorded
|
* event list.
|
* @param {Ext.ux.event.Recorder} this
|
* @param {Object} eventDescriptor The event descriptor that was coalesced.
|
*/
|
'coalesce'
|
);
|
|
me.clear();
|
me.modKeys = [];
|
me.attachTo = me.attachTo || window;
|
},
|
|
clear: function () {
|
this.eventsRecorded = [];
|
},
|
|
coalesce: function (rec) {
|
var me = this,
|
events = me.eventsRecorded,
|
length = events.length,
|
tail = length && events[length-1],
|
tailPrev;
|
|
if (!tail) {
|
return false;
|
}
|
|
if (rec.type == 'mousemove') {
|
if (tail.type == 'mousemove' && rec.ts - tail.ts < 200) {
|
rec.ts = tail.ts;
|
events[length-1] = rec;
|
return true;
|
}
|
} else if (rec.type == 'click') {
|
if (length >= 2 && tail.type == 'mouseup' &&
|
(tailPrev = events[length-2]).type == 'mousedown') {
|
if (rec.button == tail.button && rec.button == tailPrev.button &&
|
rec.target == tail.target && rec.target == tailPrev.target &&
|
samePt(rec, tail) && samePt(rec, tailPrev) ) {
|
events.pop(); // remove mouseup
|
tailPrev.type = 'mduclick';
|
return true;
|
}
|
}
|
}
|
|
return false;
|
},
|
|
getElementXPath: function (el) {
|
var me = this,
|
good = false,
|
xpath = [],
|
count,
|
sibling,
|
t,
|
tag;
|
|
for (t = el; t; t = t.parentNode) {
|
if (t == me.attachTo.document.body) {
|
xpath.unshift('~');
|
good = true;
|
break;
|
}
|
if (t.id && !me.ignoreIdRegEx.test(t.id)) {
|
xpath.unshift('#' + t.id);
|
good = true;
|
break;
|
}
|
|
for (count = 1, sibling = t; !!(sibling = sibling.previousSibling); ) {
|
if (sibling.tagName == t.tagName) {
|
++count;
|
}
|
}
|
|
tag = t.tagName.toLowerCase();
|
if (count < 2) {
|
xpath.unshift(tag);
|
} else {
|
xpath.unshift(tag + '[' + count + ']');
|
}
|
}
|
|
return good ? xpath.join('/') : null;
|
},
|
|
getRecordedEvents: function () {
|
return this.eventsRecorded;
|
},
|
|
// DOMNodeInserted
|
onDomInsert: function (event, target) {
|
this.watchTree(target);
|
},
|
|
//DOMNodeRemoved
|
onDomRemove: function (event, target) {
|
this.unwatchTree(target);
|
},
|
|
onEvent: function (e) {
|
var me = this,
|
info = me.eventsToRecord[e.type],
|
root,
|
modKeys, elXY,
|
rec = {
|
type: e.type,
|
ts: me.getTimestamp(),
|
target: me.getElementXPath(e.target)
|
},
|
xy;
|
|
if (!rec.target) {
|
return;
|
}
|
root = e.target.ownerDocument;
|
root = root.defaultView || root.parentWindow; // Standards || IE
|
if (root !== me.attachTo) {
|
return;
|
}
|
|
if (info.xy) {
|
xy = e.getXY();
|
if (rec.target) {
|
elXY = Ext.fly(e.getTarget()).getXY();
|
xy[0] -= elXY[0];
|
xy[1] -= elXY[1];
|
}
|
rec.x = xy[0];
|
rec.y = xy[1];
|
}
|
|
if (info.button) {
|
rec.button = e.button;
|
}
|
|
if (info.wheel) {
|
rec.wheel = e.getWheelDelta();
|
}
|
|
if (info.modKeys) {
|
me.modKeys[0] = e.altKey ? 'A' : '';
|
me.modKeys[1] = e.ctrlKey ? 'C' : '';
|
me.modKeys[2] = e.metaKey ? 'M' : '';
|
me.modKeys[3] = e.shiftKey ? 'S' : '';
|
|
modKeys = me.modKeys.join('');
|
if (modKeys) {
|
rec.modKeys = modKeys;
|
}
|
}
|
|
if (info.key) {
|
rec.charCode = e.getCharCode();
|
rec.keyCode = e.getKey();
|
}
|
|
if (me.coalesce(rec)) {
|
me.fireEvent('coalesce', me, rec);
|
} else {
|
me.eventsRecorded.push(rec);
|
me.fireEvent('add', me, rec);
|
}
|
},
|
|
onStart: function () {
|
var me = this,
|
on = {
|
DOMNodeInserted: me.onDomInsert,
|
DOMNodeRemoved: me.onDomRemove,
|
scope: me
|
},
|
nonBubbleEvents = (me.nonBubbleEvents = {}),
|
ddm = me.attachTo.Ext.dd.DragDropManager,
|
evproto = me.attachTo.Ext.EventObjectImpl.prototype;
|
|
me.watchingNodes = {};
|
|
Ext.Object.each(me.eventsToRecord, function (name, value) {
|
if (value) {
|
if (value.bubbles) {
|
on[name] = me.onEvent;
|
} else {
|
nonBubbleEvents[name] = value;
|
}
|
}
|
});
|
|
me.ddmStopEvent = ddm.stopEvent;
|
ddm.stopEvent = Ext.Function.createSequence(ddm.stopEvent, function (e) {
|
me.onEvent(e);
|
});
|
me.evStopEvent = evproto.stopEvent;
|
evproto.stopEvent = Ext.Function.createSequence(evproto.stopEvent, function () {
|
me.onEvent(this);
|
});
|
|
var body = me.attachTo.Ext.getBody();
|
body.on(on);
|
me.watchTree(body.dom);
|
},
|
|
onStop: function () {
|
var me = this,
|
body = me.attachTo.Ext.getBody();
|
|
Ext.Object.each(me.eventsToRecord, function (name, value) {
|
if (value) {
|
body.un(name, me.onEvent, me);
|
}
|
});
|
|
me.attachTo.Ext.dd.DragDropManager.stopEvent = me.ddmStopEvent;
|
me.attachTo.Ext.EventObjectImpl.prototype.stopEvent = me.evStopEvent;
|
|
me.unwatchTree(body.dom);
|
},
|
|
watchTree: function (root) {
|
if (root.nodeType != 1) {
|
return; // only ELEMENT_NODE's please...
|
}
|
|
var me = this,
|
id = (root.tagName == 'BODY') ? '$' : root.id,
|
watchingNodes = me.watchingNodes;
|
|
if (id && !watchingNodes[id]) {
|
var on = {
|
scope: me
|
};
|
|
Ext.Object.each(me.nonBubbleEvents, function (name, value) {
|
if (value) {
|
on[name] = me.onEvent;
|
}
|
});
|
me.attachTo.Ext.fly(root).on(on);
|
watchingNodes[id] = true;
|
console.log('watch '+root.tagName+'#'+id);
|
}
|
|
Ext.each(root.childNodes, me.watchTree, me);
|
},
|
|
unwatchTree: function (root) {
|
if (root.nodeType != 1) {
|
return; // only ELEMENT_NODE's please...
|
}
|
|
var me = this,
|
id = (root.tagName == 'BODY') ? '$' : root.id,
|
watchingNodes = me.watchingNodes;
|
|
if (id && !watchingNodes[id]) {
|
Ext.Object.each(me.nonBubbleEvents, function (name, value) {
|
me.attachTo.Ext.fly(root).un(name, me.onEvent, me);
|
});
|
delete watchingNodes[id];
|
console.log('unwatch '+root.tagName+'#'+id);
|
}
|
|
Ext.each(root.childNodes, me.unwatchTree, me);
|
}
|
};
|
}());
|
</pre>
|
</body>
|
</html>
|