/[projects]/misc/horsensspejder-web/jquery/jquery-picklist.js
ViewVC logotype

Contents of /misc/horsensspejder-web/jquery/jquery-picklist.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2125 - (show annotations) (download) (as text)
Wed Mar 12 19:30:05 2014 UTC (10 years, 2 months ago) by torben
File MIME type: application/javascript
File size: 15004 byte(s)
initial import
1 /**
2 * jQuery PickList Widget
3 *
4 * Copyright (c) 2012-2013 Jonathon Freeman <jonathon@awnry.com>
5 * Distributed under the terms of the MIT License.
6 *
7 * http://code.google.com/p/jquery-ui-picklist/
8 */
9 (function($)
10 {
11 $.widget("awnry.pickList",
12 {
13 widgetEventPrefix: "pickList_",
14
15 options:
16 {
17 // Container classes
18 mainClass: "pickList",
19 listContainerClass: "pickList_listContainer",
20 sourceListContainerClass: "pickList_sourceListContainer",
21 controlsContainerClass: "pickList_controlsContainer",
22 targetListContainerClass: "pickList_targetListContainer",
23 listClass: "pickList_list",
24 sourceListClass: "pickList_sourceList",
25 targetListClass: "pickList_targetList",
26 clearClass: "pickList_clear",
27
28 // List item classes
29 listItemClass: "pickList_listItem",
30 richListItemClass: "pickList_richListItem",
31 selectedListItemClass: "pickList_selectedListItem",
32
33 // Control classes
34 addAllClass: "pickList_addAll",
35 addClass: "pickList_add",
36 removeAllClass: "pickList_removeAll",
37 removeClass: "pickList_remove",
38
39 // Control labels
40 addAllLabel: "&gt;&gt;",
41 addLabel: "&gt;",
42 removeAllLabel: "&lt;&lt;",
43 removeLabel: "&lt;",
44
45 // List labels
46 listLabelClass: "pickList_listLabel",
47 sourceListLabel: "Available",
48 sourceListLabelClass: "pickList_sourceListLabel",
49 targetListLabel: "Selected",
50 targetListLabelClass: "pickList_targetListLabel",
51
52 // Sorting
53 sortItems: true,
54 sortAttribute: "label",
55
56 // Name of custom value attribute for list items
57 listItemValueAttribute: "data-value",
58
59 // Additional list items
60 items: []
61 },
62
63 _create: function()
64 {
65 var self = this;
66
67 self._buildPickList();
68 self._refresh();
69 },
70
71 _buildPickList: function()
72 {
73 var self = this;
74
75 self._trigger("beforeBuild");
76
77 self.pickList = $("<div/>")
78 .hide()
79 .addClass(self.options.mainClass)
80 .insertAfter(self.element)
81 .append(self._buildSourceList())
82 .append(self._buildControls())
83 .append(self._buildTargetList())
84 .append( $("<div/>").addClass(self.options.clearClass) );
85
86 self._populateLists();
87
88 self.element.hide();
89 self.pickList.show();
90
91 self._trigger("afterBuild");
92 },
93
94 _buildSourceList: function()
95 {
96 var self = this;
97
98 var container = $("<div/>")
99 .addClass(self.options.listContainerClass)
100 .addClass(self.options.sourceListContainerClass)
101 .css({
102 "-moz-user-select": "none",
103 "-webkit-user-select": "none",
104 "user-select": "none",
105 "-ms-user-select": "none"
106 })
107 .each(function()
108 {
109 this.onselectstart = function() { return false; };
110 });
111
112 var label = $("<div/>")
113 .text(self.options.sourceListLabel)
114 .addClass(self.options.listLabelClass)
115 .addClass(self.options.sourceListLabelClass);
116
117 self.sourceList = $("<ul/>")
118 .addClass(self.options.listClass)
119 .addClass(self.options.sourceListClass)
120 .delegate("li", "click", { pickList: self }, self._changeHandler);
121
122 container
123 .append(label)
124 .append(self.sourceList);
125
126 self.sourceList.delegate(".pickList_listItem", "dblclick", {pickList: self}, function(e)
127 {
128 var self = e.data.pickList;
129 self._addItems( self.sourceList.children(".ui-selected") );
130 });
131
132 return container;
133 },
134
135 _buildTargetList: function()
136 {
137 var self = this;
138
139 var container = $("<div/>")
140 .addClass(self.options.listContainerClass)
141 .addClass(self.options.targetListContainerClass)
142 .css({
143 "-moz-user-select": "none",
144 "-webkit-user-select": "none",
145 "user-select": "none",
146 "-ms-user-select": "none"
147 })
148 .each(function()
149 {
150 this.onselectstart = function() { return false; };
151 });
152
153 var label = $("<div/>")
154 .text(self.options.targetListLabel)
155 .addClass(self.options.listLabelClass)
156 .addClass(self.options.targetListLabelClass);
157
158 self.targetList = $("<ul/>")
159 .addClass(self.options.listClass)
160 .addClass(self.options.targetListClass)
161 .delegate("li", "click", { pickList: self }, self._changeHandler);
162
163 container
164 .append(label)
165 .append(self.targetList);
166
167 self.targetList.delegate(".pickList_listItem", "dblclick", {pickList: self}, function(e)
168 {
169 var self = e.data.pickList;
170 self._removeItems( self.targetList.children(".ui-selected") );
171 });
172
173 return container;
174 },
175
176 _buildControls: function()
177 {
178 var self = this;
179
180 self.controls = $("<div/>").addClass(self.options.controlsContainerClass);
181
182 self.addAllButton = $("<button type='button'/>").click({pickList: self}, self._addAllHandler).html(self.options.addAllLabel).addClass(self.options.addAllClass);
183 self.addButton = $("<button type='button'/>").click({pickList: self}, self._addHandler).html(self.options.addLabel).addClass(self.options.addClass);
184 self.removeButton = $("<button type='button'/>").click({pickList: self}, self._removeHandler).html(self.options.removeLabel).addClass(self.options.removeClass);
185 self.removeAllButton = $("<button type='button'/>").click({pickList: self}, self._removeAllHandler).html(self.options.removeAllLabel).addClass(self.options.removeAllClass);
186
187 self.controls
188 .append(self.addAllButton)
189 .append(self.addButton)
190 .append(self.removeButton)
191 .append(self.removeAllButton);
192
193 return self.controls;
194 },
195
196 _populateLists: function()
197 {
198 var self = this;
199
200 self._trigger("beforePopulate");
201
202 var sourceListItems = [];
203 var targetListItems = [];
204 var selectItems = self.element.children();
205
206 selectItems.not(":selected").each(function()
207 {
208 sourceListItems.push( self._createDoppelganger(this) );
209 });
210
211 selectItems.filter(":selected").each(function()
212 {
213 targetListItems.push( self._createDoppelganger(this) );
214 });
215
216 self.sourceList.append(sourceListItems.join("\n"));
217 self.targetList.append(targetListItems.join("\n"));
218 self.insertItems(self.options.items);
219
220 self._trigger("afterPopulate");
221 },
222
223 _addItems: function(items)
224 {
225 var self = this;
226
227 self._trigger("beforeAdd");
228
229 self.targetList.append( self._removeSelections(items) );
230
231 var itemIds = [];
232 items.each(function()
233 {
234 itemIds.push( self._getItemValue(this) );
235 });
236
237 self.element.children().filter(function()
238 {
239 return $.inArray(this.value, itemIds) != -1;
240 }).attr("selected", "selected");
241
242 self._refresh();
243
244 self._trigger("afterAdd", null, { items: items });
245 self._trigger("onChange", null, { type: "add", items: items });
246 },
247
248 _removeItems: function(items)
249 {
250 var self = this;
251
252 self._trigger("beforeRemove");
253
254 self.sourceList.append( self._removeSelections(items) );
255
256 var itemIds = [];
257 items.each(function()
258 {
259 itemIds.push( self._getItemValue(this) );
260 });
261
262 self.element.children().filter(function()
263 {
264 return $.inArray(this.value, itemIds) != -1;
265 }).removeAttr("selected");
266
267 self._refresh();
268
269 self._trigger("afterRemove", null, { items: items });
270 self._trigger("onChange", null, { type: "remove", items: items });
271 },
272
273 _addAllHandler: function(e)
274 {
275 var self = e.data.pickList;
276
277 self._trigger("beforeAddAll");
278
279 var items = self.sourceList.children();
280 self.targetList.append( self._removeSelections(items) );
281
282 self.element.children().not(":selected").attr("selected", "selected");
283
284 self._refresh();
285
286 self._trigger("afterAddAll", null, { items: items });
287 self._trigger("onChange", null, { type: "addAll", items: items });
288 },
289
290 _addHandler: function(e)
291 {
292 var self = e.data.pickList;
293 self._addItems(self.sourceList.children(".ui-selected"));
294 },
295
296 _removeHandler: function(e)
297 {
298 var self = e.data.pickList;
299 self._removeItems(self.targetList.children(".ui-selected"));
300 },
301
302 _removeAllHandler: function(e)
303 {
304 var self = e.data.pickList;
305
306 self._trigger("beforeRemoveAll");
307
308 var items = self.targetList.children();
309 self.sourceList.append( self._removeSelections(items) );
310
311 self.element.children().filter(":selected").removeAttr("selected");
312
313 self._refresh();
314
315 self._trigger("afterRemoveAll", null, { items: items });
316 self._trigger("onChange", null, { type: "removeAll", items: items });
317 },
318
319 _refresh: function()
320 {
321 var self = this;
322
323 self._trigger("beforeRefresh");
324
325 self._refreshControls();
326
327 // Sort the selection lists.
328 if(self.options.sortItems)
329 {
330 self._sortItems(self.sourceList, self.options);
331 self._sortItems(self.targetList, self.options);
332 }
333
334 self._trigger("afterRefresh");
335 },
336
337 _refreshControls: function()
338 {
339 var self = this;
340
341 self._trigger("beforeRefreshControls");
342
343 // Enable/disable the Add All button state.
344 if(self.sourceList.children().length)
345 {
346 self.addAllButton.removeAttr("disabled");
347 }
348 else
349 {
350 self.addAllButton.attr("disabled", "disabled");
351 }
352
353 // Enable/disable the Remove All button state.
354 if(self.targetList.children().length)
355 {
356 self.removeAllButton.removeAttr("disabled");
357 }
358 else
359 {
360 self.removeAllButton.attr("disabled", "disabled");
361 }
362
363 // Enable/disable the Add button state.
364 if(self.sourceList.children(".ui-selected").length)
365 {
366 self.addButton.removeAttr("disabled");
367 }
368 else
369 {
370 self.addButton.attr("disabled", "disabled");
371 }
372
373 // Enable/disable the Remove button state.
374 if(self.targetList.children(".ui-selected").length)
375 {
376 self.removeButton.removeAttr("disabled");
377 }
378 else
379 {
380 self.removeButton.attr("disabled", "disabled");
381 }
382
383 self._trigger("afterRefreshControls");
384 },
385
386 _sortItems: function(list, options)
387 {
388 var items = new Array();
389
390 list.children().each(function()
391 {
392 items.push( $(this) );
393 });
394
395 items.sort(function(a, b)
396 {
397 if(a.attr(options.sortAttribute) > b.attr(options.sortAttribute))
398 {
399 return 1;
400 }
401 else if(a.attr(options.sortAttribute) == b.attr(options.sortAttribute))
402 {
403 return 0;
404 }
405 else
406 {
407 return -1;
408 }
409 });
410
411 list.empty();
412
413 for(var i = 0; i < items.length; i++)
414 {
415 list.append(items[i]);
416 }
417 },
418
419 _changeHandler: function(e)
420 {
421 var self = e.data.pickList;
422
423 if(e.ctrlKey)
424 {
425 if(self._isSelected( $(this) ))
426 {
427 self._removeSelection( $(this) );
428 }
429 else
430 {
431 self.lastSelectedItem = $(this);
432 self._addSelection( $(this) );
433 }
434 }
435 else if(e.shiftKey)
436 {
437 var current = self._getItemValue(this);
438 var last = self._getItemValue(self.lastSelectedItem);
439
440 if($(this).index() < $(self.lastSelectedItem).index())
441 {
442 var temp = current;
443 current = last;
444 last = temp;
445 }
446
447 var pastStart = false;
448 var beforeEnd = true;
449
450 self._clearSelections( $(this).parent() );
451
452 $(this).parent().children().each(function()
453 {
454 if(self._getItemValue(this) == last)
455 {
456 pastStart = true;
457 }
458
459 if(pastStart && beforeEnd)
460 {
461 self._addSelection( $(this) );
462 }
463
464 if(self._getItemValue(this) == current)
465 {
466 beforeEnd = false;
467 }
468
469 });
470 }
471 else
472 {
473 self.lastSelectedItem = $(this);
474 self._clearSelections( $(this).parent() );
475 self._addSelection( $(this) );
476 }
477
478 self._refreshControls();
479 },
480
481 _isSelected: function(listItem)
482 {
483 return listItem.hasClass("ui-selected");
484 },
485
486 _addSelection: function(listItem)
487 {
488 var self = this;
489
490 return listItem
491 .addClass("ui-selected")
492 .addClass("ui-state-highlight")
493 .addClass(self.options.selectedListItemClass);
494 },
495
496 _removeSelection: function(listItem)
497 {
498 var self = this;
499
500 return listItem
501 .removeClass("ui-selected")
502 .removeClass("ui-state-highlight")
503 .removeClass(self.options.selectedListItemClass);
504 },
505
506 _removeSelections: function(listItems)
507 {
508 var self = this;
509
510 listItems.each(function()
511 {
512 $(this)
513 .removeClass("ui-selected")
514 .removeClass("ui-state-highlight")
515 .removeClass(self.options.selectedListItemClass);
516 });
517
518 return listItems;
519 },
520
521 _clearSelections: function(list)
522 {
523 var self = this;
524
525 list.children().each(function()
526 {
527 self._removeSelection( $(this) );
528 });
529 },
530
531 _setOption: function(key, value)
532 {
533 switch(key)
534 {
535 case "clear":
536 {
537 break;
538 }
539 }
540
541 $.Widget.prototype._setOption.apply(this, arguments);
542 },
543
544 destroy: function()
545 {
546 var self = this;
547
548 self._trigger("onDestroy");
549
550 self.pickList.remove();
551 self.element.show();
552
553 $.Widget.prototype.destroy.call(self);
554 },
555
556 insert: function(item)
557 {
558 var self = this;
559
560 var list = item.selected ? self.targetList : self.sourceList;
561 var selectItem = self._createSelectItem(item);
562 var listItem = self._createListItem(item);
563
564 self.element.append(selectItem);
565 list.append(listItem);
566
567 self._trigger("onChange");
568
569 self._refresh();
570 },
571
572 insertItems: function(items)
573 {
574 var self = this;
575
576 var selectItems = [];
577 var sourceItems = [];
578 var targetItems = [];
579
580 $(items).each(function()
581 {
582 var selectItem = self._createSelectItem(this);
583 var listItem = self._createListItem(this);
584
585 selectItems.push(selectItem);
586
587 if(this.selected)
588 {
589 targetItems.push(listItem);
590 }
591 else
592 {
593 sourceItems.push(listItem);
594 }
595 });
596
597 self.element.append(selectItems.join("\n"));
598 self.sourceList.append(sourceItems.join("\n"));
599 self.targetList.append(targetItems.join("\n"));
600
601 self._trigger("onChange");
602
603 self._refresh();
604 },
605
606 _createSelectItem: function(item)
607 {
608 var selected = item.selected ? " selected='selected'" : "";
609 return "<option value='" + item.value + "'" + selected + ">" + item.label + "</option>";
610 },
611
612 _createListItem: function(item)
613 {
614 var self = this;
615
616 if(item.element != undefined)
617 {
618 var richItemHtml = item.element.clone().wrap("<div>").parent().html();
619 item.element.hide();
620 return "<li " + self.options.listItemValueAttribute + "='" + item.value + "' label='" + item.label + "' class='" + self.options.listItemClass + " " + self.options.richListItemClass + "'>" + richItemHtml + "</li>";
621 }
622
623 return "<li " + self.options.listItemValueAttribute + "='" + item.value + "' label='" + item.label + "' class='" + self.options.listItemClass + "'>" + item.label + "</li>";
624 },
625
626 _createDoppelganger: function(item)
627 {
628 var self = this;
629 return "<li " + self.options.listItemValueAttribute + "='" + $(item).val() + "' label='" + $(item).text() + "' class='" + self.options.listItemClass + "'>" + $(item).text() + "</li>";
630 },
631
632 _getItemValue: function(item)
633 {
634 var self = this;
635 return $(item).attr(self.options.listItemValueAttribute);
636 }
637 });
638 }(jQuery));

  ViewVC Help
Powered by ViewVC 1.1.20