2 * Tag Selector plugin for jQuery: Facilitates selecting multiple tags by extending jQuery UI Autocomplete.
3 * You may use Tag Selector under the terms of either the MIT License or the GNU General Public License (GPL) Version 2.
4 * https://petprojects.googlecode.com/svn/trunk/MIT-LICENSE.txt
5 * https://petprojects.googlecode.com/svn/trunk/GPL-LICENSE.txt
8 function hide_error(input) {
9 var err = input.parent().parent().find(".invalid-remaining");
13 function show_error(input, msg) {
14 var err = input.parent().parent().find(".invalid-remaining");
15 console.log(err.length);
20 $.fn.selectSelector = function(source, select) {
21 return this.each(function() {
22 var selector = $(this),
23 input = $('input[type=text]', this);
25 selector.click(function() { input.focus(); })
26 .delegate('.badge a', 'click', function() {
27 var id = $(this).parent().data("id");
28 select.find("option[value=" + id + "]").attr("selected", false)
32 function addTag(id, text) {
33 const idx = text.indexOf(':');
35 text = text.substr(0, idx);
38 $('<span class="badge badge-pill badge-primary"/>')
43 input.attr("placeholder", null);
44 select.find("option[value='" + id + "']").attr("selected", "selected")
49 selector.find("span").remove();
50 select.find("option").each(function() {
51 if (this.hasAttribute("selected")) {
52 addTag(this.getAttribute("value"), this.innerText);
58 input.focusout(function(e) {
59 var value = input.val().trim()
61 show_error(input, "Please select an existing tag, it;s not possible to add custom ones.");
65 input.keydown(function(e) {
66 if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
72 select: function(event, ui) {
73 addTag(ui.item.id, ui.item.toString());
78 // The following works only once.
79 // $(this).trigger('keydown.autocomplete');
80 // As suggested by digitalPBK, works multiple times
81 // $(this).data("autocomplete").search($(this).val());
82 // As noted by Jonny in his answer, with newer versions use uiAutocomplete
83 $(this).data("ui-autocomplete").search($(this).val());
86 input.data('ui-autocomplete')._renderItem = function(ul, item) {
88 .data('item.autocomplete', item)
89 .append($('<a/>').text(item.toString()))
93 input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
94 var ul = this.menu.element;
95 ul.outerWidth(Math.max(
96 ul.width('').outerWidth(),
103 $.fn.csvSelector = function(source, name, result, allowSlash) {
104 return this.each(function() {
105 var selector = $(this),
106 input = $('input[type=text]', this);
110 for (var i = 0; i < source.length; i++) {
111 lookup[source[i].id] = source[i];
114 selector.click(function() { input.focus(); })
115 .delegate('.badge a', 'click', function() {
116 var id = $(this).parent().data("id");
117 for (var i = 0; i < selected.length; i++) {
118 if (selected[i] == id) {
119 selected.splice(i, 1);
125 function selectItem(id) {
126 for (var i = 0; i < selected.length; i++) {
127 if (selected[i] == id) {
135 function addTag(id, value) {
136 var tag = $('<span class="badge badge-pill badge-primary"/>')
140 .insertBefore(input);
142 input.attr("placeholder", null);
146 function recreate() {
147 selector.find("span").remove();
148 for (var i = 0; i < selected.length; i++) {
149 var value = lookup[selected[i]] || { value: selected[i] };
150 addTag(selected[i], value.value);
152 result.val(selected.join(","))
155 function readFromResult() {
157 var selected_raw = result.val().split(",");
158 for (var i = 0; i < selected_raw.length; i++) {
159 var raw = selected_raw[i].trim();
160 if (lookup[raw] || raw.match(/^([a-z0-9_]+)$/)) {
169 result.change(readFromResult);
171 input.focusout(function() {
172 var item = input.val();
173 if (item.length == 0) {
174 input.data("ui-autocomplete").search("");
175 } else if (item.match(/^([a-z0-9_]+)$/)) {
183 input.keydown(function(e) {
184 if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
186 else if (e.keyCode === $.ui.keyCode.COMMA) {
187 var item = input.val();
188 if (item.length == 0) {
189 input.data("ui-autocomplete").search("");
190 } else if (item.match(/^([a-z0-9_]+)$/)) {
195 show_error(input, "Only lowercase alphanumeric and number names allowed.");
199 } else if (e.keyCode === $.ui.keyCode.BACKSPACE) {
200 if (input.val() == "") {
201 var item = selected[selected.length - 1];
202 selected.splice(selected.length - 1, 1);
204 if (!(item.indexOf("/") > 0))
214 select: function(event, ui) {
215 selectItem(ui.item.id);
222 input.data('ui-autocomplete')._renderItem = function(ul, item) {
224 .data('item.autocomplete', item)
225 .append($('<a/>').text(item.toString()))
229 input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
230 var ul = this.menu.element;
231 ul.outerWidth(Math.max(
232 ul.width('').outerWidth(),
233 selector.outerWidth()
240 $(".multichoice_selector").each(function() {
242 var sel = ele.parent().find("select");
246 sel.find("option").each(function() {
247 var text = $(this).text();
249 id: $(this).attr("value"),
251 selected: $(this).attr("selected") ? true : false,
252 toString: function() { return text; },
256 ele.selectSelector(options, sel);
259 $(".metapackage_selector").each(function() {
260 var input = $(this).parent().children("input[type='text']");
262 $(this).csvSelector(meta_packages, input.attr("name"), input);
265 $(".deps_selector").each(function() {
266 var input = $(this).parent().children("input[type='text']");
268 $(this).csvSelector(all_packages, input.attr("name"), input);