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
data/merb-admin.gemspec CHANGED
@@ -1,232 +1,42 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{merb-admin}
8
- s.version = "0.8.1"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Erik Michaels-Ober"]
12
- s.date = %q{2010-04-20}
13
- s.description = %q{MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data.}
14
- s.email = %q{sferik@gmail.com}
15
- s.extra_rdoc_files = [
16
- "LICENSE",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".gitignore",
21
- "Gemfile",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION",
26
- "app/controllers/application.rb",
27
- "app/controllers/main.rb",
28
- "app/helpers/application_helper.rb",
29
- "app/helpers/main_helper.rb",
30
- "app/views/layout/_message.html.erb",
31
- "app/views/layout/dashboard.html.erb",
32
- "app/views/layout/form.html.erb",
33
- "app/views/layout/list.html.erb",
34
- "app/views/main/_belongs_to.html.erb",
35
- "app/views/main/_big_decimal.html.erb",
36
- "app/views/main/_boolean.html.erb",
37
- "app/views/main/_date.html.erb",
38
- "app/views/main/_datetime.html.erb",
39
- "app/views/main/_float.html.erb",
40
- "app/views/main/_has_many.html.erb",
41
- "app/views/main/_has_one.html.erb",
42
- "app/views/main/_integer.html.erb",
43
- "app/views/main/_properties.html.erb",
44
- "app/views/main/_string.html.erb",
45
- "app/views/main/_text.html.erb",
46
- "app/views/main/_time.html.erb",
47
- "app/views/main/_timestamp.html.erb",
48
- "app/views/main/delete.html.erb",
49
- "app/views/main/edit.html.erb",
50
- "app/views/main/index.html.erb",
51
- "app/views/main/list.html.erb",
52
- "app/views/main/new.html.erb",
53
- "lib/abstract_model.rb",
54
- "lib/active_record_support.rb",
55
- "lib/datamapper_support.rb",
56
- "lib/generic_support.rb",
57
- "lib/merb-admin.rb",
58
- "lib/merb-admin/merbtasks.rb",
59
- "lib/merb-admin/slicetasks.rb",
60
- "lib/merb-admin/spectasks.rb",
61
- "lib/sequel_support.rb",
62
- "merb-admin.gemspec",
63
- "public/images/arrow-down.gif",
64
- "public/images/arrow-up.gif",
65
- "public/images/changelist-bg.gif",
66
- "public/images/changelist-bg_rtl.gif",
67
- "public/images/chooser-bg.gif",
68
- "public/images/chooser_stacked-bg.gif",
69
- "public/images/default-bg-reverse.gif",
70
- "public/images/default-bg.gif",
71
- "public/images/deleted-overlay.gif",
72
- "public/images/icon-no.gif",
73
- "public/images/icon-unknown.gif",
74
- "public/images/icon-yes.gif",
75
- "public/images/icon_addlink.gif",
76
- "public/images/icon_alert.gif",
77
- "public/images/icon_calendar.gif",
78
- "public/images/icon_changelink.gif",
79
- "public/images/icon_clock.gif",
80
- "public/images/icon_deletelink.gif",
81
- "public/images/icon_error.gif",
82
- "public/images/icon_searchbox.png",
83
- "public/images/icon_success.gif",
84
- "public/images/inline-delete-8bit.png",
85
- "public/images/inline-delete.png",
86
- "public/images/inline-restore-8bit.png",
87
- "public/images/inline-restore.png",
88
- "public/images/inline-splitter-bg.gif",
89
- "public/images/nav-bg-grabber.gif",
90
- "public/images/nav-bg-reverse.gif",
91
- "public/images/nav-bg.gif",
92
- "public/images/selector-add.gif",
93
- "public/images/selector-addall.gif",
94
- "public/images/selector-remove.gif",
95
- "public/images/selector-removeall.gif",
96
- "public/images/selector-search.gif",
97
- "public/images/selector_stacked-add.gif",
98
- "public/images/selector_stacked-remove.gif",
99
- "public/images/tool-left.gif",
100
- "public/images/tool-left_over.gif",
101
- "public/images/tool-right.gif",
102
- "public/images/tool-right_over.gif",
103
- "public/images/tooltag-add.gif",
104
- "public/images/tooltag-add_over.gif",
105
- "public/images/tooltag-arrowright.gif",
106
- "public/images/tooltag-arrowright_over.gif",
107
- "public/javascripts/CollapsedFieldsets.js",
108
- "public/javascripts/DateTimeShortcuts.js",
109
- "public/javascripts/RelatedObjectLookups.js",
110
- "public/javascripts/SelectBox.js",
111
- "public/javascripts/SelectFilter2.js",
112
- "public/javascripts/actions.js",
113
- "public/javascripts/calendar.js",
114
- "public/javascripts/core.js",
115
- "public/javascripts/dateparse.js",
116
- "public/javascripts/getElementsBySelector.js",
117
- "public/javascripts/i18n.js",
118
- "public/javascripts/master.js",
119
- "public/javascripts/ordering.js",
120
- "public/javascripts/timeparse.js",
121
- "public/javascripts/urlify.js",
122
- "public/stylesheets/base.css",
123
- "public/stylesheets/changelists.css",
124
- "public/stylesheets/dashboard.css",
125
- "public/stylesheets/forms.css",
126
- "public/stylesheets/global.css",
127
- "public/stylesheets/ie.css",
128
- "public/stylesheets/layout.css",
129
- "public/stylesheets/login.css",
130
- "public/stylesheets/master.css",
131
- "public/stylesheets/null.css",
132
- "public/stylesheets/patch-iewin.css",
133
- "public/stylesheets/rtl.css",
134
- "public/stylesheets/widgets.css",
135
- "spec/controllers/main_spec.rb",
136
- "spec/migrations/activerecord/001_create_divisions_migration.rb",
137
- "spec/migrations/activerecord/002_create_drafts_migration.rb",
138
- "spec/migrations/activerecord/003_create_leagues_migration.rb",
139
- "spec/migrations/activerecord/004_create_players_migration.rb",
140
- "spec/migrations/activerecord/005_create_teams_migration.rb",
141
- "spec/migrations/sequel/001_create_divisions_migration.rb",
142
- "spec/migrations/sequel/002_create_drafts_migration.rb",
143
- "spec/migrations/sequel/003_create_leagues_migration.rb",
144
- "spec/migrations/sequel/004_create_players_migration.rb",
145
- "spec/migrations/sequel/005_create_teams_migration.rb",
146
- "spec/models/activerecord/division.rb",
147
- "spec/models/activerecord/draft.rb",
148
- "spec/models/activerecord/league.rb",
149
- "spec/models/activerecord/player.rb",
150
- "spec/models/activerecord/team.rb",
151
- "spec/models/datamapper/division.rb",
152
- "spec/models/datamapper/draft.rb",
153
- "spec/models/datamapper/league.rb",
154
- "spec/models/datamapper/player.rb",
155
- "spec/models/datamapper/team.rb",
156
- "spec/models/sequel/division.rb",
157
- "spec/models/sequel/draft.rb",
158
- "spec/models/sequel/league.rb",
159
- "spec/models/sequel/player.rb",
160
- "spec/models/sequel/team.rb",
161
- "spec/requests/main_spec.rb",
162
- "spec/spec_helper.rb"
163
- ]
164
- s.homepage = %q{http://github.com/sferik/merb-admin}
165
- s.post_install_message = %q{********************************************************************************
166
-
167
- WARNING: MerbAdmin does not implement any authorization scheme.
168
- Make sure to apply authorization logic before deploying to production!
169
-
170
- ********************************************************************************
171
- }
172
- s.rdoc_options = ["--charset=UTF-8"]
173
- s.require_paths = ["lib"]
174
- s.rubygems_version = %q{1.3.6}
175
- s.summary = %q{MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data.}
176
- s.test_files = [
177
- "spec/controllers/main_spec.rb",
178
- "spec/migrations/activerecord/001_create_divisions_migration.rb",
179
- "spec/migrations/activerecord/002_create_drafts_migration.rb",
180
- "spec/migrations/activerecord/003_create_leagues_migration.rb",
181
- "spec/migrations/activerecord/004_create_players_migration.rb",
182
- "spec/migrations/activerecord/005_create_teams_migration.rb",
183
- "spec/migrations/sequel/001_create_divisions_migration.rb",
184
- "spec/migrations/sequel/002_create_drafts_migration.rb",
185
- "spec/migrations/sequel/003_create_leagues_migration.rb",
186
- "spec/migrations/sequel/004_create_players_migration.rb",
187
- "spec/migrations/sequel/005_create_teams_migration.rb",
188
- "spec/models/activerecord/division.rb",
189
- "spec/models/activerecord/draft.rb",
190
- "spec/models/activerecord/league.rb",
191
- "spec/models/activerecord/player.rb",
192
- "spec/models/activerecord/team.rb",
193
- "spec/models/datamapper/division.rb",
194
- "spec/models/datamapper/draft.rb",
195
- "spec/models/datamapper/league.rb",
196
- "spec/models/datamapper/player.rb",
197
- "spec/models/datamapper/team.rb",
198
- "spec/models/sequel/division.rb",
199
- "spec/models/sequel/draft.rb",
200
- "spec/models/sequel/league.rb",
201
- "spec/models/sequel/player.rb",
202
- "spec/models/sequel/team.rb",
203
- "spec/requests/main_spec.rb",
204
- "spec/spec_helper.rb"
205
- ]
206
-
207
- if s.respond_to? :specification_version then
208
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
209
- s.specification_version = 3
210
-
211
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
212
- s.add_runtime_dependency(%q<merb-slices>, ["~> 1.1"])
213
- s.add_runtime_dependency(%q<merb-assets>, ["~> 1.1"])
214
- s.add_runtime_dependency(%q<merb-helpers>, ["~> 1.1"])
215
- s.add_runtime_dependency(%q<builder>, ["~> 2.1"])
216
- s.add_development_dependency(%q<rspec>, ["~> 1.3"])
217
- else
218
- s.add_dependency(%q<merb-slices>, ["~> 1.1"])
219
- s.add_dependency(%q<merb-assets>, ["~> 1.1"])
220
- s.add_dependency(%q<merb-helpers>, ["~> 1.1"])
221
- s.add_dependency(%q<builder>, ["~> 2.1"])
222
- s.add_dependency(%q<rspec>, ["~> 1.3"])
223
- end
224
- else
225
- s.add_dependency(%q<merb-slices>, ["~> 1.1"])
226
- s.add_dependency(%q<merb-assets>, ["~> 1.1"])
227
- s.add_dependency(%q<merb-helpers>, ["~> 1.1"])
228
- s.add_dependency(%q<builder>, ["~> 2.1"])
229
- s.add_dependency(%q<rspec>, ["~> 1.3"])
230
- end
231
- end
232
-
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/merb-admin/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.add_development_dependency("activerecord", ["~> 2.3"])
6
+ s.add_development_dependency("dm-core", ["~> 0.10"])
7
+ s.add_development_dependency("dm-aggregates", ["~> 0.10"])
8
+ s.add_development_dependency("dm-types", ["~> 0.10"])
9
+ s.add_development_dependency("dm-migrations", ["~> 0.10"])
10
+ s.add_development_dependency("dm-validations", ["~> 0.10"])
11
+ s.add_development_dependency("data_objects", ["~> 0.10"])
12
+ s.add_development_dependency("do_sqlite3", ["~> 0.10"])
13
+ s.add_development_dependency("rspec", ["~> 1.3"])
14
+ s.add_development_dependency("sequel", ["~> 3.6.0"])
15
+ s.add_development_dependency("sqlite3-ruby", ["~> 1.3"])
16
+ s.add_development_dependency("webrat", ["~> 0.7"])
17
+ s.add_runtime_dependency("builder", ["~> 2.1"])
18
+ s.add_runtime_dependency("json", ["~> 1.4"])
19
+ s.add_runtime_dependency("merb-assets", ["~> 1.1"])
20
+ s.add_runtime_dependency("merb-helpers", ["~> 1.1"])
21
+ s.add_runtime_dependency("merb-slices", ["~> 1.1"])
22
+ s.authors = ["Erik Michaels-Ober"]
23
+ s.description = %q{MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data}
24
+ s.email = "sferik@gmail.com"
25
+ s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
26
+ s.files = `git ls-files`.split("\n")
27
+ s.homepage = "http://rubygems.org/gems/merb-admin"
28
+ s.name = "merb-admin"
29
+ s.post_install_message =<<eos
30
+ ********************************************************************************
31
+ Make sure to add authorization logic before deploying to production!
32
+ WARNING: MerbAdmin does not implement any authorization scheme.
33
+ ********************************************************************************
34
+ eos
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.required_rubygems_version = ">= 1.3.6"
38
+ s.rubyforge_project = "merb-admin"
39
+ s.summary = %q{MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data}
40
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
41
+ s.version = MerbAdmin::VERSION
42
+ end
@@ -1,85 +1,85 @@
1
- // Finds all fieldsets with class="collapse", collapses them, and gives each
2
- // one a "Show" link that uncollapses it. The "Show" link becomes a "Hide"
3
- // link when the fieldset is visible.
4
-
5
- function findForm(node) {
6
- // returns the node of the form containing the given node
7
- if (node.tagName.toLowerCase() != 'form') {
8
- return findForm(node.parentNode);
9
- }
10
- return node;
11
- }
12
-
13
- var CollapsedFieldsets = {
14
- collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
15
- collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
16
- collapsed_class: 'collapsed',
17
- init: function() {
18
- var fieldsets = document.getElementsByTagName('fieldset');
19
- var collapsed_seen = false;
20
- for (var i = 0, fs; fs = fieldsets[i]; i++) {
21
- // Collapse this fieldset if it has the correct class, and if it
22
- // doesn't have any errors. (Collapsing shouldn't apply in the case
23
- // of error messages.)
24
- if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
25
- collapsed_seen = true;
26
- // Give it an additional class, used by CSS to hide it.
27
- fs.className += ' ' + CollapsedFieldsets.collapsed_class;
28
- // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
29
- var collapse_link = document.createElement('a');
30
- collapse_link.className = 'collapse-toggle';
31
- collapse_link.id = 'fieldsetcollapser' + i;
32
- collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
33
- collapse_link.href = '#';
34
- collapse_link.innerHTML = gettext('Show');
35
- var h2 = fs.getElementsByTagName('h2')[0];
36
- h2.appendChild(document.createTextNode(' ('));
37
- h2.appendChild(collapse_link);
38
- h2.appendChild(document.createTextNode(')'));
39
- }
40
- }
41
- if (collapsed_seen) {
42
- // Expand all collapsed fieldsets when form is submitted.
43
- addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
44
- }
45
- },
46
- fieldset_has_errors: function(fs) {
47
- // Returns true if any fields in the fieldset have validation errors.
48
- var divs = fs.getElementsByTagName('div');
49
- for (var i=0; i<divs.length; i++) {
50
- if (divs[i].className.match(/\berrors\b/)) {
51
- return true;
52
- }
53
- }
54
- return false;
55
- },
56
- show: function(fieldset_index) {
57
- var fs = document.getElementsByTagName('fieldset')[fieldset_index];
58
- // Remove the class name that causes the "display: none".
59
- fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
60
- // Toggle the "Show" link to a "Hide" link
61
- var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
62
- collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
63
- collapse_link.innerHTML = gettext('Hide');
64
- },
65
- hide: function(fieldset_index) {
66
- var fs = document.getElementsByTagName('fieldset')[fieldset_index];
67
- // Add the class name that causes the "display: none".
68
- fs.className += ' ' + CollapsedFieldsets.collapsed_class;
69
- // Toggle the "Hide" link to a "Show" link
70
- var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
71
- collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
72
- collapse_link.innerHTML = gettext('Show');
73
- },
74
-
75
- uncollapse_all: function() {
76
- var fieldsets = document.getElementsByTagName('fieldset');
77
- for (var i=0; i<fieldsets.length; i++) {
78
- if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
79
- CollapsedFieldsets.show(i);
80
- }
81
- }
82
- }
83
- }
84
-
85
- addEvent(window, 'load', CollapsedFieldsets.init);
1
+ // Finds all fieldsets with class="collapse", collapses them, and gives each
2
+ // one a "Show" link that uncollapses it. The "Show" link becomes a "Hide"
3
+ // link when the fieldset is visible.
4
+
5
+ function findForm(node) {
6
+ // returns the node of the form containing the given node
7
+ if (node.tagName.toLowerCase() != 'form') {
8
+ return findForm(node.parentNode);
9
+ }
10
+ return node;
11
+ }
12
+
13
+ var CollapsedFieldsets = {
14
+ collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
15
+ collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
16
+ collapsed_class: 'collapsed',
17
+ init: function() {
18
+ var fieldsets = document.getElementsByTagName('fieldset');
19
+ var collapsed_seen = false;
20
+ for (var i = 0, fs; fs = fieldsets[i]; i++) {
21
+ // Collapse this fieldset if it has the correct class, and if it
22
+ // doesn't have any errors. (Collapsing shouldn't apply in the case
23
+ // of error messages.)
24
+ if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
25
+ collapsed_seen = true;
26
+ // Give it an additional class, used by CSS to hide it.
27
+ fs.className += ' ' + CollapsedFieldsets.collapsed_class;
28
+ // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
29
+ var collapse_link = document.createElement('a');
30
+ collapse_link.className = 'collapse-toggle';
31
+ collapse_link.id = 'fieldsetcollapser' + i;
32
+ collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
33
+ collapse_link.href = '#';
34
+ collapse_link.innerHTML = gettext('Show');
35
+ var h2 = fs.getElementsByTagName('h2')[0];
36
+ h2.appendChild(document.createTextNode(' ('));
37
+ h2.appendChild(collapse_link);
38
+ h2.appendChild(document.createTextNode(')'));
39
+ }
40
+ }
41
+ if (collapsed_seen) {
42
+ // Expand all collapsed fieldsets when form is submitted.
43
+ addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
44
+ }
45
+ },
46
+ fieldset_has_errors: function(fs) {
47
+ // Returns true if any fields in the fieldset have validation errors.
48
+ var divs = fs.getElementsByTagName('div');
49
+ for (var i=0; i<divs.length; i++) {
50
+ if (divs[i].className.match(/\berrors\b/)) {
51
+ return true;
52
+ }
53
+ }
54
+ return false;
55
+ },
56
+ show: function(fieldset_index) {
57
+ var fs = document.getElementsByTagName('fieldset')[fieldset_index];
58
+ // Remove the class name that causes the "display: none".
59
+ fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
60
+ // Toggle the "Show" link to a "Hide" link
61
+ var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
62
+ collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
63
+ collapse_link.innerHTML = gettext('Hide');
64
+ },
65
+ hide: function(fieldset_index) {
66
+ var fs = document.getElementsByTagName('fieldset')[fieldset_index];
67
+ // Add the class name that causes the "display: none".
68
+ fs.className += ' ' + CollapsedFieldsets.collapsed_class;
69
+ // Toggle the "Hide" link to a "Show" link
70
+ var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
71
+ collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
72
+ collapse_link.innerHTML = gettext('Show');
73
+ },
74
+
75
+ uncollapse_all: function() {
76
+ var fieldsets = document.getElementsByTagName('fieldset');
77
+ for (var i=0; i<fieldsets.length; i++) {
78
+ if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
79
+ CollapsedFieldsets.show(i);
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ addEvent(window, 'load', CollapsedFieldsets.init);
@@ -1,255 +1,255 @@
1
- // Inserts shortcut buttons after all of the following:
2
- // <input type="text" class="vDateField">
3
- // <input type="text" class="vTimeField">
4
-
5
- var DateTimeShortcuts = {
6
- calendars: [],
7
- calendarInputs: [],
8
- clockInputs: [],
9
- calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
10
- calendarDivName2: 'calendarin', // name of <div> that contains calendar
11
- calendarLinkName: 'calendarlink',// name of the link that is used to toggle
12
- clockDivName: 'clockbox', // name of clock <div> that gets toggled
13
- clockLinkName: 'clocklink', // name of the link that is used to toggle
14
- admin_media_prefix: '',
15
- init: function() {
16
- // Deduce admin_media_prefix by looking at the <script>s in the
17
- // current document and finding the URL of *this* module.
18
- var scripts = document.getElementsByTagName('script');
19
- for (var i=0; i<scripts.length; i++) {
20
- if (scripts[i].src.match(/DateTimeShortcuts/)) {
21
- var idx = scripts[i].src.indexOf('DateTimeShortcuts');
22
- DateTimeShortcuts.admin_media_prefix = scripts[i].src.substring(0, idx);
23
- break;
24
- }
25
- }
26
-
27
- var inputs = document.getElementsByTagName('input');
28
- for (i=0; i<inputs.length; i++) {
29
- var inp = inputs[i];
30
- if (inp.getAttribute('type') == 'text' && inp.className.match(/vTimeField/)) {
31
- DateTimeShortcuts.addClock(inp);
32
- }
33
- else if (inp.getAttribute('type') == 'text' && inp.className.match(/vDateField/)) {
34
- DateTimeShortcuts.addCalendar(inp);
35
- }
36
- }
37
- },
38
- // Add clock widget to a given field
39
- addClock: function(inp) {
40
- var num = DateTimeShortcuts.clockInputs.length;
41
- DateTimeShortcuts.clockInputs[num] = inp;
42
-
43
- // Shortcut links (clock icon and "Now" link)
44
- var shortcuts_span = document.createElement('span');
45
- inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
46
- var now_link = document.createElement('a');
47
- now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());");
48
- now_link.appendChild(document.createTextNode(gettext('Now')));
49
- var clock_link = document.createElement('a');
50
- clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
51
- clock_link.id = DateTimeShortcuts.clockLinkName + num;
52
- quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + '../images/icon_clock.gif', 'alt', gettext('Clock'));
53
- shortcuts_span.appendChild(document.createTextNode('\240'));
54
- shortcuts_span.appendChild(now_link);
55
- shortcuts_span.appendChild(document.createTextNode('\240|\240'));
56
- shortcuts_span.appendChild(clock_link);
57
-
58
- // Create clock link div
59
- //
60
- // Markup looks like:
61
- // <div id="clockbox1" class="clockbox module">
62
- // <h2>Choose a time</h2>
63
- // <ul class="timelist">
64
- // <li><a href="#">Now</a></li>
65
- // <li><a href="#">Midnight</a></li>
66
- // <li><a href="#">6 a.m.</a></li>
67
- // <li><a href="#">Noon</a></li>
68
- // </ul>
69
- // <p class="calendar-cancel"><a href="#">Cancel</a></p>
70
- // </div>
71
-
72
- var clock_box = document.createElement('div');
73
- clock_box.style.display = 'none';
74
- clock_box.style.position = 'absolute';
75
- clock_box.className = 'clockbox module';
76
- clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
77
- document.body.appendChild(clock_box);
78
- addEvent(clock_box, 'click', DateTimeShortcuts.cancelEventPropagation);
79
-
80
- quickElement('h2', clock_box, gettext('Choose a time'));
81
- time_list = quickElement('ul', clock_box, '');
82
- time_list.className = 'timelist';
83
- quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());")
84
- quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '00:00:00');")
85
- quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '06:00:00');")
86
- quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '12:00:00');")
87
-
88
- cancel_p = quickElement('p', clock_box, '');
89
- cancel_p.className = 'calendar-cancel';
90
- quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
91
- },
92
- openClock: function(num) {
93
- var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
94
- var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
95
-
96
- // Recalculate the clockbox position
97
- // is it left-to-right or right-to-left layout ?
98
- if (getStyle(document.body,'direction')!='rtl') {
99
- clock_box.style.left = findPosX(clock_link) + 17 + 'px';
100
- }
101
- else {
102
- // since style's width is in em, it'd be tough to calculate
103
- // px value of it. let's use an estimated px for now
104
- // TODO: IE returns wrong value for findPosX when in rtl mode
105
- // (it returns as it was left aligned), needs to be fixed.
106
- clock_box.style.left = findPosX(clock_link) - 110 + 'px';
107
- }
108
- clock_box.style.top = findPosY(clock_link) - 30 + 'px';
109
-
110
- // Show the clock box
111
- clock_box.style.display = 'block';
112
- addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
113
- },
114
- dismissClock: function(num) {
115
- document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
116
- window.document.onclick = null;
117
- },
118
- handleClockQuicklink: function(num, val) {
119
- DateTimeShortcuts.clockInputs[num].value = val;
120
- DateTimeShortcuts.dismissClock(num);
121
- },
122
- // Add calendar widget to a given field.
123
- addCalendar: function(inp) {
124
- var num = DateTimeShortcuts.calendars.length;
125
-
126
- DateTimeShortcuts.calendarInputs[num] = inp;
127
-
128
- // Shortcut links (calendar icon and "Today" link)
129
- var shortcuts_span = document.createElement('span');
130
- inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
131
- var today_link = document.createElement('a');
132
- today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
133
- today_link.appendChild(document.createTextNode(gettext('Today')));
134
- var cal_link = document.createElement('a');
135
- cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
136
- cal_link.id = DateTimeShortcuts.calendarLinkName + num;
137
- quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + '../images/icon_calendar.gif', 'alt', gettext('Calendar'));
138
- shortcuts_span.appendChild(document.createTextNode('\240'));
139
- shortcuts_span.appendChild(today_link);
140
- shortcuts_span.appendChild(document.createTextNode('\240|\240'));
141
- shortcuts_span.appendChild(cal_link);
142
-
143
- // Create calendarbox div.
144
- //
145
- // Markup looks like:
146
- //
147
- // <div id="calendarbox3" class="calendarbox module">
148
- // <h2>
149
- // <a href="#" class="link-previous">&lsaquo;</a>
150
- // <a href="#" class="link-next">&rsaquo;</a> February 2003
151
- // </h2>
152
- // <div class="calendar" id="calendarin3">
153
- // <!-- (cal) -->
154
- // </div>
155
- // <div class="calendar-shortcuts">
156
- // <a href="#">Yesterday</a> | <a href="#">Today</a> | <a href="#">Tomorrow</a>
157
- // </div>
158
- // <p class="calendar-cancel"><a href="#">Cancel</a></p>
159
- // </div>
160
- var cal_box = document.createElement('div');
161
- cal_box.style.display = 'none';
162
- cal_box.style.position = 'absolute';
163
- cal_box.className = 'calendarbox module';
164
- cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
165
- document.body.appendChild(cal_box);
166
- addEvent(cal_box, 'click', DateTimeShortcuts.cancelEventPropagation);
167
-
168
- // next-prev links
169
- var cal_nav = quickElement('div', cal_box, '');
170
- var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');');
171
- cal_nav_prev.className = 'calendarnav-previous';
172
- var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
173
- cal_nav_next.className = 'calendarnav-next';
174
-
175
- // main box
176
- var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
177
- cal_main.className = 'calendar';
178
- DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
179
- DateTimeShortcuts.calendars[num].drawCurrent();
180
-
181
- // calendar shortcuts
182
- var shortcuts = quickElement('div', cal_box, '');
183
- shortcuts.className = 'calendar-shortcuts';
184
- quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
185
- shortcuts.appendChild(document.createTextNode('\240|\240'));
186
- quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
187
- shortcuts.appendChild(document.createTextNode('\240|\240'));
188
- quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');
189
-
190
- // cancel bar
191
- var cancel_p = quickElement('p', cal_box, '');
192
- cancel_p.className = 'calendar-cancel';
193
- quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
194
- },
195
- openCalendar: function(num) {
196
- var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
197
- var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
198
- var inp = DateTimeShortcuts.calendarInputs[num];
199
-
200
- // Determine if the current value in the input has a valid date.
201
- // If so, draw the calendar with that date's year and month.
202
- if (inp.value) {
203
- var date_parts = inp.value.split('-');
204
- var year = date_parts[0];
205
- var month = parseFloat(date_parts[1]);
206
- if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) {
207
- DateTimeShortcuts.calendars[num].drawDate(month, year);
208
- }
209
- }
210
-
211
-
212
- // Recalculate the clockbox position
213
- // is it left-to-right or right-to-left layout ?
214
- if (getStyle(document.body,'direction')!='rtl') {
215
- cal_box.style.left = findPosX(cal_link) + 17 + 'px';
216
- }
217
- else {
218
- // since style's width is in em, it'd be tough to calculate
219
- // px value of it. let's use an estimated px for now
220
- // TODO: IE returns wrong value for findPosX when in rtl mode
221
- // (it returns as it was left aligned), needs to be fixed.
222
- cal_box.style.left = findPosX(cal_link) - 180 + 'px';
223
- }
224
- cal_box.style.top = findPosY(cal_link) - 75 + 'px';
225
-
226
- cal_box.style.display = 'block';
227
- addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
228
- },
229
- dismissCalendar: function(num) {
230
- document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none';
231
- window.document.onclick = null;
232
- },
233
- drawPrev: function(num) {
234
- DateTimeShortcuts.calendars[num].drawPreviousMonth();
235
- },
236
- drawNext: function(num) {
237
- DateTimeShortcuts.calendars[num].drawNextMonth();
238
- },
239
- handleCalendarCallback: function(num) {
240
- return "function(y, m, d) { DateTimeShortcuts.calendarInputs["+num+"].value = y+'-'+(m<10?'0':'')+m+'-'+(d<10?'0':'')+d; document.getElementById(DateTimeShortcuts.calendarDivName1+"+num+").style.display='none';}";
241
- },
242
- handleCalendarQuickLink: function(num, offset) {
243
- var d = new Date();
244
- d.setDate(d.getDate() + offset)
245
- DateTimeShortcuts.calendarInputs[num].value = d.getISODate();
246
- DateTimeShortcuts.dismissCalendar(num);
247
- },
248
- cancelEventPropagation: function(e) {
249
- if (!e) e = window.event;
250
- e.cancelBubble = true;
251
- if (e.stopPropagation) e.stopPropagation();
252
- }
253
- }
254
-
255
- addEvent(window, 'load', DateTimeShortcuts.init);
1
+ // Inserts shortcut buttons after all of the following:
2
+ // <input type="text" class="vDateField">
3
+ // <input type="text" class="vTimeField">
4
+
5
+ var DateTimeShortcuts = {
6
+ calendars: [],
7
+ calendarInputs: [],
8
+ clockInputs: [],
9
+ calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
10
+ calendarDivName2: 'calendarin', // name of <div> that contains calendar
11
+ calendarLinkName: 'calendarlink',// name of the link that is used to toggle
12
+ clockDivName: 'clockbox', // name of clock <div> that gets toggled
13
+ clockLinkName: 'clocklink', // name of the link that is used to toggle
14
+ admin_media_prefix: '',
15
+ init: function() {
16
+ // Deduce admin_media_prefix by looking at the <script>s in the
17
+ // current document and finding the URL of *this* module.
18
+ var scripts = document.getElementsByTagName('script');
19
+ for (var i=0; i<scripts.length; i++) {
20
+ if (scripts[i].src.match(/DateTimeShortcuts/)) {
21
+ var idx = scripts[i].src.indexOf('DateTimeShortcuts');
22
+ DateTimeShortcuts.admin_media_prefix = scripts[i].src.substring(0, idx);
23
+ break;
24
+ }
25
+ }
26
+
27
+ var inputs = document.getElementsByTagName('input');
28
+ for (i=0; i<inputs.length; i++) {
29
+ var inp = inputs[i];
30
+ if (inp.getAttribute('type') == 'text' && inp.className.match(/vTimeField/)) {
31
+ DateTimeShortcuts.addClock(inp);
32
+ }
33
+ else if (inp.getAttribute('type') == 'text' && inp.className.match(/vDateField/)) {
34
+ DateTimeShortcuts.addCalendar(inp);
35
+ }
36
+ }
37
+ },
38
+ // Add clock widget to a given field
39
+ addClock: function(inp) {
40
+ var num = DateTimeShortcuts.clockInputs.length;
41
+ DateTimeShortcuts.clockInputs[num] = inp;
42
+
43
+ // Shortcut links (clock icon and "Now" link)
44
+ var shortcuts_span = document.createElement('span');
45
+ inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
46
+ var now_link = document.createElement('a');
47
+ now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());");
48
+ now_link.appendChild(document.createTextNode(gettext('Now')));
49
+ var clock_link = document.createElement('a');
50
+ clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
51
+ clock_link.id = DateTimeShortcuts.clockLinkName + num;
52
+ quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + '../images/icon_clock.gif', 'alt', gettext('Clock'));
53
+ shortcuts_span.appendChild(document.createTextNode('\240'));
54
+ shortcuts_span.appendChild(now_link);
55
+ shortcuts_span.appendChild(document.createTextNode('\240|\240'));
56
+ shortcuts_span.appendChild(clock_link);
57
+
58
+ // Create clock link div
59
+ //
60
+ // Markup looks like:
61
+ // <div id="clockbox1" class="clockbox module">
62
+ // <h2>Choose a time</h2>
63
+ // <ul class="timelist">
64
+ // <li><a href="#">Now</a></li>
65
+ // <li><a href="#">Midnight</a></li>
66
+ // <li><a href="#">6 a.m.</a></li>
67
+ // <li><a href="#">Noon</a></li>
68
+ // </ul>
69
+ // <p class="calendar-cancel"><a href="#">Cancel</a></p>
70
+ // </div>
71
+
72
+ var clock_box = document.createElement('div');
73
+ clock_box.style.display = 'none';
74
+ clock_box.style.position = 'absolute';
75
+ clock_box.className = 'clockbox module';
76
+ clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
77
+ document.body.appendChild(clock_box);
78
+ addEvent(clock_box, 'click', DateTimeShortcuts.cancelEventPropagation);
79
+
80
+ quickElement('h2', clock_box, gettext('Choose a time'));
81
+ time_list = quickElement('ul', clock_box, '');
82
+ time_list.className = 'timelist';
83
+ quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());")
84
+ quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '00:00:00');")
85
+ quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '06:00:00');")
86
+ quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '12:00:00');")
87
+
88
+ cancel_p = quickElement('p', clock_box, '');
89
+ cancel_p.className = 'calendar-cancel';
90
+ quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
91
+ },
92
+ openClock: function(num) {
93
+ var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
94
+ var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
95
+
96
+ // Recalculate the clockbox position
97
+ // is it left-to-right or right-to-left layout ?
98
+ if (getStyle(document.body,'direction')!='rtl') {
99
+ clock_box.style.left = findPosX(clock_link) + 17 + 'px';
100
+ }
101
+ else {
102
+ // since style's width is in em, it'd be tough to calculate
103
+ // px value of it. let's use an estimated px for now
104
+ // TODO: IE returns wrong value for findPosX when in rtl mode
105
+ // (it returns as it was left aligned), needs to be fixed.
106
+ clock_box.style.left = findPosX(clock_link) - 110 + 'px';
107
+ }
108
+ clock_box.style.top = findPosY(clock_link) - 30 + 'px';
109
+
110
+ // Show the clock box
111
+ clock_box.style.display = 'block';
112
+ addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
113
+ },
114
+ dismissClock: function(num) {
115
+ document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
116
+ window.document.onclick = null;
117
+ },
118
+ handleClockQuicklink: function(num, val) {
119
+ DateTimeShortcuts.clockInputs[num].value = val;
120
+ DateTimeShortcuts.dismissClock(num);
121
+ },
122
+ // Add calendar widget to a given field.
123
+ addCalendar: function(inp) {
124
+ var num = DateTimeShortcuts.calendars.length;
125
+
126
+ DateTimeShortcuts.calendarInputs[num] = inp;
127
+
128
+ // Shortcut links (calendar icon and "Today" link)
129
+ var shortcuts_span = document.createElement('span');
130
+ inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
131
+ var today_link = document.createElement('a');
132
+ today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
133
+ today_link.appendChild(document.createTextNode(gettext('Today')));
134
+ var cal_link = document.createElement('a');
135
+ cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
136
+ cal_link.id = DateTimeShortcuts.calendarLinkName + num;
137
+ quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + '../images/icon_calendar.gif', 'alt', gettext('Calendar'));
138
+ shortcuts_span.appendChild(document.createTextNode('\240'));
139
+ shortcuts_span.appendChild(today_link);
140
+ shortcuts_span.appendChild(document.createTextNode('\240|\240'));
141
+ shortcuts_span.appendChild(cal_link);
142
+
143
+ // Create calendarbox div.
144
+ //
145
+ // Markup looks like:
146
+ //
147
+ // <div id="calendarbox3" class="calendarbox module">
148
+ // <h2>
149
+ // <a href="#" class="link-previous">&lsaquo;</a>
150
+ // <a href="#" class="link-next">&rsaquo;</a> February 2003
151
+ // </h2>
152
+ // <div class="calendar" id="calendarin3">
153
+ // <!-- (cal) -->
154
+ // </div>
155
+ // <div class="calendar-shortcuts">
156
+ // <a href="#">Yesterday</a> | <a href="#">Today</a> | <a href="#">Tomorrow</a>
157
+ // </div>
158
+ // <p class="calendar-cancel"><a href="#">Cancel</a></p>
159
+ // </div>
160
+ var cal_box = document.createElement('div');
161
+ cal_box.style.display = 'none';
162
+ cal_box.style.position = 'absolute';
163
+ cal_box.className = 'calendarbox module';
164
+ cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
165
+ document.body.appendChild(cal_box);
166
+ addEvent(cal_box, 'click', DateTimeShortcuts.cancelEventPropagation);
167
+
168
+ // next-prev links
169
+ var cal_nav = quickElement('div', cal_box, '');
170
+ var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');');
171
+ cal_nav_prev.className = 'calendarnav-previous';
172
+ var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
173
+ cal_nav_next.className = 'calendarnav-next';
174
+
175
+ // main box
176
+ var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
177
+ cal_main.className = 'calendar';
178
+ DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
179
+ DateTimeShortcuts.calendars[num].drawCurrent();
180
+
181
+ // calendar shortcuts
182
+ var shortcuts = quickElement('div', cal_box, '');
183
+ shortcuts.className = 'calendar-shortcuts';
184
+ quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
185
+ shortcuts.appendChild(document.createTextNode('\240|\240'));
186
+ quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
187
+ shortcuts.appendChild(document.createTextNode('\240|\240'));
188
+ quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');
189
+
190
+ // cancel bar
191
+ var cancel_p = quickElement('p', cal_box, '');
192
+ cancel_p.className = 'calendar-cancel';
193
+ quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
194
+ },
195
+ openCalendar: function(num) {
196
+ var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
197
+ var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
198
+ var inp = DateTimeShortcuts.calendarInputs[num];
199
+
200
+ // Determine if the current value in the input has a valid date.
201
+ // If so, draw the calendar with that date's year and month.
202
+ if (inp.value) {
203
+ var date_parts = inp.value.split('-');
204
+ var year = date_parts[0];
205
+ var month = parseFloat(date_parts[1]);
206
+ if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) {
207
+ DateTimeShortcuts.calendars[num].drawDate(month, year);
208
+ }
209
+ }
210
+
211
+
212
+ // Recalculate the clockbox position
213
+ // is it left-to-right or right-to-left layout ?
214
+ if (getStyle(document.body,'direction')!='rtl') {
215
+ cal_box.style.left = findPosX(cal_link) + 17 + 'px';
216
+ }
217
+ else {
218
+ // since style's width is in em, it'd be tough to calculate
219
+ // px value of it. let's use an estimated px for now
220
+ // TODO: IE returns wrong value for findPosX when in rtl mode
221
+ // (it returns as it was left aligned), needs to be fixed.
222
+ cal_box.style.left = findPosX(cal_link) - 180 + 'px';
223
+ }
224
+ cal_box.style.top = findPosY(cal_link) - 75 + 'px';
225
+
226
+ cal_box.style.display = 'block';
227
+ addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
228
+ },
229
+ dismissCalendar: function(num) {
230
+ document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none';
231
+ window.document.onclick = null;
232
+ },
233
+ drawPrev: function(num) {
234
+ DateTimeShortcuts.calendars[num].drawPreviousMonth();
235
+ },
236
+ drawNext: function(num) {
237
+ DateTimeShortcuts.calendars[num].drawNextMonth();
238
+ },
239
+ handleCalendarCallback: function(num) {
240
+ return "function(y, m, d) { DateTimeShortcuts.calendarInputs["+num+"].value = y+'-'+(m<10?'0':'')+m+'-'+(d<10?'0':'')+d; document.getElementById(DateTimeShortcuts.calendarDivName1+"+num+").style.display='none';}";
241
+ },
242
+ handleCalendarQuickLink: function(num, offset) {
243
+ var d = new Date();
244
+ d.setDate(d.getDate() + offset)
245
+ DateTimeShortcuts.calendarInputs[num].value = d.getISODate();
246
+ DateTimeShortcuts.dismissCalendar(num);
247
+ },
248
+ cancelEventPropagation: function(e) {
249
+ if (!e) e = window.event;
250
+ e.cancelBubble = true;
251
+ if (e.stopPropagation) e.stopPropagation();
252
+ }
253
+ }
254
+
255
+ addEvent(window, 'load', DateTimeShortcuts.init);