Created
December 5, 2013 23:10
-
-
Save potch/7815727 to your computer and use it in GitHub Desktop.
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
var dombind = (function() { | |
function makeSmart(obj) { | |
obj.__bound__ = {}; | |
} | |
function isSmart(obj) { | |
return '__bound__' in obj; | |
} | |
function makeSmartProperty(obj, property) { | |
var oldVal = obj[property]; | |
obj.__bound__[property] = []; | |
var bound = obj.__bound__; | |
// Apply magic | |
Object.defineProperty(obj, property, { | |
set: function(v) { | |
// set the stored value | |
bound[property].__value__ = v; | |
var els = bound[property]; | |
// fire our handlers | |
for (var i = 0; i < els.length; i++) { | |
// for each [el, fn] pair, call fn(el) | |
els[i][1](els[i][0],v); | |
} | |
}, | |
get: function() { | |
return bound[property].__value__; | |
} | |
}); | |
// apply an old value if it existed | |
if (typeof oldVal !== 'undefined') { | |
obj[property] = oldVal; | |
} | |
} | |
function isSmartProperty(obj, property) { | |
return obj.__bound__ && (property in obj.__bound__); | |
} | |
var tag = 0; | |
function getTag(obj) { | |
if (!('__tag__' in obj)) { | |
obj.__tag__ = (++tag).toString(36); | |
} | |
return obj.__tag__; | |
} | |
// wire data to DOM. | |
function link(obj, property, el, fn) { | |
// resolve selector to element | |
el = getEl(el); | |
var elTag = getTag(el); | |
// set up smartness | |
if (!isSmart(obj)) { | |
makeSmart(obj); | |
} | |
// get an appropriate default handler | |
fn = fn || getOutputFunction(el); | |
if (!isSmartProperty(obj, property)) { | |
makeSmartProperty(obj, property); | |
} | |
// call our handler once to initialize things | |
fn(el, obj[property]); | |
obj.__bound__[property].push([el, fn, elTag]); | |
} | |
function unlink(el) { | |
} | |
function map(obj, el, map) { | |
if (!(el instanceof HTMLElement)) { | |
map = el; | |
el = document.body | |
} | |
if ('set' in map) { | |
var mapping = map.set; | |
for (property in mapping) { | |
var propMap = mapping[property]; | |
if (propMap instanceof Array) { | |
propMap.forEach(singleMappingSet); | |
} else { | |
singleMappingSet(propMap) | |
} | |
} | |
} | |
if ('watch' in map) { | |
var mapping = map.watch; | |
for (property in mapping) { | |
var propMap = mapping[property]; | |
if (propMap instanceof Array) { | |
propMap.forEach(singleMappingWatch); | |
} else { | |
singleMappingWatch(propMap); | |
} | |
} | |
} | |
function singleMappingSet(propMap) { | |
var mapEl; | |
if (typeof propMap === 'object') { | |
mapEl = el.querySelector(propMap.el); | |
if (mapEl) { | |
link(obj, property, mapEl, propMap.method); | |
} | |
} else if (typeof propMap === 'string') { | |
mapEl = el.querySelector(propMap); | |
link(obj, property, mapEl, getOutputFunction(mapEl)); | |
} | |
} | |
function singleMappingWatch(propMap) { | |
var mapEl = el.querySelector(propMap.el); | |
var on = propMap.on; | |
if (mapEl && on) { | |
on = on.split(/\s+/); | |
on.forEach(function (evt) { | |
watch(mapEl, evt, obj, property, propMap.method); | |
}); | |
} | |
} | |
} | |
function getOutputFunction(el) { | |
if (el instanceof HTMLInputElement) { | |
return set.value; | |
} else { | |
return set.text; | |
} | |
} | |
function getInputFunction(el) { | |
if (el instanceof HTMLInputElement) { | |
return get.value; | |
} else { | |
return get.noop; | |
} | |
} | |
function watch(watchEl, evt, o, prop, fn) { | |
watchEl = getEl(watchEl); | |
fn = fn || getInputFunction(watchEl); | |
watchEl.addEventListener(evt, function(e) { | |
o[prop] = fn(e, watchEl); | |
}); | |
} | |
function getEl(sel, searchEl) { | |
searchEl = searchEl || document; | |
if (sel instanceof HTMLElement) { | |
return sel; | |
} else if (typeof sel === 'string') { | |
return searchEl.querySelector(sel); | |
} | |
} | |
function bind(o, el, map) { | |
for (var sel in map) { | |
var links = map[sel]; | |
if (sel === '_') { | |
var els = [el]; | |
} else { | |
var els = el.querySelectorAll(sel); | |
} | |
if (!links || !els) continue; | |
for (var prop in links) { | |
for (var i = 0; i < els.length; i++) { | |
link(o, prop, els[i], links[prop]); | |
} | |
} | |
} | |
el.__data__ = o; | |
} | |
var get = { | |
value: function value(e, el) { | |
return el.value; | |
}, | |
noop: function noop() {} | |
}; | |
var cssCache = {}; | |
var set = { | |
'value': function value(el, v) { | |
el.value = v; | |
}, | |
'css': function css(prop) { | |
if (!(prop in cssCache)) { | |
cssCache[prop] = function(el, v) { | |
el.style.setProperty(prop, v); | |
} | |
} | |
return cssCache[prop]; | |
}, | |
'text': function text(el, v) { | |
el.innerHTML = ''; | |
el.appendChild(document.createTextNode(v)); | |
} | |
}; | |
return { | |
'link' : link, | |
'bind' : bind, | |
'watch': watch, | |
'map' : map, | |
'set' : set, | |
'get' : get | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment