merb-admin 0.8.1 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.gitignore +29 -27
  2. data/Gemfile +24 -22
  3. data/Gemfile.lock +86 -0
  4. data/LICENSE +20 -20
  5. data/README.rdoc +54 -58
  6. data/Rakefile +11 -44
  7. data/app/controllers/application.rb +6 -6
  8. data/app/controllers/main.rb +191 -191
  9. data/app/helpers/application_helper.rb +64 -64
  10. data/app/helpers/main_helper.rb +167 -167
  11. data/app/models/.gitkeep +0 -0
  12. data/app/views/layout/_message.html.erb +10 -10
  13. data/app/views/layout/dashboard.html.erb +34 -34
  14. data/app/views/layout/form.html.erb +48 -48
  15. data/app/views/layout/list.html.erb +42 -42
  16. data/app/views/main/_belongs_to.html.erb +29 -29
  17. data/app/views/main/_big_decimal.html.erb +12 -12
  18. data/app/views/main/_boolean.html.erb +7 -7
  19. data/app/views/main/_date.html.erb +12 -12
  20. data/app/views/main/_datetime.html.erb +12 -12
  21. data/app/views/main/_float.html.erb +12 -12
  22. data/app/views/main/_has_many.html.erb +16 -16
  23. data/app/views/main/_has_one.html.erb +30 -30
  24. data/app/views/main/_integer.html.erb +12 -12
  25. data/app/views/main/_properties.html.erb +18 -18
  26. data/app/views/main/_string.html.erb +15 -15
  27. data/app/views/main/_text.html.erb +11 -11
  28. data/app/views/main/_time.html.erb +12 -12
  29. data/app/views/main/_timestamp.html.erb +12 -12
  30. data/app/views/main/delete.html.erb +28 -28
  31. data/app/views/main/edit.html.erb +19 -19
  32. data/app/views/main/index.html.erb +22 -22
  33. data/app/views/main/list.html.erb +93 -93
  34. data/app/views/main/new.html.erb +16 -16
  35. data/config/init.rb +30 -0
  36. data/config/router.rb +4 -0
  37. data/lib/abstract_model.rb +84 -86
  38. data/lib/active_record_support.rb +147 -147
  39. data/lib/datamapper_support.rb +139 -140
  40. data/lib/generic_support.rb +13 -13
  41. data/lib/merb-admin.rb +99 -99
  42. data/lib/merb-admin/merbtasks.rb +103 -103
  43. data/lib/merb-admin/slicetasks.rb +174 -174
  44. data/lib/merb-admin/spectasks.rb +55 -55
  45. data/lib/merb-admin/version.rb +3 -0
  46. data/lib/sequel_support.rb +275 -275
  47. data/merb-admin.gemspec +42 -232
  48. data/public/javascripts/CollapsedFieldsets.js +85 -85
  49. data/public/javascripts/DateTimeShortcuts.js +255 -255
  50. data/public/javascripts/RelatedObjectLookups.js +96 -96
  51. data/public/javascripts/SelectBox.js +111 -111
  52. data/public/javascripts/SelectFilter2.js +113 -113
  53. data/public/javascripts/actions.js +39 -39
  54. data/public/javascripts/calendar.js +143 -143
  55. data/public/javascripts/core.js +176 -176
  56. data/public/javascripts/dateparse.js +233 -233
  57. data/public/javascripts/getElementsBySelector.js +167 -167
  58. data/public/javascripts/i18n.js +33 -33
  59. data/public/javascripts/ordering.js +137 -137
  60. data/public/javascripts/timeparse.js +94 -94
  61. data/public/javascripts/urlify.js +140 -140
  62. data/public/stylesheets/base.css +746 -746
  63. data/public/stylesheets/changelists.css +269 -269
  64. data/public/stylesheets/dashboard.css +24 -24
  65. data/public/stylesheets/forms.css +327 -327
  66. data/public/stylesheets/global.css +142 -142
  67. data/public/stylesheets/ie.css +50 -50
  68. data/public/stylesheets/layout.css +29 -29
  69. data/public/stylesheets/login.css +54 -54
  70. data/public/stylesheets/master.css +1 -1
  71. data/public/stylesheets/patch-iewin.css +7 -7
  72. data/public/stylesheets/rtl.css +206 -206
  73. data/public/stylesheets/widgets.css +506 -506
  74. data/screenshots/create.png +0 -0
  75. data/screenshots/delete.png +0 -0
  76. data/screenshots/edit.png +0 -0
  77. data/screenshots/index.png +0 -0
  78. data/screenshots/list.png +0 -0
  79. data/screenshots/new.png +0 -0
  80. data/spec/controllers/main_spec.rb +25 -25
  81. data/spec/migrations/activerecord/001_create_divisions_migration.rb +13 -13
  82. data/spec/migrations/activerecord/002_create_drafts_migration.rb +19 -19
  83. data/spec/migrations/activerecord/003_create_leagues_migration.rb +12 -12
  84. data/spec/migrations/activerecord/004_create_players_migration.rb +19 -20
  85. data/spec/migrations/activerecord/005_create_teams_migration.rb +22 -22
  86. data/spec/migrations/sequel/001_create_divisions_migration.rb +15 -15
  87. data/spec/migrations/sequel/002_create_drafts_migration.rb +21 -21
  88. data/spec/migrations/sequel/003_create_leagues_migration.rb +14 -14
  89. data/spec/migrations/sequel/004_create_players_migration.rb +21 -22
  90. data/spec/migrations/sequel/005_create_teams_migration.rb +24 -24
  91. data/spec/models/activerecord/division.rb +7 -7
  92. data/spec/models/activerecord/draft.rb +11 -11
  93. data/spec/models/activerecord/league.rb +6 -6
  94. data/spec/models/activerecord/player.rb +8 -8
  95. data/spec/models/activerecord/team.rb +13 -13
  96. data/spec/models/datamapper/division.rb +12 -12
  97. data/spec/models/datamapper/draft.rb +18 -18
  98. data/spec/models/datamapper/league.rb +11 -11
  99. data/spec/models/datamapper/player.rb +20 -21
  100. data/spec/models/datamapper/team.rb +22 -22
  101. data/spec/models/sequel/division.rb +15 -15
  102. data/spec/models/sequel/draft.rb +19 -19
  103. data/spec/models/sequel/league.rb +14 -14
  104. data/spec/models/sequel/player.rb +18 -18
  105. data/spec/models/sequel/team.rb +21 -21
  106. data/spec/requests/main_spec.rb +763 -763
  107. data/spec/spec_helper.rb +113 -112
  108. metadata +247 -41
  109. data/VERSION +0 -1
@@ -1,94 +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
- }
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
+ }
@@ -1,140 +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
-
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
+