static/js/com/dropdown/index.js (93 lines of code) (raw):

var $ = require('jquery'); var Emitter = require('event-emitter'); require('./styles.scss'); var CLASSES = { OPENED: '_opened', ITEM_SELECTED: '_selected' }; var EVENTS = { SELECT: 'select' }; /** * @param {HTMLElement|string} node * @param {Object} config * @param {number} [config.selectedIndex=0] * @param {string} [config.selected] * @param {Function} [config.onSelect] * @constructor */ function Dropdown(node, config) { if (!(this instanceof Dropdown)) return new Dropdown(node, config); this._emitter = Emitter({}); var that = this; this.config = config; var $dropdown = this.render(); this.$dropdown = $dropdown; var $items = $dropdown.find('.js-item'); var selectedValueNode = $dropdown.find('.js-selected-value').get(0); $(document.body).on('click', function(event) { event.target === selectedValueNode ? that.toggle() : that.close(); }); $items.each(function (i, elem) { const $elem = $(elem); if($elem.attr('data-value') == config.selected){ config.selectedIndex = i; } $elem.on('click', that.select.bind(that, i)); }); $(node).append($dropdown); config.onSelect && this.onSelect(config.onSelect); this.select(config.selectedIndex || 0, false); } Dropdown.prototype.onSelect = function (callback) { this._emitter.on(EVENTS.SELECT, callback); }; Dropdown.prototype.render = function () { var config = this.config; var data = $.extend({}, { items: config.items, selectedIndex: config.selectedIndex || 0 }); return $(renderTemplate(data)); }; Dropdown.prototype.open = function () { this.$dropdown.addClass(CLASSES.OPENED); }; Dropdown.prototype.close = function () { this.$dropdown.removeClass(CLASSES.OPENED); }; Dropdown.prototype.toggle = function() { this.isOpened() ? this.close() : this.open(); }; Dropdown.prototype.isOpened = function () { return this.$dropdown.hasClass(CLASSES.OPENED); }; Dropdown.prototype.select = function (index, emit) { if (this.selectedIndex == index) { return; } this.selectedIndex = index; var emit = typeof emit == 'boolean' ? emit : true; var $dropdown = this.$dropdown; var $items = $dropdown.find('.js-item'); var $selectedItem = $( $items.get(index) ); var selectedValue = $selectedItem.attr('data-value'); var selectedText = $selectedItem.text(); $items.each(function (i, elem) { var $item = $(elem); if (i === index) $item.addClass(CLASSES.ITEM_SELECTED); else $item.removeClass(CLASSES.ITEM_SELECTED); }); $dropdown.find('.js-selected-value').text(selectedText); emit && this._emitter.emit('select', selectedValue); }; function renderTemplate(dropdown) { let items = ''; for (const [key, value] of Object.entries(dropdown.items)) { items += `<div class="dropdown-item js-item" data-value="${key}">${value}</div>`; } return ` <div class="dropdown js-dropdown"> <div class="dropdown-selected-value js-selected-value">${dropdown.items[dropdown.selectedIndex]}</div> <div class="dropdown-items">${items}</div> </div> `; } module.exports = Dropdown;