2019-09-30 15:38:41 +03:00
|
|
|
/**
|
|
|
|
* Count pageviews form GA or local cache file.
|
|
|
|
*
|
|
|
|
* Dependences:
|
|
|
|
* - jQuery
|
2020-04-01 15:33:49 +03:00
|
|
|
* - countUp.js <https://github.com/inorganik/countUp.js>
|
2019-09-30 15:38:41 +03:00
|
|
|
*
|
2020-01-02 16:17:49 +03:00
|
|
|
* v2.0
|
|
|
|
* https://github.com/cotes2020/jekyll-theme-chirpy
|
2019-09-30 15:38:41 +03:00
|
|
|
* © 2018-2019 Cotes Chung
|
|
|
|
* MIT License
|
|
|
|
*/
|
|
|
|
|
2020-03-19 13:56:54 +03:00
|
|
|
function countUp(min, max, destId) {
|
2019-09-30 15:38:41 +03:00
|
|
|
if (min < max) {
|
2020-03-19 13:56:54 +03:00
|
|
|
var numAnim = new CountUp(destId, min, max);
|
2019-09-30 15:38:41 +03:00
|
|
|
if (!numAnim.error) {
|
|
|
|
numAnim.start();
|
|
|
|
} else {
|
|
|
|
console.error(numAnim.error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-19 13:56:54 +03:00
|
|
|
|
2019-09-30 15:38:41 +03:00
|
|
|
function countPV(path, rows) {
|
|
|
|
/* path permalink looks like: '/posts/post-title/' */
|
|
|
|
var fileName = path.replace(/\/posts\//g, '').replace(/\//g, '.html'); /* e.g. post-title.html */
|
|
|
|
var count = 0;
|
|
|
|
|
|
|
|
var _v2_url = path.replace(/posts\//g, ''); /* the v2.0+ blog permalink: "/post-title/" */
|
|
|
|
|
|
|
|
for (var i = 0; i < rows.length; ++i) {
|
|
|
|
var gaPath = rows[i][0];
|
|
|
|
if (gaPath == path ||
|
|
|
|
gaPath == _v2_url ||
|
|
|
|
gaPath.concat('/') == _v2_url ||
|
2020-05-29 19:48:10 +03:00
|
|
|
gaPath.slice(gaPath.lastIndexOf('/') + 1) === fileName) { /* old permalink record */
|
2019-09-30 15:38:41 +03:00
|
|
|
count += parseInt(rows[i][1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2019-12-18 22:07:02 +03:00
|
|
|
|
2020-03-19 13:56:54 +03:00
|
|
|
function tacklePV(rows, path, elem, hasInit) {
|
|
|
|
var count = countPV(path, rows);
|
|
|
|
count = (count == 0 ? 1 : count);
|
|
|
|
|
|
|
|
if (!hasInit) {
|
|
|
|
elem.text(new Intl.NumberFormat().format(count));
|
|
|
|
} else {
|
|
|
|
var initCount = parseInt(elem.text().replace(/,/g, ''));
|
|
|
|
if (count > initCount) {
|
|
|
|
countUp(initCount, count, elem.attr('id'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-18 22:07:02 +03:00
|
|
|
function displayPageviews(data) {
|
|
|
|
if (data === undefined) {
|
2019-09-30 15:38:41 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-12-18 22:07:02 +03:00
|
|
|
var hasInit = getInitStatus();
|
|
|
|
var rows = data.rows;
|
|
|
|
|
2020-05-29 19:48:10 +03:00
|
|
|
if ($("#post-list").length > 0) { /* the Home page */
|
2019-09-30 15:38:41 +03:00
|
|
|
$(".post-preview").each(function() {
|
|
|
|
var path = $(this).children("h1").children("a").attr("href");
|
2020-03-19 13:56:54 +03:00
|
|
|
tacklePV(rows, path, $(this).find('.pageviews'), hasInit);
|
2019-09-30 15:38:41 +03:00
|
|
|
});
|
|
|
|
|
2020-05-29 19:48:10 +03:00
|
|
|
} else if ($(".post").length > 0) { /* the post */
|
2019-09-30 15:38:41 +03:00
|
|
|
var path = window.location.pathname;
|
2020-03-19 13:56:54 +03:00
|
|
|
tacklePV(rows, path, $('#pv'), hasInit);
|
2019-09-30 15:38:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-18 22:07:02 +03:00
|
|
|
|
|
|
|
var getInitStatus = (function() {
|
|
|
|
var hasInit = false;
|
|
|
|
return function() {
|
2020-04-01 15:33:49 +03:00
|
|
|
let ret = hasInit;
|
|
|
|
if (!hasInit) {
|
2019-12-18 22:07:02 +03:00
|
|
|
hasInit = true;
|
|
|
|
}
|
2020-04-01 15:33:49 +03:00
|
|
|
return ret;
|
2019-12-18 22:07:02 +03:00
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
2020-04-01 15:33:49 +03:00
|
|
|
var PvCache = (function() {
|
|
|
|
const KEY_PV = "pv";
|
|
|
|
const KEY_CREATION = "pv-created-date";
|
|
|
|
const KEY_PV_TYPE = "pv-type";
|
|
|
|
|
|
|
|
var PvType = {
|
|
|
|
ORIGIN: "origin",
|
|
|
|
PROXY: "proxy"
|
|
|
|
};
|
|
|
|
|
|
|
|
function get(key) {
|
|
|
|
return localStorage.getItem(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
function set(key, val) {
|
|
|
|
localStorage.setItem(key, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
getData: function() {
|
|
|
|
return JSON.parse(localStorage.getItem(KEY_PV) );
|
|
|
|
},
|
|
|
|
saveOriginCache: function(pv) {
|
|
|
|
set(KEY_PV, pv);
|
|
|
|
set(KEY_PV_TYPE, PvType.ORIGIN );
|
|
|
|
set(KEY_CREATION, new Date().toJSON() );
|
|
|
|
},
|
|
|
|
saveProxyCache: function(pv) {
|
|
|
|
set(KEY_PV, pv);
|
|
|
|
set(KEY_PV_TYPE, PvType.PROXY );
|
|
|
|
set(KEY_CREATION, new Date().toJSON() );
|
|
|
|
},
|
|
|
|
isOriginCache: function() {
|
|
|
|
return get(KEY_PV_TYPE) == PvType.ORIGIN;
|
|
|
|
},
|
|
|
|
isProxyCache: function() {
|
|
|
|
return get(KEY_PV_TYPE) == PvType.PROXY;
|
|
|
|
},
|
|
|
|
isExpired: function() {
|
|
|
|
if (PvCache.isOriginCache() ) {
|
|
|
|
let date = new Date(get(KEY_CREATION));
|
2020-05-29 19:48:10 +03:00
|
|
|
date.setDate(date.getDate() + 1); /* fetch origin-data every day */
|
2020-04-01 15:33:49 +03:00
|
|
|
return Date.now() >= date.getTime();
|
|
|
|
|
|
|
|
} else if (PvCache.isProxyCache() ) {
|
|
|
|
let date = new Date(get(KEY_CREATION) );
|
2020-05-29 19:48:10 +03:00
|
|
|
date.setHours(date.getHours() + 1); /* proxy-data is updated every hour */
|
2020-04-01 15:33:49 +03:00
|
|
|
return Date.now() >= date.getTime();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
getAllPagevies: function() {
|
|
|
|
return PvCache.getData().totalsForAllResults["ga:pageviews"];
|
|
|
|
},
|
|
|
|
newerThan: function(pv) {
|
|
|
|
return PvCache.getAllPagevies() > pv.totalsForAllResults["ga:pageviews"];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-29 19:48:10 +03:00
|
|
|
})(); /* PvCache */
|
2020-04-01 15:33:49 +03:00
|
|
|
|
|
|
|
|
|
|
|
function fetchOriginPageviews(pvData) {
|
|
|
|
if (pvData === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
displayPageviews(pvData);
|
|
|
|
PvCache.saveOriginCache(JSON.stringify(pvData));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function fetchProxyPageviews() {
|
2020-05-29 19:48:10 +03:00
|
|
|
let proxy = JSON.parse(proxyData); /* see file '/assets/data/pv-data.json' */
|
2020-04-01 15:33:49 +03:00
|
|
|
$.ajax({
|
|
|
|
type: 'GET',
|
|
|
|
url: proxy.url,
|
|
|
|
dataType: 'jsonp',
|
|
|
|
jsonpCallback: "displayPageviews",
|
|
|
|
success: function(data, textStatus, jqXHR) {
|
|
|
|
PvCache.saveProxyCache(JSON.stringify(data));
|
|
|
|
},
|
|
|
|
error: function(jqXHR, textStatus, errorThrown) {
|
|
|
|
console.log("Failed to load pageviews from proxy server: " + errorThrown);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-30 15:38:41 +03:00
|
|
|
$(function() {
|
2020-04-01 15:33:49 +03:00
|
|
|
|
2019-09-30 15:38:41 +03:00
|
|
|
if ($('.pageviews').length > 0) {
|
|
|
|
|
2020-04-01 15:33:49 +03:00
|
|
|
let cache = PvCache.getData();
|
|
|
|
|
|
|
|
if (cache) {
|
|
|
|
if (PvCache.isExpired()) {
|
|
|
|
if (PvCache.isProxyCache() ) {
|
2020-05-11 21:16:36 +03:00
|
|
|
let originPvData = pageviews ? JSON.parse(pageviews) : undefined;
|
2020-04-01 15:33:49 +03:00
|
|
|
if (originPvData) {
|
|
|
|
if (PvCache.newerThan(originPvData)) {
|
|
|
|
displayPageviews(cache);
|
|
|
|
} else {
|
|
|
|
fetchOriginPageviews(originPvData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fetchProxyPageviews();
|
|
|
|
|
|
|
|
} else if (PvCache.isOriginCache() ) {
|
|
|
|
fetchOriginPageviews(originPvData);
|
|
|
|
fetchProxyPageviews();
|
2019-09-30 15:38:41 +03:00
|
|
|
}
|
|
|
|
|
2020-05-29 19:48:10 +03:00
|
|
|
} else { /* still valid */
|
2020-04-01 15:33:49 +03:00
|
|
|
displayPageviews(cache);
|
|
|
|
|
|
|
|
if (PvCache.isOriginCache() ) {
|
|
|
|
fetchProxyPageviews();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2020-05-11 21:16:36 +03:00
|
|
|
let originPvData = pageviews ? JSON.parse(pageviews) : undefined;
|
2020-04-01 15:33:49 +03:00
|
|
|
fetchOriginPageviews(originPvData);
|
|
|
|
fetchProxyPageviews();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2019-09-30 15:38:41 +03:00
|
|
|
|
2020-03-19 13:56:54 +03:00
|
|
|
});
|