spud_core 0.8.28 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/app/assets/javascripts/spud/admin/application.js +80 -39
  2. data/app/assets/javascripts/spud/admin/editor.js +91 -0
  3. data/app/assets/libs/bootstrap/css/bootstrap-responsive.css +799 -397
  4. data/app/assets/libs/bootstrap/css/bootstrap.css +3275 -1372
  5. data/app/assets/libs/bootstrap/img/glyphicons-halflings-white.png +0 -0
  6. data/app/assets/libs/bootstrap/img/glyphicons-halflings.png +0 -0
  7. data/app/assets/libs/bootstrap/js/bootstrap.js +716 -417
  8. data/app/assets/libs/datepicker/css/datepicker.css +223 -0
  9. data/app/assets/libs/datepicker/js/bootstrap-datepicker.js +779 -0
  10. data/app/assets/libs/datepicker/less/datepicker.less +122 -0
  11. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  12. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  13. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_flat_55_ffffff_40x100.png +0 -0
  14. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  15. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  16. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
  17. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
  18. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
  19. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_0073ea_256x240.png +0 -0
  20. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_454545_256x240.png +0 -0
  21. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_666666_256x240.png +0 -0
  22. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_ff0084_256x240.png +0 -0
  23. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_ffffff_256x240.png +0 -0
  24. data/app/assets/libs/jquery-ui/css/flick/jquery-ui-1.9.1.custom.css +297 -0
  25. data/app/assets/libs/jquery-ui/css/flick/jquery-ui-1.9.1.custom.min.css +5 -0
  26. data/app/assets/libs/jquery-ui/js/jquery-ui-1.9.1.custom.js +4870 -0
  27. data/app/assets/libs/jquery-ui/js/jquery-ui-1.9.1.custom.min.js +6 -0
  28. data/app/assets/stylesheets/spud/admin/application.css +22 -4
  29. data/app/controllers/spud/admin/application_controller.rb +13 -4
  30. data/app/controllers/spud/admin/dashboard_controller.rb +1 -1
  31. data/app/controllers/spud/admin/users_controller.rb +4 -9
  32. data/app/controllers/spud/setup_controller.rb +3 -4
  33. data/app/models/spud_admin_permission.rb +1 -1
  34. data/app/models/spud_user.rb +4 -2
  35. data/app/views/layouts/spud/admin/application.html.erb +24 -5
  36. data/app/views/spud/admin/users/_edit.html.erb +2 -4
  37. data/app/views/spud/admin/users/_new.html.erb +3 -5
  38. data/app/views/spud/admin/users/index.html.erb +6 -5
  39. data/lib/spud_core/belongs_to_app.rb +9 -6
  40. data/lib/spud_core/configuration.rb +23 -1
  41. data/lib/spud_core/engine.rb +20 -28
  42. data/lib/spud_core/version.rb +1 -1
  43. data/spec/dummy/log/development.log +15 -37
  44. data/spec/dummy/log/test.log +72841 -25918
  45. metadata +25 -101
  46. data/app/assets/libs/bootstrap/css/bootstrap-responsive.min.css +0 -12
  47. data/app/assets/libs/bootstrap/css/bootstrap.min.css +0 -689
  48. data/app/assets/libs/bootstrap/js/bootstrap.min.js +0 -6
  49. data/app/assets/libs/tiny_mce/plugins/autosave/editor_plugin.js +0 -1
  50. data/app/assets/libs/tiny_mce/plugins/autosave/editor_plugin_src.js +0 -431
  51. data/app/assets/libs/tiny_mce/plugins/autosave/langs/en.js +0 -4
  52. data/app/assets/libs/tiny_mce/plugins/bbcode/editor_plugin.js +0 -1
  53. data/app/assets/libs/tiny_mce/plugins/bbcode/editor_plugin_src.js +0 -120
  54. data/app/assets/libs/tiny_mce/plugins/emotions/editor_plugin.js +0 -1
  55. data/app/assets/libs/tiny_mce/plugins/emotions/editor_plugin_src.js +0 -43
  56. data/app/assets/libs/tiny_mce/plugins/emotions/emotions.htm +0 -42
  57. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-cool.gif +0 -0
  58. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-cry.gif +0 -0
  59. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-embarassed.gif +0 -0
  60. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif +0 -0
  61. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-frown.gif +0 -0
  62. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-innocent.gif +0 -0
  63. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-kiss.gif +0 -0
  64. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-laughing.gif +0 -0
  65. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif +0 -0
  66. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-sealed.gif +0 -0
  67. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-smile.gif +0 -0
  68. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-surprised.gif +0 -0
  69. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif +0 -0
  70. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-undecided.gif +0 -0
  71. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-wink.gif +0 -0
  72. data/app/assets/libs/tiny_mce/plugins/emotions/img/smiley-yell.gif +0 -0
  73. data/app/assets/libs/tiny_mce/plugins/emotions/js/emotions.js +0 -43
  74. data/app/assets/libs/tiny_mce/plugins/emotions/langs/en_dlg.js +0 -1
  75. data/app/assets/libs/tiny_mce/plugins/fullpage/css/fullpage.css +0 -143
  76. data/app/assets/libs/tiny_mce/plugins/fullpage/editor_plugin.js +0 -1
  77. data/app/assets/libs/tiny_mce/plugins/fullpage/editor_plugin_src.js +0 -405
  78. data/app/assets/libs/tiny_mce/plugins/fullpage/fullpage.htm +0 -259
  79. data/app/assets/libs/tiny_mce/plugins/fullpage/js/fullpage.js +0 -232
  80. data/app/assets/libs/tiny_mce/plugins/fullpage/langs/en_dlg.js +0 -1
  81. data/app/assets/libs/tiny_mce/plugins/fullscreen/editor_plugin.js +0 -1
  82. data/app/assets/libs/tiny_mce/plugins/fullscreen/editor_plugin_src.js +0 -159
  83. data/app/assets/libs/tiny_mce/plugins/fullscreen/fullscreen.htm +0 -110
  84. data/app/assets/libs/tiny_mce/plugins/insertdatetime/editor_plugin.js +0 -1
  85. data/app/assets/libs/tiny_mce/plugins/insertdatetime/editor_plugin_src.js +0 -83
  86. data/app/assets/libs/tiny_mce/plugins/legacyoutput/editor_plugin.js +0 -1
  87. data/app/assets/libs/tiny_mce/plugins/legacyoutput/editor_plugin_src.js +0 -139
  88. data/app/assets/libs/tiny_mce/plugins/nonbreaking/editor_plugin.js +0 -1
  89. data/app/assets/libs/tiny_mce/plugins/nonbreaking/editor_plugin_src.js +0 -54
  90. data/app/assets/libs/tiny_mce/plugins/noneditable/editor_plugin.js +0 -1
  91. data/app/assets/libs/tiny_mce/plugins/noneditable/editor_plugin_src.js +0 -454
  92. data/app/assets/libs/tiny_mce/plugins/pagebreak/editor_plugin.js +0 -1
  93. data/app/assets/libs/tiny_mce/plugins/pagebreak/editor_plugin_src.js +0 -74
  94. data/app/assets/libs/tiny_mce/plugins/preview/editor_plugin.js +0 -1
  95. data/app/assets/libs/tiny_mce/plugins/preview/editor_plugin_src.js +0 -53
  96. data/app/assets/libs/tiny_mce/plugins/preview/example.html +0 -28
  97. data/app/assets/libs/tiny_mce/plugins/preview/jscripts/embed.js +0 -73
  98. data/app/assets/libs/tiny_mce/plugins/preview/preview.html +0 -17
  99. data/app/assets/libs/tiny_mce/plugins/print/editor_plugin.js +0 -1
  100. data/app/assets/libs/tiny_mce/plugins/print/editor_plugin_src.js +0 -34
  101. data/app/assets/libs/tiny_mce/plugins/save/editor_plugin.js +0 -1
  102. data/app/assets/libs/tiny_mce/plugins/save/editor_plugin_src.js +0 -101
  103. data/app/assets/libs/tiny_mce/plugins/searchreplace/css/searchreplace.css +0 -6
  104. data/app/assets/libs/tiny_mce/plugins/searchreplace/editor_plugin.js +0 -1
  105. data/app/assets/libs/tiny_mce/plugins/searchreplace/editor_plugin_src.js +0 -61
  106. data/app/assets/libs/tiny_mce/plugins/searchreplace/js/searchreplace.js +0 -142
  107. data/app/assets/libs/tiny_mce/plugins/searchreplace/langs/en_dlg.js +0 -1
  108. data/app/assets/libs/tiny_mce/plugins/searchreplace/searchreplace.htm +0 -100
  109. data/app/assets/libs/tiny_mce/plugins/tabfocus/editor_plugin.js +0 -1
  110. data/app/assets/libs/tiny_mce/plugins/tabfocus/editor_plugin_src.js +0 -122
  111. data/app/assets/libs/tiny_mce/plugins/template/blank.htm +0 -12
  112. data/app/assets/libs/tiny_mce/plugins/template/css/template.css +0 -23
  113. data/app/assets/libs/tiny_mce/plugins/template/editor_plugin.js +0 -1
  114. data/app/assets/libs/tiny_mce/plugins/template/editor_plugin_src.js +0 -159
  115. data/app/assets/libs/tiny_mce/plugins/template/js/template.js +0 -106
  116. data/app/assets/libs/tiny_mce/plugins/template/langs/en_dlg.js +0 -1
  117. data/app/assets/libs/tiny_mce/plugins/template/template.htm +0 -31
  118. data/app/assets/libs/tiny_mce/plugins/visualblocks/css/visualblocks.css +0 -21
  119. data/app/assets/libs/tiny_mce/plugins/visualblocks/editor_plugin.js +0 -1
  120. data/app/assets/libs/tiny_mce/plugins/visualblocks/editor_plugin_src.js +0 -63
  121. data/app/assets/libs/tiny_mce/plugins/visualchars/editor_plugin.js +0 -1
  122. data/app/assets/libs/tiny_mce/plugins/visualchars/editor_plugin_src.js +0 -83
  123. data/app/assets/libs/tiny_mce/plugins/wordcount/editor_plugin.js +0 -1
  124. data/app/assets/libs/tiny_mce/plugins/wordcount/editor_plugin_src.js +0 -122
  125. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/abbr.htm +0 -142
  126. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/acronym.htm +0 -142
  127. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/attributes.htm +0 -149
  128. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/cite.htm +0 -142
  129. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/css/attributes.css +0 -11
  130. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/css/popup.css +0 -9
  131. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/del.htm +0 -162
  132. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/editor_plugin.js +0 -1
  133. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js +0 -132
  134. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/ins.htm +0 -162
  135. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/js/abbr.js +0 -28
  136. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/js/acronym.js +0 -28
  137. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/js/attributes.js +0 -111
  138. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/js/cite.js +0 -28
  139. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/js/del.js +0 -53
  140. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/js/element_common.js +0 -229
  141. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/js/ins.js +0 -53
  142. data/app/assets/libs/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js +0 -1
@@ -0,0 +1,223 @@
1
+ /*!
2
+ * Datepicker for Bootstrap
3
+ *
4
+ * Copyright 2012 Stefan Petre
5
+ * Improvements by Andrew Rowls
6
+ * Licensed under the Apache License v2.0
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ */
10
+ .datepicker {
11
+ top: 0;
12
+ left: 0;
13
+ padding: 4px;
14
+ margin-top: 1px;
15
+ -webkit-border-radius: 4px;
16
+ -moz-border-radius: 4px;
17
+ border-radius: 4px;
18
+ /*.dow {
19
+ border-top: 1px solid #ddd !important;
20
+ }*/
21
+
22
+ }
23
+ .datepicker:before {
24
+ content: '';
25
+ display: inline-block;
26
+ border-left: 7px solid transparent;
27
+ border-right: 7px solid transparent;
28
+ border-bottom: 7px solid #ccc;
29
+ border-bottom-color: rgba(0, 0, 0, 0.2);
30
+ position: absolute;
31
+ top: -7px;
32
+ left: 6px;
33
+ }
34
+ .datepicker:after {
35
+ content: '';
36
+ display: inline-block;
37
+ border-left: 6px solid transparent;
38
+ border-right: 6px solid transparent;
39
+ border-bottom: 6px solid #ffffff;
40
+ position: absolute;
41
+ top: -6px;
42
+ left: 7px;
43
+ }
44
+ .datepicker > div {
45
+ display: none;
46
+ }
47
+ .datepicker.days div.datepicker-days {
48
+ display: block;
49
+ }
50
+ .datepicker.months div.datepicker-months {
51
+ display: block;
52
+ }
53
+ .datepicker.years div.datepicker-years {
54
+ display: block;
55
+ }
56
+ .datepicker table {
57
+ margin: 0;
58
+ }
59
+ .datepicker td,
60
+ .datepicker th {
61
+ text-align: center;
62
+ width: 20px;
63
+ height: 20px;
64
+ -webkit-border-radius: 4px;
65
+ -moz-border-radius: 4px;
66
+ border-radius: 4px;
67
+ }
68
+ .datepicker td.day:hover {
69
+ background: #eeeeee;
70
+ cursor: pointer;
71
+ }
72
+ .datepicker td.old,
73
+ .datepicker td.new {
74
+ color: #999999;
75
+ }
76
+ .datepicker td.disabled,
77
+ .datepicker td.disabled:hover {
78
+ background: none;
79
+ color: #999999;
80
+ cursor: default;
81
+ }
82
+ .datepicker td.active,
83
+ .datepicker td.active:hover,
84
+ .datepicker td.active.disabled,
85
+ .datepicker td.active.disabled:hover {
86
+ background-color: #006dcc;
87
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
88
+ background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
89
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
90
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
91
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
92
+ background-image: linear-gradient(top, #0088cc, #0044cc);
93
+ background-repeat: repeat-x;
94
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
95
+ border-color: #0044cc #0044cc #002a80;
96
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
97
+ filter: progid:dximagetransform.microsoft.gradient(enabled=false);
98
+ color: #fff;
99
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
100
+ }
101
+ .datepicker td.active:hover,
102
+ .datepicker td.active:hover:hover,
103
+ .datepicker td.active.disabled:hover,
104
+ .datepicker td.active.disabled:hover:hover,
105
+ .datepicker td.active:active,
106
+ .datepicker td.active:hover:active,
107
+ .datepicker td.active.disabled:active,
108
+ .datepicker td.active.disabled:hover:active,
109
+ .datepicker td.active.active,
110
+ .datepicker td.active:hover.active,
111
+ .datepicker td.active.disabled.active,
112
+ .datepicker td.active.disabled:hover.active,
113
+ .datepicker td.active.disabled,
114
+ .datepicker td.active:hover.disabled,
115
+ .datepicker td.active.disabled.disabled,
116
+ .datepicker td.active.disabled:hover.disabled,
117
+ .datepicker td.active[disabled],
118
+ .datepicker td.active:hover[disabled],
119
+ .datepicker td.active.disabled[disabled],
120
+ .datepicker td.active.disabled:hover[disabled] {
121
+ background-color: #0044cc;
122
+ }
123
+ .datepicker td.active:active,
124
+ .datepicker td.active:hover:active,
125
+ .datepicker td.active.disabled:active,
126
+ .datepicker td.active.disabled:hover:active,
127
+ .datepicker td.active.active,
128
+ .datepicker td.active:hover.active,
129
+ .datepicker td.active.disabled.active,
130
+ .datepicker td.active.disabled:hover.active {
131
+ background-color: #003399 \9;
132
+ }
133
+ .datepicker td span {
134
+ display: block;
135
+ width: 23%;
136
+ height: 54px;
137
+ line-height: 54px;
138
+ float: left;
139
+ margin: 1%;
140
+ cursor: pointer;
141
+ -webkit-border-radius: 4px;
142
+ -moz-border-radius: 4px;
143
+ border-radius: 4px;
144
+ }
145
+ .datepicker td span:hover {
146
+ background: #eeeeee;
147
+ }
148
+ .datepicker td span.disabled,
149
+ .datepicker td span.disabled:hover {
150
+ background: none;
151
+ color: #999999;
152
+ cursor: default;
153
+ }
154
+ .datepicker td span.active,
155
+ .datepicker td span.active:hover,
156
+ .datepicker td span.active.disabled,
157
+ .datepicker td span.active.disabled:hover {
158
+ background-color: #006dcc;
159
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
160
+ background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
161
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
162
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
163
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
164
+ background-image: linear-gradient(top, #0088cc, #0044cc);
165
+ background-repeat: repeat-x;
166
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
167
+ border-color: #0044cc #0044cc #002a80;
168
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
169
+ filter: progid:dximagetransform.microsoft.gradient(enabled=false);
170
+ color: #fff;
171
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
172
+ }
173
+ .datepicker td span.active:hover,
174
+ .datepicker td span.active:hover:hover,
175
+ .datepicker td span.active.disabled:hover,
176
+ .datepicker td span.active.disabled:hover:hover,
177
+ .datepicker td span.active:active,
178
+ .datepicker td span.active:hover:active,
179
+ .datepicker td span.active.disabled:active,
180
+ .datepicker td span.active.disabled:hover:active,
181
+ .datepicker td span.active.active,
182
+ .datepicker td span.active:hover.active,
183
+ .datepicker td span.active.disabled.active,
184
+ .datepicker td span.active.disabled:hover.active,
185
+ .datepicker td span.active.disabled,
186
+ .datepicker td span.active:hover.disabled,
187
+ .datepicker td span.active.disabled.disabled,
188
+ .datepicker td span.active.disabled:hover.disabled,
189
+ .datepicker td span.active[disabled],
190
+ .datepicker td span.active:hover[disabled],
191
+ .datepicker td span.active.disabled[disabled],
192
+ .datepicker td span.active.disabled:hover[disabled] {
193
+ background-color: #0044cc;
194
+ }
195
+ .datepicker td span.active:active,
196
+ .datepicker td span.active:hover:active,
197
+ .datepicker td span.active.disabled:active,
198
+ .datepicker td span.active.disabled:hover:active,
199
+ .datepicker td span.active.active,
200
+ .datepicker td span.active:hover.active,
201
+ .datepicker td span.active.disabled.active,
202
+ .datepicker td span.active.disabled:hover.active {
203
+ background-color: #003399 \9;
204
+ }
205
+ .datepicker td span.old {
206
+ color: #999999;
207
+ }
208
+ .datepicker th.switch {
209
+ width: 145px;
210
+ }
211
+ .datepicker thead tr:first-child th {
212
+ cursor: pointer;
213
+ }
214
+ .datepicker thead tr:first-child th:hover {
215
+ background: #eeeeee;
216
+ }
217
+ .input-append.date .add-on i,
218
+ .input-prepend.date .add-on i {
219
+ display: block;
220
+ cursor: pointer;
221
+ width: 16px;
222
+ height: 16px;
223
+ }
@@ -0,0 +1,779 @@
1
+ /* =========================================================
2
+ * bootstrap-datepicker.js
3
+ * http://www.eyecon.ro/bootstrap-datepicker
4
+ * =========================================================
5
+ * Copyright 2012 Stefan Petre
6
+ * Improvements by Andrew Rowls
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ * ========================================================= */
20
+
21
+ !function( $ ) {
22
+
23
+ function UTCDate(){
24
+ return new Date(Date.UTC.apply(Date, arguments));
25
+ }
26
+
27
+ // Picker object
28
+
29
+ var Datepicker = function(element, options) {
30
+ var that = this;
31
+
32
+ this.element = $(element);
33
+ this.language = options.language||this.element.data('date-language')||"en";
34
+ this.language = this.language in dates ? this.language : "en";
35
+ this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
36
+ this.picker = $(DPGlobal.template)
37
+ .appendTo('body')
38
+ .on({
39
+ click: $.proxy(this.click, this)
40
+ });
41
+ this.isInput = this.element.is('input');
42
+ this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
43
+ this.hasInput = this.component && this.element.find('input').length;
44
+ if(this.component && this.component.length === 0)
45
+ this.component = false;
46
+
47
+ if (this.isInput) {
48
+ this.element.on({
49
+ focus: $.proxy(this.show, this),
50
+ keyup: $.proxy(this.update, this),
51
+ keydown: $.proxy(this.keydown, this)
52
+ });
53
+ } else {
54
+ if (this.component && this.hasInput){
55
+ // For components that are not readonly, allow keyboard nav
56
+ this.element.find('input').on({
57
+ focus: $.proxy(this.show, this),
58
+ keyup: $.proxy(this.update, this),
59
+ keydown: $.proxy(this.keydown, this)
60
+ });
61
+
62
+ this.component.on('click', $.proxy(this.show, this));
63
+ } else {
64
+ this.element.on('click', $.proxy(this.show, this));
65
+ }
66
+ }
67
+
68
+ $(document).on('mousedown', function (e) {
69
+ // Clicked outside the datepicker, hide it
70
+ if ($(e.target).closest('.datepicker').length == 0) {
71
+ that.hide();
72
+ }
73
+ });
74
+
75
+ this.autoclose = false;
76
+ if ('autoclose' in options) {
77
+ this.autoclose = options.autoclose;
78
+ } else if ('dateAutoclose' in this.element.data()) {
79
+ this.autoclose = this.element.data('date-autoclose');
80
+ }
81
+
82
+ this.keyboardNavigation = true;
83
+ if ('keyboardNavigation' in options) {
84
+ this.keyboardNavigation = options.keyboardNavigation;
85
+ } else if ('dateKeyboardNavigation' in this.element.data()) {
86
+ this.keyboardNavigation = this.element.data('date-keyboard-navigation');
87
+ }
88
+
89
+ switch(options.startView || this.element.data('date-start-view')){
90
+ case 2:
91
+ case 'decade':
92
+ this.viewMode = this.startViewMode = 2;
93
+ break;
94
+ case 1:
95
+ case 'year':
96
+ this.viewMode = this.startViewMode = 1;
97
+ break;
98
+ case 0:
99
+ case 'month':
100
+ default:
101
+ this.viewMode = this.startViewMode = 0;
102
+ break;
103
+ }
104
+
105
+ this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
106
+ this.weekEnd = ((this.weekStart + 6) % 7);
107
+ this.startDate = -Infinity;
108
+ this.endDate = Infinity;
109
+ this.setStartDate(options.startDate||this.element.data('date-startdate'));
110
+ this.setEndDate(options.endDate||this.element.data('date-enddate'));
111
+ this.fillDow();
112
+ this.fillMonths();
113
+ this.update();
114
+ this.showMode();
115
+ };
116
+
117
+ Datepicker.prototype = {
118
+ constructor: Datepicker,
119
+
120
+ show: function(e) {
121
+ this.picker.show();
122
+ this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
123
+ this.update();
124
+ this.place();
125
+ $(window).on('resize', $.proxy(this.place, this));
126
+ if (e ) {
127
+ e.stopPropagation();
128
+ e.preventDefault();
129
+ }
130
+ this.element.trigger({
131
+ type: 'show',
132
+ date: this.date
133
+ });
134
+ },
135
+
136
+ hide: function(e){
137
+ this.picker.hide();
138
+ $(window).off('resize', this.place);
139
+ this.viewMode = this.startViewMode;
140
+ this.showMode();
141
+ if (!this.isInput) {
142
+ $(document).off('mousedown', this.hide);
143
+ }
144
+ if (e && e.currentTarget.value)
145
+ this.setValue();
146
+ this.element.trigger({
147
+ type: 'hide',
148
+ date: this.date
149
+ });
150
+ },
151
+
152
+ setValue: function() {
153
+ var formatted = DPGlobal.formatDate(this.date, this.format, this.language);
154
+ if (!this.isInput) {
155
+ if (this.component){
156
+ this.element.find('input').prop('value', formatted);
157
+ }
158
+ this.element.data('date', formatted);
159
+ } else {
160
+ this.element.prop('value', formatted);
161
+ }
162
+ },
163
+
164
+ setStartDate: function(startDate){
165
+ this.startDate = startDate||-Infinity;
166
+ if (this.startDate !== -Infinity) {
167
+ this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
168
+ }
169
+ this.update();
170
+ this.updateNavArrows();
171
+ },
172
+
173
+ setEndDate: function(endDate){
174
+ this.endDate = endDate||Infinity;
175
+ if (this.endDate !== Infinity) {
176
+ this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
177
+ }
178
+ this.update();
179
+ this.updateNavArrows();
180
+ },
181
+
182
+ place: function(){
183
+ var zIndex = parseInt(this.element.parents().filter(function() {
184
+ return $(this).css('z-index') != 'auto';
185
+ }).first().css('z-index'))+10;
186
+ var offset = this.component ? this.component.offset() : this.element.offset();
187
+ this.picker.css({
188
+ top: offset.top + this.height,
189
+ left: offset.left,
190
+ zIndex: zIndex
191
+ });
192
+ },
193
+
194
+ update: function(){
195
+ this.date = DPGlobal.parseDate(
196
+ this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'),
197
+ this.format, this.language
198
+ );
199
+ if (this.date < this.startDate) {
200
+ this.viewDate = new Date(this.startDate);
201
+ } else if (this.date > this.endDate) {
202
+ this.viewDate = new Date(this.endDate);
203
+ } else {
204
+ this.viewDate = new Date(this.date);
205
+ }
206
+ this.fill();
207
+ },
208
+
209
+ fillDow: function(){
210
+ var dowCnt = this.weekStart;
211
+ var html = '<tr>';
212
+ while (dowCnt < this.weekStart + 7) {
213
+ html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
214
+ }
215
+ html += '</tr>';
216
+ this.picker.find('.datepicker-days thead').append(html);
217
+ },
218
+
219
+ fillMonths: function(){
220
+ var html = '';
221
+ var i = 0
222
+ while (i < 12) {
223
+ html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
224
+ }
225
+ this.picker.find('.datepicker-months td').html(html);
226
+ },
227
+
228
+ fill: function() {
229
+ var d = new Date(this.viewDate),
230
+ year = d.getUTCFullYear(),
231
+ month = d.getUTCMonth(),
232
+ startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
233
+ startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
234
+ endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
235
+ endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
236
+ currentDate = this.date.valueOf();
237
+ this.picker.find('.datepicker-days th:eq(1)')
238
+ .text(dates[this.language].months[month]+' '+year);
239
+ this.updateNavArrows();
240
+ this.fillMonths();
241
+ var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
242
+ day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
243
+ prevMonth.setUTCDate(day);
244
+ prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
245
+ var nextMonth = new Date(prevMonth);
246
+ nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
247
+ nextMonth = nextMonth.valueOf();
248
+ var html = [];
249
+ var clsName;
250
+ while(prevMonth.valueOf() < nextMonth) {
251
+ if (prevMonth.getUTCDay() == this.weekStart) {
252
+ html.push('<tr>');
253
+ }
254
+ clsName = '';
255
+ if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
256
+ clsName += ' old';
257
+ } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
258
+ clsName += ' new';
259
+ }
260
+ if (prevMonth.valueOf() == currentDate) {
261
+ clsName += ' active';
262
+ }
263
+ if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate) {
264
+ clsName += ' disabled';
265
+ }
266
+ html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>');
267
+ if (prevMonth.getUTCDay() == this.weekEnd) {
268
+ html.push('</tr>');
269
+ }
270
+ prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
271
+ }
272
+ this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
273
+ var currentYear = this.date.getUTCFullYear();
274
+
275
+ var months = this.picker.find('.datepicker-months')
276
+ .find('th:eq(1)')
277
+ .text(year)
278
+ .end()
279
+ .find('span').removeClass('active');
280
+ if (currentYear == year) {
281
+ months.eq(this.date.getUTCMonth()).addClass('active');
282
+ }
283
+ if (year < startYear || year > endYear) {
284
+ months.addClass('disabled');
285
+ }
286
+ if (year == startYear) {
287
+ months.slice(0, startMonth).addClass('disabled');
288
+ }
289
+ if (year == endYear) {
290
+ months.slice(endMonth+1).addClass('disabled');
291
+ }
292
+
293
+ html = '';
294
+ year = parseInt(year/10, 10) * 10;
295
+ var yearCont = this.picker.find('.datepicker-years')
296
+ .find('th:eq(1)')
297
+ .text(year + '-' + (year + 9))
298
+ .end()
299
+ .find('td');
300
+ year -= 1;
301
+ for (var i = -1; i < 11; i++) {
302
+ html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
303
+ year += 1;
304
+ }
305
+ yearCont.html(html);
306
+ },
307
+
308
+ updateNavArrows: function() {
309
+ var d = new Date(this.viewDate),
310
+ year = d.getUTCFullYear(),
311
+ month = d.getUTCMonth();
312
+ switch (this.viewMode) {
313
+ case 0:
314
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
315
+ this.picker.find('.prev').css({visibility: 'hidden'});
316
+ } else {
317
+ this.picker.find('.prev').css({visibility: 'visible'});
318
+ }
319
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
320
+ this.picker.find('.next').css({visibility: 'hidden'});
321
+ } else {
322
+ this.picker.find('.next').css({visibility: 'visible'});
323
+ }
324
+ break;
325
+ case 1:
326
+ case 2:
327
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
328
+ this.picker.find('.prev').css({visibility: 'hidden'});
329
+ } else {
330
+ this.picker.find('.prev').css({visibility: 'visible'});
331
+ }
332
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
333
+ this.picker.find('.next').css({visibility: 'hidden'});
334
+ } else {
335
+ this.picker.find('.next').css({visibility: 'visible'});
336
+ }
337
+ break;
338
+ }
339
+ },
340
+
341
+ click: function(e) {
342
+ e.stopPropagation();
343
+ e.preventDefault();
344
+ var target = $(e.target).closest('span, td, th');
345
+ if (target.length == 1) {
346
+ switch(target[0].nodeName.toLowerCase()) {
347
+ case 'th':
348
+ switch(target[0].className) {
349
+ case 'switch':
350
+ this.showMode(1);
351
+ break;
352
+ case 'prev':
353
+ case 'next':
354
+ var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
355
+ switch(this.viewMode){
356
+ case 0:
357
+ this.viewDate = this.moveMonth(this.viewDate, dir);
358
+ break;
359
+ case 1:
360
+ case 2:
361
+ this.viewDate = this.moveYear(this.viewDate, dir);
362
+ break;
363
+ }
364
+ this.fill();
365
+ break;
366
+ }
367
+ break;
368
+ case 'span':
369
+ if (!target.is('.disabled')) {
370
+ this.viewDate.setUTCDate(1);
371
+ if (target.is('.month')) {
372
+ var month = target.parent().find('span').index(target);
373
+ this.viewDate.setUTCMonth(month);
374
+ this.element.trigger({
375
+ type: 'changeMonth',
376
+ date: this.viewDate
377
+ });
378
+ } else {
379
+ var year = parseInt(target.text(), 10)||0;
380
+ this.viewDate.setUTCFullYear(year);
381
+ this.element.trigger({
382
+ type: 'changeYear',
383
+ date: this.viewDate
384
+ });
385
+ }
386
+ this.showMode(-1);
387
+ this.fill();
388
+ }
389
+ break;
390
+ case 'td':
391
+ if (target.is('.day') && !target.is('.disabled')){
392
+ var day = parseInt(target.text(), 10)||1;
393
+ var year = this.viewDate.getUTCFullYear(),
394
+ month = this.viewDate.getUTCMonth();
395
+ if (target.is('.old')) {
396
+ if (month == 0) {
397
+ month = 11;
398
+ year -= 1;
399
+ } else {
400
+ month -= 1;
401
+ }
402
+ } else if (target.is('.new')) {
403
+ if (month == 11) {
404
+ month = 0;
405
+ year += 1;
406
+ } else {
407
+ month += 1;
408
+ }
409
+ }
410
+ this.date = UTCDate(year, month, day,0,0,0,0);
411
+ this.viewDate = UTCDate(year, month, day,0,0,0,0);
412
+ this.fill();
413
+ this.setValue();
414
+ this.element.trigger({
415
+ type: 'changeDate',
416
+ date: this.date
417
+ });
418
+ var element;
419
+ if (this.isInput) {
420
+ element = this.element;
421
+ } else if (this.component){
422
+ element = this.element.find('input');
423
+ }
424
+ if (element) {
425
+ element.change();
426
+ if (this.autoclose) {
427
+ this.hide();
428
+ }
429
+ }
430
+ }
431
+ break;
432
+ }
433
+ }
434
+ },
435
+
436
+ moveMonth: function(date, dir){
437
+ if (!dir) return date;
438
+ var new_date = new Date(date.valueOf()),
439
+ day = new_date.getUTCDate(),
440
+ month = new_date.getUTCMonth(),
441
+ mag = Math.abs(dir),
442
+ new_month, test;
443
+ dir = dir > 0 ? 1 : -1;
444
+ if (mag == 1){
445
+ test = dir == -1
446
+ // If going back one month, make sure month is not current month
447
+ // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
448
+ ? function(){ return new_date.getUTCMonth() == month; }
449
+ // If going forward one month, make sure month is as expected
450
+ // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
451
+ : function(){ return new_date.getUTCMonth() != new_month; };
452
+ new_month = month + dir;
453
+ new_date.setUTCMonth(new_month);
454
+ // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
455
+ if (new_month < 0 || new_month > 11)
456
+ new_month = (new_month + 12) % 12;
457
+ } else {
458
+ // For magnitudes >1, move one month at a time...
459
+ for (var i=0; i<mag; i++)
460
+ // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
461
+ new_date = this.moveMonth(new_date, dir);
462
+ // ...then reset the day, keeping it in the new month
463
+ new_month = new_date.getUTCMonth();
464
+ new_date.setUTCDate(day);
465
+ test = function(){ return new_month != new_date.getUTCMonth(); };
466
+ }
467
+ // Common date-resetting loop -- if date is beyond end of month, make it
468
+ // end of month
469
+ while (test()){
470
+ new_date.setUTCDate(--day);
471
+ new_date.setUTCMonth(new_month);
472
+ }
473
+ return new_date;
474
+ },
475
+
476
+ moveYear: function(date, dir){
477
+ return this.moveMonth(date, dir*12);
478
+ },
479
+
480
+ dateWithinRange: function(date){
481
+ return date >= this.startDate && date <= this.endDate;
482
+ },
483
+
484
+ keydown: function(e){
485
+ if (this.picker.is(':not(:visible)')){
486
+ if (e.keyCode == 27) // allow escape to hide and re-show picker
487
+ this.show();
488
+ return;
489
+ }
490
+ var dateChanged = false,
491
+ dir, day, month,
492
+ newDate, newViewDate;
493
+ switch(e.keyCode){
494
+ case 27: // escape
495
+ this.hide();
496
+ e.preventDefault();
497
+ break;
498
+ case 37: // left
499
+ case 39: // right
500
+ if (!this.keyboardNavigation) break;
501
+ dir = e.keyCode == 37 ? -1 : 1;
502
+ if (e.ctrlKey){
503
+ newDate = this.moveYear(this.date, dir);
504
+ newViewDate = this.moveYear(this.viewDate, dir);
505
+ } else if (e.shiftKey){
506
+ newDate = this.moveMonth(this.date, dir);
507
+ newViewDate = this.moveMonth(this.viewDate, dir);
508
+ } else {
509
+ newDate = new Date(this.date);
510
+ newDate.setUTCDate(this.date.getUTCDate() + dir);
511
+ newViewDate = new Date(this.viewDate);
512
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
513
+ }
514
+ if (this.dateWithinRange(newDate)){
515
+ this.date = newDate;
516
+ this.viewDate = newViewDate;
517
+ this.setValue();
518
+ this.update();
519
+ e.preventDefault();
520
+ dateChanged = true;
521
+ }
522
+ break;
523
+ case 38: // up
524
+ case 40: // down
525
+ if (!this.keyboardNavigation) break;
526
+ dir = e.keyCode == 38 ? -1 : 1;
527
+ if (e.ctrlKey){
528
+ newDate = this.moveYear(this.date, dir);
529
+ newViewDate = this.moveYear(this.viewDate, dir);
530
+ } else if (e.shiftKey){
531
+ newDate = this.moveMonth(this.date, dir);
532
+ newViewDate = this.moveMonth(this.viewDate, dir);
533
+ } else {
534
+ newDate = new Date(this.date);
535
+ newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
536
+ newViewDate = new Date(this.viewDate);
537
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
538
+ }
539
+ if (this.dateWithinRange(newDate)){
540
+ this.date = newDate;
541
+ this.viewDate = newViewDate;
542
+ this.setValue();
543
+ this.update();
544
+ e.preventDefault();
545
+ dateChanged = true;
546
+ }
547
+ break;
548
+ case 13: // enter
549
+ this.hide();
550
+ e.preventDefault();
551
+ break;
552
+ case 9: // tab
553
+ this.hide();
554
+ break;
555
+ }
556
+ if (dateChanged){
557
+ this.element.trigger({
558
+ type: 'changeDate',
559
+ date: this.date
560
+ });
561
+ var element;
562
+ if (this.isInput) {
563
+ element = this.element;
564
+ } else if (this.component){
565
+ element = this.element.find('input');
566
+ }
567
+ if (element) {
568
+ element.change();
569
+ }
570
+ }
571
+ },
572
+
573
+ showMode: function(dir) {
574
+ if (dir) {
575
+ this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
576
+ }
577
+ this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
578
+ this.updateNavArrows();
579
+ }
580
+ };
581
+
582
+ $.fn.datepicker = function ( option ) {
583
+ var args = Array.apply(null, arguments);
584
+ args.shift();
585
+ return this.each(function () {
586
+ var $this = $(this),
587
+ data = $this.data('datepicker'),
588
+ options = typeof option == 'object' && option;
589
+ if (!data) {
590
+ $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
591
+ }
592
+ if (typeof option == 'string' && typeof data[option] == 'function') {
593
+ data[option].apply(data, args);
594
+ }
595
+ });
596
+ };
597
+
598
+ $.fn.datepicker.defaults = {
599
+ };
600
+ $.fn.datepicker.Constructor = Datepicker;
601
+ var dates = $.fn.datepicker.dates = {
602
+ en: {
603
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
604
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
605
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
606
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
607
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
608
+ }
609
+ }
610
+
611
+ var DPGlobal = {
612
+ modes: [
613
+ {
614
+ clsName: 'days',
615
+ navFnc: 'Month',
616
+ navStep: 1
617
+ },
618
+ {
619
+ clsName: 'months',
620
+ navFnc: 'FullYear',
621
+ navStep: 1
622
+ },
623
+ {
624
+ clsName: 'years',
625
+ navFnc: 'FullYear',
626
+ navStep: 10
627
+ }],
628
+ isLeapYear: function (year) {
629
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
630
+ },
631
+ getDaysInMonth: function (year, month) {
632
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
633
+ },
634
+ validParts: /dd?|mm?|MM?|yy(?:yy)?/g,
635
+ nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\r]+/g,
636
+ parseFormat: function(format){
637
+ // IE treats \0 as a string end in inputs (truncating the value),
638
+ // so it's a bad format delimiter, anyway
639
+ var separators = format.replace(this.validParts, '\0').split('\0'),
640
+ parts = format.match(this.validParts);
641
+ if (!separators || !separators.length || !parts || parts.length == 0){
642
+ throw new Error("Invalid date format.");
643
+ }
644
+ return {separators: separators, parts: parts};
645
+ },
646
+ parseDate: function(date, format, language) {
647
+ if (date instanceof Date) return date;
648
+ if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
649
+ var part_re = /([-+]\d+)([dmwy])/,
650
+ parts = date.match(/([-+]\d+)([dmwy])/g),
651
+ part, dir;
652
+ date = new Date();
653
+ for (var i=0; i<parts.length; i++) {
654
+ part = part_re.exec(parts[i]);
655
+ dir = parseInt(part[1]);
656
+ switch(part[2]){
657
+ case 'd':
658
+ date.setUTCDate(date.getUTCDate() + dir);
659
+ break;
660
+ case 'm':
661
+ date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
662
+ break;
663
+ case 'w':
664
+ date.setUTCDate(date.getUTCDate() + dir * 7);
665
+ break;
666
+ case 'y':
667
+ date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
668
+ break;
669
+ }
670
+ }
671
+ return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
672
+ }
673
+ var parts = date && date.match(this.nonpunctuation) || [],
674
+ date = new Date(),
675
+ parsed = {},
676
+ setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
677
+ setters_map = {
678
+ yyyy: function(d,v){ return d.setUTCFullYear(v); },
679
+ yy: function(d,v){ return d.setUTCFullYear(2000+v); },
680
+ m: function(d,v){
681
+ v -= 1;
682
+ while (v<0) v += 12;
683
+ v %= 12;
684
+ d.setUTCMonth(v);
685
+ while (d.getUTCMonth() != v)
686
+ d.setUTCDate(d.getUTCDate()-1);
687
+ return d;
688
+ },
689
+ d: function(d,v){ return d.setUTCDate(v); }
690
+ },
691
+ val, filtered, part;
692
+ setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
693
+ setters_map['dd'] = setters_map['d'];
694
+ date = UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
695
+ if (parts.length == format.parts.length) {
696
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
697
+ val = parseInt(parts[i], 10);
698
+ part = format.parts[i];
699
+ if (isNaN(val)) {
700
+ switch(part) {
701
+ case 'MM':
702
+ filtered = $(dates[language].months).filter(function(){
703
+ var m = this.slice(0, parts[i].length),
704
+ p = parts[i].slice(0, m.length);
705
+ return m == p;
706
+ });
707
+ val = $.inArray(filtered[0], dates[language].months) + 1;
708
+ break;
709
+ case 'M':
710
+ filtered = $(dates[language].monthsShort).filter(function(){
711
+ var m = this.slice(0, parts[i].length),
712
+ p = parts[i].slice(0, m.length);
713
+ return m == p;
714
+ });
715
+ val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
716
+ break;
717
+ }
718
+ }
719
+ parsed[part] = val;
720
+ }
721
+ for (var i=0, s; i<setters_order.length; i++){
722
+ s = setters_order[i];
723
+ if (s in parsed)
724
+ setters_map[s](date, parsed[s])
725
+ }
726
+ }
727
+ return date;
728
+ },
729
+ formatDate: function(date, format, language){
730
+ var val = {
731
+ d: date.getUTCDate(),
732
+ m: date.getUTCMonth() + 1,
733
+ M: dates[language].monthsShort[date.getUTCMonth()],
734
+ MM: dates[language].months[date.getUTCMonth()],
735
+ yy: date.getUTCFullYear().toString().substring(2),
736
+ yyyy: date.getUTCFullYear()
737
+ };
738
+ val.dd = (val.d < 10 ? '0' : '') + val.d;
739
+ val.mm = (val.m < 10 ? '0' : '') + val.m;
740
+ var date = [],
741
+ seps = $.extend([], format.separators);
742
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
743
+ if (seps.length)
744
+ date.push(seps.shift())
745
+ date.push(val[format.parts[i]]);
746
+ }
747
+ return date.join('');
748
+ },
749
+ headTemplate: '<thead>'+
750
+ '<tr>'+
751
+ '<th class="prev"><i class="icon-arrow-left"/></th>'+
752
+ '<th colspan="5" class="switch"></th>'+
753
+ '<th class="next"><i class="icon-arrow-right"/></th>'+
754
+ '</tr>'+
755
+ '</thead>',
756
+ contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
757
+ };
758
+ DPGlobal.template = '<div class="datepicker dropdown-menu">'+
759
+ '<div class="datepicker-days">'+
760
+ '<table class=" table-condensed">'+
761
+ DPGlobal.headTemplate+
762
+ '<tbody></tbody>'+
763
+ '</table>'+
764
+ '</div>'+
765
+ '<div class="datepicker-months">'+
766
+ '<table class="table-condensed">'+
767
+ DPGlobal.headTemplate+
768
+ DPGlobal.contTemplate+
769
+ '</table>'+
770
+ '</div>'+
771
+ '<div class="datepicker-years">'+
772
+ '<table class="table-condensed">'+
773
+ DPGlobal.headTemplate+
774
+ DPGlobal.contTemplate+
775
+ '</table>'+
776
+ '</div>'+
777
+ '</div>';
778
+
779
+ }( window.jQuery );