function Dropdown(target, obj, returnCB) {
'use strict';
// borrowed for now
function getElementFromString(s, tmplArgs) {
var d = document.createElement('div');
d.innerHTML = !!tmplArgs ? render(s, tmplArgs) : s;
return d.childNodes[0];
}
var defaultOptions = getDefaultOptions(),
events = new EventManager,
template = new Template,
options = new Options(obj.options || {}),
data = new Data(obj),
render = (new itsMustache()).render,
element = getElementFromString(render(template.index, getRenderObject())),
elements = new Elements(element, {
'displayItem': {
'selector': 'display-item'
},
'carrot': {},
'menuItems': {
'selector': 'menu-items'
}
}),
state = false,
currentValue = null;
init();
this.set = setValue;
this.setValue = setValue;
this.setByValue = setByValue;
this.get = getValue;
this.exit = exit;
this.ele = element;
this.openMenu = openMenu;
this.closeMenu = closeMenu;
this.toggleMenu = toggleMenu;
function Data(o) {
this.items = getItems(o);
this.displayIndex = 0;
}
function Options(o) {
this.dropdownClass = o.dropdownClass || defaultOptions.dropdownClass;
this.menuItemClass = o.menuItemClass || defaultOptions.menuItemClass;
this.carrotClass = o.carrotClass || defaultOptions.carrotClass;
this.staticMenu = o.staticMenu;
}
function Item(o, i) {
var href = o.href !== undefined ? o.href : null;
this.title = o.title;
this.index = i;
this.placeholder = o.placeholder;
this.element = null;
this.className = options.menuItemClass;
this.setElement = setElement;
this.value = o.value !== undefined ? o.value : null;
function setElement(e) {
this.element = e;
if (o.placeholder) return;
events.add(e, 'click', clickAction);
}
function clickAction() {
if (isClickItem()) itemClick(i);
else if (href !== null) navigate(href, i);
else if (returnCB) returnCB(getReturnValue(i));
}
function isClickItem() {
if (href !== null) return false;
else if (options.staticMenu || o.placeholder) return false;
else return true;
}
}
function Template() {
var menuAnchor = '{{ title }}',
menuP = '
{{ title }}
',
children = '{{# children }}{{> multiDropdownMenuItem }}{{/ children }}',
menuItem = '{{# hrefState }}' + menuAnchor + '{{/ hrefState }}{{^ hrefState }}' + menuP + '{{/ hrefState }}{{# childrenState }}' + children + '{{/ childrenState }}',
displayItem = '{{# displayItem }}' + menuItem + '{{/ displayItem }}',
items = '{{# menuItems }}' + menuItem + '{{/ menuItems }}';
this.index = '' + displayItem + items + '';
}
function init() {
setCarrot();
processItems();
bindDisplayItem();
target.appendChild(element);
if (obj.initialValue != null) setByValue(obj.initialValue);
}
function processItems() {
loop(element.querySelectorAll('menu-item'), process);
function process(i, item) {
data.items[i].setElement(item);
}
}
function insertItems(d, m) {
inBeforeTheCarrot(d);
elements.menuItems.appendChild(m);
}
function inBeforeTheCarrot(t) {
elements.displayItem.insertBefore(t, elements.carrot);
}
function bindDisplayItem() {
events.add(elements.displayItem, 'click', toggleMenu);
}
function windowClick(e) {
if (!isParentOfTarget(element, e.target)) closeMenu();
}
function itemClick(nI) {
var d = data;
if (nI !== d.displayIndex) updateMenu(d, nI);
}
function setValue(i) {
if (i < data.items.length && i > -1) updateMenu(data, i);
}
function getValue() {
return currentValue;
}
function setByValue(v) {
var items = data.items,
l = items.length - 1,
c = l;
while (c > -1) {
var item = items[l - c];
if (item.value === v) {
setValue(item.index);
return true;
} else c--;
}
return false;
}
function navigate(href, i) {
closeMenu();
pop('Pop!', 'Dashboard', href);
if (returnCB) returnCB(getReturnValue(i));
}
function toggleMenu() {
if (!state) openMenu();
else closeMenu();
}
function openMenu() {
element.classList.add('active');
state = true;
events.add(window, 'click', windowClick, 'window');
}
function closeMenu() {
element.classList.remove('active');
state = false;
events.removeByTag('window');
}
function updateMenu(d, nI) {
var f = getFragment();
d.displayIndex = nI;
closeMenu();
loop(d.items, process);
insertItems(d.items[nI].element, f);
currentValue = getReturnValue(nI);
if (returnCB) returnCB(getReturnValue(nI));
function process(i, item) {
if (i !== nI) {
if (item.placeholder !== true) f.appendChild(item.element);
else if (nI !== 0) removeChild(elements.displayItem, item.element);
}
}
}
function getReturnValue(i) {
var t = data.items[i];
return t.value != null ? t.value : t.title;
}
function getPlaceholderObj(text) {
return {
'title': text,
'placeholder': true
};
}
function getDefaultOptions() {
return {
'dropdownClass': 'cool',
'menuItemClass': 'cool',
'carrotClass': null
};
}
function getDisplayItem() {
return data.items[data.displayIndex];
}
function getMenuItems() {
var d = data,
a = [];
loop(d.items, p);
return a;
function p(i, t) {
if (i != d.displayIndex && t.placeholder !== true) a.push(t);
}
}
function getRenderObject() {
return {
'displayItem': getDisplayItem(),
'menuItems': getMenuItems(),
'dropdownClass': options.dropdownClass,
'carrotClass': options.carrotClass
};
}
function getItems(o) {
var a = [],
c = 0,
p = o.placeholder;
if (p != null) p(getPlaceholderObj(p));
loop(o.data, r);
return a;
function r(_, t) {
a.push(new Item(t, c++));
}
}
function setCarrot() {
elements.carrot = elements.displayItem.childNodes[1];
}
function exit() {
events.reset();
if (elements) removeElements();
housekeeping();
}
function removeElements() {
elements.exit();
elements = null;
removeChild(target, element);
element = null;
}
function housekeeping() {
target = obj = returnCB = defaultOptions = events = template = options = data = element = elements = null;
}
}