/* * EasyAutocomplete * jQuery plugin for autocompletion * * @author Łukasz Pawełczak * @version 1.0.0 * Copyright MIT License: https://github.com/pawelczak/easy-autocomplete/blob/master/LICENSE.txt */ /* * EasyAutocomplete - Configuration */ var EasyAutocomplete = (function(scope){ scope.Configuration = function Configuration(options) { var defaults = { data: "list-required", url: "list-required", dataType: "json", listLocation: function(data) { return data; }, xmlElementName: "", getValue: function(element) { return element; }, autocompleteOff: true, placeholder: false, ajaxCallback: function() {}, list: { sort: { enabled: false, method: function(a, b) { a = defaults.getValue(a); b = defaults.getValue(b); if (a < b) { return -1; } if (a > b) { return 1; } return 0; } }, maxNumberOfElements: 6, match: { enabled: false, caseSensitive: false, method: function(a, b) { a = defaults.getValue(a); b = defaults.getValue(b); if (a === b){ return true; } return false; } }, showAnimation: { type: "normal", //normal|slide|fade time: 400, callback: function() {} }, hideAnimation: { type: "normal", time: 400, callback: function() {} } }, highlightPhrase: true, theme: "", cssClasses: "" }; prepareDefaults(); mergeOptions(); processAfterMerge(); this.get = function(propertyName) { return defaults[propertyName]; }; this.equals = function(name, value) { if (isAssigned(name)) { if (defaults[name] === value) { return true; } } return false; }; this.checkDataUrlProperties = function() { if (defaults.url === "list-required" && defaults.data === "list-required") { return false; } return true; }; this.checkRequiredProperties = function() { for (var propertyName in defaults) { if (defaults[propertyName] === "required") { logger.error("Option " + propertyName + " must be defined"); return false; } } return true; }; function prepareDefaults() { if (options.dataType === "xml") { if (!options.getValue) { options.getValue = function(element) { return $(element).text(); }; } if (!options.list) { options.list = {}; } if (!options.list.sort) { options.list.sort = {}; } options.list.sort.method = function(a, b) { a = options.getValue(a); b = options.getValue(b); if (a < b) { return -1; } if (a > b) { return 1; } return 0; }; if (!options.list.match) { options.list.match = {}; } options.list.match.method = function(a, b) { a = options.getValue(a); b = options.getValue(b); if (a === b){ return true; } return false; }; } } function mergeOptions() { defaults = mergeObjects(defaults, options); function mergeObjects(source, target) { var mergedObject = source || {}; for (var propertyName in source) { if (target[propertyName] !== undefined && target[propertyName] !== null) { if (typeof target[propertyName] !== "object" || target[propertyName] instanceof Array) { mergedObject[propertyName] = target[propertyName]; } else { mergeObjects(source[propertyName], target[propertyName]); } } } return mergedObject; } } function processAfterMerge() { if (defaults.url !== "list-required" && typeof defaults.url !== "function") { var defaultUrl = defaults.url; defaults.url = function() { return defaultUrl; }; } if (typeof defaults.listLocation === "string") { var defaultlistLocation = defaults.listLocation; defaults.listLocation = function(data) { return data[defaultlistLocation]; }; } if (typeof defaults.getValue === "string") { var defaultsGetValue = defaults.getValue; defaults.getValue = function(element) { return element[defaultsGetValue]; }; } } function isAssigned(name) { if (defaults[name] !== undefined && defaults[name] !== null) { return true; } else { return false; } } }; return scope; })(EasyAutocomplete || {}); /* * EasyAutocomplete - Logger */ var EasyAutocomplete = (function(scope){ scope.Logger = function Logger() { var logger = {}; this.error = function(message) { console.log("ERROR: " + message); } this.warning = function(message) { console.log("WARNING: " + message); } }; return scope; })(EasyAutocomplete || {}); /* * EasyAutocomplete - Constans */ var EasyAutocomplete = (function(scope){ scope.Constans = function Constans() { var constants = { CONTAINER_CLASS: "easy-autocomplete-container", CONTAINER_ID: "eac-container-", WRAPPER_CSS_CLASS: "easy-autocomplete" }; this.getValue = function(propertyName) { return constants[propertyName]; }; }; return scope; })(EasyAutocomplete || {}); /* * EasyAutocomplete - Data proccess module * * Process list to display: * - sort * - decrease number to specific number * - show only matching list * */ var EasyAutocomplete = (function(scope) { scope.proccess = function proccessData(config, list, phrase) { var inputPhrase = phrase;//TODO REFACTOR list = findMatch(list, inputPhrase); list = reduceElementsInList(list); list = sort(list); return list; function findMatch(list, phrase) { var preparedList = [], value = ""; if (config.get("list").match.enabled) { for(var i = 0, length = list.length; i < length; i += 1) { value = config.get("getValue")(list[i]); if (!config.get("list").match.caseSensitive) { if (typeof value === "string") { value = value.toLowerCase(); } phrase = phrase.toLowerCase(); } if (value.search(phrase) > -1) { preparedList.push(list[i]); } } } else { preparedList = list; } return preparedList; } function reduceElementsInList(list) { if (list.length > config.get("list").maxNumberOfElements) { list = list.slice(0, config.get("list").maxNumberOfElements); } return list; } function sort(list) { if (config.get("list").sort.enabled) { list.sort(config.get("list").sort.method); } return list; } }; return scope; })(EasyAutocomplete || {}); /* * EasyAutocomplete - jQuery plugin for autocompletion * */ var EasyAutocomplete = (function(scope) { scope.main = function Core($input, options) { var module = { name: "EasyAutocomplete" }; var consts = new scope.Constans(), config = new scope.Configuration(options), logger = new scope.Logger(), proccessResponseData = scope.proccess, checkParam = config.equals, $field = $input, $container = "", elementsList = [], selectedElement = -1; this.getConstants = function() { return consts; }; this.getConfiguration = function() { return config; }; this.getContainer = function() { return $container; }; this.build = function() { prepareField(); }; this.init = function() { init(); }; function init() { if (!config.checkDataUrlProperties()) { logger.error("One of options variables 'data' or 'url' must be defined."); return; } if (!config.checkRequiredProperties()) { logger.error("Will not work without mentioned properties."); return; } prepareField(); bindEvents(); } function prepareField() { if ($field.parent().hasClass(consts.getValue("WRAPPER_CSS_CLASS"))) { removeContainer(); removeWrapper(); } createWrapper(); createContainer(); $container = $("#" + getContainerId()); if (config.get("placeholder")) { $field.attr("placeholder", config.get("placeholder")); } function createWrapper() { var $wrapper = $("