cmsimple 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);