Greasy Fork is available in English.

LighboxModern

Simple Lightbox

Tento skript by neměl být instalován přímo. Jedná se o knihovnu, kterou by měly jiné skripty využívat pomocí meta příkazu // @require https://update.greatest.deepsurf.us/scripts/480727/1285876/LighboxModern.js

  1. class LightboxModern {
  2. _swipeStartX = null;
  3. _swipeStartY = null;
  4. _swipeEndX = null;
  5. _swipeEndY = null;
  6. _clickTimeStart = null;
  7. _clickTimeEnd = null;
  8.  
  9. // Tentukan threshold untuk dianggap sebagai swipe
  10. _THRESHOLD = 20;
  11. _CLICK_TIME_THRESHOLD = 100;
  12. _currentImage = null;
  13.  
  14. _progress = 1
  15. _idFadeOutTool = null;
  16.  
  17. constructor(container, { images = [] } = {}) {
  18. this.container = container;
  19. this.container.classList.add("LightboxModern", "FadeIn")
  20. this.container.innerHTML = ""
  21.  
  22. this.progress = this._renderProgress();
  23. this.container.append(this.progress);
  24.  
  25. this.images = images
  26. const imagesContainer = this._renderListImage(images);
  27. this.container.append(imagesContainer)
  28.  
  29. this._updateProgress()
  30.  
  31. // this.swiper = this._SwipeListener()
  32. // this.container.append(this.swiper)
  33.  
  34. this.tool = this._RenderTool()
  35. this.container.append(this.tool)
  36. }
  37.  
  38. _renderListImage(images) {
  39. const container = document.createElement("div");
  40. container.classList.add("ImagesContainer");
  41. this._listenSwipe(container)
  42.  
  43. for(const index in images) {
  44. const wrapper = document.createElement("div");
  45. wrapper.classList.add("ImageWrapper");
  46.  
  47. if(index == 0) {
  48. wrapper.classList.add("FadeIn")
  49. this._currentImage = wrapper;
  50. }
  51.  
  52. const imgElement = document.createElement("img");
  53. imgElement.src = images[index];
  54. imgElement.alt = `Images Number ${index + 1}`;
  55.  
  56. const padding = document.createElement("div")
  57. padding.classList.add("ImagePadding");
  58.  
  59. wrapper.append(imgElement, padding)
  60. container.append(wrapper)
  61. }
  62.  
  63. return container;
  64. }
  65.  
  66. _renderProgress() {
  67. const container = document.createElement("div");
  68. container.classList.add("Progress");
  69. return container;
  70. }
  71. _updateProgress() {
  72. this.progress.style.width = `${Math.floor(this._progress / this.images.length * 100)}%`
  73. }
  74.  
  75. _SwipeListener() {
  76. const container = document.createElement("div");
  77. container.classList.add("Swiper")
  78. _listenSwipe
  79.  
  80. return container;
  81. }
  82.  
  83. _listenSwipe(element) {
  84. element.addEventListener("touchstart", (e) => {
  85. this._clickTimeStart = new Date().getTime()
  86. this._swipeStartX = e.touches[0].clientX;
  87. this._swipeStartY = e.touches[0].clientY;
  88. })
  89.  
  90. element.addEventListener("touchmove", (e) => {
  91. if(e.touches.length === 1) {
  92. e.preventDefault(); // Mencegah scroll selama swipe
  93. this._swipeEndX = e.touches[0].clientX;
  94. this._swipeEndY = e.touches[0].clientY;
  95. }
  96. })
  97.  
  98. element.addEventListener("touchend", (e) => {
  99. this._clickTimeEnd = new Date().getTime()
  100. this._detectSwipe()
  101. })
  102. }
  103.  
  104. _RenderTool() {
  105. const container = document.createElement("div");
  106. container.classList.add("LightboxTool")
  107. this._listenSwipe(container)
  108.  
  109. const header = document.createElement("div");
  110. header.classList.add("ToolHeader")
  111.  
  112. const closeButton = document.createElement("button")
  113. closeButton.classList.add("btn")
  114. closeButton.innerText = "Close"
  115.  
  116. closeButton.addEventListener("click", () => {
  117. this.container.classList.remove("FadeIn")
  118. })
  119.  
  120. const fullScreenButton = document.createElement("button")
  121. fullScreenButton.classList.add("btn")
  122. fullScreenButton.innerText = "[ ]"
  123. fullScreenButton.onclick = () => {
  124. if(document.fullscreenElement) {
  125. document.exitFullscreen()
  126. } else {
  127. document.documentElement.requestFullscreen()
  128. }
  129. }
  130.  
  131. header.append(fullScreenButton, closeButton)
  132.  
  133. const footer = document.createElement("div")
  134. footer.classList.add("ToolFooter")
  135.  
  136. const downloadImage = document.createElement("button")
  137. downloadImage.classList.add("btn")
  138. downloadImage.innerText = "Download Image"
  139. downloadImage.onclick = () => this.downloadImage(this._currentImage.querySelector("img").src)
  140.  
  141. const downloadAllImage = document.createElement("button")
  142. downloadAllImage.classList.add("btn")
  143. downloadAllImage.innerText = "Download All Image"
  144. downloadAllImage.onclick = () => {
  145. downloadAllImage.disabled = true;
  146. for(const image of this.images) {
  147. this.downloadImage(image)
  148. }
  149. downloadAllImage.disabled = false;
  150. }
  151.  
  152. footer.append(downloadImage, downloadAllImage)
  153.  
  154. container.append(header, footer);
  155. container.addEventListener("click", () => {
  156. container.classList.toggle("FadeIn")
  157. })
  158.  
  159. return container
  160. }
  161.  
  162. _fadeOutImage() {
  163. if(this._currentImage) this._currentImage.classList.remove("FadeIn")
  164. }
  165.  
  166. _nextImage() {
  167. const nextElement = this._currentImage.nextElementSibling;
  168. this._fadeOutImage();
  169.  
  170. if( nextElement ) {
  171. nextElement.classList.add("FadeIn")
  172. this._currentImage = nextElement;
  173. this._progress += 1
  174. } else {
  175. const currentImage = this.container.querySelector(".ImagesContainer .ImageWrapper");
  176. currentImage.classList.add("FadeIn")
  177. this._currentImage = currentImage;
  178. this._progress = 1
  179. }
  180. }
  181.  
  182. _prevImage() {
  183. const prevElement = this._currentImage.previousElementSibling;
  184. this._fadeOutImage()
  185. if(prevElement) {
  186. prevElement.classList.add("FadeIn")
  187. this._currentImage = prevElement;
  188. this._progress -= 1
  189. } else {
  190. const currentImage = this.container.querySelector(".ImagesContainer").lastElementChild
  191. currentImage.classList.add("FadeIn")
  192. this._currentImage = currentImage;
  193. this._progress = this.images.length
  194. }
  195. }
  196.  
  197. _detectSwipe() {
  198. const deltaX = this._swipeEndX - this._swipeStartX;
  199. const deltaY = this._swipeEndY - this._swipeStartY;
  200. const deltaTime = this._clickTimeEnd - this._clickTimeStart
  201.  
  202. if((Math.abs(deltaX) > this._THRESHOLD || Math.abs(deltaY) > this._THRESHOLD) &&
  203. deltaTime > this._CLICK_TIME_THRESHOLD) {
  204. if(deltaX > 0) {
  205. this._prevImage();
  206. } else {
  207. this._nextImage();
  208. }
  209.  
  210. this._updateProgress()
  211. } else if(deltaTime < this._CLICK_TIME_THRESHOLD ) {
  212. this.tool.classList.toggle("FadeIn")
  213. if(this._idFadeOutTool) clearTimeout(this._idFadeOutTool)
  214.  
  215. this._idFadeOutTool = setTimeout(() => this.tool.classList.remove("FadeIn") , 1500)
  216. } else {
  217. console.log('Tidak ada swipe yang terdeteksi.');
  218. }
  219. }
  220.  
  221. downloadImage(url) {
  222. const link = document.createElement("a")
  223. link.href = url
  224. link.click()
  225. }
  226. }