| 1 |
export class Lightbox { |
| 2 |
deep; |
| 3 |
lastDeep; |
| 4 |
constructor() { |
| 5 |
this.socialIcons = "<div id='photonic-social'>" + |
| 6 |
"<a class='photonic-share-fb' href='https://www.facebook.com/sharer/sharer.php?u={photonic_share_link}&title={photonic_share_title}&picture={photonic_share_image}' target='_blank' title='Share on Facebook'><div class='icon-facebook'></div></a>" + |
| 7 |
"<a class='photonic-share-twitter' href='https://twitter.com/share?url={photonic_share_link}&text={photonic_share_title}' target='_blank' title='Share on Twitter'><div class='icon-twitter'></div></a>" + |
| 8 |
"<a class='photonic-share-pinterest' data-pin-do='buttonPin' href='https://www.pinterest.com/pin/create/button/?url={photonic_share_link}&media={photonic_share_image}&description={photonic_share_title}' data-pin-custom='true' target='_blank' title='Share on Pinterest'><div class='icon-pinterest'></div></a>" + |
| 9 |
"</div>"; |
| 10 |
this.videoIndex = 1; |
| 11 |
}; |
| 12 |
|
| 13 |
getVideoSize(url, baseline) { |
| 14 |
return new Promise(resolve => { |
| 15 |
// create the video element |
| 16 |
const video = document.createElement('video'); |
| 17 |
|
| 18 |
// place a listener on it |
| 19 |
video.addEventListener("loadedmetadata", function () { |
| 20 |
// retrieve dimensions |
| 21 |
const height = this.videoHeight, |
| 22 |
width = this.videoWidth; |
| 23 |
|
| 24 |
const videoAspectRatio = this.videoWidth / this.videoHeight, |
| 25 |
baseAspectRatio = baseline.width / baseline.height; |
| 26 |
|
| 27 |
let newWidth, newHeight; |
| 28 |
if (baseAspectRatio > videoAspectRatio) { |
| 29 |
// Window is wider than it needs to be ... constrain by window height |
| 30 |
newHeight = baseline.height; |
| 31 |
newWidth = width * newHeight / height; |
| 32 |
} else { |
| 33 |
// Window is narrower than it needs to be ... constrain by window width |
| 34 |
newWidth = baseline.width; |
| 35 |
newHeight = height * newWidth / width; |
| 36 |
} |
| 37 |
|
| 38 |
// send back result |
| 39 |
resolve({ |
| 40 |
height: height, |
| 41 |
width: width, |
| 42 |
newHeight: newHeight, |
| 43 |
newWidth: newWidth |
| 44 |
}); |
| 45 |
}, false); |
| 46 |
|
| 47 |
// start download meta-data |
| 48 |
video.src = url; |
| 49 |
}); |
| 50 |
} |
| 51 |
|
| 52 |
getImageSize(url, baseline) { |
| 53 |
return new Promise(function (resolve) { |
| 54 |
const image = document.createElement('img'); |
| 55 |
|
| 56 |
// place a listener on it |
| 57 |
image.addEventListener("load", function () { |
| 58 |
// retrieve dimensions |
| 59 |
const height = this.height, |
| 60 |
width = this.width, |
| 61 |
imageAspectRatio = this.width / this.height, |
| 62 |
baseAspectRatio = baseline.width / baseline.height; |
| 63 |
|
| 64 |
let newWidth, newHeight; |
| 65 |
if (baseAspectRatio > imageAspectRatio) { |
| 66 |
// Window is wider than it needs to be ... constrain by window height |
| 67 |
newHeight = baseline.height; |
| 68 |
newWidth = width * newHeight / height; |
| 69 |
} else { |
| 70 |
// Window is narrower than it needs to be ... constrain by window width |
| 71 |
newWidth = baseline.width; |
| 72 |
newHeight = height * newWidth / width; |
| 73 |
} |
| 74 |
|
| 75 |
// send back result |
| 76 |
resolve({ |
| 77 |
height: height, |
| 78 |
width: width, |
| 79 |
newHeight: newHeight, |
| 80 |
newWidth: newWidth |
| 81 |
}); |
| 82 |
}, false); |
| 83 |
|
| 84 |
// start download meta-data |
| 85 |
image.src = url; |
| 86 |
}); |
| 87 |
} |
| 88 |
|
| 89 |
addSocial(selector, shareable, position) { |
| 90 |
if ((Photonic_JS.social_media === undefined || Photonic_JS.social_media === '') && shareable['buy'] === undefined) { |
| 91 |
return; |
| 92 |
} |
| 93 |
|
| 94 |
const socialEl = document.getElementById('photonic-social'); |
| 95 |
if (socialEl !== null) { |
| 96 |
socialEl.parentNode.removeChild(socialEl); |
| 97 |
} |
| 98 |
|
| 99 |
let addTo; |
| 100 |
if (position === undefined || position === null) { |
| 101 |
addTo = 'beforeend'; |
| 102 |
} |
| 103 |
else { |
| 104 |
addTo = position; |
| 105 |
} |
| 106 |
|
| 107 |
if (location.hash !== '') { |
| 108 |
const social = this.socialIcons.replace(/{photonic_share_link}/g, encodeURIComponent(shareable['url'])) |
| 109 |
.replace(/{photonic_share_title}/g, encodeURIComponent(shareable['title'])) |
| 110 |
.replace(/{photonic_share_image}/g, encodeURIComponent(shareable['image'])); |
| 111 |
|
| 112 |
let selectorEl; |
| 113 |
if (typeof selector === 'string') { |
| 114 |
selectorEl = document.documentElement.querySelector(selector); |
| 115 |
} |
| 116 |
else { |
| 117 |
selectorEl = selector; |
| 118 |
} |
| 119 |
|
| 120 |
if (selectorEl !== null) { |
| 121 |
selectorEl.insertAdjacentHTML(addTo, social); |
| 122 |
} |
| 123 |
|
| 124 |
if (Photonic_JS.social_media === undefined || Photonic_JS.social_media === '') { |
| 125 |
const socialMediaIcons = document.documentElement.querySelectorAll('.photonic-share-fb, .photonic-share-twitter, .photonic-share-pinterest'); |
| 126 |
Array.prototype.forEach.call(socialMediaIcons, function(socialIcon) { |
| 127 |
socialIcon.parentNode.removeChild(socialIcon); |
| 128 |
}); |
| 129 |
} |
| 130 |
} |
| 131 |
}; |
| 132 |
|
| 133 |
setHash(a) { |
| 134 |
if (Photonic_JS.deep_linking === undefined || Photonic_JS.deep_linking === 'none' || a === null || a === undefined) { |
| 135 |
return; |
| 136 |
} |
| 137 |
|
| 138 |
const hash = typeof a === 'string' ? a : a.getAttribute('data-photonic-deep'); |
| 139 |
if (hash === undefined) { |
| 140 |
return; |
| 141 |
} |
| 142 |
|
| 143 |
if (typeof(window.history.pushState) === 'function' && Photonic_JS.deep_linking === 'yes-history') { |
| 144 |
window.history.pushState({}, document.title, '#' + hash); |
| 145 |
} |
| 146 |
else if (typeof(window.history.replaceState) === 'function' && Photonic_JS.deep_linking === 'no-history') { |
| 147 |
window.history.replaceState({}, document.title, '#' + hash); |
| 148 |
} |
| 149 |
else { |
| 150 |
document.location.hash = hash; |
| 151 |
} |
| 152 |
}; |
| 153 |
|
| 154 |
unsetHash() { |
| 155 |
this.lastDeep = (this.lastDeep === undefined || this.deep !== '') ? location.hash : this.lastDeep; |
| 156 |
if (window.history && 'replaceState' in window.history) { |
| 157 |
history.replaceState({}, document.title, location.href.substr(0, location.href.length-location.hash.length)); |
| 158 |
} |
| 159 |
else { |
| 160 |
window.location.hash = ''; |
| 161 |
} |
| 162 |
}; |
| 163 |
|
| 164 |
changeHash(e) { |
| 165 |
if (e.type === 'load') { |
| 166 |
let hash = window.location.hash; |
| 167 |
hash = hash.substr(1); |
| 168 |
if (hash && hash !== '') { |
| 169 |
const allMatches = document.querySelectorAll('[data-photonic-deep="' + hash + '"]'); |
| 170 |
if (allMatches.length > 0) { |
| 171 |
const thumbToClick = allMatches[0]; |
| 172 |
const event = document.createEvent('HTMLEvents'); |
| 173 |
event.initEvent('click', true, false); |
| 174 |
thumbToClick.dispatchEvent(event); |
| 175 |
} |
| 176 |
} |
| 177 |
} |
| 178 |
else { |
| 179 |
|
| 180 |
let node = this.deep; |
| 181 |
|
| 182 |
if (node != null) { |
| 183 |
if (node.length > 1) { |
| 184 |
if (window.location.hash && node.indexOf('#access_token=') !== -1) { |
| 185 |
this.unsetHash(); |
| 186 |
} |
| 187 |
else { |
| 188 |
node = node.substr(1); |
| 189 |
const allMatches = document.querySelectorAll('[data-photonic-deep="' + node + '"]'); |
| 190 |
if (allMatches.length > 0) { |
| 191 |
const thumbToClick = allMatches[0]; |
| 192 |
const event = document.createEvent('HTMLEvents'); |
| 193 |
event.initEvent('click', true, false); |
| 194 |
thumbToClick.dispatchEvent(event); |
| 195 |
this.setHash(node); |
| 196 |
} |
| 197 |
} |
| 198 |
} |
| 199 |
} |
| 200 |
} |
| 201 |
}; |
| 202 |
|
| 203 |
catchYouTubeURL(url) { |
| 204 |
const regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*)(?:(\?t|&t|\?start|&start)=(\d+))?.*/, |
| 205 |
match = url.match(regExp); |
| 206 |
if (match && match[2].length === 11) { |
| 207 |
let obj = { |
| 208 |
url: match[2] |
| 209 |
}; |
| 210 |
if (match[4] !== undefined) { |
| 211 |
obj.timestamp = match[4]; |
| 212 |
} |
| 213 |
return obj; |
| 214 |
} |
| 215 |
}; |
| 216 |
|
| 217 |
catchVimeoURL(url) { |
| 218 |
const regExp = /(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/, |
| 219 |
match = url.match(regExp); |
| 220 |
if (match) { |
| 221 |
return match[1]; |
| 222 |
} |
| 223 |
}; |
| 224 |
|
| 225 |
soloImages() { |
| 226 |
const a = document.querySelectorAll('a[href]'); |
| 227 |
const solos = Array.from(a).filter(elem => /(\.jpg|\.jpeg|\.bmp|\.gif|\.png)/i.test(elem.getAttribute('href'))) |
| 228 |
.filter(elem => !elem.classList.contains('photonic-lb')); |
| 229 |
solos.forEach(solo => { |
| 230 |
solo.classList.add("photonic-" + Photonic_JS.lightbox_library); |
| 231 |
solo.classList.add("photonic-" + Photonic_JS.lightbox_library + '-solo'); |
| 232 |
solo.classList.add(Photonic_JS.lightbox_library); |
| 233 |
}); |
| 234 |
return solos; |
| 235 |
}; |
| 236 |
|
| 237 |
changeVideoURL(element, regular, embed, poster) { |
| 238 |
// Implemented in individual lightboxes. Empty for unsupported lightboxes |
| 239 |
}; |
| 240 |
|
| 241 |
hostedVideo(a) { |
| 242 |
// Implemented in individual lightboxes. Empty for unsupported lightboxes |
| 243 |
}; |
| 244 |
|
| 245 |
soloVideos() { |
| 246 |
const self = this; |
| 247 |
if (Photonic_JS.lightbox_for_videos) { |
| 248 |
const a = document.querySelectorAll('a[href]'); |
| 249 |
a.forEach(function(anchor) { |
| 250 |
let regular, embed, poster; |
| 251 |
const href = anchor.getAttribute('href'), |
| 252 |
youTube = self.catchYouTubeURL(href), |
| 253 |
vimeo = self.catchVimeoURL(href); |
| 254 |
if ((youTube) !== undefined) { |
| 255 |
let ytSrc = youTube.url, ytTimeStamp = youTube.timestamp, regularT = '', embedT = ''; |
| 256 |
if (ytTimeStamp !== undefined) { |
| 257 |
regularT = '&t=' + ytTimeStamp; |
| 258 |
embedT = '?start=' + ytTimeStamp; |
| 259 |
} |
| 260 |
regular = 'https://youtube.com/watch?v=' + ytSrc + regularT; |
| 261 |
embed = 'https://youtube.com/embed/' + ytSrc + embedT; |
| 262 |
poster = 'https://img.youtube.com/vi/' + ytSrc + '/hddefault.jpg'; |
| 263 |
} |
| 264 |
else if (vimeo !== undefined) { |
| 265 |
regular = 'https://vimeo.com/' + vimeo; |
| 266 |
embed = 'https://player.vimeo.com/video/' + vimeo; |
| 267 |
} |
| 268 |
|
| 269 |
if (regular !== undefined) { |
| 270 |
anchor.classList.add(Photonic_JS.lightbox_library + "-video"); |
| 271 |
self.changeVideoURL(anchor, regular, embed, poster); |
| 272 |
self.modifyAdditionalVideoProperties(anchor); |
| 273 |
} |
| 274 |
self.hostedVideo(anchor); |
| 275 |
}); |
| 276 |
} |
| 277 |
}; |
| 278 |
|
| 279 |
handleSolos() { |
| 280 |
if (Photonic_JS.lightbox_for_all) { |
| 281 |
this.soloImages(); |
| 282 |
} |
| 283 |
this.soloVideos(); |
| 284 |
|
| 285 |
if (Photonic_JS.deep_linking !== undefined && Photonic_JS.deep_linking !== 'none') { |
| 286 |
window.addEventListener('load', this.changeHash); |
| 287 |
window.addEventListener('hashchange', this.changeHash); |
| 288 |
} |
| 289 |
}; |
| 290 |
|
| 291 |
initialize() { |
| 292 |
this.handleSolos(); |
| 293 |
// Implemented by child classes |
| 294 |
}; |
| 295 |
|
| 296 |
initializeForNewContainer(containerId) { |
| 297 |
// Implemented by individual lightboxes. Empty for cases where not required |
| 298 |
}; |
| 299 |
|
| 300 |
initializeForExisting() { |
| 301 |
// Implemented by child classes |
| 302 |
}; |
| 303 |
|
| 304 |
modifyAdditionalVideoProperties(anchor) { |
| 305 |
// Implemented by individual lightboxes. Empty for cases where not required |
| 306 |
} |
| 307 |
} |
| 308 |
|