merb-admin 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,167 @@
|
|
|
1
|
+
/* document.getElementsBySelector(selector)
|
|
2
|
+
- returns an array of element objects from the current document
|
|
3
|
+
matching the CSS selector. Selectors can contain element names,
|
|
4
|
+
class names and ids and can be nested. For example:
|
|
5
|
+
|
|
6
|
+
elements = document.getElementsBySelect('div#main p a.external')
|
|
7
|
+
|
|
8
|
+
Will return an array of all 'a' elements with 'external' in their
|
|
9
|
+
class attribute that are contained inside 'p' elements that are
|
|
10
|
+
contained inside the 'div' element which has id="main"
|
|
11
|
+
|
|
12
|
+
New in version 0.4: Support for CSS2 and CSS3 attribute selectors:
|
|
13
|
+
See http://www.w3.org/TR/css3-selectors/#attribute-selectors
|
|
14
|
+
|
|
15
|
+
Version 0.4 - Simon Willison, March 25th 2003
|
|
16
|
+
-- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows
|
|
17
|
+
-- Opera 7 fails
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
function getAllChildren(e) {
|
|
21
|
+
// Returns all children of element. Workaround required for IE5/Windows. Ugh.
|
|
22
|
+
return e.all ? e.all : e.getElementsByTagName('*');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
document.getElementsBySelector = function(selector) {
|
|
26
|
+
// Attempt to fail gracefully in lesser browsers
|
|
27
|
+
if (!document.getElementsByTagName) {
|
|
28
|
+
return new Array();
|
|
29
|
+
}
|
|
30
|
+
// Split selector in to tokens
|
|
31
|
+
var tokens = selector.split(' ');
|
|
32
|
+
var currentContext = new Array(document);
|
|
33
|
+
for (var i = 0; i < tokens.length; i++) {
|
|
34
|
+
token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
|
|
35
|
+
if (token.indexOf('#') > -1) {
|
|
36
|
+
// Token is an ID selector
|
|
37
|
+
var bits = token.split('#');
|
|
38
|
+
var tagName = bits[0];
|
|
39
|
+
var id = bits[1];
|
|
40
|
+
var element = document.getElementById(id);
|
|
41
|
+
if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) {
|
|
42
|
+
// ID not found or tag with that ID not found, return false.
|
|
43
|
+
return new Array();
|
|
44
|
+
}
|
|
45
|
+
// Set currentContext to contain just this element
|
|
46
|
+
currentContext = new Array(element);
|
|
47
|
+
continue; // Skip to next token
|
|
48
|
+
}
|
|
49
|
+
if (token.indexOf('.') > -1) {
|
|
50
|
+
// Token contains a class selector
|
|
51
|
+
var bits = token.split('.');
|
|
52
|
+
var tagName = bits[0];
|
|
53
|
+
var className = bits[1];
|
|
54
|
+
if (!tagName) {
|
|
55
|
+
tagName = '*';
|
|
56
|
+
}
|
|
57
|
+
// Get elements matching tag, filter them for class selector
|
|
58
|
+
var found = new Array;
|
|
59
|
+
var foundCount = 0;
|
|
60
|
+
for (var h = 0; h < currentContext.length; h++) {
|
|
61
|
+
var elements;
|
|
62
|
+
if (tagName == '*') {
|
|
63
|
+
elements = getAllChildren(currentContext[h]);
|
|
64
|
+
} else {
|
|
65
|
+
try {
|
|
66
|
+
elements = currentContext[h].getElementsByTagName(tagName);
|
|
67
|
+
}
|
|
68
|
+
catch(e) {
|
|
69
|
+
elements = [];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (var j = 0; j < elements.length; j++) {
|
|
73
|
+
found[foundCount++] = elements[j];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
currentContext = new Array;
|
|
77
|
+
var currentContextIndex = 0;
|
|
78
|
+
for (var k = 0; k < found.length; k++) {
|
|
79
|
+
if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
|
|
80
|
+
currentContext[currentContextIndex++] = found[k];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
continue; // Skip to next token
|
|
84
|
+
}
|
|
85
|
+
// Code to deal with attribute selectors
|
|
86
|
+
if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
|
|
87
|
+
var tagName = RegExp.$1;
|
|
88
|
+
var attrName = RegExp.$2;
|
|
89
|
+
var attrOperator = RegExp.$3;
|
|
90
|
+
var attrValue = RegExp.$4;
|
|
91
|
+
if (!tagName) {
|
|
92
|
+
tagName = '*';
|
|
93
|
+
}
|
|
94
|
+
// Grab all of the tagName elements within current context
|
|
95
|
+
var found = new Array;
|
|
96
|
+
var foundCount = 0;
|
|
97
|
+
for (var h = 0; h < currentContext.length; h++) {
|
|
98
|
+
var elements;
|
|
99
|
+
if (tagName == '*') {
|
|
100
|
+
elements = getAllChildren(currentContext[h]);
|
|
101
|
+
} else {
|
|
102
|
+
elements = currentContext[h].getElementsByTagName(tagName);
|
|
103
|
+
}
|
|
104
|
+
for (var j = 0; j < elements.length; j++) {
|
|
105
|
+
found[foundCount++] = elements[j];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
currentContext = new Array;
|
|
109
|
+
var currentContextIndex = 0;
|
|
110
|
+
var checkFunction; // This function will be used to filter the elements
|
|
111
|
+
switch (attrOperator) {
|
|
112
|
+
case '=': // Equality
|
|
113
|
+
checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
|
|
114
|
+
break;
|
|
115
|
+
case '~': // Match one of space seperated words
|
|
116
|
+
checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
|
|
117
|
+
break;
|
|
118
|
+
case '|': // Match start with value followed by optional hyphen
|
|
119
|
+
checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
|
|
120
|
+
break;
|
|
121
|
+
case '^': // Match starts with value
|
|
122
|
+
checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
|
|
123
|
+
break;
|
|
124
|
+
case '$': // Match ends with value - fails with "Warning" in Opera 7
|
|
125
|
+
checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
|
|
126
|
+
break;
|
|
127
|
+
case '*': // Match ends with value
|
|
128
|
+
checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
|
|
129
|
+
break;
|
|
130
|
+
default :
|
|
131
|
+
// Just test for existence of attribute
|
|
132
|
+
checkFunction = function(e) { return e.getAttribute(attrName); };
|
|
133
|
+
}
|
|
134
|
+
currentContext = new Array;
|
|
135
|
+
var currentContextIndex = 0;
|
|
136
|
+
for (var k = 0; k < found.length; k++) {
|
|
137
|
+
if (checkFunction(found[k])) {
|
|
138
|
+
currentContext[currentContextIndex++] = found[k];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
|
|
142
|
+
continue; // Skip to next token
|
|
143
|
+
}
|
|
144
|
+
// If we get here, token is JUST an element (not a class or ID selector)
|
|
145
|
+
tagName = token;
|
|
146
|
+
var found = new Array;
|
|
147
|
+
var foundCount = 0;
|
|
148
|
+
for (var h = 0; h < currentContext.length; h++) {
|
|
149
|
+
var elements = currentContext[h].getElementsByTagName(tagName);
|
|
150
|
+
for (var j = 0; j < elements.length; j++) {
|
|
151
|
+
found[foundCount++] = elements[j];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
currentContext = found;
|
|
155
|
+
}
|
|
156
|
+
return currentContext;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* That revolting regular expression explained
|
|
160
|
+
/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
|
|
161
|
+
\---/ \---/\-------------/ \-------/
|
|
162
|
+
| | | |
|
|
163
|
+
| | | The value
|
|
164
|
+
| | ~,|,^,$,* or =
|
|
165
|
+
| Attribute
|
|
166
|
+
Tag
|
|
167
|
+
*/
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* gettext library */
|
|
2
|
+
|
|
3
|
+
var catalog = new Array();
|
|
4
|
+
|
|
5
|
+
function pluralidx(count) { return (count == 1) ? 0 : 1; }
|
|
6
|
+
|
|
7
|
+
function gettext(msgid) {
|
|
8
|
+
var value = catalog[msgid];
|
|
9
|
+
if (typeof(value) == 'undefined') {
|
|
10
|
+
return msgid;
|
|
11
|
+
} else {
|
|
12
|
+
return (typeof(value) == 'string') ? value : value[0];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function ngettext(singular, plural, count) {
|
|
17
|
+
value = catalog[singular];
|
|
18
|
+
if (typeof(value) == 'undefined') {
|
|
19
|
+
return (count == 1) ? singular : plural;
|
|
20
|
+
} else {
|
|
21
|
+
return value[pluralidx(count)];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function gettext_noop(msgid) { return msgid; }
|
|
26
|
+
|
|
27
|
+
function interpolate(fmt, obj, named) {
|
|
28
|
+
if (named) {
|
|
29
|
+
return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])});
|
|
30
|
+
} else {
|
|
31
|
+
return fmt.replace(/%s/g, function(match){return String(obj.shift())});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
addEvent(window, 'load', reorder_init);
|
|
2
|
+
|
|
3
|
+
var lis;
|
|
4
|
+
var top = 0;
|
|
5
|
+
var left = 0;
|
|
6
|
+
var height = 30;
|
|
7
|
+
|
|
8
|
+
function reorder_init() {
|
|
9
|
+
lis = document.getElementsBySelector('ul#orderthese li');
|
|
10
|
+
var input = document.getElementsBySelector('input[name=order_]')[0];
|
|
11
|
+
setOrder(input.value.split(','));
|
|
12
|
+
input.disabled = true;
|
|
13
|
+
draw();
|
|
14
|
+
// Now initialise the dragging behaviour
|
|
15
|
+
var limit = (lis.length - 1) * height;
|
|
16
|
+
for (var i = 0; i < lis.length; i++) {
|
|
17
|
+
var li = lis[i];
|
|
18
|
+
var img = document.getElementById('handle'+li.id);
|
|
19
|
+
li.style.zIndex = 1;
|
|
20
|
+
Drag.init(img, li, left + 10, left + 10, top + 10, top + 10 + limit);
|
|
21
|
+
li.onDragStart = startDrag;
|
|
22
|
+
li.onDragEnd = endDrag;
|
|
23
|
+
img.style.cursor = 'move';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function submitOrderForm() {
|
|
28
|
+
var inputOrder = document.getElementsBySelector('input[name=order_]')[0];
|
|
29
|
+
inputOrder.value = getOrder();
|
|
30
|
+
inputOrder.disabled=false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function startDrag() {
|
|
34
|
+
this.style.zIndex = '10';
|
|
35
|
+
this.className = 'dragging';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function endDrag(x, y) {
|
|
39
|
+
this.style.zIndex = '1';
|
|
40
|
+
this.className = '';
|
|
41
|
+
// Work out how far along it has been dropped, using x co-ordinate
|
|
42
|
+
var oldIndex = this.index;
|
|
43
|
+
var newIndex = Math.round((y - 10 - top) / height);
|
|
44
|
+
// 'Snap' to the correct position
|
|
45
|
+
this.style.top = (10 + top + newIndex * height) + 'px';
|
|
46
|
+
this.index = newIndex;
|
|
47
|
+
moveItem(oldIndex, newIndex);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function moveItem(oldIndex, newIndex) {
|
|
51
|
+
// Swaps two items, adjusts the index and left co-ord for all others
|
|
52
|
+
if (oldIndex == newIndex) {
|
|
53
|
+
return; // Nothing to swap;
|
|
54
|
+
}
|
|
55
|
+
var direction, lo, hi;
|
|
56
|
+
if (newIndex > oldIndex) {
|
|
57
|
+
lo = oldIndex;
|
|
58
|
+
hi = newIndex;
|
|
59
|
+
direction = -1;
|
|
60
|
+
} else {
|
|
61
|
+
direction = 1;
|
|
62
|
+
hi = oldIndex;
|
|
63
|
+
lo = newIndex;
|
|
64
|
+
}
|
|
65
|
+
var lis2 = new Array(); // We will build the new order in this array
|
|
66
|
+
for (var i = 0; i < lis.length; i++) {
|
|
67
|
+
if (i < lo || i > hi) {
|
|
68
|
+
// Position of items not between the indexes is unaffected
|
|
69
|
+
lis2[i] = lis[i];
|
|
70
|
+
continue;
|
|
71
|
+
} else if (i == newIndex) {
|
|
72
|
+
lis2[i] = lis[oldIndex];
|
|
73
|
+
continue;
|
|
74
|
+
} else {
|
|
75
|
+
// Item is between the two indexes - move it along 1
|
|
76
|
+
lis2[i] = lis[i - direction];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Re-index everything
|
|
80
|
+
reIndex(lis2);
|
|
81
|
+
lis = lis2;
|
|
82
|
+
draw();
|
|
83
|
+
// document.getElementById('hiddenOrder').value = getOrder();
|
|
84
|
+
document.getElementsBySelector('input[name=order_]')[0].value = getOrder();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function reIndex(lis) {
|
|
88
|
+
for (var i = 0; i < lis.length; i++) {
|
|
89
|
+
lis[i].index = i;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function draw() {
|
|
94
|
+
for (var i = 0; i < lis.length; i++) {
|
|
95
|
+
var li = lis[i];
|
|
96
|
+
li.index = i;
|
|
97
|
+
li.style.position = 'absolute';
|
|
98
|
+
li.style.left = (10 + left) + 'px';
|
|
99
|
+
li.style.top = (10 + top + (i * height)) + 'px';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function getOrder() {
|
|
104
|
+
var order = new Array(lis.length);
|
|
105
|
+
for (var i = 0; i < lis.length; i++) {
|
|
106
|
+
order[i] = lis[i].id.substring(1, 100);
|
|
107
|
+
}
|
|
108
|
+
return order.join(',');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function setOrder(id_list) {
|
|
112
|
+
/* Set the current order to match the lsit of IDs */
|
|
113
|
+
var temp_lis = new Array();
|
|
114
|
+
for (var i = 0; i < id_list.length; i++) {
|
|
115
|
+
var id = 'p' + id_list[i];
|
|
116
|
+
temp_lis[temp_lis.length] = document.getElementById(id);
|
|
117
|
+
}
|
|
118
|
+
reIndex(temp_lis);
|
|
119
|
+
lis = temp_lis;
|
|
120
|
+
draw();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function addEvent(elm, evType, fn, useCapture)
|
|
124
|
+
// addEvent and removeEvent
|
|
125
|
+
// cross-browser event handling for IE5+, NS6 and Mozilla
|
|
126
|
+
// By Scott Andrew
|
|
127
|
+
{
|
|
128
|
+
if (elm.addEventListener){
|
|
129
|
+
elm.addEventListener(evType, fn, useCapture);
|
|
130
|
+
return true;
|
|
131
|
+
} else if (elm.attachEvent){
|
|
132
|
+
var r = elm.attachEvent("on"+evType, fn);
|
|
133
|
+
return r;
|
|
134
|
+
} else {
|
|
135
|
+
elm['on'+evType] = fn;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
var timeParsePatterns = [
|
|
2
|
+
// 9
|
|
3
|
+
{ re: /^\d{1,2}$/i,
|
|
4
|
+
handler: function(bits) {
|
|
5
|
+
if (bits[0].length == 1) {
|
|
6
|
+
return '0' + bits[0] + ':00';
|
|
7
|
+
} else {
|
|
8
|
+
return bits[0] + ':00';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
// 13:00
|
|
13
|
+
{ re: /^\d{2}[:.]\d{2}$/i,
|
|
14
|
+
handler: function(bits) {
|
|
15
|
+
return bits[0].replace('.', ':');
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
// 9:00
|
|
19
|
+
{ re: /^\d[:.]\d{2}$/i,
|
|
20
|
+
handler: function(bits) {
|
|
21
|
+
return '0' + bits[0].replace('.', ':');
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
// 3 am / 3 a.m. / 3am
|
|
25
|
+
{ re: /^(\d+)\s*([ap])(?:.?m.?)?$/i,
|
|
26
|
+
handler: function(bits) {
|
|
27
|
+
var hour = parseInt(bits[1]);
|
|
28
|
+
if (hour == 12) {
|
|
29
|
+
hour = 0;
|
|
30
|
+
}
|
|
31
|
+
if (bits[2].toLowerCase() == 'p') {
|
|
32
|
+
if (hour == 12) {
|
|
33
|
+
hour = 0;
|
|
34
|
+
}
|
|
35
|
+
return (hour + 12) + ':00';
|
|
36
|
+
} else {
|
|
37
|
+
if (hour < 10) {
|
|
38
|
+
return '0' + hour + ':00';
|
|
39
|
+
} else {
|
|
40
|
+
return hour + ':00';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
// 3.30 am / 3:15 a.m. / 3.00am
|
|
46
|
+
{ re: /^(\d+)[.:](\d{2})\s*([ap]).?m.?$/i,
|
|
47
|
+
handler: function(bits) {
|
|
48
|
+
var hour = parseInt(bits[1]);
|
|
49
|
+
var mins = parseInt(bits[2]);
|
|
50
|
+
if (mins < 10) {
|
|
51
|
+
mins = '0' + mins;
|
|
52
|
+
}
|
|
53
|
+
if (hour == 12) {
|
|
54
|
+
hour = 0;
|
|
55
|
+
}
|
|
56
|
+
if (bits[3].toLowerCase() == 'p') {
|
|
57
|
+
if (hour == 12) {
|
|
58
|
+
hour = 0;
|
|
59
|
+
}
|
|
60
|
+
return (hour + 12) + ':' + mins;
|
|
61
|
+
} else {
|
|
62
|
+
if (hour < 10) {
|
|
63
|
+
return '0' + hour + ':' + mins;
|
|
64
|
+
} else {
|
|
65
|
+
return hour + ':' + mins;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
// noon
|
|
71
|
+
{ re: /^no/i,
|
|
72
|
+
handler: function(bits) {
|
|
73
|
+
return '12:00';
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
// midnight
|
|
77
|
+
{ re: /^mid/i,
|
|
78
|
+
handler: function(bits) {
|
|
79
|
+
return '00:00';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
function parseTimeString(s) {
|
|
85
|
+
for (var i = 0; i < timeParsePatterns.length; i++) {
|
|
86
|
+
var re = timeParsePatterns[i].re;
|
|
87
|
+
var handler = timeParsePatterns[i].handler;
|
|
88
|
+
var bits = re.exec(s);
|
|
89
|
+
if (bits) {
|
|
90
|
+
return handler(bits);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return s;
|
|
94
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
var LATIN_MAP = {
|
|
2
|
+
'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
|
|
3
|
+
'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
|
|
4
|
+
'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
|
|
5
|
+
'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
|
|
6
|
+
'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
|
|
7
|
+
'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
|
|
8
|
+
'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó':
|
|
9
|
+
'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
|
|
10
|
+
'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
|
|
11
|
+
}
|
|
12
|
+
var LATIN_SYMBOLS_MAP = {
|
|
13
|
+
'©':'(c)'
|
|
14
|
+
}
|
|
15
|
+
var GREEK_MAP = {
|
|
16
|
+
'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
|
|
17
|
+
'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
|
|
18
|
+
'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
|
|
19
|
+
'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
|
|
20
|
+
'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
|
|
21
|
+
'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
|
|
22
|
+
'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
|
|
23
|
+
'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
|
|
24
|
+
'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
|
|
25
|
+
'Ϋ':'Y'
|
|
26
|
+
}
|
|
27
|
+
var TURKISH_MAP = {
|
|
28
|
+
'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
|
|
29
|
+
'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
|
|
30
|
+
}
|
|
31
|
+
var RUSSIAN_MAP = {
|
|
32
|
+
'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
|
|
33
|
+
'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
|
|
34
|
+
'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
|
|
35
|
+
'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
|
|
36
|
+
'я':'ya',
|
|
37
|
+
'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
|
|
38
|
+
'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
|
|
39
|
+
'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
|
|
40
|
+
'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
|
|
41
|
+
'Я':'Ya'
|
|
42
|
+
}
|
|
43
|
+
var UKRAINIAN_MAP = {
|
|
44
|
+
'Є':'Ye', 'І':'I', 'Ї':'Yi', 'Ґ':'G', 'є':'ye', 'і':'i', 'ї':'yi', 'ґ':'g'
|
|
45
|
+
}
|
|
46
|
+
var CZECH_MAP = {
|
|
47
|
+
'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u',
|
|
48
|
+
'ž':'z', 'Č':'C', 'Ď':'D', 'Ě':'E', 'Ň': 'N', 'Ř':'R', 'Š':'S', 'Ť':'T',
|
|
49
|
+
'Ů':'U', 'Ž':'Z'
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
var POLISH_MAP = {
|
|
53
|
+
'ą':'a', 'ć':'c', 'ę':'e', 'ł':'l', 'ń':'n', 'ó':'o', 'ś':'s', 'ź':'z',
|
|
54
|
+
'ż':'z', 'Ą':'A', 'Ć':'C', 'Ę':'e', 'Ł':'L', 'Ń':'N', 'Ó':'o', 'Ś':'S',
|
|
55
|
+
'Ź':'Z', 'Ż':'Z'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
var LATVIAN_MAP = {
|
|
59
|
+
'ā':'a', 'č':'c', 'ē':'e', 'ģ':'g', 'ī':'i', 'ķ':'k', 'ļ':'l', 'ņ':'n',
|
|
60
|
+
'š':'s', 'ū':'u', 'ž':'z', 'Ā':'A', 'Č':'C', 'Ē':'E', 'Ģ':'G', 'Ī':'i',
|
|
61
|
+
'Ķ':'k', 'Ļ':'L', 'Ņ':'N', 'Š':'S', 'Ū':'u', 'Ž':'Z'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
var ALL_DOWNCODE_MAPS=new Array()
|
|
65
|
+
ALL_DOWNCODE_MAPS[0]=LATIN_MAP
|
|
66
|
+
ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP
|
|
67
|
+
ALL_DOWNCODE_MAPS[2]=GREEK_MAP
|
|
68
|
+
ALL_DOWNCODE_MAPS[3]=TURKISH_MAP
|
|
69
|
+
ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP
|
|
70
|
+
ALL_DOWNCODE_MAPS[5]=UKRAINIAN_MAP
|
|
71
|
+
ALL_DOWNCODE_MAPS[6]=CZECH_MAP
|
|
72
|
+
ALL_DOWNCODE_MAPS[7]=POLISH_MAP
|
|
73
|
+
ALL_DOWNCODE_MAPS[8]=LATVIAN_MAP
|
|
74
|
+
|
|
75
|
+
var Downcoder = new Object();
|
|
76
|
+
Downcoder.Initialize = function()
|
|
77
|
+
{
|
|
78
|
+
if (Downcoder.map) // already made
|
|
79
|
+
return ;
|
|
80
|
+
Downcoder.map ={}
|
|
81
|
+
Downcoder.chars = '' ;
|
|
82
|
+
for(var i in ALL_DOWNCODE_MAPS)
|
|
83
|
+
{
|
|
84
|
+
var lookup = ALL_DOWNCODE_MAPS[i]
|
|
85
|
+
for (var c in lookup)
|
|
86
|
+
{
|
|
87
|
+
Downcoder.map[c] = lookup[c] ;
|
|
88
|
+
Downcoder.chars += c ;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
Downcoder.regex = new RegExp('[' + Downcoder.chars + ']|[^' + Downcoder.chars + ']+','g') ;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
downcode= function( slug )
|
|
95
|
+
{
|
|
96
|
+
Downcoder.Initialize() ;
|
|
97
|
+
var downcoded =""
|
|
98
|
+
var pieces = slug.match(Downcoder.regex);
|
|
99
|
+
if(pieces)
|
|
100
|
+
{
|
|
101
|
+
for (var i = 0 ; i < pieces.length ; i++)
|
|
102
|
+
{
|
|
103
|
+
if (pieces[i].length == 1)
|
|
104
|
+
{
|
|
105
|
+
var mapped = Downcoder.map[pieces[i]] ;
|
|
106
|
+
if (mapped != null)
|
|
107
|
+
{
|
|
108
|
+
downcoded+=mapped;
|
|
109
|
+
continue ;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
downcoded+=pieces[i];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else
|
|
116
|
+
{
|
|
117
|
+
downcoded = slug;
|
|
118
|
+
}
|
|
119
|
+
return downcoded;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
function URLify(s, num_chars) {
|
|
124
|
+
// changes, e.g., "Petty theft" to "petty_theft"
|
|
125
|
+
// remove all these words from the string before urlifying
|
|
126
|
+
s = downcode(s);
|
|
127
|
+
removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
|
|
128
|
+
"is", "in", "into", "like", "of", "off", "on", "onto", "per",
|
|
129
|
+
"since", "than", "the", "this", "that", "to", "up", "via",
|
|
130
|
+
"with"];
|
|
131
|
+
r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
|
|
132
|
+
s = s.replace(r, '');
|
|
133
|
+
// if downcode doesn't hit, the char will be stripped here
|
|
134
|
+
s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
|
|
135
|
+
s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
|
|
136
|
+
s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
|
|
137
|
+
s = s.toLowerCase(); // convert to lowercase
|
|
138
|
+
return s.substring(0, num_chars);// trim to first num_chars chars
|
|
139
|
+
}
|
|
140
|
+
|