treant
Version:
Dependency free component library for the browser
115 lines (99 loc) • 3.29 kB
JavaScript
var camelcase = require("camelcase")
var COMPONENT_ATTRIBUTE = "data-component"
var hook = module.exports = {}
hook.setHookAttribute = setHookAttribute
hook.selector = selector
hook.findComponent = findComponent
hook.findAllComponents = findAllComponents
hook.findSubComponents = findSubComponents
hook.getComponentName = getComponentName
hook.getMainComponentName = getMainComponentName
hook.getSubComponentName = getSubComponentName
hook.assignSubComponents = assignSubComponents
hook.filter = filter
function setHookAttribute (hook) {
COMPONENT_ATTRIBUTE = hook
}
function selector (name, operator, extra) {
name = name && '"' + name + '"'
operator = name ? operator || "=" : ""
extra = extra || ""
return "[" + COMPONENT_ATTRIBUTE + operator + name + "]" + extra
}
function find (selector, root) {
return (root || document).querySelector(selector)
}
function findAll (selector, root) {
return (root || document).querySelectorAll(selector)
}
function findComponent (name, root) {
return find(selector(name), root)
}
function findAllComponents (name, root) {
return [].slice.call(findAll(selector(name), root))
}
function getComponentName (element, cc) {
if (!element) return ""
cc = cc == undefined || cc
var value = typeof element == "string" ? element : element.getAttribute(COMPONENT_ATTRIBUTE) || ""
return cc ? camelcase(value) : value
}
function getMainComponentName (element, cc) {
cc = cc == undefined || cc
var value = getComponentName(element, false).split(":")
value = value[0] || ""
return cc && value ? camelcase(value) : value
}
function getSubComponentName (element, cc) {
cc = cc == undefined || cc
var value = getComponentName(element, false).split(":")
value = value[1] || ""
return cc && value ? camelcase(value) : value
}
function getComponentNameList (element, cc) {
return getComponentName(element, cc).split(/\s+/)
}
function findSubComponents (mainName, root) {
var elements = findAll(selector(mainName+":", "*="), root)
return filter(elements, function (element, componentName) {
return getComponentNameList(componentName, false).some(function (name) {
return getMainComponentName(name, false) == mainName && getSubComponentName(name)
})
})
}
function assignSubComponents (obj, subComponents, transform, assign) {
return subComponents.reduce(function (obj, element) {
getComponentNameList(element, false).forEach(function (name) {
var subName = getSubComponentName(name, true)
element = typeof transform == "function"
? transform(element, name)
: element
if (typeof assign == "function") {
assign(obj, subName, element)
}
else if (Array.isArray(obj[subName])) {
obj[subName].push(element)
}
else {
obj[subName] = element
}
})
return obj
}, obj)
}
function filter (elements, filter) {
switch (typeof filter) {
case "function":
return [].slice.call(elements).filter(function (element) {
return filter(element, getComponentName(element, false))
})
break
case "string":
return [].slice.call(elements).filter(function (element) {
return getComponentName(element) === filter
})
break
default:
return null
}
}