merb-admin 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.markdown +58 -0
- data/Rakefile +64 -0
- data/app/controllers/application.rb +6 -0
- data/app/controllers/main.rb +145 -0
- data/app/helpers/application_helper.rb +64 -0
- data/app/helpers/main_helper.rb +122 -0
- data/app/views/layout/_message.html.erb +10 -0
- data/app/views/layout/dashboard.html.erb +34 -0
- data/app/views/layout/form.html.erb +48 -0
- data/app/views/layout/list.html.erb +42 -0
- data/app/views/main/_belongs_to.html.erb +29 -0
- data/app/views/main/_big_decimal.html.erb +12 -0
- data/app/views/main/_boolean.html.erb +7 -0
- data/app/views/main/_date.html.erb +12 -0
- data/app/views/main/_datetime.html.erb +12 -0
- data/app/views/main/_float.html.erb +12 -0
- data/app/views/main/_has_many.html.erb +16 -0
- data/app/views/main/_has_one.html.erb +30 -0
- data/app/views/main/_integer.html.erb +18 -0
- data/app/views/main/_properties.html.erb +18 -0
- data/app/views/main/_string.html.erb +12 -0
- data/app/views/main/_text.html.erb +11 -0
- data/app/views/main/_time.html.erb +12 -0
- data/app/views/main/_timestamp.html.erb +12 -0
- data/app/views/main/delete.html.erb +12 -0
- data/app/views/main/edit.html.erb +25 -0
- data/app/views/main/index.html.erb +22 -0
- data/app/views/main/list.html.erb +72 -0
- data/app/views/main/new.html.erb +22 -0
- data/lib/abstract_model.rb +67 -0
- data/lib/activerecord_support.rb +169 -0
- data/lib/datamapper_support.rb +157 -0
- data/lib/generic_support.rb +17 -0
- data/lib/merb-admin/merbtasks.rb +103 -0
- data/lib/merb-admin/slicetasks.rb +20 -0
- data/lib/merb-admin/spectasks.rb +53 -0
- data/lib/merb-admin.rb +99 -0
- data/public/images/arrow-down.gif +0 -0
- data/public/images/arrow-up.gif +0 -0
- data/public/images/changelist-bg.gif +0 -0
- data/public/images/changelist-bg_rtl.gif +0 -0
- data/public/images/chooser-bg.gif +0 -0
- data/public/images/chooser_stacked-bg.gif +0 -0
- data/public/images/default-bg-reverse.gif +0 -0
- data/public/images/default-bg.gif +0 -0
- data/public/images/deleted-overlay.gif +0 -0
- data/public/images/icon-no.gif +0 -0
- data/public/images/icon-unknown.gif +0 -0
- data/public/images/icon-yes.gif +0 -0
- data/public/images/icon_addlink.gif +0 -0
- data/public/images/icon_alert.gif +0 -0
- data/public/images/icon_calendar.gif +0 -0
- data/public/images/icon_changelink.gif +0 -0
- data/public/images/icon_clock.gif +0 -0
- data/public/images/icon_deletelink.gif +0 -0
- data/public/images/icon_error.gif +0 -0
- data/public/images/icon_searchbox.png +0 -0
- data/public/images/icon_success.gif +0 -0
- data/public/images/inline-delete-8bit.png +0 -0
- data/public/images/inline-delete.png +0 -0
- data/public/images/inline-restore-8bit.png +0 -0
- data/public/images/inline-restore.png +0 -0
- data/public/images/inline-splitter-bg.gif +0 -0
- data/public/images/nav-bg-grabber.gif +0 -0
- data/public/images/nav-bg-reverse.gif +0 -0
- data/public/images/nav-bg.gif +0 -0
- data/public/images/selector-add.gif +0 -0
- data/public/images/selector-addall.gif +0 -0
- data/public/images/selector-remove.gif +0 -0
- data/public/images/selector-removeall.gif +0 -0
- data/public/images/selector-search.gif +0 -0
- data/public/images/selector_stacked-add.gif +0 -0
- data/public/images/selector_stacked-remove.gif +0 -0
- data/public/images/tool-left.gif +0 -0
- data/public/images/tool-left_over.gif +0 -0
- data/public/images/tool-right.gif +0 -0
- data/public/images/tool-right_over.gif +0 -0
- data/public/images/tooltag-add.gif +0 -0
- data/public/images/tooltag-add_over.gif +0 -0
- data/public/images/tooltag-arrowright.gif +0 -0
- data/public/images/tooltag-arrowright_over.gif +0 -0
- data/public/javascripts/CollapsedFieldsets.js +85 -0
- data/public/javascripts/DateTimeShortcuts.js +255 -0
- data/public/javascripts/RelatedObjectLookups.js +96 -0
- data/public/javascripts/SelectBox.js +111 -0
- data/public/javascripts/SelectFilter2.js +113 -0
- data/public/javascripts/actions.js +39 -0
- data/public/javascripts/calendar.js +143 -0
- data/public/javascripts/core.js +176 -0
- data/public/javascripts/dateparse.js +233 -0
- data/public/javascripts/getElementsBySelector.js +167 -0
- data/public/javascripts/i18n.js +33 -0
- data/public/javascripts/master.js +0 -0
- data/public/javascripts/ordering.js +137 -0
- data/public/javascripts/timeparse.js +94 -0
- data/public/javascripts/urlify.js +140 -0
- data/public/stylesheets/base.css +746 -0
- data/public/stylesheets/changelists.css +269 -0
- data/public/stylesheets/dashboard.css +24 -0
- data/public/stylesheets/forms.css +327 -0
- data/public/stylesheets/global.css +142 -0
- data/public/stylesheets/ie.css +51 -0
- data/public/stylesheets/layout.css +29 -0
- data/public/stylesheets/login.css +54 -0
- data/public/stylesheets/master.css +2 -0
- data/public/stylesheets/null.css +1 -0
- data/public/stylesheets/patch-iewin.css +8 -0
- data/public/stylesheets/rtl.css +206 -0
- data/public/stylesheets/widgets.css +506 -0
- data/schema/migrations/001_create_divisions_migration.rb +15 -0
- data/schema/migrations/002_create_drafts_migration.rb +21 -0
- data/schema/migrations/003_create_leagues_migration.rb +13 -0
- data/schema/migrations/004_create_players_migration.rb +23 -0
- data/schema/migrations/005_create_teams_migration.rb +18 -0
- data/spec/controllers/main_spec.rb +25 -0
- data/spec/models/activerecord/division.rb +8 -0
- data/spec/models/activerecord/draft.rb +16 -0
- data/spec/models/activerecord/league.rb +6 -0
- data/spec/models/activerecord/player.rb +10 -0
- data/spec/models/activerecord/team.rb +11 -0
- data/spec/models/datamapper/division.rb +12 -0
- data/spec/models/datamapper/draft.rb +18 -0
- data/spec/models/datamapper/league.rb +11 -0
- data/spec/models/datamapper/player.rb +21 -0
- data/spec/models/datamapper/team.rb +15 -0
- data/spec/requests/main_spec.rb +475 -0
- data/spec/spec_helper.rb +112 -0
- metadata +209 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
/*
|
2
|
+
calendar.js - Calendar functions by Adrian Holovaty
|
3
|
+
*/
|
4
|
+
|
5
|
+
function removeChildren(a) { // "a" is reference to an object
|
6
|
+
while (a.hasChildNodes()) a.removeChild(a.lastChild);
|
7
|
+
}
|
8
|
+
|
9
|
+
// quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]);
|
10
|
+
function quickElement() {
|
11
|
+
var obj = document.createElement(arguments[0]);
|
12
|
+
if (arguments[2] != '' && arguments[2] != null) {
|
13
|
+
var textNode = document.createTextNode(arguments[2]);
|
14
|
+
obj.appendChild(textNode);
|
15
|
+
}
|
16
|
+
var len = arguments.length;
|
17
|
+
for (var i = 3; i < len; i += 2) {
|
18
|
+
obj.setAttribute(arguments[i], arguments[i+1]);
|
19
|
+
}
|
20
|
+
arguments[1].appendChild(obj);
|
21
|
+
return obj;
|
22
|
+
}
|
23
|
+
|
24
|
+
// CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
|
25
|
+
var CalendarNamespace = {
|
26
|
+
monthsOfYear: gettext('January February March April May June July August September October November December').split(' '),
|
27
|
+
daysOfWeek: gettext('S M T W T F S').split(' '),
|
28
|
+
isLeapYear: function(year) {
|
29
|
+
return (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0));
|
30
|
+
},
|
31
|
+
getDaysInMonth: function(month,year) {
|
32
|
+
var days;
|
33
|
+
if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) {
|
34
|
+
days = 31;
|
35
|
+
}
|
36
|
+
else if (month==4 || month==6 || month==9 || month==11) {
|
37
|
+
days = 30;
|
38
|
+
}
|
39
|
+
else if (month==2 && CalendarNamespace.isLeapYear(year)) {
|
40
|
+
days = 29;
|
41
|
+
}
|
42
|
+
else {
|
43
|
+
days = 28;
|
44
|
+
}
|
45
|
+
return days;
|
46
|
+
},
|
47
|
+
draw: function(month, year, div_id, callback) { // month = 1-12, year = 1-9999
|
48
|
+
month = parseInt(month);
|
49
|
+
year = parseInt(year);
|
50
|
+
var calDiv = document.getElementById(div_id);
|
51
|
+
removeChildren(calDiv);
|
52
|
+
var calTable = document.createElement('table');
|
53
|
+
quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month-1] + ' ' + year);
|
54
|
+
var tableBody = quickElement('tbody', calTable);
|
55
|
+
|
56
|
+
// Draw days-of-week header
|
57
|
+
var tableRow = quickElement('tr', tableBody);
|
58
|
+
for (var i = 0; i < 7; i++) {
|
59
|
+
quickElement('th', tableRow, CalendarNamespace.daysOfWeek[i]);
|
60
|
+
}
|
61
|
+
|
62
|
+
var startingPos = new Date(year, month-1, 1).getDay();
|
63
|
+
var days = CalendarNamespace.getDaysInMonth(month, year);
|
64
|
+
|
65
|
+
// Draw blanks before first of month
|
66
|
+
tableRow = quickElement('tr', tableBody);
|
67
|
+
for (var i = 0; i < startingPos; i++) {
|
68
|
+
var _cell = quickElement('td', tableRow, ' ');
|
69
|
+
_cell.style.backgroundColor = '#f3f3f3';
|
70
|
+
}
|
71
|
+
|
72
|
+
// Draw days of month
|
73
|
+
var currentDay = 1;
|
74
|
+
for (var i = startingPos; currentDay <= days; i++) {
|
75
|
+
if (i%7 == 0 && currentDay != 1) {
|
76
|
+
tableRow = quickElement('tr', tableBody);
|
77
|
+
}
|
78
|
+
var cell = quickElement('td', tableRow, '');
|
79
|
+
quickElement('a', cell, currentDay, 'href', 'javascript:void(' + callback + '('+year+','+month+','+currentDay+'));');
|
80
|
+
currentDay++;
|
81
|
+
}
|
82
|
+
|
83
|
+
// Draw blanks after end of month (optional, but makes for valid code)
|
84
|
+
while (tableRow.childNodes.length < 7) {
|
85
|
+
var _cell = quickElement('td', tableRow, ' ');
|
86
|
+
_cell.style.backgroundColor = '#f3f3f3';
|
87
|
+
}
|
88
|
+
|
89
|
+
calDiv.appendChild(calTable);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
// Calendar -- A calendar instance
|
94
|
+
function Calendar(div_id, callback) {
|
95
|
+
// div_id (string) is the ID of the element in which the calendar will
|
96
|
+
// be displayed
|
97
|
+
// callback (string) is the name of a JavaScript function that will be
|
98
|
+
// called with the parameters (year, month, day) when a day in the
|
99
|
+
// calendar is clicked
|
100
|
+
this.div_id = div_id;
|
101
|
+
this.callback = callback;
|
102
|
+
this.today = new Date();
|
103
|
+
this.currentMonth = this.today.getMonth() + 1;
|
104
|
+
this.currentYear = this.today.getFullYear();
|
105
|
+
}
|
106
|
+
Calendar.prototype = {
|
107
|
+
drawCurrent: function() {
|
108
|
+
CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback);
|
109
|
+
},
|
110
|
+
drawDate: function(month, year) {
|
111
|
+
this.currentMonth = month;
|
112
|
+
this.currentYear = year;
|
113
|
+
this.drawCurrent();
|
114
|
+
},
|
115
|
+
drawPreviousMonth: function() {
|
116
|
+
if (this.currentMonth == 1) {
|
117
|
+
this.currentMonth = 12;
|
118
|
+
this.currentYear--;
|
119
|
+
}
|
120
|
+
else {
|
121
|
+
this.currentMonth--;
|
122
|
+
}
|
123
|
+
this.drawCurrent();
|
124
|
+
},
|
125
|
+
drawNextMonth: function() {
|
126
|
+
if (this.currentMonth == 12) {
|
127
|
+
this.currentMonth = 1;
|
128
|
+
this.currentYear++;
|
129
|
+
}
|
130
|
+
else {
|
131
|
+
this.currentMonth++;
|
132
|
+
}
|
133
|
+
this.drawCurrent();
|
134
|
+
},
|
135
|
+
drawPreviousYear: function() {
|
136
|
+
this.currentYear--;
|
137
|
+
this.drawCurrent();
|
138
|
+
},
|
139
|
+
drawNextYear: function() {
|
140
|
+
this.currentYear++;
|
141
|
+
this.drawCurrent();
|
142
|
+
}
|
143
|
+
}
|
@@ -0,0 +1,176 @@
|
|
1
|
+
// Core javascript helper functions
|
2
|
+
|
3
|
+
// basic browser identification & version
|
4
|
+
var isOpera = (navigator.userAgent.indexOf("Opera")>=0) && parseFloat(navigator.appVersion);
|
5
|
+
var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]);
|
6
|
+
|
7
|
+
// Cross-browser event handlers.
|
8
|
+
function addEvent(obj, evType, fn) {
|
9
|
+
if (obj.addEventListener) {
|
10
|
+
obj.addEventListener(evType, fn, false);
|
11
|
+
return true;
|
12
|
+
} else if (obj.attachEvent) {
|
13
|
+
var r = obj.attachEvent("on" + evType, fn);
|
14
|
+
return r;
|
15
|
+
} else {
|
16
|
+
return false;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
function removeEvent(obj, evType, fn) {
|
21
|
+
if (obj.removeEventListener) {
|
22
|
+
obj.removeEventListener(evType, fn, false);
|
23
|
+
return true;
|
24
|
+
} else if (obj.detachEvent) {
|
25
|
+
obj.detachEvent("on" + evType, fn);
|
26
|
+
return true;
|
27
|
+
} else {
|
28
|
+
return false;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
// quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]);
|
33
|
+
function quickElement() {
|
34
|
+
var obj = document.createElement(arguments[0]);
|
35
|
+
if (arguments[2] != '' && arguments[2] != null) {
|
36
|
+
var textNode = document.createTextNode(arguments[2]);
|
37
|
+
obj.appendChild(textNode);
|
38
|
+
}
|
39
|
+
var len = arguments.length;
|
40
|
+
for (var i = 3; i < len; i += 2) {
|
41
|
+
obj.setAttribute(arguments[i], arguments[i+1]);
|
42
|
+
}
|
43
|
+
arguments[1].appendChild(obj);
|
44
|
+
return obj;
|
45
|
+
}
|
46
|
+
|
47
|
+
// ----------------------------------------------------------------------------
|
48
|
+
// Cross-browser xmlhttp object
|
49
|
+
// from http://jibbering.com/2002/4/httprequest.html
|
50
|
+
// ----------------------------------------------------------------------------
|
51
|
+
var xmlhttp;
|
52
|
+
/*@cc_on @*/
|
53
|
+
/*@if (@_jscript_version >= 5)
|
54
|
+
try {
|
55
|
+
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
|
56
|
+
} catch (e) {
|
57
|
+
try {
|
58
|
+
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
59
|
+
} catch (E) {
|
60
|
+
xmlhttp = false;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
@else
|
64
|
+
xmlhttp = false;
|
65
|
+
@end @*/
|
66
|
+
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
|
67
|
+
xmlhttp = new XMLHttpRequest();
|
68
|
+
}
|
69
|
+
|
70
|
+
// ----------------------------------------------------------------------------
|
71
|
+
// Find-position functions by PPK
|
72
|
+
// See http://www.quirksmode.org/js/findpos.html
|
73
|
+
// ----------------------------------------------------------------------------
|
74
|
+
function findPosX(obj) {
|
75
|
+
var curleft = 0;
|
76
|
+
if (obj.offsetParent) {
|
77
|
+
while (obj.offsetParent) {
|
78
|
+
curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft);
|
79
|
+
obj = obj.offsetParent;
|
80
|
+
}
|
81
|
+
// IE offsetParent does not include the top-level
|
82
|
+
if (isIE && obj.parentElement){
|
83
|
+
curleft += obj.offsetLeft - obj.scrollLeft;
|
84
|
+
}
|
85
|
+
} else if (obj.x) {
|
86
|
+
curleft += obj.x;
|
87
|
+
}
|
88
|
+
return curleft;
|
89
|
+
}
|
90
|
+
|
91
|
+
function findPosY(obj) {
|
92
|
+
var curtop = 0;
|
93
|
+
if (obj.offsetParent) {
|
94
|
+
while (obj.offsetParent) {
|
95
|
+
curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop);
|
96
|
+
obj = obj.offsetParent;
|
97
|
+
}
|
98
|
+
// IE offsetParent does not include the top-level
|
99
|
+
if (isIE && obj.parentElement){
|
100
|
+
curtop += obj.offsetTop - obj.scrollTop;
|
101
|
+
}
|
102
|
+
} else if (obj.y) {
|
103
|
+
curtop += obj.y;
|
104
|
+
}
|
105
|
+
return curtop;
|
106
|
+
}
|
107
|
+
|
108
|
+
//-----------------------------------------------------------------------------
|
109
|
+
// Date object extensions
|
110
|
+
// ----------------------------------------------------------------------------
|
111
|
+
Date.prototype.getCorrectYear = function() {
|
112
|
+
// Date.getYear() is unreliable --
|
113
|
+
// see http://www.quirksmode.org/js/introdate.html#year
|
114
|
+
var y = this.getYear() % 100;
|
115
|
+
return (y < 38) ? y + 2000 : y + 1900;
|
116
|
+
}
|
117
|
+
|
118
|
+
Date.prototype.getTwoDigitMonth = function() {
|
119
|
+
return (this.getMonth() < 9) ? '0' + (this.getMonth()+1) : (this.getMonth()+1);
|
120
|
+
}
|
121
|
+
|
122
|
+
Date.prototype.getTwoDigitDate = function() {
|
123
|
+
return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate();
|
124
|
+
}
|
125
|
+
|
126
|
+
Date.prototype.getTwoDigitHour = function() {
|
127
|
+
return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours();
|
128
|
+
}
|
129
|
+
|
130
|
+
Date.prototype.getTwoDigitMinute = function() {
|
131
|
+
return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes();
|
132
|
+
}
|
133
|
+
|
134
|
+
Date.prototype.getTwoDigitSecond = function() {
|
135
|
+
return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
|
136
|
+
}
|
137
|
+
|
138
|
+
Date.prototype.getISODate = function() {
|
139
|
+
return this.getCorrectYear() + '-' + this.getTwoDigitMonth() + '-' + this.getTwoDigitDate();
|
140
|
+
}
|
141
|
+
|
142
|
+
Date.prototype.getHourMinute = function() {
|
143
|
+
return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute();
|
144
|
+
}
|
145
|
+
|
146
|
+
Date.prototype.getHourMinuteSecond = function() {
|
147
|
+
return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond();
|
148
|
+
}
|
149
|
+
|
150
|
+
// ----------------------------------------------------------------------------
|
151
|
+
// String object extensions
|
152
|
+
// ----------------------------------------------------------------------------
|
153
|
+
String.prototype.pad_left = function(pad_length, pad_string) {
|
154
|
+
var new_string = this;
|
155
|
+
for (var i = 0; new_string.length < pad_length; i++) {
|
156
|
+
new_string = pad_string + new_string;
|
157
|
+
}
|
158
|
+
return new_string;
|
159
|
+
}
|
160
|
+
|
161
|
+
// ----------------------------------------------------------------------------
|
162
|
+
// Get the computed style for and element
|
163
|
+
// ----------------------------------------------------------------------------
|
164
|
+
function getStyle(oElm, strCssRule){
|
165
|
+
var strValue = "";
|
166
|
+
if(document.defaultView && document.defaultView.getComputedStyle){
|
167
|
+
strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
|
168
|
+
}
|
169
|
+
else if(oElm.currentStyle){
|
170
|
+
strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
|
171
|
+
return p1.toUpperCase();
|
172
|
+
});
|
173
|
+
strValue = oElm.currentStyle[strCssRule];
|
174
|
+
}
|
175
|
+
return strValue;
|
176
|
+
}
|
@@ -0,0 +1,233 @@
|
|
1
|
+
/* 'Magic' date parsing, by Simon Willison (6th October 2003)
|
2
|
+
http://simon.incutio.com/archive/2003/10/06/betterDateInput
|
3
|
+
Adapted for 6newslawrence.com, 28th January 2004
|
4
|
+
*/
|
5
|
+
|
6
|
+
/* Finds the index of the first occurence of item in the array, or -1 if not found */
|
7
|
+
if (typeof Array.prototype.indexOf == 'undefined') {
|
8
|
+
Array.prototype.indexOf = function(item) {
|
9
|
+
var len = this.length;
|
10
|
+
for (var i = 0; i < len; i++) {
|
11
|
+
if (this[i] == item) {
|
12
|
+
return i;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
return -1;
|
16
|
+
};
|
17
|
+
}
|
18
|
+
/* Returns an array of items judged 'true' by the passed in test function */
|
19
|
+
if (typeof Array.prototype.filter == 'undefined') {
|
20
|
+
Array.prototype.filter = function(test) {
|
21
|
+
var matches = [];
|
22
|
+
var len = this.length;
|
23
|
+
for (var i = 0; i < len; i++) {
|
24
|
+
if (test(this[i])) {
|
25
|
+
matches[matches.length] = this[i];
|
26
|
+
}
|
27
|
+
}
|
28
|
+
return matches;
|
29
|
+
};
|
30
|
+
}
|
31
|
+
|
32
|
+
var monthNames = gettext("January February March April May June July August September October November December").split(" ");
|
33
|
+
var weekdayNames = gettext("Sunday Monday Tuesday Wednesday Thursday Friday Saturday").split(" ");
|
34
|
+
|
35
|
+
/* Takes a string, returns the index of the month matching that string, throws
|
36
|
+
an error if 0 or more than 1 matches
|
37
|
+
*/
|
38
|
+
function parseMonth(month) {
|
39
|
+
var matches = monthNames.filter(function(item) {
|
40
|
+
return new RegExp("^" + month, "i").test(item);
|
41
|
+
});
|
42
|
+
if (matches.length == 0) {
|
43
|
+
throw new Error("Invalid month string");
|
44
|
+
}
|
45
|
+
if (matches.length > 1) {
|
46
|
+
throw new Error("Ambiguous month");
|
47
|
+
}
|
48
|
+
return monthNames.indexOf(matches[0]);
|
49
|
+
}
|
50
|
+
/* Same as parseMonth but for days of the week */
|
51
|
+
function parseWeekday(weekday) {
|
52
|
+
var matches = weekdayNames.filter(function(item) {
|
53
|
+
return new RegExp("^" + weekday, "i").test(item);
|
54
|
+
});
|
55
|
+
if (matches.length == 0) {
|
56
|
+
throw new Error("Invalid day string");
|
57
|
+
}
|
58
|
+
if (matches.length > 1) {
|
59
|
+
throw new Error("Ambiguous weekday");
|
60
|
+
}
|
61
|
+
return weekdayNames.indexOf(matches[0]);
|
62
|
+
}
|
63
|
+
|
64
|
+
/* Array of objects, each has 're', a regular expression and 'handler', a
|
65
|
+
function for creating a date from something that matches the regular
|
66
|
+
expression. Handlers may throw errors if string is unparseable.
|
67
|
+
*/
|
68
|
+
var dateParsePatterns = [
|
69
|
+
// Today
|
70
|
+
{ re: /^tod/i,
|
71
|
+
handler: function() {
|
72
|
+
return new Date();
|
73
|
+
}
|
74
|
+
},
|
75
|
+
// Tomorrow
|
76
|
+
{ re: /^tom/i,
|
77
|
+
handler: function() {
|
78
|
+
var d = new Date();
|
79
|
+
d.setDate(d.getDate() + 1);
|
80
|
+
return d;
|
81
|
+
}
|
82
|
+
},
|
83
|
+
// Yesterday
|
84
|
+
{ re: /^yes/i,
|
85
|
+
handler: function() {
|
86
|
+
var d = new Date();
|
87
|
+
d.setDate(d.getDate() - 1);
|
88
|
+
return d;
|
89
|
+
}
|
90
|
+
},
|
91
|
+
// 4th
|
92
|
+
{ re: /^(\d{1,2})(st|nd|rd|th)?$/i,
|
93
|
+
handler: function(bits) {
|
94
|
+
var d = new Date();
|
95
|
+
d.setDate(parseInt(bits[1], 10));
|
96
|
+
return d;
|
97
|
+
}
|
98
|
+
},
|
99
|
+
// 4th Jan
|
100
|
+
{ re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+)$/i,
|
101
|
+
handler: function(bits) {
|
102
|
+
var d = new Date();
|
103
|
+
d.setDate(parseInt(bits[1], 10));
|
104
|
+
d.setMonth(parseMonth(bits[2]));
|
105
|
+
return d;
|
106
|
+
}
|
107
|
+
},
|
108
|
+
// 4th Jan 2003
|
109
|
+
{ re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+),? (\d{4})$/i,
|
110
|
+
handler: function(bits) {
|
111
|
+
var d = new Date();
|
112
|
+
d.setDate(parseInt(bits[1], 10));
|
113
|
+
d.setMonth(parseMonth(bits[2]));
|
114
|
+
d.setYear(bits[3]);
|
115
|
+
return d;
|
116
|
+
}
|
117
|
+
},
|
118
|
+
// Jan 4th
|
119
|
+
{ re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?$/i,
|
120
|
+
handler: function(bits) {
|
121
|
+
var d = new Date();
|
122
|
+
d.setDate(parseInt(bits[2], 10));
|
123
|
+
d.setMonth(parseMonth(bits[1]));
|
124
|
+
return d;
|
125
|
+
}
|
126
|
+
},
|
127
|
+
// Jan 4th 2003
|
128
|
+
{ re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?,? (\d{4})$/i,
|
129
|
+
handler: function(bits) {
|
130
|
+
var d = new Date();
|
131
|
+
d.setDate(parseInt(bits[2], 10));
|
132
|
+
d.setMonth(parseMonth(bits[1]));
|
133
|
+
d.setYear(bits[3]);
|
134
|
+
return d;
|
135
|
+
}
|
136
|
+
},
|
137
|
+
// next Tuesday - this is suspect due to weird meaning of "next"
|
138
|
+
{ re: /^next (\w+)$/i,
|
139
|
+
handler: function(bits) {
|
140
|
+
var d = new Date();
|
141
|
+
var day = d.getDay();
|
142
|
+
var newDay = parseWeekday(bits[1]);
|
143
|
+
var addDays = newDay - day;
|
144
|
+
if (newDay <= day) {
|
145
|
+
addDays += 7;
|
146
|
+
}
|
147
|
+
d.setDate(d.getDate() + addDays);
|
148
|
+
return d;
|
149
|
+
}
|
150
|
+
},
|
151
|
+
// last Tuesday
|
152
|
+
{ re: /^last (\w+)$/i,
|
153
|
+
handler: function(bits) {
|
154
|
+
throw new Error("Not yet implemented");
|
155
|
+
}
|
156
|
+
},
|
157
|
+
// mm/dd/yyyy (American style)
|
158
|
+
{ re: /(\d{1,2})\/(\d{1,2})\/(\d{4})/,
|
159
|
+
handler: function(bits) {
|
160
|
+
var d = new Date();
|
161
|
+
d.setYear(bits[3]);
|
162
|
+
d.setDate(parseInt(bits[2], 10));
|
163
|
+
d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0
|
164
|
+
return d;
|
165
|
+
}
|
166
|
+
},
|
167
|
+
// yyyy-mm-dd (ISO style)
|
168
|
+
{ re: /(\d{4})-(\d{1,2})-(\d{1,2})/,
|
169
|
+
handler: function(bits) {
|
170
|
+
var d = new Date();
|
171
|
+
d.setYear(parseInt(bits[1]));
|
172
|
+
d.setMonth(parseInt(bits[2], 10) - 1);
|
173
|
+
d.setDate(parseInt(bits[3], 10));
|
174
|
+
return d;
|
175
|
+
}
|
176
|
+
},
|
177
|
+
];
|
178
|
+
|
179
|
+
function parseDateString(s) {
|
180
|
+
for (var i = 0; i < dateParsePatterns.length; i++) {
|
181
|
+
var re = dateParsePatterns[i].re;
|
182
|
+
var handler = dateParsePatterns[i].handler;
|
183
|
+
var bits = re.exec(s);
|
184
|
+
if (bits) {
|
185
|
+
return handler(bits);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
throw new Error("Invalid date string");
|
189
|
+
}
|
190
|
+
|
191
|
+
function fmt00(x) {
|
192
|
+
// fmt00: Tags leading zero onto numbers 0 - 9.
|
193
|
+
// Particularly useful for displaying results from Date methods.
|
194
|
+
//
|
195
|
+
if (Math.abs(parseInt(x)) < 10){
|
196
|
+
x = "0"+ Math.abs(x);
|
197
|
+
}
|
198
|
+
return x;
|
199
|
+
}
|
200
|
+
|
201
|
+
function parseDateStringISO(s) {
|
202
|
+
try {
|
203
|
+
var d = parseDateString(s);
|
204
|
+
return d.getFullYear() + '-' + (fmt00(d.getMonth() + 1)) + '-' + fmt00(d.getDate())
|
205
|
+
}
|
206
|
+
catch (e) { return s; }
|
207
|
+
}
|
208
|
+
function magicDate(input) {
|
209
|
+
var messagespan = input.id + 'Msg';
|
210
|
+
try {
|
211
|
+
var d = parseDateString(input.value);
|
212
|
+
input.value = d.getFullYear() + '-' + (fmt00(d.getMonth() + 1)) + '-' +
|
213
|
+
fmt00(d.getDate());
|
214
|
+
input.className = '';
|
215
|
+
// Human readable date
|
216
|
+
if (document.getElementById(messagespan)) {
|
217
|
+
document.getElementById(messagespan).firstChild.nodeValue = d.toDateString();
|
218
|
+
document.getElementById(messagespan).className = 'normal';
|
219
|
+
}
|
220
|
+
}
|
221
|
+
catch (e) {
|
222
|
+
input.className = 'error';
|
223
|
+
var message = e.message;
|
224
|
+
// Fix for IE6 bug
|
225
|
+
if (message.indexOf('is null or not an object') > -1) {
|
226
|
+
message = 'Invalid date string';
|
227
|
+
}
|
228
|
+
if (document.getElementById(messagespan)) {
|
229
|
+
document.getElementById(messagespan).firstChild.nodeValue = message;
|
230
|
+
document.getElementById(messagespan).className = 'error';
|
231
|
+
}
|
232
|
+
}
|
233
|
+
}
|