rails-diff-time 0.1.5 → 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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/README.md +82 -6
- data/lib/rails/diff/time/helpers.rb +34 -35
- data/lib/rails/diff/time/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f500ef502d22be1eb93fe920650122bdd370b5799788e00180235a48afa17ce1
|
|
4
|
+
data.tar.gz: 0b954d61dcfbc5c431a8ea9a85ea996bac0a71470dc6db8dafb69e77d4c88813
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b515308f6f0ace59434dd0ee7be048696fbdddfe196d02198fb7cfd8d8ca7625195d5867dd3b3e287bf1bdc40f01bd92d6667b1295ff9e0c06edba1cdfc9b0e4
|
|
7
|
+
data.tar.gz: ee2d795c5307826898c38ca91421d106db62e4d0592a9c4ceebbf9ef34a1edb06970e2ab246b5c8e15ea1df60c5303d442f213766bfc8b28f9b4464eee1d3910
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# rails-diff-time
|
|
2
2
|
|
|
3
|
-
A Rails helper gem to display time differences in a human-readable format.
|
|
3
|
+
A Rails helper gem to display time differences in a human-readable format with automatic updates.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -18,6 +18,10 @@ Or install it yourself as:
|
|
|
18
18
|
|
|
19
19
|
$ gem install rails-diff-time
|
|
20
20
|
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
No setup required! Just install the gem and start using it. The auto-update JavaScript will be automatically included when you use `auto_update: true` for the first time on a page.
|
|
24
|
+
|
|
21
25
|
## Usage
|
|
22
26
|
|
|
23
27
|
In your Rails views, you can use the `diff_time` helper to display time differences:
|
|
@@ -29,15 +33,34 @@ In your Rails views, you can use the `diff_time` helper to display time differen
|
|
|
29
33
|
<%= diff_time(Time.now - 2.hours) %>
|
|
30
34
|
# Output: <span>2 hours ago</span>
|
|
31
35
|
|
|
32
|
-
<%= diff_time(Time.now + 1.year + 2.months, "div", class: "time-diff") %>
|
|
36
|
+
<%= diff_time(Time.now + 1.year + 2.months, "div", { class: "time-diff" }) %>
|
|
33
37
|
# Output: <div class="time-diff">1 year 2 months later</div>
|
|
34
38
|
```
|
|
35
39
|
|
|
40
|
+
### Auto-update Feature
|
|
41
|
+
|
|
42
|
+
Enable automatic updates (every 1 minute) by passing the `auto_update: true` option:
|
|
43
|
+
|
|
44
|
+
```erb
|
|
45
|
+
<%= diff_time(user.created_at, auto_update: true) %>
|
|
46
|
+
# The display will automatically update every minute
|
|
47
|
+
|
|
48
|
+
<%= diff_time(post.published_at, "span", { class: "timestamp" }, auto_update: true) %>
|
|
49
|
+
# With custom element and attributes
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Note:** The necessary JavaScript code will be automatically included on the page the first time you call `diff_time` with `auto_update: true`. No manual setup required!
|
|
53
|
+
|
|
36
54
|
### Parameters
|
|
37
55
|
|
|
56
|
+
```ruby
|
|
57
|
+
diff_time(certain_time, element_name = "span", attributes = {}, auto_update: false)
|
|
58
|
+
```
|
|
59
|
+
|
|
38
60
|
- `certain_time` (required): The time to compare with the current time
|
|
39
61
|
- `element_name` (optional, default: "span"): The HTML element to wrap the output
|
|
40
62
|
- `attributes` (optional, default: {}): HTML attributes to add to the element
|
|
63
|
+
- `auto_update` (optional, default: false): Enable automatic updates every minute (JavaScript automatically included on first use)
|
|
41
64
|
|
|
42
65
|
## Examples
|
|
43
66
|
|
|
@@ -49,9 +72,63 @@ In your Rails views, you can use the `diff_time` helper to display time differen
|
|
|
49
72
|
<%= diff_time(event.starts_at, "p") %>
|
|
50
73
|
|
|
51
74
|
# With CSS classes
|
|
52
|
-
<%= diff_time(post.published_at, "span", class: "text-muted", id: "post-time") %>
|
|
75
|
+
<%= diff_time(post.published_at, "span", { class: "text-muted", id: "post-time" }) %>
|
|
76
|
+
|
|
77
|
+
# With auto-update enabled (JavaScript automatically included)
|
|
78
|
+
<%= diff_time(meeting.scheduled_at, "span", { class: "meeting-time" }, auto_update: true) %>
|
|
79
|
+
|
|
80
|
+
# Live timestamps for comments
|
|
81
|
+
<% @comments.each do |comment| %>
|
|
82
|
+
<div class="comment">
|
|
83
|
+
<p><%= comment.body %></p>
|
|
84
|
+
<small>Posted <%= diff_time(comment.created_at, auto_update: true) %></small>
|
|
85
|
+
</div>
|
|
86
|
+
<% end %>
|
|
53
87
|
```
|
|
54
88
|
|
|
89
|
+
### Complete Example
|
|
90
|
+
|
|
91
|
+
**app/views/posts/show.html.erb:**
|
|
92
|
+
```erb
|
|
93
|
+
<article>
|
|
94
|
+
<h1><%= @post.title %></h1>
|
|
95
|
+
<p class="meta">
|
|
96
|
+
Published <%= diff_time(@post.published_at, auto_update: true) %>
|
|
97
|
+
</p>
|
|
98
|
+
<div><%= @post.content %></div>
|
|
99
|
+
</article>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
That's it! No need to modify layout files or configure JavaScript imports.
|
|
103
|
+
|
|
104
|
+
## How It Works
|
|
105
|
+
|
|
106
|
+
The auto-update feature works by:
|
|
107
|
+
|
|
108
|
+
1. Storing the original timestamp in a `data-certain-time` attribute (ISO 8601 format)
|
|
109
|
+
2. Automatically including JavaScript code on first use of `auto_update: true`
|
|
110
|
+
3. Running a JavaScript timer that recalculates the time difference every 60 seconds
|
|
111
|
+
4. Updating the text content of elements client-side
|
|
112
|
+
|
|
113
|
+
This means:
|
|
114
|
+
- No additional server requests are made
|
|
115
|
+
- The display stays accurate without page reloads
|
|
116
|
+
- Works with Turbolinks/Turbo for SPA-like experiences
|
|
117
|
+
- **No JavaScript imports, asset pipeline configuration, or layout modifications needed** - everything is automatic!
|
|
118
|
+
|
|
119
|
+
## Browser Support
|
|
120
|
+
|
|
121
|
+
The JavaScript functionality requires:
|
|
122
|
+
- Modern browsers with ES6+ support
|
|
123
|
+
- Native `Date` object support
|
|
124
|
+
- `setInterval` support
|
|
125
|
+
|
|
126
|
+
Compatible with:
|
|
127
|
+
- Chrome/Edge (latest)
|
|
128
|
+
- Firefox (latest)
|
|
129
|
+
- Safari (latest)
|
|
130
|
+
- Mobile browsers (iOS Safari, Chrome Mobile)
|
|
131
|
+
|
|
55
132
|
## Development
|
|
56
133
|
|
|
57
134
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -64,5 +141,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/dhq_bo
|
|
|
64
141
|
|
|
65
142
|
## License
|
|
66
143
|
|
|
67
|
-
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
68
|
-
|
|
144
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -17,7 +17,7 @@ module RailsDiffTime
|
|
|
17
17
|
# If auto_update is enabled and the script has not been included yet
|
|
18
18
|
if auto_update && !@_diff_time_script_included
|
|
19
19
|
@_diff_time_script_included = true
|
|
20
|
-
result
|
|
20
|
+
result += diff_time_script_tag
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
result
|
|
@@ -30,36 +30,36 @@ module RailsDiffTime
|
|
|
30
30
|
<<~JAVASCRIPT.html_safe
|
|
31
31
|
(function() {
|
|
32
32
|
'use strict';
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
class DiffTimeUpdater {
|
|
35
35
|
constructor() {
|
|
36
36
|
this.updateInterval = 60000;
|
|
37
37
|
this.elements = [];
|
|
38
38
|
this.timerId = null;
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
init() {
|
|
42
42
|
this.findElements();
|
|
43
43
|
if (this.elements.length > 0) {
|
|
44
44
|
this.startAutoUpdate();
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
findElements() {
|
|
49
49
|
this.elements = Array.from(
|
|
50
50
|
document.querySelectorAll('[data-diff-time-target="display"]')
|
|
51
51
|
);
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
startAutoUpdate() {
|
|
55
55
|
if (this.timerId) clearInterval(this.timerId);
|
|
56
56
|
this.timerId = setInterval(() => this.updateAll(), this.updateInterval);
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
updateAll() {
|
|
60
60
|
this.elements.forEach(element => this.updateElement(element));
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
updateElement(element) {
|
|
64
64
|
const certainTimeStr = element.dataset.certainTime;
|
|
65
65
|
if (!certainTimeStr) return;
|
|
@@ -67,16 +67,16 @@ module RailsDiffTime
|
|
|
67
67
|
const diffTimeStr = this.calculateDiffTime(certainTime);
|
|
68
68
|
element.textContent = diffTimeStr;
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
calculateDiffTime(certainTime) {
|
|
72
72
|
const now = new Date();
|
|
73
73
|
const diff = certainTime - now;
|
|
74
74
|
const differenceInSeconds = Math.abs(diff) / 1000;
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
if (differenceInSeconds <= 5) return "now";
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
const isLater = diff > 0;
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
if (differenceInSeconds >= this.yearInSeconds()) {
|
|
81
81
|
return this.formatYears(differenceInSeconds, isLater);
|
|
82
82
|
} else if (differenceInSeconds >= this.monthInSeconds()) {
|
|
@@ -93,17 +93,17 @@ module RailsDiffTime
|
|
|
93
93
|
return this.formatSeconds(differenceInSeconds, isLater);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
formatYears(seconds, isLater) {
|
|
98
98
|
const years = Math.floor(seconds / this.yearInSeconds());
|
|
99
99
|
let remaining = seconds - (years * this.yearInSeconds());
|
|
100
100
|
let result = this.timeStr(years, "year");
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
if (remaining >= this.monthInSeconds()) {
|
|
103
103
|
const months = Math.floor(remaining / this.monthInSeconds());
|
|
104
104
|
remaining -= months * this.monthInSeconds();
|
|
105
105
|
result += ` ${this.timeStr(months, "month")}`;
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
if (remaining >= this.dayInSeconds()) {
|
|
108
108
|
const days = Math.floor(remaining / this.dayInSeconds());
|
|
109
109
|
result += ` ${this.timeStr(days, "day")}`;
|
|
@@ -111,72 +111,72 @@ module RailsDiffTime
|
|
|
111
111
|
}
|
|
112
112
|
return `${result} ${this.agoOrLater(isLater)}`;
|
|
113
113
|
}
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
formatMonths(seconds, isLater) {
|
|
116
116
|
const months = Math.floor(seconds / this.monthInSeconds());
|
|
117
117
|
const remaining = seconds - (months * this.monthInSeconds());
|
|
118
118
|
let result = this.timeStr(months, "month");
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
if (remaining >= this.dayInSeconds()) {
|
|
121
121
|
const days = Math.floor(remaining / this.dayInSeconds());
|
|
122
122
|
result += ` ${this.timeStr(days, "day")}`;
|
|
123
123
|
}
|
|
124
124
|
return `${result} ${this.agoOrLater(isLater)}`;
|
|
125
125
|
}
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
formatWeeks(seconds, isLater) {
|
|
128
128
|
const weeks = Math.floor(seconds / this.weekInSeconds());
|
|
129
129
|
return `${this.timeStr(weeks, "week")} ${this.agoOrLater(isLater)}`;
|
|
130
130
|
}
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
formatDays(seconds, isLater) {
|
|
133
133
|
const days = Math.floor(seconds / this.dayInSeconds());
|
|
134
134
|
return `${this.timeStr(days, "day")} ${this.agoOrLater(isLater)}`;
|
|
135
135
|
}
|
|
136
|
-
|
|
136
|
+
|
|
137
137
|
formatHours(seconds, isLater) {
|
|
138
138
|
const hours = Math.floor(seconds / this.hourInSeconds());
|
|
139
139
|
const remaining = seconds - (hours * this.hourInSeconds());
|
|
140
140
|
let result = this.timeStr(hours, "hour");
|
|
141
|
-
|
|
141
|
+
|
|
142
142
|
if (remaining >= this.minuteInSeconds()) {
|
|
143
143
|
const minutes = Math.floor(remaining / this.minuteInSeconds());
|
|
144
144
|
result += ` ${this.timeStr(minutes, "minute")}`;
|
|
145
145
|
}
|
|
146
146
|
return `${result} ${this.agoOrLater(isLater)}`;
|
|
147
147
|
}
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
formatMinutes(seconds, isLater) {
|
|
150
150
|
const minutes = Math.floor(seconds / this.minuteInSeconds());
|
|
151
151
|
const remaining = seconds - (minutes * this.minuteInSeconds());
|
|
152
152
|
let result = this.timeStr(minutes, "minute");
|
|
153
|
-
|
|
153
|
+
|
|
154
154
|
if (remaining > 0) {
|
|
155
155
|
const secs = Math.floor(remaining);
|
|
156
156
|
result += ` ${this.timeStr(secs, "second")}`;
|
|
157
157
|
}
|
|
158
158
|
return `${result} ${this.agoOrLater(isLater)}`;
|
|
159
159
|
}
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
formatSeconds(seconds, isLater) {
|
|
162
162
|
const secs = Math.floor(seconds);
|
|
163
163
|
return `${this.timeStr(secs, "second")} ${this.agoOrLater(isLater)}`;
|
|
164
164
|
}
|
|
165
|
-
|
|
165
|
+
|
|
166
166
|
yearInSeconds() { return 365.25 * 24 * 3600; }
|
|
167
167
|
monthInSeconds() { return 30 * 24 * 3600; }
|
|
168
168
|
weekInSeconds() { return 7 * 24 * 3600; }
|
|
169
169
|
dayInSeconds() { return 24 * 3600; }
|
|
170
170
|
hourInSeconds() { return 3600; }
|
|
171
171
|
minuteInSeconds() { return 60; }
|
|
172
|
-
|
|
172
|
+
|
|
173
173
|
agoOrLater(isLater) { return isLater ? "later" : "ago"; }
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
timeStr(count, singular) {
|
|
176
176
|
const plural = singular + "s";
|
|
177
177
|
return `${count} ${count === 1 ? singular : plural}`;
|
|
178
178
|
}
|
|
179
|
-
|
|
179
|
+
|
|
180
180
|
destroy() {
|
|
181
181
|
if (this.timerId) {
|
|
182
182
|
clearInterval(this.timerId);
|
|
@@ -185,32 +185,32 @@ module RailsDiffTime
|
|
|
185
185
|
this.elements = [];
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
|
-
|
|
188
|
+
|
|
189
189
|
let updater = null;
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
function initUpdater() {
|
|
192
192
|
if (updater) updater.destroy();
|
|
193
193
|
updater = new DiffTimeUpdater();
|
|
194
194
|
updater.init();
|
|
195
195
|
}
|
|
196
|
-
|
|
196
|
+
|
|
197
197
|
if (document.readyState === 'loading') {
|
|
198
198
|
document.addEventListener('DOMContentLoaded', initUpdater);
|
|
199
199
|
} else {
|
|
200
200
|
initUpdater();
|
|
201
201
|
}
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
document.addEventListener('turbolinks:load', initUpdater);
|
|
204
204
|
document.addEventListener('turbo:load', initUpdater);
|
|
205
|
-
|
|
205
|
+
|
|
206
206
|
document.addEventListener('turbolinks:before-cache', function() {
|
|
207
207
|
if (updater) updater.destroy();
|
|
208
208
|
});
|
|
209
|
-
|
|
209
|
+
|
|
210
210
|
document.addEventListener('turbo:before-cache', function() {
|
|
211
211
|
if (updater) updater.destroy();
|
|
212
212
|
});
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
window.RailsDiffTime = {
|
|
215
215
|
updater: updater,
|
|
216
216
|
DiffTimeUpdater: DiffTimeUpdater
|
|
@@ -372,4 +372,3 @@ module RailsDiffTime
|
|
|
372
372
|
end
|
|
373
373
|
end
|
|
374
374
|
end
|
|
375
|
-
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-diff-time
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- dhq_boiler
|
|
@@ -46,7 +46,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
46
46
|
requirements:
|
|
47
47
|
- - ">="
|
|
48
48
|
- !ruby/object:Gem::Version
|
|
49
|
-
version: 3.4.
|
|
49
|
+
version: 3.4.7
|
|
50
50
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - ">="
|