Last active
August 29, 2015 14:15
-
-
Save nickytonline/e34290b72661db9873f1 to your computer and use it in GitHub Desktop.
Event management in the DOM via bubbling for Handlebars templating POC
This file contains hidden or 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
<html> | |
<head> | |
<title>Client-Side Event Binding with HandleBards POC</title> | |
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" /> | |
<!--[if IE]> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<![endif]--> | |
<style type="text/css"> | |
#logger { | |
height: 250px; | |
overflow-y: auto; | |
background-color: #000; | |
color: #fff; | |
margin: 10px; | |
padding: 10px; | |
} | |
.date--log { | |
color: #336600; | |
} | |
.message--important { | |
color: #ff3300; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="col-md-5"> | |
<h2>Logger</h2> | |
<div id="logger"></div> | |
</div> | |
<div class="col-md-5"> | |
<div id="main-content"></div> | |
</div> | |
<script id="testTemplate" type="template"> | |
<ul> | |
{{#each names}} | |
<li> | |
<input value="{{this}}" data-orckaction="{'mouseover': 'mouseOverAction', 'mouseout': 'mouseOutAction', 'click': 'inputClickAction', 'dblclick': 'doubleClickAction', 'change': 'inputChangedAction', 'keypress': 'keyPressAction', 'keyup': 'keyUpAction', 'keydown': 'keyDownAction' }" /> | |
</li> | |
{{/each}} | |
</ul> | |
<ul> | |
{{#each urls}} | |
<li> | |
<a href="{{this}}" data-orckaction="{'mouseover': 'mouseOverAction', 'mouseout': 'mouseOutAction', 'click': 'linkClickAction', 'dblclick': 'doubleClickAction' }">Test Event Bubbling on link {{@index}}</a> | |
</li> | |
{{/each}} | |
</ul> | |
</script> | |
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> | |
<!--[if lt IE 9]> | |
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> | |
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> | |
<![endif]--> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> | |
<script src="//cdn.jsdelivr.net/lodash/3.0.0/lodash.compat.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.0/handlebars.min.js"></script> | |
<script> | |
$(document).ready(function() { | |
var linkTimeoutId = 0, | |
template, | |
model, | |
log, | |
mainElementContext = $('#main-content'), | |
bodyContext = $(document.body), | |
nonBubblingEvents = { | |
focus: 'focus', | |
blur: 'blur', | |
submit: 'submit', | |
reset: 'reset', | |
change: 'change' | |
}, | |
bubblingEvents = [ 'mouseover', 'mouseout', 'click', 'dblclick', 'keypress', 'keyup', 'keydown' ], | |
actions = { | |
'mouseOverAction': function(e) { | |
e.stopPropagation(); | |
log('Moused over'); | |
}, | |
'mouseOutAction': function(e) { | |
e.stopPropagation(); | |
log('Moused out'); | |
}, | |
'linkClickAction': function(e) { | |
e.stopPropagation(); | |
e.preventDefault(); | |
log('<span class="message--important">Hyperlink clicked! Did you know my URL is ' + this.attr('href') + '</span>'); | |
}, | |
'inputChangedAction': function(e) { | |
log('<span class="message--important">Changed! Did you know my new value is ' + this.val() + '</span>'); | |
}, | |
'inputClickAction': function(e) { | |
e.stopPropagation(); | |
e.preventDefault(); | |
log('<span class="message--important">Clicked! Did you know my value is ' + this.val() + '</span>'); | |
}, | |
'doubleClickAction': function(e) { | |
clearTimeout(linkTimeoutId); | |
e.stopPropagation(); | |
e.preventDefault(); | |
log('Double-clicked! Did you know my URL is ' + this.attr('href')); | |
}, | |
'keyPressAction': function(e) { | |
log('Keypress fired! Keycode is ' + (e.keyCode ? e.keyCode : e.which)); | |
}, | |
'keyUpAction': function(e) { | |
log('Keyup fired! Keycode is ' + (e.keyCode ? e.keyCode : e.which)); | |
}, | |
'keyDownAction': function(e) { | |
log('Keydown fired! Keycode is ' + (e.keyCode ? e.keyCode : e.which)); | |
} | |
}; | |
log = (function(loggerContext) { | |
return function (message) { | |
loggerContext.prepend('<span class="date--log">' + (new Date()).toLocaleString() + '</span> ' + message + '<br />'); | |
}; | |
})($("#logger")); | |
function manageAction(e) { | |
var context = $(e.target), | |
eventType = e.type, | |
elementActions, | |
rawActions, | |
action, | |
elementActionEventType,nonBubblingAction; | |
rawActions = context.data('orckaction'); | |
if (_.isEmpty(rawActions)) { | |
return; | |
} | |
// Csn probably set this as an expando property instead of parsing the JSON all the time. | |
elementActions = $.parseJSON(rawActions.replace(/'/g, '"')); | |
action = elementActions[eventType]; | |
if (action in actions) { | |
if (context.data('orckBound') !== true) { | |
context.data('orckBound', true); | |
for (elementActionEventType in elementActions) { | |
if (elementActionEventType in nonBubblingEvents) { | |
nonBubblingAction = elementActions[elementActionEventType]; | |
context.on( | |
elementActionEventType, | |
(function(context, actionCallback) { | |
return actionCallback.bind(context); | |
})(context, actions[nonBubblingAction]) | |
); | |
log('This ' + action + ' is a non-bubbling event. Binding to the element directly'); | |
} | |
} | |
} | |
if (!(eventType in nonBubblingEvents)) { | |
actions[action].apply(context, [e]); | |
} | |
} else { | |
log("No action " + action + " is registered."); | |
} | |
} | |
$.map(bubblingEvents , function(item, index) { | |
bodyContext.on(item, manageAction); | |
}); | |
template = Handlebars.compile($("#testTemplate").html()); | |
model = { | |
names: [ | |
'nick', | |
'john', | |
'suzie', | |
'walter', | |
'jesse' | |
], | |
urls: [ | |
'http://www.google.com', | |
'http://www.twitter.com', | |
'http://www.microsoft.com', | |
'http://www.bing.com', | |
'http://youtube.com', | |
'http://facebook.com', | |
'http://linkedin.com', | |
'http://cnn.com', | |
'http://msnbc.com' | |
] | |
}; | |
mainElementContext.html(template(model)); | |
}); | |
</script> | |
</body> | |
</html> |
Here is a version that uses hammer.js for tactile events, specifically single tap and double tap.
http://plnkr.co/edit/jZeCUc
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
And here's the code running http://jsfiddle.net/nickyt/jk3fespv . It works in IE8+/Chrome/FF and although not tested, I would assume Safari and Opera.