Commit 3699b36b4f94803e2cd4adf3a8d8b03c18f9f505
1 parent
615652db
Exists in
master
and in
3 other branches
added select field and javascript libraries quicksearch and multiselect.js to our project
Showing
7 changed files
with
904 additions
and
0 deletions
Show diff stats
amadeus/static/css/base/amadeus.css
... | ... | @@ -0,0 +1,93 @@ |
1 | +.ms-container{ | |
2 | + background: transparent url('../img/switch.png') no-repeat 50% 50%; | |
3 | + width: 370px; | |
4 | +} | |
5 | + | |
6 | +.ms-container:after{ | |
7 | + content: "."; | |
8 | + display: block; | |
9 | + height: 0; | |
10 | + line-height: 0; | |
11 | + font-size: 0; | |
12 | + clear: both; | |
13 | + min-height: 0; | |
14 | + visibility: hidden; | |
15 | +} | |
16 | + | |
17 | +.ms-container .ms-selectable, .ms-container .ms-selection{ | |
18 | + background: #fff; | |
19 | + color: #555555; | |
20 | + float: left; | |
21 | + width: 45%; | |
22 | +} | |
23 | +.ms-container .ms-selection{ | |
24 | + float: right; | |
25 | +} | |
26 | + | |
27 | +.ms-container .ms-list{ | |
28 | + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
29 | + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
30 | + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); | |
31 | + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; | |
32 | + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; | |
33 | + -ms-transition: border linear 0.2s, box-shadow linear 0.2s; | |
34 | + -o-transition: border linear 0.2s, box-shadow linear 0.2s; | |
35 | + transition: border linear 0.2s, box-shadow linear 0.2s; | |
36 | + border: 1px solid #ccc; | |
37 | + -webkit-border-radius: 3px; | |
38 | + -moz-border-radius: 3px; | |
39 | + border-radius: 3px; | |
40 | + position: relative; | |
41 | + height: 200px; | |
42 | + padding: 0; | |
43 | + overflow-y: auto; | |
44 | +} | |
45 | + | |
46 | +.ms-container .ms-list.ms-focus{ | |
47 | + border-color: rgba(82, 168, 236, 0.8); | |
48 | + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); | |
49 | + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); | |
50 | + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); | |
51 | + outline: 0; | |
52 | + outline: thin dotted \9; | |
53 | +} | |
54 | + | |
55 | +.ms-container ul{ | |
56 | + margin: 0; | |
57 | + list-style-type: none; | |
58 | + padding: 0; | |
59 | +} | |
60 | + | |
61 | +.ms-container .ms-optgroup-container{ | |
62 | + width: 100%; | |
63 | +} | |
64 | + | |
65 | +.ms-container .ms-optgroup-label{ | |
66 | + margin: 0; | |
67 | + padding: 5px 0px 0px 5px; | |
68 | + cursor: pointer; | |
69 | + color: #999; | |
70 | +} | |
71 | + | |
72 | +.ms-container .ms-selectable li.ms-elem-selectable, | |
73 | +.ms-container .ms-selection li.ms-elem-selection{ | |
74 | + border-bottom: 1px #eee solid; | |
75 | + padding: 2px 10px; | |
76 | + color: #555; | |
77 | + font-size: 14px; | |
78 | +} | |
79 | + | |
80 | +.ms-container .ms-selectable li.ms-hover, | |
81 | +.ms-container .ms-selection li.ms-hover{ | |
82 | + cursor: pointer; | |
83 | + color: #fff; | |
84 | + text-decoration: none; | |
85 | + background-color: #08c; | |
86 | +} | |
87 | + | |
88 | +.ms-container .ms-selectable li.disabled, | |
89 | +.ms-container .ms-selection li.disabled{ | |
90 | + background-color: #eee; | |
91 | + color: #aaa; | |
92 | + cursor: text; | |
93 | +} | |
0 | 94 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,544 @@ |
1 | +/* | |
2 | +* MultiSelect v0.9.12 | |
3 | +* Copyright (c) 2012 Louis Cuny | |
4 | +* | |
5 | +* This program is free software. It comes without any warranty, to | |
6 | +* the extent permitted by applicable law. You can redistribute it | |
7 | +* and/or modify it under the terms of the Do What The Fuck You Want | |
8 | +* To Public License, Version 2, as published by Sam Hocevar. See | |
9 | +* http://sam.zoy.org/wtfpl/COPYING for more details. | |
10 | +*/ | |
11 | + | |
12 | +!function ($) { | |
13 | + | |
14 | + "use strict"; | |
15 | + | |
16 | + | |
17 | + /* MULTISELECT CLASS DEFINITION | |
18 | + * ====================== */ | |
19 | + | |
20 | + var MultiSelect = function (element, options) { | |
21 | + this.options = options; | |
22 | + this.$element = $(element); | |
23 | + this.$container = $('<div/>', { 'class': "ms-container" }); | |
24 | + this.$selectableContainer = $('<div/>', { 'class': 'ms-selectable' }); | |
25 | + this.$selectionContainer = $('<div/>', { 'class': 'ms-selection' }); | |
26 | + this.$selectableUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' }); | |
27 | + this.$selectionUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' }); | |
28 | + this.scrollTo = 0; | |
29 | + this.elemsSelector = 'li:visible:not(.ms-optgroup-label,.ms-optgroup-container,.'+options.disabledClass+')'; | |
30 | + }; | |
31 | + | |
32 | + MultiSelect.prototype = { | |
33 | + constructor: MultiSelect, | |
34 | + | |
35 | + init: function(){ | |
36 | + var that = this, | |
37 | + ms = this.$element; | |
38 | + | |
39 | + if (ms.next('.ms-container').length === 0){ | |
40 | + ms.css({ position: 'absolute', left: '-9999px' }); | |
41 | + ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect'); | |
42 | + this.$container.attr('id', 'ms-'+ms.attr('id')); | |
43 | + this.$container.addClass(that.options.cssClass); | |
44 | + ms.find('option').each(function(){ | |
45 | + that.generateLisFromOption(this); | |
46 | + }); | |
47 | + | |
48 | + this.$selectionUl.find('.ms-optgroup-label').hide(); | |
49 | + | |
50 | + if (that.options.selectableHeader){ | |
51 | + that.$selectableContainer.append(that.options.selectableHeader); | |
52 | + } | |
53 | + that.$selectableContainer.append(that.$selectableUl); | |
54 | + if (that.options.selectableFooter){ | |
55 | + that.$selectableContainer.append(that.options.selectableFooter); | |
56 | + } | |
57 | + | |
58 | + if (that.options.selectionHeader){ | |
59 | + that.$selectionContainer.append(that.options.selectionHeader); | |
60 | + } | |
61 | + that.$selectionContainer.append(that.$selectionUl); | |
62 | + if (that.options.selectionFooter){ | |
63 | + that.$selectionContainer.append(that.options.selectionFooter); | |
64 | + } | |
65 | + | |
66 | + that.$container.append(that.$selectableContainer); | |
67 | + that.$container.append(that.$selectionContainer); | |
68 | + ms.after(that.$container); | |
69 | + | |
70 | + that.activeMouse(that.$selectableUl); | |
71 | + that.activeKeyboard(that.$selectableUl); | |
72 | + | |
73 | + var action = that.options.dblClick ? 'dblclick' : 'click'; | |
74 | + | |
75 | + that.$selectableUl.on(action, '.ms-elem-selectable', function(){ | |
76 | + that.select($(this).data('ms-value')); | |
77 | + }); | |
78 | + that.$selectionUl.on(action, '.ms-elem-selection', function(){ | |
79 | + that.deselect($(this).data('ms-value')); | |
80 | + }); | |
81 | + | |
82 | + that.activeMouse(that.$selectionUl); | |
83 | + that.activeKeyboard(that.$selectionUl); | |
84 | + | |
85 | + ms.on('focus', function(){ | |
86 | + that.$selectableUl.focus(); | |
87 | + }); | |
88 | + } | |
89 | + | |
90 | + var selectedValues = ms.find('option:selected').map(function(){ return $(this).val(); }).get(); | |
91 | + that.select(selectedValues, 'init'); | |
92 | + | |
93 | + if (typeof that.options.afterInit === 'function') { | |
94 | + that.options.afterInit.call(this, this.$container); | |
95 | + } | |
96 | + }, | |
97 | + | |
98 | + 'generateLisFromOption' : function(option, index, $container){ | |
99 | + var that = this, | |
100 | + ms = that.$element, | |
101 | + attributes = "", | |
102 | + $option = $(option); | |
103 | + | |
104 | + for (var cpt = 0; cpt < option.attributes.length; cpt++){ | |
105 | + var attr = option.attributes[cpt]; | |
106 | + | |
107 | + if(attr.name !== 'value' && attr.name !== 'disabled'){ | |
108 | + attributes += attr.name+'="'+attr.value+'" '; | |
109 | + } | |
110 | + } | |
111 | + var selectableLi = $('<li '+attributes+'><span>'+that.escapeHTML($option.text())+'</span></li>'), | |
112 | + selectedLi = selectableLi.clone(), | |
113 | + value = $option.val(), | |
114 | + elementId = that.sanitize(value); | |
115 | + | |
116 | + selectableLi | |
117 | + .data('ms-value', value) | |
118 | + .addClass('ms-elem-selectable') | |
119 | + .attr('id', elementId+'-selectable'); | |
120 | + | |
121 | + selectedLi | |
122 | + .data('ms-value', value) | |
123 | + .addClass('ms-elem-selection') | |
124 | + .attr('id', elementId+'-selection') | |
125 | + .hide(); | |
126 | + | |
127 | + if ($option.prop('disabled') || ms.prop('disabled')){ | |
128 | + selectedLi.addClass(that.options.disabledClass); | |
129 | + selectableLi.addClass(that.options.disabledClass); | |
130 | + } | |
131 | + | |
132 | + var $optgroup = $option.parent('optgroup'); | |
133 | + | |
134 | + if ($optgroup.length > 0){ | |
135 | + var optgroupLabel = $optgroup.attr('label'), | |
136 | + optgroupId = that.sanitize(optgroupLabel), | |
137 | + $selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId), | |
138 | + $selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId); | |
139 | + | |
140 | + if ($selectableOptgroup.length === 0){ | |
141 | + var optgroupContainerTpl = '<li class="ms-optgroup-container"></li>', | |
142 | + optgroupTpl = '<ul class="ms-optgroup"><li class="ms-optgroup-label"><span>'+optgroupLabel+'</span></li></ul>'; | |
143 | + | |
144 | + $selectableOptgroup = $(optgroupContainerTpl); | |
145 | + $selectionOptgroup = $(optgroupContainerTpl); | |
146 | + $selectableOptgroup.attr('id', 'optgroup-selectable-'+optgroupId); | |
147 | + $selectionOptgroup.attr('id', 'optgroup-selection-'+optgroupId); | |
148 | + $selectableOptgroup.append($(optgroupTpl)); | |
149 | + $selectionOptgroup.append($(optgroupTpl)); | |
150 | + if (that.options.selectableOptgroup){ | |
151 | + $selectableOptgroup.find('.ms-optgroup-label').on('click', function(){ | |
152 | + var values = $optgroup.children(':not(:selected, :disabled)').map(function(){ return $(this).val();}).get(); | |
153 | + that.select(values); | |
154 | + }); | |
155 | + $selectionOptgroup.find('.ms-optgroup-label').on('click', function(){ | |
156 | + var values = $optgroup.children(':selected:not(:disabled)').map(function(){ return $(this).val();}).get(); | |
157 | + that.deselect(values); | |
158 | + }); | |
159 | + } | |
160 | + that.$selectableUl.append($selectableOptgroup); | |
161 | + that.$selectionUl.append($selectionOptgroup); | |
162 | + } | |
163 | + index = index === undefined ? $selectableOptgroup.find('ul').children().length : index + 1; | |
164 | + selectableLi.insertAt(index, $selectableOptgroup.children()); | |
165 | + selectedLi.insertAt(index, $selectionOptgroup.children()); | |
166 | + } else { | |
167 | + index = index === undefined ? that.$selectableUl.children().length : index; | |
168 | + | |
169 | + selectableLi.insertAt(index, that.$selectableUl); | |
170 | + selectedLi.insertAt(index, that.$selectionUl); | |
171 | + } | |
172 | + }, | |
173 | + | |
174 | + 'addOption' : function(options){ | |
175 | + var that = this; | |
176 | + | |
177 | + if (options.value !== undefined && options.value !== null){ | |
178 | + options = [options]; | |
179 | + } | |
180 | + $.each(options, function(index, option){ | |
181 | + if (option.value !== undefined && option.value !== null && | |
182 | + that.$element.find("option[value='"+option.value+"']").length === 0){ | |
183 | + var $option = $('<option value="'+option.value+'">'+option.text+'</option>'), | |
184 | + $container = option.nested === undefined ? that.$element : $("optgroup[label='"+option.nested+"']"), | |
185 | + index = parseInt((typeof option.index === 'undefined' ? $container.children().length : option.index)); | |
186 | + | |
187 | + if (option.optionClass) { | |
188 | + $option.addClass(option.optionClass); | |
189 | + } | |
190 | + | |
191 | + if (option.disabled) { | |
192 | + $option.prop('disabled', true); | |
193 | + } | |
194 | + | |
195 | + $option.insertAt(index, $container); | |
196 | + that.generateLisFromOption($option.get(0), index, option.nested); | |
197 | + } | |
198 | + }); | |
199 | + }, | |
200 | + | |
201 | + 'escapeHTML' : function(text){ | |
202 | + return $("<div>").text(text).html(); | |
203 | + }, | |
204 | + | |
205 | + 'activeKeyboard' : function($list){ | |
206 | + var that = this; | |
207 | + | |
208 | + $list.on('focus', function(){ | |
209 | + $(this).addClass('ms-focus'); | |
210 | + }) | |
211 | + .on('blur', function(){ | |
212 | + $(this).removeClass('ms-focus'); | |
213 | + }) | |
214 | + .on('keydown', function(e){ | |
215 | + switch (e.which) { | |
216 | + case 40: | |
217 | + case 38: | |
218 | + e.preventDefault(); | |
219 | + e.stopPropagation(); | |
220 | + that.moveHighlight($(this), (e.which === 38) ? -1 : 1); | |
221 | + return; | |
222 | + case 37: | |
223 | + case 39: | |
224 | + e.preventDefault(); | |
225 | + e.stopPropagation(); | |
226 | + that.switchList($list); | |
227 | + return; | |
228 | + case 9: | |
229 | + if(that.$element.is('[tabindex]')){ | |
230 | + e.preventDefault(); | |
231 | + var tabindex = parseInt(that.$element.attr('tabindex'), 10); | |
232 | + tabindex = (e.shiftKey) ? tabindex-1 : tabindex+1; | |
233 | + $('[tabindex="'+(tabindex)+'"]').focus(); | |
234 | + return; | |
235 | + }else{ | |
236 | + if(e.shiftKey){ | |
237 | + that.$element.trigger('focus'); | |
238 | + } | |
239 | + } | |
240 | + } | |
241 | + if($.inArray(e.which, that.options.keySelect) > -1){ | |
242 | + e.preventDefault(); | |
243 | + e.stopPropagation(); | |
244 | + that.selectHighlighted($list); | |
245 | + return; | |
246 | + } | |
247 | + }); | |
248 | + }, | |
249 | + | |
250 | + 'moveHighlight': function($list, direction){ | |
251 | + var $elems = $list.find(this.elemsSelector), | |
252 | + $currElem = $elems.filter('.ms-hover'), | |
253 | + $nextElem = null, | |
254 | + elemHeight = $elems.first().outerHeight(), | |
255 | + containerHeight = $list.height(), | |
256 | + containerSelector = '#'+this.$container.prop('id'); | |
257 | + | |
258 | + $elems.removeClass('ms-hover'); | |
259 | + if (direction === 1){ // DOWN | |
260 | + | |
261 | + $nextElem = $currElem.nextAll(this.elemsSelector).first(); | |
262 | + if ($nextElem.length === 0){ | |
263 | + var $optgroupUl = $currElem.parent(); | |
264 | + | |
265 | + if ($optgroupUl.hasClass('ms-optgroup')){ | |
266 | + var $optgroupLi = $optgroupUl.parent(), | |
267 | + $nextOptgroupLi = $optgroupLi.next(':visible'); | |
268 | + | |
269 | + if ($nextOptgroupLi.length > 0){ | |
270 | + $nextElem = $nextOptgroupLi.find(this.elemsSelector).first(); | |
271 | + } else { | |
272 | + $nextElem = $elems.first(); | |
273 | + } | |
274 | + } else { | |
275 | + $nextElem = $elems.first(); | |
276 | + } | |
277 | + } | |
278 | + } else if (direction === -1){ // UP | |
279 | + | |
280 | + $nextElem = $currElem.prevAll(this.elemsSelector).first(); | |
281 | + if ($nextElem.length === 0){ | |
282 | + var $optgroupUl = $currElem.parent(); | |
283 | + | |
284 | + if ($optgroupUl.hasClass('ms-optgroup')){ | |
285 | + var $optgroupLi = $optgroupUl.parent(), | |
286 | + $prevOptgroupLi = $optgroupLi.prev(':visible'); | |
287 | + | |
288 | + if ($prevOptgroupLi.length > 0){ | |
289 | + $nextElem = $prevOptgroupLi.find(this.elemsSelector).last(); | |
290 | + } else { | |
291 | + $nextElem = $elems.last(); | |
292 | + } | |
293 | + } else { | |
294 | + $nextElem = $elems.last(); | |
295 | + } | |
296 | + } | |
297 | + } | |
298 | + if ($nextElem.length > 0){ | |
299 | + $nextElem.addClass('ms-hover'); | |
300 | + var scrollTo = $list.scrollTop() + $nextElem.position().top - | |
301 | + containerHeight / 2 + elemHeight / 2; | |
302 | + | |
303 | + $list.scrollTop(scrollTo); | |
304 | + } | |
305 | + }, | |
306 | + | |
307 | + 'selectHighlighted' : function($list){ | |
308 | + var $elems = $list.find(this.elemsSelector), | |
309 | + $highlightedElem = $elems.filter('.ms-hover').first(); | |
310 | + | |
311 | + if ($highlightedElem.length > 0){ | |
312 | + if ($list.parent().hasClass('ms-selectable')){ | |
313 | + this.select($highlightedElem.data('ms-value')); | |
314 | + } else { | |
315 | + this.deselect($highlightedElem.data('ms-value')); | |
316 | + } | |
317 | + $elems.removeClass('ms-hover'); | |
318 | + } | |
319 | + }, | |
320 | + | |
321 | + 'switchList' : function($list){ | |
322 | + $list.blur(); | |
323 | + this.$container.find(this.elemsSelector).removeClass('ms-hover'); | |
324 | + if ($list.parent().hasClass('ms-selectable')){ | |
325 | + this.$selectionUl.focus(); | |
326 | + } else { | |
327 | + this.$selectableUl.focus(); | |
328 | + } | |
329 | + }, | |
330 | + | |
331 | + 'activeMouse' : function($list){ | |
332 | + var that = this; | |
333 | + | |
334 | + this.$container.on('mouseenter', that.elemsSelector, function(){ | |
335 | + $(this).parents('.ms-container').find(that.elemsSelector).removeClass('ms-hover'); | |
336 | + $(this).addClass('ms-hover'); | |
337 | + }); | |
338 | + | |
339 | + this.$container.on('mouseleave', that.elemsSelector, function () { | |
340 | + $(this).parents('.ms-container').find(that.elemsSelector).removeClass('ms-hover'); | |
341 | + }); | |
342 | + }, | |
343 | + | |
344 | + 'refresh' : function() { | |
345 | + this.destroy(); | |
346 | + this.$element.multiSelect(this.options); | |
347 | + }, | |
348 | + | |
349 | + 'destroy' : function(){ | |
350 | + $("#ms-"+this.$element.attr("id")).remove(); | |
351 | + this.$element.off('focus'); | |
352 | + this.$element.css('position', '').css('left', ''); | |
353 | + this.$element.removeData('multiselect'); | |
354 | + }, | |
355 | + | |
356 | + 'select' : function(value, method){ | |
357 | + if (typeof value === 'string'){ value = [value]; } | |
358 | + | |
359 | + var that = this, | |
360 | + ms = this.$element, | |
361 | + msIds = $.map(value, function(val){ return(that.sanitize(val)); }), | |
362 | + selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'), | |
363 | + selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'), | |
364 | + options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); }); | |
365 | + | |
366 | + if (method === 'init'){ | |
367 | + selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'), | |
368 | + selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection'); | |
369 | + } | |
370 | + | |
371 | + if (selectables.length > 0){ | |
372 | + selectables.addClass('ms-selected').hide(); | |
373 | + selections.addClass('ms-selected').show(); | |
374 | + | |
375 | + options.prop('selected', true); | |
376 | + | |
377 | + that.$container.find(that.elemsSelector).removeClass('ms-hover'); | |
378 | + | |
379 | + var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container'); | |
380 | + if (selectableOptgroups.length > 0){ | |
381 | + selectableOptgroups.each(function(){ | |
382 | + var selectablesLi = $(this).find('.ms-elem-selectable'); | |
383 | + if (selectablesLi.length === selectablesLi.filter('.ms-selected').length){ | |
384 | + $(this).find('.ms-optgroup-label').hide(); | |
385 | + } | |
386 | + }); | |
387 | + | |
388 | + var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container'); | |
389 | + selectionOptgroups.each(function(){ | |
390 | + var selectionsLi = $(this).find('.ms-elem-selection'); | |
391 | + if (selectionsLi.filter('.ms-selected').length > 0){ | |
392 | + $(this).find('.ms-optgroup-label').show(); | |
393 | + } | |
394 | + }); | |
395 | + } else { | |
396 | + if (that.options.keepOrder && method !== 'init'){ | |
397 | + var selectionLiLast = that.$selectionUl.find('.ms-selected'); | |
398 | + if((selectionLiLast.length > 1) && (selectionLiLast.last().get(0) != selections.get(0))) { | |
399 | + selections.insertAfter(selectionLiLast.last()); | |
400 | + } | |
401 | + } | |
402 | + } | |
403 | + if (method !== 'init'){ | |
404 | + ms.trigger('change'); | |
405 | + if (typeof that.options.afterSelect === 'function') { | |
406 | + that.options.afterSelect.call(this, value); | |
407 | + } | |
408 | + } | |
409 | + } | |
410 | + }, | |
411 | + | |
412 | + 'deselect' : function(value){ | |
413 | + if (typeof value === 'string'){ value = [value]; } | |
414 | + | |
415 | + var that = this, | |
416 | + ms = this.$element, | |
417 | + msIds = $.map(value, function(val){ return(that.sanitize(val)); }), | |
418 | + selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'), | |
419 | + selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected').filter(':not(.'+that.options.disabledClass+')'), | |
420 | + options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); }); | |
421 | + | |
422 | + if (selections.length > 0){ | |
423 | + selectables.removeClass('ms-selected').show(); | |
424 | + selections.removeClass('ms-selected').hide(); | |
425 | + options.prop('selected', false); | |
426 | + | |
427 | + that.$container.find(that.elemsSelector).removeClass('ms-hover'); | |
428 | + | |
429 | + var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container'); | |
430 | + if (selectableOptgroups.length > 0){ | |
431 | + selectableOptgroups.each(function(){ | |
432 | + var selectablesLi = $(this).find('.ms-elem-selectable'); | |
433 | + if (selectablesLi.filter(':not(.ms-selected)').length > 0){ | |
434 | + $(this).find('.ms-optgroup-label').show(); | |
435 | + } | |
436 | + }); | |
437 | + | |
438 | + var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container'); | |
439 | + selectionOptgroups.each(function(){ | |
440 | + var selectionsLi = $(this).find('.ms-elem-selection'); | |
441 | + if (selectionsLi.filter('.ms-selected').length === 0){ | |
442 | + $(this).find('.ms-optgroup-label').hide(); | |
443 | + } | |
444 | + }); | |
445 | + } | |
446 | + ms.trigger('change'); | |
447 | + if (typeof that.options.afterDeselect === 'function') { | |
448 | + that.options.afterDeselect.call(this, value); | |
449 | + } | |
450 | + } | |
451 | + }, | |
452 | + | |
453 | + 'select_all' : function(){ | |
454 | + var ms = this.$element, | |
455 | + values = ms.val(); | |
456 | + | |
457 | + ms.find('option:not(":disabled")').prop('selected', true); | |
458 | + this.$selectableUl.find('.ms-elem-selectable').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').hide(); | |
459 | + this.$selectionUl.find('.ms-optgroup-label').show(); | |
460 | + this.$selectableUl.find('.ms-optgroup-label').hide(); | |
461 | + this.$selectionUl.find('.ms-elem-selection').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').show(); | |
462 | + this.$selectionUl.focus(); | |
463 | + ms.trigger('change'); | |
464 | + if (typeof this.options.afterSelect === 'function') { | |
465 | + var selectedValues = $.grep(ms.val(), function(item){ | |
466 | + return $.inArray(item, values) < 0; | |
467 | + }); | |
468 | + this.options.afterSelect.call(this, selectedValues); | |
469 | + } | |
470 | + }, | |
471 | + | |
472 | + 'deselect_all' : function(){ | |
473 | + var ms = this.$element, | |
474 | + values = ms.val(); | |
475 | + | |
476 | + ms.find('option').prop('selected', false); | |
477 | + this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show(); | |
478 | + this.$selectionUl.find('.ms-optgroup-label').hide(); | |
479 | + this.$selectableUl.find('.ms-optgroup-label').show(); | |
480 | + this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide(); | |
481 | + this.$selectableUl.focus(); | |
482 | + ms.trigger('change'); | |
483 | + if (typeof this.options.afterDeselect === 'function') { | |
484 | + this.options.afterDeselect.call(this, values); | |
485 | + } | |
486 | + }, | |
487 | + | |
488 | + sanitize: function(value){ | |
489 | + var hash = 0, i, character; | |
490 | + if (value.length == 0) return hash; | |
491 | + var ls = 0; | |
492 | + for (i = 0, ls = value.length; i < ls; i++) { | |
493 | + character = value.charCodeAt(i); | |
494 | + hash = ((hash<<5)-hash)+character; | |
495 | + hash |= 0; // Convert to 32bit integer | |
496 | + } | |
497 | + return hash; | |
498 | + } | |
499 | + }; | |
500 | + | |
501 | + /* MULTISELECT PLUGIN DEFINITION | |
502 | + * ======================= */ | |
503 | + | |
504 | + $.fn.multiSelect = function () { | |
505 | + var option = arguments[0], | |
506 | + args = arguments; | |
507 | + | |
508 | + return this.each(function () { | |
509 | + var $this = $(this), | |
510 | + data = $this.data('multiselect'), | |
511 | + options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option === 'object' && option); | |
512 | + | |
513 | + if (!data){ $this.data('multiselect', (data = new MultiSelect(this, options))); } | |
514 | + | |
515 | + if (typeof option === 'string'){ | |
516 | + data[option](args[1]); | |
517 | + } else { | |
518 | + data.init(); | |
519 | + } | |
520 | + }); | |
521 | + }; | |
522 | + | |
523 | + $.fn.multiSelect.defaults = { | |
524 | + keySelect: [32], | |
525 | + selectableOptgroup: false, | |
526 | + disabledClass : 'disabled', | |
527 | + dblClick : false, | |
528 | + keepOrder: false, | |
529 | + cssClass: '' | |
530 | + }; | |
531 | + | |
532 | + $.fn.multiSelect.Constructor = MultiSelect; | |
533 | + | |
534 | + $.fn.insertAt = function(index, $parent) { | |
535 | + return this.each(function() { | |
536 | + if (index === 0) { | |
537 | + $parent.prepend(this); | |
538 | + } else { | |
539 | + $parent.children().eq(index - 1).after(this); | |
540 | + } | |
541 | + }); | |
542 | +}; | |
543 | + | |
544 | +}(window.jQuery); | ... | ... |
... | ... | @@ -0,0 +1,181 @@ |
1 | +(function($, window, document, undefined) { | |
2 | + $.fn.quicksearch = function (target, opt) { | |
3 | + | |
4 | + var timeout, cache, rowcache, jq_results, val = '', e = this, options = $.extend({ | |
5 | + delay: 100, | |
6 | + selector: null, | |
7 | + stripeRows: null, | |
8 | + loader: null, | |
9 | + noResults: '', | |
10 | + matchedResultsCount: 0, | |
11 | + bind: 'keyup', | |
12 | + onBefore: function () { | |
13 | + return; | |
14 | + }, | |
15 | + onAfter: function () { | |
16 | + return; | |
17 | + }, | |
18 | + show: function () { | |
19 | + this.style.display = ""; | |
20 | + }, | |
21 | + hide: function () { | |
22 | + this.style.display = "none"; | |
23 | + }, | |
24 | + prepareQuery: function (val) { | |
25 | + return val.toLowerCase().split(' '); | |
26 | + }, | |
27 | + testQuery: function (query, txt, _row) { | |
28 | + for (var i = 0; i < query.length; i += 1) { | |
29 | + if (txt.indexOf(query[i]) === -1) { | |
30 | + return false; | |
31 | + } | |
32 | + } | |
33 | + return true; | |
34 | + } | |
35 | + }, opt); | |
36 | + | |
37 | + this.go = function () { | |
38 | + | |
39 | + var i = 0, | |
40 | + numMatchedRows = 0, | |
41 | + noresults = true, | |
42 | + query = options.prepareQuery(val), | |
43 | + val_empty = (val.replace(' ', '').length === 0); | |
44 | + | |
45 | + for (var i = 0, len = rowcache.length; i < len; i++) { | |
46 | + if (val_empty || options.testQuery(query, cache[i], rowcache[i])) { | |
47 | + options.show.apply(rowcache[i]); | |
48 | + noresults = false; | |
49 | + numMatchedRows++; | |
50 | + } else { | |
51 | + options.hide.apply(rowcache[i]); | |
52 | + } | |
53 | + } | |
54 | + | |
55 | + if (noresults) { | |
56 | + this.results(false); | |
57 | + } else { | |
58 | + this.results(true); | |
59 | + this.stripe(); | |
60 | + } | |
61 | + | |
62 | + this.matchedResultsCount = numMatchedRows; | |
63 | + this.loader(false); | |
64 | + options.onAfter(); | |
65 | + | |
66 | + return this; | |
67 | + }; | |
68 | + | |
69 | + /* | |
70 | + * External API so that users can perform search programatically. | |
71 | + * */ | |
72 | + this.search = function (submittedVal) { | |
73 | + val = submittedVal; | |
74 | + e.trigger(); | |
75 | + }; | |
76 | + | |
77 | + /* | |
78 | + * External API to get the number of matched results as seen in | |
79 | + * https://github.com/ruiz107/quicksearch/commit/f78dc440b42d95ce9caed1d087174dd4359982d6 | |
80 | + * */ | |
81 | + this.currentMatchedResults = function() { | |
82 | + return this.matchedResultsCount; | |
83 | + }; | |
84 | + | |
85 | + this.stripe = function () { | |
86 | + | |
87 | + if (typeof options.stripeRows === "object" && options.stripeRows !== null) | |
88 | + { | |
89 | + var joined = options.stripeRows.join(' '); | |
90 | + var stripeRows_length = options.stripeRows.length; | |
91 | + | |
92 | + jq_results.not(':hidden').each(function (i) { | |
93 | + $(this).removeClass(joined).addClass(options.stripeRows[i % stripeRows_length]); | |
94 | + }); | |
95 | + } | |
96 | + | |
97 | + return this; | |
98 | + }; | |
99 | + | |
100 | + this.strip_html = function (input) { | |
101 | + var output = input.replace(new RegExp('<[^<]+\>', 'g'), ""); | |
102 | + output = $.trim(output.toLowerCase()); | |
103 | + return output; | |
104 | + }; | |
105 | + | |
106 | + this.results = function (bool) { | |
107 | + if (typeof options.noResults === "string" && options.noResults !== "") { | |
108 | + if (bool) { | |
109 | + $(options.noResults).hide(); | |
110 | + } else { | |
111 | + $(options.noResults).show(); | |
112 | + } | |
113 | + } | |
114 | + return this; | |
115 | + }; | |
116 | + | |
117 | + this.loader = function (bool) { | |
118 | + if (typeof options.loader === "string" && options.loader !== "") { | |
119 | + (bool) ? $(options.loader).show() : $(options.loader).hide(); | |
120 | + } | |
121 | + return this; | |
122 | + }; | |
123 | + | |
124 | + this.cache = function () { | |
125 | + | |
126 | + jq_results = $(target); | |
127 | + | |
128 | + if (typeof options.noResults === "string" && options.noResults !== "") { | |
129 | + jq_results = jq_results.not(options.noResults); | |
130 | + } | |
131 | + | |
132 | + var t = (typeof options.selector === "string") ? jq_results.find(options.selector) : $(target).not(options.noResults); | |
133 | + cache = t.map(function () { | |
134 | + return e.strip_html(this.innerHTML); | |
135 | + }); | |
136 | + | |
137 | + rowcache = jq_results.map(function () { | |
138 | + return this; | |
139 | + }); | |
140 | + | |
141 | + /* | |
142 | + * Modified fix for sync-ing "val". | |
143 | + * Original fix https://github.com/michaellwest/quicksearch/commit/4ace4008d079298a01f97f885ba8fa956a9703d1 | |
144 | + * */ | |
145 | + val = val || this.val() || ""; | |
146 | + | |
147 | + return this.go(); | |
148 | + }; | |
149 | + | |
150 | + this.trigger = function () { | |
151 | + this.loader(true); | |
152 | + options.onBefore(); | |
153 | + | |
154 | + window.clearTimeout(timeout); | |
155 | + timeout = window.setTimeout(function () { | |
156 | + e.go(); | |
157 | + }, options.delay); | |
158 | + | |
159 | + return this; | |
160 | + }; | |
161 | + | |
162 | + this.cache(); | |
163 | + this.results(true); | |
164 | + this.stripe(); | |
165 | + this.loader(false); | |
166 | + | |
167 | + return this.each(function () { | |
168 | + | |
169 | + /* | |
170 | + * Changed from .bind to .on. | |
171 | + * */ | |
172 | + $(this).on(options.bind, function () { | |
173 | + | |
174 | + val = $(this).val(); | |
175 | + e.trigger(); | |
176 | + }); | |
177 | + }); | |
178 | + | |
179 | + }; | |
180 | + | |
181 | +}(jQuery, this, document)); | ... | ... |
categories/templates/categories/create.html
... | ... | @@ -63,5 +63,41 @@ |
63 | 63 | $('.date-picker').datepicker({ |
64 | 64 | language: locale, |
65 | 65 | }); |
66 | + | |
67 | + $('#id_coordinators').multiSelect({ | |
68 | + selectableHeader: "<input type='text' class='search-input category-search-users' autocomplete='off' placeholder='{% trans "try an username" %} '>", | |
69 | + selectionHeader: "<input type='text' class='search-input category-search-users' autocomplete='off' placeholder='{% trans "try an username" %} '>", | |
70 | + afterInit: function(ms){ | |
71 | + var that = this, | |
72 | + $selectableSearch = that.$selectableUl.prev(), | |
73 | + $selectionSearch = that.$selectionUl.prev(), | |
74 | + selectableSearchString = '#'+that.$container.attr('id')+' .ms-elem-selectable:not(.ms-selected)', | |
75 | + selectionSearchString = '#'+that.$container.attr('id')+' .ms-elem-selection.ms-selected'; | |
76 | + | |
77 | + that.qs1 = $selectableSearch.quicksearch(selectableSearchString) | |
78 | + .on('keydown', function(e){ | |
79 | + if (e.which === 40){ | |
80 | + that.$selectableUl.focus(); | |
81 | + return false; | |
82 | + } | |
83 | + }); | |
84 | + | |
85 | + that.qs2 = $selectionSearch.quicksearch(selectionSearchString) | |
86 | + .on('keydown', function(e){ | |
87 | + if (e.which == 40){ | |
88 | + that.$selectionUl.focus(); | |
89 | + return false; | |
90 | + } | |
91 | + }); | |
92 | + }, | |
93 | + afterSelect: function(){ | |
94 | + this.qs1.cache(); | |
95 | + this.qs2.cache(); | |
96 | + }, | |
97 | + afterDeselect: function(){ | |
98 | + this.qs1.cache(); | |
99 | + this.qs2.cache(); | |
100 | + } | |
101 | + });// Used to create multi-select css style | |
66 | 102 | </script> |
67 | 103 | {% endblock %} |
68 | 104 | \ No newline at end of file | ... | ... |
categories/templates/categories/home.html
... | ... | @@ -7,6 +7,15 @@ |
7 | 7 | {% breadcrumb 'Home' 'categories:index' %} |
8 | 8 | {% endblock %} |
9 | 9 | |
10 | +{% block style %} | |
11 | + <link rel="stylesheet" type="text/css" href="{% static "css/multi-select.css" %}"> | |
12 | +{% endblock style %} | |
13 | + | |
14 | +{% block javascript %} | |
15 | + {{super.block}} | |
16 | + <script src="{% static "js/jquery.multi-select.js" %} " type="text/javascript"></script> | |
17 | + <script type="text/javascript" src="{% static "js/quicksearch.js" %}"></script> | |
18 | +{% endblock javascript %} | |
10 | 19 | |
11 | 20 | {% block render_breadcrumbs %} |
12 | 21 | {% render_breadcrumbs %} | ... | ... |
categories/templates/categories/update.html
... | ... | @@ -64,5 +64,41 @@ |
64 | 64 | $('.date-picker').datepicker({ |
65 | 65 | language: locale, |
66 | 66 | }); |
67 | + | |
68 | + $('#id_coordinators').multiSelect({ | |
69 | + selectableHeader: "<input type='text' class='search-input' autocomplete='off' placeholder='{% trans "try an username" %} '>", | |
70 | + selectionHeader: "<input type='text' class='search-input' autocomplete='off' placeholder='{% trans "try an username" %} '>", | |
71 | + afterInit: function(ms){ | |
72 | + var that = this, | |
73 | + $selectableSearch = that.$selectableUl.prev(), | |
74 | + $selectionSearch = that.$selectionUl.prev(), | |
75 | + selectableSearchString = '#'+that.$container.attr('id')+' .ms-elem-selectable:not(.ms-selected)', | |
76 | + selectionSearchString = '#'+that.$container.attr('id')+' .ms-elem-selection.ms-selected'; | |
77 | + | |
78 | + that.qs1 = $selectableSearch.quicksearch(selectableSearchString) | |
79 | + .on('keydown', function(e){ | |
80 | + if (e.which === 40){ | |
81 | + that.$selectableUl.focus(); | |
82 | + return false; | |
83 | + } | |
84 | + }); | |
85 | + | |
86 | + that.qs2 = $selectionSearch.quicksearch(selectionSearchString) | |
87 | + .on('keydown', function(e){ | |
88 | + if (e.which == 40){ | |
89 | + that.$selectionUl.focus(); | |
90 | + return false; | |
91 | + } | |
92 | + }); | |
93 | + }, | |
94 | + afterSelect: function(){ | |
95 | + this.qs1.cache(); | |
96 | + this.qs2.cache(); | |
97 | + }, | |
98 | + afterDeselect: function(){ | |
99 | + this.qs1.cache(); | |
100 | + this.qs2.cache(); | |
101 | + } | |
102 | + });// Used to create multi-select css style | |
67 | 103 | </script> |
68 | 104 | {% endblock %} |
69 | 105 | \ No newline at end of file | ... | ... |