taskwarrior-web 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +0,0 @@
1
- div.tagsinput { border:1px solid #CCC; background: #FFF; padding:5px; width:300px; height:100px; overflow-y: auto;}
2
- div.tagsinput span.tag { border: 1px solid #a5d24a; -moz-border-radius:2px; -webkit-border-radius:2px; display: block; float: left; padding: 5px; text-decoration:none; background: #cde69c; color: #638421; margin-right: 5px; margin-bottom:5px;font-family: helvetica; font-size:13px;}
3
- div.tagsinput span.tag a { font-weight: bold; color: #82ad2b; text-decoration:none; font-size: 11px; }
4
- div.tagsinput input { width:80px; margin:0px; font-family: helvetica; font-size: 13px; border:1px solid transparent; padding:5px; background: transparent; color: #000; outline:0px; margin-right:5px; margin-bottom:5px; }
5
- div.tagsinput div { display:block; float: left; }
6
- .tags_clear { clear: both; width: 100%; height: 0px; }
@@ -1,122 +0,0 @@
1
- /* Example tokeninput style #2: Facebook style */
2
- ul.token-input-list-facebook {
3
- overflow: hidden;
4
- height: auto !important;
5
- height: 1%;
6
- width: 400px;
7
- border: 1px solid #8496ba;
8
- cursor: text;
9
- font-size: 12px;
10
- font-family: Verdana, sans-serif;
11
- min-height: 1px;
12
- z-index: 999;
13
- margin: 0;
14
- padding: 0;
15
- background-color: #fff;
16
- list-style-type: none;
17
- clear: left;
18
- }
19
-
20
- ul.token-input-list-facebook li input {
21
- border: 0;
22
- width: 100px;
23
- padding: 3px 8px;
24
- background-color: white;
25
- margin: 2px 0;
26
- -webkit-appearance: caret;
27
- }
28
-
29
- li.token-input-token-facebook {
30
- overflow: hidden;
31
- height: auto !important;
32
- height: 15px;
33
- margin: 3px;
34
- padding: 1px 3px;
35
- background-color: #eff2f7;
36
- color: #000;
37
- cursor: default;
38
- border: 1px solid #ccd5e4;
39
- font-size: 11px;
40
- border-radius: 5px;
41
- -moz-border-radius: 5px;
42
- -webkit-border-radius: 5px;
43
- float: left;
44
- white-space: nowrap;
45
- }
46
-
47
- li.token-input-token-facebook p {
48
- display: inline;
49
- padding: 0;
50
- margin: 0;
51
- }
52
-
53
- li.token-input-token-facebook span {
54
- color: #a6b3cf;
55
- margin-left: 5px;
56
- font-weight: bold;
57
- cursor: pointer;
58
- }
59
-
60
- li.token-input-selected-token-facebook {
61
- background-color: #5670a6;
62
- border: 1px solid #3b5998;
63
- color: #fff;
64
- }
65
-
66
- li.token-input-input-token-facebook {
67
- float: left;
68
- margin: 0;
69
- padding: 0;
70
- list-style-type: none;
71
- }
72
-
73
- div.token-input-dropdown-facebook {
74
- position: absolute;
75
- width: 400px;
76
- background-color: #fff;
77
- overflow: hidden;
78
- border-left: 1px solid #ccc;
79
- border-right: 1px solid #ccc;
80
- border-bottom: 1px solid #ccc;
81
- cursor: default;
82
- font-size: 11px;
83
- font-family: Verdana, sans-serif;
84
- z-index: 1;
85
- }
86
-
87
- div.token-input-dropdown-facebook p {
88
- margin: 0;
89
- padding: 5px;
90
- font-weight: bold;
91
- color: #777;
92
- }
93
-
94
- div.token-input-dropdown-facebook ul {
95
- margin: 0;
96
- padding: 0;
97
- }
98
-
99
- div.token-input-dropdown-facebook ul li {
100
- background-color: #fff;
101
- padding: 3px;
102
- margin: 0;
103
- list-style-type: none;
104
- }
105
-
106
- div.token-input-dropdown-facebook ul li.token-input-dropdown-item-facebook {
107
- background-color: #fff;
108
- }
109
-
110
- div.token-input-dropdown-facebook ul li.token-input-dropdown-item2-facebook {
111
- background-color: #fff;
112
- }
113
-
114
- div.token-input-dropdown-facebook ul li em {
115
- font-weight: bold;
116
- font-style: normal;
117
- }
118
-
119
- div.token-input-dropdown-facebook ul li.token-input-selected-dropdown-item-facebook {
120
- background-color: #3b5998;
121
- color: #fff;
122
- }
@@ -1,127 +0,0 @@
1
- /* Example tokeninput style #1: Token vertical list*/
2
- ul.token-input-list {
3
- overflow: hidden;
4
- height: auto !important;
5
- height: 1%;
6
- width: 400px;
7
- border: 1px solid #999;
8
- cursor: text;
9
- font-size: 12px;
10
- font-family: Verdana, sans-serif;
11
- z-index: 999;
12
- margin: 0;
13
- padding: 0;
14
- background-color: #fff;
15
- list-style-type: none;
16
- clear: left;
17
- }
18
-
19
- ul.token-input-list li {
20
- list-style-type: none;
21
- }
22
-
23
- ul.token-input-list li input {
24
- border: 0;
25
- width: 350px;
26
- padding: 3px 8px;
27
- background-color: white;
28
- -webkit-appearance: caret;
29
- }
30
-
31
- ul.token-input-disabled,
32
- ul.token-input-disabled li input {
33
- background-color: #E8E8E8;
34
- }
35
-
36
- ul.token-input-disabled li.token-input-token {
37
- background-color: #D9E3CA;
38
- color: #7D7D7D
39
- }
40
-
41
- ul.token-input-disabled li.token-input-token span {
42
- color: #CFCFCF;
43
- cursor: default;
44
- }
45
-
46
- li.token-input-token {
47
- overflow: hidden;
48
- height: auto !important;
49
- height: 1%;
50
- margin: 3px;
51
- padding: 3px 5px;
52
- background-color: #d0efa0;
53
- color: #000;
54
- font-weight: bold;
55
- cursor: default;
56
- display: block;
57
- }
58
-
59
- li.token-input-token p {
60
- float: left;
61
- padding: 0;
62
- margin: 0;
63
- }
64
-
65
- li.token-input-token span {
66
- float: right;
67
- color: #777;
68
- cursor: pointer;
69
- }
70
-
71
- li.token-input-selected-token {
72
- background-color: #08844e;
73
- color: #fff;
74
- }
75
-
76
- li.token-input-selected-token span {
77
- color: #bbb;
78
- }
79
-
80
- div.token-input-dropdown {
81
- position: absolute;
82
- width: 400px;
83
- background-color: #fff;
84
- overflow: hidden;
85
- border-left: 1px solid #ccc;
86
- border-right: 1px solid #ccc;
87
- border-bottom: 1px solid #ccc;
88
- cursor: default;
89
- font-size: 12px;
90
- font-family: Verdana, sans-serif;
91
- z-index: 1;
92
- }
93
-
94
- div.token-input-dropdown p {
95
- margin: 0;
96
- padding: 5px;
97
- font-weight: bold;
98
- color: #777;
99
- }
100
-
101
- div.token-input-dropdown ul {
102
- margin: 0;
103
- padding: 0;
104
- }
105
-
106
- div.token-input-dropdown ul li {
107
- background-color: #fff;
108
- padding: 3px;
109
- list-style-type: none;
110
- }
111
-
112
- div.token-input-dropdown ul li.token-input-dropdown-item {
113
- background-color: #fafafa;
114
- }
115
-
116
- div.token-input-dropdown ul li.token-input-dropdown-item2 {
117
- background-color: #fff;
118
- }
119
-
120
- div.token-input-dropdown ul li em {
121
- font-weight: bold;
122
- font-style: normal;
123
- }
124
-
125
- div.token-input-dropdown ul li.token-input-selected-dropdown-item {
126
- background-color: #d0efa0;
127
- }
@@ -1,1015 +0,0 @@
1
- /*
2
- * jQuery Plugin: Tokenizing Autocomplete Text Entry
3
- * Version 1.6.0
4
- *
5
- * Copyright (c) 2009 James Smith (http://loopj.com)
6
- * Licensed jointly under the GPL and MIT licenses,
7
- * choose which one suits your project best!
8
- *
9
- */
10
-
11
- (function ($) {
12
- // Default settings
13
- var DEFAULT_SETTINGS = {
14
- // Search settings
15
- method: "GET",
16
- queryParam: "q",
17
- searchDelay: 300,
18
- minChars: 1,
19
- propertyToSearch: "name",
20
- jsonContainer: null,
21
- contentType: "json",
22
-
23
- // Prepopulation settings
24
- prePopulate: null,
25
- processPrePopulate: false,
26
-
27
- // Display settings
28
- hintText: "Type in a search term",
29
- noResultsText: "No results",
30
- searchingText: "Searching...",
31
- deleteText: "×",
32
- animateDropdown: true,
33
- theme: null,
34
- zindex: 999,
35
- resultsLimit: null,
36
-
37
- enableHTML: false,
38
-
39
- resultsFormatter: function(item) {
40
- var string = item[this.propertyToSearch];
41
- return "<li>" + (this.enableHTML ? string : _escapeHTML(string)) + "</li>";
42
- },
43
-
44
- tokenFormatter: function(item) {
45
- var string = item[this.propertyToSearch];
46
- return "<li><p>" + (this.enableHTML ? string : _escapeHTML(string)) + "</p></li>";
47
- },
48
-
49
- // Tokenization settings
50
- tokenLimit: null,
51
- tokenDelimiter: ",",
52
- preventDuplicates: false,
53
- tokenValue: "id",
54
-
55
- // Behavioral settings
56
- allowFreeTagging: false,
57
-
58
- // Callbacks
59
- onResult: null,
60
- onCachedResult: null,
61
- onAdd: null,
62
- onFreeTaggingAdd: null,
63
- onDelete: null,
64
- onReady: null,
65
-
66
- // Other settings
67
- idPrefix: "token-input-",
68
-
69
- // Keep track if the input is currently in disabled mode
70
- disabled: false
71
- };
72
-
73
- // Default classes to use when theming
74
- var DEFAULT_CLASSES = {
75
- tokenList: "token-input-list",
76
- token: "token-input-token",
77
- tokenReadOnly: "token-input-token-readonly",
78
- tokenDelete: "token-input-delete-token",
79
- selectedToken: "token-input-selected-token",
80
- highlightedToken: "token-input-highlighted-token",
81
- dropdown: "token-input-dropdown",
82
- dropdownItem: "token-input-dropdown-item",
83
- dropdownItem2: "token-input-dropdown-item2",
84
- selectedDropdownItem: "token-input-selected-dropdown-item",
85
- inputToken: "token-input-input-token",
86
- focused: "token-input-focused",
87
- disabled: "token-input-disabled"
88
- };
89
-
90
- // Input box position "enum"
91
- var POSITION = {
92
- BEFORE: 0,
93
- AFTER: 1,
94
- END: 2
95
- };
96
-
97
- // Keys "enum"
98
- var KEY = {
99
- BACKSPACE: 8,
100
- TAB: 9,
101
- ENTER: 13,
102
- ESCAPE: 27,
103
- SPACE: 32,
104
- PAGE_UP: 33,
105
- PAGE_DOWN: 34,
106
- END: 35,
107
- HOME: 36,
108
- LEFT: 37,
109
- UP: 38,
110
- RIGHT: 39,
111
- DOWN: 40,
112
- NUMPAD_ENTER: 108,
113
- COMMA: 188
114
- };
115
-
116
- var HTML_ESCAPES = {
117
- '&': '&amp;',
118
- '<': '&lt;',
119
- '>': '&gt;',
120
- '"': '&quot;',
121
- "'": '&#x27;',
122
- '/': '&#x2F;'
123
- };
124
-
125
- var HTML_ESCAPE_CHARS = /[&<>"'\/]/g;
126
-
127
- function coerceToString(val) {
128
- return String((val === null || val === undefined) ? '' : val);
129
- }
130
-
131
- function _escapeHTML(text) {
132
- return coerceToString(text).replace(HTML_ESCAPE_CHARS, function(match) {
133
- return HTML_ESCAPES[match];
134
- });
135
- }
136
-
137
- // Additional public (exposed) methods
138
- var methods = {
139
- init: function(url_or_data_or_function, options) {
140
- var settings = $.extend({}, DEFAULT_SETTINGS, options || {});
141
-
142
- return this.each(function () {
143
- $(this).data("settings", settings);
144
- $(this).data("tokenInputObject", new $.TokenList(this, url_or_data_or_function, settings));
145
- });
146
- },
147
- clear: function() {
148
- this.data("tokenInputObject").clear();
149
- return this;
150
- },
151
- add: function(item) {
152
- this.data("tokenInputObject").add(item);
153
- return this;
154
- },
155
- remove: function(item) {
156
- this.data("tokenInputObject").remove(item);
157
- return this;
158
- },
159
- get: function() {
160
- return this.data("tokenInputObject").getTokens();
161
- },
162
- toggleDisabled: function(disable) {
163
- this.data("tokenInputObject").toggleDisabled(disable);
164
- return this;
165
- },
166
- setOptions: function(options){
167
- $(this).data("settings", $.extend({}, $(this).data("settings"), options || {}));
168
- return this;
169
- }
170
- }
171
-
172
- // Expose the .tokenInput function to jQuery as a plugin
173
- $.fn.tokenInput = function (method) {
174
- // Method calling and initialization logic
175
- if(methods[method]) {
176
- return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
177
- } else {
178
- return methods.init.apply(this, arguments);
179
- }
180
- };
181
-
182
- // TokenList class for each input
183
- $.TokenList = function (input, url_or_data, settings) {
184
- //
185
- // Initialization
186
- //
187
-
188
- // Configure the data source
189
- if($.type(url_or_data) === "string" || $.type(url_or_data) === "function") {
190
- // Set the url to query against
191
- $(input).data("settings").url = url_or_data;
192
-
193
- // If the URL is a function, evaluate it here to do our initalization work
194
- var url = computeURL();
195
-
196
- // Make a smart guess about cross-domain if it wasn't explicitly specified
197
- if($(input).data("settings").crossDomain === undefined && typeof url === "string") {
198
- if(url.indexOf("://") === -1) {
199
- $(input).data("settings").crossDomain = false;
200
- } else {
201
- $(input).data("settings").crossDomain = (location.href.split(/\/+/g)[1] !== url.split(/\/+/g)[1]);
202
- }
203
- }
204
- } else if(typeof(url_or_data) === "object") {
205
- // Set the local data to search through
206
- $(input).data("settings").local_data = url_or_data;
207
- }
208
-
209
- // Build class names
210
- if($(input).data("settings").classes) {
211
- // Use custom class names
212
- $(input).data("settings").classes = $.extend({}, DEFAULT_CLASSES, $(input).data("settings").classes);
213
- } else if($(input).data("settings").theme) {
214
- // Use theme-suffixed default class names
215
- $(input).data("settings").classes = {};
216
- $.each(DEFAULT_CLASSES, function(key, value) {
217
- $(input).data("settings").classes[key] = value + "-" + $(input).data("settings").theme;
218
- });
219
- } else {
220
- $(input).data("settings").classes = DEFAULT_CLASSES;
221
- }
222
-
223
-
224
- // Save the tokens
225
- var saved_tokens = [];
226
-
227
- // Keep track of the number of tokens in the list
228
- var token_count = 0;
229
-
230
- // Basic cache to save on db hits
231
- var cache = new $.TokenList.Cache();
232
-
233
- // Keep track of the timeout, old vals
234
- var timeout;
235
- var input_val;
236
-
237
- // Create a new text input an attach keyup events
238
- var input_box = $("<input type=\"text\" autocomplete=\"off\">")
239
- .css({
240
- outline: "none"
241
- })
242
- .attr("id", $(input).data("settings").idPrefix + input.id)
243
- .focus(function () {
244
- if ($(input).data("settings").disabled) {
245
- return false;
246
- } else
247
- if ($(input).data("settings").tokenLimit === null || $(input).data("settings").tokenLimit !== token_count) {
248
- show_dropdown_hint();
249
- }
250
- token_list.addClass($(input).data("settings").classes.focused);
251
- })
252
- .blur(function () {
253
- hide_dropdown();
254
- $(this).val("");
255
- token_list.removeClass($(input).data("settings").classes.focused);
256
-
257
- if ($(input).data("settings").allowFreeTagging) {
258
- add_freetagging_tokens();
259
- } else {
260
- $(this).val("");
261
- }
262
- token_list.removeClass($(input).data("settings").classes.focused);
263
- })
264
- .bind("keyup keydown blur update", resize_input)
265
- .keydown(function (event) {
266
- var previous_token;
267
- var next_token;
268
-
269
- switch(event.keyCode) {
270
- case KEY.LEFT:
271
- case KEY.RIGHT:
272
- case KEY.UP:
273
- case KEY.DOWN:
274
- if(!$(this).val()) {
275
- previous_token = input_token.prev();
276
- next_token = input_token.next();
277
-
278
- if((previous_token.length && previous_token.get(0) === selected_token) || (next_token.length && next_token.get(0) === selected_token)) {
279
- // Check if there is a previous/next token and it is selected
280
- if(event.keyCode === KEY.LEFT || event.keyCode === KEY.UP) {
281
- deselect_token($(selected_token), POSITION.BEFORE);
282
- } else {
283
- deselect_token($(selected_token), POSITION.AFTER);
284
- }
285
- } else if((event.keyCode === KEY.LEFT || event.keyCode === KEY.UP) && previous_token.length) {
286
- // We are moving left, select the previous token if it exists
287
- select_token($(previous_token.get(0)));
288
- } else if((event.keyCode === KEY.RIGHT || event.keyCode === KEY.DOWN) && next_token.length) {
289
- // We are moving right, select the next token if it exists
290
- select_token($(next_token.get(0)));
291
- }
292
- } else {
293
- var dropdown_item = null;
294
-
295
- if(event.keyCode === KEY.DOWN || event.keyCode === KEY.RIGHT) {
296
- dropdown_item = $(selected_dropdown_item).next();
297
- } else {
298
- dropdown_item = $(selected_dropdown_item).prev();
299
- }
300
-
301
- if(dropdown_item.length) {
302
- select_dropdown_item(dropdown_item);
303
- }
304
- }
305
- return false;
306
- break;
307
-
308
- case KEY.BACKSPACE:
309
- previous_token = input_token.prev();
310
-
311
- if(!$(this).val().length) {
312
- if(selected_token) {
313
- delete_token($(selected_token));
314
- hidden_input.change();
315
- } else if(previous_token.length) {
316
- select_token($(previous_token.get(0)));
317
- }
318
-
319
- return false;
320
- } else if($(this).val().length === 1) {
321
- hide_dropdown();
322
- } else {
323
- // set a timeout just long enough to let this function finish.
324
- setTimeout(function(){do_search();}, 5);
325
- }
326
- break;
327
-
328
- case KEY.TAB:
329
- case KEY.ENTER:
330
- case KEY.NUMPAD_ENTER:
331
- case KEY.COMMA:
332
- if(selected_dropdown_item) {
333
- add_token($(selected_dropdown_item).data("tokeninput"));
334
- hidden_input.change();
335
- } else {
336
- if ($(input).data("settings").allowFreeTagging) {
337
- add_freetagging_tokens();
338
- } else {
339
- $(this).val("");
340
- }
341
- event.stopPropagation();
342
- event.preventDefault();
343
- }
344
- return false;
345
-
346
- case KEY.ESCAPE:
347
- hide_dropdown();
348
- return true;
349
-
350
- default:
351
- if(String.fromCharCode(event.which)) {
352
- // set a timeout just long enough to let this function finish.
353
- setTimeout(function(){do_search();}, 5);
354
- }
355
- break;
356
- }
357
- });
358
-
359
- // Keep a reference to the original input box
360
- var hidden_input = $(input)
361
- .hide()
362
- .val("")
363
- .focus(function () {
364
- focus_with_timeout(input_box);
365
- })
366
- .blur(function () {
367
- input_box.blur();
368
- });
369
-
370
- // Keep a reference to the selected token and dropdown item
371
- var selected_token = null;
372
- var selected_token_index = 0;
373
- var selected_dropdown_item = null;
374
-
375
- // The list to store the token items in
376
- var token_list = $("<ul />")
377
- .addClass($(input).data("settings").classes.tokenList)
378
- .click(function (event) {
379
- var li = $(event.target).closest("li");
380
- if(li && li.get(0) && $.data(li.get(0), "tokeninput")) {
381
- toggle_select_token(li);
382
- } else {
383
- // Deselect selected token
384
- if(selected_token) {
385
- deselect_token($(selected_token), POSITION.END);
386
- }
387
-
388
- // Focus input box
389
- focus_with_timeout(input_box);
390
- }
391
- })
392
- .mouseover(function (event) {
393
- var li = $(event.target).closest("li");
394
- if(li && selected_token !== this) {
395
- li.addClass($(input).data("settings").classes.highlightedToken);
396
- }
397
- })
398
- .mouseout(function (event) {
399
- var li = $(event.target).closest("li");
400
- if(li && selected_token !== this) {
401
- li.removeClass($(input).data("settings").classes.highlightedToken);
402
- }
403
- })
404
- .insertBefore(hidden_input);
405
-
406
- // The token holding the input box
407
- var input_token = $("<li />")
408
- .addClass($(input).data("settings").classes.inputToken)
409
- .appendTo(token_list)
410
- .append(input_box);
411
-
412
- // The list to store the dropdown items in
413
- var dropdown = $("<div>")
414
- .addClass($(input).data("settings").classes.dropdown)
415
- .appendTo("body")
416
- .hide();
417
-
418
- // Magic element to help us resize the text input
419
- var input_resizer = $("<tester/>")
420
- .insertAfter(input_box)
421
- .css({
422
- position: "absolute",
423
- top: -9999,
424
- left: -9999,
425
- width: "auto",
426
- fontSize: input_box.css("fontSize"),
427
- fontFamily: input_box.css("fontFamily"),
428
- fontWeight: input_box.css("fontWeight"),
429
- letterSpacing: input_box.css("letterSpacing"),
430
- whiteSpace: "nowrap"
431
- });
432
-
433
- // Pre-populate list if items exist
434
- hidden_input.val("");
435
- var li_data = $(input).data("settings").prePopulate || hidden_input.data("pre");
436
- if($(input).data("settings").processPrePopulate && $.isFunction($(input).data("settings").onResult)) {
437
- li_data = $(input).data("settings").onResult.call(hidden_input, li_data);
438
- }
439
- if(li_data && li_data.length) {
440
- $.each(li_data, function (index, value) {
441
- insert_token(value);
442
- checkTokenLimit();
443
- });
444
- }
445
-
446
- // Check if widget should initialize as disabled
447
- if ($(input).data("settings").disabled) {
448
- toggleDisabled(true);
449
- }
450
-
451
- // Initialization is done
452
- if($.isFunction($(input).data("settings").onReady)) {
453
- $(input).data("settings").onReady.call();
454
- }
455
-
456
- //
457
- // Public functions
458
- //
459
-
460
- this.clear = function() {
461
- token_list.children("li").each(function() {
462
- if ($(this).children("input").length === 0) {
463
- delete_token($(this));
464
- }
465
- });
466
- }
467
-
468
- this.add = function(item) {
469
- add_token(item);
470
- }
471
-
472
- this.remove = function(item) {
473
- token_list.children("li").each(function() {
474
- if ($(this).children("input").length === 0) {
475
- var currToken = $(this).data("tokeninput");
476
- var match = true;
477
- for (var prop in item) {
478
- if (item[prop] !== currToken[prop]) {
479
- match = false;
480
- break;
481
- }
482
- }
483
- if (match) {
484
- delete_token($(this));
485
- }
486
- }
487
- });
488
- }
489
-
490
- this.getTokens = function() {
491
- return saved_tokens;
492
- }
493
-
494
- this.toggleDisabled = function(disable) {
495
- toggleDisabled(disable);
496
- }
497
-
498
- //
499
- // Private functions
500
- //
501
-
502
- function escapeHTML(text) {
503
- return $(input).data("settings").enableHTML ? text : _escapeHTML(text);
504
- }
505
-
506
- // Toggles the widget between enabled and disabled state, or according
507
- // to the [disable] parameter.
508
- function toggleDisabled(disable) {
509
- if (typeof disable === 'boolean') {
510
- $(input).data("settings").disabled = disable
511
- } else {
512
- $(input).data("settings").disabled = !$(input).data("settings").disabled;
513
- }
514
- input_box.attr('disabled', $(input).data("settings").disabled);
515
- token_list.toggleClass($(input).data("settings").classes.disabled, $(input).data("settings").disabled);
516
- // if there is any token selected we deselect it
517
- if(selected_token) {
518
- deselect_token($(selected_token), POSITION.END);
519
- }
520
- hidden_input.attr('disabled', $(input).data("settings").disabled);
521
- }
522
-
523
- function checkTokenLimit() {
524
- if($(input).data("settings").tokenLimit !== null && token_count >= $(input).data("settings").tokenLimit) {
525
- input_box.hide();
526
- hide_dropdown();
527
- return;
528
- }
529
- }
530
-
531
- function resize_input() {
532
- if(input_val === (input_val = input_box.val())) {return;}
533
-
534
- // Enter new content into resizer and resize input accordingly
535
- input_resizer.html(_escapeHTML(input_val));
536
- input_box.width(input_resizer.width() + 30);
537
- }
538
-
539
- function is_printable_character(keycode) {
540
- return ((keycode >= 48 && keycode <= 90) || // 0-1a-z
541
- (keycode >= 96 && keycode <= 111) || // numpad 0-9 + - / * .
542
- (keycode >= 186 && keycode <= 192) || // ; = , - . / ^
543
- (keycode >= 219 && keycode <= 222)); // ( \ ) '
544
- }
545
-
546
- function add_freetagging_tokens() {
547
- var value = $.trim(input_box.val());
548
- var tokens = value.split($(input).data("settings").tokenDelimiter);
549
- $.each(tokens, function(i, token) {
550
- if (!token) {
551
- return;
552
- }
553
-
554
- if ($.isFunction($(input).data("settings").onFreeTaggingAdd)) {
555
- token = $(input).data("settings").onFreeTaggingAdd.call(hidden_input, token);
556
- }
557
- var object = {};
558
- object[$(input).data("settings").tokenValue] = object[$(input).data("settings").propertyToSearch] = token;
559
- add_token(object);
560
- });
561
- }
562
-
563
- // Inner function to a token to the list
564
- function insert_token(item) {
565
- var $this_token = $($(input).data("settings").tokenFormatter(item));
566
- var readonly = item.readonly === true ? true : false;
567
-
568
- if(readonly) $this_token.addClass($(input).data("settings").classes.tokenReadOnly);
569
-
570
- $this_token.addClass($(input).data("settings").classes.token).insertBefore(input_token);
571
-
572
- // The 'delete token' button
573
- if(!readonly) {
574
- $("<span>" + $(input).data("settings").deleteText + "</span>")
575
- .addClass($(input).data("settings").classes.tokenDelete)
576
- .appendTo($this_token)
577
- .click(function () {
578
- if (!$(input).data("settings").disabled) {
579
- delete_token($(this).parent());
580
- hidden_input.change();
581
- return false;
582
- }
583
- });
584
- }
585
-
586
- // Store data on the token
587
- var token_data = item;
588
- $.data($this_token.get(0), "tokeninput", item);
589
-
590
- // Save this token for duplicate checking
591
- saved_tokens = saved_tokens.slice(0,selected_token_index).concat([token_data]).concat(saved_tokens.slice(selected_token_index));
592
- selected_token_index++;
593
-
594
- // Update the hidden input
595
- update_hidden_input(saved_tokens, hidden_input);
596
-
597
- token_count += 1;
598
-
599
- // Check the token limit
600
- if($(input).data("settings").tokenLimit !== null && token_count >= $(input).data("settings").tokenLimit) {
601
- input_box.hide();
602
- hide_dropdown();
603
- }
604
-
605
- return $this_token;
606
- }
607
-
608
- // Add a token to the token list based on user input
609
- function add_token (item) {
610
- var callback = $(input).data("settings").onAdd;
611
-
612
- // See if the token already exists and select it if we don't want duplicates
613
- if(token_count > 0 && $(input).data("settings").preventDuplicates) {
614
- var found_existing_token = null;
615
- token_list.children().each(function () {
616
- var existing_token = $(this);
617
- var existing_data = $.data(existing_token.get(0), "tokeninput");
618
- if(existing_data && existing_data.id === item.id) {
619
- found_existing_token = existing_token;
620
- return false;
621
- }
622
- });
623
-
624
- if(found_existing_token) {
625
- select_token(found_existing_token);
626
- input_token.insertAfter(found_existing_token);
627
- focus_with_timeout(input_box);
628
- return;
629
- }
630
- }
631
-
632
- // Insert the new tokens
633
- if($(input).data("settings").tokenLimit == null || token_count < $(input).data("settings").tokenLimit) {
634
- insert_token(item);
635
- checkTokenLimit();
636
- }
637
-
638
- // Clear input box
639
- input_box.val("");
640
-
641
- // Don't show the help dropdown, they've got the idea
642
- hide_dropdown();
643
-
644
- // Execute the onAdd callback if defined
645
- if($.isFunction(callback)) {
646
- callback.call(hidden_input,item);
647
- }
648
- }
649
-
650
- // Select a token in the token list
651
- function select_token (token) {
652
- if (!$(input).data("settings").disabled) {
653
- token.addClass($(input).data("settings").classes.selectedToken);
654
- selected_token = token.get(0);
655
-
656
- // Hide input box
657
- input_box.val("");
658
-
659
- // Hide dropdown if it is visible (eg if we clicked to select token)
660
- hide_dropdown();
661
- }
662
- }
663
-
664
- // Deselect a token in the token list
665
- function deselect_token (token, position) {
666
- token.removeClass($(input).data("settings").classes.selectedToken);
667
- selected_token = null;
668
-
669
- if(position === POSITION.BEFORE) {
670
- input_token.insertBefore(token);
671
- selected_token_index--;
672
- } else if(position === POSITION.AFTER) {
673
- input_token.insertAfter(token);
674
- selected_token_index++;
675
- } else {
676
- input_token.appendTo(token_list);
677
- selected_token_index = token_count;
678
- }
679
-
680
- // Show the input box and give it focus again
681
- focus_with_timeout(input_box);
682
- }
683
-
684
- // Toggle selection of a token in the token list
685
- function toggle_select_token(token) {
686
- var previous_selected_token = selected_token;
687
-
688
- if(selected_token) {
689
- deselect_token($(selected_token), POSITION.END);
690
- }
691
-
692
- if(previous_selected_token === token.get(0)) {
693
- deselect_token(token, POSITION.END);
694
- } else {
695
- select_token(token);
696
- }
697
- }
698
-
699
- // Delete a token from the token list
700
- function delete_token (token) {
701
- // Remove the id from the saved list
702
- var token_data = $.data(token.get(0), "tokeninput");
703
- var callback = $(input).data("settings").onDelete;
704
-
705
- var index = token.prevAll().length;
706
- if(index > selected_token_index) index--;
707
-
708
- // Delete the token
709
- token.remove();
710
- selected_token = null;
711
-
712
- // Show the input box and give it focus again
713
- focus_with_timeout(input_box);
714
-
715
- // Remove this token from the saved list
716
- saved_tokens = saved_tokens.slice(0,index).concat(saved_tokens.slice(index+1));
717
- if(index < selected_token_index) selected_token_index--;
718
-
719
- // Update the hidden input
720
- update_hidden_input(saved_tokens, hidden_input);
721
-
722
- token_count -= 1;
723
-
724
- if($(input).data("settings").tokenLimit !== null) {
725
- input_box
726
- .show()
727
- .val("");
728
- focus_with_timeout(input_box);
729
- }
730
-
731
- // Execute the onDelete callback if defined
732
- if($.isFunction(callback)) {
733
- callback.call(hidden_input,token_data);
734
- }
735
- }
736
-
737
- // Update the hidden input box value
738
- function update_hidden_input(saved_tokens, hidden_input) {
739
- var token_values = $.map(saved_tokens, function (el) {
740
- if(typeof $(input).data("settings").tokenValue == 'function')
741
- return $(input).data("settings").tokenValue.call(this, el);
742
-
743
- return el[$(input).data("settings").tokenValue];
744
- });
745
- hidden_input.val(token_values.join($(input).data("settings").tokenDelimiter));
746
-
747
- }
748
-
749
- // Hide and clear the results dropdown
750
- function hide_dropdown () {
751
- dropdown.hide().empty();
752
- selected_dropdown_item = null;
753
- }
754
-
755
- function show_dropdown() {
756
- dropdown
757
- .css({
758
- position: "absolute",
759
- top: $(token_list).offset().top + $(token_list).outerHeight(),
760
- left: $(token_list).offset().left,
761
- width: $(token_list).width(),
762
- 'z-index': $(input).data("settings").zindex
763
- })
764
- .show();
765
- }
766
-
767
- function show_dropdown_searching () {
768
- if($(input).data("settings").searchingText) {
769
- dropdown.html("<p>" + escapeHTML($(input).data("settings").searchingText) + "</p>");
770
- show_dropdown();
771
- }
772
- }
773
-
774
- function show_dropdown_hint () {
775
- if($(input).data("settings").hintText) {
776
- dropdown.html("<p>" + escapeHTML($(input).data("settings").hintText) + "</p>");
777
- show_dropdown();
778
- }
779
- }
780
-
781
- var regexp_special_chars = new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]', 'g');
782
- function regexp_escape(term) {
783
- return term.replace(regexp_special_chars, '\\$&');
784
- }
785
-
786
- // Highlight the query part of the search term
787
- function highlight_term(value, term) {
788
- return value.replace(
789
- new RegExp(
790
- "(?![^&;]+;)(?!<[^<>]*)(" + regexp_escape(term) + ")(?![^<>]*>)(?![^&;]+;)",
791
- "gi"
792
- ), function(match, p1) {
793
- return "<b>" + escapeHTML(p1) + "</b>";
794
- }
795
- );
796
- }
797
-
798
- function find_value_and_highlight_term(template, value, term) {
799
- return template.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + regexp_escape(value) + ")(?![^<>]*>)(?![^&;]+;)", "g"), highlight_term(value, term));
800
- }
801
-
802
- // Populate the results dropdown with some results
803
- function populate_dropdown (query, results) {
804
- if(results && results.length) {
805
- dropdown.empty();
806
- var dropdown_ul = $("<ul>")
807
- .appendTo(dropdown)
808
- .mouseover(function (event) {
809
- select_dropdown_item($(event.target).closest("li"));
810
- })
811
- .mousedown(function (event) {
812
- add_token($(event.target).closest("li").data("tokeninput"));
813
- hidden_input.change();
814
- return false;
815
- })
816
- .hide();
817
-
818
- if ($(input).data("settings").resultsLimit && results.length > $(input).data("settings").resultsLimit) {
819
- results = results.slice(0, $(input).data("settings").resultsLimit);
820
- }
821
-
822
- $.each(results, function(index, value) {
823
- var this_li = $(input).data("settings").resultsFormatter(value);
824
-
825
- this_li = find_value_and_highlight_term(this_li ,value[$(input).data("settings").propertyToSearch], query);
826
-
827
- this_li = $(this_li).appendTo(dropdown_ul);
828
-
829
- if(index % 2) {
830
- this_li.addClass($(input).data("settings").classes.dropdownItem);
831
- } else {
832
- this_li.addClass($(input).data("settings").classes.dropdownItem2);
833
- }
834
-
835
- if(index === 0) {
836
- select_dropdown_item(this_li);
837
- }
838
-
839
- $.data(this_li.get(0), "tokeninput", value);
840
- });
841
-
842
- show_dropdown();
843
-
844
- if($(input).data("settings").animateDropdown) {
845
- dropdown_ul.slideDown("fast");
846
- } else {
847
- dropdown_ul.show();
848
- }
849
- } else {
850
- if($(input).data("settings").noResultsText) {
851
- dropdown.html("<p>" + escapeHTML($(input).data("settings").noResultsText) + "</p>");
852
- show_dropdown();
853
- }
854
- }
855
- }
856
-
857
- // Highlight an item in the results dropdown
858
- function select_dropdown_item (item) {
859
- if(item) {
860
- if(selected_dropdown_item) {
861
- deselect_dropdown_item($(selected_dropdown_item));
862
- }
863
-
864
- item.addClass($(input).data("settings").classes.selectedDropdownItem);
865
- selected_dropdown_item = item.get(0);
866
- }
867
- }
868
-
869
- // Remove highlighting from an item in the results dropdown
870
- function deselect_dropdown_item (item) {
871
- item.removeClass($(input).data("settings").classes.selectedDropdownItem);
872
- selected_dropdown_item = null;
873
- }
874
-
875
- // Do a search and show the "searching" dropdown if the input is longer
876
- // than $(input).data("settings").minChars
877
- function do_search() {
878
- var query = input_box.val();
879
-
880
- if(query && query.length) {
881
- if(selected_token) {
882
- deselect_token($(selected_token), POSITION.AFTER);
883
- }
884
-
885
- if(query.length >= $(input).data("settings").minChars) {
886
- show_dropdown_searching();
887
- clearTimeout(timeout);
888
-
889
- timeout = setTimeout(function(){
890
- run_search(query);
891
- }, $(input).data("settings").searchDelay);
892
- } else {
893
- hide_dropdown();
894
- }
895
- }
896
- }
897
-
898
- // Do the actual search
899
- function run_search(query) {
900
- var cache_key = query + computeURL();
901
- var cached_results = cache.get(cache_key);
902
- if(cached_results) {
903
- if ($.isFunction($(input).data("settings").onCachedResult)) {
904
- cached_results = $(input).data("settings").onCachedResult.call(hidden_input, cached_results);
905
- }
906
- populate_dropdown(query, cached_results);
907
- } else {
908
- // Are we doing an ajax search or local data search?
909
- if($(input).data("settings").url) {
910
- var url = computeURL();
911
- // Extract exisiting get params
912
- var ajax_params = {};
913
- ajax_params.data = {};
914
- if(url.indexOf("?") > -1) {
915
- var parts = url.split("?");
916
- ajax_params.url = parts[0];
917
-
918
- var param_array = parts[1].split("&");
919
- $.each(param_array, function (index, value) {
920
- var kv = value.split("=");
921
- ajax_params.data[kv[0]] = kv[1];
922
- });
923
- } else {
924
- ajax_params.url = url;
925
- }
926
-
927
- // Prepare the request
928
- ajax_params.data[$(input).data("settings").queryParam] = query;
929
- ajax_params.type = $(input).data("settings").method;
930
- ajax_params.dataType = $(input).data("settings").contentType;
931
- if($(input).data("settings").crossDomain) {
932
- ajax_params.dataType = "jsonp";
933
- }
934
-
935
- // Attach the success callback
936
- ajax_params.success = function(results) {
937
- cache.add(cache_key, $(input).data("settings").jsonContainer ? results[$(input).data("settings").jsonContainer] : results);
938
- if($.isFunction($(input).data("settings").onResult)) {
939
- results = $(input).data("settings").onResult.call(hidden_input, results);
940
- }
941
-
942
- // only populate the dropdown if the results are associated with the active search query
943
- if(input_box.val() === query) {
944
- populate_dropdown(query, $(input).data("settings").jsonContainer ? results[$(input).data("settings").jsonContainer] : results);
945
- }
946
- };
947
-
948
- // Make the request
949
- $.ajax(ajax_params);
950
- } else if($(input).data("settings").local_data) {
951
- // Do the search through local data
952
- var results = $.grep($(input).data("settings").local_data, function (row) {
953
- return row[$(input).data("settings").propertyToSearch].toLowerCase().indexOf(query.toLowerCase()) > -1;
954
- });
955
-
956
- cache.add(cache_key, results);
957
- if($.isFunction($(input).data("settings").onResult)) {
958
- results = $(input).data("settings").onResult.call(hidden_input, results);
959
- }
960
- populate_dropdown(query, results);
961
- }
962
- }
963
- }
964
-
965
- // compute the dynamic URL
966
- function computeURL() {
967
- var url = $(input).data("settings").url;
968
- if(typeof $(input).data("settings").url == 'function') {
969
- url = $(input).data("settings").url.call($(input).data("settings"));
970
- }
971
- return url;
972
- }
973
-
974
- // Bring browser focus to the specified object.
975
- // Use of setTimeout is to get around an IE bug.
976
- // (See, e.g., http://stackoverflow.com/questions/2600186/focus-doesnt-work-in-ie)
977
- //
978
- // obj: a jQuery object to focus()
979
- function focus_with_timeout(obj) {
980
- setTimeout(function() { obj.focus(); }, 50);
981
- }
982
-
983
- };
984
-
985
- // Really basic cache for the results
986
- $.TokenList.Cache = function (options) {
987
- var settings = $.extend({
988
- max_size: 500
989
- }, options);
990
-
991
- var data = {};
992
- var size = 0;
993
-
994
- var flush = function () {
995
- data = {};
996
- size = 0;
997
- };
998
-
999
- this.add = function (query, results) {
1000
- if(size > settings.max_size) {
1001
- flush();
1002
- }
1003
-
1004
- if(!data[query]) {
1005
- size += 1;
1006
- }
1007
-
1008
- data[query] = results;
1009
- };
1010
-
1011
- this.get = function (query) {
1012
- return data[query];
1013
- };
1014
- };
1015
- }(jQuery));