Created
July 9, 2013 16:43
-
-
Save kevingorski/5958985 to your computer and use it in GitHub Desktop.
Trying to show delegated click events not working on group elements in IE.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
<title>SVG Group Element Click Events</title> | |
<style> | |
.DirectClickEvent { fill: green; } | |
.GroupClickEvent { fill: red; } | |
text { fill: white; } | |
</style> | |
</head> | |
<body> | |
<svg data-bind="delegatedHandler: 'click'"> | |
<!-- ko foreach: Items --> | |
<rect class="DirectClickEvent" data-bind="delegatedClick: alertIndex, attr: { y: Y, width: 50, height:45 }" /> | |
<!-- /ko --> | |
<!-- ko foreach: Items --> | |
<g data-bind="delegatedClick: alertIndex"> | |
<rect class="GroupClickEvent" data-bind="attr: { y: Y, x: 55, width: 50, height:45 }" /> | |
<text data-bind="text: Index, attr: { x: 75, y: Y + 25 }" /> | |
</g> | |
<!-- /ko --> | |
</svg> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script> | |
<script src="knockout-delegatedEvents.js"></script> | |
<script> | |
function ItemViewModel(index) { | |
this.Index = index; | |
this.Y = index*50; | |
} | |
ItemViewModel.prototype.alertIndex = function() { | |
alert(this.Index); | |
}; | |
var ListViewModel = function(count) { | |
this.Items = ko.observableArray(new Array(count)); | |
for(var i=0;i<count;i++) { | |
this.Items()[i] = new ItemViewModel(i) | |
} | |
}; | |
ko.applyBindings(new ListViewModel(3)); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;(function(factory) { | |
//CommonJS | |
if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { | |
factory(require("knockout"), exports); | |
//AMD | |
} else if (typeof define === "function" && define.amd) { | |
define(["knockout", "exports"], factory); | |
//normal script tag | |
} else { | |
factory(ko, ko.actions = {}); | |
} | |
}(function(ko, actions) { | |
var prefix = "ko_delegated_"; | |
var createDelegatedHandler = function(eventName, root) { | |
return function(event) { | |
var data, method, action, owner, matchingParent, command, result, | |
el = event.target || event.srcElement, | |
context = ko.contextFor(el), | |
attr = "data-" + eventName, | |
key = prefix + eventName; | |
if (context) { | |
//loop until we either find an action, run out of elements, or hit the root element that has our delegated handler | |
while (!method && el) { | |
method = el.getAttribute(attr) || ko.utils.domData.get(el, key); | |
if (!method) { | |
el = el !== root ? el.parentElement : null; | |
} | |
} | |
if (method) { | |
//get context of the element that actually held the action | |
context = ko.contextFor(el); | |
if (context) { | |
data = context.$data; | |
if (typeof method === "string") { | |
//check defined actions | |
if (method in actions) { | |
command = actions[method]; | |
if (command) { | |
action = typeof command === "function" ? command : command.action; | |
owner = command.owner || data; | |
} | |
} | |
//search for the action | |
else if (data && data[method] && typeof data[method] === "function") { | |
action = data[method]; | |
owner = data; | |
} | |
//search parents for the action | |
if (!action) { | |
matchingParent = ko.utils.arrayFirst(context.$parents, function(parent) { | |
return parent[method] && typeof parent[method] === "function"; | |
}); | |
action = matchingParent && matchingParent[method]; | |
owner = matchingParent; | |
} | |
} | |
//a binding handler was used to associate the element with a function | |
else if (typeof method === "function") { | |
action = method; | |
owner = data; | |
} | |
} | |
//execute the action as KO normally would | |
if (action) { | |
result = action.call(owner, data, event); | |
//prevent default action, if handler returns true | |
if (result !== true) { | |
if (event.preventDefault) { | |
event.preventDefault(); | |
} | |
else { | |
event.returnValue = false; | |
} | |
} | |
} | |
} | |
} | |
}; | |
}; | |
//create a binding for an event to associate a function with the element | |
var createDelegatedBinding = function(event) { | |
var bindingName; | |
if (event) { | |
//capitalize first letter | |
bindingName = "delegated" + event.substr(0, 1).toUpperCase() + event.slice(1); | |
} | |
//create the binding, if it does not exist | |
if (!ko.bindingHandlers[bindingName]) { | |
ko.bindingHandlers[bindingName] = { | |
init: function(element, valueAccessor) { | |
var action = valueAccessor(); | |
ko.utils.domData.set(element, prefix + event, action); | |
} | |
}; | |
} | |
}; | |
//add a handler on a parent element that responds to events from the children | |
ko.bindingHandlers.delegatedHandler = { | |
init: function(element, valueAccessor) { | |
var events = ko.utils.unwrapObservable(valueAccessor()) || []; | |
if (typeof events === "string") { | |
events = [events]; | |
} | |
ko.utils.arrayForEach(events, function(event) { | |
createDelegatedBinding(event); | |
ko.utils.registerEventHandler(element, event, createDelegatedHandler(event, element)); | |
}); | |
} | |
}; | |
})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment