1 | (function($) {
|
---|
2 |
|
---|
3 | $.fn.multiselectfilter = function (params) {
|
---|
4 | return this.each(function () {
|
---|
5 | var field_id = this.id;
|
---|
6 | if (this.id.match(/__prefix__/)){
|
---|
7 | // Don't intialize on empty forms.
|
---|
8 | return;
|
---|
9 | }
|
---|
10 | var from_box = $(this);
|
---|
11 | var from = this;
|
---|
12 | this.id += '_from';
|
---|
13 | this.className = 'filtered';
|
---|
14 |
|
---|
15 | // Remove <p class="info">, because it just gets in the way.
|
---|
16 | from_box.parent().find('p').remove();
|
---|
17 |
|
---|
18 | // <div class="selector"> or <div class="selector stacked">
|
---|
19 | var selector_div = $('<div/>').appendTo(from_box.parent());
|
---|
20 | selector_div.addClass('selector');
|
---|
21 | if (params.stacked) {
|
---|
22 | selector_div.addClass('stacked');
|
---|
23 | }
|
---|
24 | var hidden = $('<div/>');
|
---|
25 |
|
---|
26 | // <div class="selector-available">
|
---|
27 | var selector_available = $('<div><h2>'+interpolate(gettext('Available %s'), [params.verbose_name])+'</h2></div>').appendTo(selector_div);
|
---|
28 | selector_available.addClass('selector-available');
|
---|
29 | var filter_p = $('<p><img src="'+params.admin_media_prefix+'img/admin/selector-search.gif" /> </p>').appendTo(selector_available);
|
---|
30 | filter_p.addClass('selector-filter');
|
---|
31 | var filter_input = $('<input type="text" id="'+field_id+'_input" />').appendTo(filter_p);
|
---|
32 | from_box.appendTo(selector_available);
|
---|
33 | var choose_all = $('<a href="#">'+gettext('Choose all')+'</a>').appendTo(selector_available);
|
---|
34 | choose_all.addClass('selector-chooseall');
|
---|
35 |
|
---|
36 | // <ul class="selector-chooser">
|
---|
37 | var selector_chooser = $('<ul/>').appendTo(selector_div);
|
---|
38 | selector_chooser.addClass('selector-chooser');
|
---|
39 | var add_link = $('<a href="#">'+gettext('Add')+'</a>').appendTo($('<li/>').appendTo(selector_chooser));
|
---|
40 | add_link.addClass('selector-add');
|
---|
41 | var remove_link = $('<a href="#">'+gettext('Remove')+'</a>').appendTo($('<li/>').appendTo(selector_chooser));
|
---|
42 | remove_link.addClass('selector-remove');
|
---|
43 |
|
---|
44 | // <div class="selector-chosen">
|
---|
45 | var selector_chosen = $('<div><h2>'+interpolate(gettext('Chosen %s'), [params.verbose_name])+'</h2></div>').appendTo(selector_div);
|
---|
46 | selector_chosen.addClass('selector-chosen');
|
---|
47 | var selector_filter = $('<p>'+gettext('Select your choice(s) and click ')+'<img src="'+params.admin_media_prefix + (params.stacked ? 'img/admin/selector_stacked-add.gif':'img/admin/selector-add.gif')+'" alt="Add" /></p>').appendTo(selector_chosen);
|
---|
48 | selector_filter.addClass('selector-filter');
|
---|
49 | var to_box = $('<select id="'+field_id + '_to" multiple="multiple" size="'+from.size+'" name="'+from.name+'" />').appendTo(selector_chosen);
|
---|
50 | to_box.addClass('filtered');
|
---|
51 | var clear_all = $('<a href="#">'+gettext('Clear all')+'</a>').appendTo(selector_chosen);
|
---|
52 | clear_all.addClass('selector-clearall');
|
---|
53 |
|
---|
54 | from.name += '_old';
|
---|
55 |
|
---|
56 | function move(from_box, to_box) {
|
---|
57 | from_box.find('option[selected]').appendTo(to_box).removeAttr('selected');
|
---|
58 | to_box.focus();
|
---|
59 | };
|
---|
60 |
|
---|
61 | choose_all.click(function () {
|
---|
62 | from_box.find('option').appendTo(to_box);
|
---|
63 | });
|
---|
64 | clear_all.click(function () {
|
---|
65 | to_box.find('option').appendTo(from_box);
|
---|
66 | });
|
---|
67 | add_link.click(function (e) { move(from_box, to_box); e.preventDefault(); });
|
---|
68 | remove_link.click(function (e) { move(to_box, from_box); e.preventDefault(); });
|
---|
69 | from_box.dblclick(function (e) { move(from_box, to_box); e.preventDefault(); });
|
---|
70 | to_box.dblclick(function (e) { move(to_box, from_box); e.preventDefault(); });
|
---|
71 | from_box.parents('form').submit(function () { to_box.find('option').attr('selected', 'selected'); });
|
---|
72 | move(from_box, to_box);
|
---|
73 |
|
---|
74 | filter_input.keyup(function (e) {
|
---|
75 | // don't submit form if user pressed Enter
|
---|
76 | if (e.which == 13) {
|
---|
77 | from_box.find('option[selected]').appendTo(to_box).removeAttr('selected');
|
---|
78 | e.preventDefault();
|
---|
79 | return;
|
---|
80 | }
|
---|
81 | var temp = from.selectedIndex;
|
---|
82 | var tokens = filter_input.val().toLowerCase().split(/\s+/);
|
---|
83 | if (tokens[0] == "") {
|
---|
84 | hidden.find('option').each(function () {
|
---|
85 | $(this).appendTo(from_box);
|
---|
86 | });
|
---|
87 | }
|
---|
88 | var node, token;
|
---|
89 | from_box.add(hidden).find('option').each(function () {
|
---|
90 | var opt = $(this);
|
---|
91 | for (var j = 0; (token = tokens[j]); j++) {
|
---|
92 | if (opt.text().toLowerCase().indexOf(token) == -1) {
|
---|
93 | opt.appendTo(hidden);
|
---|
94 | break;
|
---|
95 | } else {
|
---|
96 | opt.appendTo(from_box);
|
---|
97 | }
|
---|
98 | }
|
---|
99 | });
|
---|
100 | from.selectedIndex = temp;
|
---|
101 | return true;
|
---|
102 | });
|
---|
103 | filter_input.keydown(function (e) {
|
---|
104 | // right arrow -- move across
|
---|
105 | if (e.which == 39) {
|
---|
106 | var old_index = from.selectedIndex;
|
---|
107 | move(from_box, to_box);
|
---|
108 | from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index;
|
---|
109 | from_box.focus();
|
---|
110 | e.preventDefault();
|
---|
111 | return;
|
---|
112 | }
|
---|
113 | // down arrow -- wrap around
|
---|
114 | if (e.which == 40) {
|
---|
115 | from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1;
|
---|
116 | }
|
---|
117 | // up arrow -- wrap around
|
---|
118 | if (e.which == 38) {
|
---|
119 | from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1;
|
---|
120 | }
|
---|
121 | });
|
---|
122 | });
|
---|
123 | }
|
---|
124 |
|
---|
125 | })(django.jQuery );
|
---|