]> git.lizzy.rs Git - cheatdb.git/blob - app/public/static/tagselector.js
Add descriptions to tags, and show in multiselect
[cheatdb.git] / app / public / static / tagselector.js
1 /*!
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
6  */
7 (function($) {
8         function hide_error(input) {
9                 var err = input.parent().parent().find(".invalid-remaining");
10                 err.hide();
11         }
12
13         function show_error(input, msg) {
14                 var err = input.parent().parent().find(".invalid-remaining");
15                 console.log(err.length);
16                 err.text(msg);
17                 err.show();
18         }
19
20         $.fn.selectSelector = function(source, select) {
21                 return this.each(function() {
22                         var selector = $(this),
23                                 input = $('input[type=text]', this);
24
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)
29                                         recreate();
30                                 });
31
32                         function addTag(id, text) {
33                                 const idx = text.indexOf(':');
34                                 if (idx > 0) {
35                                         text = text.substr(0, idx);
36                                 }
37
38                                 $('<span class="badge badge-pill badge-primary"/>')
39                                         .text(text + ' ')
40                                         .data("id", id)
41                                         .append('<a>x</a>')
42                                         .insertBefore(input);
43                                 input.attr("placeholder", null);
44                                 select.find("option[value='" + id + "']").attr("selected", "selected")
45                                 hide_error(input);
46                         }
47
48                         function recreate() {
49                                 selector.find("span").remove();
50                                 select.find("option").each(function() {
51                                         if (this.hasAttribute("selected")) {
52                                                 addTag(this.getAttribute("value"), this.innerText);
53                                         }
54                                 });
55                         }
56                         recreate();
57
58                         input.focusout(function(e) {
59                                 var value = input.val().trim()
60                                 if (value != "") {
61                                         show_error(input, "Please select an existing tag, it;s not possible to add custom ones.");
62                                 }
63                         })
64
65                         input.keydown(function(e) {
66                                         if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
67                                                 e.preventDefault();
68                                 })
69                                 .autocomplete({
70                                         minLength: 0,
71                                         source: source,
72                                         select: function(event, ui) {
73                                                 addTag(ui.item.id, ui.item.toString());
74                                                 input.val("");
75                                                 return false;
76                                         }
77                                 }).focus(function() {
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());
84                                 });
85
86                         input.data('ui-autocomplete')._renderItem = function(ul, item) {
87                                         return $('<li/>')
88                                                 .data('item.autocomplete', item)
89                                                 .append($('<a/>').text(item.toString()))
90                                                 .appendTo(ul);
91                                 };
92
93                         input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
94                                         var ul = this.menu.element;
95                                         ul.outerWidth(Math.max(
96                                                 ul.width('').outerWidth(),
97                                                 selector.outerWidth()
98                                         ));
99                                 };
100                 });
101         }
102
103         $.fn.csvSelector = function(source, name, result, allowSlash) {
104                 return this.each(function() {
105                                 var selector = $(this),
106                                         input = $('input[type=text]', this);
107
108                                 var selected = [];
109                                 var lookup = {};
110                                 for (var i = 0; i < source.length; i++) {
111                                         lookup[source[i].id] = source[i];
112                                 }
113
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);
120                                                         }
121                                                 }
122                                                 recreate();
123                                         });
124
125                                 function selectItem(id) {
126                                         for (var i = 0; i < selected.length; i++) {
127                                                 if (selected[i] == id) {
128                                                         return false;
129                                                 }
130                                         }
131                                         selected.push(id);
132                                         return true;
133                                 }
134
135                                 function addTag(id, value) {
136                                         var tag = $('<span class="badge badge-pill badge-primary"/>')
137                                                 .text(value)
138                                                 .data("id", id)
139                                                 .append(' <a>x</a>')
140                                                 .insertBefore(input);
141
142                                         input.attr("placeholder", null);
143                                         hide_error(input);
144                                 }
145
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);
151                                         }
152                                         result.val(selected.join(","))
153                                 }
154
155                                 function readFromResult() {
156                                         selected = [];
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_]+)$/)) {
161                                                         selected.push(raw);
162                                                 }
163                                         }
164
165                                         recreate();
166                                 }
167                                 readFromResult();
168
169                                 result.change(readFromResult);
170
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_]+)$/)) {
176                                                 selectItem(item);
177                                                 recreate();
178                                                 input.val("");
179                                         }
180                                         return true;
181                                 });
182
183                                 input.keydown(function(e) {
184                                                 if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
185                                                         e.preventDefault();
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_]+)$/)) {
191                                                                 selectItem(item);
192                                                                 recreate();
193                                                                 input.val("");
194                                                         } else {
195                                                                 show_error(input, "Only lowercase alphanumeric and number names allowed.");
196                                                         }
197                                                         e.preventDefault();
198                                                         return true;
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);
203                                                                 recreate();
204                                                                 if (!(item.indexOf("/") > 0))
205                                                                         input.val(item);
206                                                                 e.preventDefault();
207                                                                 return true;
208                                                         }
209                                                 }
210                                         })
211                                         .autocomplete({
212                                                 minLength: 0,
213                                                 source: source,
214                                                 select: function(event, ui) {
215                                                         selectItem(ui.item.id);
216                                                         recreate();
217                                                         input.val("");
218                                                         return false;
219                                                 }
220                                         });
221
222                                 input.data('ui-autocomplete')._renderItem = function(ul, item) {
223                                                 return $('<li/>')
224                                                         .data('item.autocomplete', item)
225                                                         .append($('<a/>').text(item.toString()))
226                                                         .appendTo(ul);
227                                         };
228
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()
234                                                 ));
235                                         };
236                         });
237         }
238
239         $(function() {
240                 $(".multichoice_selector").each(function() {
241                         var ele = $(this);
242                         var sel = ele.parent().find("select");
243                         sel.hide();
244
245                         var options = [];
246                         sel.find("option").each(function() {
247                                 var text = $(this).text();
248                                 options.push({
249                                         id: $(this).attr("value"),
250                                         value: text,
251                                         selected: $(this).attr("selected") ? true : false,
252                                         toString: function() { return text; },
253                                 });
254                         });
255
256                         ele.selectSelector(options, sel);
257                 });
258
259                 $(".metapackage_selector").each(function() {
260                         var input = $(this).parent().children("input[type='text']");
261                         input.hide();
262                         $(this).csvSelector(meta_packages, input.attr("name"), input);
263                 });
264
265                 $(".deps_selector").each(function() {
266                         var input = $(this).parent().children("input[type='text']");
267                         input.hide();
268                         $(this).csvSelector(all_packages, input.attr("name"), input);
269                 });
270         });
271 })(jQuery);