cmsimple 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. data/.gitignore +31 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +16 -0
  4. data/Gemfile +20 -0
  5. data/Gemfile.ci +5 -0
  6. data/LICENSE +19 -0
  7. data/README.md +118 -0
  8. data/Rakefile +47 -0
  9. data/app/assets/javascripts/cmsimple.js +61 -0
  10. data/app/assets/javascripts/cmsimple/controllers/editor.coffee +102 -0
  11. data/app/assets/javascripts/cmsimple/lib/namespaces.coffee +3 -0
  12. data/app/assets/javascripts/cmsimple/lib/support.coffee +4 -0
  13. data/app/assets/javascripts/cmsimple/mercury/config.js +462 -0
  14. data/app/assets/javascripts/cmsimple/mercury/handlers.coffee +9 -0
  15. data/app/assets/javascripts/cmsimple/models/image.coffee +49 -0
  16. data/app/assets/javascripts/cmsimple/models/page.coffee +106 -0
  17. data/app/assets/javascripts/cmsimple/models/path.coffee +31 -0
  18. data/app/assets/javascripts/cmsimple/models/version.coffee +29 -0
  19. data/app/assets/javascripts/cmsimple/panels/images/index.coffee +2 -0
  20. data/app/assets/javascripts/cmsimple/panels/images/list.coffee +48 -0
  21. data/app/assets/javascripts/cmsimple/panels/images/panel.coffee +69 -0
  22. data/app/assets/javascripts/cmsimple/panels/images/selection.coffee +52 -0
  23. data/app/assets/javascripts/cmsimple/panels/page_metadata.coffee +42 -0
  24. data/app/assets/javascripts/cmsimple/panels/publish.coffee +32 -0
  25. data/app/assets/javascripts/cmsimple/panels/redirects/form.coffee +51 -0
  26. data/app/assets/javascripts/cmsimple/panels/redirects/index.coffee +2 -0
  27. data/app/assets/javascripts/cmsimple/panels/redirects/list.coffee +34 -0
  28. data/app/assets/javascripts/cmsimple/panels/redirects/panel.coffee +39 -0
  29. data/app/assets/javascripts/cmsimple/panels/sitemap/index.coffee +2 -0
  30. data/app/assets/javascripts/cmsimple/panels/sitemap/panel.coffee +40 -0
  31. data/app/assets/javascripts/cmsimple/panels/sitemap/sortable.coffee +55 -0
  32. data/app/assets/javascripts/cmsimple/panels/sitemap/tree.coffee +61 -0
  33. data/app/assets/javascripts/cmsimple/panels/versions/index.coffee +2 -0
  34. data/app/assets/javascripts/cmsimple/panels/versions/list.coffee +51 -0
  35. data/app/assets/javascripts/cmsimple/panels/versions/panel.coffee +53 -0
  36. data/app/assets/javascripts/cmsimple/views/image_library/_item.jst.hamlc +24 -0
  37. data/app/assets/javascripts/cmsimple/views/image_library/list.jst.hamlc +8 -0
  38. data/app/assets/javascripts/cmsimple/views/redirects/_path.jst.hamlc +6 -0
  39. data/app/assets/javascripts/cmsimple/views/redirects/list.jst.hamlc +19 -0
  40. data/app/assets/javascripts/cmsimple/views/sitemap/_page.jst.hamlc +9 -0
  41. data/app/assets/javascripts/cmsimple/views/sitemap/tree.jst.hamlc +5 -0
  42. data/app/assets/javascripts/cmsimple/views/versions/_item.jst.hamlc +6 -0
  43. data/app/assets/javascripts/cmsimple/views/versions/list.jst.hamlc +4 -0
  44. data/app/assets/stylesheets/cmsimple.css +15 -0
  45. data/app/assets/stylesheets/cmsimple/forms.css +10 -0
  46. data/app/assets/stylesheets/cmsimple/panels.css +399 -0
  47. data/app/assets/stylesheets/cmsimple/toolbar-images.css +27 -0
  48. data/app/assets/stylesheets/mercury_overrides.css +2 -0
  49. data/app/controllers/cmsimple/front_controller.rb +38 -0
  50. data/app/controllers/cmsimple/images_controller.rb +28 -0
  51. data/app/controllers/cmsimple/mercury_controller.rb +7 -0
  52. data/app/controllers/cmsimple/pages_controller.rb +89 -0
  53. data/app/controllers/cmsimple/paths_controller.rb +23 -0
  54. data/app/controllers/cmsimple/snippets_controller.rb +23 -0
  55. data/app/controllers/cmsimple/versions_controller.rb +17 -0
  56. data/app/helpers/cmsimple/regions_helper.rb +38 -0
  57. data/app/models/cmsimple/image.rb +19 -0
  58. data/app/models/cmsimple/page.rb +203 -0
  59. data/app/models/cmsimple/path.rb +63 -0
  60. data/app/models/cmsimple/region.rb +43 -0
  61. data/app/models/cmsimple/snippet.rb +64 -0
  62. data/app/models/cmsimple/version.rb +18 -0
  63. data/app/uploaders/image_attachment_uploader.rb +53 -0
  64. data/app/views/cmsimple/images/_form.html.haml +13 -0
  65. data/app/views/cmsimple/images/new.html.haml +5 -0
  66. data/app/views/cmsimple/pages/_form.html.haml +49 -0
  67. data/app/views/cmsimple/pages/_form_extras.html.haml +2 -0
  68. data/app/views/cmsimple/pages/edit.html.haml +3 -0
  69. data/app/views/cmsimple/pages/new.html.haml +3 -0
  70. data/app/views/cmsimple/pages/publish.html.haml +12 -0
  71. data/app/views/cmsimple/snippets/index.html.haml +5 -0
  72. data/app/views/cmsimple/templates/default.html.haml +4 -0
  73. data/app/views/layouts/editor.html.haml +12 -0
  74. data/app/views/layouts/panel.html.haml +9 -0
  75. data/cmsimple.gemspec +44 -0
  76. data/config.ru +4 -0
  77. data/config/application.rb +1 -0
  78. data/config/cucumber.yml +8 -0
  79. data/config/environment.rb +2 -0
  80. data/config/routes.rb +34 -0
  81. data/db/migrate/20120201221410_create_cmsimple_pages.rb +10 -0
  82. data/db/migrate/20120222185901_add_title_parent_id_and_position_to_pages.rb +10 -0
  83. data/db/migrate/20120229185214_add_slug_to_pages.rb +7 -0
  84. data/db/migrate/20120323200439_add_is_root_to_page.rb +5 -0
  85. data/db/migrate/20120328174339_add_meta_info_to_cmsimple_pages.rb +9 -0
  86. data/db/migrate/20120329172857_create_cmsimple_path.rb +11 -0
  87. data/db/migrate/20120407024752_create_cmsimple_images.rb +13 -0
  88. data/db/migrate/20120410041105_add_timestamps_to_cmsimple_pages.rb +7 -0
  89. data/db/migrate/20120425211937_add_published_at_to_cmsimple_pages.rb +6 -0
  90. data/db/migrate/20120430175047_create_cmsimple_versions.rb +13 -0
  91. data/db/migrate/20120831233927_rename_path_to_current_uri_on_paths.rb +5 -0
  92. data/features/create.feature +18 -0
  93. data/features/delete.feature +12 -0
  94. data/features/edit.feature +54 -0
  95. data/features/publishing.feature +31 -0
  96. data/features/redirects.feature +27 -0
  97. data/features/step_definitions/mercury_steps.rb +440 -0
  98. data/features/step_definitions/page_steps.rb +269 -0
  99. data/features/step_definitions/web_steps.rb +254 -0
  100. data/features/support/env.rb +77 -0
  101. data/features/support/mercury_content.rb +25 -0
  102. data/features/support/mercury_selectors.rb +148 -0
  103. data/features/support/paths.rb +16 -0
  104. data/features/support/selectors.rb +26 -0
  105. data/features/support/utils.rb +18 -0
  106. data/features/versioning.feature +27 -0
  107. data/features/visit.feature +7 -0
  108. data/lib/cmsimple.rb +22 -0
  109. data/lib/cmsimple/configuration.rb +65 -0
  110. data/lib/cmsimple/exts/to_bool.rb +25 -0
  111. data/lib/cmsimple/page_responder.rb +46 -0
  112. data/lib/cmsimple/rails.rb +5 -0
  113. data/lib/cmsimple/regions_proxy.rb +32 -0
  114. data/lib/cmsimple/template_resolver.rb +14 -0
  115. data/lib/cmsimple/template_responder.rb +12 -0
  116. data/lib/cmsimple/version.rb +3 -0
  117. data/lib/generators/cmsimple/install/install_generator.rb +46 -0
  118. data/lib/generators/cmsimple/install/templates/default.html.erb +10 -0
  119. data/lib/generators/cmsimple/install/templates/default.html.haml +6 -0
  120. data/lib/generators/cmsimple/install/templates/initializer.rb +22 -0
  121. data/lib/generators/cmsimple/snippet/snippet_generator.rb +56 -0
  122. data/lib/generators/cmsimple/snippet/templates/cell.rb +18 -0
  123. data/lib/generators/cmsimple/snippet/templates/display.html.erb +14 -0
  124. data/lib/generators/cmsimple/snippet/templates/display.html.haml +11 -0
  125. data/lib/generators/cmsimple/snippet/templates/options.html.erb +18 -0
  126. data/lib/generators/cmsimple/snippet/templates/options.html.haml +12 -0
  127. data/script/app +2 -0
  128. data/script/migrate +2 -0
  129. data/script/rails +8 -0
  130. data/spec/fixtures/rails.png +0 -0
  131. data/spec/helpers/regions_helper_spec.rb +62 -0
  132. data/spec/javascripts/controllers/editor_spec.coffee +57 -0
  133. data/spec/javascripts/models/image_geometry_spec.coffee +64 -0
  134. data/spec/javascripts/models/image_spec.coffee +4 -0
  135. data/spec/javascripts/models/page_spec.coffee +121 -0
  136. data/spec/javascripts/models/path_spec.coffee +39 -0
  137. data/spec/javascripts/models/version_spec.coffee +31 -0
  138. data/spec/javascripts/panels/images/selection_spec.coffee +104 -0
  139. data/spec/javascripts/panels/sitemap/panel_spec.coffee +10 -0
  140. data/spec/javascripts/panels/sitemap/sortable_spec.coffee +63 -0
  141. data/spec/javascripts/panels/sitemap/tree_spec.coffee +62 -0
  142. data/spec/javascripts/spec_helper.coffee +25 -0
  143. data/spec/javascripts/support/stubs.coffee +16 -0
  144. data/spec/lib/page_responder_spec.rb +58 -0
  145. data/spec/lib/regions_proxy_spec.rb +47 -0
  146. data/spec/models/image_spec.rb +46 -0
  147. data/spec/models/page_spec.rb +237 -0
  148. data/spec/models/path_spec.rb +71 -0
  149. data/spec/models/region_spec.rb +14 -0
  150. data/spec/models/snippet_spec.rb +57 -0
  151. data/spec/models/version_spec.rb +7 -0
  152. data/spec/rails_app/.gitignore +33 -0
  153. data/spec/rails_app/Rakefile +7 -0
  154. data/spec/rails_app/app/assets/images/rails.png +0 -0
  155. data/spec/rails_app/app/assets/javascripts/application.js +9 -0
  156. data/spec/rails_app/app/assets/stylesheets/application.css +7 -0
  157. data/spec/rails_app/app/cells/example/display.html.haml +2 -0
  158. data/spec/rails_app/app/cells/example/options.html.haml +15 -0
  159. data/spec/rails_app/app/cells/example_cell.rb +19 -0
  160. data/spec/rails_app/app/cells/image_example/display.html.haml +4 -0
  161. data/spec/rails_app/app/cells/image_example/options.html.haml +15 -0
  162. data/spec/rails_app/app/cells/image_example_cell.rb +18 -0
  163. data/spec/rails_app/app/controllers/application_controller.rb +3 -0
  164. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  165. data/spec/rails_app/app/mailers/.gitkeep +0 -0
  166. data/spec/rails_app/app/models/.gitkeep +0 -0
  167. data/spec/rails_app/app/views/cmsimple/_snippet_list.html.haml +8 -0
  168. data/spec/rails_app/app/views/cmsimple/templates/default.html.haml +19 -0
  169. data/spec/rails_app/app/views/cmsimple/templates/test.html.haml +2 -0
  170. data/spec/rails_app/app/views/layouts/application.html.haml +13 -0
  171. data/spec/rails_app/config.ru +4 -0
  172. data/spec/rails_app/config/application.rb +65 -0
  173. data/spec/rails_app/config/boot.rb +9 -0
  174. data/spec/rails_app/config/database.example.yml +22 -0
  175. data/spec/rails_app/config/database.travis.yml +8 -0
  176. data/spec/rails_app/config/environment.rb +5 -0
  177. data/spec/rails_app/config/environments/development.rb +30 -0
  178. data/spec/rails_app/config/environments/test.rb +39 -0
  179. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  180. data/spec/rails_app/config/initializers/cells.rb +1 -0
  181. data/spec/rails_app/config/initializers/cmsimple.rb +3 -0
  182. data/spec/rails_app/config/initializers/inflections.rb +10 -0
  183. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  184. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  185. data/spec/rails_app/config/initializers/session_store.rb +8 -0
  186. data/spec/rails_app/config/initializers/teabag.rb +58 -0
  187. data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
  188. data/spec/rails_app/config/locales/en.yml +5 -0
  189. data/spec/rails_app/config/routes.rb +61 -0
  190. data/spec/rails_app/db/seeds.rb +11 -0
  191. data/spec/rails_app/lib/assets/.gitkeep +0 -0
  192. data/spec/rails_app/lib/tasks/.gitkeep +0 -0
  193. data/spec/rails_app/public/404.html +26 -0
  194. data/spec/rails_app/public/422.html +26 -0
  195. data/spec/rails_app/public/500.html +26 -0
  196. data/spec/rails_app/public/robots.txt +5 -0
  197. data/spec/rails_app/script/rails +6 -0
  198. data/spec/rails_app/vendor/assets/stylesheets/.gitkeep +0 -0
  199. data/spec/rails_app/vendor/plugins/.gitkeep +0 -0
  200. data/spec/spec_helper.rb +31 -0
  201. data/spec/support/active_model_lint_example.rb +14 -0
  202. data/spec/teabag_env.rb +28 -0
  203. data/vendor/assets/images/sitemap/has-changes.png +0 -0
  204. data/vendor/assets/images/sitemap/published.png +0 -0
  205. data/vendor/assets/images/sitemap/unpublished.png +0 -0
  206. data/vendor/assets/images/toolbar/metadata.png +0 -0
  207. data/vendor/assets/images/toolbar/publish.png +0 -0
  208. data/vendor/assets/images/toolbar/redirect.png +0 -0
  209. data/vendor/assets/images/toolbar/sitemap.png +0 -0
  210. data/vendor/assets/images/toolbar/snippets.png +0 -0
  211. data/vendor/assets/images/toolbar/unpublished.png +0 -0
  212. data/vendor/assets/images/tree-line-horizontal-last.png +0 -0
  213. data/vendor/assets/images/tree-line-horizontal.png +0 -0
  214. data/vendor/assets/images/tree-line-vertical.png +0 -0
  215. data/vendor/assets/javascripts/jquery-serializeObject.js +107 -0
  216. data/vendor/assets/javascripts/jquery.to-json.js +74 -0
  217. data/vendor/assets/javascripts/jquery.ui.nestedSortable-1.3.4.js +391 -0
  218. data/vendor/assets/javascripts/moment-1.6.2.js +918 -0
  219. data/vendor/assets/javascripts/underscore-1.3.1.js +31 -0
  220. data/vendor/assets/stylesheets/jasmine-modified.css +216 -0
  221. metadata +686 -0
@@ -0,0 +1,918 @@
1
+ // moment.js
2
+ // version : 1.6.2
3
+ // author : Tim Wood
4
+ // license : MIT
5
+ // momentjs.com
6
+
7
+ (function (Date, undefined) {
8
+
9
+ var moment,
10
+ VERSION = "1.6.2",
11
+ round = Math.round, i,
12
+ // internal storage for language config files
13
+ languages = {},
14
+ currentLanguage = 'en',
15
+
16
+ // check for nodeJS
17
+ hasModule = (typeof module !== 'undefined'),
18
+
19
+ // parameters to check for on the lang config
20
+ langConfigProperties = 'months|monthsShort|monthsParse|weekdays|weekdaysShort|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'),
21
+
22
+ // ASP.NET json date format regex
23
+ aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
24
+
25
+ // format tokens
26
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|LT|LL?L?L?)/g,
27
+
28
+ // parsing tokens
29
+ parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
30
+
31
+ // parsing token regexes
32
+ parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
33
+ parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
34
+ parseTokenThreeDigits = /\d{3}/, // 000 - 999
35
+ parseTokenFourDigits = /\d{4}/, // 0000 - 9999
36
+ parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i, // any word characters or numbers
37
+ parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
38
+ parseTokenT = /T/i, // T (ISO seperator)
39
+
40
+ // preliminary iso regex
41
+ // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
42
+ isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
43
+ isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
44
+
45
+ // iso time formats and regexes
46
+ isoTimes = [
47
+ ['HH:mm:ss.S', /T\d\d:\d\d:\d\d\.\d{1,3}/],
48
+ ['HH:mm:ss', /T\d\d:\d\d:\d\d/],
49
+ ['HH:mm', /T\d\d:\d\d/],
50
+ ['HH', /T\d\d/]
51
+ ],
52
+
53
+ // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
54
+ parseTimezoneChunker = /([\+\-]|\d\d)/gi,
55
+
56
+ // getter and setter names
57
+ proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
58
+ unitMillisecondFactors = {
59
+ 'Milliseconds' : 1,
60
+ 'Seconds' : 1e3,
61
+ 'Minutes' : 6e4,
62
+ 'Hours' : 36e5,
63
+ 'Days' : 864e5,
64
+ 'Months' : 2592e6,
65
+ 'Years' : 31536e6
66
+ };
67
+
68
+ // Moment prototype object
69
+ function Moment(date, isUTC) {
70
+ this._d = date;
71
+ this._isUTC = !!isUTC;
72
+ }
73
+
74
+ function absRound(number) {
75
+ if (number < 0) {
76
+ return Math.ceil(number);
77
+ } else {
78
+ return Math.floor(number);
79
+ }
80
+ }
81
+
82
+ // Duration Constructor
83
+ function Duration(duration) {
84
+ var data = this._data = {},
85
+ years = duration.years || duration.y || 0,
86
+ months = duration.months || duration.M || 0,
87
+ weeks = duration.weeks || duration.w || 0,
88
+ days = duration.days || duration.d || 0,
89
+ hours = duration.hours || duration.h || 0,
90
+ minutes = duration.minutes || duration.m || 0,
91
+ seconds = duration.seconds || duration.s || 0,
92
+ milliseconds = duration.milliseconds || duration.ms || 0;
93
+
94
+ // representation for dateAddRemove
95
+ this._milliseconds = milliseconds +
96
+ seconds * 1e3 + // 1000
97
+ minutes * 6e4 + // 1000 * 60
98
+ hours * 36e5; // 1000 * 60 * 60
99
+ // Because of dateAddRemove treats 24 hours as different from a
100
+ // day when working around DST, we need to store them separately
101
+ this._days = days +
102
+ weeks * 7;
103
+ // It is impossible translate months into days without knowing
104
+ // which months you are are talking about, so we have to store
105
+ // it separately.
106
+ this._months = months +
107
+ years * 12;
108
+
109
+ // The following code bubbles up values, see the tests for
110
+ // examples of what that means.
111
+ data.milliseconds = milliseconds % 1000;
112
+ seconds += absRound(milliseconds / 1000);
113
+
114
+ data.seconds = seconds % 60;
115
+ minutes += absRound(seconds / 60);
116
+
117
+ data.minutes = minutes % 60;
118
+ hours += absRound(minutes / 60);
119
+
120
+ data.hours = hours % 24;
121
+ days += absRound(hours / 24);
122
+
123
+ days += weeks * 7;
124
+ data.days = days % 30;
125
+
126
+ months += absRound(days / 30);
127
+
128
+ data.months = months % 12;
129
+ years += absRound(months / 12);
130
+
131
+ data.years = years;
132
+ }
133
+
134
+ // left zero fill a number
135
+ // see http://jsperf.com/left-zero-filling for performance comparison
136
+ function leftZeroFill(number, targetLength) {
137
+ var output = number + '';
138
+ while (output.length < targetLength) {
139
+ output = '0' + output;
140
+ }
141
+ return output;
142
+ }
143
+
144
+ // helper function for _.addTime and _.subtractTime
145
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
146
+ var ms = duration._milliseconds,
147
+ d = duration._days,
148
+ M = duration._months,
149
+ currentDate;
150
+
151
+ if (ms) {
152
+ mom._d.setTime(+mom + ms * isAdding);
153
+ }
154
+ if (d) {
155
+ mom.date(mom.date() + d * isAdding);
156
+ }
157
+ if (M) {
158
+ currentDate = mom.date();
159
+ mom.date(1)
160
+ .month(mom.month() + M * isAdding)
161
+ .date(Math.min(currentDate, mom.daysInMonth()));
162
+ }
163
+ }
164
+
165
+ // check if is an array
166
+ function isArray(input) {
167
+ return Object.prototype.toString.call(input) === '[object Array]';
168
+ }
169
+
170
+ // convert an array to a date.
171
+ // the array should mirror the parameters below
172
+ // note: all values past the year are optional and will default to the lowest possible value.
173
+ // [year, month, day , hour, minute, second, millisecond]
174
+ function dateFromArray(input) {
175
+ return new Date(input[0], input[1] || 0, input[2] || 1, input[3] || 0, input[4] || 0, input[5] || 0, input[6] || 0);
176
+ }
177
+
178
+ // format date using native date object
179
+ function formatMoment(m, inputString) {
180
+ var currentMonth = m.month(),
181
+ currentDate = m.date(),
182
+ currentYear = m.year(),
183
+ currentDay = m.day(),
184
+ currentHours = m.hours(),
185
+ currentMinutes = m.minutes(),
186
+ currentSeconds = m.seconds(),
187
+ currentMilliseconds = m.milliseconds(),
188
+ currentZone = -m.zone(),
189
+ ordinal = moment.ordinal,
190
+ meridiem = moment.meridiem;
191
+ // check if the character is a format
192
+ // return formatted string or non string.
193
+ //
194
+ // uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380)
195
+ // for minification and performance
196
+ // see http://jsperf.com/object-of-functions-vs-switch for performance comparison
197
+ function replaceFunction(input) {
198
+ // create a couple variables to be used later inside one of the cases.
199
+ var a, b;
200
+ switch (input) {
201
+ // MONTH
202
+ case 'M' :
203
+ return currentMonth + 1;
204
+ case 'Mo' :
205
+ return (currentMonth + 1) + ordinal(currentMonth + 1);
206
+ case 'MM' :
207
+ return leftZeroFill(currentMonth + 1, 2);
208
+ case 'MMM' :
209
+ return moment.monthsShort[currentMonth];
210
+ case 'MMMM' :
211
+ return moment.months[currentMonth];
212
+ // DAY OF MONTH
213
+ case 'D' :
214
+ return currentDate;
215
+ case 'Do' :
216
+ return currentDate + ordinal(currentDate);
217
+ case 'DD' :
218
+ return leftZeroFill(currentDate, 2);
219
+ // DAY OF YEAR
220
+ case 'DDD' :
221
+ a = new Date(currentYear, currentMonth, currentDate);
222
+ b = new Date(currentYear, 0, 1);
223
+ return ~~ (((a - b) / 864e5) + 1.5);
224
+ case 'DDDo' :
225
+ a = replaceFunction('DDD');
226
+ return a + ordinal(a);
227
+ case 'DDDD' :
228
+ return leftZeroFill(replaceFunction('DDD'), 3);
229
+ // WEEKDAY
230
+ case 'd' :
231
+ return currentDay;
232
+ case 'do' :
233
+ return currentDay + ordinal(currentDay);
234
+ case 'ddd' :
235
+ return moment.weekdaysShort[currentDay];
236
+ case 'dddd' :
237
+ return moment.weekdays[currentDay];
238
+ // WEEK OF YEAR
239
+ case 'w' :
240
+ a = new Date(currentYear, currentMonth, currentDate - currentDay + 5);
241
+ b = new Date(a.getFullYear(), 0, 4);
242
+ return ~~ ((a - b) / 864e5 / 7 + 1.5);
243
+ case 'wo' :
244
+ a = replaceFunction('w');
245
+ return a + ordinal(a);
246
+ case 'ww' :
247
+ return leftZeroFill(replaceFunction('w'), 2);
248
+ // YEAR
249
+ case 'YY' :
250
+ return leftZeroFill(currentYear % 100, 2);
251
+ case 'YYYY' :
252
+ return currentYear;
253
+ // AM / PM
254
+ case 'a' :
255
+ return meridiem ? meridiem(currentHours, currentMinutes, false) : (currentHours > 11 ? 'pm' : 'am');
256
+ case 'A' :
257
+ return meridiem ? meridiem(currentHours, currentMinutes, true) : (currentHours > 11 ? 'PM' : 'AM');
258
+ // 24 HOUR
259
+ case 'H' :
260
+ return currentHours;
261
+ case 'HH' :
262
+ return leftZeroFill(currentHours, 2);
263
+ // 12 HOUR
264
+ case 'h' :
265
+ return currentHours % 12 || 12;
266
+ case 'hh' :
267
+ return leftZeroFill(currentHours % 12 || 12, 2);
268
+ // MINUTE
269
+ case 'm' :
270
+ return currentMinutes;
271
+ case 'mm' :
272
+ return leftZeroFill(currentMinutes, 2);
273
+ // SECOND
274
+ case 's' :
275
+ return currentSeconds;
276
+ case 'ss' :
277
+ return leftZeroFill(currentSeconds, 2);
278
+ // MILLISECONDS
279
+ case 'S' :
280
+ return ~~ (currentMilliseconds / 100);
281
+ case 'SS' :
282
+ return leftZeroFill(~~(currentMilliseconds / 10), 2);
283
+ case 'SSS' :
284
+ return leftZeroFill(currentMilliseconds, 3);
285
+ // TIMEZONE
286
+ case 'Z' :
287
+ return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(Math.abs(currentZone) / 60), 2) + ':' + leftZeroFill(~~(Math.abs(currentZone) % 60), 2);
288
+ case 'ZZ' :
289
+ return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(10 * Math.abs(currentZone) / 6), 4);
290
+ // LONG DATES
291
+ case 'L' :
292
+ case 'LL' :
293
+ case 'LLL' :
294
+ case 'LLLL' :
295
+ case 'LT' :
296
+ return formatMoment(m, moment.longDateFormat[input]);
297
+ // DEFAULT
298
+ default :
299
+ return input.replace(/(^\[)|(\\)|\]$/g, "");
300
+ }
301
+ }
302
+ return inputString.replace(formattingTokens, replaceFunction);
303
+ }
304
+
305
+ // get the regex to find the next token
306
+ function getParseRegexForToken(token) {
307
+ switch (token) {
308
+ case 'DDDD':
309
+ return parseTokenThreeDigits;
310
+ case 'YYYY':
311
+ return parseTokenFourDigits;
312
+ case 'S':
313
+ case 'SS':
314
+ case 'SSS':
315
+ case 'DDD':
316
+ return parseTokenOneToThreeDigits;
317
+ case 'MMM':
318
+ case 'MMMM':
319
+ case 'ddd':
320
+ case 'dddd':
321
+ case 'a':
322
+ case 'A':
323
+ return parseTokenWord;
324
+ case 'Z':
325
+ case 'ZZ':
326
+ return parseTokenTimezone;
327
+ case 'T':
328
+ return parseTokenT;
329
+ case 'MM':
330
+ case 'DD':
331
+ case 'dd':
332
+ case 'YY':
333
+ case 'HH':
334
+ case 'hh':
335
+ case 'mm':
336
+ case 'ss':
337
+ case 'M':
338
+ case 'D':
339
+ case 'd':
340
+ case 'H':
341
+ case 'h':
342
+ case 'm':
343
+ case 's':
344
+ return parseTokenOneOrTwoDigits;
345
+ default :
346
+ return new RegExp(token.replace('\\', ''));
347
+ }
348
+ }
349
+
350
+ // function to convert string input to date
351
+ function addTimeToArrayFromToken(token, input, datePartArray, config) {
352
+ var a;
353
+ //console.log('addTime', format, input);
354
+ switch (token) {
355
+ // MONTH
356
+ case 'M' : // fall through to MM
357
+ case 'MM' :
358
+ datePartArray[1] = (input == null) ? 0 : ~~input - 1;
359
+ break;
360
+ case 'MMM' : // fall through to MMMM
361
+ case 'MMMM' :
362
+ for (a = 0; a < 12; a++) {
363
+ if (moment.monthsParse[a].test(input)) {
364
+ datePartArray[1] = a;
365
+ break;
366
+ }
367
+ }
368
+ break;
369
+ // DAY OF MONTH
370
+ case 'D' : // fall through to DDDD
371
+ case 'DD' : // fall through to DDDD
372
+ case 'DDD' : // fall through to DDDD
373
+ case 'DDDD' :
374
+ datePartArray[2] = ~~input;
375
+ break;
376
+ // YEAR
377
+ case 'YY' :
378
+ input = ~~input;
379
+ datePartArray[0] = input + (input > 70 ? 1900 : 2000);
380
+ break;
381
+ case 'YYYY' :
382
+ datePartArray[0] = ~~Math.abs(input);
383
+ break;
384
+ // AM / PM
385
+ case 'a' : // fall through to A
386
+ case 'A' :
387
+ config.isPm = ((input + '').toLowerCase() === 'pm');
388
+ break;
389
+ // 24 HOUR
390
+ case 'H' : // fall through to hh
391
+ case 'HH' : // fall through to hh
392
+ case 'h' : // fall through to hh
393
+ case 'hh' :
394
+ datePartArray[3] = ~~input;
395
+ break;
396
+ // MINUTE
397
+ case 'm' : // fall through to mm
398
+ case 'mm' :
399
+ datePartArray[4] = ~~input;
400
+ break;
401
+ // SECOND
402
+ case 's' : // fall through to ss
403
+ case 'ss' :
404
+ datePartArray[5] = ~~input;
405
+ break;
406
+ // MILLISECOND
407
+ case 'S' :
408
+ case 'SS' :
409
+ case 'SSS' :
410
+ datePartArray[6] = ~~ (('0.' + input) * 1000);
411
+ break;
412
+ // TIMEZONE
413
+ case 'Z' : // fall through to ZZ
414
+ case 'ZZ' :
415
+ config.isUTC = true;
416
+ a = (input + '').match(parseTimezoneChunker);
417
+ if (a && a[1]) {
418
+ config.tzh = ~~a[1];
419
+ }
420
+ if (a && a[2]) {
421
+ config.tzm = ~~a[2];
422
+ }
423
+ // reverse offsets
424
+ if (a && a[0] === '+') {
425
+ config.tzh = -config.tzh;
426
+ config.tzm = -config.tzm;
427
+ }
428
+ break;
429
+ }
430
+ }
431
+
432
+ // date from string and format string
433
+ function makeDateFromStringAndFormat(string, format) {
434
+ var datePartArray = [0, 0, 1, 0, 0, 0, 0],
435
+ config = {
436
+ tzh : 0, // timezone hour offset
437
+ tzm : 0 // timezone minute offset
438
+ },
439
+ tokens = format.match(formattingTokens),
440
+ i, parsedInput;
441
+
442
+ for (i = 0; i < tokens.length; i++) {
443
+ parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
444
+ string = string.replace(getParseRegexForToken(tokens[i]), '');
445
+ addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config);
446
+ }
447
+ // handle am pm
448
+ if (config.isPm && datePartArray[3] < 12) {
449
+ datePartArray[3] += 12;
450
+ }
451
+ // if is 12 am, change hours to 0
452
+ if (config.isPm === false && datePartArray[3] === 12) {
453
+ datePartArray[3] = 0;
454
+ }
455
+ // handle timezone
456
+ datePartArray[3] += config.tzh;
457
+ datePartArray[4] += config.tzm;
458
+ // return
459
+ return config.isUTC ? new Date(Date.UTC.apply({}, datePartArray)) : dateFromArray(datePartArray);
460
+ }
461
+
462
+ // compare two arrays, return the number of differences
463
+ function compareArrays(array1, array2) {
464
+ var len = Math.min(array1.length, array2.length),
465
+ lengthDiff = Math.abs(array1.length - array2.length),
466
+ diffs = 0,
467
+ i;
468
+ for (i = 0; i < len; i++) {
469
+ if (~~array1[i] !== ~~array2[i]) {
470
+ diffs++;
471
+ }
472
+ }
473
+ return diffs + lengthDiff;
474
+ }
475
+
476
+ // date from string and array of format strings
477
+ function makeDateFromStringAndArray(string, formats) {
478
+ var output,
479
+ inputParts = string.match(parseMultipleFormatChunker) || [],
480
+ formattedInputParts,
481
+ scoreToBeat = 99,
482
+ i,
483
+ currentDate,
484
+ currentScore;
485
+ for (i = 0; i < formats.length; i++) {
486
+ currentDate = makeDateFromStringAndFormat(string, formats[i]);
487
+ formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || [];
488
+ currentScore = compareArrays(inputParts, formattedInputParts);
489
+ if (currentScore < scoreToBeat) {
490
+ scoreToBeat = currentScore;
491
+ output = currentDate;
492
+ }
493
+ }
494
+ return output;
495
+ }
496
+
497
+ // date from iso format
498
+ function makeDateFromString(string) {
499
+ var format = 'YYYY-MM-DDT',
500
+ i;
501
+ if (isoRegex.exec(string)) {
502
+ for (i = 0; i < 4; i++) {
503
+ if (isoTimes[i][1].exec(string)) {
504
+ format += isoTimes[i][0];
505
+ break;
506
+ }
507
+ }
508
+ return parseTokenTimezone.exec(string) ?
509
+ makeDateFromStringAndFormat(string, format + ' Z') :
510
+ makeDateFromStringAndFormat(string, format);
511
+ }
512
+ return new Date(string);
513
+ }
514
+
515
+ // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
516
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture) {
517
+ var rt = moment.relativeTime[string];
518
+ return (typeof rt === 'function') ?
519
+ rt(number || 1, !!withoutSuffix, string, isFuture) :
520
+ rt.replace(/%d/i, number || 1);
521
+ }
522
+
523
+ function relativeTime(milliseconds, withoutSuffix) {
524
+ var seconds = round(Math.abs(milliseconds) / 1000),
525
+ minutes = round(seconds / 60),
526
+ hours = round(minutes / 60),
527
+ days = round(hours / 24),
528
+ years = round(days / 365),
529
+ args = seconds < 45 && ['s', seconds] ||
530
+ minutes === 1 && ['m'] ||
531
+ minutes < 45 && ['mm', minutes] ||
532
+ hours === 1 && ['h'] ||
533
+ hours < 22 && ['hh', hours] ||
534
+ days === 1 && ['d'] ||
535
+ days <= 25 && ['dd', days] ||
536
+ days <= 45 && ['M'] ||
537
+ days < 345 && ['MM', round(days / 30)] ||
538
+ years === 1 && ['y'] || ['yy', years];
539
+ args[2] = withoutSuffix;
540
+ args[3] = milliseconds > 0;
541
+ return substituteTimeAgo.apply({}, args);
542
+ }
543
+
544
+ moment = function (input, format) {
545
+ if (input === null || input === '') {
546
+ return null;
547
+ }
548
+ var date,
549
+ matched,
550
+ isUTC;
551
+ // parse Moment object
552
+ if (moment.isMoment(input)) {
553
+ date = new Date(+input._d);
554
+ isUTC = input._isUTC;
555
+ // parse string and format
556
+ } else if (format) {
557
+ if (isArray(format)) {
558
+ date = makeDateFromStringAndArray(input, format);
559
+ } else {
560
+ date = makeDateFromStringAndFormat(input, format);
561
+ }
562
+ // evaluate it as a JSON-encoded date
563
+ } else {
564
+ matched = aspNetJsonRegex.exec(input);
565
+ date = input === undefined ? new Date() :
566
+ matched ? new Date(+matched[1]) :
567
+ input instanceof Date ? input :
568
+ isArray(input) ? dateFromArray(input) :
569
+ typeof input === 'string' ? makeDateFromString(input) :
570
+ new Date(input);
571
+ }
572
+ return new Moment(date, isUTC);
573
+ };
574
+
575
+ // creating with utc
576
+ moment.utc = function (input, format) {
577
+ if (isArray(input)) {
578
+ return new Moment(new Date(Date.UTC.apply({}, input)), true);
579
+ }
580
+ return (format && input) ?
581
+ moment(input + ' +0000', format + ' Z').utc() :
582
+ moment(input && !parseTokenTimezone.exec(input) ? input + '+0000' : input).utc();
583
+ };
584
+
585
+ // creating with unix timestamp (in seconds)
586
+ moment.unix = function (input) {
587
+ return moment(input * 1000);
588
+ };
589
+
590
+ // duration
591
+ moment.duration = function (input, key) {
592
+ var isDuration = moment.isDuration(input),
593
+ isNumber = (typeof input === 'number'),
594
+ duration = (isDuration ? input._data : (isNumber ? {} : input));
595
+
596
+ if (isNumber) {
597
+ if (key) {
598
+ duration[key] = input;
599
+ } else {
600
+ duration.milliseconds = input;
601
+ }
602
+ }
603
+
604
+ return new Duration(duration);
605
+ };
606
+
607
+ // humanizeDuration
608
+ // This method is deprecated in favor of the new Duration object. Please
609
+ // see the moment.duration method.
610
+ moment.humanizeDuration = function (num, type, withSuffix) {
611
+ return moment.duration(num, type === true ? null : type).humanize(type === true ? true : withSuffix);
612
+ };
613
+
614
+ // version number
615
+ moment.version = VERSION;
616
+
617
+ // default format
618
+ moment.defaultFormat = isoFormat;
619
+
620
+ // language switching and caching
621
+ moment.lang = function (key, values) {
622
+ var i, req,
623
+ parse = [];
624
+ if (!key) {
625
+ return currentLanguage;
626
+ }
627
+ if (values) {
628
+ for (i = 0; i < 12; i++) {
629
+ parse[i] = new RegExp('^' + values.months[i] + '|^' + values.monthsShort[i].replace('.', ''), 'i');
630
+ }
631
+ values.monthsParse = values.monthsParse || parse;
632
+ languages[key] = values;
633
+ }
634
+ if (languages[key]) {
635
+ for (i = 0; i < langConfigProperties.length; i++) {
636
+ moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]] ||
637
+ languages.en[langConfigProperties[i]];
638
+ }
639
+ currentLanguage = key;
640
+ } else {
641
+ if (hasModule) {
642
+ req = require('./lang/' + key);
643
+ moment.lang(key, req);
644
+ }
645
+ }
646
+ };
647
+
648
+ // set default language
649
+ moment.lang('en', {
650
+ months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
651
+ monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
652
+ weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
653
+ weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
654
+ longDateFormat : {
655
+ LT : "h:mm A",
656
+ L : "MM/DD/YYYY",
657
+ LL : "MMMM D YYYY",
658
+ LLL : "MMMM D YYYY LT",
659
+ LLLL : "dddd, MMMM D YYYY LT"
660
+ },
661
+ meridiem : false,
662
+ calendar : {
663
+ sameDay : '[Today at] LT',
664
+ nextDay : '[Tomorrow at] LT',
665
+ nextWeek : 'dddd [at] LT',
666
+ lastDay : '[Yesterday at] LT',
667
+ lastWeek : '[last] dddd [at] LT',
668
+ sameElse : 'L'
669
+ },
670
+ relativeTime : {
671
+ future : "in %s",
672
+ past : "%s ago",
673
+ s : "a few seconds",
674
+ m : "a minute",
675
+ mm : "%d minutes",
676
+ h : "an hour",
677
+ hh : "%d hours",
678
+ d : "a day",
679
+ dd : "%d days",
680
+ M : "a month",
681
+ MM : "%d months",
682
+ y : "a year",
683
+ yy : "%d years"
684
+ },
685
+ ordinal : function (number) {
686
+ var b = number % 10;
687
+ return (~~ (number % 100 / 10) === 1) ? 'th' :
688
+ (b === 1) ? 'st' :
689
+ (b === 2) ? 'nd' :
690
+ (b === 3) ? 'rd' : 'th';
691
+ }
692
+ });
693
+
694
+ // compare moment object
695
+ moment.isMoment = function (obj) {
696
+ return obj instanceof Moment;
697
+ };
698
+
699
+ // for typechecking Duration objects
700
+ moment.isDuration = function (obj) {
701
+ return obj instanceof Duration;
702
+ };
703
+
704
+ // shortcut for prototype
705
+ moment.fn = Moment.prototype = {
706
+
707
+ clone : function () {
708
+ return moment(this);
709
+ },
710
+
711
+ valueOf : function () {
712
+ return +this._d;
713
+ },
714
+
715
+ unix : function () {
716
+ return Math.floor(+this._d / 1000);
717
+ },
718
+
719
+ toString : function () {
720
+ return this._d.toString();
721
+ },
722
+
723
+ toDate : function () {
724
+ return this._d;
725
+ },
726
+
727
+ utc : function () {
728
+ this._isUTC = true;
729
+ return this;
730
+ },
731
+
732
+ local : function () {
733
+ this._isUTC = false;
734
+ return this;
735
+ },
736
+
737
+ format : function (inputString) {
738
+ return formatMoment(this, inputString ? inputString : moment.defaultFormat);
739
+ },
740
+
741
+ add : function (input, val) {
742
+ var dur = val ? moment.duration(+val, input) : moment.duration(input);
743
+ addOrSubtractDurationFromMoment(this, dur, 1);
744
+ return this;
745
+ },
746
+
747
+ subtract : function (input, val) {
748
+ var dur = val ? moment.duration(+val, input) : moment.duration(input);
749
+ addOrSubtractDurationFromMoment(this, dur, -1);
750
+ return this;
751
+ },
752
+
753
+ diff : function (input, val, asFloat) {
754
+ var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(),
755
+ zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
756
+ diff = this._d - inputMoment._d - zoneDiff,
757
+ year = this.year() - inputMoment.year(),
758
+ month = this.month() - inputMoment.month(),
759
+ date = this.date() - inputMoment.date(),
760
+ output;
761
+ if (val === 'months') {
762
+ output = year * 12 + month + date / 30;
763
+ } else if (val === 'years') {
764
+ output = year + (month + date / 30) / 12;
765
+ } else {
766
+ output = val === 'seconds' ? diff / 1e3 : // 1000
767
+ val === 'minutes' ? diff / 6e4 : // 1000 * 60
768
+ val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
769
+ val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
770
+ val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
771
+ diff;
772
+ }
773
+ return asFloat ? output : round(output);
774
+ },
775
+
776
+ from : function (time, withoutSuffix) {
777
+ return moment.duration(this.diff(time)).humanize(!withoutSuffix);
778
+ },
779
+
780
+ fromNow : function (withoutSuffix) {
781
+ return this.from(moment(), withoutSuffix);
782
+ },
783
+
784
+ calendar : function () {
785
+ var diff = this.diff(moment().sod(), 'days', true),
786
+ calendar = moment.calendar,
787
+ allElse = calendar.sameElse,
788
+ format = diff < -6 ? allElse :
789
+ diff < -1 ? calendar.lastWeek :
790
+ diff < 0 ? calendar.lastDay :
791
+ diff < 1 ? calendar.sameDay :
792
+ diff < 2 ? calendar.nextDay :
793
+ diff < 7 ? calendar.nextWeek : allElse;
794
+ return this.format(typeof format === 'function' ? format.apply(this) : format);
795
+ },
796
+
797
+ isLeapYear : function () {
798
+ var year = this.year();
799
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
800
+ },
801
+
802
+ isDST : function () {
803
+ return (this.zone() < moment([this.year()]).zone() ||
804
+ this.zone() < moment([this.year(), 5]).zone());
805
+ },
806
+
807
+ day : function (input) {
808
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
809
+ return input == null ? day :
810
+ this.add({ d : input - day });
811
+ },
812
+
813
+ sod: function () {
814
+ return moment(this)
815
+ .hours(0)
816
+ .minutes(0)
817
+ .seconds(0)
818
+ .milliseconds(0);
819
+ },
820
+
821
+ eod: function () {
822
+ // end of day = start of day plus 1 day, minus 1 millisecond
823
+ return this.sod().add({
824
+ d : 1,
825
+ ms : -1
826
+ });
827
+ },
828
+
829
+ zone : function () {
830
+ return this._isUTC ? 0 : this._d.getTimezoneOffset();
831
+ },
832
+
833
+ daysInMonth : function () {
834
+ return moment(this).month(this.month() + 1).date(0).date();
835
+ }
836
+ };
837
+
838
+ // helper for adding shortcuts
839
+ function makeGetterAndSetter(name, key) {
840
+ moment.fn[name] = function (input) {
841
+ var utc = this._isUTC ? 'UTC' : '';
842
+ if (input != null) {
843
+ this._d['set' + utc + key](input);
844
+ return this;
845
+ } else {
846
+ return this._d['get' + utc + key]();
847
+ }
848
+ };
849
+ }
850
+
851
+ // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
852
+ for (i = 0; i < proxyGettersAndSetters.length; i ++) {
853
+ makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase(), proxyGettersAndSetters[i]);
854
+ }
855
+
856
+ // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
857
+ makeGetterAndSetter('year', 'FullYear');
858
+
859
+ moment.duration.fn = Duration.prototype = {
860
+ weeks : function () {
861
+ return absRound(this.days() / 7);
862
+ },
863
+
864
+ valueOf : function () {
865
+ return this._milliseconds +
866
+ this._days * 864e5 +
867
+ this._months * 2592e6;
868
+ },
869
+
870
+ humanize : function (withSuffix) {
871
+ var difference = +this,
872
+ rel = moment.relativeTime,
873
+ output = relativeTime(difference, !withSuffix);
874
+
875
+ if (withSuffix) {
876
+ output = (difference <= 0 ? rel.past : rel.future).replace(/%s/i, output);
877
+ }
878
+
879
+ return output;
880
+ }
881
+ };
882
+
883
+ function makeDurationGetter(name) {
884
+ moment.duration.fn[name] = function () {
885
+ return this._data[name];
886
+ };
887
+ }
888
+
889
+ function makeDurationAsGetter(name, factor) {
890
+ moment.duration.fn['as' + name] = function () {
891
+ return +this / factor;
892
+ };
893
+ }
894
+
895
+ for (i in unitMillisecondFactors) {
896
+ if (unitMillisecondFactors.hasOwnProperty(i)) {
897
+ makeDurationAsGetter(i, unitMillisecondFactors[i]);
898
+ makeDurationGetter(i.toLowerCase());
899
+ }
900
+ }
901
+
902
+ makeDurationAsGetter('Weeks', 6048e5);
903
+
904
+ // CommonJS module is defined
905
+ if (hasModule) {
906
+ module.exports = moment;
907
+ }
908
+ /*global ender:false */
909
+ if (typeof window !== 'undefined' && typeof ender === 'undefined') {
910
+ window.moment = moment;
911
+ }
912
+ /*global define:false */
913
+ if (typeof define === "function" && define.amd) {
914
+ define("moment", [], function () {
915
+ return moment;
916
+ });
917
+ }
918
+ })(Date);