merb-admin 0.8.5 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/Gemfile +21 -23
  2. data/Gemfile.lock +107 -89
  3. data/LICENSE +20 -20
  4. data/README.rdoc +54 -54
  5. data/Rakefile +11 -11
  6. data/app/controllers/application.rb +6 -6
  7. data/app/controllers/main.rb +191 -191
  8. data/app/helpers/application_helper.rb +64 -64
  9. data/app/helpers/main_helper.rb +167 -167
  10. data/app/views/layout/_message.html.erb +10 -10
  11. data/app/views/layout/dashboard.html.erb +34 -34
  12. data/app/views/layout/form.html.erb +48 -48
  13. data/app/views/layout/list.html.erb +42 -42
  14. data/app/views/main/_belongs_to.html.erb +29 -29
  15. data/app/views/main/_big_decimal.html.erb +12 -12
  16. data/app/views/main/_boolean.html.erb +7 -7
  17. data/app/views/main/_date.html.erb +12 -12
  18. data/app/views/main/_datetime.html.erb +12 -12
  19. data/app/views/main/_float.html.erb +12 -12
  20. data/app/views/main/_has_many.html.erb +16 -16
  21. data/app/views/main/_has_one.html.erb +30 -30
  22. data/app/views/main/_integer.html.erb +12 -12
  23. data/app/views/main/_properties.html.erb +18 -18
  24. data/app/views/main/_string.html.erb +15 -15
  25. data/app/views/main/_text.html.erb +11 -11
  26. data/app/views/main/_time.html.erb +12 -12
  27. data/app/views/main/_timestamp.html.erb +12 -12
  28. data/app/views/main/delete.html.erb +28 -28
  29. data/app/views/main/edit.html.erb +19 -19
  30. data/app/views/main/index.html.erb +22 -22
  31. data/app/views/main/list.html.erb +93 -93
  32. data/app/views/main/new.html.erb +16 -16
  33. data/config/init.rb +31 -30
  34. data/config/router.rb +4 -4
  35. data/lib/abstract_model.rb +84 -84
  36. data/lib/active_record_support.rb +151 -147
  37. data/lib/datamapper_support.rb +145 -141
  38. data/lib/generic_support.rb +13 -13
  39. data/lib/merb-admin.rb +100 -100
  40. data/lib/merb-admin/merbtasks.rb +103 -103
  41. data/lib/merb-admin/slicetasks.rb +168 -174
  42. data/lib/merb-admin/spectasks.rb +55 -55
  43. data/lib/merb-admin/version.rb +3 -3
  44. data/lib/sequel_support.rb +282 -275
  45. data/merb-admin.gemspec +42 -41
  46. data/public/javascripts/CollapsedFieldsets.js +85 -85
  47. data/public/javascripts/DateTimeShortcuts.js +255 -255
  48. data/public/javascripts/RelatedObjectLookups.js +96 -96
  49. data/public/javascripts/SelectBox.js +111 -111
  50. data/public/javascripts/SelectFilter2.js +113 -113
  51. data/public/javascripts/actions.js +39 -39
  52. data/public/javascripts/calendar.js +143 -143
  53. data/public/javascripts/core.js +176 -176
  54. data/public/javascripts/dateparse.js +233 -233
  55. data/public/javascripts/getElementsBySelector.js +167 -167
  56. data/public/javascripts/i18n.js +33 -33
  57. data/public/javascripts/ordering.js +137 -137
  58. data/public/javascripts/timeparse.js +94 -94
  59. data/public/javascripts/urlify.js +140 -140
  60. data/public/stylesheets/base.css +746 -746
  61. data/public/stylesheets/changelists.css +269 -269
  62. data/public/stylesheets/dashboard.css +24 -24
  63. data/public/stylesheets/forms.css +327 -327
  64. data/public/stylesheets/global.css +142 -142
  65. data/public/stylesheets/ie.css +50 -50
  66. data/public/stylesheets/layout.css +29 -29
  67. data/public/stylesheets/login.css +54 -54
  68. data/public/stylesheets/master.css +1 -1
  69. data/public/stylesheets/patch-iewin.css +7 -7
  70. data/public/stylesheets/rtl.css +206 -206
  71. data/public/stylesheets/widgets.css +506 -506
  72. data/spec/controllers/main_spec.rb +25 -25
  73. data/spec/migrations/activerecord/001_create_divisions_migration.rb +13 -13
  74. data/spec/migrations/activerecord/002_create_drafts_migration.rb +19 -19
  75. data/spec/migrations/activerecord/003_create_leagues_migration.rb +12 -12
  76. data/spec/migrations/activerecord/004_create_players_migration.rb +19 -19
  77. data/spec/migrations/activerecord/005_create_teams_migration.rb +22 -22
  78. data/spec/migrations/sequel/001_create_divisions_migration.rb +15 -15
  79. data/spec/migrations/sequel/002_create_drafts_migration.rb +21 -21
  80. data/spec/migrations/sequel/003_create_leagues_migration.rb +14 -14
  81. data/spec/migrations/sequel/004_create_players_migration.rb +21 -21
  82. data/spec/migrations/sequel/005_create_teams_migration.rb +24 -24
  83. data/spec/models/activerecord/division.rb +7 -7
  84. data/spec/models/activerecord/draft.rb +11 -11
  85. data/spec/models/activerecord/league.rb +6 -6
  86. data/spec/models/activerecord/player.rb +8 -8
  87. data/spec/models/activerecord/team.rb +13 -13
  88. data/spec/models/datamapper/division.rb +12 -12
  89. data/spec/models/datamapper/draft.rb +18 -18
  90. data/spec/models/datamapper/league.rb +11 -11
  91. data/spec/models/datamapper/player.rb +20 -20
  92. data/spec/models/datamapper/team.rb +22 -22
  93. data/spec/models/sequel/division.rb +15 -15
  94. data/spec/models/sequel/draft.rb +19 -19
  95. data/spec/models/sequel/league.rb +14 -14
  96. data/spec/models/sequel/player.rb +18 -18
  97. data/spec/models/sequel/team.rb +21 -21
  98. data/spec/requests/main_spec.rb +873 -763
  99. data/spec/spec_helper.rb +111 -113
  100. metadata +40 -26
@@ -1,41 +1,42 @@
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", ["~> 1.0"])
7
- s.add_development_dependency("dm-aggregates", ["~> 1.0"])
8
- s.add_development_dependency("dm-types", ["~> 1.0"])
9
- s.add_development_dependency("dm-migrations", ["~> 1.0"])
10
- s.add_development_dependency("dm-sqlite-adapter", ["~> 1.0"])
11
- s.add_development_dependency("dm-validations", ["~> 1.0"])
12
- s.add_development_dependency("rspec", ["~> 1.3"])
13
- s.add_development_dependency("sequel", ["~> 3.6.0"])
14
- s.add_development_dependency("sqlite3-ruby", ["~> 1.3"])
15
- s.add_development_dependency("webrat", ["~> 0.7"])
16
- s.add_runtime_dependency("builder", ["~> 2.1"])
17
- s.add_runtime_dependency("json", ["~> 1.4"])
18
- s.add_runtime_dependency("merb-assets", ["~> 1.1"])
19
- s.add_runtime_dependency("merb-helpers", ["~> 1.1"])
20
- s.add_runtime_dependency("merb-slices", ["~> 1.1"])
21
- s.authors = ["Erik Michaels-Ober"]
22
- s.description = %q{MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data}
23
- s.email = "sferik@gmail.com"
24
- s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
25
- s.files = `git ls-files`.split("\n")
26
- s.homepage = "http://rubygems.org/gems/merb-admin"
27
- s.name = "merb-admin"
28
- s.post_install_message =<<eos
29
- ********************************************************************************
30
- Make sure to add authorization logic before deploying to production!
31
- WARNING: MerbAdmin does not implement any authorization scheme.
32
- ********************************************************************************
33
- eos
34
- s.rdoc_options = ["--charset=UTF-8"]
35
- s.require_paths = ["lib"]
36
- s.required_rubygems_version = ">= 1.3.6"
37
- s.rubyforge_project = "merb-admin"
38
- s.summary = %q{MerbAdmin is a Merb plugin that provides an easy-to-use interface for managing your data}
39
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
40
- s.version = MerbAdmin::VERSION
41
- end
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", ["~> 1.0"])
7
+ s.add_development_dependency("dm-aggregates", ["~> 1.0"])
8
+ s.add_development_dependency("dm-types", ["~> 1.0"])
9
+ s.add_development_dependency("dm-migrations", ["~> 1.0"])
10
+ s.add_development_dependency("dm-sqlite-adapter", ["~> 1.0"])
11
+ s.add_development_dependency("dm-validations", ["~> 1.0"])
12
+ s.add_development_dependency("thin", ["~> 1.2"])
13
+ s.add_development_dependency("rspec", ["~> 1.3"])
14
+ s.add_development_dependency("sequel", ["~> 3.16"])
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 = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version=
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);