local_time 0.1.0 → 0.3.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: 84f0f9773b1e9bfac34c2e579af56d6c784a8d23
4
+ data.tar.gz: a1606c79f356e6e09b67f5b2adca382e38366a9f
5
5
  SHA512:
6
- metadata.gz: 840814649a2e4c03f7b8b9592ff696c7d5b7516a088a270fe2bdb4fb96e1a29221d455c31bbc31fdaa2a2dc0a38fe3718144c4c2dfe8ced9cbbc1d7ee76f425b
7
- data.tar.gz: 2ed6f4bd924c469c23fd1134a53e4818ac1f5de1fd9cf9060859726bb47429176a8e5421f07c48d18303502c288ea38ccf74fff70ce55134f2e6b8fc110d23a4
6
+ metadata.gz: 88db2bd3c1a77268ef0e8a59a18c81bed59c9f3b837bd3f9d2e555862228ded216dc7a2cf8e2d19a1c06fc262ada3ca319e4b2538eeae3ea826c3ecbe65c113f
7
+ data.tar.gz: 71e7a980c10839bc5e81dda212a9a99f1dd9a5ec68cbd3a082e754126de0dfccad334e3efc28bb01a1c416b71c31bc7bdece4a9c848a2de60e7d771513de9121
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2013 Javan Makhmali
1
+ Copyright 2014 Javan Makhmali
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
@@ -4,13 +4,11 @@ Local Time is a Rails engine with helpers and JavaScript for displaying times an
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`:
8
-
9
7
  ```erb
10
- <%= local_time(Time.now) # index.html.erb %>
8
+ <%= local_time(comment.created_at) # comment.created_at => Wed, 27 Nov 2013 18:43:22 EST -0500 %>
11
9
  ```
12
10
 
13
- Renders in UTC time:
11
+ Renders:
14
12
 
15
13
  ```html
16
14
  <time data-format="%B %e, %Y %l:%M%P"
@@ -18,7 +16,7 @@ Renders in UTC time:
18
16
  datetime="2013-11-27T23:43:22Z">November 27, 2013 11:43pm</time>
19
17
  ```
20
18
 
21
- Then immediately converts to local time and strftime formats with JavaScript:
19
+ When the DOM loads, the content is immediately replaced with a local, formatted time:
22
20
 
23
21
  ```html
24
22
  <time data-format="%B %e, %Y %l:%M%P"
@@ -39,6 +37,13 @@ Alias for local_time with a month-formatted default
39
37
  <%= local_date(time, format: '%B %e, %Y') %>
40
38
  ```
41
39
 
40
+ To use a strftime format already defined in your app, pass a symbol as the format.
41
+ ```erb
42
+ <%= local_time(date, format: :long) %>
43
+ ```
44
+
45
+ `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.
46
+
42
47
  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`
43
48
 
44
49
  #### Time ago helper
@@ -65,8 +70,30 @@ Displays the relative amount of time passed. With age, the descriptions transiti
65
70
 
66
71
  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
72
 
73
+ #### JavaScript API
74
+
75
+ `strftime` and `relativeTimeAgo` are available via the global `LocalTime` object.
76
+
77
+ ```js
78
+ > LocalTime.strftime(new Date, "%B %e, %Y %l:%M%P")
79
+ "February 9, 2014 12:55pm"
80
+
81
+ > LocalTime.relativeTimeAgo(new Date(new Date - 60 * 1000 * 5))
82
+ "5 minutes ago"
83
+ ```
84
+
68
85
  #### Version History
69
86
 
87
+ **0.3.0** (February 9, 2014)
88
+
89
+ * Allow :format option lookup in I18n or DATE_FORMATS hashes [Paul Dobbins]
90
+ * Expose public API to JavaScript helpers
91
+
92
+ **0.2.0** (December 10, 2013)
93
+
94
+ * Prefer `textContent` over `innerText` for Firefox compatibility
95
+ * Added `options` argument to `local_time_ago` helper
96
+
70
97
  **0.1.0** (November 29, 2013)
71
98
 
72
99
  * Initial release.
@@ -83,9 +83,6 @@ class CalendarDate
83
83
 
84
84
 
85
85
  class RelativeTimeAgo
86
- @generate: (date) ->
87
- new this(date).toString()
88
-
89
86
  constructor: (@date) ->
90
87
  @calendarDate = CalendarDate.fromDate @date
91
88
 
@@ -146,6 +143,8 @@ class RelativeTimeAgo
146
143
  formatTime: ->
147
144
  strftime @date, '%l:%M%P'
148
145
 
146
+ relativeTimeAgo = (date) ->
147
+ new RelativeTimeAgo(date).toString()
149
148
 
150
149
  domLoaded = false
151
150
 
@@ -171,6 +170,7 @@ process = (selector, callback) ->
171
170
 
172
171
  document.addEventListener "DOMContentLoaded", ->
173
172
  domLoaded = true
173
+ textProperty = if "textContent" of document.body then "textContent" else "innerText"
174
174
 
175
175
  process "time[data-local]:not([data-localized])", (element) ->
176
176
  datetime = element.getAttribute "datetime"
@@ -180,16 +180,19 @@ document.addEventListener "DOMContentLoaded", ->
180
180
  time = new Date Date.parse datetime
181
181
  return if isNaN time
182
182
 
183
- element.innerText =
183
+ element[textProperty] =
184
184
  switch local
185
185
  when "time"
186
186
  element.setAttribute "data-localized", true
187
187
  strftime time, format
188
188
  when "time-ago"
189
- RelativeTimeAgo.generate time
189
+ relativeTimeAgo time
190
190
 
191
191
  setInterval ->
192
192
  event = document.createEvent "Events"
193
193
  event.initEvent "time:elapse", true, true
194
194
  document.dispatchEvent event
195
195
  , 60 * 1000
196
+
197
+ # Public API
198
+ @LocalTime = {strftime, relativeTimeAgo}
@@ -1,7 +1,9 @@
1
1
  module LocalTimeHelper
2
+ DEFAULT_FORMAT = '%B %e, %Y %l:%M%P'
3
+
2
4
  def local_time(time, options = {})
3
5
  time = utc_time(time)
4
- format = options.delete(:format).presence || '%B %e, %Y %l:%M%P'
6
+ format = time_format(options.delete(:format))
5
7
 
6
8
  options[:data] ||= {}
7
9
  options[:data].merge! local: :time, format: format
@@ -14,9 +16,13 @@ module LocalTimeHelper
14
16
  local_time time, options
15
17
  end
16
18
 
17
- def local_time_ago(time)
19
+ def local_time_ago(time, options = {})
18
20
  time = utc_time(time)
19
- time_tag time, time.strftime('%B %e, %Y %l:%M%P'), data: { local: 'time-ago' }
21
+
22
+ options[:data] ||= {}
23
+ options[:data].merge! local: 'time-ago'
24
+
25
+ time_tag time, time.strftime(DEFAULT_FORMAT), options
20
26
  end
21
27
 
22
28
  def utc_time(time_or_date)
@@ -26,4 +32,19 @@ module LocalTimeHelper
26
32
  time_or_date.to_time.utc
27
33
  end
28
34
  end
35
+
36
+ private
37
+ def time_format(format)
38
+ if format.is_a?(Symbol)
39
+ if (i18n_format = I18n.t("time.formats.#{format}", default: [:"date.formats.#{format}", ''])).present?
40
+ i18n_format
41
+ elsif (date_format = Time::DATE_FORMATS[format] || Date::DATE_FORMATS[format])
42
+ date_format.is_a?(Proc) ? DEFAULT_FORMAT : date_format
43
+ else
44
+ DEFAULT_FORMAT
45
+ end
46
+ else
47
+ format.presence || DEFAULT_FORMAT
48
+ end
49
+ end
29
50
  end
@@ -3,14 +3,20 @@ require 'active_support/all'
3
3
  require 'action_view'
4
4
  require 'minitest/autorun'
5
5
 
6
+ I18n.enforce_available_locales = false
6
7
 
7
- class LocalTimeHelperTest < Minitest::Test
8
+ class LocalTimeHelperTest < MiniTest::Unit::TestCase
8
9
  include ActionView::Helpers::DateHelper, ActionView::Helpers::TagHelper
9
10
  include LocalTimeHelper
10
11
 
11
12
  def setup
12
13
  @original_zone = Time.zone
13
14
  Time.zone = ActiveSupport::TimeZone["Central Time (US & Canada)"]
15
+ I18n.backend.store_translations(:en, {
16
+ time: { formats: { simple_time: "%b %e" } },
17
+ date: { formats: { simple_date: "%b %e" } } })
18
+ Time::DATE_FORMATS[:time_formats_simple_time] = '%b %e'
19
+ Date::DATE_FORMATS[:date_formats_simple_date] = '%b %e'
14
20
 
15
21
  @date = "2013-11-21"
16
22
  @time = Time.zone.parse(@date)
@@ -45,6 +51,27 @@ class LocalTimeHelperTest < Minitest::Test
45
51
  assert_equal expected, local_time(@time, format: '%b %e')
46
52
  end
47
53
 
54
+ def test_local_time_with_i18n_format
55
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
56
+ assert_equal expected, local_time(@time, format: :simple_time)
57
+ end
58
+
59
+ def test_local_time_with_date_formats_format
60
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
61
+ assert_equal expected, local_time(@time, format: :time_formats_simple_time)
62
+ end
63
+
64
+ def test_local_time_with_missing_i18n_and_date_formats_format
65
+ expected = %Q(<time data-format="%B %e, %Y %l:%M%P" data-local="time" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
66
+ assert_equal expected, local_time(@time, format: :missing_format)
67
+ end
68
+
69
+ def test_local_time_with_date_formats_proc_format
70
+ Time::DATE_FORMATS[:proc] = proc { |time| "nope" }
71
+ expected = %Q(<time data-format="%B %e, %Y %l:%M%P" data-local="time" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
72
+ assert_equal expected, local_time(@time, format: :proc)
73
+ end
74
+
48
75
  def test_local_time_with_options
49
76
  expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}" style="display:none">Nov 21</time>)
50
77
  assert_equal expected, local_time(@time, format: '%b %e', style: 'display:none')
@@ -58,11 +85,31 @@ class LocalTimeHelperTest < Minitest::Test
58
85
 
59
86
  def test_local_date_with_format
60
87
  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')
88
+ assert_equal expected, local_date(@time.to_date, format: '%b %e')
89
+ end
90
+
91
+ def test_local_date_with_i18n_format
92
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
93
+ assert_equal expected, local_date(@time.to_date, format: :simple_date)
94
+ end
95
+
96
+ def test_local_date_with_date_formats_format
97
+ expected = %Q(<time data-format="%b %e" data-local="time" datetime="#{@time_js}">Nov 21</time>)
98
+ assert_equal expected, local_date(@time.to_date, format: :date_formats_simple_date)
99
+ end
100
+
101
+ def test_local_date_with_missing_i18n_and_date_formats_format
102
+ expected = %Q(<time data-format="%B %e, %Y %l:%M%P" data-local="time" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
103
+ assert_equal expected, local_date(@time.to_date, format: :missing_date_format)
62
104
  end
63
105
 
64
106
  def test_local_time_ago
65
107
  expected = %Q(<time data-local="time-ago" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
66
108
  assert_equal expected, local_time_ago(@time)
67
109
  end
110
+
111
+ def test_local_time_ago_with_options
112
+ expected = %Q(<time class="date-time" data-local="time-ago" datetime="#{@time_js}">November 21, 2013 6:00am</time>)
113
+ assert_equal expected, local_time_ago(@time, class: "date-time")
114
+ end
68
115
  end
@@ -1,5 +1,6 @@
1
1
  #= require qunit
2
2
  #= require moment
3
+ #= require sinon-timers
3
4
  #= require local_time
4
5
  #= require_directory ./unit
5
6
  #= require_self
@@ -12,6 +13,15 @@
12
13
  document.body.appendChild el
13
14
  el
14
15
 
16
+ @setText = (el, text) ->
17
+ textProperty = if "textContent" of el then "textContent" else "innerText"
18
+ el[textProperty] = text
19
+
20
+ @getText = (el) ->
21
+ # innerHTML works in all browsers so using it ensures we're
22
+ # reading the text content, not a potentially arbitrary property.
23
+ el.innerHTML
24
+
15
25
  @triggerEvent = (name, el = document) ->
16
26
  event = document.createEvent "Events"
17
27
  event.initEvent name, true, true
@@ -9,9 +9,9 @@ test "date", ->
9
9
 
10
10
  test "unparseable time", ->
11
11
  el = addTimeEl "%Y", ":("
12
- el.innerText = "2013"
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,28 @@ 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
11
+ ok getText el
12
12
 
13
13
  test "window popstate", ->
14
14
  el = addTimeEl()
15
15
  triggerEvent "popstate", window
16
- ok el.innerText
16
+ ok getText el
17
17
 
18
18
  test "document page:update with Turbolinks on", ->
19
19
  el = addTimeEl()
20
20
  triggerEvent "page:update"
21
- ok not el.innerText
21
+ ok not getText el
22
22
 
23
23
  original = window.Turbolinks
24
24
  window.Turbolinks = { supported: true }
25
25
 
26
26
  triggerEvent "DOMContentLoaded"
27
27
  triggerEvent "page:update"
28
- ok el.innerText
28
+ ok getText el
29
29
 
30
30
  window.Turbolinks = original
@@ -0,0 +1,21 @@
1
+ module "public API"
2
+
3
+ test "strftime", ->
4
+ datetime = "2013-11-12T12:13:00Z"
5
+ time = new Date Date.parse datetime
6
+ format = "%B %e, %Y %l:%M%P"
7
+ results = LocalTime.strftime time, format
8
+
9
+ ok results
10
+
11
+ datetimeParsed = moment datetime
12
+ localParsed = moment results, "MMMM D, YYYY h:mma"
13
+
14
+ ok datetimeParsed.isValid()
15
+ ok localParsed.isValid()
16
+ equal datetimeParsed.toString(), localParsed.toString()
17
+
18
+ test "relativeTimeAgo", ->
19
+ time = moment().subtract("minutes", 42).toDate()
20
+ results = LocalTime.relativeTimeAgo(time)
21
+ equal results, "42 minutes ago"
@@ -32,7 +32,7 @@ for day in [0..30] by 6
32
32
  el = addTimeEl format, now.toISOString()
33
33
  run()
34
34
 
35
- equal el.innerText,
35
+ equal getText(el),
36
36
  if func = momentFormat.match(/(\w+)\(\)/)?[1]
37
37
  now.toDate()[func]()
38
38
  else
@@ -30,12 +30,11 @@ test "last week", ->
30
30
  assertTimeAgo "#{day} at #{time}", "days", 5
31
31
 
32
32
  test "this year", ->
33
- # This will fail on the first 7 days of the year.
34
- # Not sure how to test without somehow stubbing Date.
35
- if moment().dayOfYear() > 7
36
- date = moment().subtract("days", 7).format "MMM D"
37
- assertTimeAgo "on #{date}", "days", 7
38
-
33
+ clock = sinon.useFakeTimers(new Date(2013,11,11,11,11).getTime(), "Date")
34
+ date = moment().subtract("days", 7).format "MMM D"
35
+ assertTimeAgo "on #{date}", "days", 7
36
+ clock.restore()
37
+
39
38
  test "last year", ->
40
39
  date = moment().subtract("days", 366).format "MMM D, YYYY"
41
40
  assertTimeAgo "on #{date}", "days", 366
@@ -46,4 +45,4 @@ assertTimeAgo = (string, unit, amount) ->
46
45
  el.setAttribute "data-local", "time-ago"
47
46
  el.setAttribute "datetime", moment().subtract(unit, amount).utc().toISOString()
48
47
  run()
49
- equal el.innerText, string
48
+ equal getText(el), string
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: local_time
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javan Makhmali
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-29 00:00:00.000000000 Z
12
+ date: 2014-02-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: coffee-rails
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - '>='
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rails
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
28
42
  description:
29
43
  email: javan@37signals.com
30
44
  executables: []
@@ -42,6 +56,7 @@ files:
42
56
  - test/javascripts/index.js.coffee
43
57
  - test/javascripts/unit/local_time_test.js.coffee
44
58
  - test/javascripts/unit/page_events_test.js.coffee
59
+ - test/javascripts/unit/public_api_test.js.coffee
45
60
  - test/javascripts/unit/strftime_test.js.coffee
46
61
  - test/javascripts/unit/time_ago_test.js.coffee
47
62
  homepage:
@@ -67,7 +82,7 @@ rubyforge_project:
67
82
  rubygems_version: 2.1.11
68
83
  signing_key:
69
84
  specification_version: 4
70
- summary: Rails engine for displaying local times using JavaScript
85
+ summary: Rails engine for client-side local time
71
86
  test_files:
72
87
  - test/helpers/local_time_helper_test.rb
73
88
  - test/javascripts/config.ru
@@ -75,5 +90,6 @@ test_files:
75
90
  - test/javascripts/index.js.coffee
76
91
  - test/javascripts/unit/local_time_test.js.coffee
77
92
  - test/javascripts/unit/page_events_test.js.coffee
93
+ - test/javascripts/unit/public_api_test.js.coffee
78
94
  - test/javascripts/unit/strftime_test.js.coffee
79
95
  - test/javascripts/unit/time_ago_test.js.coffee