merb-admin 0.8.1 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.gitignore +29 -27
  2. data/Gemfile +24 -22
  3. data/Gemfile.lock +86 -0
  4. data/LICENSE +20 -20
  5. data/README.rdoc +54 -58
  6. data/Rakefile +11 -44
  7. data/app/controllers/application.rb +6 -6
  8. data/app/controllers/main.rb +191 -191
  9. data/app/helpers/application_helper.rb +64 -64
  10. data/app/helpers/main_helper.rb +167 -167
  11. data/app/models/.gitkeep +0 -0
  12. data/app/views/layout/_message.html.erb +10 -10
  13. data/app/views/layout/dashboard.html.erb +34 -34
  14. data/app/views/layout/form.html.erb +48 -48
  15. data/app/views/layout/list.html.erb +42 -42
  16. data/app/views/main/_belongs_to.html.erb +29 -29
  17. data/app/views/main/_big_decimal.html.erb +12 -12
  18. data/app/views/main/_boolean.html.erb +7 -7
  19. data/app/views/main/_date.html.erb +12 -12
  20. data/app/views/main/_datetime.html.erb +12 -12
  21. data/app/views/main/_float.html.erb +12 -12
  22. data/app/views/main/_has_many.html.erb +16 -16
  23. data/app/views/main/_has_one.html.erb +30 -30
  24. data/app/views/main/_integer.html.erb +12 -12
  25. data/app/views/main/_properties.html.erb +18 -18
  26. data/app/views/main/_string.html.erb +15 -15
  27. data/app/views/main/_text.html.erb +11 -11
  28. data/app/views/main/_time.html.erb +12 -12
  29. data/app/views/main/_timestamp.html.erb +12 -12
  30. data/app/views/main/delete.html.erb +28 -28
  31. data/app/views/main/edit.html.erb +19 -19
  32. data/app/views/main/index.html.erb +22 -22
  33. data/app/views/main/list.html.erb +93 -93
  34. data/app/views/main/new.html.erb +16 -16
  35. data/config/init.rb +30 -0
  36. data/config/router.rb +4 -0
  37. data/lib/abstract_model.rb +84 -86
  38. data/lib/active_record_support.rb +147 -147
  39. data/lib/datamapper_support.rb +139 -140
  40. data/lib/generic_support.rb +13 -13
  41. data/lib/merb-admin.rb +99 -99
  42. data/lib/merb-admin/merbtasks.rb +103 -103
  43. data/lib/merb-admin/slicetasks.rb +174 -174
  44. data/lib/merb-admin/spectasks.rb +55 -55
  45. data/lib/merb-admin/version.rb +3 -0
  46. data/lib/sequel_support.rb +275 -275
  47. data/merb-admin.gemspec +42 -232
  48. data/public/javascripts/CollapsedFieldsets.js +85 -85
  49. data/public/javascripts/DateTimeShortcuts.js +255 -255
  50. data/public/javascripts/RelatedObjectLookups.js +96 -96
  51. data/public/javascripts/SelectBox.js +111 -111
  52. data/public/javascripts/SelectFilter2.js +113 -113
  53. data/public/javascripts/actions.js +39 -39
  54. data/public/javascripts/calendar.js +143 -143
  55. data/public/javascripts/core.js +176 -176
  56. data/public/javascripts/dateparse.js +233 -233
  57. data/public/javascripts/getElementsBySelector.js +167 -167
  58. data/public/javascripts/i18n.js +33 -33
  59. data/public/javascripts/ordering.js +137 -137
  60. data/public/javascripts/timeparse.js +94 -94
  61. data/public/javascripts/urlify.js +140 -140
  62. data/public/stylesheets/base.css +746 -746
  63. data/public/stylesheets/changelists.css +269 -269
  64. data/public/stylesheets/dashboard.css +24 -24
  65. data/public/stylesheets/forms.css +327 -327
  66. data/public/stylesheets/global.css +142 -142
  67. data/public/stylesheets/ie.css +50 -50
  68. data/public/stylesheets/layout.css +29 -29
  69. data/public/stylesheets/login.css +54 -54
  70. data/public/stylesheets/master.css +1 -1
  71. data/public/stylesheets/patch-iewin.css +7 -7
  72. data/public/stylesheets/rtl.css +206 -206
  73. data/public/stylesheets/widgets.css +506 -506
  74. data/screenshots/create.png +0 -0
  75. data/screenshots/delete.png +0 -0
  76. data/screenshots/edit.png +0 -0
  77. data/screenshots/index.png +0 -0
  78. data/screenshots/list.png +0 -0
  79. data/screenshots/new.png +0 -0
  80. data/spec/controllers/main_spec.rb +25 -25
  81. data/spec/migrations/activerecord/001_create_divisions_migration.rb +13 -13
  82. data/spec/migrations/activerecord/002_create_drafts_migration.rb +19 -19
  83. data/spec/migrations/activerecord/003_create_leagues_migration.rb +12 -12
  84. data/spec/migrations/activerecord/004_create_players_migration.rb +19 -20
  85. data/spec/migrations/activerecord/005_create_teams_migration.rb +22 -22
  86. data/spec/migrations/sequel/001_create_divisions_migration.rb +15 -15
  87. data/spec/migrations/sequel/002_create_drafts_migration.rb +21 -21
  88. data/spec/migrations/sequel/003_create_leagues_migration.rb +14 -14
  89. data/spec/migrations/sequel/004_create_players_migration.rb +21 -22
  90. data/spec/migrations/sequel/005_create_teams_migration.rb +24 -24
  91. data/spec/models/activerecord/division.rb +7 -7
  92. data/spec/models/activerecord/draft.rb +11 -11
  93. data/spec/models/activerecord/league.rb +6 -6
  94. data/spec/models/activerecord/player.rb +8 -8
  95. data/spec/models/activerecord/team.rb +13 -13
  96. data/spec/models/datamapper/division.rb +12 -12
  97. data/spec/models/datamapper/draft.rb +18 -18
  98. data/spec/models/datamapper/league.rb +11 -11
  99. data/spec/models/datamapper/player.rb +20 -21
  100. data/spec/models/datamapper/team.rb +22 -22
  101. data/spec/models/sequel/division.rb +15 -15
  102. data/spec/models/sequel/draft.rb +19 -19
  103. data/spec/models/sequel/league.rb +14 -14
  104. data/spec/models/sequel/player.rb +18 -18
  105. data/spec/models/sequel/team.rb +21 -21
  106. data/spec/requests/main_spec.rb +763 -763
  107. data/spec/spec_helper.rb +113 -112
  108. metadata +247 -41
  109. data/VERSION +0 -1
@@ -1,96 +1,96 @@
1
- // Handles related-objects functionality: lookup link for raw_id_fields
2
- // and Add Another links.
3
-
4
- function html_unescape(text) {
5
- // Unescape a string that was escaped using django.utils.html.escape.
6
- text = text.replace(/&lt;/g, '<');
7
- text = text.replace(/&gt;/g, '>');
8
- text = text.replace(/&quot;/g, '"');
9
- text = text.replace(/&#39;/g, "'");
10
- text = text.replace(/&amp;/g, '&');
11
- return text;
12
- }
13
-
14
- // IE doesn't accept periods or dashes in the window name, but the element IDs
15
- // we use to generate popup window names may contain them, therefore we map them
16
- // to allowed characters in a reversible way so that we can locate the correct
17
- // element when the popup window is dismissed.
18
- function id_to_windowname(text) {
19
- text = text.replace(/\./g, '__dot__');
20
- text = text.replace(/\-/g, '__dash__');
21
- return text;
22
- }
23
-
24
- function windowname_to_id(text) {
25
- text = text.replace(/__dot__/g, '.');
26
- text = text.replace(/__dash__/g, '-');
27
- return text;
28
- }
29
-
30
- function showRelatedObjectLookupPopup(triggeringLink) {
31
- var name = triggeringLink.id.replace(/^lookup_/, '');
32
- name = id_to_windowname(name);
33
- var href;
34
- if (triggeringLink.href.search(/\?/) >= 0) {
35
- href = triggeringLink.href + '&pop=1';
36
- } else {
37
- href = triggeringLink.href + '?pop=1';
38
- }
39
- var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
40
- win.focus();
41
- return false;
42
- }
43
-
44
- function dismissRelatedLookupPopup(win, chosenId) {
45
- var name = windowname_to_id(win.name);
46
- var elem = document.getElementById(name);
47
- if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
48
- elem.value += ',' + chosenId;
49
- } else {
50
- document.getElementById(name).value = chosenId;
51
- }
52
- win.close();
53
- }
54
-
55
- function showAddAnotherPopup(triggeringLink) {
56
- var name = triggeringLink.id.replace(/^add_/, '');
57
- name = id_to_windowname(name);
58
- href = triggeringLink.href
59
- if (href.indexOf('?') == -1) {
60
- href += '?_popup=1';
61
- } else {
62
- href += '&_popup=1';
63
- }
64
- var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
65
- win.focus();
66
- return false;
67
- }
68
-
69
- function dismissAddAnotherPopup(win, newId, newRepr) {
70
- // newId and newRepr are expected to have previously been escaped by
71
- // django.utils.html.escape.
72
- newId = html_unescape(newId);
73
- newRepr = html_unescape(newRepr);
74
- var name = windowname_to_id(win.name);
75
- var elem = document.getElementById(name);
76
- if (elem) {
77
- if (elem.nodeName == 'SELECT') {
78
- var o = new Option(newRepr, newId);
79
- elem.options[elem.options.length] = o;
80
- o.selected = true;
81
- } else if (elem.nodeName == 'INPUT') {
82
- if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
83
- elem.value += ',' + newId;
84
- } else {
85
- elem.value = newId;
86
- }
87
- }
88
- } else {
89
- var toId = name + "_to";
90
- elem = document.getElementById(toId);
91
- var o = new Option(newRepr, newId);
92
- SelectBox.add_to_cache(toId, o);
93
- SelectBox.redisplay(toId);
94
- }
95
- win.close();
96
- }
1
+ // Handles related-objects functionality: lookup link for raw_id_fields
2
+ // and Add Another links.
3
+
4
+ function html_unescape(text) {
5
+ // Unescape a string that was escaped using django.utils.html.escape.
6
+ text = text.replace(/&lt;/g, '<');
7
+ text = text.replace(/&gt;/g, '>');
8
+ text = text.replace(/&quot;/g, '"');
9
+ text = text.replace(/&#39;/g, "'");
10
+ text = text.replace(/&amp;/g, '&');
11
+ return text;
12
+ }
13
+
14
+ // IE doesn't accept periods or dashes in the window name, but the element IDs
15
+ // we use to generate popup window names may contain them, therefore we map them
16
+ // to allowed characters in a reversible way so that we can locate the correct
17
+ // element when the popup window is dismissed.
18
+ function id_to_windowname(text) {
19
+ text = text.replace(/\./g, '__dot__');
20
+ text = text.replace(/\-/g, '__dash__');
21
+ return text;
22
+ }
23
+
24
+ function windowname_to_id(text) {
25
+ text = text.replace(/__dot__/g, '.');
26
+ text = text.replace(/__dash__/g, '-');
27
+ return text;
28
+ }
29
+
30
+ function showRelatedObjectLookupPopup(triggeringLink) {
31
+ var name = triggeringLink.id.replace(/^lookup_/, '');
32
+ name = id_to_windowname(name);
33
+ var href;
34
+ if (triggeringLink.href.search(/\?/) >= 0) {
35
+ href = triggeringLink.href + '&pop=1';
36
+ } else {
37
+ href = triggeringLink.href + '?pop=1';
38
+ }
39
+ var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
40
+ win.focus();
41
+ return false;
42
+ }
43
+
44
+ function dismissRelatedLookupPopup(win, chosenId) {
45
+ var name = windowname_to_id(win.name);
46
+ var elem = document.getElementById(name);
47
+ if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
48
+ elem.value += ',' + chosenId;
49
+ } else {
50
+ document.getElementById(name).value = chosenId;
51
+ }
52
+ win.close();
53
+ }
54
+
55
+ function showAddAnotherPopup(triggeringLink) {
56
+ var name = triggeringLink.id.replace(/^add_/, '');
57
+ name = id_to_windowname(name);
58
+ href = triggeringLink.href
59
+ if (href.indexOf('?') == -1) {
60
+ href += '?_popup=1';
61
+ } else {
62
+ href += '&_popup=1';
63
+ }
64
+ var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
65
+ win.focus();
66
+ return false;
67
+ }
68
+
69
+ function dismissAddAnotherPopup(win, newId, newRepr) {
70
+ // newId and newRepr are expected to have previously been escaped by
71
+ // django.utils.html.escape.
72
+ newId = html_unescape(newId);
73
+ newRepr = html_unescape(newRepr);
74
+ var name = windowname_to_id(win.name);
75
+ var elem = document.getElementById(name);
76
+ if (elem) {
77
+ if (elem.nodeName == 'SELECT') {
78
+ var o = new Option(newRepr, newId);
79
+ elem.options[elem.options.length] = o;
80
+ o.selected = true;
81
+ } else if (elem.nodeName == 'INPUT') {
82
+ if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
83
+ elem.value += ',' + newId;
84
+ } else {
85
+ elem.value = newId;
86
+ }
87
+ }
88
+ } else {
89
+ var toId = name + "_to";
90
+ elem = document.getElementById(toId);
91
+ var o = new Option(newRepr, newId);
92
+ SelectBox.add_to_cache(toId, o);
93
+ SelectBox.redisplay(toId);
94
+ }
95
+ win.close();
96
+ }
@@ -1,111 +1,111 @@
1
- var SelectBox = {
2
- cache: new Object(),
3
- init: function(id) {
4
- var box = document.getElementById(id);
5
- var node;
6
- SelectBox.cache[id] = new Array();
7
- var cache = SelectBox.cache[id];
8
- for (var i = 0; (node = box.options[i]); i++) {
9
- cache.push({value: node.value, text: node.text, displayed: 1});
10
- }
11
- },
12
- redisplay: function(id) {
13
- // Repopulate HTML select box from cache
14
- var box = document.getElementById(id);
15
- box.options.length = 0; // clear all options
16
- for (var i = 0, j = SelectBox.cache[id].length; i < j; i++) {
17
- var node = SelectBox.cache[id][i];
18
- if (node.displayed) {
19
- box.options[box.options.length] = new Option(node.text, node.value, false, false);
20
- }
21
- }
22
- },
23
- filter: function(id, text) {
24
- // Redisplay the HTML select box, displaying only the choices containing ALL
25
- // the words in text. (It's an AND search.)
26
- var tokens = text.toLowerCase().split(/\s+/);
27
- var node, token;
28
- for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
29
- node.displayed = 1;
30
- for (var j = 0; (token = tokens[j]); j++) {
31
- if (node.text.toLowerCase().indexOf(token) == -1) {
32
- node.displayed = 0;
33
- }
34
- }
35
- }
36
- SelectBox.redisplay(id);
37
- },
38
- delete_from_cache: function(id, value) {
39
- var node, delete_index = null;
40
- for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
41
- if (node.value == value) {
42
- delete_index = i;
43
- break;
44
- }
45
- }
46
- var j = SelectBox.cache[id].length - 1;
47
- for (var i = delete_index; i < j; i++) {
48
- SelectBox.cache[id][i] = SelectBox.cache[id][i+1];
49
- }
50
- SelectBox.cache[id].length--;
51
- },
52
- add_to_cache: function(id, option) {
53
- SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1});
54
- },
55
- cache_contains: function(id, value) {
56
- // Check if an item is contained in the cache
57
- var node;
58
- for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
59
- if (node.value == value) {
60
- return true;
61
- }
62
- }
63
- return false;
64
- },
65
- move: function(from, to) {
66
- var from_box = document.getElementById(from);
67
- var to_box = document.getElementById(to);
68
- var option;
69
- for (var i = 0; (option = from_box.options[i]); i++) {
70
- if (option.selected && SelectBox.cache_contains(from, option.value)) {
71
- SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
72
- SelectBox.delete_from_cache(from, option.value);
73
- }
74
- }
75
- SelectBox.redisplay(from);
76
- SelectBox.redisplay(to);
77
- },
78
- move_all: function(from, to) {
79
- var from_box = document.getElementById(from);
80
- var to_box = document.getElementById(to);
81
- var option;
82
- for (var i = 0; (option = from_box.options[i]); i++) {
83
- if (SelectBox.cache_contains(from, option.value)) {
84
- SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
85
- SelectBox.delete_from_cache(from, option.value);
86
- }
87
- }
88
- SelectBox.redisplay(from);
89
- SelectBox.redisplay(to);
90
- },
91
- sort: function(id) {
92
- SelectBox.cache[id].sort( function(a, b) {
93
- a = a.text.toLowerCase();
94
- b = b.text.toLowerCase();
95
- try {
96
- if (a > b) return 1;
97
- if (a < b) return -1;
98
- }
99
- catch (e) {
100
- // silently fail on IE 'unknown' exception
101
- }
102
- return 0;
103
- } );
104
- },
105
- select_all: function(id) {
106
- var box = document.getElementById(id);
107
- for (var i = 0; i < box.options.length; i++) {
108
- box.options[i].selected = 'selected';
109
- }
110
- }
111
- }
1
+ var SelectBox = {
2
+ cache: new Object(),
3
+ init: function(id) {
4
+ var box = document.getElementById(id);
5
+ var node;
6
+ SelectBox.cache[id] = new Array();
7
+ var cache = SelectBox.cache[id];
8
+ for (var i = 0; (node = box.options[i]); i++) {
9
+ cache.push({value: node.value, text: node.text, displayed: 1});
10
+ }
11
+ },
12
+ redisplay: function(id) {
13
+ // Repopulate HTML select box from cache
14
+ var box = document.getElementById(id);
15
+ box.options.length = 0; // clear all options
16
+ for (var i = 0, j = SelectBox.cache[id].length; i < j; i++) {
17
+ var node = SelectBox.cache[id][i];
18
+ if (node.displayed) {
19
+ box.options[box.options.length] = new Option(node.text, node.value, false, false);
20
+ }
21
+ }
22
+ },
23
+ filter: function(id, text) {
24
+ // Redisplay the HTML select box, displaying only the choices containing ALL
25
+ // the words in text. (It's an AND search.)
26
+ var tokens = text.toLowerCase().split(/\s+/);
27
+ var node, token;
28
+ for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
29
+ node.displayed = 1;
30
+ for (var j = 0; (token = tokens[j]); j++) {
31
+ if (node.text.toLowerCase().indexOf(token) == -1) {
32
+ node.displayed = 0;
33
+ }
34
+ }
35
+ }
36
+ SelectBox.redisplay(id);
37
+ },
38
+ delete_from_cache: function(id, value) {
39
+ var node, delete_index = null;
40
+ for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
41
+ if (node.value == value) {
42
+ delete_index = i;
43
+ break;
44
+ }
45
+ }
46
+ var j = SelectBox.cache[id].length - 1;
47
+ for (var i = delete_index; i < j; i++) {
48
+ SelectBox.cache[id][i] = SelectBox.cache[id][i+1];
49
+ }
50
+ SelectBox.cache[id].length--;
51
+ },
52
+ add_to_cache: function(id, option) {
53
+ SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1});
54
+ },
55
+ cache_contains: function(id, value) {
56
+ // Check if an item is contained in the cache
57
+ var node;
58
+ for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
59
+ if (node.value == value) {
60
+ return true;
61
+ }
62
+ }
63
+ return false;
64
+ },
65
+ move: function(from, to) {
66
+ var from_box = document.getElementById(from);
67
+ var to_box = document.getElementById(to);
68
+ var option;
69
+ for (var i = 0; (option = from_box.options[i]); i++) {
70
+ if (option.selected && SelectBox.cache_contains(from, option.value)) {
71
+ SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
72
+ SelectBox.delete_from_cache(from, option.value);
73
+ }
74
+ }
75
+ SelectBox.redisplay(from);
76
+ SelectBox.redisplay(to);
77
+ },
78
+ move_all: function(from, to) {
79
+ var from_box = document.getElementById(from);
80
+ var to_box = document.getElementById(to);
81
+ var option;
82
+ for (var i = 0; (option = from_box.options[i]); i++) {
83
+ if (SelectBox.cache_contains(from, option.value)) {
84
+ SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
85
+ SelectBox.delete_from_cache(from, option.value);
86
+ }
87
+ }
88
+ SelectBox.redisplay(from);
89
+ SelectBox.redisplay(to);
90
+ },
91
+ sort: function(id) {
92
+ SelectBox.cache[id].sort( function(a, b) {
93
+ a = a.text.toLowerCase();
94
+ b = b.text.toLowerCase();
95
+ try {
96
+ if (a > b) return 1;
97
+ if (a < b) return -1;
98
+ }
99
+ catch (e) {
100
+ // silently fail on IE 'unknown' exception
101
+ }
102
+ return 0;
103
+ } );
104
+ },
105
+ select_all: function(id) {
106
+ var box = document.getElementById(id);
107
+ for (var i = 0; i < box.options.length; i++) {
108
+ box.options[i].selected = 'selected';
109
+ }
110
+ }
111
+ }
@@ -1,113 +1,113 @@
1
- /*
2
- SelectFilter2 - Turns a multiple-select box into a filter interface.
3
-
4
- Different than SelectFilter because this is coupled to the admin framework.
5
-
6
- Requires core.js, SelectBox.js and addevent.js.
7
- */
8
-
9
- function findForm(node) {
10
- // returns the node of the form containing the given node
11
- if (node.tagName.toLowerCase() != 'form') {
12
- return findForm(node.parentNode);
13
- }
14
- return node;
15
- }
16
-
17
- var SelectFilter = {
18
- init: function(field_id, field_name, is_stacked, admin_media_prefix) {
19
- var from_box = document.getElementById(field_id);
20
- from_box.id += '_from'; // change its ID
21
- from_box.className = 'filtered';
22
-
23
- // Remove <p class="info">, because it just gets in the way.
24
- var ps = from_box.parentNode.getElementsByTagName('p');
25
- for (var i=0; i<ps.length; i++) {
26
- from_box.parentNode.removeChild(ps[i]);
27
- }
28
-
29
- // <div class="selector"> or <div class="selector stacked">
30
- var selector_div = quickElement('div', from_box.parentNode);
31
- selector_div.className = is_stacked ? 'selector stacked' : 'selector';
32
-
33
- // <div class="selector-available">
34
- var selector_available = quickElement('div', selector_div, '');
35
- selector_available.className = 'selector-available';
36
- quickElement('h2', selector_available, interpolate(gettext('Available %s'), [field_name]));
37
- var filter_p = quickElement('p', selector_available, '');
38
- filter_p.className = 'selector-filter';
39
- quickElement('img', filter_p, '', 'src', admin_media_prefix + '/selector-search.gif');
40
- filter_p.appendChild(document.createTextNode(' '));
41
- var filter_input = quickElement('input', filter_p, '', 'type', 'text');
42
- filter_input.id = field_id + '_input';
43
- selector_available.appendChild(from_box);
44
- var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'href', 'javascript: (function(){ SelectBox.move_all("' + field_id + '_from", "' + field_id + '_to"); })()');
45
- choose_all.className = 'selector-chooseall';
46
-
47
- // <ul class="selector-chooser">
48
- var selector_chooser = quickElement('ul', selector_div, '');
49
- selector_chooser.className = 'selector-chooser';
50
- var add_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Add'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_from","' + field_id + '_to");})()');
51
- add_link.className = 'selector-add';
52
- var remove_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Remove'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_to","' + field_id + '_from");})()');
53
- remove_link.className = 'selector-remove';
54
-
55
- // <div class="selector-chosen">
56
- var selector_chosen = quickElement('div', selector_div, '');
57
- selector_chosen.className = 'selector-chosen';
58
- quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s'), [field_name]));
59
- var selector_filter = quickElement('p', selector_chosen, gettext('Select your choice(s) and click '));
60
- selector_filter.className = 'selector-filter';
61
- quickElement('img', selector_filter, '', 'src', admin_media_prefix + (is_stacked ? '/selector_stacked-add.gif':'/selector-add.gif'), 'alt', 'Add');
62
- var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name'));
63
- to_box.className = 'filtered';
64
- var clear_all = quickElement('a', selector_chosen, gettext('Clear all'), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from");})()');
65
- clear_all.className = 'selector-clearall';
66
-
67
- from_box.setAttribute('name', from_box.getAttribute('name') + '_old');
68
-
69
- // Set up the JavaScript event handlers for the select box filter interface
70
- addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); });
71
- addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); });
72
- addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); });
73
- addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); });
74
- addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); });
75
- SelectBox.init(field_id + '_from');
76
- SelectBox.init(field_id + '_to');
77
- // Move selected from_box options to to_box
78
- SelectBox.move(field_id + '_from', field_id + '_to');
79
- },
80
- filter_key_up: function(event, field_id) {
81
- from = document.getElementById(field_id + '_from');
82
- // don't submit form if user pressed Enter
83
- if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {
84
- from.selectedIndex = 0;
85
- SelectBox.move(field_id + '_from', field_id + '_to');
86
- from.selectedIndex = 0;
87
- return false;
88
- }
89
- var temp = from.selectedIndex;
90
- SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value);
91
- from.selectedIndex = temp;
92
- return true;
93
- },
94
- filter_key_down: function(event, field_id) {
95
- from = document.getElementById(field_id + '_from');
96
- // right arrow -- move across
97
- if ((event.which && event.which == 39) || (event.keyCode && event.keyCode == 39)) {
98
- var old_index = from.selectedIndex;
99
- SelectBox.move(field_id + '_from', field_id + '_to');
100
- from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index;
101
- return false;
102
- }
103
- // down arrow -- wrap around
104
- if ((event.which && event.which == 40) || (event.keyCode && event.keyCode == 40)) {
105
- from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1;
106
- }
107
- // up arrow -- wrap around
108
- if ((event.which && event.which == 38) || (event.keyCode && event.keyCode == 38)) {
109
- from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1;
110
- }
111
- return true;
112
- }
113
- }
1
+ /*
2
+ SelectFilter2 - Turns a multiple-select box into a filter interface.
3
+
4
+ Different than SelectFilter because this is coupled to the admin framework.
5
+
6
+ Requires core.js, SelectBox.js and addevent.js.
7
+ */
8
+
9
+ function findForm(node) {
10
+ // returns the node of the form containing the given node
11
+ if (node.tagName.toLowerCase() != 'form') {
12
+ return findForm(node.parentNode);
13
+ }
14
+ return node;
15
+ }
16
+
17
+ var SelectFilter = {
18
+ init: function(field_id, field_name, is_stacked, admin_media_prefix) {
19
+ var from_box = document.getElementById(field_id);
20
+ from_box.id += '_from'; // change its ID
21
+ from_box.className = 'filtered';
22
+
23
+ // Remove <p class="info">, because it just gets in the way.
24
+ var ps = from_box.parentNode.getElementsByTagName('p');
25
+ for (var i=0; i<ps.length; i++) {
26
+ from_box.parentNode.removeChild(ps[i]);
27
+ }
28
+
29
+ // <div class="selector"> or <div class="selector stacked">
30
+ var selector_div = quickElement('div', from_box.parentNode);
31
+ selector_div.className = is_stacked ? 'selector stacked' : 'selector';
32
+
33
+ // <div class="selector-available">
34
+ var selector_available = quickElement('div', selector_div, '');
35
+ selector_available.className = 'selector-available';
36
+ quickElement('h2', selector_available, interpolate(gettext('Available %s'), [field_name]));
37
+ var filter_p = quickElement('p', selector_available, '');
38
+ filter_p.className = 'selector-filter';
39
+ quickElement('img', filter_p, '', 'src', admin_media_prefix + '/selector-search.gif');
40
+ filter_p.appendChild(document.createTextNode(' '));
41
+ var filter_input = quickElement('input', filter_p, '', 'type', 'text');
42
+ filter_input.id = field_id + '_input';
43
+ selector_available.appendChild(from_box);
44
+ var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'href', 'javascript: (function(){ SelectBox.move_all("' + field_id + '_from", "' + field_id + '_to"); })()');
45
+ choose_all.className = 'selector-chooseall';
46
+
47
+ // <ul class="selector-chooser">
48
+ var selector_chooser = quickElement('ul', selector_div, '');
49
+ selector_chooser.className = 'selector-chooser';
50
+ var add_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Add'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_from","' + field_id + '_to");})()');
51
+ add_link.className = 'selector-add';
52
+ var remove_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Remove'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_to","' + field_id + '_from");})()');
53
+ remove_link.className = 'selector-remove';
54
+
55
+ // <div class="selector-chosen">
56
+ var selector_chosen = quickElement('div', selector_div, '');
57
+ selector_chosen.className = 'selector-chosen';
58
+ quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s'), [field_name]));
59
+ var selector_filter = quickElement('p', selector_chosen, gettext('Select your choice(s) and click '));
60
+ selector_filter.className = 'selector-filter';
61
+ quickElement('img', selector_filter, '', 'src', admin_media_prefix + (is_stacked ? '/selector_stacked-add.gif':'/selector-add.gif'), 'alt', 'Add');
62
+ var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name'));
63
+ to_box.className = 'filtered';
64
+ var clear_all = quickElement('a', selector_chosen, gettext('Clear all'), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from");})()');
65
+ clear_all.className = 'selector-clearall';
66
+
67
+ from_box.setAttribute('name', from_box.getAttribute('name') + '_old');
68
+
69
+ // Set up the JavaScript event handlers for the select box filter interface
70
+ addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); });
71
+ addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); });
72
+ addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); });
73
+ addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); });
74
+ addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); });
75
+ SelectBox.init(field_id + '_from');
76
+ SelectBox.init(field_id + '_to');
77
+ // Move selected from_box options to to_box
78
+ SelectBox.move(field_id + '_from', field_id + '_to');
79
+ },
80
+ filter_key_up: function(event, field_id) {
81
+ from = document.getElementById(field_id + '_from');
82
+ // don't submit form if user pressed Enter
83
+ if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {
84
+ from.selectedIndex = 0;
85
+ SelectBox.move(field_id + '_from', field_id + '_to');
86
+ from.selectedIndex = 0;
87
+ return false;
88
+ }
89
+ var temp = from.selectedIndex;
90
+ SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value);
91
+ from.selectedIndex = temp;
92
+ return true;
93
+ },
94
+ filter_key_down: function(event, field_id) {
95
+ from = document.getElementById(field_id + '_from');
96
+ // right arrow -- move across
97
+ if ((event.which && event.which == 39) || (event.keyCode && event.keyCode == 39)) {
98
+ var old_index = from.selectedIndex;
99
+ SelectBox.move(field_id + '_from', field_id + '_to');
100
+ from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index;
101
+ return false;
102
+ }
103
+ // down arrow -- wrap around
104
+ if ((event.which && event.which == 40) || (event.keyCode && event.keyCode == 40)) {
105
+ from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1;
106
+ }
107
+ // up arrow -- wrap around
108
+ if ((event.which && event.which == 38) || (event.keyCode && event.keyCode == 38)) {
109
+ from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1;
110
+ }
111
+ return true;
112
+ }
113
+ }