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; } }