134 lines
No EOL
4 KiB
JavaScript
134 lines
No EOL
4 KiB
JavaScript
frappe.pages['characters'].on_page_load = function(wrapper) {
|
|
var page = frappe.ui.make_app_page({
|
|
parent: wrapper,
|
|
title: 'My Characters',
|
|
single_column: true
|
|
});
|
|
|
|
frappe.db.get_list('Character', {
|
|
fields: ['name', 'type', 'profile_picture', 'type.frame_image', 'type.background_image', 'death'],
|
|
filters: {
|
|
//owner: frappe.session.user
|
|
}
|
|
}).then(docs => {
|
|
render_cards(docs, wrapper);
|
|
|
|
const deathclocks = document.getElementsByClassName("deathclock");
|
|
|
|
function createDigit() {
|
|
const digit = document.createElement("div");
|
|
digit.className = "digit";
|
|
digit.dataset.value = "0";
|
|
|
|
digit.innerHTML = `
|
|
<div class="flipcard">0</div>
|
|
<div class="shine"></div>
|
|
`;
|
|
|
|
return digit;
|
|
}
|
|
|
|
function flipDigit(digit, nextValue) {
|
|
const currentValue = digit.dataset.value;
|
|
if (currentValue === String(nextValue)) return;
|
|
|
|
const flipcard = digit.querySelector(".flipcard");
|
|
|
|
const topFlip = document.createElement("div");
|
|
topFlip.className = "top flip-top";
|
|
topFlip.textContent = currentValue;
|
|
|
|
const bottomFlip = document.createElement("div");
|
|
bottomFlip.className = "bottom flip-bottom";
|
|
bottomFlip.textContent = nextValue;
|
|
|
|
digit.appendChild(topFlip);
|
|
|
|
setTimeout(() => {
|
|
flipcard.textContent = nextValue;
|
|
digit.appendChild(bottomFlip);
|
|
}, 140);
|
|
|
|
setTimeout(() => {
|
|
topFlip.remove();
|
|
bottomFlip.remove();
|
|
digit.dataset.value = String(nextValue);
|
|
}, 320);
|
|
}
|
|
|
|
function countUpDigit(digit, target, delay = 0) {
|
|
let value = 0;
|
|
|
|
setTimeout(() => {
|
|
const timer = setInterval(() => {
|
|
if (value >= target) {
|
|
clearInterval(timer);
|
|
return;
|
|
}
|
|
|
|
value++;
|
|
flipDigit(digit, value % 10);
|
|
}, 360);
|
|
}, delay);
|
|
}
|
|
|
|
function initDisplay(clock) {
|
|
const value = clock.dataset.value || "0000";
|
|
clock.innerHTML = "";
|
|
|
|
const digits = value.padStart(4, "0").slice(-4).split("");
|
|
|
|
digits.forEach((targetDigit, index) => {
|
|
const digit = createDigit();
|
|
clock.appendChild(digit);
|
|
|
|
countUpDigit(
|
|
digit,
|
|
Number(targetDigit),
|
|
index * 160
|
|
);
|
|
});
|
|
}
|
|
for (let i = 0; i < deathclocks.length; i++) {
|
|
initDisplay(deathclocks.item(i));
|
|
}
|
|
});
|
|
}
|
|
|
|
function render_cards(docs, wrapper) {
|
|
const container = $('<div class="row m-2"></div>');
|
|
|
|
function days_until(deathdate) {
|
|
const targetDate = new Date(deathdate.replace(' ', 'T'));
|
|
const now = new Date();
|
|
|
|
const diffMs = targetDate - now;
|
|
|
|
const diffDays = diffMs / (1000 * 60 * 60 * 24);
|
|
|
|
return Math.round(diffDays);
|
|
}
|
|
|
|
docs.forEach(doc => {
|
|
const card = $(`
|
|
<div class="col-md-4 mb-3">
|
|
<div class="card p-3">
|
|
<div class="deathclock-wrapper">
|
|
<div class="deathclock" data-value="${days_until(doc.death)}"></div>
|
|
</div>
|
|
<h5><a href="/desk/character/${doc.name}">${doc.name}</a></h5>
|
|
<p>${doc.type}</p>
|
|
<div class="image-stack">
|
|
<img src="${doc.background_image}" class="layer bg">
|
|
<img src="${doc.profile_picture}" class="layer fg">
|
|
<img src="${doc.frame_image}" class="layer frame">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`);
|
|
|
|
container.append(card);
|
|
});
|
|
|
|
$(wrapper).find('.layout-main-section').html(container);
|
|
} |