Skip to content

Instantly share code, notes, and snippets.

@boucher
Created April 4, 2010 01:34
Show Gist options
  • Save boucher/354998 to your computer and use it in GitHub Desktop.
Save boucher/354998 to your computer and use it in GitHub Desktop.
@implementation CPEvent (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
var type = [aCoder decodeObjectForKey:CPEventTypeKey],
altKey = [aCoder decodeBoolForKey:CPEventAltKeyKey],
bubbles = [aCoder decodeBoolForKey:CPEventBubblesKey],
button = [aCoder decodeIntForKey:CPEventButtonKey],
cancelBubble = [aCoder decodeBoolForKey:CPEventCancelBubbleKey],
cancelable = [aCoder decodeBoolForKey:CPEventCancelableKey],
charCode = [aCoder decodeObjectForKey:CPEventCharCodeKey],
clientX = [aCoder decodeObjectForKey:CPEventClientXKey],
clientY = [aCoder decodeObjectForKey:CPEventClientYKey],
ctrlKey = [aCoder decodeBoolForKey:CPEventCtrlKeyKey],
eventPhase = [aCoder decodeObjectForKey:CPEventEventPhaseKey],
isChar = [aCoder decodeBoolForKey:CPEventIsCharKey],
keyCode = [aCoder decodeObjectForKey:CPEventKeyCodeKey],
metaKey = [aCoder decodeBoolForKey:CPEventMetaKeyKey],
pageX = [aCoder decodeObjectForKey:CPEventPageXKey],
pageY = [aCoder decodeObjectForKey:CPEventPageYKey],
screenX = [aCoder decodeObjectForKey:CPEventScreenXKey],
screenY = [aCoder decodeObjectForKey:CPEventScreenYKey],
shiftKey = [aCoder decodeBoolForKey:CPEventShiftKey],
timeStamp = [aCoder decodeObjectForKey:CPEventTimeStampKey],
which = [aCoder decodeObjectForKey:CPEventWhichKey],
scale = [aCoder decodeObjectForKey:CPEventScaleKey],
rotation = [aCoder decodeObjectForKey:CPEventRotationKey],
nativeEvent;
if ([aCoder containsValueForKey:CPEventCurrentTargetKey])
var currentTarget = getElementFromXPath([aCoder decodeObjectForKey:CPEventCurrentTargetKey], recorderWindow.document);
if ([aCoder containsValueForKey:CPEventExplicitOriginalTargeyKey])
var explicitOriginalTarget = getElementFromXPath([aCoder decodeObjectForKey:CPEventExplicitOriginalTargeyKey], recorderWindow.document);
if ([aCoder containsValueForKey:CPEventOriginalTargetKey])
var originalTarget = getElementFromXPath([aCoder decodeObjectForKey:CPEventOriginalTargetKey], recorderWindow.document);
if ([aCoder containsValueForKey:CPEventRelatedTargetKey])
var relatedTarget = getElementFromXPath([aCoder decodeObjectForKey:CPEventRelatedTargetKey], recorderWindow.document);
if ([aCoder containsValueForKey:CPEventTargetKey])
var target = getElementFromXPath([aCoder decodeObjectForKey:CPEventTargetKey], recorderWindow.document);
if ([aCoder containsValueForKey:CPEventTouchesKey])
var touches = touchListFromTouchEventArray([aCoder decodeObjectForKey:CPEventTouchesKey]);
if ([aCoder containsValueForKey:CPEventTargetTouchesKey])
var targetTouches = touchListFromTouchEventArray([aCoder decodeObjectForKey:CPEventTargetTouchesKey]);
if ([aCoder containsValueForKey:CPEventChangedTouchesKey])
var changedTouches = touchListFromTouchEventArray([aCoder decodeObjectForKey:CPEventChangedTouchesKey]);
if (type in mouseTypes)
{
nativeEvent = recorderWindow.document.createEvent("MouseEvent");
nativeEvent.initMouseEvent(type, bubbles, cancelable, recorderWindow,
"", screenX, screenY, clientX, clientY,
ctrlKey, altKey, shiftKey, metaKey,
button, relatedTarget);
// nativeEvent.target = target; // ?
}
else if (type in touchTypes)
{
nativeEvent = recorderWindow.document.createEvent("TouchEvent");
nativeEvent.initTouchEvent(type, canBubble, cancelable, recorderWindow, "", screenX, screenY,
clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
touches, targetTouches, changedTouches, scale, rotation);
}
else if (type in keyTypes)
{
nativeEvent = recorderWindow.document.createEvent("KeyboardEvent");
nativeEvent.initKeyEvent(type, bubbles, cancelable, recorderWindow,
ctrlKey, altKey, shiftKey, metaKey,
keyCode, charCode);
// nativeEvent.target = target; // ?
}
else
{
nativeEvent = recorderWindow.document.createEvent("Event");
nativeEvent.initEvent(type, bubbles, cancelable);
nativeEvent.target = target; // ?
nativeEvent.clientX = clientX;
nativeEvent.clientY = clientY;
nativeEvent.pageX = pageX;
nativeEvent.pageY = pageY;
nativeEvent.screenX = screenX;
nativeEvent.screenY = screenY;
nativeEvent.shiftKey = shiftKey;
nativeEvent.ctrlKey = ctrlKey;
nativeEvent.altKey = altKey;
nativeEvent.metaKey = metaKey;
}
nativeEvent.isa = [CPEvent class];
return nativeEvent;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeBool:self.altKey forKey:CPEventAltKeyKey];
[aCoder encodeBool:self.bubbles forKey:CPEventBubblesKey];
[aCoder encodeInt:self.button forKey:CPEventButtonKey];
[aCoder encodeBool:self.cancelBubble forKey:CPEventCancelBubbleKey];
[aCoder encodeBool:self.cancelable forKey:CPEventCancelableKey];
[aCoder encodeObject:self.charCode forKey:CPEventCharCodeKey];
[aCoder encodeObject:self.clientX forKey:CPEventClientXKey];
[aCoder encodeObject:self.clientY forKey:CPEventClientYKey];
[aCoder encodeBool:self.ctrlKey forKey:CPEventCtrlKeyKey];
if (self.currentTarget)
[aCoder encodeObject:getXPathForElement(self.currentTarget, recorderWindow.document) forKey:CPEventCurrentTargetKey];
[aCoder encodeObject:self.eventPhase forKey:CPEventEventPhaseKey];
if (self.explicitOriginalTarget)
[aCoder encodeObject:getXPathForElement(self.explicitOriginalTarget, recorderWindow.document) forKey:CPEventExplicitOriginalTargeyKey];
[aCoder encodeBool:self.isChar forKey:CPEventIsCharKey];
[aCoder encodeObject:self.keyCode forKey:CPEventKeyCodeKey];
[aCoder encodeBool:self.metaKey forKey:CPEventMetaKeyKey];
if (self.originalTarget)
[aCoder encodeObject:getXPathForElement(self.originalTarget, recorderWindow.document) forKey:CPEventOriginalTargetKey];
[aCoder encodeObject:self.pageX forKey:CPEventPageXKey];
[aCoder encodeObject:self.pageY forKey:CPEventPageYKey];
if (self.relatedTarget)
[aCoder encodeObject:getXPathForElement(self.relatedTarget, recorderWindow.document) forKey:CPEventRelatedTargetKey];
[aCoder encodeObject:self.screenX forKey:CPEventScreenXKey];
[aCoder encodeObject:self.screenY forKey:CPEventScreenYKey];
[aCoder encodeBool:self.shiftKey forKey:CPEventShiftKey];
if (self.target)
[aCoder encodeObject:getXPathForElement(self.target, recorderWindow.document) forKey:CPEventTargetKey];
[aCoder encodeObject:self.timeStamp forKey:CPEventTimeStampKey];
[aCoder encodeObject:self.type forKey:CPEventTypeKey];
[aCoder encodeObject:self.which forKey:CPEventWhichKey];
if (self.touches)
[aCoder encodeObject:touchEventArrayFromTouchList(self.touches) forKey:CPEventTouchesKey];
if (self.targetTouches)
[aCoder encodeObject:touchEventArrayFromTouchList(self.targetTouches) forKey:CPEventTargetTouchesKey];
if (self.changedTouches)
[aCoder encodeObject:touchEventArrayFromTouchList(self.changedTouches) forKey:CPEventChangedTouchesKey];
[aCoder encodeObject:self.scale forKey:CPEventScaleKey];
[aCoder encodeObject:self.rotation forKey:CPEventRotationKey];
}
@end
function touchEventArrayFromTouchList(touchList)
{
var array = [],
count = touchList.length;
for (var i = 0; i < count; i++)
{
var item = touchList.item(i);
array.push({
clientX : item.clientX,
clientY : item.clientY,
identifier : item.identifier,
pageX : item.pageX,
pageY : item.pageY,
screenX : item.screenX,
screenY : item.screenY,
target : getXPathForElement(item.target, recorderWindow.document)
});
}
return array;
}
function touchListFromTouchEventArray(touchEventArray)
{
var count = touchEventArray.length;
for (var i = 0; i < count; i++)
{
var item = touchEventArray[i];
item.target = getElementFromXPath(item.target);
}
touchEventArray.item = function(i)
{
return touchEventArray[i];
}
return touchEventArray;
}
function getXPathForElement(el, xml)
{
var xpath = '';
var pos, tempitem2;
while(el !== xml.documentElement) {
pos = 0;
tempitem2 = el;
while(tempitem2) {
if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { // If it is ELEMENT_NODE of the same name
pos += 1;
}
tempitem2 = tempitem2.previousSibling;
}
xpath = "*[name()='"+el.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']["+pos+']'+'/'+xpath;
el = el.parentNode;
}
xpath = '/*'+"[name()='"+xml.documentElement.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']"+'/'+xpath;
xpath = xpath.replace(/\/$/, '');
return xpath;
}
function getElementFromXPath(aExpr, aNode)
{
var xpe = new XPathEvaluator();
var nsResolver = xpe.createNSResolver(aNode.ownerDocument == null ?
aNode.documentElement : aNode.ownerDocument.documentElement);
var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null),
found = [],
res;
while (res = result.iterateNext())
found.push(res);
return found.length === 1 ? found[0] : found;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment