]> git.lizzy.rs Git - cheatdb.git/blob - app/public/static/tagselector.js
Add start of bulk tag editor
[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                                 $('<span class="badge badge-pill badge-primary"/>')
34                                         .text(text + ' ')
35                                         .data("id", id)
36                                         .append('<a>x</a>')
37                                         .insertBefore(input);
38                                 input.attr("placeholder", null);
39                                 select.find("option[value='" + id + "']").attr("selected", "selected")
40                                 hide_error(input);
41                         }
42
43                         function recreate() {
44                                 selector.find("span").remove();
45                                 select.find("option").each(function() {
46                                         if (this.hasAttribute("selected")) {
47                                                 addTag(this.getAttribute("value"), this.innerText);
48                                         }
49                                 });
50                         }
51                         recreate();
52
53                         input.focusout(function(e) {
54                                 var value = input.val().trim()
55                                 if (value != "") {
56                                         show_error(input, "Please select an existing tag, it;s not possible to add custom ones.");
57                                 }
58                         })
59
60                         input.keydown(function(e) {
61                                         if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
62                                                 e.preventDefault();
63                                 })
64                                 .autocomplete({
65                                         minLength: 0,
66                                         source: source,
67                                         select: function(event, ui) {
68                                                 addTag(ui.item.id, ui.item.toString());
69                                                 input.val("");
70                                                 return false;
71                                         }
72                                 }).focus(function() {
73                                         // The following works only once.
74                                         // $(this).trigger('keydown.autocomplete');
75                                         // As suggested by digitalPBK, works multiple times
76                                         // $(this).data("autocomplete").search($(this).val());
77                                         // As noted by Jonny in his answer, with newer versions use uiAutocomplete
78                                         $(this).data("ui-autocomplete").search($(this).val());
79                                 });
80
81                         input.data('ui-autocomplete')._renderItem = function(ul, item) {
82                                         return $('<li/>')
83                                                 .data('item.autocomplete', item)
84                                                 .append($('<a/>').text(item.toString()))
85                                                 .appendTo(ul);
86                                 };
87
88                         input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
89                                         var ul = this.menu.element;
90                                         ul.outerWidth(Math.max(
91                                                 ul.width('').outerWidth(),
92                                                 selector.outerWidth()
93                                         ));
94                                 };
95                 });
96         }
97
98         $.fn.csvSelector = function(source, name, result, allowSlash) {
99                 return this.each(function() {
100                                 var selector = $(this),
101                                         input = $('input[type=text]', this);
102
103                                 var selected = [];
104                                 var lookup = {};
105                                 for (var i = 0; i < source.length; i++) {
106                                         lookup[source[i].id] = source[i];
107                                 }
108
109                                 selector.click(function() { input.focus(); })
110                                         .delegate('.badge a', 'click', function() {
111                                                 var id = $(this).parent().data("id");
112                                                 for (var i = 0; i < selected.length; i++) {
113                                                         if (selected[i] == id) {
114                                                                 selected.splice(i, 1);
115                                                         }
116                                                 }
117                                                 recreate();
118                                         });
119
120                                 function selectItem(id) {
121                                         for (var i = 0; i < selected.length; i++) {
122                                                 if (selected[i] == id) {
123                                                         return false;
124                                                 }
125                                         }
126                                         selected.push(id);
127                                         return true;
128                                 }
129
130                                 function addTag(id, value) {
131                                         var tag = $('<span class="badge badge-pill badge-primary"/>')
132                                                 .text(value)
133                                                 .data("id", id)
134                                                 .append(' <a>x</a>')
135                                                 .insertBefore(input);
136
137                                         input.attr("placeholder", null);
138                                         hide_error(input);
139                                 }
140
141                                 function recreate() {
142                                         selector.find("span").remove();
143                                         for (var i = 0; i < selected.length; i++) {
144                                                 var value = lookup[selected[i]] || { value: selected[i] };
145                                                 addTag(selected[i], value.value);
146                                         }
147                                         result.val(selected.join(","))
148                                 }
149
150                                 function readFromResult() {
151                                         selected = [];
152                                         var selected_raw = result.val().split(",");
153                                         for (var i = 0; i < selected_raw.length; i++) {
154                                                 var raw = selected_raw[i].trim();
155                                                 if (lookup[raw] || raw.match(/^([a-z0-9_]+)$/)) {
156                                                         selected.push(raw);
157                                                 }
158                                         }
159
160                                         recreate();
161                                 }
162                                 readFromResult();
163
164                                 result.change(readFromResult);
165
166                                 input.focusout(function() {
167                                         var item = input.val();
168                                         if (item.length == 0) {
169                                                 input.data("ui-autocomplete").search("");
170                                         } else if (item.match(/^([a-z0-9_]+)$/)) {
171                                                 selectItem(item);
172                                                 recreate();
173                                                 input.val("");
174                                         }
175                                         return true;
176                                 });
177
178                                 input.keydown(function(e) {
179                                                 if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
180                                                         e.preventDefault();
181                                                 else if (e.keyCode === $.ui.keyCode.COMMA) {
182                                                         var item = input.val();
183                                                         if (item.length == 0) {
184                                                                 input.data("ui-autocomplete").search("");
185                                                         } else if (item.match(/^([a-z0-9_]+)$/)) {
186                                                                 selectItem(item);
187                                                                 recreate();
188                                                                 input.val("");
189                                                         } else {
190                                                                 show_error(input, "Only lowercase alphanumeric and number names allowed.");
191                                                         }
192                                                         e.preventDefault();
193                                                         return true;
194                                                 } else if (e.keyCode === $.ui.keyCode.BACKSPACE) {
195                                                         if (input.val() == "") {
196                                                                 var item = selected[selected.length - 1];
197                                                                 selected.splice(selected.length - 1, 1);
198                                                                 recreate();
199                                                                 if (!(item.indexOf("/") > 0))
200                                                                         input.val(item);
201                                                                 e.preventDefault();
202                                                                 return true;
203                                                         }
204                                                 }
205                                         })
206                                         .autocomplete({
207                                                 minLength: 0,
208                                                 source: source,
209                                                 select: function(event, ui) {
210                                                         selectItem(ui.item.id);
211                                                         recreate();
212                                                         input.val("");
213                                                         return false;
214                                                 }
215                                         });
216
217                                 input.data('ui-autocomplete')._renderItem = function(ul, item) {
218                                                 return $('<li/>')
219                                                         .data('item.autocomplete', item)
220                                                         .append($('<a/>').text(item.toString()))
221                                                         .appendTo(ul);
222                                         };
223
224                                 input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
225                                                 var ul = this.menu.element;
226                                                 ul.outerWidth(Math.max(
227                                                         ul.width('').outerWidth(),
228                                                         selector.outerWidth()
229                                                 ));
230                                         };
231                         });
232         }
233
234         $(function() {
235                 $(".multichoice_selector").each(function() {
236                         var ele = $(this);
237                         var sel = ele.parent().find("select");
238                         sel.hide();
239
240                         var options = [];
241                         sel.find("option").each(function() {
242                                 var text = $(this).text();
243                                 options.push({
244                                         id: $(this).attr("value"),
245                                         value: text,
246                                         selected: $(this).attr("selected") ? true : false,
247                                         toString: function() { return text; },
248                                 });
249                         });
250
251                         ele.selectSelector(options, sel);
252                 });
253
254                 $(".metapackage_selector").each(function() {
255                         var input = $(this).parent().children("input[type='text']");
256                         input.hide();
257                         $(this).csvSelector(meta_packages, input.attr("name"), input);
258                 });
259
260                 $(".deps_selector").each(function() {
261                         var input = $(this).parent().children("input[type='text']");
262                         input.hide();
263                         $(this).csvSelector(all_packages, input.attr("name"), input);
264                 });
265         });
266 })(jQuery);