Added new type ahead feature, documented it and tested it.
This commit is contained in:
		| @@ -805,6 +805,89 @@ class IgniteTemplate { | |||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Adds a special event handler to this element that invokes with the content of an input after a certain amount of time has passed after typing. | ||||||
|  |      * This function supports inputs, text area's and content editable elements. | ||||||
|  |      * @param {Function|IgniteProperty} eventCallback The callback function to be invoked when a typeAhead event occurs, it will be passed the typed value. | ||||||
|  |      * @param {Number} minCharacters Min number of characters excluding whitespace that have to be typed before this event is invoked. Default is 2. | ||||||
|  |      * @param {Number} callbackDelay The delay in miliseconds between each event callback. Default is 350. | ||||||
|  |      * @param {Boolean} callbackReset Whether or not to reset the callback delay on each keypress. Default is true. If true, type ahead only occurrs when typing has stopped. | ||||||
|  |      * @param {Boolean} enterCallback Whether or not the enter key should be considered for a type ahead. Default is true. | ||||||
|  |      * @returns {IgniteTemplate} This ignite template so function calls can be chained.  | ||||||
|  |      */ | ||||||
|  |     onTypeAhead(eventCallback, minCharacters = 2, callbackDelay = 350, callbackReset = true, enterCallback = true) { | ||||||
|  |         var typeAheadTimeout = null; | ||||||
|  |  | ||||||
|  |         var typeAheadRunning = false; | ||||||
|  |  | ||||||
|  |         var lastValue = null; | ||||||
|  |  | ||||||
|  |         var typeAhead = async (target, force) => { | ||||||
|  |             var value = null; | ||||||
|  |  | ||||||
|  |             typeAheadRunning = true; | ||||||
|  |  | ||||||
|  |             //Get the value from the target if we can. | ||||||
|  |             if (target instanceof HTMLElement) { | ||||||
|  |                 if (target.tagName == "INPUT" || target.tagName == "TEXTAREA") { | ||||||
|  |                     value = target.value; | ||||||
|  |                 } else if (target.contentEditable == "true") { | ||||||
|  |                     value = target.innerText; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             //Trim the value if we can | ||||||
|  |             value = value?.trim(); | ||||||
|  |  | ||||||
|  |             //If the value has at least the min number of characters after being trimmed invoke the callback. | ||||||
|  |             if (value != null && value.length >= minCharacters && (lastValue != value || force)) { | ||||||
|  |                 try { | ||||||
|  |                     if (eventCallback instanceof IgniteProperty) { | ||||||
|  |                         await eventCallback.value(value); | ||||||
|  |                     } else if (eventCallback instanceof Function) { | ||||||
|  |                         await eventCallback(value); | ||||||
|  |                     } | ||||||
|  |                 } catch (error) { | ||||||
|  |                     console.error("Error occurred during type ahead callback", error); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 //Request another type ahead incase the value changed while we were waiting for the event callback to finish. | ||||||
|  |                 typeAheadTimeout = setTimeout(() => typeAhead(target, false), callbackDelay); | ||||||
|  |             } else { | ||||||
|  |                 typeAheadTimeout = null; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             lastValue = value; | ||||||
|  |  | ||||||
|  |             typeAheadRunning = false; | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         //Attach a keydown event and handle the type ahead. | ||||||
|  |         this.on("keydown", (e) => { | ||||||
|  |             //If the key was an enter key, dont allow if it's not allowed. | ||||||
|  |             if (e.key == "Enter" && !enterCallback) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             //If callback reset is true and there's a pending type ahead, clear it. | ||||||
|  |             if (callbackReset && typeAheadTimeout && !typeAheadRunning) { | ||||||
|  |                 clearTimeout(typeAheadTimeout); | ||||||
|  |                 typeAheadTimeout = null; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             //Schedule a new type ahead timeout if one isn't already running. | ||||||
|  |             if (!typeAheadTimeout) { | ||||||
|  |                 if (e.key == "Enter") { | ||||||
|  |                     typeAheadTimeout = setTimeout(() => typeAhead(e.target, true), 0); | ||||||
|  |                 } else { | ||||||
|  |                     typeAheadTimeout = setTimeout(() => typeAhead(e.target, false), callbackDelay); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Adds a CSS property to this template with a value and priority. |      * Adds a CSS property to this template with a value and priority. | ||||||
|      * @param {String} name The name of the CSS property to set. |      * @param {String} name The name of the CSS property to set. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user