| 1 |
document.addEventListener('DOMContentLoaded', () => { |
| 2 |
const PhotonicWizard = () => { |
| 3 |
let photonicLastActiveScreen = 1; |
| 4 |
let photonicMustPost = false; |
| 5 |
let photonicPermittedGalleries = ['wp', 'default', 'flickr', 'smugmug', 'google', 'zenfolio', 'instagram']; |
| 6 |
let photonicShortcodeObjectEditor; |
| 7 |
let photonicParentShortcode = ''; |
| 8 |
let photonicParentSelectionError; |
| 9 |
let photonicIFramePort; |
| 10 |
let isEditor = false, isMCE = false, isWidget = false, isBlock = false; |
| 11 |
let photonicActiveScreenElementMediaLibrary, photonicClickedNodeMediaLibrary; |
| 12 |
let startupConnectionError; |
| 13 |
|
| 14 |
// setWaitingVisibility(true); |
| 15 |
window.addEventListener('message', initializeWizardPort); |
| 16 |
|
| 17 |
function initializeWizardPort(event) { |
| 18 |
// Perform a secure port transfer |
| 19 |
if (event.ports[0] && event.origin === Photonic_Wizard_JS.safe_origin) { |
| 20 |
photonicIFramePort = event.ports[0]; |
| 21 |
photonicIFramePort.onmessage = handleMessageFromParent; |
| 22 |
} |
| 23 |
else if (event.origin !== Photonic_Wizard_JS.safe_origin) { |
| 24 |
startupConnectionError = '<strong>ERROR: </strong>Photonic wizard failed to initiate communication with main page. <ul><li>Main window is on ' + event.origin + '</li><li>Wizard is in ' + Photonic_Wizard_JS.safe_origin + '</li></ul>'; |
| 25 |
console.error('Photonic failed to initialize communication. Main window is in ' + event.origin + ', Wizard is in ' + Photonic_Wizard_JS.safe_origin); |
| 26 |
if (startupConnectionError) { |
| 27 |
document.querySelector('.photonic-editor-info').innerHTML += '<div>' + startupConnectionError + '</div>'; |
| 28 |
} |
| 29 |
} |
| 30 |
} |
| 31 |
|
| 32 |
function handleMessageFromParent(event) { |
| 33 |
if (event.data.type === 'photonicShortcode' || event.data.type === 'photonicMCENode' || event.data.type === 'photonicWidget' || event.data.type === 'photonicBlock') { |
| 34 |
receiveEditorShortcode(event); |
| 35 |
} |
| 36 |
else if (event.data.type === 'photonicReceiveMediaLibrarySelections') { |
| 37 |
receiveMediaLibrarySelections(event.data.selection, event.data.options); |
| 38 |
} |
| 39 |
} |
| 40 |
|
| 41 |
function receiveEditorShortcode(event) { |
| 42 |
let selection = event.data.object; |
| 43 |
// Selection = null if something went wrong |
| 44 |
// Selection = shortcode object if valid shortcode |
| 45 |
// Selection = null shortcode object and error, if not a valid shortcode |
| 46 |
// Selection = '' if nothing was selected |
| 47 |
if (selection !== null && selection.shortcode !== undefined && selection.shortcode !== null) { |
| 48 |
if (selection.shortcode.content !== undefined) { // Selection is a valid shortcode |
| 49 |
photonicParentShortcode = selection.shortcode.content; |
| 50 |
photonicShortcodeObjectEditor = selection.shortcode; |
| 51 |
} |
| 52 |
else { |
| 53 |
photonicParentShortcode = selection.shortcode; // Selection = '' |
| 54 |
} |
| 55 |
} |
| 56 |
else if (selection !== null && selection.error !== undefined) { |
| 57 |
photonicParentSelectionError = selection.error; |
| 58 |
} |
| 59 |
|
| 60 |
isEditor = event.data.type === 'photonicShortcode'; |
| 61 |
isWidget = event.data.type === 'photonicWidget'; |
| 62 |
isBlock = event.data.type === 'photonicBlock'; |
| 63 |
isMCE = event.data.type === 'photonicMCENode'; |
| 64 |
|
| 65 |
photonicIFramePort.postMessage(event.data); |
| 66 |
photonicIFramePort.postMessage({type: 'photonicAddTBClass'}); |
| 67 |
|
| 68 |
wizardLogic(1); |
| 69 |
} |
| 70 |
|
| 71 |
function post(url, args, callback) { |
| 72 |
const xhr = new XMLHttpRequest(); |
| 73 |
xhr.open('POST', url); |
| 74 |
xhr.onreadystatechange = function () { |
| 75 |
if (xhr.readyState === 4) { |
| 76 |
if (xhr.status === 200) { |
| 77 |
const data = xhr.responseText; |
| 78 |
callback(data); |
| 79 |
} |
| 80 |
} |
| 81 |
}; |
| 82 |
let form = new FormData(); |
| 83 |
const parameters = new URLSearchParams(args); |
| 84 |
for (const [key, value] of parameters.entries()) { |
| 85 |
form.append(key, value); |
| 86 |
} |
| 87 |
xhr.send(form); |
| 88 |
} |
| 89 |
|
| 90 |
function getElement(value) { |
| 91 |
const parser = new DOMParser(); |
| 92 |
const doc = parser.parseFromString(value, 'text/html'); |
| 93 |
return doc.body; |
| 94 |
} |
| 95 |
|
| 96 |
function log(value) { |
| 97 |
if (console !== undefined && Photonic_Wizard_JS.debug_on !== '0' && Photonic_Wizard_JS.debug_on !== '') { |
| 98 |
console.log(value); |
| 99 |
} |
| 100 |
} |
| 101 |
|
| 102 |
const postFlowData = (activeScreen, nextScreen, activeScreenElement, screenParameters, parameters) => { |
| 103 |
post(Photonic_Wizard_JS.ajaxurl, parameters, data => { |
| 104 |
let ret = getElement(data); |
| 105 |
|
| 106 |
if (ret.querySelector('.photonic-flow-error')) { |
| 107 |
if (document.querySelector('.photonic-flow-error')) { |
| 108 |
document.querySelector('.photonic-flow-error').remove(); |
| 109 |
} |
| 110 |
document.querySelector('.photonic-flow-screen[data-screen="' + activeScreen + '"]').before(ret.querySelector('.photonic-flow-error')); |
| 111 |
activeScreenElement.setAttribute('data-submitted', ''); |
| 112 |
log('Parameters causing failure: activeScreen = ' + activeScreen + ', nextScreen = ' + nextScreen); |
| 113 |
log(screenParameters); |
| 114 |
log(parameters); |
| 115 |
} |
| 116 |
else { |
| 117 |
if (document.querySelector('.photonic-flow-error')) { |
| 118 |
document.querySelector('.photonic-flow-error').style.display = 'none'; |
| 119 |
} |
| 120 |
|
| 121 |
let forceScreen = ret.querySelector('input[name="force_next_screen"]'); |
| 122 |
if (forceScreen) { |
| 123 |
if (parseInt(forceScreen.value, 10) > -1) { |
| 124 |
nextScreen = parseInt(forceScreen.value, 10); |
| 125 |
} |
| 126 |
} |
| 127 |
|
| 128 |
let nextScreenContent = document.querySelector('.photonic-flow-screen[data-screen="' + nextScreen + '"]'); |
| 129 |
nextScreenContent.replaceChildren(); |
| 130 |
nextScreenContent.insertAdjacentHTML('beforeend', data); |
| 131 |
|
| 132 |
wizardLogic(nextScreen); |
| 133 |
if (nextScreen <= 3) { |
| 134 |
const existing = document.querySelector('input[name="existing_selection"]') ? document.querySelector('input[name="existing_selection"]').value : undefined; |
| 135 |
const selection = document.querySelector('input[name="selected_data"]'); |
| 136 |
const passworded = document.querySelector('input[name="selection_passworded"]'); |
| 137 |
if (existing !== undefined && existing !== '') { |
| 138 |
selection.value = existing; |
| 139 |
} |
| 140 |
else { |
| 141 |
selection.value = ''; |
| 142 |
passworded.value = ''; |
| 143 |
} |
| 144 |
} |
| 145 |
photonicLastActiveScreen = nextScreen; |
| 146 |
activeScreenElement.setAttribute('data-submitted', screenParameters); |
| 147 |
photonicMustPost = false; |
| 148 |
} |
| 149 |
setWaitingVisibility(false); |
| 150 |
}); |
| 151 |
}; |
| 152 |
|
| 153 |
function receiveMediaLibrarySelections(selected_data, options) { |
| 154 |
document.querySelector('input[name="selected_data"]').value = selected_data |
| 155 |
|
| 156 |
const form = document.getElementById('photonic-flow'); |
| 157 |
const formData = new FormData(form); |
| 158 |
let formParameters = new URLSearchParams(formData).toString(); |
| 159 |
formParameters += ((formParameters === '') ? '' : '&') + 'action=photonic_wizard_next_screen&screen=' + (options.activeScreen) + '&_ajax_nonce=' + photonicClickedNodeMediaLibrary.getAttribute('data-photonic-nonce'); |
| 160 |
|
| 161 |
postFlowData(options.activeScreen, options.nextScreen, photonicActiveScreenElementMediaLibrary, options.screenParameters, formParameters); |
| 162 |
|
| 163 |
if (selected_data !== '') { |
| 164 |
wizardLogic(options.nextScreen); |
| 165 |
} |
| 166 |
} |
| 167 |
|
| 168 |
const initializeWPMediaLibrary = (activeScreen, nextScreen, activeScreenElement, screenParameters, clicked) => { |
| 169 |
let mode = document.querySelector('select[name="display_type"]').value; |
| 170 |
if (mode === '') { |
| 171 |
alert(Photonic_Wizard_JS.error_mandatory); |
| 172 |
} |
| 173 |
else { |
| 174 |
mode = mode === 'single-photo' ? 'single' : 'add'; |
| 175 |
|
| 176 |
// These 2 are needed as we cannot pass elements to postMessage --> |
| 177 |
photonicActiveScreenElementMediaLibrary = activeScreenElement; |
| 178 |
photonicClickedNodeMediaLibrary = clicked; |
| 179 |
// <-- |
| 180 |
|
| 181 |
photonicIFramePort.postMessage({ |
| 182 |
type: 'photonicInitializeMediaLibrary', |
| 183 |
mediaOptions: { |
| 184 |
multiple: mode, |
| 185 |
title: Photonic_Wizard_JS.media_library_title, |
| 186 |
library: {type: 'image'}, |
| 187 |
button: {text: Photonic_Wizard_JS.media_library_button} |
| 188 |
}, |
| 189 |
photonicOptions: { |
| 190 |
shortcodeTag: Photonic_Wizard_JS.shortcode, |
| 191 |
activeScreen: activeScreen, |
| 192 |
nextScreen: nextScreen, |
| 193 |
screenParameters: screenParameters, |
| 194 |
currentShortcode: photonicParentShortcode, |
| 195 |
selectedIds: document.querySelector('input[name="selected_data"]').value, |
| 196 |
isBlock: isBlock |
| 197 |
} |
| 198 |
}); |
| 199 |
} |
| 200 |
}; |
| 201 |
|
| 202 |
const checkCondition = (conditions) => { |
| 203 |
let conditionMet = true; |
| 204 |
Object.entries(conditions).forEach(([key, condition]) => { |
| 205 |
const keyField = document.querySelector('input[type="radio"][name="' + key + '"]:checked, select[name="' + key + '"], input[type="text"][name="' + key + '"], input[type="hidden"][name="' + key + '"]'); |
| 206 |
if (keyField === null) { |
| 207 |
conditionMet = false; |
| 208 |
} |
| 209 |
else { |
| 210 |
conditionMet = conditionMet && condition.includes(keyField.value); |
| 211 |
} |
| 212 |
}); |
| 213 |
return conditionMet; |
| 214 |
}; |
| 215 |
|
| 216 |
const updateSelection = (clicked) => { |
| 217 |
const parent = clicked.closest('.photonic-flow-selector-container'); |
| 218 |
let selection = []; |
| 219 |
|
| 220 |
parent.querySelectorAll('.photonic-flow-selector.selected .photonic-flow-selector-inner').forEach(item => { |
| 221 |
selection.push(item.getAttribute('data-photonic-selection-id')); |
| 222 |
}); |
| 223 |
|
| 224 |
selection = selection.join(); |
| 225 |
let selectorFor = parent.getAttribute('data-photonic-flow-selector-for'); |
| 226 |
photonicMustPost = true; |
| 227 |
document.querySelector('input[name="' + selectorFor + '"]').value = selection; |
| 228 |
}; |
| 229 |
|
| 230 |
const showConditionalFieldValues = (sibling) => { |
| 231 |
const siblingFieldValues = sibling.querySelectorAll('input[type="radio"], option'); |
| 232 |
siblingFieldValues.forEach(input => { |
| 233 |
if (input.getAttribute('data-photonic-option-condition')) { |
| 234 |
const conditionMet = checkCondition(JSON.parse(input.getAttribute('data-photonic-option-condition'))); |
| 235 |
if (conditionMet) { |
| 236 |
if (input.type === 'radio') { |
| 237 |
input.closest('.photonic-flow-field-radio').style.display = 'block'; |
| 238 |
} |
| 239 |
else { |
| 240 |
input.style.display = 'block'; |
| 241 |
} |
| 242 |
} |
| 243 |
else { |
| 244 |
if (input.type === 'radio') { |
| 245 |
input.checked = false; |
| 246 |
input.closest('.photonic-flow-field-radio').style.display = 'none'; |
| 247 |
} |
| 248 |
else { |
| 249 |
input.style.display = 'none'; |
| 250 |
} |
| 251 |
} |
| 252 |
} |
| 253 |
}); |
| 254 |
}; |
| 255 |
|
| 256 |
// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_2_%E2%80%93_rewriting_atob_and_btoa_using_typedarrays_and_utf-8, to handle https://wordpress.org/support/topic/set-load-more-button-default/ ... |
| 257 |
|
| 258 |
/*\ |
| 259 |
|*| |
| 260 |
|*| Base64 / binary data / UTF-8 strings utilities |
| 261 |
|*| |
| 262 |
|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding |
| 263 |
|*| |
| 264 |
\*/ |
| 265 |
|
| 266 |
/* Array of bytes to Base64 string decoding */ |
| 267 |
const photonicB64ToUint6 = (nChr) => { |
| 268 |
return nChr > 64 && nChr < 91 ? |
| 269 |
nChr - 65 |
| 270 |
: nChr > 96 && nChr < 123 ? |
| 271 |
nChr - 71 |
| 272 |
: nChr > 47 && nChr < 58 ? |
| 273 |
nChr + 4 |
| 274 |
: nChr === 43 ? |
| 275 |
62 |
| 276 |
: nChr === 47 ? |
| 277 |
63 |
| 278 |
: |
| 279 |
0; |
| 280 |
}; |
| 281 |
|
| 282 |
const photonicBase64DecToArr = (sBase64, nBlocksSize) => { |
| 283 |
let |
| 284 |
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length, |
| 285 |
nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, |
| 286 |
taBytes = new Uint8Array(nOutLen); |
| 287 |
|
| 288 |
for (let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) { |
| 289 |
nMod4 = nInIdx & 3; |
| 290 |
nUint24 |= photonicB64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 6 * (3 - nMod4); |
| 291 |
if (nMod4 === 3 || nInLen - nInIdx === 1) { |
| 292 |
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { |
| 293 |
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255; |
| 294 |
} |
| 295 |
nUint24 = 0; |
| 296 |
|
| 297 |
} |
| 298 |
} |
| 299 |
|
| 300 |
return taBytes; |
| 301 |
}; |
| 302 |
|
| 303 |
/* Base64 string to array encoding */ |
| 304 |
const photonicUint6ToB64 = (nUint6) => { |
| 305 |
|
| 306 |
return nUint6 < 26 ? |
| 307 |
nUint6 + 65 |
| 308 |
: nUint6 < 52 ? |
| 309 |
nUint6 + 71 |
| 310 |
: nUint6 < 62 ? |
| 311 |
nUint6 - 4 |
| 312 |
: nUint6 === 62 ? |
| 313 |
43 |
| 314 |
: nUint6 === 63 ? |
| 315 |
47 |
| 316 |
: |
| 317 |
65; |
| 318 |
|
| 319 |
}; |
| 320 |
|
| 321 |
const photonicBase64EncArr = (aBytes) => { |
| 322 |
let nMod3 = 2, sB64Enc = ""; |
| 323 |
|
| 324 |
for (let nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { |
| 325 |
nMod3 = nIdx % 3; |
| 326 |
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { |
| 327 |
sB64Enc += "\r\n"; |
| 328 |
} |
| 329 |
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24); |
| 330 |
if (nMod3 === 2 || aBytes.length - nIdx === 1) { |
| 331 |
sB64Enc += String.fromCodePoint(photonicUint6ToB64(nUint24 >>> 18 & 63), photonicUint6ToB64(nUint24 >>> 12 & 63), photonicUint6ToB64(nUint24 >>> 6 & 63), photonicUint6ToB64(nUint24 & 63)); |
| 332 |
nUint24 = 0; |
| 333 |
} |
| 334 |
} |
| 335 |
|
| 336 |
return sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + (nMod3 === 2 ? '' : nMod3 === 1 ? '=' : '=='); |
| 337 |
|
| 338 |
}; |
| 339 |
|
| 340 |
/* UTF-8 array to JS string and vice versa */ |
| 341 |
const photonicUTF8ArrToStr = (aBytes) => { |
| 342 |
let sView = ""; |
| 343 |
|
| 344 |
for (let nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) { |
| 345 |
nPart = aBytes[nIdx]; |
| 346 |
sView += String.fromCodePoint( |
| 347 |
nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */ |
| 348 |
/* (nPart - 252 << 30) may be not so safe in ECMAScript! So…: */ |
| 349 |
(nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 |
| 350 |
: nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */ |
| 351 |
(nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 |
| 352 |
: nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */ |
| 353 |
(nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 |
| 354 |
: nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */ |
| 355 |
(nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 |
| 356 |
: nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */ |
| 357 |
(nPart - 192 << 6) + aBytes[++nIdx] - 128 |
| 358 |
: /* nPart < 127 ? */ /* one byte */ |
| 359 |
nPart |
| 360 |
); |
| 361 |
} |
| 362 |
|
| 363 |
return sView; |
| 364 |
|
| 365 |
}; |
| 366 |
|
| 367 |
const photonicStrToUTF8Arr = (sDOMStr) => { |
| 368 |
let aBytes, nChr, nStrLen = sDOMStr.length, nArrLen = 0; |
| 369 |
|
| 370 |
/* mapping… */ |
| 371 |
|
| 372 |
for (let nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) { |
| 373 |
nChr = sDOMStr.codePointAt(nMapIdx); |
| 374 |
|
| 375 |
if (nChr > 65536) { |
| 376 |
nMapIdx++; |
| 377 |
} |
| 378 |
|
| 379 |
nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6; |
| 380 |
} |
| 381 |
|
| 382 |
aBytes = new Uint8Array(nArrLen); |
| 383 |
|
| 384 |
/* transcription… */ |
| 385 |
|
| 386 |
for (let nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) { |
| 387 |
nChr = sDOMStr.codePointAt(nChrIdx); |
| 388 |
if (nChr < 128) { |
| 389 |
/* one byte */ |
| 390 |
aBytes[nIdx++] = nChr; |
| 391 |
} |
| 392 |
else if (nChr < 0x800) { |
| 393 |
/* two bytes */ |
| 394 |
aBytes[nIdx++] = 192 + (nChr >>> 6); |
| 395 |
aBytes[nIdx++] = 128 + (nChr & 63); |
| 396 |
} |
| 397 |
else if (nChr < 0x10000) { |
| 398 |
/* three bytes */ |
| 399 |
aBytes[nIdx++] = 224 + (nChr >>> 12); |
| 400 |
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); |
| 401 |
aBytes[nIdx++] = 128 + (nChr & 63); |
| 402 |
} |
| 403 |
else if (nChr < 0x200000) { |
| 404 |
/* four bytes */ |
| 405 |
aBytes[nIdx++] = 240 + (nChr >>> 18); |
| 406 |
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); |
| 407 |
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); |
| 408 |
aBytes[nIdx++] = 128 + (nChr & 63); |
| 409 |
nChrIdx++; |
| 410 |
} |
| 411 |
else if (nChr < 0x4000000) { |
| 412 |
/* five bytes */ |
| 413 |
aBytes[nIdx++] = 248 + (nChr >>> 24); |
| 414 |
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63); |
| 415 |
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); |
| 416 |
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); |
| 417 |
aBytes[nIdx++] = 128 + (nChr & 63); |
| 418 |
nChrIdx++; |
| 419 |
} |
| 420 |
else /* if (nChr <= 0x7fffffff) */ { |
| 421 |
/* six bytes */ |
| 422 |
aBytes[nIdx++] = 252 + (nChr >>> 30); |
| 423 |
aBytes[nIdx++] = 128 + (nChr >>> 24 & 63); |
| 424 |
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63); |
| 425 |
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); |
| 426 |
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); |
| 427 |
aBytes[nIdx++] = 128 + (nChr & 63); |
| 428 |
nChrIdx++; |
| 429 |
} |
| 430 |
} |
| 431 |
|
| 432 |
return aBytes; |
| 433 |
|
| 434 |
}; |
| 435 |
|
| 436 |
const wizardLogic = (screen) => { |
| 437 |
const existing = document.querySelector('input[name="photonic-editor-shortcode"]').getAttribute('value'); |
| 438 |
const existingBlock = document.querySelector('input[name="photonic-editor-json"]').getAttribute('value'); |
| 439 |
|
| 440 |
if (screen === 1) { |
| 441 |
if (existing === undefined || existing === null || existing === '') { |
| 442 |
let shortcode = photonicShortcodeObjectEditor, attributes, type; |
| 443 |
|
| 444 |
if (isEditor || isWidget || isMCE) { |
| 445 |
if (typeof shortcode !== 'undefined' && shortcode !== null) { |
| 446 |
let scParameter = photonicBase64EncArr(photonicStrToUTF8Arr(JSON.stringify(shortcode))); // To handle unicode in "more"; see https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_1_%E2%80%93_escaping_the_string_before_encoding_it |
| 447 |
scParameter = scParameter.replace(/\n/g, ''); |
| 448 |
scParameter = scParameter.replace(/^=+|=+$/g, ''); |
| 449 |
attributes = shortcode.shortcode.attrs.named; |
| 450 |
if (attributes['type'] !== undefined && photonicPermittedGalleries.indexOf(attributes['type']) !== -1) { |
| 451 |
type = attributes['type']; |
| 452 |
} |
| 453 |
else if ((attributes['type'] === undefined && Photonic_Wizard_JS.shortcode !== 'gallery') || attributes['style'] !== undefined) { |
| 454 |
type = 'wp'; |
| 455 |
} |
| 456 |
|
| 457 |
if (type !== undefined) { |
| 458 |
if (type === 'google') { |
| 459 |
document.querySelector('.photonic-editor-info').innerHTML = '<div>' + Photonic_Wizard_JS.info_editor_google_shortcode + '</div>'; |
| 460 |
} |
| 461 |
else { |
| 462 |
document.querySelector('[name="photonic-editor-shortcode-raw"]').value = scParameter; |
| 463 |
document.querySelector('[name="photonic-editor-shortcode"]').value = photonicParentShortcode; |
| 464 |
document.querySelector('[data-photonic-selection-id="' + type + '"]').click(); |
| 465 |
document.querySelector('.photonic-editor-info').innerHTML = ''; |
| 466 |
} |
| 467 |
} |
| 468 |
else { |
| 469 |
document.querySelector('.photonic-editor-info').innerHTML = '<div>' + Photonic_Wizard_JS.info_editor_not_shortcode + '</div>'; |
| 470 |
} |
| 471 |
} |
| 472 |
else if (photonicParentSelectionError !== undefined) { |
| 473 |
document.querySelector('.photonic-editor-info').innerHTML = '<div>' + Photonic_Wizard_JS.info_editor_not_shortcode + '</div>'; |
| 474 |
} |
| 475 |
} |
| 476 |
else if (isBlock) { // Gutenberg |
| 477 |
document.querySelector('[name="photonic-gutenberg-active"]').value = 1; |
| 478 |
|
| 479 |
if (photonicParentShortcode !== undefined && photonicParentShortcode !== '') { |
| 480 |
shortcode = photonicParentShortcode; |
| 481 |
attributes = JSON.parse(shortcode); |
| 482 |
|
| 483 |
if (attributes.type !== undefined && photonicPermittedGalleries.indexOf(attributes.type) !== -1) { |
| 484 |
type = attributes.type; |
| 485 |
} |
| 486 |
else if (attributes.style !== undefined) { |
| 487 |
type = 'wp'; |
| 488 |
} |
| 489 |
|
| 490 |
if (type !== undefined) { |
| 491 |
document.querySelector('[name="photonic-editor-json"]').value = shortcode; |
| 492 |
document.querySelector('[data-photonic-selection-id="' + type + '"]').click(); |
| 493 |
document.querySelector('.photonic-editor-info').replaceChildren(); |
| 494 |
} |
| 495 |
} |
| 496 |
else { |
| 497 |
document.querySelector('.photonic-editor-info').innerHTML = '<div>' + Photonic_Wizard_JS.info_editor_block_select + '</div>'; |
| 498 |
} |
| 499 |
} |
| 500 |
} |
| 501 |
setWaitingVisibility(false); |
| 502 |
} |
| 503 |
|
| 504 |
if (screen === 6) { |
| 505 |
if ((existing === undefined || existing === '') && (existingBlock === undefined || existingBlock === '')) { |
| 506 |
document.getElementById('photonic-nav-next').innerHTML = Photonic_Wizard_JS.insert_gallery; |
| 507 |
} |
| 508 |
else { |
| 509 |
document.getElementById('photonic-nav-next').innerHTML = Photonic_Wizard_JS.update_gallery; |
| 510 |
} |
| 511 |
} |
| 512 |
else { |
| 513 |
document.getElementById('photonic-nav-next').innerHTML = 'Next'; |
| 514 |
} |
| 515 |
|
| 516 |
document.querySelectorAll('.photonic-flow-screen').forEach(screen => { |
| 517 |
screen.style.display = 'none'; |
| 518 |
}); |
| 519 |
|
| 520 |
const activeScreen = document.querySelector('.photonic-flow-screen[data-screen="' + screen + '"]'); |
| 521 |
const fieldSequences = activeScreen.querySelectorAll('.photonic-flow-field[data-photonic-flow-sequence="1"]'); |
| 522 |
const displayType = activeScreen.querySelector('select[name="display_type"]'); |
| 523 |
const popupType = activeScreen.querySelector('select[name="popup"]'); |
| 524 |
|
| 525 |
fieldSequences.forEach(fieldSequence => { |
| 526 |
const group = fieldSequence.getAttribute('data-photonic-flow-sequence-group'); |
| 527 |
|
| 528 |
document.querySelectorAll('.photonic-flow-field[data-photonic-flow-sequence-group="' + group + '"]').forEach((fieldContainer, idx) => { |
| 529 |
let field = fieldContainer.querySelector('input, select'); |
| 530 |
let isRadio = false; |
| 531 |
|
| 532 |
const fieldName = field.getAttribute('name'); |
| 533 |
let fieldSelection = document.querySelector('input[type="radio"][name="' + fieldName + '"]:checked') || document.querySelector('input[type="text"][name="' + fieldName + '"], select[name="' + fieldName + '"]'); |
| 534 |
const fieldValue = fieldSelection ? fieldSelection.value : undefined; |
| 535 |
|
| 536 |
if (idx !== 0 && (fieldValue === '' || fieldValue === undefined)) { |
| 537 |
fieldContainer.style.display = 'none'; |
| 538 |
} |
| 539 |
|
| 540 |
// This has to happen after "fieldValue" is set |
| 541 |
if (field.tagName === 'INPUT' && field.type === 'radio') { |
| 542 |
field = field.closest('.photonic-flow-field-radio-group'); |
| 543 |
isRadio = true; |
| 544 |
} |
| 545 |
|
| 546 |
|
| 547 |
const siblings = fieldContainer.parentNode.children; |
| 548 |
let sequence = parseInt(fieldContainer.getAttribute('data-photonic-flow-sequence'), 10); |
| 549 |
|
| 550 |
field.addEventListener('change', () => { |
| 551 |
if (isRadio) { |
| 552 |
fieldSelection = document.querySelector('input[type="radio"][name="' + fieldName + '"]:checked'); |
| 553 |
} |
| 554 |
const error = document.querySelector('.photonic-flow-error'); |
| 555 |
if (error) { |
| 556 |
error.style.display = 'none'; |
| 557 |
} |
| 558 |
|
| 559 |
if ((!isRadio && field.value !== '') || (isRadio && fieldSelection && fieldSelection.value !== undefined)) { |
| 560 |
Array.from(siblings).forEach(sibling => { |
| 561 |
let currSequence = parseInt(sibling.getAttribute('data-photonic-flow-sequence'), 10); |
| 562 |
if (currSequence > sequence) { |
| 563 |
if (sibling.getAttribute('data-photonic-condition')) { |
| 564 |
const conditionMet = checkCondition(JSON.parse(sibling.getAttribute('data-photonic-condition'))); |
| 565 |
sibling.style.display = conditionMet ? 'block' : 'none'; |
| 566 |
} |
| 567 |
else { |
| 568 |
fadeIn(sibling); |
| 569 |
} |
| 570 |
showConditionalFieldValues(sibling); |
| 571 |
} |
| 572 |
}); |
| 573 |
} |
| 574 |
else { |
| 575 |
Array.from(siblings).forEach(sibling => { |
| 576 |
let currSequence = parseInt(sibling.getAttribute('data-photonic-flow-sequence'), 10); |
| 577 |
if (currSequence > sequence) { |
| 578 |
fadeOut(sibling); |
| 579 |
} |
| 580 |
}); |
| 581 |
} |
| 582 |
}); |
| 583 |
}); |
| 584 |
}); |
| 585 |
|
| 586 |
activeScreen.querySelectorAll('[data-photonic-condition] input, [data-photonic-condition] select').forEach(input => { |
| 587 |
const fieldContainer = input.closest('.photonic-flow-field'); |
| 588 |
const sequences = input.closest('[data-photonic-flow-sequence]'); |
| 589 |
if (fieldContainer && !sequences) { |
| 590 |
if (fieldContainer.getAttribute('data-photonic-condition') && fieldContainer.getAttribute('data-photonic-condition') !== '') { |
| 591 |
const conditionMet = checkCondition(fieldContainer.getAttribute('data-photonic-condition')); |
| 592 |
fieldContainer.style.display = conditionMet ? 'block' : 'none'; |
| 593 |
} |
| 594 |
} |
| 595 |
}); |
| 596 |
|
| 597 |
if (screen === 2) { |
| 598 |
// One exception to the above ... |
| 599 |
if (displayType && displayType.value !== '') { |
| 600 |
const fieldContainer = document.querySelector('[name="for"]') ? document.querySelector('[name="for"]').closest('.photonic-flow-field') : undefined; |
| 601 |
if (fieldContainer) { |
| 602 |
showConditionalFieldValues(fieldContainer); |
| 603 |
fadeIn(fieldContainer); |
| 604 |
} |
| 605 |
} |
| 606 |
} |
| 607 |
else if (screen === 5) { |
| 608 |
// ... And another exception |
| 609 |
if (popupType && popupType.value !== '' && popupType.value !== 'hide') { |
| 610 |
const managedFields = document.querySelectorAll('[name="photo_count"], [name="photo_more"], [name="photo_layout"]'); |
| 611 |
managedFields.forEach(managedField => { |
| 612 |
const fieldContainer = managedField.closest('.photonic-flow-field'); |
| 613 |
showConditionalFieldValues(fieldContainer); |
| 614 |
fadeIn(fieldContainer); |
| 615 |
}); |
| 616 |
} |
| 617 |
} |
| 618 |
|
| 619 |
activeScreen.style.display = 'block'; |
| 620 |
if (screen === 1) { |
| 621 |
document.querySelector('.photonic-flow-navigation a.previous').classList.add('disabled'); |
| 622 |
} |
| 623 |
else { |
| 624 |
document.querySelector('.photonic-flow-navigation a.previous').classList.remove('disabled'); |
| 625 |
} |
| 626 |
}; |
| 627 |
|
| 628 |
function fadeIn(el) { |
| 629 |
if (!el.classList.contains('fade-in')) { |
| 630 |
el.style.display = 'block'; |
| 631 |
el.style.visibility = 'visible'; |
| 632 |
el.classList.add('fade-in'); |
| 633 |
} |
| 634 |
} |
| 635 |
|
| 636 |
function fadeOut(el, duration) { |
| 637 |
let s = el.style, |
| 638 |
step = 25 / (duration || 500); |
| 639 |
s.opacity = s.opacity || 1; |
| 640 |
(function fade() { |
| 641 |
s.opacity -= step; |
| 642 |
if (s.opacity < 0) { |
| 643 |
s.display = "none"; |
| 644 |
el.classList.remove('fade-in'); |
| 645 |
} |
| 646 |
else { |
| 647 |
setTimeout(fade, 25); |
| 648 |
} |
| 649 |
})(); |
| 650 |
} |
| 651 |
|
| 652 |
function setWaitingVisibility(visible) { |
| 653 |
const waiting = document.querySelector('.photonic-waiting'); |
| 654 |
waiting.style.display = visible ? 'block' : 'none'; |
| 655 |
} |
| 656 |
|
| 657 |
document.querySelector('.photonic-flow-navigation a.disabled').addEventListener('click', (e) => { |
| 658 |
e.preventDefault(); |
| 659 |
}); |
| 660 |
|
| 661 |
document.addEventListener('click', e => { |
| 662 |
if (!(e.target instanceof Element) || !e.target.closest('.photonic-flow-navigation a')) { |
| 663 |
return; |
| 664 |
} |
| 665 |
|
| 666 |
let clicked = e.target.closest('.photonic-flow-navigation a'); |
| 667 |
if (!clicked.classList.contains('disabled')) { |
| 668 |
e.preventDefault(); |
| 669 |
setWaitingVisibility(true); |
| 670 |
let activeScreen; |
| 671 |
let flowScreens = document.querySelectorAll('.photonic-flow-screen'); |
| 672 |
flowScreens.forEach(f => { |
| 673 |
if (f.checkVisibility()) { |
| 674 |
activeScreen = parseInt(f.getAttribute('data-screen'), 10); |
| 675 |
} |
| 676 |
}); |
| 677 |
|
| 678 |
let nextScreen = activeScreen + 1; |
| 679 |
let previousScreen = activeScreen - 1; |
| 680 |
|
| 681 |
const form = document.getElementById('photonic-flow'); |
| 682 |
const formData = new FormData(form); |
| 683 |
let formParameters = new URLSearchParams(formData).toString(); |
| 684 |
|
| 685 |
const activeScreenElement = document.querySelector('.photonic-flow-screen[data-screen="' + activeScreen + '"]'); |
| 686 |
if (clicked.classList.contains('next')) { |
| 687 |
let shortcode = activeScreenElement.querySelector('#photonic_shortcode'); |
| 688 |
let submission = activeScreenElement.getAttribute('data-submitted'); |
| 689 |
|
| 690 |
let screenFormFields = new FormData(); |
| 691 |
activeScreenElement.querySelectorAll('input, select').forEach(input => { |
| 692 |
// Only serialize fields with names that aren't disabled |
| 693 |
if (input.name && !input.disabled) { |
| 694 |
// Handle checkboxes and radios only if checked |
| 695 |
if (['checkbox', 'radio'].includes(input.type)) { |
| 696 |
if (input.checked) { |
| 697 |
screenFormFields.append(input.name, input.value); |
| 698 |
} |
| 699 |
} |
| 700 |
else { |
| 701 |
screenFormFields.append(input.name, input.value); |
| 702 |
} |
| 703 |
} |
| 704 |
}); |
| 705 |
let screenParameters = new URLSearchParams(screenFormFields).toString(); |
| 706 |
|
| 707 |
formParameters += ((formParameters === '') ? '' : '&') + 'action=photonic_wizard_next_screen&screen=' + activeScreen + '&_ajax_nonce=' + clicked.getAttribute('data-photonic-nonce'); |
| 708 |
|
| 709 |
// Make AJAX call if we are on the last screen, or if the current screen's parameters have changed since the last time. |
| 710 |
// Otherwise just get the previously fetched screen. This saves a server call, and also helps preserve screen changes not sent to the back-end. |
| 711 |
if (shortcode) { |
| 712 |
if (isMCE) { // TinyMCE Editor |
| 713 |
photonicIFramePort.postMessage({type: 'photonicUpdateGallery', html: shortcode.textContent}); |
| 714 |
} |
| 715 |
else if (isBlock) { // Gutenberg |
| 716 |
photonicIFramePort.postMessage({type: 'photonicUpdateGallery', props: shortcode.value}); |
| 717 |
} |
| 718 |
else if (isWidget) { |
| 719 |
photonicIFramePort.postMessage({type: 'photonicUpdateGallery', html: shortcode.textContent}); |
| 720 |
} |
| 721 |
else { |
| 722 |
photonicIFramePort.postMessage({type: 'photonicUpdateGallery', html: shortcode.textContent}); |
| 723 |
} |
| 724 |
} |
| 725 |
else if (activeScreen === 2 |
| 726 |
&& document.querySelector('input[name="provider"]') && document.querySelector('input[name="provider"]').value === 'wp' |
| 727 |
&& document.querySelector('select[name="display_type"]') && document.querySelector('select[name="display_type"]').value === 'multi-photo') { |
| 728 |
initializeWPMediaLibrary(activeScreen, nextScreen, activeScreenElement, screenParameters, clicked); |
| 729 |
photonicIFramePort.postMessage({type: 'photonicOpenMediaLibrary'}); |
| 730 |
setWaitingVisibility(false); |
| 731 |
} |
| 732 |
else if (activeScreen === photonicLastActiveScreen || submission !== screenParameters || photonicMustPost) { |
| 733 |
postFlowData(activeScreen, nextScreen, activeScreenElement, screenParameters, formParameters); |
| 734 |
} |
| 735 |
else { |
| 736 |
wizardLogic(nextScreen); |
| 737 |
setWaitingVisibility(false); |
| 738 |
} |
| 739 |
} |
| 740 |
else if (clicked.classList.contains('previous')) { |
| 741 |
let forceScreen = activeScreenElement.querySelector('input[name="force_previous_screen"]'); |
| 742 |
if (forceScreen && parseInt(forceScreen.value, 10) > -1) { |
| 743 |
previousScreen = parseInt(forceScreen.value, 10); |
| 744 |
} |
| 745 |
|
| 746 |
wizardLogic(previousScreen); |
| 747 |
setWaitingVisibility(false); |
| 748 |
} |
| 749 |
} |
| 750 |
}); |
| 751 |
|
| 752 |
document.addEventListener('click', e => { |
| 753 |
if (!(e.target instanceof Element) || !e.target.closest('.photonic-gallery a')) { |
| 754 |
return; |
| 755 |
} |
| 756 |
e.preventDefault(); |
| 757 |
document.querySelectorAll('.photonic-gallery a').forEach(icon => { |
| 758 |
icon.classList.remove('selected'); |
| 759 |
}); |
| 760 |
const clicked = e.target.closest('.photonic-gallery a'); |
| 761 |
clicked.classList.add('selected'); |
| 762 |
document.getElementById('provider').value = clicked.getAttribute('data-provider'); |
| 763 |
}); |
| 764 |
|
| 765 |
document.addEventListener('click', e => { |
| 766 |
if (!(e.target instanceof Element) || !e.target.closest('.photonic-flow-selector')) { |
| 767 |
return; |
| 768 |
} |
| 769 |
e.preventDefault(); |
| 770 |
|
| 771 |
const clicked = e.target.closest('.photonic-flow-selector'); |
| 772 |
const container = clicked.closest('.photonic-flow-selector-container'); |
| 773 |
const selectionMode = container.getAttribute('data-photonic-flow-selector-mode'); |
| 774 |
|
| 775 |
if (selectionMode === 'none') { |
| 776 |
return; |
| 777 |
} |
| 778 |
else if (selectionMode === 'single' || selectionMode === 'single-no-plus') { |
| 779 |
container.querySelectorAll('.photonic-flow-selector').forEach(selector => { |
| 780 |
selector.classList.remove('selected'); |
| 781 |
}); |
| 782 |
container.querySelectorAll('.photonic-flow-selector .dashicons').forEach(selector => { |
| 783 |
selector.remove(); |
| 784 |
}); |
| 785 |
|
| 786 |
if (container.getAttribute('data-photonic-flow-selector-for') === 'selected_data') { |
| 787 |
const selectionPassworded = document.querySelector('input[name="selection_passworded"]'); |
| 788 |
|
| 789 |
if (clicked.classList.contains('passworded')) { |
| 790 |
if (selectionPassworded.value === '') { |
| 791 |
photonicMustPost = true; |
| 792 |
} |
| 793 |
selectionPassworded.value = '1'; |
| 794 |
} |
| 795 |
else { |
| 796 |
if (selectionPassworded.value === '1' || selectionPassworded.value === 1) { |
| 797 |
photonicMustPost = true; |
| 798 |
} |
| 799 |
selectionPassworded.value = ''; |
| 800 |
} |
| 801 |
} |
| 802 |
} |
| 803 |
|
| 804 |
if (selectionMode === 'multi') { |
| 805 |
clicked.classList.add('selected'); |
| 806 |
addDashIcon(clicked); |
| 807 |
} |
| 808 |
else if (selectionMode === 'single-no-plus' || selectionMode === 'single') { |
| 809 |
clicked.classList.add('selected'); |
| 810 |
} |
| 811 |
updateSelection(clicked); |
| 812 |
}); |
| 813 |
|
| 814 |
function addDashIcon(thumbnail) { |
| 815 |
const icon = document.createElement("a"); |
| 816 |
icon.classList.add('dashicons', 'dashicons-plus'); |
| 817 |
icon.href = '#'; |
| 818 |
thumbnail.append(icon); |
| 819 |
icon.addEventListener('click', ie => { // For some reason, doing this on document.addEventListener is unable to remove the dashicons. |
| 820 |
ie.preventDefault(); |
| 821 |
ie.stopPropagation(); |
| 822 |
thumbnail.classList.remove('selected'); |
| 823 |
icon.remove(); |
| 824 |
updateSelection(thumbnail); |
| 825 |
}); |
| 826 |
|
| 827 |
['mouseenter', 'mouseleave'].forEach(eventType => { |
| 828 |
icon.addEventListener(eventType, me => { |
| 829 |
me.preventDefault(); |
| 830 |
me.stopPropagation(); |
| 831 |
icon.classList.toggle('dashicons-plus'); |
| 832 |
icon.classList.toggle('dashicons-minus'); |
| 833 |
}); |
| 834 |
}); |
| 835 |
} |
| 836 |
|
| 837 |
document.addEventListener('click', e => { |
| 838 |
if (!(e.target instanceof Element) || !e.target.closest('.photonic-mark')) { |
| 839 |
return; |
| 840 |
} |
| 841 |
e.preventDefault(); |
| 842 |
const clicked = e.target.closest('.photonic-mark'); |
| 843 |
const markFor = clicked.getAttribute('data-photonic-mark-for'); |
| 844 |
const thumbnails = document.querySelectorAll('.photonic-flow-selector-container[data-photonic-flow-selector-for="' + markFor + '"] .photonic-flow-selector'); |
| 845 |
let selection = ''; |
| 846 |
thumbnails.forEach(thumbnail => { |
| 847 |
if (clicked.classList.contains('photonic-mark-all') && !thumbnail.classList.contains('selected')) { |
| 848 |
thumbnail.classList.add('selected'); |
| 849 |
addDashIcon(thumbnail); |
| 850 |
selection += thumbnail.querySelector('.photonic-flow-selector-inner').getAttribute('data-photonic-selection-id') + ','; |
| 851 |
} |
| 852 |
else if (clicked.classList.contains('photonic-mark-none')) { |
| 853 |
thumbnail.classList.remove('selected'); |
| 854 |
if (thumbnail.querySelector('.dashicons')) { |
| 855 |
thumbnail.querySelector('.dashicons').remove(); |
| 856 |
} |
| 857 |
} |
| 858 |
}); |
| 859 |
if (selection !== '') { |
| 860 |
selection = selection.replace(/^,+|,+$/g, ''); |
| 861 |
} |
| 862 |
document.querySelector('input[name="' + markFor + '"]').value = selection; |
| 863 |
}); |
| 864 |
|
| 865 |
document.addEventListener('click', e => { |
| 866 |
if (!(e.target instanceof Element) || !e.target.closest('a.photonic-add-date-filter')) { |
| 867 |
return; |
| 868 |
} |
| 869 |
e.preventDefault(); |
| 870 |
const clicked = e.target.closest('a.photonic-add-date-filter'); |
| 871 |
|
| 872 |
const dateFilterField = clicked.getAttribute('data-photonic-add-date'); |
| 873 |
const list = document.querySelector('ol[data-photonic-date-filter="' + dateFilterField + '"]'); |
| 874 |
const dateFilterCount = parseInt(list.getAttribute('data-photonic-filter-count'), 10); |
| 875 |
const currentCount = list.children.length; |
| 876 |
const listItem = document.createElement("li"); |
| 877 |
const div = document.createElement('div'); |
| 878 |
div.classList.add('photonic-single-date'); |
| 879 |
const parts = ['Year', 'Month', 'Date']; |
| 880 |
const texts = ['Year (0 - 9999)', 'Month (0 - 12)', 'Date (0 - 31)']; |
| 881 |
parts.forEach((part, j) => { |
| 882 |
div.insertAdjacentHTML('beforeend', |
| 883 |
"<label class='photonic-date-filter'>" + |
| 884 |
part.substring(0, 1) + |
| 885 |
"<input type='text' class='photonic-date-" + part.toLowerCase() + "' name='" + dateFilterField + "_" + part.toLowerCase() + "[]' aria-describedby='date_filter_" + dateFilterField + "_" + currentCount + "_" + part.toLowerCase() + "-hint'/>" + |
| 886 |
"<div class='photonic-flow-hint' role='tooltip' id='date_filter_" + dateFilterField + "_" + currentCount + "_" + part.toLowerCase() + "-hint'>" + texts[j] + "</div>" + |
| 887 |
"</label>" |
| 888 |
); |
| 889 |
}); |
| 890 |
listItem.append(div); |
| 891 |
listItem.insertAdjacentHTML('beforeend', "<a href='#' class='photonic-remove-date-filter' title='Remove filter'><span class=\"dashicons dashicons-no\"> </span></a>"); |
| 892 |
list.append(listItem); |
| 893 |
if (list.children.length === dateFilterCount) { |
| 894 |
clicked.style.display = 'none'; |
| 895 |
} |
| 896 |
}); |
| 897 |
|
| 898 |
document.addEventListener('click', e => { |
| 899 |
if (!(e.target instanceof Element) || !e.target.closest('a.photonic-add-date-range-filter')) { |
| 900 |
return; |
| 901 |
} |
| 902 |
e.preventDefault(); |
| 903 |
const clicked = e.target.closest('a.photonic-add-date-range-filter'); |
| 904 |
|
| 905 |
const dateFilterField = clicked.getAttribute('data-photonic-add-date-range'); |
| 906 |
const list = document.querySelector('ol[data-photonic-date-range-filter="' + dateFilterField + '"]'); |
| 907 |
const dateFilterCount = parseInt(list.getAttribute('data-photonic-filter-count'), 10); |
| 908 |
const currentCount = list.children.length; |
| 909 |
const listItem = document.createElement('li'); |
| 910 |
const parts = ['Year', 'Month', 'Date']; |
| 911 |
const range_parts = ['start', 'finish']; |
| 912 |
const texts = ['Year (0 - 9999)', 'Month (0 - 12)', 'Date (0 - 31)']; |
| 913 |
|
| 914 |
range_parts.forEach(range_part => { |
| 915 |
const div = document.createElement('div'); |
| 916 |
div.classList.add('photonic-single-date'); |
| 917 |
parts.forEach((part, counter) => { |
| 918 |
div.insertAdjacentHTML('beforeend', |
| 919 |
"<label class='photonic-date-filter'>" + |
| 920 |
part.substr(0, 1) + |
| 921 |
"<input type='text' class='photonic-date-" + part.toLowerCase() + "' name='" + dateFilterField + "_" + range_part + "_" + part.toLowerCase() + "[]' aria-describedby='date_range_filter_" + dateFilterField + "_" + currentCount + "_" + range_part + "_" + part.toLowerCase() + "-hint'/>" + |
| 922 |
"<div class='photonic-flow-hint' role='tooltip' id='date_range_filter_" + dateFilterField + "_" + currentCount + "_" + range_part + "_" + part.toLowerCase() + "-hint'>" + texts[counter] + "</div>" + |
| 923 |
"</label>" |
| 924 |
); |
| 925 |
}); |
| 926 |
listItem.append(div); |
| 927 |
}); |
| 928 |
|
| 929 |
listItem.insertAdjacentHTML('beforeend', "<a href='#' class='photonic-remove-date-range-filter' title='Remove filter'><span class=\"dashicons dashicons-no\"> </span></a>"); |
| 930 |
list.append(listItem); |
| 931 |
if (list.children.length === dateFilterCount) { |
| 932 |
clicked.style.display = 'none'; |
| 933 |
} |
| 934 |
}); |
| 935 |
|
| 936 |
document.addEventListener('click', e => { |
| 937 |
if (!(e.target instanceof Element) || !e.target.closest('a.photonic-remove-date-filter')) { |
| 938 |
return; |
| 939 |
} |
| 940 |
e.preventDefault(); |
| 941 |
const clicked = e.target.closest('a.photonic-remove-date-filter'); |
| 942 |
|
| 943 |
const listItem = clicked.closest('li'); |
| 944 |
const list = listItem.parentElement; |
| 945 |
const dateFilterField = list.getAttribute('data-photonic-date-filter'); |
| 946 |
const dateFilterCount = parseInt(list.getAttribute('data-photonic-filter-count'), 10); |
| 947 |
let addButton = document.querySelector("a[data-photonic-add-date='" + dateFilterField + "']"); |
| 948 |
if (!addButton) { |
| 949 |
addButton = document.createElement('a'); |
| 950 |
addButton.setAttribute('href', '#'); |
| 951 |
addButton.setAttribute('data-photonic-add-date', dateFilterField); |
| 952 |
addButton.classList.add('photonic-add-date-filter'); |
| 953 |
addButton.insertAdjacentHTML('beforeend', "<span class=\"dashicons dashicons-plus-alt\"> </span> Add filter"); |
| 954 |
|
| 955 |
list.after(addButton); |
| 956 |
addButton.style.display = 'none'; |
| 957 |
} |
| 958 |
listItem.remove(); |
| 959 |
if (list.children.length < dateFilterCount) { |
| 960 |
addButton.style.display = 'block'; |
| 961 |
} |
| 962 |
}); |
| 963 |
|
| 964 |
document.addEventListener('click', e => { |
| 965 |
if (!(e.target instanceof Element) || !e.target.closest('a.photonic-remove-date-range-filter')) { |
| 966 |
return; |
| 967 |
} |
| 968 |
e.preventDefault(); |
| 969 |
const clicked = e.target.closest('a.photonic-remove-date-range-filter'); |
| 970 |
const listItem = clicked.closest('li'); |
| 971 |
const list = listItem.parentElement; |
| 972 |
const dateFilterField = list.getAttribute('data-photonic-date-range-filter'); |
| 973 |
const dateFilterCount = parseInt(list.getAttribute('data-photonic-filter-count'), 10); |
| 974 |
|
| 975 |
let addButton = document.querySelector("a[data-photonic-add-date-range='" + dateFilterField + "']"); |
| 976 |
if (!addButton) { |
| 977 |
addButton = document.createElement('a'); |
| 978 |
addButton.setAttribute('href', '#'); |
| 979 |
addButton.setAttribute('data-photonic-add-date-range', dateFilterField); |
| 980 |
addButton.classList.add('photonic-add-date-range-filter'); |
| 981 |
addButton.insertAdjacentHTML('beforeend', "<span class=\"dashicons dashicons-plus-alt\"> </span> Add filter"); |
| 982 |
|
| 983 |
list.after(addButton); |
| 984 |
addButton.style.display = 'none'; |
| 985 |
} |
| 986 |
|
| 987 |
listItem.remove(); |
| 988 |
if (list.children.length < dateFilterCount) { |
| 989 |
addButton.style.display = 'block'; |
| 990 |
} |
| 991 |
}); |
| 992 |
|
| 993 |
document.addEventListener('change', e => { |
| 994 |
if (!(e.target instanceof Element) || !e.target.closest('input[class^=photonic-date-]')) { |
| 995 |
return; |
| 996 |
} |
| 997 |
e.preventDefault(); |
| 998 |
const changed = e.target.closest('input[class^=photonic-date-]'); |
| 999 |
const container = changed.closest('ol'); |
| 1000 |
if (container) { |
| 1001 |
const range = container.getAttribute('data-photonic-date-range-filter') !== undefined; |
| 1002 |
const dates = container.children; |
| 1003 |
let listMerge = []; |
| 1004 |
|
| 1005 |
dates.forEach(date => { |
| 1006 |
let itemMerge = []; |
| 1007 |
const dateFields = date.querySelectorAll('input'); |
| 1008 |
if (dateFields.length > 0) { |
| 1009 |
itemMerge[itemMerge.length] = []; |
| 1010 |
} |
| 1011 |
if (dateFields.length > 3) { |
| 1012 |
itemMerge[itemMerge.length] = []; |
| 1013 |
} |
| 1014 |
dateFields.forEach((d, i) => { |
| 1015 |
const mod = Math.floor(i / 3); |
| 1016 |
const div = i % 3; |
| 1017 |
itemMerge[mod][div] = d.value === '' ? 0 : d.value; |
| 1018 |
}); |
| 1019 |
itemMerge.forEach((d, i) => { |
| 1020 |
itemMerge[i] = d.join('/'); |
| 1021 |
}); |
| 1022 |
listMerge.push(itemMerge.join('-')); |
| 1023 |
}); |
| 1024 |
listMerge = listMerge.join(); |
| 1025 |
if (range) { |
| 1026 |
document.querySelector('input[name="' + container.getAttribute('data-photonic-date-range-filter') + '"]').value = listMerge; |
| 1027 |
} |
| 1028 |
else { |
| 1029 |
document.querySelector('input[name="' + container.getAttribute('data-photonic-date-filter') + '"]').value = listMerge; |
| 1030 |
} |
| 1031 |
} |
| 1032 |
}); |
| 1033 |
|
| 1034 |
document.addEventListener('click', e => { |
| 1035 |
if (!(e.target instanceof Element) || !e.target.closest('a.photonic-flow-more')) { |
| 1036 |
return; |
| 1037 |
} |
| 1038 |
e.preventDefault(); |
| 1039 |
|
| 1040 |
const clicked = e.target.closest('a.photonic-flow-more'); |
| 1041 |
const container = clicked.closest('.photonic-flow-selector-container'); |
| 1042 |
const link = clicked.getAttribute('data-photonic-more-link'); |
| 1043 |
const existing = document.querySelector('input[name="photonic-editor-shortcode"]') ? document.querySelector('input[name="photonic-editor-shortcode"]').value : undefined; |
| 1044 |
const existingBlock = document.querySelector('input[name="photonic-editor-json"]') ? document.querySelector('input[name="photonic-editor-json"]').value : undefined; |
| 1045 |
|
| 1046 |
let shortcode, attributes, albumFilter; |
| 1047 |
|
| 1048 |
if (existing && !isBlock) { |
| 1049 |
if (photonicShortcodeObjectEditor !== undefined) { |
| 1050 |
attributes = photonicShortcodeObjectEditor.shortcode.attrs.named; |
| 1051 |
if (attributes['filter']) { |
| 1052 |
albumFilter = attributes['filter']; |
| 1053 |
} |
| 1054 |
} |
| 1055 |
} |
| 1056 |
else if (existingBlock && isBlock) { // Gutenberg |
| 1057 |
if (photonicParentShortcode !== undefined && photonicParentShortcode !== '') { |
| 1058 |
shortcode = photonicParentShortcode; |
| 1059 |
attributes = JSON.parse(shortcode); |
| 1060 |
|
| 1061 |
if (attributes.filter !== undefined) { |
| 1062 |
albumFilter = attributes.filter; |
| 1063 |
} |
| 1064 |
} |
| 1065 |
} |
| 1066 |
|
| 1067 |
if (link !== undefined && link !== '') { |
| 1068 |
setWaitingVisibility(true); |
| 1069 |
let parameters = []; |
| 1070 |
parameters['action'] = 'photonic_wizard_more'; |
| 1071 |
parameters['provider'] = clicked.getAttribute('data-photonic-provider'); |
| 1072 |
parameters['display_type'] = clicked.getAttribute('data-photonic-display-type'); |
| 1073 |
parameters['url'] = encodeURIComponent(clicked.getAttribute('data-photonic-more-link')); |
| 1074 |
|
| 1075 |
if (albumFilter) { |
| 1076 |
albumFilter = '&filter=' + albumFilter; |
| 1077 |
} |
| 1078 |
else { |
| 1079 |
albumFilter = ''; |
| 1080 |
} |
| 1081 |
parameters = 'action=photonic_wizard_more&provider=' + clicked.getAttribute('data-photonic-provider') + '&display_type=' + clicked.getAttribute('data-photonic-display-type') + '&url=' + |
| 1082 |
btoa(clicked.getAttribute('data-photonic-more-link')) + albumFilter + '&_ajax_nonce=' + clicked.getAttribute('data-photonic-nonce'); |
| 1083 |
|
| 1084 |
post(Photonic_Wizard_JS.ajaxurl, parameters, function (data) { |
| 1085 |
clicked.style.display = 'none'; |
| 1086 |
if (clicked.closest('.photonic-more-wrapper')) { |
| 1087 |
clicked.closest('.photonic-more-wrapper').remove(); |
| 1088 |
} |
| 1089 |
const currentSelectors = container.querySelectorAll('.photonic-flow-selector'); |
| 1090 |
const lastItem = currentSelectors.item(currentSelectors.length - 1); |
| 1091 |
|
| 1092 |
if (lastItem) { |
| 1093 |
lastItem.insertAdjacentHTML('afterend', data); |
| 1094 |
} |
| 1095 |
|
| 1096 |
const search = document.getElementById('thumb-search'); |
| 1097 |
search.focus(); |
| 1098 |
search.blur(); |
| 1099 |
|
| 1100 |
updateSelection(document.querySelector('.photonic-flow-selector:last-child')); |
| 1101 |
|
| 1102 |
setWaitingVisibility(false); |
| 1103 |
}); |
| 1104 |
} |
| 1105 |
}); |
| 1106 |
|
| 1107 |
document.addEventListener('mouseover', e => { |
| 1108 |
if (!(e.target instanceof Element) || !e.target.closest('input, select')) { |
| 1109 |
return; |
| 1110 |
} |
| 1111 |
e.stopPropagation(); |
| 1112 |
const item = e.target; |
| 1113 |
const tooltip = document.querySelector('#' + item.getAttribute('aria-describedby')); |
| 1114 |
if (tooltip) { |
| 1115 |
tooltip.setAttribute('aria-hidden', false); |
| 1116 |
tooltip.style.display = 'block'; |
| 1117 |
fadeIn(tooltip); |
| 1118 |
} |
| 1119 |
}); |
| 1120 |
|
| 1121 |
document.addEventListener('mouseout', e => { |
| 1122 |
if (!(e.target instanceof Element) || !e.target.closest('input, select, .photonic-flow-hint')) { |
| 1123 |
return; |
| 1124 |
} |
| 1125 |
e.stopPropagation(); |
| 1126 |
const item = e.target; |
| 1127 |
const tooltipId = item.classList.contains('photonic-flow-hint') ? item.getAttribute('id') : '#' + item.getAttribute('aria-describedby'); |
| 1128 |
const tooltip = document.querySelector(tooltipId); |
| 1129 |
if (tooltip && !document.querySelector(tooltipId + ':hover')) { |
| 1130 |
tooltip.setAttribute('aria-hidden', true); |
| 1131 |
tooltip.style.display = 'none'; |
| 1132 |
} |
| 1133 |
}); |
| 1134 |
|
| 1135 |
document.getElementById('photonic-flow').addEventListener('focusin', e => { |
| 1136 |
if (!e.target.matches('#thumb-search')) { |
| 1137 |
return; |
| 1138 |
} |
| 1139 |
|
| 1140 |
const search = e.target; |
| 1141 |
const images = document.querySelectorAll('.photonic-flow-selector-container img'); |
| 1142 |
const cache = []; |
| 1143 |
|
| 1144 |
images.forEach((image) => { |
| 1145 |
cache.push({ |
| 1146 |
element: image, |
| 1147 |
text: image.alt.trim().toLowerCase() |
| 1148 |
}); |
| 1149 |
}); |
| 1150 |
|
| 1151 |
function filter(e) { |
| 1152 |
const query = e.target.value.trim().toLowerCase(); |
| 1153 |
cache.forEach(image => { |
| 1154 |
let index = 0; |
| 1155 |
if (query) { |
| 1156 |
index = image.text.indexOf(query); |
| 1157 |
} |
| 1158 |
if (index === -1) { |
| 1159 |
image.element.closest('.photonic-flow-selector').style.display = 'none'; |
| 1160 |
} |
| 1161 |
else { |
| 1162 |
image.element.closest('.photonic-flow-selector').style.display = 'inline-block'; |
| 1163 |
} |
| 1164 |
}); |
| 1165 |
} |
| 1166 |
|
| 1167 |
search.addEventListener('input', filter); |
| 1168 |
search.addEventListener('keyup', filter); |
| 1169 |
}); |
| 1170 |
|
| 1171 |
document.addEventListener('change', e => { |
| 1172 |
if (!(e.target instanceof Element) || !e.target.matches('[name="selected_data"],[name="selection_passworded"]')) { |
| 1173 |
return; |
| 1174 |
} |
| 1175 |
photonicMustPost = true; |
| 1176 |
}); |
| 1177 |
} |
| 1178 |
|
| 1179 |
PhotonicWizard(); |
| 1180 |
}); |
| 1181 |
|