Materialize = {}; Materialize.guid = (function () { function s4() { return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1) } return function () { return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4() } })(); (function ($) { var materialChipsDefaults = { data: [], placeholder: '', secondaryPlaceholder: '', autocompleteOptions: {}, }; $(document).ready(function() { // Handle removal of static chips. $(document).on('click', '.chip .close', function(e){ var $chips = $(this).closest('.chips'); if ($chips.attr('data-initialized')) { return; } $(this).closest('.chip').remove(); }); }); $.fn.material_chip = function (options) { var self = this; this.$el = $(this); this.$document = $(document); this.SELS = { CHIPS: '.chips', CHIP: '.chip', INPUT: 'input', DELETE: '.material-icons', SELECTED_CHIP: '.selected', }; if ('data' === options) { return this.$el.data('chips'); } var curr_options = $.extend({}, materialChipsDefaults, options); self.hasAutocomplete = !$.isEmptyObject(curr_options.autocompleteOptions.data); // Initialize this.init = function() { var i = 0; var chips; self.$el.each(function(){ var $chips = $(this); var chipId = Materialize.guid(); self.chipId = chipId; if (!curr_options.data || !(curr_options.data instanceof Array)) { curr_options.data = []; } $chips.data('chips', curr_options.data); $chips.attr('data-index', i); $chips.attr('data-initialized', true); if (!$chips.hasClass(self.SELS.CHIPS)) { $chips.addClass('chips'); } self.chips($chips, chipId); i++; }); }; this.handleEvents = function() { var SELS = self.SELS; self.$document.off('click.chips-focus', SELS.CHIPS).on('click.chips-focus', SELS.CHIPS, function(e){ $(e.target).find(SELS.INPUT).focus(); }); self.$document.off('click.chips-select', SELS.CHIP).on('click.chips-select', SELS.CHIP, function(e){ var $chip = $(e.target); if ($chip.length) { var wasSelected = $chip.hasClass('selected'); var $chips = $chip.closest(SELS.CHIPS); $(SELS.CHIP).removeClass('selected'); if (!wasSelected) { self.selectChip($chip.index(), $chips); } } }); self.$document.off('keydown.chips').on('keydown.chips', function(e){ if ($(e.target).is('input, textarea')) { return; } // delete var $chip = self.$document.find(SELS.CHIP + SELS.SELECTED_CHIP); var $chips = $chip.closest(SELS.CHIPS); var length = $chip.siblings(SELS.CHIP).length; var index; if (!$chip.length) { return; } if (e.which === 8 || e.which === 46) { e.preventDefault(); index = $chip.index(); self.deleteChip(index, $chips); var selectIndex = null; if ((index + 1) < length) { selectIndex = index; } else if (index === length || (index + 1) === length) { selectIndex = length - 1; } if (selectIndex < 0) selectIndex = null; if (null !== selectIndex) { self.selectChip(selectIndex, $chips); } if (!length) $chips.find('input').focus(); // left } else if (e.which === 37) { index = $chip.index() - 1; if (index < 0) { return; } $(SELS.CHIP).removeClass('selected'); self.selectChip(index, $chips); // right } else if (e.which === 39) { index = $chip.index() + 1; $(SELS.CHIP).removeClass('selected'); if (index > length) { $chips.find('input').focus(); return; } self.selectChip(index, $chips); } }); self.$document.off('focusin.chips', SELS.CHIPS + ' ' + SELS.INPUT).on('focusin.chips', SELS.CHIPS + ' ' + SELS.INPUT, function(e){ var $currChips = $(e.target).closest(SELS.CHIPS); $currChips.addClass('focus'); $currChips.siblings('label, .prefix').addClass('active'); $(SELS.CHIP).removeClass('selected'); }); self.$document.off('focusout.chips', SELS.CHIPS + ' ' + SELS.INPUT).on('focusout.chips', SELS.CHIPS + ' ' + SELS.INPUT, function(e){ var $currChips = $(e.target).closest(SELS.CHIPS); $currChips.removeClass('focus'); // Remove active if empty if ($currChips.data('chips') === undefined || !$currChips.data('chips').length) { $currChips.siblings('label').removeClass('active'); } $currChips.siblings('.prefix').removeClass('active'); }); self.$document.off('keydown.chips-add', SELS.CHIPS + ' ' + SELS.INPUT).on('keydown.chips-add', SELS.CHIPS + ' ' + SELS.INPUT, function(e){ var $target = $(e.target); var $chips = $target.closest(SELS.CHIPS); var chipsLength = $chips.children(SELS.CHIP).length; // enter if (13 === e.which) { // Override enter if autocompleting. if (self.hasAutocomplete && $chips.find('.autocomplete-content.dropdown-content').length && $chips.find('.autocomplete-content.dropdown-content').children().length) { return; } e.preventDefault(); self.addChip({tag: $target.val()}, $chips); $target.val(''); return; } // delete or left if ((8 === e.keyCode || 37 === e.keyCode) && '' === $target.val() && chipsLength) { e.preventDefault(); self.selectChip(chipsLength - 1, $chips); $target.blur(); return; } }); // Click on delete icon in chip. self.$document.off('click.chips-delete', SELS.CHIPS + ' ' + SELS.DELETE).on('click.chips-delete', SELS.CHIPS + ' ' + SELS.DELETE, function(e) { var $target = $(e.target); var $chips = $target.closest(SELS.CHIPS); var $chip = $target.closest(SELS.CHIP); e.stopPropagation(); self.deleteChip($chip.index(), $chips); $chips.find('input').focus(); }); }; this.chips = function($chips, chipId) { $chips.empty(); $chips.data('chips').forEach(function(elem){ $chips.append(self.renderChip(elem)); }); $chips.append($('')); self.setPlaceholder($chips); // Set for attribute for label var label = $chips.next('label'); if (label.length) { label.attr('for', chipId); if ($chips.data('chips')!== undefined && $chips.data('chips').length) { label.addClass('active'); } } // Setup autocomplete if needed. var input = $('#' + chipId); if (self.hasAutocomplete) { curr_options.autocompleteOptions.onAutocomplete = function(val) { self.addChip({tag: val}, $chips); input.val(''); input.focus(); } input.autocomplete(curr_options.autocompleteOptions); } }; /** * Render chip jQuery element. * @param {Object} elem * @return {jQuery} */ this.renderChip = function(elem) { if (!elem.tag) return; var $renderedChip = $('
'); $renderedChip.text(elem.tag); if (elem.image) { $renderedChip.prepend($('').attr('src', elem.image)) } $renderedChip.append($('close')); return $renderedChip; }; this.setPlaceholder = function($chips) { if ($chips.data('chips') !== undefined && $chips.data('chips').length && curr_options.placeholder) { $chips.find('input').prop('placeholder', curr_options.placeholder); } else if (($chips.data('chips') === undefined || !$chips.data('chips').length) && curr_options.secondaryPlaceholder) { $chips.find('input').prop('placeholder', curr_options.secondaryPlaceholder); } }; this.isValid = function($chips, elem) { var chips = $chips.data('chips'); var exists = false; for (var i=0; i < chips.length; i++) { if (chips[i].tag === elem.tag) { exists = true; return; } } return '' !== elem.tag && !exists; }; this.addChip = function(elem, $chips) { if (!self.isValid($chips, elem)) { return; } var $renderedChip = self.renderChip(elem); var newData = []; var oldData = $chips.data('chips'); for (var i = 0; i < oldData.length; i++) { newData.push(oldData[i]); } newData.push(elem); $chips.data('chips', newData); $renderedChip.insertBefore($chips.find('input')); $chips.trigger('chip.add', elem); self.setPlaceholder($chips); }; this.deleteChip = function(chipIndex, $chips) { var chip = $chips.data('chips')[chipIndex]; $chips.find('.chip').eq(chipIndex).remove(); var newData = []; var oldData = $chips.data('chips'); for (var i = 0; i < oldData.length; i++) { if (i !== chipIndex) { newData.push(oldData[i]); } } $chips.data('chips', newData); $chips.trigger('chip.delete', chip); self.setPlaceholder($chips); }; this.selectChip = function(chipIndex, $chips) { var $chip = $chips.find('.chip').eq(chipIndex); if ($chip && false === $chip.hasClass('selected')) { $chip.addClass('selected'); $chips.trigger('chip.select', $chips.data('chips')[chipIndex]); } }; this.getChipsElement = function(index, $chips) { return $chips.eq(index); }; // init this.init(); this.handleEvents(); }; }( jQuery ));