blacklight-spotlight 4.7.1 → 5.0.0.pre.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -12
  3. data/Rakefile +8 -1
  4. data/app/assets/javascripts/spotlight/application.js +0 -1
  5. data/app/assets/javascripts/spotlight/spotlight.esm.js +3620 -3847
  6. data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
  7. data/app/assets/javascripts/spotlight/spotlight.js +3620 -3852
  8. data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
  9. data/app/assets/stylesheets/spotlight/_accessibility.scss +0 -9
  10. data/app/assets/stylesheets/spotlight/_autocomplete.scss +49 -0
  11. data/app/assets/stylesheets/spotlight/_blacklight_configuration.scss +0 -1
  12. data/app/assets/stylesheets/spotlight/_blacklight_overrides.scss +1 -6
  13. data/app/assets/stylesheets/spotlight/_browse.scss +2 -2
  14. data/app/assets/stylesheets/spotlight/_catalog.scss +40 -41
  15. data/app/assets/stylesheets/spotlight/_curation.scss +1 -1
  16. data/app/assets/stylesheets/spotlight/_exhibit_admin.scss +7 -0
  17. data/app/assets/stylesheets/spotlight/_exhibits_index.scss +8 -5
  18. data/app/assets/stylesheets/spotlight/_featured_browse_categories_block.scss +3 -3
  19. data/app/assets/stylesheets/spotlight/_header.scss +13 -0
  20. data/app/assets/stylesheets/spotlight/_mixins.scss +3 -4
  21. data/app/assets/stylesheets/spotlight/_nestable.scss +2 -12
  22. data/app/assets/stylesheets/spotlight/_pages.scss +11 -9
  23. data/app/assets/stylesheets/spotlight/_report_a_problem.scss +1 -3
  24. data/app/assets/stylesheets/spotlight/_sir-trevor_overrides.scss +2 -2
  25. data/app/assets/stylesheets/spotlight/_spotlight.scss +2 -1
  26. data/app/assets/stylesheets/spotlight/_tag_selector.scss +34 -0
  27. data/app/assets/stylesheets/spotlight/_variables.scss +0 -8
  28. data/app/components/spotlight/analytics/dashboard_component.html.erb +3 -3
  29. data/app/components/spotlight/breadcrumbs_component.html.erb +13 -19
  30. data/app/components/spotlight/bulk_action_component.rb +1 -1
  31. data/app/components/spotlight/document_component.rb +1 -1
  32. data/app/components/spotlight/save_search_component.rb +1 -1
  33. data/app/components/spotlight/select_image_component.html.erb +17 -0
  34. data/app/components/spotlight/select_image_component.rb +24 -0
  35. data/app/components/spotlight/skip_link_component.rb +16 -0
  36. data/app/components/spotlight/tag_selector_component.html.erb +40 -0
  37. data/app/components/spotlight/tag_selector_component.rb +41 -0
  38. data/app/components/spotlight/tag_selector_component.yml +6 -0
  39. data/app/components/spotlight/title_component.html.erb +8 -0
  40. data/app/components/spotlight/title_component.rb +22 -0
  41. data/app/controllers/spotlight/accessibility_controller.rb +2 -2
  42. data/app/controllers/spotlight/catalog_controller.rb +7 -2
  43. data/app/controllers/spotlight/contact_email_controller.rb +8 -2
  44. data/app/controllers/spotlight/languages_controller.rb +9 -4
  45. data/app/helpers/spotlight/application_helper.rb +7 -0
  46. data/app/helpers/spotlight/crop_helper.rb +4 -0
  47. data/app/helpers/spotlight/meta_helper.rb +59 -36
  48. data/app/javascript/spotlight/admin/blacklight_configuration.js +1 -1
  49. data/app/javascript/spotlight/admin/block_mixins/autocompleteable.js +70 -34
  50. data/app/javascript/spotlight/admin/blocks/block.js +1 -0
  51. data/app/javascript/spotlight/admin/blocks/browse_block.js +8 -12
  52. data/app/javascript/spotlight/admin/blocks/browse_group_categories_block.js +14 -18
  53. data/app/javascript/spotlight/admin/blocks/pages_block.js +6 -10
  54. data/app/javascript/spotlight/admin/blocks/resources_block.js +33 -15
  55. data/app/javascript/spotlight/admin/blocks/solr_documents_base_block.js +11 -6
  56. data/app/javascript/spotlight/admin/blocks/solr_documents_embed_block.js +1 -0
  57. data/app/javascript/spotlight/admin/blocks/uploaded_items_block.js +4 -3
  58. data/app/javascript/spotlight/admin/copy_email_addresses.js +2 -0
  59. data/app/javascript/spotlight/admin/crop.js +45 -17
  60. data/app/javascript/spotlight/admin/croppable.js +8 -1
  61. data/app/javascript/spotlight/admin/croppable_modal.js +68 -0
  62. data/app/javascript/spotlight/admin/exhibits.js +15 -10
  63. data/app/javascript/spotlight/admin/form_observer.js +1 -1
  64. data/app/javascript/spotlight/admin/index.js +0 -10
  65. data/app/javascript/spotlight/admin/locks.js +15 -5
  66. data/app/javascript/spotlight/admin/pages.js +1 -1
  67. data/app/javascript/spotlight/admin/search_typeahead.js +62 -55
  68. data/app/javascript/spotlight/admin/spotlight_nestable.js +173 -50
  69. data/app/javascript/spotlight/admin/visibility_toggle.js +1 -11
  70. data/app/javascript/spotlight/controllers/index.js +8 -0
  71. data/app/javascript/spotlight/controllers/tag_selector_controller.js +203 -0
  72. data/app/javascript/spotlight/core.js +4 -6
  73. data/app/javascript/spotlight/index.js +2 -0
  74. data/app/javascript/spotlight/user/browse_group_categories.js +2 -0
  75. data/app/javascript/spotlight/user/carousel.js +3 -1
  76. data/app/javascript/spotlight/user/index.js +0 -2
  77. data/app/models/sir_trevor_rails/block.rb +5 -4
  78. data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +1 -1
  79. data/app/models/sir_trevor_rails/blocks/solr_documents_embed_block.rb +1 -1
  80. data/app/models/sir_trevor_rails/blocks/uploaded_items_block.rb +1 -1
  81. data/app/models/spotlight/page_configurations.rb +1 -1
  82. data/app/views/catalog/_add_tags.html.erb +2 -2
  83. data/app/views/catalog/_change_visibility.html.erb +1 -1
  84. data/app/views/catalog/_remove_tags.html.erb +2 -2
  85. data/app/views/layouts/spotlight/base.html.erb +24 -13
  86. data/app/views/layouts/spotlight/spotlight.html.erb +6 -6
  87. data/app/views/shared/_masthead.html.erb +4 -31
  88. data/app/views/shared/_site_sidebar.html.erb +1 -1
  89. data/app/views/shared/_user_util_links.html.erb +3 -1
  90. data/app/views/spotlight/accessibility/alt_text.html.erb +2 -2
  91. data/app/views/spotlight/admin_users/index.html.erb +3 -3
  92. data/app/views/spotlight/appearances/edit.html.erb +1 -1
  93. data/app/views/spotlight/browse/_search_box.html.erb +8 -8
  94. data/app/views/spotlight/browse/show.html.erb +1 -1
  95. data/app/views/spotlight/bulk_updates/_download.html.erb +1 -1
  96. data/app/views/spotlight/bulk_updates/_upload.html.erb +1 -1
  97. data/app/views/spotlight/catalog/_admin_header.html.erb +1 -1
  98. data/app/views/spotlight/catalog/_edit_default.html.erb +2 -1
  99. data/app/views/spotlight/catalog/select_image.html.erb +1 -0
  100. data/app/views/spotlight/contacts/_form.html.erb +1 -1
  101. data/app/views/spotlight/exhibits/_contact.html.erb +5 -6
  102. data/app/views/spotlight/exhibits/_delete.html.erb +1 -1
  103. data/app/views/spotlight/exhibits/_languages.html.erb +3 -2
  104. data/app/views/spotlight/featured_images/_form.html.erb +6 -2
  105. data/app/views/spotlight/featured_images/_upload_form.html.erb +1 -1
  106. data/app/views/spotlight/metadata_configurations/_metadata_field.html.erb +1 -1
  107. data/app/views/spotlight/metadata_configurations/edit.html.erb +6 -6
  108. data/app/views/spotlight/pages/show.html.erb +1 -1
  109. data/app/views/spotlight/resources/csv_upload/_form.html.erb +1 -1
  110. data/app/views/spotlight/resources/upload/_form.html.erb +1 -1
  111. data/app/views/spotlight/roles/index.html.erb +1 -1
  112. data/app/views/spotlight/searches/_form.html.erb +1 -1
  113. data/app/views/spotlight/shared/_dd3_item.html.erb +1 -1
  114. data/app/views/spotlight/sir_trevor/blocks/_browse_group_categories_block.html.erb +1 -1
  115. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_block.html.erb +1 -1
  116. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +1 -1
  117. data/app/views/spotlight/sir_trevor/blocks/_uploaded_items_block.html.erb +1 -1
  118. data/app/views/spotlight/tags/index.html.erb +2 -3
  119. data/app/views/spotlight/translations/_import.html.erb +2 -2
  120. data/config/importmap.rb +5 -0
  121. data/config/locales/spotlight.en.yml +2 -0
  122. data/config/routes.rb +5 -3
  123. data/lib/generators/spotlight/assets/generator_common_utilities.rb +36 -0
  124. data/lib/generators/spotlight/assets/importmap_generator.rb +87 -0
  125. data/lib/generators/spotlight/assets/propshaft_generator.rb +96 -0
  126. data/lib/generators/spotlight/assets_generator.rb +22 -0
  127. data/lib/generators/spotlight/install_generator.rb +8 -36
  128. data/lib/generators/spotlight/scaffold_resource_generator.rb +1 -1
  129. data/lib/generators/spotlight/templates/assets/spotlight.scss +6 -0
  130. data/lib/generators/spotlight/templates/javascript/jquery-shim.js +1 -0
  131. data/lib/spotlight/engine.rb +7 -6
  132. data/lib/spotlight/version.rb +1 -1
  133. data/spec/support/features/capybara_wait_metadata_helper.rb +13 -0
  134. data/spec/support/features/test_features_helpers.rb +16 -30
  135. data/vendor/assets/javascripts/tiny-slider.js +3 -0
  136. metadata +35 -87
  137. data/app/assets/stylesheets/spotlight/#_accessibility.scss# +0 -12
  138. data/app/javascript/spotlight/admin/checkbox_submit.js +0 -75
  139. data/app/javascript/spotlight/admin/exhibit_tag_autocomplete.js +0 -39
  140. data/app/javascript/spotlight/user/report_a_problem.js +0 -30
  141. data/app/views/spotlight/browse/_tophat.html.erb +0 -1
  142. data/app/views/spotlight/catalog/_tophat_default.html.erb +0 -1
  143. data/app/views/spotlight/home_pages/_tophat.html.erb +0 -2
  144. data/app/views/spotlight/pages/_tophat.html.erb +0 -1
  145. data/lib/generators/spotlight/templates/spotlight.js +0 -1
  146. data/lib/generators/spotlight/templates/spotlight.scss +0 -5
  147. data/spec/support/features/capybara_default_max_wait_metadata_helper.rb +0 -20
  148. data/vendor/assets/javascripts/bootstrap-tagsinput.js +0 -530
  149. data/vendor/assets/javascripts/jquery.serializejson.js +0 -234
  150. data/vendor/assets/javascripts/nestable.js +0 -645
  151. data/vendor/assets/javascripts/sir-trevor.js +0 -23508
  152. data/vendor/assets/javascripts/typeahead.bundle.min.js +0 -7
  153. data/vendor/assets/stylesheets/bootstrap-tagsinput.css +0 -46
@@ -1,530 +0,0 @@
1
- /* From https://github.com/TimSchlechter/bootstrap-tagsinput/blob/2661784c2c281d3a69b93897ff3f39e4ffa5cbd1/dist/bootstrap-tagsinput.js */
2
-
3
- /* The MIT License (MIT)
4
-
5
- Copyright (c) 2013 Tim Schlechter
6
-
7
- Permission is hereby granted, free of charge, to any person obtaining a copy of
8
- this software and associated documentation files (the "Software"), to deal in
9
- the Software without restriction, including without limitation the rights to
10
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11
- the Software, and to permit persons to whom the Software is furnished to do so,
12
- subject to the following conditions:
13
-
14
- The above copyright notice and this permission notice shall be included in all
15
- copies or substantial portions of the Software.
16
-
17
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
- */
24
-
25
- /* Retrieved 12 February 2014 */
26
-
27
- (function ($) {
28
- "use strict";
29
-
30
- var defaultOptions = {
31
- tagClass: function(item) {
32
- return 'badge badge-info bg-info';
33
- },
34
- itemValue: function(item) {
35
- return item ? item.toString() : item;
36
- },
37
- itemText: function(item) {
38
- return this.itemValue(item);
39
- },
40
- freeInput: true,
41
- maxTags: undefined,
42
- confirmKeys: [13],
43
- onTagExists: function(item, $tag) {
44
- $tag.hide().fadeIn();
45
- }
46
- };
47
-
48
- /**
49
- * Constructor function
50
- */
51
- function TagsInput(element, options) {
52
- this.itemsArray = [];
53
-
54
- this.$element = $(element);
55
- this.$element.hide();
56
-
57
- this.isSelect = (element.tagName === 'SELECT');
58
- this.multiple = (this.isSelect && element.hasAttribute('multiple'));
59
- this.objectItems = options && options.itemValue;
60
- this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
61
- this.inputSize = Math.max(1, this.placeholderText.length);
62
-
63
- this.$container = $('<div class="bootstrap-tagsinput"></div>');
64
- this.$input = $('<input size="' + this.inputSize + '" type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
65
-
66
- this.$element.after(this.$container);
67
-
68
- this.build(options);
69
- }
70
-
71
- TagsInput.prototype = {
72
- constructor: TagsInput,
73
-
74
- /**
75
- * Adds the given item as a new tag. Pass true to dontPushVal to prevent
76
- * updating the elements val()
77
- */
78
- add: function(item, dontPushVal) {
79
- var self = this;
80
-
81
- if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
82
- return;
83
-
84
- // Ignore falsey values, except false
85
- if (item !== false && !item)
86
- return;
87
-
88
- // Throw an error when trying to add an object while the itemValue option was not set
89
- if (typeof item === "object" && !self.objectItems)
90
- throw("Can't add objects when itemValue option is not set");
91
-
92
- // Ignore strings only containg whitespace
93
- if (item.toString().match(/^\s*$/))
94
- return;
95
-
96
- // If SELECT but not multiple, remove current tag
97
- if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
98
- self.remove(self.itemsArray[0]);
99
-
100
- if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
101
- var items = item.split(',');
102
- if (items.length > 1) {
103
- for (var i = 0; i < items.length; i++) {
104
- this.add(items[i], true);
105
- }
106
-
107
- if (!dontPushVal)
108
- self.pushVal();
109
- return;
110
- }
111
- }
112
-
113
- var itemValue = self.options.itemValue(item),
114
- itemText = self.options.itemText(item),
115
- tagClass = self.options.tagClass(item);
116
-
117
- // Ignore items allready added
118
- var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0];
119
- if (existing) {
120
- // Invoke onTagExists
121
- if (self.options.onTagExists) {
122
- var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; });
123
- self.options.onTagExists(item, $existingTag);
124
- }
125
- return;
126
- }
127
-
128
- // register item in internal array and map
129
- self.itemsArray.push(item);
130
-
131
- // add a tag element
132
- var $tag = $('<span class="tag ' + htmlEncode(tagClass) + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
133
- $tag.data('item', item);
134
- self.findInputWrapper().before($tag);
135
- $tag.after(' ');
136
-
137
- // add <option /> if item represents a value not present in one of the <select />'s options
138
- if (self.isSelect && !$('option[value="' + escape(itemValue) + '"]',self.$element)[0]) {
139
- var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
140
- $option.data('item', item);
141
- $option.attr('value', itemValue);
142
- self.$element.append($option);
143
- }
144
-
145
- if (!dontPushVal)
146
- self.pushVal();
147
-
148
- // Add class when reached maxTags
149
- if (self.options.maxTags === self.itemsArray.length)
150
- self.$container.addClass('bootstrap-tagsinput-max');
151
-
152
- self.$element.trigger($.Event('itemAdded', { item: item }));
153
- },
154
-
155
- /**
156
- * Removes the given item. Pass true to dontPushVal to prevent updating the
157
- * elements val()
158
- */
159
- remove: function(item, dontPushVal) {
160
- var self = this;
161
-
162
- if (self.objectItems) {
163
- if (typeof item === "object")
164
- item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == self.options.itemValue(item); } )[0];
165
- else
166
- item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == item; } )[0];
167
- }
168
-
169
- if (item) {
170
- $('.tag', self.$container).filter(function() { return $(this).data('item') === item; }).remove();
171
- $('option', self.$element).filter(function() { return $(this).data('item') === item; }).remove();
172
- self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
173
- }
174
-
175
- if (!dontPushVal)
176
- self.pushVal();
177
-
178
- // Remove class when reached maxTags
179
- if (self.options.maxTags > self.itemsArray.length)
180
- self.$container.removeClass('bootstrap-tagsinput-max');
181
-
182
- self.$element.trigger($.Event('itemRemoved', { item: item }));
183
- },
184
-
185
- /**
186
- * Removes all items
187
- */
188
- removeAll: function() {
189
- var self = this;
190
-
191
- $('.tag', self.$container).remove();
192
- $('option', self.$element).remove();
193
-
194
- while(self.itemsArray.length > 0)
195
- self.itemsArray.pop();
196
-
197
- self.pushVal();
198
-
199
- if (self.options.maxTags && !this.isEnabled())
200
- this.enable();
201
- },
202
-
203
- /**
204
- * Refreshes the tags so they match the text/value of their corresponding
205
- * item.
206
- */
207
- refresh: function() {
208
- var self = this;
209
- $('.tag', self.$container).each(function() {
210
- var $tag = $(this),
211
- item = $tag.data('item'),
212
- itemValue = self.options.itemValue(item),
213
- itemText = self.options.itemText(item),
214
- tagClass = self.options.tagClass(item);
215
-
216
- // Update tag's class and inner text
217
- $tag.attr('class', null);
218
- $tag.addClass('tag ' + htmlEncode(tagClass));
219
- $tag.contents().filter(function() {
220
- return this.nodeType == 3;
221
- })[0].nodeValue = htmlEncode(itemText);
222
-
223
- if (self.isSelect) {
224
- var option = $('option', self.$element).filter(function() { return $(this).data('item') === item; });
225
- option.attr('value', itemValue);
226
- }
227
- });
228
- },
229
-
230
- /**
231
- * Returns the items added as tags
232
- */
233
- items: function() {
234
- return this.itemsArray;
235
- },
236
-
237
- /**
238
- * Assembly value by retrieving the value of each item, and set it on the
239
- * element.
240
- */
241
- pushVal: function() {
242
- var self = this,
243
- val = $.map(self.items(), function(item) {
244
- return self.options.itemValue(item).toString();
245
- });
246
-
247
- self.$element.val(val, true).trigger('change');
248
- },
249
-
250
- /**
251
- * Initializes the tags input behaviour on the element
252
- */
253
- build: function(options) {
254
- var self = this;
255
-
256
- self.options = $.extend({}, defaultOptions, options);
257
- var typeahead = self.options.typeahead || {};
258
-
259
- // When itemValue is set, freeInput should always be false
260
- if (self.objectItems)
261
- self.options.freeInput = false;
262
-
263
- makeOptionItemFunction(self.options, 'itemValue');
264
- makeOptionItemFunction(self.options, 'itemText');
265
- makeOptionItemFunction(self.options, 'tagClass');
266
-
267
- // for backwards compatibility, self.options.source is deprecated
268
- if (self.options.source)
269
- typeahead.source = self.options.source;
270
-
271
- if (typeahead.source && $.fn.typeahead) {
272
- makeOptionFunction(typeahead, 'source');
273
-
274
- self.$input.typeahead({
275
- source: function (query, process) {
276
- function processItems(items) {
277
- var texts = [];
278
-
279
- for (var i = 0; i < items.length; i++) {
280
- var text = self.options.itemText(items[i]);
281
- map[text] = items[i];
282
- texts.push(text);
283
- }
284
- process(texts);
285
- }
286
-
287
- this.map = {};
288
- var map = this.map,
289
- data = typeahead.source(query);
290
-
291
- if ($.isFunction(data.success)) {
292
- // support for Angular promises
293
- data.success(processItems);
294
- } else {
295
- // support for functions and jquery promises
296
- $.when(data)
297
- .then(processItems);
298
- }
299
- },
300
- updater: function (text) {
301
- self.add(this.map[text]);
302
- },
303
- matcher: function (text) {
304
- return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
305
- },
306
- sorter: function (texts) {
307
- return texts.sort();
308
- },
309
- highlighter: function (text) {
310
- var regex = new RegExp( '(' + this.query + ')', 'gi' );
311
- return text.replace( regex, "<strong>$1</strong>" );
312
- }
313
- });
314
- }
315
-
316
- self.$container.on('click', $.proxy(function(event) {
317
- self.$input.focus();
318
- }, self));
319
-
320
- self.$container.on('keydown', 'input', $.proxy(function(event) {
321
- var $input = $(event.target),
322
- $inputWrapper = self.findInputWrapper();
323
-
324
- switch (event.which) {
325
- // BACKSPACE
326
- case 8:
327
- if (doGetCaretPosition($input[0]) === 0) {
328
- var prev = $inputWrapper.prev();
329
- if (prev) {
330
- self.remove(prev.data('item'));
331
- }
332
- }
333
- break;
334
-
335
- // DELETE
336
- case 46:
337
- if (doGetCaretPosition($input[0]) === 0) {
338
- var next = $inputWrapper.next();
339
- if (next) {
340
- self.remove(next.data('item'));
341
- }
342
- }
343
- break;
344
-
345
- // LEFT ARROW
346
- case 37:
347
- // Try to move the input before the previous tag
348
- var $prevTag = $inputWrapper.prev();
349
- if ($input.val().length === 0 && $prevTag[0]) {
350
- $prevTag.before($inputWrapper);
351
- $input.focus();
352
- }
353
- break;
354
- // RIGHT ARROW
355
- case 39:
356
- // Try to move the input after the next tag
357
- var $nextTag = $inputWrapper.next();
358
- if ($input.val().length === 0 && $nextTag[0]) {
359
- $nextTag.after($inputWrapper);
360
- $input.focus();
361
- }
362
- break;
363
- default:
364
- // When key corresponds one of the confirmKeys, add current input
365
- // as a new tag
366
- if (self.options.freeInput && $.inArray(event.which, self.options.confirmKeys) >= 0) {
367
- self.add($input.val());
368
- $input.val('');
369
- event.preventDefault();
370
- }
371
- }
372
-
373
- // Reset internal input's size
374
- $input.attr('size', Math.max(this.inputSize, $input.val().length));
375
- }, self));
376
-
377
- // Remove icon clicked
378
- self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
379
- self.remove($(event.target).closest('.tag').data('item'));
380
- }, self));
381
-
382
- // Only add existing value as tags when using strings as tags
383
- if (self.options.itemValue === defaultOptions.itemValue) {
384
- if (self.$element[0].tagName === 'INPUT') {
385
- self.add(self.$element.val());
386
- } else {
387
- $('option', self.$element).each(function() {
388
- self.add($(this).attr('value'), true);
389
- });
390
- }
391
- }
392
- },
393
-
394
- /**
395
- * Removes all tagsinput behaviour and unregsiter all event handlers
396
- */
397
- destroy: function() {
398
- var self = this;
399
-
400
- // Unbind events
401
- self.$container.off('keypress', 'input');
402
- self.$container.off('click', '[role=remove]');
403
-
404
- self.$container.remove();
405
- self.$element.removeData('tagsinput');
406
- self.$element.show();
407
- },
408
-
409
- /**
410
- * Sets focus on the tagsinput
411
- */
412
- focus: function() {
413
- this.$input.focus();
414
- },
415
-
416
- /**
417
- * Returns the internal input element
418
- */
419
- input: function() {
420
- return this.$input;
421
- },
422
-
423
- /**
424
- * Returns the element which is wrapped around the internal input. This
425
- * is normally the $container, but typeahead.js moves the $input element.
426
- */
427
- findInputWrapper: function() {
428
- var elt = this.$input[0],
429
- container = this.$container[0];
430
- while(elt && elt.parentNode !== container)
431
- elt = elt.parentNode;
432
-
433
- return $(elt);
434
- }
435
- };
436
-
437
- /**
438
- * Register JQuery plugin
439
- */
440
- $.fn.tagsinput = function(arg1, arg2) {
441
- var results = [];
442
-
443
- this.each(function() {
444
- var tagsinput = $(this).data('tagsinput');
445
-
446
- // Initialize a new tags input
447
- if (!tagsinput) {
448
- tagsinput = new TagsInput(this, arg1);
449
- $(this).data('tagsinput', tagsinput);
450
- results.push(tagsinput);
451
-
452
- if (this.tagName === 'SELECT') {
453
- $('option', $(this)).attr('selected', 'selected');
454
- }
455
-
456
- // Init tags from $(this).val()
457
- $(this).val($(this).val());
458
- } else {
459
- // Invoke function on existing tags input
460
- var retVal = tagsinput[arg1](arg2);
461
- if (retVal !== undefined)
462
- results.push(retVal);
463
- }
464
- });
465
-
466
- if ( typeof arg1 == 'string') {
467
- // Return the results from the invoked function calls
468
- return results.length > 1 ? results : results[0];
469
- } else {
470
- return results;
471
- }
472
- };
473
-
474
- $.fn.tagsinput.Constructor = TagsInput;
475
-
476
- /**
477
- * Most options support both a string or number as well as a function as
478
- * option value. This function makes sure that the option with the given
479
- * key in the given options is wrapped in a function
480
- */
481
- function makeOptionItemFunction(options, key) {
482
- if (typeof options[key] !== 'function') {
483
- var propertyName = options[key];
484
- options[key] = function(item) { return item[propertyName]; };
485
- }
486
- }
487
- function makeOptionFunction(options, key) {
488
- if (typeof options[key] !== 'function') {
489
- var value = options[key];
490
- options[key] = function() { return value; };
491
- }
492
- }
493
- /**
494
- * HtmlEncodes the given value
495
- */
496
- var htmlEncodeContainer = $('<div />');
497
- function htmlEncode(value) {
498
- if (value) {
499
- return htmlEncodeContainer.text(value).html();
500
- } else {
501
- return '';
502
- }
503
- }
504
-
505
- /**
506
- * Returns the position of the caret in the given input field
507
- * http://flightschool.acylt.com/devnotes/caret-position-woes/
508
- */
509
- function doGetCaretPosition(oField) {
510
- var iCaretPos = 0;
511
- if (document.selection) {
512
- oField.focus ();
513
- var oSel = document.selection.createRange();
514
- oSel.moveStart ('character', -oField.value.length);
515
- iCaretPos = oSel.text.length;
516
- } else if (oField.selectionStart || oField.selectionStart == '0') {
517
- iCaretPos = oField.selectionStart;
518
- }
519
- return (iCaretPos);
520
- }
521
-
522
- /**
523
- * Initialize tagsinput behaviour on inputs and selects which have
524
- * data-role=tagsinput
525
- */
526
- $(function() {
527
- $("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
528
- });
529
- })(window.jQuery);
530
-