textext-rails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,354 @@
1
+ /**
2
+ * jQuery TextExt Plugin
3
+ * http://alexgorbatchev.com/textext
4
+ *
5
+ * @version 1.2.0
6
+ * @copyright Copyright (C) 2011 Alex Gorbatchev. All rights reserved.
7
+ * @license MIT License
8
+ */
9
+ (function($)
10
+ {
11
+ /**
12
+ * AJAX plugin is very useful if you want to load list of items from a data point and pass it
13
+ * to the Autocomplete or Filter plugins.
14
+ *
15
+ * Because it meant to be as a helper method for either Autocomplete or Filter plugin, without
16
+ * either of these two present AJAX plugin won't do anything.
17
+ *
18
+ * @author agorbatchev
19
+ * @date 2011/08/16
20
+ * @id TextExtAjax
21
+ */
22
+ function TextExtAjax() {};
23
+
24
+ $.fn.textext.TextExtAjax = TextExtAjax;
25
+ $.fn.textext.addPlugin('ajax', TextExtAjax);
26
+
27
+ var p = TextExtAjax.prototype,
28
+
29
+ /**
30
+ * AJAX plugin options are grouped under `ajax` when passed to the `$().textext()` function. Be
31
+ * mindful that the whole `ajax` object is also passed to jQuery `$.ajax` call which means that
32
+ * you can change all jQuery options as well. Please refer to the jQuery documentation on how
33
+ * to set url and all other parameters. For example:
34
+ *
35
+ * $('textarea').textext({
36
+ * plugins: 'ajax',
37
+ * ajax: {
38
+ * url: 'http://...'
39
+ * }
40
+ * })
41
+ *
42
+ * **Important**: Because it's necessary to pass options to `jQuery.ajax()` in a single object,
43
+ * all jQuery related AJAX options like `url`, `dataType`, etc **must** be within the `ajax` object.
44
+ * This is the exception to general rule that TextExt options can be specified in dot or camel case
45
+ * notation.
46
+ *
47
+ * @author agorbatchev
48
+ * @date 2011/08/16
49
+ * @id TextExtAjax.options
50
+ */
51
+
52
+ /**
53
+ * By default, when user starts typing into the text input, AJAX plugin will start making requests
54
+ * to the `url` that you have specified and will pass whatever user has typed so far as a parameter
55
+ * named `q`, eg `?q=foo`.
56
+ *
57
+ * If you wish to change this behaviour, you can pass a function as a value for this option which
58
+ * takes one argument (the user input) and should return a key/value object that will be converted
59
+ * to the request parameters. For example:
60
+ *
61
+ * 'dataCallback' : function(query)
62
+ * {
63
+ * return { 'search' : query };
64
+ * }
65
+ *
66
+ * @name ajax.data.callback
67
+ * @default null
68
+ * @author agorbatchev
69
+ * @date 2011/08/16
70
+ * @id TextExtAjax.options.data.callback
71
+ */
72
+ OPT_DATA_CALLBACK = 'ajax.data.callback',
73
+
74
+ /**
75
+ * By default, the server end point is constantly being reloaded whenever user changes the value
76
+ * in the text input. If you'd rather have the client do result filtering, you can return all
77
+ * possible results from the server and cache them on the client by setting this option to `true`.
78
+ *
79
+ * In such a case, only one call to the server will be made and filtering will be performed on
80
+ * the client side using `ItemManager` attached to the core.
81
+ *
82
+ * @name ajax.data.results
83
+ * @default false
84
+ * @author agorbatchev
85
+ * @date 2011/08/16
86
+ * @id TextExtAjax.options.cache.results
87
+ */
88
+ OPT_CACHE_RESULTS = 'ajax.cache.results',
89
+
90
+ /**
91
+ * The loading message delay is set in seconds and will specify how long it would take before
92
+ * user sees the message. If you don't want user to ever see this message, set the option value
93
+ * to `Number.MAX_VALUE`.
94
+ *
95
+ * @name ajax.loading.delay
96
+ * @default 0.5
97
+ * @author agorbatchev
98
+ * @date 2011/08/16
99
+ * @id TextExtAjax.options.loading.delay
100
+ */
101
+ OPT_LOADING_DELAY = 'ajax.loading.delay',
102
+
103
+ /**
104
+ * Whenever an AJAX request is made and the server takes more than the number of seconds specified
105
+ * in `ajax.loading.delay` to respond, the message specified in this option will appear in the drop
106
+ * down.
107
+ *
108
+ * @name ajax.loading.message
109
+ * @default "Loading..."
110
+ * @author agorbatchev
111
+ * @date 2011/08/17
112
+ * @id TextExtAjax.options.loading.message
113
+ */
114
+ OPT_LOADING_MESSAGE = 'ajax.loading.message',
115
+
116
+ /**
117
+ * When user is typing in or otherwise changing the value of the text input, it's undesirable to make
118
+ * an AJAX request for every keystroke. Instead it's more conservative to send a request every number
119
+ * of seconds while user is typing the value. This number of seconds is specified by the `ajax.type.delay`
120
+ * option.
121
+ *
122
+ * @name ajax.type.delay
123
+ * @default 0.5
124
+ * @author agorbatchev
125
+ * @date 2011/08/17
126
+ * @id TextExtAjax.options.type.delay
127
+ */
128
+ OPT_TYPE_DELAY = 'ajax.type.delay',
129
+
130
+ /**
131
+ * AJAX plugin dispatches or reacts to the following events.
132
+ *
133
+ * @author agorbatchev
134
+ * @date 2011/08/17
135
+ * @id TextExtAjax.events
136
+ */
137
+
138
+ /**
139
+ * AJAX plugin reacts to the `getSuggestions` event dispatched by the Autocomplete plugin.
140
+ *
141
+ * @name getSuggestions
142
+ * @author agorbatchev
143
+ * @date 2011/08/17
144
+ * @id TextExtAjax.events.getSuggestions
145
+ */
146
+
147
+ /**
148
+ * In the event of successful AJAX request, the AJAX coponent dispatches the `setSuggestions`
149
+ * event meant to be recieved by the Autocomplete plugin.
150
+ *
151
+ * @name setSuggestions
152
+ * @author agorbatchev
153
+ * @date 2011/08/17
154
+ * @id TextExtAjax.events.setSuggestions
155
+ */
156
+ EVENT_SET_SUGGESTION = 'setSuggestions',
157
+
158
+ /**
159
+ * AJAX plugin dispatches the `showDropdown` event which Autocomplete plugin is expecting.
160
+ * This is used to temporarily show the loading message if the AJAX request is taking longer
161
+ * than expected.
162
+ *
163
+ * @name showDropdown
164
+ * @author agorbatchev
165
+ * @date 2011/08/17
166
+ * @id TextExtAjax.events.showDropdown
167
+ */
168
+ EVENT_SHOW_DROPDOWN = 'showDropdown',
169
+
170
+ TIMER_LOADING = 'loading',
171
+
172
+ DEFAULT_OPTS = {
173
+ ajax : {
174
+ typeDelay : 0.5,
175
+ loadingMessage : 'Loading...',
176
+ loadingDelay : 0.5,
177
+ cacheResults : false,
178
+ dataCallback : null
179
+ }
180
+ }
181
+ ;
182
+
183
+ /**
184
+ * Initialization method called by the core during plugin instantiation.
185
+ *
186
+ * @signature TextExtAjax.init(core)
187
+ *
188
+ * @param core {TextExt} Instance of the TextExt core class.
189
+ *
190
+ * @author agorbatchev
191
+ * @date 2011/08/17
192
+ * @id TextExtAjax.init
193
+ */
194
+ p.init = function(core)
195
+ {
196
+ var self = this;
197
+
198
+ self.baseInit(core, DEFAULT_OPTS);
199
+
200
+ self.on({
201
+ getSuggestions : self.onGetSuggestions
202
+ });
203
+
204
+ self._suggestions = null;
205
+ };
206
+
207
+ /**
208
+ * Performas an async AJAX with specified options.
209
+ *
210
+ * @signature TextExtAjax.load(query)
211
+ *
212
+ * @param query {String} Value that user has typed into the text area which is
213
+ * presumably the query.
214
+ *
215
+ * @author agorbatchev
216
+ * @date 2011/08/14
217
+ * @id TextExtAjax.load
218
+ */
219
+ p.load = function(query)
220
+ {
221
+ var self = this,
222
+ dataCallback = self.opts(OPT_DATA_CALLBACK) || function(query) { return { q : query } },
223
+ opts
224
+ ;
225
+
226
+ opts = $.extend(true,
227
+ {
228
+ data : dataCallback(query),
229
+ success : function(data) { self.onComplete(data, query) },
230
+ error : function(jqXHR, message) { console.error(message, query) }
231
+ },
232
+ self.opts('ajax')
233
+ );
234
+
235
+ $.ajax(opts);
236
+ };
237
+
238
+ /**
239
+ * Successful call AJAX handler. Takes the data that came back from AJAX and the
240
+ * original query that was used to make the call.
241
+ *
242
+ * @signature TextExtAjax.onComplete(data, query)
243
+ *
244
+ * @param data {Object} Data loaded from the server, should be an Array of strings
245
+ * by default or whatever data structure your custom `ItemManager` implements.
246
+ *
247
+ * @param query {String} Query string, ie whatever user has typed in.
248
+ *
249
+ * @author agorbatchev
250
+ * @date 2011/08/14
251
+ * @id TextExtAjax.onComplete
252
+ */
253
+ p.onComplete = function(data, query)
254
+ {
255
+ var self = this,
256
+ result = data
257
+ ;
258
+
259
+ self.dontShowLoading();
260
+
261
+ // If results are expected to be cached, then we store the original
262
+ // data set and return the filtered one based on the original query.
263
+ // That means we do filtering on the client side, instead of the
264
+ // server side.
265
+ if(self.opts(OPT_CACHE_RESULTS) == true)
266
+ {
267
+ self._suggestions = data;
268
+ result = self.itemManager().filter(data, query);
269
+ }
270
+
271
+ self.trigger(EVENT_SET_SUGGESTION, { result : result });
272
+ };
273
+
274
+ /**
275
+ * If show loading message timer was started, calling this function disables it,
276
+ * otherwise nothing else happens.
277
+ *
278
+ * @signature TextExtAjax.dontShowLoading()
279
+ *
280
+ * @author agorbatchev
281
+ * @date 2011/08/16
282
+ * @id TextExtAjax.dontShowLoading
283
+ */
284
+ p.dontShowLoading = function()
285
+ {
286
+ this.stopTimer(TIMER_LOADING);
287
+ };
288
+
289
+ /**
290
+ * Shows message specified in `ajax.loading.message` if loading data takes more than
291
+ * number of seconds specified in `ajax.loading.delay`.
292
+ *
293
+ * @signature TextExtAjax.showLoading()
294
+ *
295
+ * @author agorbatchev
296
+ * @date 2011/08/15
297
+ * @id TextExtAjax.showLoading
298
+ */
299
+ p.showLoading = function()
300
+ {
301
+ var self = this;
302
+
303
+ self.dontShowLoading();
304
+ self.startTimer(
305
+ TIMER_LOADING,
306
+ self.opts(OPT_LOADING_DELAY),
307
+ function()
308
+ {
309
+ self.trigger(EVENT_SHOW_DROPDOWN, function(autocomplete)
310
+ {
311
+ autocomplete.clearItems();
312
+ var node = autocomplete.addDropdownItem(self.opts(OPT_LOADING_MESSAGE));
313
+ node.addClass('text-loading');
314
+ });
315
+ }
316
+ );
317
+ };
318
+
319
+ /**
320
+ * Reacts to the `getSuggestions` event and begin loading suggestions. If
321
+ * `ajax.cache.results` is specified, all calls after the first one will use
322
+ * cached data and filter it with the `core.itemManager.filter()`.
323
+ *
324
+ * @signature TextExtAjax.onGetSuggestions(e, data)
325
+ *
326
+ * @param e {Object} jQuery event.
327
+ * @param data {Object} Data structure passed with the `getSuggestions` event
328
+ * which contains the user query, eg `{ query : "..." }`.
329
+ *
330
+ * @author agorbatchev
331
+ * @date 2011/08/15
332
+ * @id TextExtAjax.onGetSuggestions
333
+ */
334
+ p.onGetSuggestions = function(e, data)
335
+ {
336
+ var self = this,
337
+ suggestions = self._suggestions,
338
+ query = (data || {}).query || ''
339
+ ;
340
+
341
+ if(suggestions && self.opts(OPT_CACHE_RESULTS) === true)
342
+ return self.onComplete(suggestions, query);
343
+
344
+ self.startTimer(
345
+ 'ajax',
346
+ self.opts(OPT_TYPE_DELAY),
347
+ function()
348
+ {
349
+ self.showLoading();
350
+ self.load(query);
351
+ }
352
+ );
353
+ };
354
+ })(jQuery);
@@ -0,0 +1,106 @@
1
+ /**
2
+ * jQuery TextExt Plugin
3
+ * http://alexgorbatchev.com/textext
4
+ *
5
+ * @version 1.2.0
6
+ * @copyright Copyright (C) 2011 Alex Gorbatchev. All rights reserved.
7
+ * @license MIT License
8
+ */
9
+ (function($)
10
+ {
11
+ /**
12
+ * Displays a dropdown style arrow button. The `TextExtArrow` works together with the
13
+ * `TextExtAutocomplete` plugin and whenever clicked tells the autocomplete plugin to
14
+ * display its suggestions.
15
+ *
16
+ * @author agorbatchev
17
+ * @date 2011/12/27
18
+ * @id TextExtArrow
19
+ */
20
+ function TextExtArrow() {};
21
+
22
+ $.fn.textext.TextExtArrow = TextExtArrow;
23
+ $.fn.textext.addPlugin('arrow', TextExtArrow);
24
+
25
+ var p = TextExtArrow.prototype,
26
+ /**
27
+ * Arrow plugin only has one option and that is its HTML template. It could be
28
+ * changed when passed to the `$().textext()` function. For example:
29
+ *
30
+ * $('textarea').textext({
31
+ * plugins: 'arrow',
32
+ * html: {
33
+ * arrow: "<span/>"
34
+ * }
35
+ * })
36
+ *
37
+ * @author agorbatchev
38
+ * @date 2011/12/27
39
+ * @id TextExtArrow.options
40
+ */
41
+
42
+ /**
43
+ * HTML source that is used to generate markup required for the arrow.
44
+ *
45
+ * @name html.arrow
46
+ * @default '<div class="text-arrow"/>'
47
+ * @author agorbatchev
48
+ * @date 2011/12/27
49
+ * @id TextExtArrow.options.html.arrow
50
+ */
51
+ OPT_HTML_ARROW = 'html.arrow',
52
+
53
+ DEFAULT_OPTS = {
54
+ html : {
55
+ arrow : '<div class="text-arrow"/>'
56
+ }
57
+ }
58
+ ;
59
+
60
+ /**
61
+ * Initialization method called by the core during plugin instantiation.
62
+ *
63
+ * @signature TextExtArrow.init(core)
64
+ *
65
+ * @param core {TextExt} Instance of the TextExt core class.
66
+ *
67
+ * @author agorbatchev
68
+ * @date 2011/12/27
69
+ * @id TextExtArrow.init
70
+ */
71
+ p.init = function(core)
72
+ {
73
+ var self = this,
74
+ arrow
75
+ ;
76
+
77
+ self.baseInit(core, DEFAULT_OPTS);
78
+
79
+ self._arrow = arrow = $(self.opts(OPT_HTML_ARROW));
80
+ self.core().wrapElement().append(arrow);
81
+ arrow.bind('click', function(e) { self.onArrowClick(e); });
82
+ };
83
+
84
+ //--------------------------------------------------------------------------------
85
+ // Event handlers
86
+
87
+ /**
88
+ * Reacts to the `click` event whenever user clicks the arrow.
89
+ *
90
+ * @signature TextExtArrow.onArrowClick(e)
91
+ *
92
+ * @param e {Object} jQuery event.
93
+ * @author agorbatchev
94
+ * @date 2011/12/27
95
+ * @id TextExtArrow.onArrowClick
96
+ */
97
+ p.onArrowClick = function(e)
98
+ {
99
+ this.trigger('toggleDropdown');
100
+ this.core().focusInput();
101
+ };
102
+
103
+ //--------------------------------------------------------------------------------
104
+ // Core functionality
105
+
106
+ })(jQuery);