From 879a6237b186768356f99caf992f0d25d5ec8612 Mon Sep 17 00:00:00 2001 From: Minteck Date: Sun, 5 Dec 2021 16:38:49 +0100 Subject: Commit --- app/genealogy/dllib/jquery.flexdatalist.js | 2083 ++++++++++++++++++++++++++++ 1 file changed, 2083 insertions(+) create mode 100644 app/genealogy/dllib/jquery.flexdatalist.js (limited to 'app/genealogy/dllib/jquery.flexdatalist.js') diff --git a/app/genealogy/dllib/jquery.flexdatalist.js b/app/genealogy/dllib/jquery.flexdatalist.js new file mode 100644 index 0000000..6fef98b --- /dev/null +++ b/app/genealogy/dllib/jquery.flexdatalist.js @@ -0,0 +1,2083 @@ +/** + * jQuery Flexdatalist. + * Autocomplete input fields, with support for datalists. + * + * Version: + * 2.3.0 + * + * Depends: + * jquery.js > 1.8.3 + * + * Demo and Documentation: + * http://projects.sergiodinislopes.pt/flexdatalist/ + * + * Github: + * https://github.com/sergiodlopes/jquery-flexdatalist/ + * + */ + +jQuery.fn.flexdatalist = function (_option, _value) { + 'use strict'; + + var destroy = function ($flex, clear) { + $flex.each(function () { + var $this = $(this), + data = $this.data(), + options = data.flexdatalist, + $aliascontainer = data.aliascontainer; + + if ($aliascontainer) { + $this.removeClass('flexdatalist-set') + .attr({'style': null, 'tabindex': null}) + .val((options && options.originalValue && !clear ? options.originalValue : '')) + .removeData('flexdatalist') + .removeData('aliascontainer') + .off(); + $aliascontainer.remove(); + } + }); + } + + // Callable stuff + if (typeof _option === 'string' && _option !== 'reset') { + if (typeof this[0] === 'object' && typeof this[0].fvalue !== 'undefined') { + var target = this[0]; + if (_option === 'destroy') { + destroy(this, _value); + // Get/Set value + } else if (_option === 'value') { + if (typeof _value === 'undefined') { + return target.fvalue.get(); + } + target.fvalue.set(_value); + // Add value + } else if (_option === 'add') { + if (typeof _value === 'undefined') { + return target.debug('Missing value to add!'); + } + target.fvalue.add(_value); + // Toggle value + } else if (_option === 'toggle') { + if (typeof _value === 'undefined') { + return target.debug('Missing value to toggle!'); + } + target.fvalue.toggle(_value); + // Remove value + } else if (_option === 'remove') { + if (typeof _value === 'undefined') { + return target.debug('Missing value to remove!'); + } + target.fvalue.remove(_value); + // Disabled/enabled + } else if (_option === 'disabled') { + if (typeof _value === 'undefined') { + return target.fdisabled(); + } + target.fdisabled(_value); + // Option(s) + } else if (typeof _option === 'string') { + if (typeof _value === 'undefined') { + return target.options.get(_option); + } + target.options.set(_option, _value); + } + return this; + } + _option = {_option: _value}; + } + + // Destroy if already set + if (this.length > 0 && typeof this[0].fvalue !== 'undefined') { + destroy(this); + } + + var _options = $.extend({ + url: null, + data: [], + params: {}, + relatives: null, + chainedRelatives: false, + cache: true, + cacheLifetime: 60, + minLength: 3, + groupBy: false, + selectionRequired: false, + focusFirstResult: false, + textProperty: null, + valueProperty: null, + visibleProperties: [], + iconProperty: 'thumb', + searchIn: ['label'], + searchContain: false, + searchEqual: false, + searchByWord: false, + searchDisabled: false, + searchDelay: 400, + normalizeString: null, + multiple: null, + disabled: null, + maxShownResults: 100, + removeOnBackspace: true, + noResultsText: 'No results found for "{keyword}"', + toggleSelected: false, + allowDuplicateValues: false, + redoSearchOnFocus: true, + requestType: 'get', + requestContentType: 'x-www-form-urlencoded', + requestHeaders: null, + resultsProperty: 'results', + keywordParamName: 'keyword', + searchContainParamName: 'contain', + limitOfValues: 0, + valuesSeparator: ',', + debug: true + }, _option); + + return this.each(function (id) { + var $this = $(this), + _this = this, + _searchTimeout = null, + _values = [], + fid = 'flex' + id, + $alias = null, + $multiple = null; + + /** + * Initialization + */ + this.init = function () { + var options = this.options.init(); + this.set.up(); + + $alias + // Focusin + .on('focusin', function (event) { + _this.action.redoSearchFocus(event); + _this.action.showAllResults(event); + if ($multiple) { + $multiple.addClass('focus'); + } + }) + // Keydown + .on('input keydown', function (event) { + if (_this.keyNum(event) === 9) { + _this.results.remove(); + } + _this.action.keypressValue(event, 188); + _this.action.backSpaceKeyRemove(event); + }) + // Keyup + .on('input keyup', function (event) { + _this.action.keypressValue(event, 13); + _this.action.keypressSearch(event); + _this.action.copyValue(event); + _this.action.backSpaceKeyRemove(event); + _this.action.showAllResults(event); + _this.action.clearValue(event); + _this.action.removeResults(event); + _this.action.inputWidth(event); + }) + // Focusout + .on('focusout', function (event) { + if ($multiple) { + $multiple.removeClass('focus'); + } + _this.action.clearText(event); + _this.action.clearValue(event); + }); + + window.onresize = function (event) { + _this.position(); + }; + + // Run garbage collector + this.cache.gc(); + + if (options.selectionRequired) { + _this.fvalue.clear(true, true); + } + this.fvalue._load(options.originalValue, function (values, matches) { + _this.fdisabled(options.disabled); + $this.trigger('init:flexdatalist', [options]); + }, true); + } + + /** + * Handle user actions. + */ + this.action = { + /** + * Add value on comma or enter keypress. + */ + keypressValue: function (event, keyCode) { + var key = _this.keyNum(event), + val = $alias[0].value, + options = _this.options.get(); + + if (val.length > 0 + && key === keyCode + && !options.selectionRequired + && options.multiple) { + var val = $alias[0].value; + event.preventDefault(); + event.stopPropagation(); + _this.fvalue.extract(val); + _this.results.remove(); + } + }, + /** + * Check if keypress is valid. + */ + keypressSearch: function (event) { + var key = _this.keyNum(event), + keyword = $alias.val(), + length = keyword.length, + options = _this.options.get(); + + clearTimeout(_searchTimeout); + if (!key || (key !== 13 && (key < 37 || key > 40))) { + _searchTimeout = setTimeout(function () { + if ((options.minLength === 0 && length > 0) || (options.minLength > 0 && length >= options.minLength)) { + _this.data.load(function (data) { + _this.search.get(keyword, data, function (matches) { + _this.results.show(matches); + }); + }); + } + }, options.searchDelay); + } + }, + /** + * Redo search if input get's back on focus and no value selected. + */ + redoSearchFocus: function (event) { + var val = _this.fvalue.get(), + options = _this.options.get(), + alias = $alias.val(); + if (options.redoSearchOnFocus && ((alias.length > 0 && options.multiple) || (alias.length > 0 && val.length === 0))) { + this.keypressSearch(event); + } + }, + /** + * Copy value from alias to target input. + */ + copyValue: function (event) { + if (_this.keyNum(event) !== 13) { + var keyword = $alias.val(), + val = _this.fvalue.get(true), + options = _this.options.get(); + if (!options.multiple && !options.selectionRequired && keyword.length !== val.length) { + _this.fvalue.extract(keyword); + } + } + }, + /** + * Remove value on backspace key (multiple input only). + */ + backSpaceKeyRemove: function (event) { + var options = _this.options.get(); + if (options.removeOnBackspace && options.multiple) { + var val = $alias.val(), + $remove = $alias.data('_remove'); + if (_this.keyNum(event) === 8) { + if (val.length === 0) { + if ($remove) { + _this.fvalue.remove($remove); + $alias.data('_remove', null); + } else { + $alias.data('_remove', $alias.parents('li:eq(0)').prev()); + } + } else { + $alias.data('_remove', null); + } + } + } + }, + /** + * Show all results if minLength option is 0. + */ + showAllResults: function (event) { + var val = $alias.val(); + val = $.trim(val); + if (val === '' && _this.options.get('minLength') === 0) { + _this.data.load(function (data) { + _this.results.show(data); + }); + } + }, + /** + * Calculate input width by number of characters. + */ + inputWidth: function (event) { + var options = _this.options.get(); + if (options.multiple) { + var keyword = $alias.val(), + fontSize = parseInt($alias.css('fontSize').replace('px', '')), + minWidth = 40, + maxWidth = $this.innerWidth(), + width = ((keyword.length + 1) * fontSize); + + if (width >= minWidth && width <= maxWidth) { + $alias[0].style.width = width + 'px'; + } + } + }, + /** + * Clear text/alias input when criteria is met. + */ + clearText: function (event) { + var val = _this.fvalue.get(), + options = _this.options.get(); + + if (!options.multiple && options.selectionRequired && val.length === 0) { + $alias[0].value = ''; + } + }, + /** + * Clear value when criteria is met. + */ + clearValue: function (event) { + var val = _this.fvalue.get(), + keyword = $alias.val(), + options = _this.options.get(); + + if (!options.multiple && options.selectionRequired && keyword.length <= options.minLength) { + _this.fvalue.clear(); + } + }, + /** + * Remove results when criteria is met. + */ + removeResults: function (event) { + var keyword = $alias.val(), + options = _this.options.get(); + if (options.minLength > 0 && keyword.length < options.minLength) { + _this.results.remove(); + } + } + } + + /** + * Setup flex. + */ + this.set = { + /** + * Prepare input replacement. + */ + up: function () { + $alias = this.getAlias(); + if (_this.options.get('multiple')) { + $multiple = this.multipleInput($alias); + } else { + $alias.insertAfter($this); + } + + this.accessibility($alias); + + // Respect autofocus attribute + if ($this.attr('autofocus')) { + $alias.trigger('focus'); + } + + $this.data('aliascontainer', ($multiple ? $multiple : $alias)).addClass('flexdatalist flexdatalist-set').css({ + 'position': 'absolute', + 'top': -14000, + 'left': -14000 + }).attr('tabindex', -1); + + // update input label with alias id + var inputId = $this.attr('id'), + aliasId = $alias.attr('id'); + $('label[for="' + inputId + '"]').attr('for', aliasId); + + this.chained(); + }, + /** + * Create and return the alias input field for single value input. + */ + getAlias: function () { + var aliasid = ($this.attr('id') ? $this.attr('id') + '-flexdatalist' : fid); + var $alias = $('') + .attr({ + 'class': $this.attr('class'), + 'name': ($this.attr('name') ? 'flexdatalist-' + $this.attr('name') : null), + 'id': aliasid, + 'placeholder': $this.attr('placeholder') + }) + .addClass('flexdatalist-alias ' + aliasid) + .removeClass('flexdatalist') + .attr('autocomplete', 'off'); + return $alias; + }, + /** + * Multiple values input/list + */ + multipleInput: function ($alias) { + $multiple = $('