如何用更少的Javascript行表达这一点?

时间:2018-01-13 14:50:32

标签: javascript html yaml jekyll liquid

我正在使用一些JS来计算自上次发布以来的时间(即“发布于2小时前”):

function ago(date) {
function render(n, unit) {
    return n + " " + unit + ((n == 1) ? "" : "s") + " ago";
}

var seconds = Math.floor((new Date() - date) / 1000);

var interval = Math.floor(seconds / (60 * 60 * 24 * 30 * 365));
if (Math.floor(seconds / (60 * 60 * 24 * 30 * 365)) >= 1) {
    return render(interval, "year");
}
interval = Math.floor(seconds / (60 * 60 * 24 * 30));
if (interval >= 1) {
    return render(interval, "month");
}
interval = Math.floor(seconds / (60 * 60 * 24));
if (interval >= 1) {
    return render(interval, "day");
}
interval = Math.floor(seconds / (60 * 60));
if (interval >= 1) {
    return render(interval, "hour");
}
interval = Math.floor(seconds / 60);
if (interval >= 1) {
    return render(interval, "minute");
}
interval = Math.floor(seconds);
return render(interval, "second");
}

然后将其包含在索引页面上,每个帖子旁边:

var date = 
Date.parse(document.getElementById("postedon").getAttribute("datetime"));
document.getElementById("postedago").innerHTML = ago(date);

这是HTML:

<time id="{{ post.postedon }}" datetime="{{ post.date | date_to_xmlschema }}">
<span id="{{ post.postedago }}"></span>
</time>

请注意,我正在使用Liquid&amp; amp;在每个帖子的前端设置元素的ID和属性。 YAML(和杰基尔一起):

---
date: 2018-1-4 02:00:00 +0100
postedago: postedago-post1
postedon: postedon-post2
---

问题是我必须像这样手动设置每个帖子的JS代码:

var date = 
Date.parse(document.getElementById("postedon").getAttribute("datetime"));
document.getElementById("postedago").innerHTML = ago(date);

var date = 
Date.parse(document.getElementById("postedon2").getAttribute("datetime"));
document.getElementById("postedago2").innerHTML = ago(date);

var date = 
Date.parse(document.getElementById("postedon3").getAttribute("datetime"));
document.getElementById("postedago3").innerHTML = ago(date);

否则它不会显示所有帖子的时间,只有一个。

我尝试将JS中的元素id设置为前面的参数但它不起作用(基本上让Jekyll替换JS文件中的液体标签):

var date = 
Date.parse(document.getElementById("{{ post.postedon }}").getAttribute("datetime"));
document.getElementById("{{ post.postedago }}").innerHTML = ago(date);

我尝试在js文件的顶部添加前面的破折号,但它仍然不起作用(在SO上引用:Reach Jekyll Variables With JavaScript and Pass it Throught DOM Manipulation

---
---
//rest of your JavaScript

也许还有其他方法可以做到这一点,我没有想过?

感谢您花时间阅读本文,我非常感谢您的帮助!

PS:在每个帖子的页面上引用 timeago 脚本实现(不在包含所有帖子的索引页面上):https://hejnoah.com/posts/timeago.html

4 个答案:

答案 0 :(得分:2)

您应该为HTML元素添加class属性,以便您可以使用getElementsByClassName()在循环中迭代所有这些属性。

HTML:

<time class="postedon" id="{{ post.postedon }}" datetime="{{ post.date | date_to_xmlschema }}">
    <span class="postedago" id="{{ post.postedago }}"></span>
</time>

JS:

const timeElems = document.getElementsByClassName('postedon');

for (let i = 0, len = timeElems.length; i < len; i++) {
  let date = Date.parse(timeElems[i].getAttribute("datetime"));
  timeElems[i].firstElementChild.innerHTML = ago(date);
}

现在您不必手动为每个帖子写出JS。您可以类似地使用getElementsByTagName('time'),假设这是您使用该标记的唯一地方。

答案 1 :(得分:1)

这很简单,你可以使用一些JS(/javascript-time-ago)就绪..

只需使用以下示例..

  

timeAgo.format(new Date())---&gt;将输出//“刚才”

如果您将日期格式赋予它,将给出多长时间。

答案 2 :(得分:1)

首先,您的ago功能可以简化和缩小。

然后我使用属性以选择器开头,querySelectorAll来获取元素,然后使用.forEach()设置textContent属性。

&#13;
&#13;
function render(n, unit) {
  return n + " " + unit + ((n == 1) ? "" : "s") + " ago";
}
const labels = ["year", "month", "day", "hour", "minute", "second"];
const products = [1, 60, 60, 24, 30, 365]
  .map((n, i, a) => a.slice(0, a.length-i).reduce((p, n) => p * n, 1));

function ago(date) {
  var seconds = Math.floor((new Date() - Date.parse(date)) / 1000);

  return labels.reduce((res, lab, i) => {
    const interval = Math.floor(seconds / products[i]);
    return res ? res : interval >= 1 ? render(interval, lab) : "";
  }, "");
}


document.querySelectorAll("[id^=postedon]").forEach(el =>
  el.querySelector('#' + el.id.replace('postedon', 'postedago'))
  .textContent = ago(el.getAttribute("datetime"))
);
&#13;
<time id="postedon0" datetime="2018-1-4 02:00:00 +0100">
  <span id="postedago0"></span>
</time>
<time id="postedon1" datetime="2018-1-7 02:00:00 +0100">
  <span id="postedago1"></span>
</time>
<time id="postedon2" datetime="2018-1-9 02:00:00 +0100">
  <span id="postedago2"></span>
</time>

<time id="postedon3" datetime="2018-1-13 02:00:00 +0100">
  <span id="postedago3"></span>
</time>
&#13;
&#13;
&#13;

另请注意,我使用.textContent代替.innerHTML,因为您实际上并未设置任何HTML内容。

另请注意,Date.parse在Firefox中无法使用该日期格式。

答案 3 :(得分:1)

另一个如何计算它多久以前的例子。

function ago(date) {
  var units = [
    { name : 'year', ms: 1000 * 60 * 60 * 24 * 30 * 365 },
    { name : 'month', ms: 1000 * 60 * 60 * 24 * 30 },
    { name : 'fortnight', ms : 1000 * 60 * 60 * 24 * 14 }, // yep.. I head that was a thing.
    { name : 'day', ms: 1000 * 60 * 60 * 24 },
    { name : 'hour', ms: 1000 * 60 * 60 },
    { name : 'second', ms: 1000 *60 },
  ];

  var ms = new Date() - date;
  var item = units.find( item => ms / item.ms > 1 );
  if (!item) item = units[ units.length - 1 ]; // if not found, use the last one.
  var value = Math.floor( ms / item.ms );

  return value + " " + item.name + ((value == 1) ? "" : "s") + " ago";
}