mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-30 14:57:59 +01:00
preserve vote/fave status on navigation (fixes philomena-dev/philomena#82)
This commit is contained in:
parent
c1ec2b3df2
commit
0cf48f0eab
2 changed files with 39 additions and 0 deletions
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { fetchJson } from './utils/requests';
|
import { fetchJson } from './utils/requests';
|
||||||
|
import { $ } from './utils/dom';
|
||||||
|
|
||||||
const endpoints = {
|
const endpoints = {
|
||||||
vote(imageId) { return `/images/${imageId}/vote` },
|
vote(imageId) { return `/images/${imageId}/vote` },
|
||||||
|
@ -19,6 +20,34 @@ function onImage(id, selector, cb) {
|
||||||
document.querySelectorAll(`${selector}[data-image-id="${id}"]`), cb);
|
document.querySelectorAll(`${selector}[data-image-id="${id}"]`), cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Since JS modifications to webpages, except form inputs, are not stored
|
||||||
|
* in the browser navigation history, we store a cache of the changes in a
|
||||||
|
* form to allow interactions to persist on navigation. */
|
||||||
|
|
||||||
|
function getCache() {
|
||||||
|
const cacheEl = $('.js-interaction-cache');
|
||||||
|
return Object.values(JSON.parse(cacheEl.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function modifyCache(callback) {
|
||||||
|
const cacheEl = $('.js-interaction-cache');
|
||||||
|
cacheEl.value = JSON.stringify(callback(JSON.parse(cacheEl.value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function cacheStatus(image_id, interaction_type, value) {
|
||||||
|
modifyCache(cache => {
|
||||||
|
cache[`${image_id}${interaction_type}`] = { image_id, interaction_type, value };
|
||||||
|
return cache;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function uncacheStatus(image_id, interaction_type) {
|
||||||
|
modifyCache(cache => {
|
||||||
|
delete cache[`${image_id}${interaction_type}`];
|
||||||
|
return cache;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function setScore(imageId, data) {
|
function setScore(imageId, data) {
|
||||||
onImage(imageId, '.score',
|
onImage(imageId, '.score',
|
||||||
el => el.textContent = data.score);
|
el => el.textContent = data.score);
|
||||||
|
@ -34,26 +63,32 @@ function setScore(imageId, data) {
|
||||||
* Their classes also effect their behavior due to event delegation. */
|
* Their classes also effect their behavior due to event delegation. */
|
||||||
|
|
||||||
function showUpvoted(imageId) {
|
function showUpvoted(imageId) {
|
||||||
|
cacheStatus(imageId, 'voted', 'up');
|
||||||
onImage(imageId, '.interaction--upvote',
|
onImage(imageId, '.interaction--upvote',
|
||||||
el => el.classList.add('active'));
|
el => el.classList.add('active'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function showDownvoted(imageId) {
|
function showDownvoted(imageId) {
|
||||||
|
cacheStatus(imageId, 'voted', 'down');
|
||||||
onImage(imageId, '.interaction--downvote',
|
onImage(imageId, '.interaction--downvote',
|
||||||
el => el.classList.add('active'));
|
el => el.classList.add('active'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function showFaved(imageId) {
|
function showFaved(imageId) {
|
||||||
|
cacheStatus(imageId, 'faved', '');
|
||||||
onImage(imageId, '.interaction--fave',
|
onImage(imageId, '.interaction--fave',
|
||||||
el => el.classList.add('active'));
|
el => el.classList.add('active'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function showHidden(imageId) {
|
function showHidden(imageId) {
|
||||||
|
cacheStatus(imageId, 'hidden', '');
|
||||||
onImage(imageId, '.interaction--hide',
|
onImage(imageId, '.interaction--hide',
|
||||||
el => el.classList.add('active'));
|
el => el.classList.add('active'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetVoted(imageId) {
|
function resetVoted(imageId) {
|
||||||
|
uncacheStatus(imageId, 'voted');
|
||||||
|
|
||||||
onImage(imageId, '.interaction--upvote',
|
onImage(imageId, '.interaction--upvote',
|
||||||
el => el.classList.remove('active'));
|
el => el.classList.remove('active'));
|
||||||
|
|
||||||
|
@ -62,11 +97,13 @@ function resetVoted(imageId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetFaved(imageId) {
|
function resetFaved(imageId) {
|
||||||
|
uncacheStatus(imageId, 'faved');
|
||||||
onImage(imageId, '.interaction--fave',
|
onImage(imageId, '.interaction--fave',
|
||||||
el => el.classList.remove('active'));
|
el => el.classList.remove('active'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetHidden(imageId) {
|
function resetHidden(imageId) {
|
||||||
|
uncacheStatus(imageId, 'hidden');
|
||||||
onImage(imageId, '.interaction--hide',
|
onImage(imageId, '.interaction--hide',
|
||||||
el => el.classList.remove('active'));
|
el => el.classList.remove('active'));
|
||||||
}
|
}
|
||||||
|
@ -97,6 +134,7 @@ function loadInteractions() {
|
||||||
|
|
||||||
/* Set up the actual interactions */
|
/* Set up the actual interactions */
|
||||||
displayInteractionSet(window.booru.interactions);
|
displayInteractionSet(window.booru.interactions);
|
||||||
|
displayInteractionSet(getCache());
|
||||||
|
|
||||||
/* Next part is only for image index pages
|
/* Next part is only for image index pages
|
||||||
* TODO: find a better way to do this */
|
* TODO: find a better way to do this */
|
||||||
|
|
|
@ -29,4 +29,5 @@ html lang="en"
|
||||||
main#content class=layout_class(@conn)
|
main#content class=layout_class(@conn)
|
||||||
= @inner_content
|
= @inner_content
|
||||||
= render PhilomenaWeb.LayoutView, "_footer.html", assigns
|
= render PhilomenaWeb.LayoutView, "_footer.html", assigns
|
||||||
|
form.hidden: input.js-interaction-cache type="hidden" value="{}"
|
||||||
= clientside_data(@conn)
|
= clientside_data(@conn)
|
||||||
|
|
Loading…
Reference in a new issue