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 = { data: [], placeholder: '', secondaryPlaceholder: '', autocompleteOptions: {}, limit: Infinity, onChipAdd: null, onChipSelect: null, onChipDelete: null }; /** * @typedef {Object} chip * @property {String} tag chip tag string * @property {String} [image] chip avatar image string */ /** * @class * */ var Chips = function (_Component) { _inherits(Chips, _Component); /** * Construct Chips instance and set up overlay * @constructor * @param {Element} el * @param {Object} options */ function Chips(el, options) { _classCallCheck(this, Chips); var _this = _possibleConstructorReturn(this, (Chips.__proto__ || Object.getPrototypeOf(Chips)).call(this, Chips, el, options)); _this.el.M_Chips = _this; /** * Options for the modal * @member Chips#options * @prop {Array} data * @prop {String} placeholder * @prop {String} secondaryPlaceholder * @prop {Object} autocompleteOptions */ _this.options = $.extend({}, Chips.defaults, options); _this.$el.addClass('chips input-field'); _this.chipsData = []; _this.$chips = $(); _this._setupInput(); _this.hasAutocomplete = Object.keys(_this.options.autocompleteOptions).length > 0; // Set input id if (!_this.$input.attr('id')) { _this.$input.attr('id', M.guid()); } // Render initial chips if (_this.options.data.length) { _this.chipsData = _this.options.data; _this._renderChips(_this.chipsData); } // Setup autocomplete if needed if (_this.hasAutocomplete) { _this._setupAutocomplete(); } _this._setPlaceholder(); _this._setupLabel(); _this._setupEventHandlers(); return _this; } _createClass(Chips, [{ key: 'getData', /** * Get Chips Data */ value: function getData() { return this.chipsData; } /** * Teardown component */ }, { key: 'destroy', value: function destroy() { this._removeEventHandlers(); this.$chips.remove(); this.el.M_Chips = undefined; } /** * Setup Event Handlers */ }, { key: '_setupEventHandlers', value: function _setupEventHandlers() { this._handleChipClickBound = this._handleChipClick.bind(this); this._handleInputKeydownBound = this._handleInputKeydown.bind(this); this._handleInputFocusBound = this._handleInputFocus.bind(this); this._handleInputBlurBound = this._handleInputBlur.bind(this); this.el.addEventListener('click', this._handleChipClickBound); document.addEventListener('keydown', Chips._handleChipsKeydown); document.addEventListener('keyup', Chips._handleChipsKeyup); this.el.addEventListener('blur', Chips._handleChipsBlur, true); this.$input[0].addEventListener('focus', this._handleInputFocusBound); this.$input[0].addEventListener('blur', this._handleInputBlurBound); this.$input[0].addEventListener('keydown', this._handleInputKeydownBound); } /** * Remove Event Handlers */ }, { key: '_removeEventHandlers', value: function _removeEventHandlers() { this.el.removeEventListener('click', this._handleChipClickBound); document.removeEventListener('keydown', Chips._handleChipsKeydown); document.removeEventListener('keyup', Chips._handleChipsKeyup); this.el.removeEventListener('blur', Chips._handleChipsBlur, true); this.$input[0].removeEventListener('focus', this._handleInputFocusBound); this.$input[0].removeEventListener('blur', this._handleInputBlurBound); this.$input[0].removeEventListener('keydown', this._handleInputKeydownBound); } /** * Handle Chip Click * @param {Event} e */ }, { key: '_handleChipClick', value: function _handleChipClick(e) { var $chip = $(e.target).closest('.chip'); var clickedClose = $(e.target).is('.close'); if ($chip.length) { var index = $chip.index(); if (clickedClose) { // delete chip this.deleteChip(index); this.$input[0].focus(); } else { // select chip this.selectChip(index); } // Default handle click to focus on input } else { this.$input[0].focus(); } } /** * Handle Chips Keydown * @param {Event} e */ }, { key: '_handleInputFocus', /** * Handle Input Focus */ value: function _handleInputFocus() { this.$el.addClass('focus'); } /** * Handle Input Blur */ }, { key: '_handleInputBlur', value: function _handleInputBlur() { this.$el.removeClass('focus'); } /** * Handle Input Keydown * @param {Event} e */ }, { key: '_handleInputKeydown', value: function _handleInputKeydown(e) { Chips._keydown = true; // enter if (e.keyCode === 13) { // Override enter if autocompleting. if (this.hasAutocomplete && this.autocomplete && this.autocomplete.isOpen) { return; } e.preventDefault(); this.addChip({ tag: this.$input[0].value }); this.$input[0].value = ''; // delete or left } else if ((e.keyCode === 8 || e.keyCode === 37) && this.$input[0].value === '' && this.chipsData.length) { e.preventDefault(); this.selectChip(this.chipsData.length - 1); } } /** * Render Chip * @param {chip} chip * @return {Element} */ }, { key: '_renderChip', value: function _renderChip(chip) { if (!chip.tag) { return; } var renderedChip = document.createElement('div'); var closeIcon = document.createElement('i'); renderedChip.classList.add('chip'); renderedChip.textContent = chip.tag; renderedChip.setAttribute('tabindex', 0); $(closeIcon).addClass('material-icons close'); closeIcon.textContent = 'close'; // attach image if needed if (chip.image) { var img = document.createElement('img'); img.setAttribute('src', chip.image); renderedChip.insertBefore(img, renderedChip.firstChild); } renderedChip.appendChild(closeIcon); return renderedChip; } /** * Render Chips */ }, { key: '_renderChips', value: function _renderChips() { this.$chips.remove(); for (var i = 0; i < this.chipsData.length; i++) { var chipEl = this._renderChip(this.chipsData[i]); this.$el.append(chipEl); this.$chips.add(chipEl); } // move input to end this.$el.append(this.$input[0]); } /** * Setup Autocomplete */ }, { key: '_setupAutocomplete', value: function _setupAutocomplete() { var _this2 = this; this.options.autocompleteOptions.onAutocomplete = function (val) { _this2.addChip({ tag: val }); _this2.$input[0].value = ''; _this2.$input[0].focus(); }; this.autocomplete = M.Autocomplete.init(this.$input, this.options.autocompleteOptions)[0]; } /** * Setup Input */ }, { key: '_setupInput', value: function _setupInput() { this.$input = this.$el.find('input'); if (!this.$input.length) { this.$input = $(''); this.$el.append(this.$input); } this.$input.addClass('input'); } /** * Setup Label */ }, { key: '_setupLabel', value: function _setupLabel() { this.$label = this.$el.find('label'); if (this.$label.length) { this.$label.setAttribute('for', this.$input.attr('id')); } } /** * Set placeholder */ }, { key: '_setPlaceholder', value: function _setPlaceholder() { if (this.chipsData !== undefined && !this.chipsData.length && this.options.placeholder) { $(this.$input).prop('placeholder', this.options.placeholder); } else if ((this.chipsData === undefined || !!this.chipsData.length) && this.options.secondaryPlaceholder) { $(this.$input).prop('placeholder', this.options.secondaryPlaceholder); } } /** * Check if chip is valid * @param {chip} chip */ }, { key: '_isValid', value: function _isValid(chip) { if (chip.hasOwnProperty('tag') && chip.tag !== '') { var exists = false; for (var i = 0; i < this.chipsData.length; i++) { if (this.chipsData[i].tag === chip.tag) { exists = true; break; } } return !exists; } return false; } /** * Add chip * @param {chip} chip */ }, { key: 'addChip', value: function addChip(chip) { if (!this._isValid(chip) || this.chipsData.length >= this.options.limit) { return; } var renderedChip = this._renderChip(chip); this.$chips.add(renderedChip); this.chipsData.push(chip); $(this.$input).before(renderedChip); this._setPlaceholder(); // fire chipAdd callback if (typeof this.options.onChipAdd === 'function') { this.options.onChipAdd.call(this, this.$el, renderedChip); } } /** * Delete chip * @param {Number} chip */ }, { key: 'deleteChip', value: function deleteChip(chipIndex) { var $chip = this.$chips.eq(chipIndex); this.$chips.eq(chipIndex).remove(); this.$chips = this.$chips.filter(function (el) { return $(el).index() >= 0; }); this.chipsData.splice(chipIndex, 1); this._setPlaceholder(); // fire chipDelete callback if (typeof this.options.onChipDelete === 'function') { this.options.onChipDelete.call(this, this.$el, $chip[0]); } } /** * Select chip * @param {Number} chip */ }, { key: 'selectChip', value: function selectChip(chipIndex) { var $chip = this.$chips.eq(chipIndex); this._selectedChip = $chip; $chip[0].focus(); // fire chipSelect callback if (typeof this.options.onChipSelect === 'function') { this.options.onChipSelect.call(this, this.$el, $chip[0]); } } }], [{ key: 'init', value: function init(els, options) { return _get(Chips.__proto__ || Object.getPrototypeOf(Chips), '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_Chips; } }, { key: '_handleChipsKeydown', value: function _handleChipsKeydown(e) { Chips._keydown = true; var $chips = $(e.target).closest('.chips'); var chipsKeydown = e.target && $chips.length; // Don't handle keydown inputs on input and textarea if ($(e.target).is('input, textarea') || !chipsKeydown) { return; } var currChips = $chips[0].M_Chips; // backspace and delete if (e.keyCode === 8 || e.keyCode === 46) { e.preventDefault(); var selectIndex = currChips.chipsData.length; if (currChips._selectedChip) { var index = currChips._selectedChip.index(); currChips.deleteChip(index); currChips._selectedChip = null; selectIndex = index - 1; } if (currChips.chipsData.length) { currChips.selectChip(selectIndex); } // left arrow key } else if (e.keyCode === 37) { if (currChips._selectedChip) { var _selectIndex = currChips._selectedChip.index() - 1; if (_selectIndex < 0) { return; } currChips.selectChip(_selectIndex); } // right arrow key } else if (e.keyCode === 39) { if (currChips._selectedChip) { var _selectIndex2 = currChips._selectedChip.index() + 1; if (_selectIndex2 >= currChips.chipsData.length) { currChips.$input[0].focus(); } else { currChips.selectChip(_selectIndex2); } } } } /** * Handle Chips Keyup * @param {Event} e */ }, { key: '_handleChipsKeyup', value: function _handleChipsKeyup(e) { Chips._keydown = false; } /** * Handle Chips Blur * @param {Event} e */ }, { key: '_handleChipsBlur', value: function _handleChipsBlur(e) { if (!Chips._keydown) { var $chips = $(e.target).closest('.chips'); var currChips = $chips[0].M_Chips; currChips._selectedChip = null; } } }, { key: 'defaults', get: function () { return _defaults; } }]); return Chips; }(Component); /** * @static * @memberof Chips */ Chips._keydown = false; M.Chips = Chips; if (M.jQueryLoaded) { M.initializeJqueryWrapper(Chips, 'chips', 'M_Chips'); } $(document).on('ready turbolinks:load', function () { // Handle removal of static chips. $(document.body).on('click', '.chip .close', function () { var $chips = $(this).closest('.chips'); if ($chips.length && $chips[0].M_Chips) { return; } $(this).closest('.chip').remove(); }); }); })(cash);