local_time 0.1.0 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d0bfe22e485d89d3b8b8ef64db29d82d4d4f518c
4
- data.tar.gz: 7d662d650e07542e16b13b98315ce589992bf397
3
+ metadata.gz: 0d42dfef630d09374cd897d5a842566191ff07cd
4
+ data.tar.gz: 671f048d37ba09ade8df1e01dd8c4bb36f5ccfab
5
5
  SHA512:
6
- metadata.gz: 840814649a2e4c03f7b8b9592ff696c7d5b7516a088a270fe2bdb4fb96e1a29221d455c31bbc31fdaa2a2dc0a38fe3718144c4c2dfe8ced9cbbc1d7ee76f425b
7
- data.tar.gz: 2ed6f4bd924c469c23fd1134a53e4818ac1f5de1fd9cf9060859726bb47429176a8e5421f07c48d18303502c288ea38ccf74fff70ce55134f2e6b8fc110d23a4
6
+ metadata.gz: 6209af737d470ff029db6233ca5f30e6840e8e74c40db30aca1a8ad9a592dbd705ea2159ff16eb37118946dee8d6f6db1fbfd69d6f129d30b9aab1c3f3a93b18
7
+ data.tar.gz: 26786c11ec81af062927263f55e5f4103532dbdc871d535e0e272a5c95b8a94f6e8979d165154330c3bc2cc0b93ac202f4202546f04258012e75b82d4c1d8ce1
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2013 Javan Makhmali
1
+ Copyright 2014 Javan Makhmali, Basecamp
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,16 +1,19 @@
1
- Local Time is a Rails engine with helpers and JavaScript for displaying times and dates to users in their local time. The helpers render a `<time>` element in UTC and the JavaScript swoops in to convert and format. Because the `<time>` element is only rendered in one timezone, it is ideal for caching.
1
+ Local Time is a Rails engine with helpers and JavaScript for displaying times and dates to users in their local time. The helpers render a `<time>` element and the JavaScript swoops in to convert and format. The helper output is ideal for caching since it's always in UTC time.
2
2
 
3
3
  ---
4
4
 
5
5
  ####Example
6
6
 
7
- Assuming the time zone is EST and `Time.now` is `2013-11-27 18:43:22 -0500`:
7
+ ```ruby
8
+ > comment.created_at
9
+ "Wed, 27 Nov 2013 18:43:22 EST -0500"
10
+ ```
8
11
 
9
12
  ```erb
10
- <%= local_time(Time.now) # index.html.erb %>
13
+ <%= local_time(comment.created_at) %>
11
14
  ```
12
15
 
13
- Renders in UTC time:
16
+ Renders:
14
17
 
15
18
  ```html
16
19
  <time data-format="%B %e, %Y %l:%M%P"
@@ -18,12 +21,13 @@ Renders in UTC time:
18
21
  datetime="2013-11-27T23:43:22Z">November 27, 2013 11:43pm</time>
19
22
  ```
20
23
 
21
- Then immediately converts to local time and strftime formats with JavaScript:
24
+ When the DOM loads, the content is immediately replaced with a local, formatted time:
22
25
 
23
26
  ```html
24
27
  <time data-format="%B %e, %Y %l:%M%P"
25
28
  data-local="time"
26
29
  datetime="2013-11-27T23:43:22Z"
30
+ title="November 27, 2013 6:43pm EDT"
27
31
  data-localized="true">November 27, 2013 6:43pm</time>
28
32
  ```
29
33
 
@@ -32,14 +36,36 @@ Then immediately converts to local time and strftime formats with JavaScript:
32
36
  #### Time and date helpers
33
37
 
34
38
  ```erb
35
- Pass a time and an optional strftime format (default format shown here)
36
- <%= local_time(time, format: '%B %e, %Y %l:%M%P') %>
39
+ <%= local_time(time) %>
40
+ ```
41
+
42
+ Format with a strftime string (default format shown here)
43
+
44
+ ```erb
45
+ <%= local_time(time, '%B %e, %Y %l:%M%P') %>
46
+ ```
47
+
48
+ Alias for `local_time` with a month-formatted default
37
49
 
38
- Alias for local_time with a month-formatted default
39
- <%= local_date(time, format: '%B %e, %Y') %>
50
+ ```erb
51
+ <%= local_date(time, '%B %e, %Y') %>
40
52
  ```
41
53
 
42
- Note: The included strftime JavaScript implementation is not 100% complete. It supports the following directives: `%a %A %b %B %c %d %e %H %I %l %m %M %p %P %S %w %y %Y`
54
+ To set attributes on the time tag, pass a hash as the second argument with a `:format` key and your attributes.
55
+
56
+ ```erb
57
+ <%= local_time(time, format: '%B %e, %Y %l:%M%P', class: 'my-time') %>
58
+ ```
59
+
60
+ To use a strftime format already defined in your app, pass a symbol as the format.
61
+
62
+ ```erb
63
+ <%= local_time(date, :long) %>
64
+ ```
65
+
66
+ `I18n.t("time.formats.#{format}")`, `I18n.t("date.formats.#{format}")`, `Time::DATE_FORMATS[format]`, and `Date::DATE_FORMATS[format]` will be scanned (in that order) for your format.
67
+
68
+ Note: The included strftime JavaScript implementation is not 100% complete. It supports the following directives: `%a %A %b %B %c %d %e %H %I %l %m %M %p %P %S %w %y %Y %Z`
43
69
 
44
70
  #### Time ago helper
45
71
 
@@ -47,7 +73,9 @@ Note: The included strftime JavaScript implementation is not 100% complete. It s
47
73
  <%= local_time_ago(time) %>
48
74
  ```
49
75
 
50
- Displays the relative amount of time passed. With age, the descriptions transition from specific quantities to general dates. The `<time>` elements are updated every 60 seconds. Examples (in quotes):
76
+ Displays the relative amount of time passed. With age, the descriptions transition from {quantity of seconds, minutes, or hours} to {date + time} to {date}. The `<time>` elements are updated every 60 seconds.
77
+
78
+ Examples (in quotes):
51
79
 
52
80
  * Recent: "a second ago", "32 seconds ago", "an hour ago", "14 hours ago"
53
81
  * Yesterday: "yesterday at 5:22pm"
@@ -55,6 +83,22 @@ Displays the relative amount of time passed. With age, the descriptions transiti
55
83
  * This year: "on Nov 17"
56
84
  * Last year: "on Jan 31, 2012"
57
85
 
86
+ #### Relative time helper
87
+
88
+ Preset time and date formats that vary with age. The available types are `date`, `time-ago`, `time-or-date`, and `weekday`. Like the `local_time` helper, `:type` can be passed a string or in an options hash.
89
+
90
+ ```erb
91
+ <%= local_relative_time(time, 'weekday') %>
92
+ <%= local_relative_time(time, type: 'time-or-date') %>
93
+ ```
94
+
95
+ **Available `:type` options**
96
+
97
+ * `date` Inlcudes the year unless it's current. "Apr 11" or "Apr 11, 2013"
98
+ * `time-ago` See above. `local_time_ago` calls `local_relative_time` with this `:type` option.
99
+ * `time-or-date` Displays the time if it's todday. Displays time otherwise. "3:26pm" or "Apr 11"
100
+ * `weekday` Displays "Today", "Yesterday", or the weekday (e.g. Wednesday) if the time is within a week of today.
101
+
58
102
  #### Installation
59
103
 
60
104
  1. Add `gem 'local_time'` to your Gemfile.
@@ -65,8 +109,41 @@ Displays the relative amount of time passed. With age, the descriptions transiti
65
109
 
66
110
  The included JavaScript does not depend on any frameworks or libraries, and listens for a `DOMContentLoaded` event to run initially. It also listens on `document` for `page:update` if you're using Turbolinks and `ajaxSuccess` if you're using jQuery. This should catch most cases where new `<time>` elements have been added to the DOM and process them automatically. If you're adding new elements in another context, trigger `time:elapse` to process them.
67
111
 
112
+ #### JavaScript API
113
+
114
+ `relativeDate`, `relativeTimeAgo`, `relativeTimeOrDate`, `relativeWeekday`, `run`, and `strftime` methods are available on the global `LocalTime` object.
115
+
116
+ ```js
117
+ > LocalTime.relativeTimeAgo(new Date(new Date - 60 * 1000 * 5))
118
+ "5 minutes ago"
119
+
120
+ // Process <time> tags. Equivalent to dispatching a "time:elapse" Event.
121
+ > LocalTime.run()
122
+
123
+ > LocalTime.strftime(new Date, "%B %e, %Y %l:%M%P")
124
+ "February 9, 2014 12:55pm"
125
+ ```
126
+
68
127
  #### Version History
69
128
 
129
+ **1.0.0** (April 12, 2014)
130
+
131
+ * Added `local_relative_time` helper with several built in types
132
+ * Allow `:format` (and `:type`) option as a bare string or value in hash
133
+ * Added `relativeDate`, `relativeTimeOrDate`, `relativeWeekday` and `run` to the API
134
+ * Dropped ineffective `popstate` event listener
135
+ * Now in use at [Basecamp](https://basecamp.com/)
136
+
137
+ **0.3.0** (February 9, 2014)
138
+
139
+ * Allow :format option lookup in I18n or DATE_FORMATS hashes [Paul Dobbins]
140
+ * Expose public API to JavaScript helpers
141
+
142
+ **0.2.0** (December 10, 2013)
143
+
144
+ * Prefer `textContent` over `innerText` for Firefox compatibility
145
+ * Added `options` argument to `local_time_ago` helper
146
+
70
147
  **0.1.0** (November 29, 2013)
71
148
 
72
149
  * Initial release.
@@ -30,7 +30,7 @@ strftime = (time, formatString) ->
30
30
  minute = time.getMinutes()
31
31
  second = time.getSeconds()
32
32
 
33
- formatString.replace /%([%aAbBcdeHIlmMpPSwyY])/g, ([match, modifier]) ->
33
+ formatString.replace /%([%aAbBcdeHIlmMpPSwyYZ])/g, ([match, modifier]) ->
34
34
  switch modifier
35
35
  when '%' then '%'
36
36
  when 'a' then weekdays[day].slice 0, 3
@@ -51,6 +51,7 @@ strftime = (time, formatString) ->
51
51
  when 'w' then day
52
52
  when 'y' then pad year % 100
53
53
  when 'Y' then year
54
+ when 'Z' then time.toString().match(/\((\w+)\)$/)?[1] ? ''
54
55
 
55
56
 
56
57
  class CalendarDate
@@ -67,6 +68,16 @@ class CalendarDate
67
68
  @year = @date.getUTCFullYear()
68
69
  @month = @date.getUTCMonth() + 1
69
70
  @day = @date.getUTCDate()
71
+ @value = @date.getTime()
72
+
73
+ equals: (calendarDate) ->
74
+ calendarDate?.value is @value
75
+
76
+ is: (calendarDate) ->
77
+ @equals calendarDate
78
+
79
+ isToday: ->
80
+ @is @constructor.today()
70
81
 
71
82
  occursOnSameYearAs: (date) ->
72
83
  @year is date?.year
@@ -82,10 +93,7 @@ class CalendarDate
82
93
  @constructor.today().daysSince @
83
94
 
84
95
 
85
- class RelativeTimeAgo
86
- @generate: (date) ->
87
- new this(date).toString()
88
-
96
+ class RelativeTime
89
97
  constructor: (@date) ->
90
98
  @calendarDate = CalendarDate.fromDate @date
91
99
 
@@ -103,6 +111,12 @@ class RelativeTimeAgo
103
111
  else
104
112
  "on #{@formatDate()}"
105
113
 
114
+ toTimeOrDateString: ->
115
+ if @calendarDate.isToday()
116
+ @formatTime()
117
+ else
118
+ @formatDate()
119
+
106
120
  timeElapsed: ->
107
121
  ms = new Date().getTime() - @date.getTime()
108
122
  sec = Math.round ms / 1000
@@ -146,6 +160,19 @@ class RelativeTimeAgo
146
160
  formatTime: ->
147
161
  strftime @date, '%l:%M%P'
148
162
 
163
+ relativeDate = (date) ->
164
+ new RelativeTime(date).formatDate()
165
+
166
+ relativeTimeAgo = (date) ->
167
+ new RelativeTime(date).toString()
168
+
169
+ relativeTimeOrDate = (date) ->
170
+ new RelativeTime(date).toTimeOrDateString()
171
+
172
+ relativeWeekday = (date) ->
173
+ if day = new RelativeTime(date).relativeWeekday()
174
+ day.charAt(0).toUpperCase() + day.substring(1)
175
+
149
176
 
150
177
  domLoaded = false
151
178
 
@@ -157,10 +184,6 @@ update = (callback) ->
157
184
  if Turbolinks?.supported
158
185
  document.addEventListener "page:update", callback
159
186
  else
160
- setTimeout ->
161
- window.addEventListener "popstate", callback
162
- , 1
163
-
164
187
  jQuery?(document).on "ajaxSuccess", (event, xhr) ->
165
188
  callback() if jQuery.trim xhr.responseText
166
189
 
@@ -171,6 +194,7 @@ process = (selector, callback) ->
171
194
 
172
195
  document.addEventListener "DOMContentLoaded", ->
173
196
  domLoaded = true
197
+ textProperty = if "textContent" of document.body then "textContent" else "innerText"
174
198
 
175
199
  process "time[data-local]:not([data-localized])", (element) ->
176
200
  datetime = element.getAttribute "datetime"
@@ -180,16 +204,30 @@ document.addEventListener "DOMContentLoaded", ->
180
204
  time = new Date Date.parse datetime
181
205
  return if isNaN time
182
206
 
183
- element.innerText =
207
+ unless element.hasAttribute("title")
208
+ element.setAttribute "title", strftime(time, "%B %e, %Y at %l:%M%P %Z")
209
+
210
+ element[textProperty] =
184
211
  switch local
212
+ when "date"
213
+ element.setAttribute "data-localized", true
214
+ relativeDate time
185
215
  when "time"
186
216
  element.setAttribute "data-localized", true
187
217
  strftime time, format
188
218
  when "time-ago"
189
- RelativeTimeAgo.generate time
219
+ relativeTimeAgo time
220
+ when "time-or-date"
221
+ relativeTimeOrDate time
222
+ when "weekday"
223
+ relativeWeekday(time) ? ""
224
+
225
+ run = ->
226
+ event = document.createEvent "Events"
227
+ event.initEvent "time:elapse", true, true
228
+ document.dispatchEvent event
229
+
230
+ setInterval run, 60 * 1000
190
231
 
191
- setInterval ->
192
- event = document.createEvent "Events"
193
- event.initEvent "time:elapse", true, true
194
- document.dispatchEvent event
195
- , 60 * 1000
232
+ # Public API
233
+ @LocalTime = {relativeDate, relativeTimeAgo, relativeTimeOrDate, relativeWeekday, run, strftime}
@@ -1,7 +1,11 @@
1
1
  module LocalTimeHelper
2
- def local_time(time, options = {})
3
- time = utc_time(time)
4
- format = options.delete(:format).presence || '%B %e, %Y %l:%M%P'
2
+ DEFAULT_FORMAT = '%B %e, %Y %l:%M%P'
3
+
4
+ def local_time(time, options = nil)
5
+ time = utc_time(time)
6
+
7
+ options, format = extract_options_and_value(options, :format)
8
+ format = find_time_format(format)
5
9
 
6
10
  options[:data] ||= {}
7
11
  options[:data].merge! local: :time, format: format
@@ -9,14 +13,26 @@ module LocalTimeHelper
9
13
  time_tag time, time.strftime(format), options
10
14
  end
11
15
 
12
- def local_date(time, options = {})
13
- options.reverse_merge! format: '%B %e, %Y'
16
+ def local_date(time, options = nil)
17
+ options, format = extract_options_and_value(options, :format)
18
+ options[:format] = format || '%B %e, %Y'
14
19
  local_time time, options
15
20
  end
16
21
 
17
- def local_time_ago(time)
22
+ def local_relative_time(time, options = nil)
18
23
  time = utc_time(time)
19
- time_tag time, time.strftime('%B %e, %Y %l:%M%P'), data: { local: 'time-ago' }
24
+ options, type = extract_options_and_value(options, :type)
25
+
26
+ options[:data] ||= {}
27
+ options[:data].merge! local: type
28
+
29
+ time_tag time, time.strftime(DEFAULT_FORMAT), options
30
+ end
31
+
32
+ def local_time_ago(time, options = nil)
33
+ options, type = extract_options_and_value(options, :type)
34
+ options[:type] = 'time-ago'
35
+ local_relative_time time, options
20
36
  end
21
37
 
22
38
  def utc_time(time_or_date)
@@ -26,4 +42,31 @@ module LocalTimeHelper
26
42
  time_or_date.to_time.utc
27
43
  end
28
44
  end
45
+
46
+ private
47
+ def find_time_format(format)
48
+ if format.is_a?(Symbol)
49
+ if (i18n_format = I18n.t("time.formats.#{format}", default: [:"date.formats.#{format}", ''])).present?
50
+ i18n_format
51
+ elsif (date_format = Time::DATE_FORMATS[format] || Date::DATE_FORMATS[format])
52
+ date_format.is_a?(Proc) ? DEFAULT_FORMAT : date_format
53
+ else
54
+ DEFAULT_FORMAT
55
+ end
56
+ else
57
+ format.presence || DEFAULT_FORMAT
58
+ end
59
+ end
60
+
61
+ def extract_options_and_value(options, value_key = nil)
62
+ case options
63
+ when Hash
64
+ value = options.delete(value_key)
65
+ [ options, value ]
66
+ when NilClass
67
+ [ {} ]
68
+ else
69
+ [ {}, options ]
70
+ end
71
+ end
29
72
  end
@@ -1,16 +1,30 @@
1
1
  require_relative '../../app/helpers/local_time_helper'
2
2
  require 'active_support/all'
3
3
  require 'action_view'
4
+
4
5
  require 'minitest/autorun'
6
+ begin
7
+ # 2.0.0
8
+ class TestCase < MiniTest::Test; end
9
+ rescue NameError
10
+ # 1.9.3
11
+ class TestCase < MiniTest::Unit::TestCase; end
12
+ end
5
13
 
14
+ I18n.enforce_available_locales = false
6
15
 
7
- class LocalTimeHelperTest < Minitest::Test
16
+ class LocalTimeHelperTest < TestCase
8
17
  include ActionView::Helpers::DateHelper, ActionView::Helpers::TagHelper
9
18
  include LocalTimeHelper
10
19
 
11
20
  def setup
12
21
  @original_zone = Time.zone
13
22
  Time.zone = ActiveSupport::TimeZone["Central Time (US & Canada)"]
23
+ I18n.backend.store_translations(:en, {
24
+ time: { formats: { simple_time: "%b %e" } },
25
+ date: { formats: { simple_date: "%b %e" } } })
26
+ Time::DATE_FORMATS[:time_formats_simple_time] = '%b %e'
27
+ Date::DATE_FORMATS[:date_formats_simple_date] = '%b %e'
14
28
 
15
29
  @date = "2013-11-21"
16
30
  @time = Time.zone.parse(@date)
@@ -45,6 +59,32 @@ class LocalTimeHelperTest < Minitest::Test
45
59
  assert_equal expected, local_time(@time, format: '%b %e')
46
60
  end
47
61
 
62
+ def test_local_time_with_format_as_string
63
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
64
+ assert_equal expected, local_time(@time, '%b %e')
65
+ end
66
+
67
+ def test_local_time_with_i18n_format
68
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
69
+ assert_equal expected, local_time(@time, format: :simple_time)
70
+ end
71
+
72
+ def test_local_time_with_date_formats_format
73
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
74
+ assert_equal expected, local_time(@time, format: :time_formats_simple_time)
75
+ end
76
+
77
+ def test_local_time_with_missing_i18n_and_date_formats_format
78
+ expected = %Q(<time data-format="%B %e, %Y %l:%M%P" data-local="time" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
79
+ assert_equal expected, local_time(@time, format: :missing_format)
80
+ end
81
+
82
+ def test_local_time_with_date_formats_proc_format
83
+ Time::DATE_FORMATS[:proc] = proc { |time| "nope" }
84
+ expected = %Q(<time data-format="%B %e, %Y %l:%M%P" data-local="time" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
85
+ assert_equal expected, local_time(@time, format: :proc)
86
+ end
87
+
48
88
  def test_local_time_with_options
49
89
  expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}" style="display:none">Nov 21</time>)
50
90
  assert_equal expected, local_time(@time, format: '%b %e', style: 'display:none')
@@ -58,11 +98,46 @@ class LocalTimeHelperTest < Minitest::Test
58
98
 
59
99
  def test_local_date_with_format
60
100
  expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
61
- assert_equal expected, local_date(@time, format: '%b %e')
101
+ assert_equal expected, local_date(@time.to_date, format: '%b %e')
102
+ end
103
+
104
+ def test_local_date_with_format_as_string
105
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
106
+ assert_equal expected, local_date(@time.to_date, '%b %e')
107
+ end
108
+
109
+ def test_local_date_with_i18n_format
110
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
111
+ assert_equal expected, local_date(@time.to_date, format: :simple_date)
112
+ end
113
+
114
+ def test_local_date_with_date_formats_format
115
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
116
+ assert_equal expected, local_date(@time.to_date, format: :date_formats_simple_date)
117
+ end
118
+
119
+ def test_local_date_with_missing_i18n_and_date_formats_format
120
+ expected = %Q(<time data-format="%B %e, %Y %l:%M%P" data-local="time" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
121
+ assert_equal expected, local_date(@time.to_date, format: :missing_date_format)
62
122
  end
63
123
 
64
124
  def test_local_time_ago
65
125
  expected = %Q(<time data-local="time-ago" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
66
126
  assert_equal expected, local_time_ago(@time)
67
127
  end
128
+
129
+ def test_local_time_ago_with_options
130
+ expected = %Q(<time class="date-time" data-local="time-ago" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
131
+ assert_equal expected, local_time_ago(@time, class: "date-time")
132
+ end
133
+
134
+ def test_relative_time
135
+ expected = %Q(<time data-local="time-or-date" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
136
+ assert_equal expected, local_relative_time(@time, type: "time-or-date")
137
+ end
138
+
139
+ def test_local_time_ago_with_type_as_string
140
+ expected = %Q(<time data-local="time-or-date" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
141
+ assert_equal expected, local_relative_time(@time, "time-or-date")
142
+ end
68
143
  end
@@ -0,0 +1,36 @@
1
+ #= require vendor/qunit
2
+ #= require vendor/moment
3
+ #= require vendor/sinon-timers
4
+ #= require local_time
5
+
6
+ #= require_self
7
+ #= require_directory .
8
+
9
+ @addTimeEl = ({format, type, datetime} = {}) ->
10
+ format ?= "%Y"
11
+ type ?= "time"
12
+ datetime ?= "2013-11-12T12:13:00Z"
13
+
14
+ el = document.createElement "time"
15
+ el.setAttribute "data-local", type
16
+ el.setAttribute "data-format", format
17
+ el.setAttribute "datetime", datetime
18
+ document.body.appendChild el
19
+ el
20
+
21
+ @setText = (el, text) ->
22
+ textProperty = if "textContent" of el then "textContent" else "innerText"
23
+ el[textProperty] = text
24
+
25
+ @getText = (el) ->
26
+ # innerHTML works in all browsers so using it ensures we're
27
+ # reading the text content, not a potentially arbitrary property.
28
+ el.innerHTML
29
+
30
+ @triggerEvent = (name, el = document) ->
31
+ event = document.createEvent "Events"
32
+ event.initEvent name, true, true
33
+ el.dispatchEvent event
34
+
35
+ @run = ->
36
+ triggerEvent "time:elapse"
@@ -8,10 +8,10 @@ test "date", ->
8
8
  assertLocalized "date", "date"
9
9
 
10
10
  test "unparseable time", ->
11
- el = addTimeEl "%Y", ":("
12
- el.innerText = "2013"
11
+ el = addTimeEl format: "%Y", datetime: ":("
12
+ setText el, "2013"
13
13
  run()
14
- equal el.innerText, "2013"
14
+ equal getText(el), "2013"
15
15
 
16
16
 
17
17
  assertLocalized = (id, type = "time") ->
@@ -26,7 +26,7 @@ assertLocalized = (id, type = "time") ->
26
26
  el = document.getElementById id
27
27
 
28
28
  ok datetime = el.getAttribute "datetime"
29
- ok local = el.innerText
29
+ ok local = getText el
30
30
 
31
31
  datetimeParsed = moment datetime
32
32
  localParsed = moment local, momentFormat
@@ -3,28 +3,23 @@ module "page events"
3
3
  test "document DOMContentLoaded", ->
4
4
  el = addTimeEl()
5
5
  triggerEvent "DOMContentLoaded"
6
- ok el.innerText
6
+ ok getText el
7
7
 
8
8
  test "document time:elapse", ->
9
9
  el = addTimeEl()
10
10
  triggerEvent "time:elapse"
11
- ok el.innerText
12
-
13
- test "window popstate", ->
14
- el = addTimeEl()
15
- triggerEvent "popstate", window
16
- ok el.innerText
11
+ ok getText el
17
12
 
18
13
  test "document page:update with Turbolinks on", ->
19
14
  el = addTimeEl()
20
15
  triggerEvent "page:update"
21
- ok not el.innerText
16
+ ok not getText el
22
17
 
23
18
  original = window.Turbolinks
24
19
  window.Turbolinks = { supported: true }
25
20
 
26
21
  triggerEvent "DOMContentLoaded"
27
22
  triggerEvent "page:update"
28
- ok el.innerText
23
+ ok getText el
29
24
 
30
25
  window.Turbolinks = original
@@ -0,0 +1,11 @@
1
+ module "public API"
2
+
3
+ for name, method of @LocalTime when name isnt "strftime"
4
+ do (name, method) ->
5
+ test "##{name}", ->
6
+ ok method(new Date())
7
+
8
+ {strftime} = @LocalTime
9
+
10
+ test "#strftime", =>
11
+ ok strftime(new Date(), "%Y")
@@ -0,0 +1,65 @@
1
+ module "relative date"
2
+
3
+ test "this year", ->
4
+ now = moment()
5
+ el = addTimeEl type: "date", datetime: now.toISOString()
6
+ run()
7
+
8
+ equal getText(el), now.format("MMM D")
9
+
10
+ test "last year", ->
11
+ before = moment().subtract("years", 1).subtract("days", 1)
12
+ el = addTimeEl type: "date", datetime: before.toISOString()
13
+ run()
14
+
15
+ equal getText(el), before.format("MMM D, YYYY")
16
+
17
+
18
+ module "relative time or date"
19
+
20
+
21
+ test "today", ->
22
+ now = moment()
23
+ el = addTimeEl type: "time-or-date", datetime: now.toISOString()
24
+ run()
25
+
26
+ equal getText(el), now.format("h:mma")
27
+
28
+ test "before today", ->
29
+ before = moment().subtract("days", 1)
30
+ el = addTimeEl type: "time-or-date", datetime: before.toISOString()
31
+ run()
32
+
33
+ equal getText(el), before.format("MMM D")
34
+
35
+
36
+ module "relative weekday"
37
+
38
+
39
+ test "today", ->
40
+ now = moment()
41
+ el = addTimeEl type: "weekday", datetime: now.toISOString()
42
+ run()
43
+
44
+ equal getText(el), "Today"
45
+
46
+ test "yesterday", ->
47
+ yesterday = moment().subtract("days", 1)
48
+ el = addTimeEl type: "weekday", datetime: yesterday.toISOString()
49
+ run()
50
+
51
+ equal getText(el), "Yesterday"
52
+
53
+ test "this week", ->
54
+ recent = moment().subtract("days", 3)
55
+ el = addTimeEl type: "weekday", datetime: recent.toISOString()
56
+ run()
57
+
58
+ equal getText(el), recent.format("dddd")
59
+
60
+ test "before this week", ->
61
+ before = moment().subtract("days", 8)
62
+ el = addTimeEl type: "weekday", datetime: before.toISOString()
63
+ run()
64
+
65
+ equal getText(el), ""