diff options
author | ArthurHoaro <arthur@hoa.ro> | 2020-10-15 11:46:24 +0200 |
---|---|---|
committer | ArthurHoaro <arthur@hoa.ro> | 2020-10-20 10:15:18 +0200 |
commit | 21e72da9ee34cec56b10c83ae0c75b4bf320dfcb (patch) | |
tree | b6c0b8208f004e1b2b37b1af54e8d4c40310d56e /assets/common | |
parent | 9b3c1270bcbe4f8e30e0160da8badd43dd94871a (diff) | |
download | Shaarli-21e72da9ee34cec56b10c83ae0c75b4bf320dfcb.tar.gz Shaarli-21e72da9ee34cec56b10c83ae0c75b4bf320dfcb.tar.zst Shaarli-21e72da9ee34cec56b10c83ae0c75b4bf320dfcb.zip |
Asynchronous retrieval of bookmark's thumbnails
This feature is based general.enable_async_metadata setting and works with existing metadata.js file.
The script is compatible with any template:
- the thumbnail div bloc must have attribute
- the bookmark bloc must have attribute with the bookmark ID as value
Fixes #1564
Diffstat (limited to 'assets/common')
-rw-r--r-- | assets/common/js/metadata.js | 106 |
1 files changed, 85 insertions, 21 deletions
diff --git a/assets/common/js/metadata.js b/assets/common/js/metadata.js index 5200b481..2b013364 100644 --- a/assets/common/js/metadata.js +++ b/assets/common/js/metadata.js | |||
@@ -1,5 +1,19 @@ | |||
1 | import he from 'he'; | 1 | import he from 'he'; |
2 | 2 | ||
3 | /** | ||
4 | * This script is used to retrieve bookmarks metadata asynchronously: | ||
5 | * - title, description and keywords while creating a new bookmark | ||
6 | * - thumbnails while visiting the bookmark list | ||
7 | * | ||
8 | * Note: it should only be included if the user is logged in | ||
9 | * and the setting general.enable_async_metadata is enabled. | ||
10 | */ | ||
11 | |||
12 | /** | ||
13 | * Removes given input loaders - used in edit link template. | ||
14 | * | ||
15 | * @param {object} loaders List of input DOM element that need to be cleared | ||
16 | */ | ||
3 | function clearLoaders(loaders) { | 17 | function clearLoaders(loaders) { |
4 | if (loaders != null && loaders.length > 0) { | 18 | if (loaders != null && loaders.length > 0) { |
5 | [...loaders].forEach((loader) => { | 19 | [...loaders].forEach((loader) => { |
@@ -8,32 +22,82 @@ function clearLoaders(loaders) { | |||
8 | } | 22 | } |
9 | } | 23 | } |
10 | 24 | ||
25 | /** | ||
26 | * AJAX request to update the thumbnail of a bookmark with the provided ID. | ||
27 | * If a thumbnail is retrieved, it updates the divElement with the image src, and displays it. | ||
28 | * | ||
29 | * @param {string} basePath Shaarli subfolder for XHR requests | ||
30 | * @param {object} divElement Main <div> DOM element containing the thumbnail placeholder | ||
31 | * @param {int} id Bookmark ID to update | ||
32 | */ | ||
33 | function updateThumb(basePath, divElement, id) { | ||
34 | const xhr = new XMLHttpRequest(); | ||
35 | xhr.open('PATCH', `${basePath}/admin/shaare/${id}/update-thumbnail`); | ||
36 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); | ||
37 | xhr.responseType = 'json'; | ||
38 | xhr.onload = () => { | ||
39 | if (xhr.status !== 200) { | ||
40 | alert(`An error occurred. Return code: ${xhr.status}`); | ||
41 | } else { | ||
42 | const { response } = xhr; | ||
43 | |||
44 | if (response.thumbnail !== false) { | ||
45 | const imgElement = divElement.querySelector('img'); | ||
46 | |||
47 | imgElement.src = response.thumbnail; | ||
48 | imgElement.dataset.src = response.thumbnail; | ||
49 | imgElement.style.opacity = '1'; | ||
50 | divElement.classList.remove('hidden'); | ||
51 | } | ||
52 | } | ||
53 | }; | ||
54 | xhr.send(); | ||
55 | } | ||
56 | |||
11 | (() => { | 57 | (() => { |
58 | const basePath = document.querySelector('input[name="js_base_path"]').value; | ||
12 | const loaders = document.querySelectorAll('.loading-input'); | 59 | const loaders = document.querySelectorAll('.loading-input'); |
60 | |||
61 | /* | ||
62 | * METADATA FOR EDIT BOOKMARK PAGE | ||
63 | */ | ||
13 | const inputTitle = document.querySelector('input[name="lf_title"]'); | 64 | const inputTitle = document.querySelector('input[name="lf_title"]'); |
14 | if (inputTitle != null && inputTitle.value.length > 0) { | 65 | if (inputTitle != null) { |
15 | clearLoaders(loaders); | 66 | if (inputTitle.value.length > 0) { |
16 | return; | 67 | clearLoaders(loaders); |
17 | } | 68 | return; |
69 | } | ||
18 | 70 | ||
19 | const url = document.querySelector('input[name="lf_url"]').value; | 71 | const url = document.querySelector('input[name="lf_url"]').value; |
20 | const basePath = document.querySelector('input[name="js_base_path"]').value; | ||
21 | 72 | ||
22 | const xhr = new XMLHttpRequest(); | 73 | const xhr = new XMLHttpRequest(); |
23 | xhr.open('GET', `${basePath}/admin/metadata?url=${encodeURI(url)}`, true); | 74 | xhr.open('GET', `${basePath}/admin/metadata?url=${encodeURI(url)}`, true); |
24 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); | 75 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); |
25 | xhr.onload = () => { | 76 | xhr.onload = () => { |
26 | const result = JSON.parse(xhr.response); | 77 | const result = JSON.parse(xhr.response); |
27 | Object.keys(result).forEach((key) => { | 78 | Object.keys(result).forEach((key) => { |
28 | if (result[key] !== null && result[key].length) { | 79 | if (result[key] !== null && result[key].length) { |
29 | const element = document.querySelector(`input[name="lf_${key}"], textarea[name="lf_${key}"]`); | 80 | const element = document.querySelector(`input[name="lf_${key}"], textarea[name="lf_${key}"]`); |
30 | if (element != null && element.value.length === 0) { | 81 | if (element != null && element.value.length === 0) { |
31 | element.value = he.decode(result[key]); | 82 | element.value = he.decode(result[key]); |
83 | } | ||
32 | } | 84 | } |
33 | } | 85 | }); |
34 | }); | 86 | clearLoaders(loaders); |
35 | clearLoaders(loaders); | 87 | }; |
36 | }; | ||
37 | 88 | ||
38 | xhr.send(); | 89 | xhr.send(); |
90 | } | ||
91 | |||
92 | /* | ||
93 | * METADATA FOR THUMBNAIL RETRIEVAL | ||
94 | */ | ||
95 | const thumbsToLoad = document.querySelectorAll('div[data-async-thumbnail]'); | ||
96 | if (thumbsToLoad != null) { | ||
97 | [...thumbsToLoad].forEach((divElement) => { | ||
98 | const { id } = divElement.closest('[data-id]').dataset; | ||
99 | |||
100 | updateThumb(basePath, divElement, id); | ||
101 | }); | ||
102 | } | ||
39 | })(); | 103 | })(); |