diff --git a/assets/autoComplete/autoComplete.js b/assets/autoComplete/autoComplete.js new file mode 100644 index 0000000..24a6843 --- /dev/null +++ b/assets/autoComplete/autoComplete.js @@ -0,0 +1,646 @@ + +(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document); +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.autoComplete = factory()); +})(this, (function () { 'use strict'; + + function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + enumerableOnly && (symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + })), keys.push.apply(keys, symbols); + } + + return keys; + } + + function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = null != arguments[i] ? arguments[i] : {}; + i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { + _defineProperty(target, key, source[key]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + + return target; + } + + function _typeof(obj) { + "@babel/helpers - typeof"; + + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }, _typeof(obj); + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _createForOfIteratorHelper(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + + if (!it) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + + var F = function () {}; + + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = it.call(o); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; + } + + var select$1 = function select(element) { + return typeof element === "string" ? document.querySelector(element) : element(); + }; + var create = function create(tag, options) { + var el = typeof tag === "string" ? document.createElement(tag) : tag; + for (var key in options) { + var val = options[key]; + if (key === "inside") { + val.append(el); + } else if (key === "dest") { + select$1(val[0]).insertAdjacentElement(val[1], el); + } else if (key === "around") { + var ref = val; + ref.parentNode.insertBefore(el, ref); + el.append(ref); + if (ref.getAttribute("autofocus") != null) ref.focus(); + } else if (key in el) { + el[key] = val; + } else { + el.setAttribute(key, val); + } + } + return el; + }; + var getQuery = function getQuery(field) { + return field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement ? field.value : field.innerHTML; + }; + var format = function format(value, diacritics) { + value = String(value).toLowerCase(); + return diacritics ? value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").normalize("NFC") : value; + }; + var debounce = function debounce(callback, duration) { + var timer; + return function () { + clearTimeout(timer); + timer = setTimeout(function () { + return callback(); + }, duration); + }; + }; + var checkTrigger = function checkTrigger(query, condition, threshold) { + return condition ? condition(query) : query.length >= threshold; + }; + var mark = function mark(value, cls) { + return create("mark", _objectSpread2({ + innerHTML: value + }, typeof cls === "string" && { + "class": cls + })).outerHTML; + }; + + var configure = (function (ctx) { + var name = ctx.name, + options = ctx.options, + resultsList = ctx.resultsList, + resultItem = ctx.resultItem; + for (var option in options) { + if (_typeof(options[option]) === "object") { + if (!ctx[option]) ctx[option] = {}; + for (var subOption in options[option]) { + ctx[option][subOption] = options[option][subOption]; + } + } else { + ctx[option] = options[option]; + } + } + ctx.selector = ctx.selector || "#" + name; + resultsList.destination = resultsList.destination || ctx.selector; + resultsList.id = resultsList.id || name + "_list_" + ctx.id; + resultItem.id = resultItem.id || name + "_result"; + ctx.input = select$1(ctx.selector); + }); + + var eventEmitter = (function (name, ctx) { + ctx.input.dispatchEvent(new CustomEvent(name, { + bubbles: true, + detail: ctx.feedback, + cancelable: true + })); + }); + + var search = (function (query, record, options) { + var _ref = options || {}, + mode = _ref.mode, + diacritics = _ref.diacritics, + highlight = _ref.highlight; + var nRecord = format(record, diacritics); + record = String(record); + query = format(query, diacritics); + if (mode === "loose") { + query = query.replace(/ /g, ""); + var qLength = query.length; + var cursor = 0; + var match = Array.from(record).map(function (character, index) { + if (cursor < qLength && nRecord[index] === query[cursor]) { + character = highlight ? mark(character, highlight) : character; + cursor++; + } + return character; + }).join(""); + if (cursor === qLength) return match; + } else { + var _match = nRecord.indexOf(query); + if (~_match) { + query = record.substring(_match, _match + query.length); + _match = highlight ? record.replace(query, mark(query, highlight)) : record; + return _match; + } + } + }); + + var getData = function getData(ctx, query) { + return new Promise(function ($return, $error) { + var data; + data = ctx.data; + if (data.cache && data.store) return $return(); + return new Promise(function ($return, $error) { + if (typeof data.src === "function") { + return new Promise(function ($return, $error) { + if (data.src.constructor.name === "AsyncFunction") { + return data.src(query).then($return, $error); + } + return $return(data.src(query)); + }).then($return, $error); + } + return $return(data.src); + }).then(function ($await_7) { + try { + ctx.feedback = data.store = $await_7; + eventEmitter("response", ctx); + return $return(); + } catch ($boundEx) { + return $error($boundEx); + } + }, $error); + }); + }; + var findMatches = function findMatches(query, ctx) { + var data = ctx.data, + searchEngine = ctx.searchEngine; + var matches = []; + data.store.forEach(function (value, index) { + var find = function find(key) { + var record = key ? value[key] : value; + var match = typeof searchEngine === "function" ? searchEngine(query, record) : search(query, record, { + mode: searchEngine, + diacritics: ctx.diacritics, + highlight: ctx.resultItem.highlight + }); + if (!match) return; + var result = { + match: match, + value: value + }; + if (key) result.key = key; + matches.push(result); + }; + if (data.keys) { + var _iterator = _createForOfIteratorHelper(data.keys), + _step; + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var key = _step.value; + find(key); + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } + } else { + find(); + } + }); + if (data.filter) matches = data.filter(matches); + var results = matches.slice(0, ctx.resultsList.maxResults); + ctx.feedback = { + query: query, + matches: matches, + results: results + }; + eventEmitter("results", ctx); + }; + + var Expand = "aria-expanded"; + var Active = "aria-activedescendant"; + var Selected = "aria-selected"; + var feedback = function feedback(ctx, index) { + ctx.feedback.selection = _objectSpread2({ + index: index + }, ctx.feedback.results[index]); + }; + var render = function render(ctx) { + var resultsList = ctx.resultsList, + list = ctx.list, + resultItem = ctx.resultItem, + feedback = ctx.feedback; + var matches = feedback.matches, + results = feedback.results; + ctx.cursor = -1; + list.innerHTML = ""; + if (matches.length || resultsList.noResults) { + var fragment = new DocumentFragment(); + results.forEach(function (result, index) { + var element = create(resultItem.tag, _objectSpread2({ + id: "".concat(resultItem.id, "_").concat(index), + role: "option", + innerHTML: result.match, + inside: fragment + }, resultItem["class"] && { + "class": resultItem["class"] + })); + if (resultItem.element) resultItem.element(element, result); + }); + list.append(fragment); + if (resultsList.element) resultsList.element(list, feedback); + open(ctx); + } else { + close(ctx); + } + }; + var open = function open(ctx) { + if (ctx.isOpen) return; + (ctx.wrapper || ctx.input).setAttribute(Expand, true); + ctx.list.removeAttribute("hidden"); + ctx.isOpen = true; + eventEmitter("open", ctx); + }; + var close = function close(ctx) { + if (!ctx.isOpen) return; + (ctx.wrapper || ctx.input).setAttribute(Expand, false); + ctx.input.setAttribute(Active, ""); + ctx.list.setAttribute("hidden", ""); + ctx.isOpen = false; + eventEmitter("close", ctx); + }; + var goTo = function goTo(index, ctx) { + var resultItem = ctx.resultItem; + var results = ctx.list.getElementsByTagName(resultItem.tag); + var cls = resultItem.selected ? resultItem.selected.split(" ") : false; + if (ctx.isOpen && results.length) { + var _results$index$classL; + var state = ctx.cursor; + if (index >= results.length) index = 0; + if (index < 0) index = results.length - 1; + ctx.cursor = index; + if (state > -1) { + var _results$state$classL; + results[state].removeAttribute(Selected); + if (cls) (_results$state$classL = results[state].classList).remove.apply(_results$state$classL, _toConsumableArray(cls)); + } + results[index].setAttribute(Selected, true); + if (cls) (_results$index$classL = results[index].classList).add.apply(_results$index$classL, _toConsumableArray(cls)); + ctx.input.setAttribute(Active, results[ctx.cursor].id); + ctx.list.scrollTop = results[index].offsetTop - ctx.list.clientHeight + results[index].clientHeight + 5; + ctx.feedback.cursor = ctx.cursor; + feedback(ctx, index); + eventEmitter("navigate", ctx); + } + }; + var next = function next(ctx) { + goTo(ctx.cursor + 1, ctx); + }; + var previous = function previous(ctx) { + goTo(ctx.cursor - 1, ctx); + }; + var select = function select(ctx, event, index) { + index = index >= 0 ? index : ctx.cursor; + if (index < 0) return; + ctx.feedback.event = event; + feedback(ctx, index); + eventEmitter("selection", ctx); + close(ctx); + }; + var click = function click(event, ctx) { + var itemTag = ctx.resultItem.tag.toUpperCase(); + var items = Array.from(ctx.list.querySelectorAll(itemTag)); + var item = event.target.closest(itemTag); + if (item && item.nodeName === itemTag) { + select(ctx, event, items.indexOf(item)); + } + }; + var navigate = function navigate(event, ctx) { + switch (event.keyCode) { + case 40: + case 38: + event.preventDefault(); + event.keyCode === 40 ? next(ctx) : previous(ctx); + break; + case 13: + if (!ctx.submit) event.preventDefault(); + if (ctx.cursor >= 0) select(ctx, event); + break; + case 9: + if (ctx.resultsList.tabSelect && ctx.cursor >= 0) select(ctx, event); + break; + case 27: + ctx.input.value = ""; + close(ctx); + break; + } + }; + + function start (ctx, q) { + var _this = this; + return new Promise(function ($return, $error) { + var queryVal, condition; + queryVal = q || getQuery(ctx.input); + queryVal = ctx.query ? ctx.query(queryVal) : queryVal; + condition = checkTrigger(queryVal, ctx.trigger, ctx.threshold); + if (condition) { + return getData(ctx, queryVal).then(function ($await_2) { + try { + if (ctx.feedback instanceof Error) return $return(); + findMatches(queryVal, ctx); + if (ctx.resultsList) render(ctx); + return $If_1.call(_this); + } catch ($boundEx) { + return $error($boundEx); + } + }, $error); + } else { + close(ctx); + return $If_1.call(_this); + } + function $If_1() { + return $return(); + } + }); + } + + var eventsManager = function eventsManager(events, callback) { + for (var element in events) { + for (var event in events[element]) { + callback(element, event); + } + } + }; + var addEvents = function addEvents(ctx) { + var events = ctx.events; + var run = debounce(function () { + return start(ctx); + }, ctx.debounce); + var publicEvents = ctx.events = _objectSpread2({ + input: _objectSpread2({}, events && events.input) + }, ctx.resultsList && { + list: events ? _objectSpread2({}, events.list) : {} + }); + var privateEvents = { + input: { + input: function input() { + run(); + }, + keydown: function keydown(event) { + navigate(event, ctx); + }, + blur: function blur() { + close(ctx); + } + }, + list: { + mousedown: function mousedown(event) { + event.preventDefault(); + }, + click: function click$1(event) { + click(event, ctx); + } + } + }; + eventsManager(privateEvents, function (element, event) { + if (!ctx.resultsList && event !== "input") return; + if (publicEvents[element][event]) return; + publicEvents[element][event] = privateEvents[element][event]; + }); + eventsManager(publicEvents, function (element, event) { + ctx[element].addEventListener(event, publicEvents[element][event]); + }); + }; + var removeEvents = function removeEvents(ctx) { + eventsManager(ctx.events, function (element, event) { + ctx[element].removeEventListener(event, ctx.events[element][event]); + }); + }; + + function init (ctx) { + var _this = this; + return new Promise(function ($return, $error) { + var placeHolder, resultsList, parentAttrs; + placeHolder = ctx.placeHolder; + resultsList = ctx.resultsList; + parentAttrs = { + role: "combobox", + "aria-owns": resultsList.id, + "aria-haspopup": true, + "aria-expanded": false + }; + create(ctx.input, _objectSpread2(_objectSpread2({ + "aria-controls": resultsList.id, + "aria-autocomplete": "both" + }, placeHolder && { + placeholder: placeHolder + }), !ctx.wrapper && _objectSpread2({}, parentAttrs))); + if (ctx.wrapper) ctx.wrapper = create("div", _objectSpread2({ + around: ctx.input, + "class": ctx.name + "_wrapper" + }, parentAttrs)); + if (resultsList) ctx.list = create(resultsList.tag, _objectSpread2({ + dest: [resultsList.destination, resultsList.position], + id: resultsList.id, + role: "listbox", + hidden: "hidden" + }, resultsList["class"] && { + "class": resultsList["class"] + })); + addEvents(ctx); + if (ctx.data.cache) { + return getData(ctx).then(function ($await_2) { + try { + return $If_1.call(_this); + } catch ($boundEx) { + return $error($boundEx); + } + }, $error); + } + function $If_1() { + eventEmitter("init", ctx); + return $return(); + } + return $If_1.call(_this); + }); + } + + function extend (autoComplete) { + var prototype = autoComplete.prototype; + prototype.init = function () { + init(this); + }; + prototype.start = function (query) { + start(this, query); + }; + prototype.unInit = function () { + if (this.wrapper) { + var parentNode = this.wrapper.parentNode; + parentNode.insertBefore(this.input, this.wrapper); + parentNode.removeChild(this.wrapper); + } + removeEvents(this); + }; + prototype.open = function () { + open(this); + }; + prototype.close = function () { + close(this); + }; + prototype.goTo = function (index) { + goTo(index, this); + }; + prototype.next = function () { + next(this); + }; + prototype.previous = function () { + previous(this); + }; + prototype.select = function (index) { + select(this, null, index); + }; + prototype.search = function (query, record, options) { + return search(query, record, options); + }; + } + + function autoComplete(config) { + this.options = config; + this.id = autoComplete.instances = (autoComplete.instances || 0) + 1; + this.name = "autoComplete"; + this.wrapper = 1; + this.threshold = 1; + this.debounce = 0; + this.resultsList = { + position: "afterend", + tag: "ul", + maxResults: 5 + }; + this.resultItem = { + tag: "li" + }; + configure(this); + extend.call(this, autoComplete); + init(this); + } + + /** + * @memberOf {kit} + */ + return autoComplete; + +})); diff --git a/assets/autoComplete/autoComplete.min.js b/assets/autoComplete/autoComplete.min.js new file mode 100644 index 0000000..01fc1b6 --- /dev/null +++ b/assets/autoComplete/autoComplete.min.js @@ -0,0 +1,6 @@ +/** @module autoComplete */ +kit.PluginManager.register('autoComplete', function(module, exports, require, global){ + +var t,e;t=this,e=function(){"use strict";function t(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function e(e){for(var n=1;nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,u=!0,a=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return u=t.done,t},e:function(t){a=!0,s=t},f:function(){try{u||null==n.return||n.return()}finally{if(a)throw s}}}}(n.keys);try{for(l.s();!(c=l.n()).done;)a(c.value)}catch(t){l.e(t)}finally{l.f()}}else a()})),n.filter&&(i=n.filter(i));var s=i.slice(0,e.resultsList.maxResults);e.feedback={query:t,matches:i,results:s},f("results",e)},m="aria-expanded",b="aria-activedescendant",y="aria-selected",v=function(t,n){t.feedback.selection=e({index:n},t.feedback.results[n])},g=function(t){t.isOpen||((t.wrapper||t.input).setAttribute(m,!0),t.list.removeAttribute("hidden"),t.isOpen=!0,f("open",t))},w=function(t){t.isOpen&&((t.wrapper||t.input).setAttribute(m,!1),t.input.setAttribute(b,""),t.list.setAttribute("hidden",""),t.isOpen=!1,f("close",t))},O=function(t,e){var n=e.resultItem,r=e.list.getElementsByTagName(n.tag),o=!!n.selected&&n.selected.split(" ");if(e.isOpen&&r.length){var s,u,a=e.cursor;t>=r.length&&(t=0),t<0&&(t=r.length-1),e.cursor=t,a>-1&&(r[a].removeAttribute(y),o&&(u=r[a].classList).remove.apply(u,i(o))),r[t].setAttribute(y,!0),o&&(s=r[t].classList).add.apply(s,i(o)),e.input.setAttribute(b,r[e.cursor].id),e.list.scrollTop=r[t].offsetTop-e.list.clientHeight+r[t].clientHeight+5,e.feedback.cursor=e.cursor,v(e,t),f("navigate",e)}},A=function(t){O(t.cursor+1,t)},k=function(t){O(t.cursor-1,t)},L=function(t,e,n){(n=n>=0?n:t.cursor)<0||(t.feedback.event=e,v(t,n),f("selection",t),w(t))};function j(t,n){var r=this;return new Promise((function(i,o){var s,u;return s=n||((u=t.input)instanceof HTMLInputElement||u instanceof HTMLTextAreaElement?u.value:u.innerHTML),function(t,e,n){return e?e(t):t.length>=n}(s=t.query?t.query(s):s,t.trigger,t.threshold)?d(t,s).then((function(n){try{return t.feedback instanceof Error?i():(h(s,t),t.resultsList&&function(t){var n=t.resultsList,r=t.list,i=t.resultItem,o=t.feedback,s=o.matches,u=o.results;if(t.cursor=-1,r.innerHTML="",s.length||n.noResults){var c=new DocumentFragment;u.forEach((function(t,n){var r=a(i.tag,e({id:"".concat(i.id,"_").concat(n),role:"option",innerHTML:t.match,inside:c},i.class&&{class:i.class}));i.element&&i.element(r,t)})),r.append(c),n.element&&n.element(r,o),g(t)}else w(t)}(t),c.call(r))}catch(t){return o(t)}}),o):(w(t),c.call(r));function c(){return i()}}))}var S=function(t,e){for(var n in t)for(var r in t[n])e(n,r)},T=function(t){var n,r,i,o=t.events,s=(n=function(){return j(t)},r=t.debounce,function(){clearTimeout(i),i=setTimeout((function(){return n()}),r)}),u=t.events=e({input:e({},o&&o.input)},t.resultsList&&{list:o?e({},o.list):{}}),a={input:{input:function(){s()},keydown:function(e){!function(t,e){switch(t.keyCode){case 40:case 38:t.preventDefault(),40===t.keyCode?A(e):k(e);break;case 13:e.submit||t.preventDefault(),e.cursor>=0&&L(e,t);break;case 9:e.resultsList.tabSelect&&e.cursor>=0&&L(e,t);break;case 27:e.input.value="",w(e)}}(e,t)},blur:function(){w(t)}},list:{mousedown:function(t){t.preventDefault()},click:function(e){!function(t,e){var n=e.resultItem.tag.toUpperCase(),r=Array.from(e.list.querySelectorAll(n)),i=t.target.closest(n);i&&i.nodeName===n&&L(e,t,r.indexOf(i))}(e,t)}}};S(a,(function(e,n){(t.resultsList||"input"===n)&&(u[e][n]||(u[e][n]=a[e][n]))})),S(u,(function(e,n){t[e].addEventListener(n,u[e][n])}))};function E(t){var n=this;return new Promise((function(r,i){var o,s,u;if(o=t.placeHolder,u={role:"combobox","aria-owns":(s=t.resultsList).id,"aria-haspopup":!0,"aria-expanded":!1},a(t.input,e(e({"aria-controls":s.id,"aria-autocomplete":"both"},o&&{placeholder:o}),!t.wrapper&&e({},u))),t.wrapper&&(t.wrapper=a("div",e({around:t.input,class:t.name+"_wrapper"},u))),s&&(t.list=a(s.tag,e({dest:[s.destination,s.position],id:s.id,role:"listbox",hidden:"hidden"},s.class&&{class:s.class}))),T(t),t.data.cache)return d(t).then((function(t){try{return c.call(n)}catch(t){return i(t)}}),i);function c(){return f("init",t),r()}return c.call(n)}))}function x(t){var e=t.prototype;e.init=function(){E(this)},e.start=function(t){j(this,t)},e.unInit=function(){if(this.wrapper){var t=this.wrapper.parentNode;t.insertBefore(this.input,this.wrapper),t.removeChild(this.wrapper)}var e;S((e=this).events,(function(t,n){e[t].removeEventListener(n,e.events[t][n])}))},e.open=function(){g(this)},e.close=function(){w(this)},e.goTo=function(t){O(t,this)},e.next=function(){A(this)},e.previous=function(){k(this)},e.select=function(t){L(this,null,t)},e.search=function(t,e,n){return p(t,e,n)}}return function t(e){this.options=e,this.id=t.instances=(t.instances||0)+1,this.name="autoComplete",this.wrapper=1,this.threshold=1,this.debounce=0,this.resultsList={position:"afterend",tag:"ul",maxResults:5},this.resultItem={tag:"li"},function(t){var e=t.name,r=t.options,i=t.resultsList,o=t.resultItem;for(var s in r)if("object"===n(r[s]))for(var a in t[s]||(t[s]={}),r[s])t[s][a]=r[s][a];else t[s]=r[s];t.selector=t.selector||"#"+e,i.destination=i.destination||t.selector,i.id=i.id||e+"_list_"+t.id,o.id=o.id||e+"_result",t.input=u(t.selector)}(this),x.call(this,t),E(this)}},"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).autoComplete=e(); + +}); \ No newline at end of file diff --git a/assets/autoComplete/css/autoComplete.01.css b/assets/autoComplete/css/autoComplete.01.css new file mode 100644 index 0000000..4df567e --- /dev/null +++ b/assets/autoComplete/css/autoComplete.01.css @@ -0,0 +1,92 @@ +.autoComplete_wrapper { + display: inline-block; + position: relative; +} + +.autoComplete_wrapper > input { + width: 370px; + height: 40px; + padding-left: 20px; + font-size: 1rem; + color: rgba(123, 123, 123, 1); + border-radius: 8px; + border: 0; + outline: none; + background-color: #f1f3f4; +} + +.autoComplete_wrapper > input::placeholder { + color: rgba(123, 123, 123, 0.5); + transition: all 0.3s ease; +} + +.autoComplete_wrapper > ul { + position: absolute; + max-height: 226px; + overflow-y: scroll; + top: 100%; + left: 0; + right: 0; + padding: 0; + margin: 0.5rem 0 0 0; + border-radius: 0.6rem; + background-color: #fff; + box-shadow: 0 3px 6px rgba(149, 157, 165, 0.15); + border: 1px solid rgba(33, 33, 33, 0.07); + z-index: 1000; + outline: none; +} + +.autoComplete_wrapper > ul[hidden], +.autoComplete_wrapper > ul:empty { + display: block; + opacity: 0; + transform: scale(0); +} + +.autoComplete_wrapper > ul > li { + margin: 0.3rem; + padding: 0.3rem 0.5rem; + list-style: none; + text-align: left; + font-size: 1rem; + color: #212121; + transition: all 0.1s ease-in-out; + border-radius: 0.35rem; + background-color: rgba(255, 255, 255, 1); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.2s ease; +} + +.autoComplete_wrapper > ul > li::selection { + color: rgba(#ffffff, 0); + background-color: rgba(#ffffff, 0); +} + +.autoComplete_wrapper > ul > li:hover { + cursor: pointer; + background-color: rgba(123, 123, 123, 0.1); +} + +.autoComplete_wrapper > ul > li mark { + background-color: transparent; + color: rgba(255, 122, 122, 1); + font-weight: bold; +} + +.autoComplete_wrapper > ul > li mark::selection { + color: rgba(#ffffff, 0); + background-color: rgba(#ffffff, 0); +} + +.autoComplete_wrapper > ul > li[aria-selected="true"] { + background-color: rgba(123, 123, 123, 0.1); +} + +@media only screen and (max-width: 600px) { + .autoComplete_wrapper > input { + width: 18rem; + } +} diff --git a/assets/autoComplete/css/autoComplete.02.css b/assets/autoComplete/css/autoComplete.02.css new file mode 100644 index 0000000..e9e233c --- /dev/null +++ b/assets/autoComplete/css/autoComplete.02.css @@ -0,0 +1,82 @@ +.autoComplete_wrapper { + display: inline-block; + position: relative; +} + +.autoComplete_wrapper > input { + width: 370px; + height: 40px; + padding-left: 10px; + font-size: 1rem; + color: rgb(116, 116, 116); + border-radius: 4px; + border: 1px solid rgba(33, 33, 33, 0.2); + outline: none; +} + +.autoComplete_wrapper > input::placeholder { + color: rgba(123, 123, 123, 0.5); + transition: all 0.3s ease; +} + +.autoComplete_wrapper > ul { + position: absolute; + max-height: 226px; + overflow-y: scroll; + top: 100%; + left: 0; + right: 0; + padding: 0; + margin: 0.5rem 0 0 0; + border-radius: 4px; + background-color: #fff; + border: 1px solid rgba(33, 33, 33, 0.1); + z-index: 1000; + outline: none; +} + +.autoComplete_wrapper > ul > li { + padding: 10px 20px; + list-style: none; + text-align: left; + font-size: 16px; + color: #212121; + transition: all 0.1s ease-in-out; + border-radius: 3px; + background-color: rgba(255, 255, 255, 1); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.2s ease; +} + +.autoComplete_wrapper > ul > li::selection { + color: rgba(#ffffff, 0); + background-color: rgba(#ffffff, 0); +} + +.autoComplete_wrapper > ul > li:hover { + cursor: pointer; + background-color: rgba(123, 123, 123, 0.1); +} + +.autoComplete_wrapper > ul > li mark { + background-color: transparent; + color: rgba(255, 122, 122, 1); + font-weight: bold; +} + +.autoComplete_wrapper > ul > li mark::selection { + color: rgba(#ffffff, 0); + background-color: rgba(#ffffff, 0); +} + +.autoComplete_wrapper > ul > li[aria-selected="true"] { + background-color: rgba(123, 123, 123, 0.1); +} + +@media only screen and (max-width: 600px) { + .autoComplete_wrapper > input { + width: 18rem; + } +} diff --git a/assets/autoComplete/css/autoComplete.css b/assets/autoComplete/css/autoComplete.css new file mode 100644 index 0000000..35688b2 --- /dev/null +++ b/assets/autoComplete/css/autoComplete.css @@ -0,0 +1,116 @@ +.autoComplete_wrapper { + display: inline-block; + position: relative; +} + +.autoComplete_wrapper > input { + height: 3rem; + width: 370px; + margin: 0; + padding: 0 2rem 0 3.2rem; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + font-size: 1rem; + text-overflow: ellipsis; + outline: none; + border-radius: 10rem; + background-image: url(./images/search.svg); + background-size: 1.4rem; + background-position: left 1.05rem top 0.8rem; + background-repeat: no-repeat; + background-origin: border-box; + background-color: #fff; + transition: all 0.4s ease; + -webkit-transition: all -webkit-transform 0.4s ease; +} + +.autoComplete_wrapper > input::placeholder { + +} + +.autoComplete_wrapper > input:hover::placeholder { + +} + +.autoComplete_wrapper > input:focus::placeholder { + +} + +.autoComplete_wrapper > input:focus::selection { + /*background-color: rgba(255, 122, 122, 0.15);*/ +} + +.autoComplete_wrapper > input::selection { + /*background-color: rgba(255, 122, 122, 0.15);*/ +} + +.autoComplete_wrapper > input:hover { + +} + +.autoComplete_wrapper > input:focus { + +} + +.autoComplete_wrapper > ul { + position: absolute; + max-height: 226px; + overflow-y: scroll; + box-sizing: border-box; + left: 0; + right: 0; + margin: 0.5rem 0 0 0; + padding: 0; + z-index: 1; + list-style: none; + border-radius: 0.6rem; + background-color: #fff; + border: 1px solid rgba(33, 33, 33, 0.07); + box-shadow: 0 3px 6px rgba(149, 157, 165, 0.15); + outline: none; + transition: opacity 0.15s ease-in-out; + -moz-transition: opacity 0.15s ease-in-out; + -webkit-transition: opacity 0.15s ease-in-out; +} + +.autoComplete_wrapper > ul[hidden], +.autoComplete_wrapper > ul:empty { + display: block; + opacity: 0; + transform: scale(0); +} + +.autoComplete_wrapper > ul > li, +.autoComplete_wrapper .no_result { + margin: 0.3rem; + padding: 0.3rem 0.5rem; + text-align: left; + font-size: 1rem; + color: #212121; + border-radius: 0.35rem; + background-color: rgba(255, 255, 255, 1); + white-space: normal; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.2s ease; +} + +.autoComplete_wrapper > ul > li mark { + background-color: transparent; + font-weight: bold; +} + +.autoComplete_wrapper > ul > li:hover { + cursor: pointer; + background-color: rgba(255, 122, 122, 0.15); +} + +.autoComplete_wrapper > ul > li[aria-selected="true"] { + background-color: rgba(255, 122, 122, 0.15); +} + +@media only screen and (max-width: 600px) { + .autoComplete_wrapper > input { + } +} diff --git a/assets/autoComplete/css/images/magnifier.svg b/assets/autoComplete/css/images/magnifier.svg new file mode 100644 index 0000000..2a0ee79 --- /dev/null +++ b/assets/autoComplete/css/images/magnifier.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/autoComplete/css/images/search.svg b/assets/autoComplete/css/images/search.svg new file mode 100644 index 0000000..8063ea1 --- /dev/null +++ b/assets/autoComplete/css/images/search.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/assets/core/core.js b/assets/core/core.js index ba124cf..f3f4546 100644 --- a/assets/core/core.js +++ b/assets/core/core.js @@ -147,6 +147,7 @@ kit.config = kit.config || {}; } config.loadJsAfterModule = !!config.loadJsAfterModule; + config.isSetTimestamp = config.hasOwnProperty('isSetTimestamp')?!!config.isSetTimestamp:true; config.type = config.type || 'import'; //loader if(typeof config.deps === 'string') { @@ -231,13 +232,14 @@ kit.config = kit.config || {}; } function loadScript(src, resolveCallback, rejectCallback) { + var originSrc = src; src = String(src).split('?')[0]; if(typeof resolveCallback !== 'function'){ resolveCallback = function(){}; } if(typeof rejectCallback !== 'function'){ rejectCallback = function(res){ - console.warn(res.message); + console.warn(res.message, originSrc); }; } return new Promise(function(resolve, reject) { @@ -248,7 +250,17 @@ kit.config = kit.config || {}; resolve(); } else { var script = document.createElement('script'); - script.src = '' + src + '?__pm' + (new Date()).getTime(); + + try { + var url = new URL(originSrc); + if(plugin.config.isSetTimestamp){ + url.searchParams.append('__pm', (new Date()).getTime()); + } + script.src = url.toString(); + } catch (e) { + script.src = '' + src + '?__pm' + ((new Date()).getTime()); + } + script.onload = function() {resolve(script);}; script.onerror = function() {reject(new Error(`Ошибка загрузки скрипта ${src}`));}; document.head.append(script); @@ -435,10 +447,9 @@ kit.config = kit.config || {}; if(data === undefined) { return; } - if(this.global.hasOwnProperty(key)) { - console.warn(`PluginManager.install(${pluginId}): key ${key} overwritten in kit (${plugin.state}).`); + if(!this.global.hasOwnProperty(key)) { + this.global[key] = data; } - this.global[key] = data; if(Array.isArray(aliasList) && aliasList.length) { aliasList.forEach(function (alias) { setGlobalExtension(alias, [], data) @@ -452,7 +463,10 @@ kit.config = kit.config || {}; var returnData; if(plugin.config.type === moduleTypeList.loader && typeof plugin.config.loader === 'function') { // var returnData = plugin.config.loader.bind(module.exports).call(module.exports, module, module.exports, this.require.bind(this), global); - returnData = plugin.config.loader.bind(window).call(module.exports, module, module.exports, this.require.bind(this), global); + returnData = plugin.config.loader.bind(this.global).call(this.global, module, module.exports, this.require.bind(this), this.global); + if(returnData === undefined && module.exports){ + returnData = module.exports; + } setGlobalExtension(pluginId, plugin.config.alias, returnData); } else if(plugin.config.type === moduleTypeList.import && typeof plugin.config.module === 'string') { returnData = (typeof module.exports === 'object' && module.exports.default !== undefined)?module.exports.default:module.exports; @@ -679,6 +693,12 @@ kit.config = kit.config || {}; defaultPhoneMask: '+7 (999) 999-99-99', }; + var script = document.currentScript; + if(script){ + var path = script.src.split('?')[0]; + defaultConfig.assetsPath = path.split('/').slice(0, -2).join('/'); + } + var manager = new PluginManager(global); manager.register('PluginManager', { alias: 'pm', diff --git a/assets/core/core.register.js b/assets/core/core.register.js index 0f00368..38bd21e 100644 --- a/assets/core/core.register.js +++ b/assets/core/core.register.js @@ -365,6 +365,14 @@ __PluginManager__.registerPlugins({ type: 'import', alias: ['intl-tel-input'], }, + autoComplete: { + path: __pmConfig__.assetsPath + '/autoComplete', + module: '/autoComplete.min.js', + css: [ + '/css/autoComplete.css', + ], + type: 'loader', + }, }); __pmConfig__.debug && (function(){ diff --git a/assets/toolkit/toolkit.css b/assets/toolkit/toolkit.css index a81b6f6..8bffebc 100644 --- a/assets/toolkit/toolkit.css +++ b/assets/toolkit/toolkit.css @@ -2,7 +2,7 @@ box-sizing: border-box; } -.kit-field { +.kit-field, .kit-field.autoComplete_wrapper { display: flex; flex-direction: row; flex-wrap: nowrap; @@ -166,6 +166,7 @@ } .kit-field textarea, .kit-field input, +.kit-field.autoComplete_wrapper > input, .kit-field .kit-field__display { pointer-events: auto; background-color: transparent; @@ -191,6 +192,9 @@ outline-width: 0; font-family: var(--kit-font-family); list-style-type: none; + background-image: none; + background-position: unset; + border-radius: 0; } .kit-field textarea[data-dirty='true'], @@ -201,15 +205,15 @@ .kit-field [data-dirty='true'] ~ .kit-field__label, .kit-field input[type='checkbox'] ~.kit-field__label { top: 0; - transform: translate(0, 0); + /*transform: translate(0, 0);*/ } .kit-field .kit-field__label { font-weight: 400; line-height: calc(1em * 1.5); position: absolute; display: block; - top: 100%; - transform: translate(0, -100%); + top: calc(100% - 1em* 1.5 - var(--kit-field-line-padding)* 2); + /*transform: translate(0, -100%);*/ left: 0; color: var(--kit-color-text); pointer-events: none; @@ -1463,4 +1467,9 @@ select.kit-field__input:disabled ~.kit-field__hr { } .kit-field__area-right { order: 200; +} + +.kit-field.autoComplete_wrapper > ul[id^=autoComplete] { + top: 100%; + pointer-events: auto; } \ No newline at end of file diff --git a/templates/form/field/input/edit.php b/templates/form/field/input/edit.php index 91d4ff1..f1659d2 100644 --- a/templates/form/field/input/edit.php +++ b/templates/form/field/input/edit.php @@ -9,7 +9,7 @@ $labelAttrs = []; if(mb_strlen($field->getId())){ $labelAttrs['for'] = $field->getId(); } -if($bLabel){?>isHidden()){?>isMultiple()){ $values = $field->getValue();