var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } (function ($) { 'use strict'; var _defaults = { classes: '' }; /** * @class * */ var Select = function (_Component) { _inherits(Select, _Component); /** * Construct Select instance * @constructor * @param {Element} el * @param {Object} options */ function Select(el, options) { _classCallCheck(this, Select); var _this = _possibleConstructorReturn(this, (Select.__proto__ || Object.getPrototypeOf(Select)).call(this, Select, el, options)); _this.el.M_Select = _this; /** * Options for the select * @member Select#options */ _this.options = $.extend({}, Select.defaults, options); _this.isMultiple = _this.$el.prop('multiple'); // Setup _this._keysSelected = {}; _this._valueDict = {}; // Maps key to original and generated option element. _this._setupDropdown(); _this._setupEventHandlers(); return _this; } _createClass(Select, [{ key: 'destroy', /** * Teardown component */ value: function destroy() { this._removeEventHandlers(); this._removeDropdown(); this.el.M_Select = undefined; } /** * Setup Event Handlers */ }, { key: '_setupEventHandlers', value: function _setupEventHandlers() { var _this2 = this; this._handleSelectChangeBound = this._handleSelectChange.bind(this); this._handleOptionClickBound = this._handleOptionClick.bind(this); this._handleInputClickBound = this._handleInputClick.bind(this); $(this.dropdownOptions).find('li:not(.optgroup)').each(function (el) { el.addEventListener('click', _this2._handleOptionClickBound); }); this.el.addEventListener('change', this._handleSelectChangeBound); this.input.addEventListener('click', this._handleInputClickBound); } /** * Remove Event Handlers */ }, { key: '_removeEventHandlers', value: function _removeEventHandlers() { var _this3 = this; $(this.dropdownOptions).find('li:not(.optgroup)').each(function (el) { el.removeEventListener('click', _this3._handleOptionClickBound); }); this.el.removeEventListener('change', this._handleSelectChangeBound); this.input.removeEventListener('click', this._handleInputClickBound); this.input.removeEventListener('focus', this._handleInputFocusBound); } /** * Handle Select Change * @param {Event} e */ }, { key: '_handleSelectChange', value: function _handleSelectChange(e) { this._setValueToInput(); } /** * Handle Option Click * @param {Event} e */ }, { key: '_handleOptionClick', value: function _handleOptionClick(e) { e.preventDefault(); var option = $(e.target).closest('li')[0]; var key = option.id; if (!$(option).hasClass('disabled') && !$(option).hasClass('optgroup') && key.length) { var selected = true; if (this.isMultiple) { // Deselect placeholder option if still selected. var placeholderOption = $(this.dropdownOptions).find('li.disabled.selected'); if (placeholderOption.length) { placeholderOption.removeClass('selected'); placeholderOption.find('input[type="checkbox"]').prop('checked', false); this._toggleEntryFromArray(placeholderOption[0].id); } var checkbox = $(option).find('input[type="checkbox"]'); checkbox.prop('checked', !checkbox.prop('checked')); selected = this._toggleEntryFromArray(key); } else { $(this.dropdownOptions).find('li').removeClass('active'); $(option).toggleClass('active'); this.input.value = option.textContent; } this._activateOption($(this.dropdownOptions), option); $(this._valueDict[key].el).prop('selected', selected); this.$el.trigger('change'); } e.stopPropagation(); } /** * Handle Input Click */ }, { key: '_handleInputClick', value: function _handleInputClick() { if (this.dropdown && this.dropdown.isOpen) { this._setValueToInput(); this._setSelectedStates(); } } /** * Setup dropdown */ }, { key: '_setupDropdown', value: function _setupDropdown() { var _this4 = this; this.wrapper = document.createElement('div'); $(this.wrapper).addClass('select-wrapper' + ' ' + this.options.classes); this.$el.before($(this.wrapper)); this.wrapper.appendChild(this.el); if (this.el.disabled) { this.wrapper.classList.add('disabled'); } // Create dropdown this.$selectOptions = this.$el.children('option, optgroup'); this.dropdownOptions = document.createElement('ul'); this.dropdownOptions.id = 'select-options-' + M.guid(); $(this.dropdownOptions).addClass('dropdown-content select-dropdown ' + (this.isMultiple ? 'multiple-select-dropdown' : '')); // Create dropdown structure. if (this.$selectOptions.length) { this.$selectOptions.each(function (el) { if ($(el).is('option')) { // Direct descendant option. var optionEl = void 0; if (_this4.isMultiple) { optionEl = _this4._appendOptionWithIcon(_this4.$el, el, 'multiple'); } else { optionEl = _this4._appendOptionWithIcon(_this4.$el, el); } _this4._addOptionToValueDict(el, optionEl); } else if ($(el).is('optgroup')) { // Optgroup. var selectOptions = $(el).children('option'); $(_this4.dropdownOptions).append($('
  • ' + el.getAttribute('label') + '
  • ')[0]); selectOptions.each(function (el) { var optionEl = _this4._appendOptionWithIcon(_this4.$el, el, 'optgroup-option'); _this4._addOptionToValueDict(el, optionEl); }); } }); } this.$el.after(this.dropdownOptions); // Add input dropdown this.input = document.createElement('input'); $(this.input).addClass('select-dropdown dropdown-trigger'); this.input.setAttribute('type', 'text'); this.input.setAttribute('readonly', 'true'); this.input.setAttribute('data-target', this.dropdownOptions.id); if (this.el.disabled) { $(this.input).prop('disabled', 'true'); } this.$el.before(this.input); this._setValueToInput(); // Add caret var dropdownIcon = $(''); this.$el.before(dropdownIcon[0]); // Initialize dropdown if (!this.el.disabled) { var dropdownOptions = {}; if (this.isMultiple) { dropdownOptions.closeOnClick = false; } this.dropdown = M.Dropdown.init(this.input, dropdownOptions); } // Add initial selections this._setSelectedStates(); } /** * Add option to value dict * @param {Element} el original option element * @param {Element} optionEl generated option element */ }, { key: '_addOptionToValueDict', value: function _addOptionToValueDict(el, optionEl) { var index = Object.keys(this._valueDict).length; var key = this.dropdownOptions.id + index; var obj = {}; optionEl.id = key; obj.el = el; obj.optionEl = optionEl; this._valueDict[key] = obj; } /** * Remove dropdown */ }, { key: '_removeDropdown', value: function _removeDropdown() { $(this.wrapper).find('.caret').remove(); $(this.input).remove(); $(this.dropdownOptions).remove(); $(this.wrapper).before(this.$el); $(this.wrapper).remove(); } /** * Setup dropdown * @param {Element} select select element * @param {Element} option option element from select * @param {String} type * @return {Element} option element added */ }, { key: '_appendOptionWithIcon', value: function _appendOptionWithIcon(select, option, type) { // Add disabled attr if disabled var disabledClass = option.disabled ? 'disabled ' : ''; var optgroupClass = type === 'optgroup-option' ? 'optgroup-option ' : ''; var multipleCheckbox = this.isMultiple ? '' : option.innerHTML; var liEl = $('
  • '); var spanEl = $(''); spanEl.html(multipleCheckbox); liEl.addClass(disabledClass + ' ' + optgroupClass); liEl.append(spanEl); // add icons var iconUrl = option.getAttribute('data-icon'); var classes = option.getAttribute('class'); if (!!iconUrl) { var imgEl = $(''); liEl.prepend(imgEl); } // Check for multiple type. $(this.dropdownOptions).append(liEl[0]); return liEl[0]; } /** * Toggle entry from option * @param {String} key Option key * @return {Boolean} if entry was added or removed */ }, { key: '_toggleEntryFromArray', value: function _toggleEntryFromArray(key) { var notAdded = !this._keysSelected.hasOwnProperty(key); if (notAdded) { this._keysSelected[key] = true; } else { delete this._keysSelected[key]; } $(this._valueDict[key].optionEl).toggleClass('active'); // use notAdded instead of true (to detect if the option is selected or not) $(this._valueDict[key].el).prop('selected', notAdded); return notAdded; } /** * Set value to input */ }, { key: '_setValueToInput', value: function _setValueToInput() { var value = ''; var options = this.$el.find('option'); options.each(function (el) { if ($(el).prop('selected')) { var text = $(el).text(); value === '' ? value += text : value += ', ' + text; } }); if (value === '') { var firstDisabled = this.$el.find('option:disabled').eq(0); if (firstDisabled.length) { value = firstDisabled.text(); } } this.input.value = value; } /** * Set selected state of dropdown too match actual select element */ }, { key: '_setSelectedStates', value: function _setSelectedStates() { this._keysSelected = {}; for (var key in this._valueDict) { var option = this._valueDict[key]; if ($(option.el).prop('selected')) { $(option.optionEl).find('input[type="checkbox"]').prop("checked", true); this._activateOption($(this.dropdownOptions), $(option.optionEl)); this._keysSelected[key] = true; } else { $(option.optionEl).find('input[type="checkbox"]').prop("checked", false); $(option.optionEl).removeClass('selected'); } } } /** * Make option as selected and scroll to selected position * @param {jQuery} collection Select options jQuery element * @param {Element} newOption element of the new option */ }, { key: '_activateOption', value: function _activateOption(collection, newOption) { if (newOption) { if (!this.isMultiple) { collection.find('li.selected').removeClass('selected'); } var option = $(newOption); option.addClass('selected'); } } /** * Get Selected Values * @return {Array} Array of selected values */ }, { key: 'getSelectedValues', value: function getSelectedValues() { var selectedValues = []; for (var key in this._keysSelected) { selectedValues.push(this._valueDict[key].el.value); } return selectedValues; } }], [{ key: 'init', value: function init(els, options) { return _get(Select.__proto__ || Object.getPrototypeOf(Select), 'init', this).call(this, this, els, options); } /** * Get Instance */ }, { key: 'getInstance', value: function getInstance(el) { var domElem = !!el.jquery ? el[0] : el; return domElem.M_Select; } }, { key: 'defaults', get: function () { return _defaults; } }]); return Select; }(Component); M.Select = Select; if (M.jQueryLoaded) { M.initializeJqueryWrapper(Select, 'select', 'M_Select'); } })(cash);