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 @@ | @@ -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 | \ No newline at end of file | 94 | \ No newline at end of file |
@@ -0,0 +1,544 @@ | @@ -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 @@ | @@ -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,5 +63,41 @@ | ||
63 | $('.date-picker').datepicker({ | 63 | $('.date-picker').datepicker({ |
64 | language: locale, | 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 | </script> | 102 | </script> |
67 | {% endblock %} | 103 | {% endblock %} |
68 | \ No newline at end of file | 104 | \ No newline at end of file |
categories/templates/categories/home.html
@@ -7,6 +7,15 @@ | @@ -7,6 +7,15 @@ | ||
7 | {% breadcrumb 'Home' 'categories:index' %} | 7 | {% breadcrumb 'Home' 'categories:index' %} |
8 | {% endblock %} | 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 | {% block render_breadcrumbs %} | 20 | {% block render_breadcrumbs %} |
12 | {% render_breadcrumbs %} | 21 | {% render_breadcrumbs %} |
categories/templates/categories/update.html
@@ -64,5 +64,41 @@ | @@ -64,5 +64,41 @@ | ||
64 | $('.date-picker').datepicker({ | 64 | $('.date-picker').datepicker({ |
65 | language: locale, | 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 | </script> | 103 | </script> |
68 | {% endblock %} | 104 | {% endblock %} |
69 | \ No newline at end of file | 105 | \ No newline at end of file |