diff options
Diffstat (limited to 'src/main/webapp/textext/textext.plugin.ajax.js')
-rw-r--r-- | src/main/webapp/textext/textext.plugin.ajax.js | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/src/main/webapp/textext/textext.plugin.ajax.js b/src/main/webapp/textext/textext.plugin.ajax.js new file mode 100644 index 00000000..073f46ab --- /dev/null +++ b/src/main/webapp/textext/textext.plugin.ajax.js @@ -0,0 +1,354 @@ +/** + * jQuery TextExt Plugin + * http://textextjs.com + * + * @version 1.3.1 + * @copyright Copyright (C) 2011 Alex Gorbatchev. All rights reserved. + * @license MIT License + */ +(function($) +{ + /** + * AJAX plugin is very useful if you want to load list of items from a data point and pass it + * to the Autocomplete or Filter plugins. + * + * Because it meant to be as a helper method for either Autocomplete or Filter plugin, without + * either of these two present AJAX plugin won't do anything. + * + * @author agorbatchev + * @date 2011/08/16 + * @id TextExtAjax + */ + function TextExtAjax() {}; + + $.fn.textext.TextExtAjax = TextExtAjax; + $.fn.textext.addPlugin('ajax', TextExtAjax); + + var p = TextExtAjax.prototype, + + /** + * AJAX plugin options are grouped under `ajax` when passed to the `$().textext()` function. Be + * mindful that the whole `ajax` object is also passed to jQuery `$.ajax` call which means that + * you can change all jQuery options as well. Please refer to the jQuery documentation on how + * to set url and all other parameters. For example: + * + * $('textarea').textext({ + * plugins: 'ajax', + * ajax: { + * url: 'http://...' + * } + * }) + * + * **Important**: Because it's necessary to pass options to `jQuery.ajax()` in a single object, + * all jQuery related AJAX options like `url`, `dataType`, etc **must** be within the `ajax` object. + * This is the exception to general rule that TextExt options can be specified in dot or camel case + * notation. + * + * @author agorbatchev + * @date 2011/08/16 + * @id TextExtAjax.options + */ + + /** + * By default, when user starts typing into the text input, AJAX plugin will start making requests + * to the `url` that you have specified and will pass whatever user has typed so far as a parameter + * named `q`, eg `?q=foo`. + * + * If you wish to change this behaviour, you can pass a function as a value for this option which + * takes one argument (the user input) and should return a key/value object that will be converted + * to the request parameters. For example: + * + * 'dataCallback' : function(query) + * { + * return { 'search' : query }; + * } + * + * @name ajax.data.callback + * @default null + * @author agorbatchev + * @date 2011/08/16 + * @id TextExtAjax.options.data.callback + */ + OPT_DATA_CALLBACK = 'ajax.data.callback', + + /** + * By default, the server end point is constantly being reloaded whenever user changes the value + * in the text input. If you'd rather have the client do result filtering, you can return all + * possible results from the server and cache them on the client by setting this option to `true`. + * + * In such a case, only one call to the server will be made and filtering will be performed on + * the client side using `ItemManager` attached to the core. + * + * @name ajax.data.results + * @default false + * @author agorbatchev + * @date 2011/08/16 + * @id TextExtAjax.options.cache.results + */ + OPT_CACHE_RESULTS = 'ajax.cache.results', + + /** + * The loading message delay is set in seconds and will specify how long it would take before + * user sees the message. If you don't want user to ever see this message, set the option value + * to `Number.MAX_VALUE`. + * + * @name ajax.loading.delay + * @default 0.5 + * @author agorbatchev + * @date 2011/08/16 + * @id TextExtAjax.options.loading.delay + */ + OPT_LOADING_DELAY = 'ajax.loading.delay', + + /** + * Whenever an AJAX request is made and the server takes more than the number of seconds specified + * in `ajax.loading.delay` to respond, the message specified in this option will appear in the drop + * down. + * + * @name ajax.loading.message + * @default "Loading..." + * @author agorbatchev + * @date 2011/08/17 + * @id TextExtAjax.options.loading.message + */ + OPT_LOADING_MESSAGE = 'ajax.loading.message', + + /** + * When user is typing in or otherwise changing the value of the text input, it's undesirable to make + * an AJAX request for every keystroke. Instead it's more conservative to send a request every number + * of seconds while user is typing the value. This number of seconds is specified by the `ajax.type.delay` + * option. + * + * @name ajax.type.delay + * @default 0.5 + * @author agorbatchev + * @date 2011/08/17 + * @id TextExtAjax.options.type.delay + */ + OPT_TYPE_DELAY = 'ajax.type.delay', + + /** + * AJAX plugin dispatches or reacts to the following events. + * + * @author agorbatchev + * @date 2011/08/17 + * @id TextExtAjax.events + */ + + /** + * AJAX plugin reacts to the `getSuggestions` event dispatched by the Autocomplete plugin. + * + * @name getSuggestions + * @author agorbatchev + * @date 2011/08/17 + * @id TextExtAjax.events.getSuggestions + */ + + /** + * In the event of successful AJAX request, the AJAX coponent dispatches the `setSuggestions` + * event meant to be recieved by the Autocomplete plugin. + * + * @name setSuggestions + * @author agorbatchev + * @date 2011/08/17 + * @id TextExtAjax.events.setSuggestions + */ + EVENT_SET_SUGGESTION = 'setSuggestions', + + /** + * AJAX plugin dispatches the `showDropdown` event which Autocomplete plugin is expecting. + * This is used to temporarily show the loading message if the AJAX request is taking longer + * than expected. + * + * @name showDropdown + * @author agorbatchev + * @date 2011/08/17 + * @id TextExtAjax.events.showDropdown + */ + EVENT_SHOW_DROPDOWN = 'showDropdown', + + TIMER_LOADING = 'loading', + + DEFAULT_OPTS = { + ajax : { + typeDelay : 0.5, + loadingMessage : 'Loading...', + loadingDelay : 0.5, + cacheResults : false, + dataCallback : null + } + } + ; + + /** + * Initialization method called by the core during plugin instantiation. + * + * @signature TextExtAjax.init(core) + * + * @param core {TextExt} Instance of the TextExt core class. + * + * @author agorbatchev + * @date 2011/08/17 + * @id TextExtAjax.init + */ + p.init = function(core) + { + var self = this; + + self.baseInit(core, DEFAULT_OPTS); + + self.on({ + getSuggestions : self.onGetSuggestions + }); + + self._suggestions = null; + }; + + /** + * Performas an async AJAX with specified options. + * + * @signature TextExtAjax.load(query) + * + * @param query {String} Value that user has typed into the text area which is + * presumably the query. + * + * @author agorbatchev + * @date 2011/08/14 + * @id TextExtAjax.load + */ + p.load = function(query) + { + var self = this, + dataCallback = self.opts(OPT_DATA_CALLBACK) || function(query) { return { q : query } }, + opts + ; + + opts = $.extend(true, + { + data : dataCallback(query), + success : function(data) { self.onComplete(data, query) }, + error : function(jqXHR, message) { console.error(message, query) } + }, + self.opts('ajax') + ); + + $.ajax(opts); + }; + + /** + * Successful call AJAX handler. Takes the data that came back from AJAX and the + * original query that was used to make the call. + * + * @signature TextExtAjax.onComplete(data, query) + * + * @param data {Object} Data loaded from the server, should be an Array of strings + * by default or whatever data structure your custom `ItemManager` implements. + * + * @param query {String} Query string, ie whatever user has typed in. + * + * @author agorbatchev + * @date 2011/08/14 + * @id TextExtAjax.onComplete + */ + p.onComplete = function(data, query) + { + var self = this, + result = data + ; + + self.dontShowLoading(); + + // If results are expected to be cached, then we store the original + // data set and return the filtered one based on the original query. + // That means we do filtering on the client side, instead of the + // server side. + if(self.opts(OPT_CACHE_RESULTS) == true) + { + self._suggestions = data; + result = self.itemManager().filter(data, query); + } + + self.trigger(EVENT_SET_SUGGESTION, { result : result }); + }; + + /** + * If show loading message timer was started, calling this function disables it, + * otherwise nothing else happens. + * + * @signature TextExtAjax.dontShowLoading() + * + * @author agorbatchev + * @date 2011/08/16 + * @id TextExtAjax.dontShowLoading + */ + p.dontShowLoading = function() + { + this.stopTimer(TIMER_LOADING); + }; + + /** + * Shows message specified in `ajax.loading.message` if loading data takes more than + * number of seconds specified in `ajax.loading.delay`. + * + * @signature TextExtAjax.showLoading() + * + * @author agorbatchev + * @date 2011/08/15 + * @id TextExtAjax.showLoading + */ + p.showLoading = function() + { + var self = this; + + self.dontShowLoading(); + self.startTimer( + TIMER_LOADING, + self.opts(OPT_LOADING_DELAY), + function() + { + self.trigger(EVENT_SHOW_DROPDOWN, function(autocomplete) + { + autocomplete.clearItems(); + var node = autocomplete.addDropdownItem(self.opts(OPT_LOADING_MESSAGE)); + node.addClass('text-loading'); + }); + } + ); + }; + + /** + * Reacts to the `getSuggestions` event and begin loading suggestions. If + * `ajax.cache.results` is specified, all calls after the first one will use + * cached data and filter it with the `core.itemManager.filter()`. + * + * @signature TextExtAjax.onGetSuggestions(e, data) + * + * @param e {Object} jQuery event. + * @param data {Object} Data structure passed with the `getSuggestions` event + * which contains the user query, eg `{ query : "..." }`. + * + * @author agorbatchev + * @date 2011/08/15 + * @id TextExtAjax.onGetSuggestions + */ + p.onGetSuggestions = function(e, data) + { + var self = this, + suggestions = self._suggestions, + query = (data || {}).query || '' + ; + + if(suggestions && self.opts(OPT_CACHE_RESULTS) === true) + return self.onComplete(suggestions, query); + + self.startTimer( + 'ajax', + self.opts(OPT_TYPE_DELAY), + function() + { + self.showLoading(); + self.load(query); + } + ); + }; +})(jQuery); |