uiMediaFullpage.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. $(() => {
  2. function serializeFileSize(size) {
  3. let units = [ 'o', 'Ko', 'Mo', 'Go', 'To' ];
  4. let idx = 0;
  5. while (size >= 800 && idx < units.length) {
  6. ++idx;
  7. size /= 1024;
  8. }
  9. size = Math.floor(size * 100) / 100;
  10. return `${size} ${units[idx]}`;
  11. }
  12. function displayMeta(key, value, isRo) {
  13. let li = document.createElement("li");
  14. let type = value?.type || null;
  15. let val = (value?.value !== undefined ? value.value : value);
  16. if (!val && val !== '')
  17. return null;
  18. if (type === 'date')
  19. val = val.toLocaleString();
  20. if (["dimension", "height", "width"].indexOf(key) >= 0)
  21. val += ' px';
  22. if (["fileSize"].indexOf(key) >= 0)
  23. val = serializeFileSize(val);
  24. if (key == 'fNumber')
  25. val = `f/ ${val}`;
  26. let keyTranslate = {
  27. fileSize: "File Size",
  28. photochamberImport: "Photochamber Imported",
  29. lensModel: "Lens Model",
  30. exposureTimeStr: "Exposure Time"
  31. };
  32. let keySpan = document.createElement('span');
  33. let valSpan = document.createElement('div');
  34. li.classList.add("row");
  35. keySpan.className = "metaKey col-xl-12 col-4";
  36. valSpan.className = "metaVal col-xl-12 col-8";
  37. let inputGroup = document.createElement('form');
  38. valSpan.appendChild(inputGroup);
  39. inputGroup.classList.add('input-group');
  40. keySpan.innerText = (keyTranslate[key] || (key[0].toUpperCase()+key.substr(1))) + ':';
  41. let valInput = document.createElement("input");
  42. valInput.classList.add("form-control");
  43. valInput.value = val;
  44. valInput.disabled = isRo;
  45. valInput.addEventListener('keyup', evt => evt.stopPropagation());
  46. valInput.addEventListener('keydown', evt => evt.stopPropagation());
  47. inputGroup.appendChild(valInput);
  48. if (!isRo) {
  49. let bt = document.createElement('button');
  50. bt.className = 'btn btn-outline-secondary';
  51. bt.type = 'button';
  52. bt.innerHTML = '<i class="bi bi-pen"></i>';
  53. inputGroup.appendChild(bt);
  54. bt.addEventListener('click', () => MediaStorage.Instance.setMetaValue(fullPageMediaDisplayed.md5sum, key, valInput.value));
  55. inputGroup.addEventListener('submit', evt => {
  56. evt.preventDefault();
  57. MediaStorage.Instance.setMetaValue(fullPageMediaDisplayed.md5sum, key, valInput.value);
  58. });
  59. }
  60. li.appendChild(keySpan);
  61. li.appendChild(valSpan);
  62. return li;
  63. }
  64. function displayMetas(metaData, isRo) {
  65. let metaList = document.createElement("ul");
  66. metaData.libraryPath = null;
  67. metaData.tags = metaData.fixedTags = null;
  68. if (metaData.exposureTime && metaData.exposureTimeStr)
  69. metaData.exposureTime = null;
  70. if (metaData.date && metaData.dateTime)
  71. metaData.dateTime = null;
  72. if (metaData.height && metaData.width) {
  73. metaData.dimension = { type: "string", value: `${metaData.width.value} x ${metaData.height.value}` }
  74. metaData.height = metaData.width = null;
  75. }
  76. for (let i of [ "date", "dimension", "height", "width", "fileSize" ]) {
  77. let metaItem = displayMeta(i, metaData[i], true);
  78. metaItem && metaList.appendChild(metaItem);
  79. metaData[i] = null;
  80. }
  81. for (let i of Object.keys(metaData).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))) {
  82. let metaItem = displayMeta(i, metaData[i], isRo || !MediaStorage.Instance.allMetaTypes[i]?.canWrite);
  83. metaItem && metaList.appendChild(metaItem);
  84. }
  85. if (!isRo)
  86. for (let i of ['geoCountry']) {
  87. if (!metaData[i]) {
  88. let metaItem = displayMeta(i, "", false);
  89. metaItem && metaList.appendChild(metaItem);
  90. }
  91. }
  92. return metaList;
  93. }
  94. function displayTags(fixedTagList, tagList, writeAccess) {
  95. let tagListUi = document.createElement("ul");
  96. tagListUi.className = "taglist";
  97. let createTagUiItem = (i, roTag) => {
  98. let uiItem = document.createElement("li");
  99. uiItem.className = "badge text-bg-light";
  100. let textItem = document.createElement("span");
  101. textItem.textContent = i;
  102. uiItem.appendChild(textItem);
  103. if (!roTag) {
  104. let btItem = document.createElement("a");
  105. btItem.className = "border-start bi bi-x removeBt";
  106. btItem.href = '#';
  107. btItem.addEventListener('click', e => {
  108. e.preventDefault();
  109. });
  110. uiItem.appendChild(btItem);
  111. }
  112. tagListUi.appendChild(uiItem);
  113. };
  114. for (let i of fixedTagList)
  115. createTagUiItem(i, true);
  116. for (let i of tagList)
  117. createTagUiItem(i, !writeAccess);
  118. return tagListUi;
  119. }
  120. function _displayMediaFullPage(fileName, imgUrl, metaData, downloadLink, writeAccess) {
  121. return new Promise(ok => {
  122. document.getElementById("pch-fullPagePreviewContainer").classList.add("loading");
  123. document.getElementById("pch-fullPageMedia-title").innerText = fileName;
  124. document.getElementById("pch-fullPagePreview").onceLoaded = ok;
  125. document.getElementById("pch-fullPagePreview").src = imgUrl;
  126. document.getElementById("pch-fullPageDetail").innerText = "";
  127. document.getElementById("pch-fullPageDetail").appendChild(displayMetas(Object.assign({}, metaData || {}), !writeAccess));
  128. document.getElementById("pch-fullPageDetail").appendChild(displayTags(metaData?.fixedTags || [], metaData?.tags || [], writeAccess));
  129. if (downloadLink) {
  130. document.getElementById("pch-fullPageDetail-dlButton").classList.remove("hidden");
  131. document.getElementById("pch-fullPageDetail-dlButton").dataset["link"] = downloadLink;
  132. } else {
  133. document.getElementById("pch-fullPageDetail-dlButton").classList.add("hidden");
  134. }
  135. });
  136. }
  137. function LoadPreviousMedia() {
  138. let media = MediaStorage.Instance.previousMedia(fullPageMediaDisplayed);
  139. if (media)
  140. window.displayMediaFullPage(media);
  141. }
  142. function LoadNextMedia() {
  143. let media = MediaStorage.Instance.nextMedia(fullPageMediaDisplayed);
  144. if (media)
  145. window.displayMediaFullPage(media);
  146. }
  147. function CloseFullpageMedia() {
  148. document.getElementById("pch-fullPageMedia").classList.add("hidden");
  149. fullPageMediaDisplayed = false;
  150. history.pushState({}, '', '#');
  151. }
  152. window.displayMediaFullPage = function(mediaItem) {
  153. document.getElementById("pch-fullPageMedia").classList.remove("hidden");
  154. fullPageMediaDisplayed = mediaItem;
  155. if (!mediaItem)
  156. return _displayMediaFullPage("Error", null, {}, [], null, false);
  157. let containerSize = document.getElementById("pch-fullPageMedia").getBoundingClientRect();
  158. let requestSize = mediaItem.resize(containerSize.width, containerSize.height);
  159. document.getElementById("pch-fullPagePreview").parentNode.style.maxWidth = "100%";
  160. document.getElementById("pch-fullPagePreview").parentNode.style.maxHeight = "100%";
  161. let meta = {
  162. ...mediaItem.meta,
  163. date: { type: 'date', value: mediaItem.date } || undefined,
  164. filename: mediaItem.filename ? { type: 'string', value: mediaItem.fileName } : undefined,
  165. fixedTags: mediaItem.fixedTags,
  166. tags: mediaItem.tags
  167. };
  168. if (document.location.hash != `#${mediaItem.md5sum}`)
  169. history.pushState({}, '', `#${mediaItem.md5sum}`);
  170. return _displayMediaFullPage(mediaItem.fileName, `${mediaItem.thumbnail}?w=${requestSize.width}&h=${requestSize.height}&q=6`, meta, mediaItem.original, mediaItem.writeAccess);
  171. }
  172. document.getElementById("pch-fullPageMedia-closeBt")
  173. .addEventListener("click", () => CloseFullpageMedia());
  174. document.getElementById("pch-fullPagePreview").addEventListener("load", () => {
  175. document.getElementById("pch-fullPagePreviewContainer").classList.remove("loading");
  176. let domItem = document.getElementById("pch-fullPagePreview");
  177. domItem.onceLoaded && domItem.onceLoaded();
  178. domItem.onceLoaded = null;
  179. });
  180. document.getElementById('pch-fullPageDetail-dlButton').addEventListener("click", (evt) => {
  181. if (!evt.target?.dataset?.link)
  182. return;
  183. let link = document.createElement('a');
  184. link.target='_blank';
  185. link.setAttribute("download", "");
  186. link.href = evt.target.dataset.link;
  187. link.click();
  188. });
  189. document.addEventListener("keyup", evt => {
  190. lastKeyboardEvent = evt;
  191. });
  192. document.addEventListener("keydown", evt => {
  193. lastKeyboardEvent = evt;
  194. if (!fullPageMediaDisplayed)
  195. return;
  196. if (evt.keyCode === 37 || evt.keyCode === 38)
  197. LoadPreviousMedia();
  198. else if (evt.keyCode === 39 || evt.keyCode === 40)
  199. LoadNextMedia();
  200. else if (evt.keyCode === 27)
  201. CloseFullpageMedia();
  202. else {
  203. console.log("Unregistered key event", evt.key, evt.keyCode);
  204. return;
  205. }
  206. evt.preventDefault();
  207. });
  208. });