remove momentjs and fork timeago.js
parent
767be9543c
commit
f9481bfe38
|
@ -4,9 +4,6 @@
|
|||
[submodule "public/vendor/tagmanager"]
|
||||
path = public/vendor/tagmanager
|
||||
url = https://github.com/max-favilli/tagmanager
|
||||
[submodule "public/vendor/moment"]
|
||||
path = public/vendor/moment
|
||||
url = https://github.com/moment/moment
|
||||
[submodule "public/vendor/ChessPursuit"]
|
||||
path = public/vendor/ChessPursuit
|
||||
url = https://github.com/ornicar/ChessPursuit
|
||||
|
|
|
@ -65,21 +65,15 @@ trait AssetHelper { self: I18nHelper =>
|
|||
"""<script src="//code.highcharts.com/4.1.4/highcharts-more.js"></script>"""
|
||||
}
|
||||
|
||||
private val momentJsMissingLangs = Set("le", "pi", "tp", "ky", "ga", "zu", "la", "tg", "mg", "as", "yo", "ps", "fp", "ur", "tc", "ia", "jb", "gu", "kn", "gd", "kb", "io", "sw", "sa", "kk", "mn")
|
||||
private val timeagoLangs = Set("ar", "be", "bg", "ca", "da", "de", "el", "en", "en_short", "es", "eu", "fa", "fi", "fr", "gl", "he", "hu", "in_BG", "in_HI", "in_ID", "it", "ja", "ko", "ml", "my", "nb_NO", "nl", "nn_NO", "pl", "pt_BR", "ro", "ru", "sv", "ta", "th", "tr", "uk", "vi", "zh_CN", "zh_TW")
|
||||
private def timeagoLangUrl(code: String) = s"/assets/vendor/timeago/locales/$code.js"
|
||||
|
||||
def momentLangUrl(implicit ctx: lila.api.Context): Option[String] = {
|
||||
val l = lang(ctx)
|
||||
if (momentJsMissingLangs contains l.language) none
|
||||
else ((l.language, l.country.toLowerCase) match {
|
||||
case ("en", "us") => none
|
||||
case ("en", "au" | "ca" | "gb") => l.code.some
|
||||
case ("pt", "br") => l.code.some
|
||||
case ("zh", "tw") => l.code.some
|
||||
case ("zh", _) => "zh-cn".some
|
||||
case ("ar", "ma" | "sa" | "tn") => l.code.some
|
||||
case ("fr", "ca") => l.code.some
|
||||
case _ => l.language.some
|
||||
}).map { locale => s"/assets/vendor/moment/locale/${locale.toLowerCase}.js" }
|
||||
def timeagoLangUrl(implicit ctx: lila.api.Context): Option[String] = {
|
||||
Some("/assets/vendor/timeago/dist/timeago.locales.min.js")
|
||||
// val l = lang(ctx)
|
||||
// if (timeagoLangs(l.code)) Some(timeagoLangUrl(l.code))
|
||||
// else if (timeagoLangs(l.language)) Some(timeagoLangUrl(l.language))
|
||||
// else none
|
||||
}
|
||||
|
||||
val tagmanagerTag = cdnOrLocal(
|
||||
|
|
|
@ -76,16 +76,14 @@ trait DateHelper { self: I18nHelper =>
|
|||
|
||||
def isoDate(date: DateTime): String = isoFormatter print date
|
||||
|
||||
def momentFormat(date: DateTime, format: String): Html = Html {
|
||||
s"""<time class="moment" datetime="${isoDate(date)}" data-format="$format"></time>"""
|
||||
}
|
||||
def momentFormat(date: DateTime): Html = momentFormat(date, "calendar")
|
||||
|
||||
private val oneDayMillis = 1000 * 60 * 60 * 24
|
||||
def momentFromNow(date: DateTime)(implicit ctx: Context) = Html {
|
||||
s"""<time class="moment-from-now" title="${showDate(date)}" datetime="${isoDate(date)}"></time>"""
|
||||
val rendered = showDateTime(date)
|
||||
if ((date.getMillis - nowMillis) > oneDayMillis) s"""<time>$rendered</time>"""
|
||||
else s"""<time class="timeago" title="$rendered" datetime="${isoDate(date)}">$rendered</time>"""
|
||||
}
|
||||
def momentFromNowNoCtx(date: DateTime) = Html {
|
||||
s"""<time class="moment-from-now" datetime="${isoDate(date)}"></time>"""
|
||||
s"""<time class="timeago" datetime="${isoDate(date)}"></time>"""
|
||||
}
|
||||
|
||||
def secondsFromNow(seconds: Int)(implicit ctx: Context) =
|
||||
|
|
|
@ -179,9 +179,27 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
|
|||
@moreJs
|
||||
@embedJs {
|
||||
lichess.quantity = @i18nJsQuantityFunction();
|
||||
lichess.timeagoLocale = function(number, index) {
|
||||
return [
|
||||
['à l\'instant', 'dans un instant'],
|
||||
['il y a %s secondes', 'dans %s secondes'],
|
||||
['il y a 1 minute', 'dans 1 minute'],
|
||||
['il y a %s minutes', 'dans %s minutes'],
|
||||
['il y a 1 heure', 'dans 1 heure'],
|
||||
['il y a %s heures', 'dans %s heures'],
|
||||
['il y a 1 jour', 'dans 1 jour'],
|
||||
['il y a %s jours', 'dans %s jours'],
|
||||
['il y a 1 semaine', 'dans 1 semaine'],
|
||||
['il y a %s semaines', 'dans %s semaines'],
|
||||
['il y a 1 mois', 'dans 1 mois'],
|
||||
['il y a %s mois', 'dans %s mois'],
|
||||
['il y a 1 an', 'dans 1 an'],
|
||||
['il y a %s ans', 'dans %s ans']
|
||||
][index];
|
||||
};
|
||||
@if(lang.language != "en") {
|
||||
@momentLangUrl.map { url =>
|
||||
window.momentLocaleUrl = "@url";
|
||||
@timeagoLangUrl.map { url =>
|
||||
window.timeagoLocaleUrl = "@url";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ moreCss = cssTag("event.css")) {
|
|||
}
|
||||
</td>
|
||||
<td>
|
||||
<span class="date">@momentFormat(e.startsAt)</span>
|
||||
<span class="date">@momentFromNow(e.startsAt)</span>
|
||||
@momentFromNow(e.startsAt)
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -28,7 +28,7 @@ searchText = text
|
|||
<p>@shortenWithBr(view.post.text, 200)</p>
|
||||
</td>
|
||||
<td class="info">
|
||||
@momentFormat(view.post.createdAt) by @authorLink(view.post)
|
||||
@momentFromNow(view.post.createdAt) by @authorLink(view.post)
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
}
|
||||
</span>
|
||||
@game.pgnImport.flatMap(_.date).getOrElse(
|
||||
game.isBeingPlayed.fold(trans.playingRightNow(), momentFormat(game.createdAt))
|
||||
game.isBeingPlayed.fold(trans.playingRightNow(), momentFromNow(game.createdAt))
|
||||
)
|
||||
</div>
|
||||
@game.pgnImport.flatMap(_.date).map { date =>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
• @g.rated.fold(trans.rated(), trans.casual())
|
||||
}
|
||||
</strong>
|
||||
@g.pgnImport.flatMap(_.date).getOrElse(momentFormat(g.createdAt))
|
||||
@g.pgnImport.flatMap(_.date).getOrElse(momentFromNow(g.createdAt))
|
||||
@g.tournamentId.map { tourId =>
|
||||
• @tournamentLink(tourId)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ title = trans.inbox.txt()) {
|
|||
<td class="subject">
|
||||
<a href="@routes.Message.thread(thread.id)#bottom">@thread.name</a>
|
||||
</td>
|
||||
<td class="date">@momentFormat(thread.updatedAt)</td>
|
||||
<td class="date">@momentFromNow(thread.updatedAt)</td>
|
||||
<td class="check">
|
||||
<input type="checkbox" name="threads" value="@thread.id" />
|
||||
</td>
|
||||
|
|
|
@ -16,7 +16,7 @@ title = thread.name) {
|
|||
@thread.posts.map { post =>
|
||||
<div class="thread_message embed_analyse" id="message_@post.id">
|
||||
<span class="infos">
|
||||
@userIdLink(thread.visibleSenderOf(post), none) <span data-icon="H"></span> @userIdLink(thread.visibleReceiverOf(post), "inline".some) - @momentFormat(post.createdAt)
|
||||
@userIdLink(thread.visibleSenderOf(post), none) <span data-icon="H"></span> @userIdLink(thread.visibleReceiverOf(post), "inline".some) - @momentFromNow(post.createdAt)
|
||||
</span>
|
||||
<div class="thread_message_body">@autoLink(post.text)</div>
|
||||
</div>
|
||||
|
|
|
@ -25,7 +25,7 @@ active = "log") {
|
|||
<tbody>
|
||||
@logs.map { log =>
|
||||
<tr>
|
||||
<td>@userIdLink(log.mod.some)<br />@momentFormat(log.date)</td>
|
||||
<td>@userIdLink(log.mod.some)<br />@momentFromNow(log.date)</td>
|
||||
<td>@log.showAction.capitalize @log.user.map { u =>
|
||||
@userIdLink(u.some)
|
||||
}</td>
|
||||
|
|
|
@ -42,7 +42,7 @@ moreCss = cssTag("report.css")) {
|
|||
<tr class="@r.unprocessed.fold("new", "")">
|
||||
<td>
|
||||
@userIdLink(r.createdBy.some)<br />
|
||||
@momentFormat(r.createdAt)
|
||||
@momentFromNow(r.createdAt)
|
||||
@if(accuracy.isDefined) {
|
||||
<br /><strong>@accuracy%</strong> accuracy
|
||||
}
|
||||
|
|
|
@ -15,5 +15,5 @@
|
|||
<br />
|
||||
Host color: @sim.color.getOrElse("random").capitalize
|
||||
</div>
|
||||
@trans.by(usernameOrId(sim.hostId)), <span title="@showDateTime(sim.createdAt)">@momentFormat(sim.createdAt)</span>
|
||||
@trans.by(usernameOrId(sim.hostId)), <span title="@showDateTime(sim.createdAt)">@momentFromNow(sim.createdAt)</span>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<td>@userLink(request.user)</td>
|
||||
}
|
||||
<td>@autoLink(request.message)</td>
|
||||
<td>@momentFormat(request.date)</td>
|
||||
<td>@momentFromNow(request.date)</td>
|
||||
<td class="process">
|
||||
<form class="process-request" action="@routes.Team.requestProcess(request.id)" method="post">
|
||||
<input type="hidden" name="url" value="@t.fold(routes.Team.requests())(te => routes.Team.show(te.id))" />
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
<p class="meta clearfix">
|
||||
<a href="@routes.ForumPost.redirect(p.postId)">@p.topicName</a>
|
||||
@userIdLink(p.userId, withOnline = false)
|
||||
@momentFormat(p.createdAt)
|
||||
@momentFromNow(p.createdAt)
|
||||
</p>
|
||||
<p>@shorten(p.text, 200)</p>
|
||||
</li>
|
||||
|
|
|
@ -37,7 +37,7 @@ lichess.StrongSocket.defaults.events.reload = app.update;
|
|||
@if(s.freq != lila.tournament.Schedule.Freq.Hourly) {
|
||||
<li data-icon="@tournamentIconChar(tour)" class="is-gold @s.freq.name">
|
||||
<a href="@routes.Tournament.show(tour.id)">@tour.name</a>
|
||||
@momentFormat(s.at, "calendar")
|
||||
@momentFromNow(s.at)
|
||||
</li>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
} else {
|
||||
@trans.by(usernameOrId(tour.createdBy))
|
||||
}
|
||||
• @momentFormat(tour.startsAt)
|
||||
• @momentFromNow(tour.startsAt)
|
||||
@if(!tour.position.initial) {
|
||||
<br /><br />
|
||||
<a target="_blank" href="@tour.position.url">
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
} else {
|
||||
@e.tour.perfType.map(_.name)
|
||||
} •
|
||||
@momentFormat(e.tour.startsAt)
|
||||
@momentFromNow(e.tour.startsAt)
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit f3fbef9d9875bbff340b527dbe3f1c447a942f69
|
|
@ -4,10 +4,6 @@ import { ModerationCtrl, ModerationOpts, ModerationData, ModerationReason } from
|
|||
import { userModInfo } from './xhr'
|
||||
import { userLink, spinner, bind } from './util';
|
||||
|
||||
function isToday(timestamp: number) {
|
||||
return window.moment(timestamp).isSame(Date.now(), 'day');
|
||||
}
|
||||
|
||||
export function moderationCtrl(opts: ModerationOpts): ModerationCtrl {
|
||||
|
||||
let data: ModerationData | undefined;
|
||||
|
@ -129,9 +125,8 @@ export function moderationView(ctrl?: ModerationCtrl): VNode[] | undefined {
|
|||
return h('tr', [
|
||||
h('td.reason', e.reason),
|
||||
h('td.mod', e.mod),
|
||||
h('td', h('time.moment', {
|
||||
h('td', h('time.timeago', {
|
||||
attrs: {
|
||||
'data-format': isToday(e.date) ? 'LT' : 'DD/MM/YY',
|
||||
datetime: new Date(e.date).toISOString()
|
||||
}
|
||||
}))
|
||||
|
|
|
@ -14,7 +14,7 @@ module.exports = function(element, opts) {
|
|||
view: view
|
||||
});
|
||||
|
||||
lichess.pubsub.on('moment.locale_loaded', m.redraw);
|
||||
lichess.pubsub.on('timeago.locale-loaded', m.redraw);
|
||||
|
||||
return controller;
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ function formatNumber(dt, n) {
|
|||
}
|
||||
|
||||
function formatSerieName(dt, n) {
|
||||
if (dt === 'date') return moment(n * 1000).format('LL');
|
||||
if (dt === 'date') return new Date(n).toLocaleDateString();
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ var renderMeat = cache(function(ctrl) {
|
|||
]);
|
||||
}, function(ctrl) {
|
||||
var q = ctrl.vm.answer ? ctrl.vm.answer.question : null;
|
||||
return q ? ctrl.makeUrl(q.dimension, q.metric, q.filters) + moment.locale() : '';
|
||||
return q ? ctrl.makeUrl(q.dimension, q.metric, q.filters) : '';
|
||||
});
|
||||
|
||||
module.exports = function(ctrl) {
|
||||
|
|
|
@ -3,10 +3,7 @@ import { Chessground } from 'chessground';
|
|||
import LobbyController from '../ctrl';
|
||||
|
||||
function timer(pov) {
|
||||
const time = window.moment().add(pov.secondsLeft, 'seconds');
|
||||
return h('time.moment-from-now', {
|
||||
attrs: { datetime: time.format() }
|
||||
}, time.fromNow());
|
||||
return h('time', window.timeago().format(Date.now() + pov.secondsLeft * 1000));
|
||||
}
|
||||
|
||||
export default function(ctrl: LobbyController) {
|
||||
|
|
|
@ -201,9 +201,10 @@ function generic(n: Notification, url: string | undefined, icon: string, content
|
|||
}
|
||||
|
||||
function drawTime(n: Notification) {
|
||||
return h('time.moment-from-now', {
|
||||
attrs: { datetime: new Date(n.date).toISOString() }
|
||||
});
|
||||
var date = new Date(n.date);
|
||||
return h('time', {
|
||||
attrs: { title: date.toLocaleString() }
|
||||
}, window.timeago().format(date));
|
||||
}
|
||||
|
||||
function userFullName(u?: LightUser) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
var m = require('mithril');
|
||||
|
||||
const timeago = window.timeago();
|
||||
|
||||
function fMap(v, f, orDefault) {
|
||||
return v ? f(v) : (orDefault || null);
|
||||
}
|
||||
|
@ -12,11 +14,7 @@ function gameLink(id, content) {
|
|||
}
|
||||
|
||||
function date(d) {
|
||||
return m('time', {
|
||||
class: 'moment',
|
||||
datetime: d,
|
||||
'data-format': 'calendar'
|
||||
}, '...')
|
||||
return m('time', timeago.format(d));
|
||||
}
|
||||
|
||||
function fromTo(s) {
|
||||
|
@ -64,9 +62,9 @@ module.exports = {
|
|||
return v;
|
||||
},
|
||||
formatSeconds: function(s, format) {
|
||||
var d = moment.duration(s, 'seconds');
|
||||
var hours = d.days() * 24 + d.hours();
|
||||
if (format === 'short') return hours + 'h, ' + d.minutes() + 'm';
|
||||
return hours + ' hours, ' + d.minutes() + ' minutes';
|
||||
var hours = Math.floor(s / 3600);
|
||||
var minutes = Math.floor((s % 3600) / 60);
|
||||
if (format === 'short') return hours + 'h, ' + minutes + 'm';
|
||||
return hours + ' hours, ' + minutes + ' minutes';
|
||||
}
|
||||
};
|
||||
|
|
|
@ -16,12 +16,6 @@ function player(p) {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
secondsFromNow: function(seconds) {
|
||||
var time = moment().add(seconds, 'seconds');
|
||||
return m('time.moment-from-now', {
|
||||
datetime: time.format()
|
||||
}, time.fromNow());
|
||||
},
|
||||
title: function(ctrl) {
|
||||
return m('h1.text[data-icon=|]', [
|
||||
ctrl.data.fullName,
|
||||
|
|
|
@ -86,7 +86,6 @@ function makeBundle(filename) {
|
|||
return gulp.src([
|
||||
'../../public/javascripts/vendor/jquery.min.js',
|
||||
'./dist/jquery.fill.js',
|
||||
'../../public/vendor/moment/min/moment.min.js',
|
||||
'./dep/powertip.min.js',
|
||||
'./dep/howler.min.js',
|
||||
'./dep/mousetrap.min.js',
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
"vinyl-source-stream": "^1"
|
||||
},
|
||||
"dependencies": {
|
||||
"gulp-concat": "^2.6",
|
||||
"tablesort": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require('./util');
|
||||
require('./timeago');
|
||||
require('./trans');
|
||||
require('./socket');
|
||||
require('./main');
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
lichess.topMenuIntent = function() {
|
||||
$('#topmenu.hover').removeClass('hover').hoverIntent(function() {
|
||||
$(this).toggleClass('hover');
|
||||
|
@ -330,31 +329,20 @@ lichess.topMenuIntent = function() {
|
|||
|
||||
document.body.addEventListener('mouseover', lichess.powertip.mouseover);
|
||||
|
||||
function setMoment() {
|
||||
function setTimeago() {
|
||||
// check that locale was loaded
|
||||
if (!window.momentLocaleUrl) lichess.requestIdleCallback(function() {
|
||||
$(".moment-from-now").each(function() {
|
||||
this.textContent = moment(this.getAttribute('datetime')).fromNow();
|
||||
});
|
||||
$("time.moment").removeClass('moment').each(function() {
|
||||
var parsed = moment(this.getAttribute('datetime'));
|
||||
var format = this.getAttribute('data-format');
|
||||
this.textContent = format === 'calendar' ? parsed.calendar(null, {
|
||||
sameElse: 'DD/MM/YYYY HH:mm'
|
||||
}) : parsed.format(format);
|
||||
});
|
||||
});
|
||||
if (window.timeagoLocaleUrl) return;
|
||||
timeago().render($('.timeago').removeClass('timeago'));
|
||||
}
|
||||
|
||||
if (window.momentLocaleUrl) lichess.loadScript(momentLocaleUrl, {noVersion: true}).then(function() {
|
||||
delete window.momentLocaleUrl;
|
||||
lichess.pubsub.emit('moment.locale_loaded')();
|
||||
setMoment();
|
||||
if (window.timeagoLocaleUrl) lichess.loadScript(timeagoLocaleUrl, {noVersion: true}).then(function() {
|
||||
window.timeagoLocaleUrl = false;
|
||||
lichess.pubsub.emit('timeago.locale-loaded')();
|
||||
setTimeago();
|
||||
});
|
||||
else setMoment();
|
||||
else setTimeago();
|
||||
|
||||
lichess.pubsub.on('content_loaded', setMoment);
|
||||
setInterval(setMoment, 2000);
|
||||
lichess.pubsub.on('content_loaded', setTimeago);
|
||||
|
||||
if ($('body').hasClass('blind_mode')) {
|
||||
var setBlindMode = function() {
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
/**
|
||||
* based on https://github.com/hustcc/timeago.js
|
||||
* Copyright (c) 2016 hustcc
|
||||
* License: MIT
|
||||
**/
|
||||
window.timeago = (function() {
|
||||
// second, minute, hour, day, week, month, year(365 days)
|
||||
var SEC_ARRAY = [60, 60, 24, 7, 365/7/12, 12],
|
||||
SEC_ARRAY_LEN = 6,
|
||||
// ATTR_DATETIME = 'datetime',
|
||||
ATTR_DATA_TID = 'data-tid',
|
||||
timers = {}; // real-time render timers
|
||||
|
||||
// format Date / string / timestamp to Date instance.
|
||||
function toDate(input) {
|
||||
if (input instanceof Date) return input;
|
||||
if (!isNaN(input)) return new Date(parseInt(input));
|
||||
if (/^\d+$/.test(input)) return new Date(parseInt(input));
|
||||
input = (input || '').trim().replace(/\.\d+/, '') // remove milliseconds
|
||||
.replace(/-/, '/').replace(/-/, '/')
|
||||
.replace(/(\d)T(\d)/, '$1 $2').replace(/Z/, ' UTC') // 2017-2-5T3:57:52Z -> 2017-2-5 3:57:52UTC
|
||||
.replace(/([\+\-]\d\d)\:?(\d\d)/, ' $1$2'); // -04:00 -> -0400
|
||||
return new Date(input);
|
||||
}
|
||||
// format the diff second to *** time ago
|
||||
function formatDiff(diff) {
|
||||
var i = 0,
|
||||
agoin = diff < 0 ? 1 : 0, // timein or timeago
|
||||
total_sec = diff = Math.abs(diff);
|
||||
|
||||
for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) {
|
||||
diff /= SEC_ARRAY[i];
|
||||
}
|
||||
diff = parseInt(diff);
|
||||
i *= 2;
|
||||
|
||||
if (diff > (i === 0 ? 9 : 1)) i += 1;
|
||||
return lichess.timeagoLocale(diff, i, total_sec)[agoin].replace('%s', diff);
|
||||
}
|
||||
// calculate the diff second between date to be formated an now date.
|
||||
function diffSec(date, nowDate) {
|
||||
nowDate = nowDate ? toDate(nowDate) : new Date();
|
||||
return (nowDate - toDate(date)) / 1000;
|
||||
}
|
||||
/**
|
||||
* nextInterval: calculate the next interval time.
|
||||
* - diff: the diff sec between now and date to be formated.
|
||||
*
|
||||
* What's the meaning?
|
||||
* diff = 61 then return 59
|
||||
* diff = 3601 (an hour + 1 second), then return 3599
|
||||
* make the interval with high performace.
|
||||
**/
|
||||
function nextInterval(diff) {
|
||||
var rst = 1, i = 0, d = Math.abs(diff);
|
||||
for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) {
|
||||
diff /= SEC_ARRAY[i];
|
||||
rst *= SEC_ARRAY[i];
|
||||
}
|
||||
// return leftSec(d, rst);
|
||||
d = d % rst;
|
||||
d = d ? rst - d : rst;
|
||||
return Math.ceil(d);
|
||||
}
|
||||
// get the datetime attribute, `data-timeagp` / `datetime` are supported.
|
||||
function getDateAttr(node) {
|
||||
return getAttr(node, 'data-timeago') || getAttr(node, 'datetime');
|
||||
}
|
||||
// get the node attribute, native DOM and jquery supported.
|
||||
function getAttr(node, name) {
|
||||
if(node.getAttribute) return node.getAttribute(name); // native
|
||||
if(node.attr) return node.attr(name); // jquery
|
||||
}
|
||||
// set the node attribute, native DOM and jquery supported.
|
||||
function setTidAttr(node, val) {
|
||||
if(node.setAttribute) return node.setAttribute(ATTR_DATA_TID, val); // native
|
||||
if(node.attr) return node.attr(ATTR_DATA_TID, val); // jquery
|
||||
}
|
||||
// get the timer id of node.
|
||||
// remove the function, can save some bytes.
|
||||
// function getTidFromNode(node) {
|
||||
// return getAttr(node, ATTR_DATA_TID);
|
||||
// }
|
||||
/**
|
||||
* timeago: the function to get `timeago` instance.
|
||||
* - nowDate: the relative date, default is new Date().
|
||||
*
|
||||
* How to use it?
|
||||
* var timeagoLib = require('timeago.js');
|
||||
* var timeago = timeagoLib(); // all use default.
|
||||
* var timeago = timeagoLib('2016-09-10'); // the relative date is 2016-09-10, so the 2016-09-11 will be 1 day ago.
|
||||
**/
|
||||
function Timeago(nowDate) {
|
||||
this.nowDate = nowDate;
|
||||
}
|
||||
// what the timer will do
|
||||
Timeago.prototype.doRender = function(node, date) {
|
||||
var diff = diffSec(date, this.nowDate),
|
||||
self = this,
|
||||
tid;
|
||||
// delete previously assigned timeout's id to node
|
||||
node.innerHTML = formatDiff(diff);
|
||||
// waiting %s seconds, do the next render
|
||||
timers[tid = setTimeout(function() {
|
||||
self.doRender(node, date);
|
||||
delete timers[tid];
|
||||
}, Math.min(nextInterval(diff) * 1000, 0x7FFFFFFF))] = 0; // there is no need to save node in object.
|
||||
// set attribute date-tid
|
||||
setTidAttr(node, tid);
|
||||
};
|
||||
/**
|
||||
* format: format the date to *** time ago
|
||||
* - date: the date / string / timestamp to be formated
|
||||
*
|
||||
* How to use it?
|
||||
* var timeago = require('timeago.js')();
|
||||
* timeago.format(new Date(), 'pl'); // Date instance
|
||||
* timeago.format('2016-09-10', 'fr'); // formated date string
|
||||
* timeago.format(1473473400269); // timestamp with ms
|
||||
**/
|
||||
Timeago.prototype.format = function(date) {
|
||||
return formatDiff(diffSec(date, this.nowDate));
|
||||
};
|
||||
/**
|
||||
* render: render the DOM real-time.
|
||||
* - nodes: which nodes will be rendered.
|
||||
*
|
||||
* How to use it?
|
||||
* var timeago = require('timeago.js')();
|
||||
* // 1. javascript selector
|
||||
* timeago.render(document.querySelectorAll('.need_to_be_rendered'));
|
||||
* // 2. use jQuery selector
|
||||
* timeago.render($('.need_to_be_rendered'));
|
||||
*
|
||||
* Notice: please be sure the dom has attribute `datetime`.
|
||||
**/
|
||||
Timeago.prototype.render = function(nodes) {
|
||||
if (nodes.length === undefined) nodes = [nodes];
|
||||
for (var i = 0, len = nodes.length; i < len; i++) {
|
||||
this.doRender(nodes[i], getDateAttr(nodes[i])); // render item
|
||||
}
|
||||
};
|
||||
|
||||
function timeagoFactory(nowDate) {
|
||||
return new Timeago(nowDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* cancel: cancels one or all the timers which are doing real-time render.
|
||||
*
|
||||
* How to use it?
|
||||
* For canceling all the timers:
|
||||
* var timeagoFactory = require('timeago.js');
|
||||
* var timeago = timeagoFactory();
|
||||
* timeago.render(document.querySelectorAll('.need_to_be_rendered'));
|
||||
* timeagoFactory.cancel(); // will stop all the timers, stop render in real time.
|
||||
*
|
||||
* For canceling single timer on specific node:
|
||||
* var timeagoFactory = require('timeago.js');
|
||||
* var timeago = timeagoFactory();
|
||||
* var nodes = document.querySelectorAll('.need_to_be_rendered');
|
||||
* timeago.render(nodes);
|
||||
* timeagoFactory.cancel(nodes[0]); // will clear a timer attached to the first node, stop render in real time.
|
||||
**/
|
||||
timeagoFactory.cancel = function(node) {
|
||||
var tid;
|
||||
// assigning in if statement to save space
|
||||
if (node) {
|
||||
tid = getAttr(node, ATTR_DATA_TID); // get the timer of DOM node(native / jq).
|
||||
if (tid) {
|
||||
clearTimeout(tid);
|
||||
delete timers[tid];
|
||||
}
|
||||
} else {
|
||||
for (tid in timers) clearTimeout(tid);
|
||||
timers = {};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* timeago: the function to get `timeago` instance.
|
||||
* - nowDate: the relative date, default is new Date().
|
||||
*
|
||||
* How to use it?
|
||||
* var timeagoFactory = require('timeago.js');
|
||||
* var timeago = timeagoFactory(); // all use default.
|
||||
* var timeago = timeagoFactory('2016-09-10'); // the relative date is 2016-09-10, so the 2016-09-11 will be 1 day ago.
|
||||
**/
|
||||
return timeagoFactory;
|
||||
})();
|
|
@ -18,7 +18,12 @@ function clock(d): VNode | undefined {
|
|||
if (d.isFinished) return;
|
||||
if (d.secondsToStart) {
|
||||
if (d.secondsToStart > oneDayInSeconds) return h('div.clock', [
|
||||
h('time.moment-from-now.shy', { attrs: { datetime: d.startsAt } }, d.startsAt)
|
||||
h('time.timeago.shy', {
|
||||
attrs: {
|
||||
title: new Date(d.startsAt).toLocaleString(),
|
||||
datetime: Date.now() + (d.secondsToStart * 1000)
|
||||
}
|
||||
})
|
||||
]);
|
||||
return h('div.clock.created', {
|
||||
hook: startClock(d.secondsToStart)
|
||||
|
|
|
@ -46,9 +46,9 @@ function nextTournament(ctrl: TournamentController): MaybeVNodes {
|
|||
' • ',
|
||||
...(t.finishesAt ? [
|
||||
'finishes ',
|
||||
h('time.moment-from-now', { attrs: { datetime: t.finishesAt } }, t.finishesAt)
|
||||
h('time.timeago', { attrs: { datetime: t.finishesAt } })
|
||||
] : [
|
||||
h('time.moment-from-now', { attrs: { datetime: t.startsAt } }, t.startsAt)
|
||||
h('time.timeago', { attrs: { datetime: t.startsAt } })
|
||||
])
|
||||
])
|
||||
])
|
||||
|
|
Loading…
Reference in New Issue