- Implemented StreamInterface, UploadedFileInterface, and UriInterface as per PSR standards. - Added getallheaders function to retrieve HTTP headers in a compatible manner. - Included LICENSE files for ralouphie/getallheaders and symfony/deprecation-contracts. - Introduced function for triggering deprecation notices in Symfony.
313 lines
14 KiB
JavaScript
313 lines
14 KiB
JavaScript
'use strict';
|
|
|
|
(() => {
|
|
const { createBlock } = wp.blocks;
|
|
const { dispatch, select } = wp.data;
|
|
class atfpCreateNewBlock {
|
|
constructor() {
|
|
this.updateBlockStore = {};
|
|
this.loaderRemove = null;
|
|
this.loader = null;
|
|
this.replaceAttributes = null;
|
|
this.updateBlockId = new Array();
|
|
}
|
|
|
|
copyTranslateText = () => {
|
|
// Get the current selection object
|
|
const selection = window.getSelection();
|
|
// Create a new range object
|
|
const range = document.createRange();
|
|
// Select the contents of the copy text element
|
|
range.selectNodeContents(document.getElementById('atfp-copy-text'));
|
|
// Remove any existing selections
|
|
selection.removeAllRanges();
|
|
// Add the new range to the selection
|
|
selection.addRange(range);
|
|
// Execute the copy command
|
|
document.execCommand('copy');
|
|
// Clear the selection
|
|
selection.removeAllRanges();
|
|
}
|
|
|
|
noticeInitialize = () => {
|
|
dispatch("core/notices").createNotice('info', 'To enable translation, please include the Make This Content Available for Translation text in your block content. For help, watch the video and click <b>"Copy Text"</b> to use. Then, paste it into the section of your block you want automatically translated',
|
|
{
|
|
isDismissible : false,
|
|
id: 'atfp-notice-id',
|
|
actions: [
|
|
{
|
|
label: 'Watch Video.',
|
|
url: `${atfpAddBlockVars.atfp_demo_page_url}#custom-block-translate`,
|
|
},
|
|
],
|
|
__unstableHTML: true
|
|
}).then(()=>{
|
|
const targetAnchor=document.querySelector(`a[href^="${atfpAddBlockVars.atfp_demo_page_url}#custom-block-translate"]`);
|
|
|
|
if(targetAnchor){
|
|
targetAnchor.addEventListener('click', (e)=>{
|
|
e.preventDefault();
|
|
window.open(targetAnchor.href, '_blank');
|
|
})
|
|
}
|
|
});
|
|
}
|
|
|
|
copyBtnInitialize = () => { // Initialize the copy button
|
|
const copyBtn = document.createElement('div'); // Create a new div element for the copy button
|
|
copyBtn.id = 'atfp-copy-btn'; // Set the ID of the copy button
|
|
copyBtn.innerHTML = 'Copy Text'; // Set the inner HTML of the copy button
|
|
copyBtn.addEventListener('click', this.copyTranslateText); // Add click event listener to copy text
|
|
copyBtn.ariaLabel = 'Copy Text'; // Set the aria-label for accessibility
|
|
copyBtn.title = 'Click to copy the text "Make This Content Available for Translation"'; // Tooltip message
|
|
|
|
const copyText = document.createElement('div'); // Create a new div element for the copy text
|
|
copyText.id = 'atfp-copy-text'; // Set the ID of the copy text div
|
|
copyText.innerHTML = 'Make This Content Available for Translation'; // Set the inner HTML of the copy text div
|
|
|
|
document.body.appendChild(copyBtn); // Append the copy button to the document body
|
|
document.body.appendChild(copyText); // Append the copy text to the document body
|
|
}
|
|
|
|
addBlockInitialize = (newBlock) => {
|
|
this.newBlock = newBlock;
|
|
this.creteNewBlock();
|
|
this.skeletonLoader();
|
|
}
|
|
|
|
removeLoader = () => {
|
|
clearTimeout(this.loaderRemove);
|
|
|
|
this.loaderRemove = setTimeout(() => {
|
|
if (this.loader) {
|
|
this.loader.remove();
|
|
}
|
|
}, 2000);
|
|
|
|
}
|
|
|
|
creteNewBlock = () => {
|
|
const newBlock = createBlock(this.newBlock);
|
|
this.updateBlockData(newBlock);
|
|
}
|
|
|
|
updateBlockData = async (Block) => {
|
|
await dispatch('core/block-editor').insertBlocks([Block]);
|
|
|
|
setTimeout(() => {
|
|
const blockWrp = document.getElementById(`block-${Block.clientId}`);
|
|
if (blockWrp) {
|
|
blockWrp.appendChild(this.loader);
|
|
}
|
|
}, 100);
|
|
|
|
setTimeout(() => {
|
|
this.updateBlockContent(Block);
|
|
}, 400);
|
|
}
|
|
|
|
updateBlockContent = (Block) => {
|
|
const newBlock = document.getElementById(`block-${Block.clientId}`);
|
|
|
|
if (newBlock) {
|
|
this.updateContent(newBlock);
|
|
}
|
|
return;
|
|
}
|
|
|
|
updateContent = async (ele) => {
|
|
const element = ele;
|
|
let i = 1;
|
|
this.removeLoader();
|
|
|
|
if (element) {
|
|
if (element.contentEditable == 'true' && element.children.length < 2) {
|
|
element.innerHTML = 'Make This Content Available for Translation';
|
|
} else {
|
|
const innerElements = element.getElementsByTagName('*');
|
|
|
|
for (let innerElement of innerElements) {
|
|
if (i === innerElements.length) {
|
|
this.removeLoader();
|
|
setTimeout(() => {
|
|
this.updateBlockFromStore();
|
|
}, 500);
|
|
}
|
|
|
|
i++;
|
|
if (["SCRIPT", "STYLE", "META", "LINK", "TITLE", "NOSCRIPT", "STYLE", "SCRIPT", "NOSCRIPT", "STYLE", "SCRIPT", "NOSCRIPT", "STYLE", "SCRIPT", "NOSCRIPT"].includes(innerElement.tagName)) {
|
|
continue;
|
|
}
|
|
|
|
if (innerElement.childNodes.length > 0) {
|
|
innerElement.childNodes.forEach((child) => {
|
|
if (child.nodeType === Node.TEXT_NODE) {
|
|
this.updateBlockAttr(innerElement, child);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
updateBlockAttr = (innerElement, child) => {
|
|
let blockId = false;
|
|
if (innerElement.classList.contains('wp-block')) {
|
|
blockId = innerElement.dataset.block;
|
|
} else {
|
|
const parentBlock = innerElement.closest('.wp-block');
|
|
if (parentBlock) {
|
|
blockId = parentBlock.dataset.block;
|
|
}
|
|
}
|
|
|
|
const blockAttributes = select('core/block-editor').getBlockAttributes(blockId);
|
|
|
|
let index = 0;
|
|
|
|
if (!this.updateBlockStore[blockId]) {
|
|
let attributes = JSON.parse(JSON.stringify(blockAttributes));
|
|
this.updateBlockStore[blockId] = { attributes: attributes };
|
|
this.updateBlockStore[blockId].updateBlockData = {};
|
|
}
|
|
|
|
const updateNestedAttributes = async (attributes, child) => {
|
|
const updateAttributes = async (key) => {
|
|
index++;
|
|
|
|
if (typeof attributes[key] === 'string' && attributes[key].trim() !== '' && (attributes[key].trim() === child.textContent.trim() || attributes[key] === child.textContent.trim())) {
|
|
const originalValue = attributes[key];
|
|
const newValue = 'Make This Content Available for Translation ' + index;
|
|
this.updateBlockStore[blockId].updateBlockData[newValue.replace(/\s+/g, '-')] = originalValue;
|
|
attributes[key] = newValue;
|
|
}
|
|
};
|
|
|
|
if (typeof attributes === 'object' && attributes !== null) {
|
|
for (const key of Object.keys(attributes)) {
|
|
await updateAttributes(key);
|
|
|
|
if (typeof attributes[key] === 'object' && attributes[key] !== null) {
|
|
await updateNestedAttributes(attributes[key], child); // Recursively update nested objects
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
const blockStoreAttributes = this.updateBlockStore[blockId].attributes;
|
|
updateNestedAttributes(blockStoreAttributes, child);
|
|
}
|
|
|
|
updateBlockFromStore = () => {
|
|
const blockStoreAttributes = this.updateBlockStore;
|
|
|
|
Object.keys(blockStoreAttributes).forEach((blockId) => {
|
|
const blockAttributes = blockStoreAttributes[blockId].attributes;
|
|
this.removeLoader();
|
|
dispatch('core/block-editor').updateBlockAttributes(blockId, blockAttributes).then(() => {
|
|
clearTimeout(this.replaceAttributes);
|
|
this.replaceAttributes = setTimeout(() => {
|
|
this.removeLoader();
|
|
const blockIds = Object.keys(this.updateBlockStore);
|
|
this.replaceBlockContent(blockIds[0]);
|
|
}, 500);
|
|
});
|
|
});
|
|
}
|
|
|
|
replaceBlockContent = (blockId) => {
|
|
const blockStoreAttributes = this.updateBlockStore;
|
|
|
|
const checkValidAttributes = (value = false, blockId) => {
|
|
const blockElement = document.querySelector(`#block-${blockId}`);
|
|
const regex = new RegExp(value, 'g'); // Create regex from the value parameter with global flag
|
|
const matchFound = regex.test(blockElement.innerText); // Check if the regex matches
|
|
return matchFound; // Return the result of the regex test directly
|
|
};
|
|
|
|
const blockAttributes = blockStoreAttributes[blockId].attributes;
|
|
|
|
const upateNestedAttributes = async (attributes) => {
|
|
const updateAttributes = async (key) => {
|
|
|
|
if (typeof attributes[key] === 'string' && attributes[key].includes('Make This Content Available for Translation')) {
|
|
try {
|
|
const keyWithDashes = attributes[key].replace(/\s+/g, '-');
|
|
const originalValue = this.updateBlockStore[blockId].updateBlockData[keyWithDashes];
|
|
|
|
const status = checkValidAttributes(attributes[key], blockId);
|
|
|
|
if (!status) {
|
|
attributes[key] = originalValue;
|
|
} else {
|
|
attributes[key] = 'Make This Content Available for Translation';
|
|
}
|
|
} catch (e) {
|
|
console.log(`${attributes[key]} is not valid JSON.`);
|
|
}
|
|
}
|
|
};
|
|
|
|
if (typeof attributes === 'object' && attributes !== null) {
|
|
for (const key of Object.keys(attributes)) {
|
|
await updateAttributes(key);
|
|
|
|
if (typeof attributes[key] === 'object' && attributes[key] !== null) {
|
|
await upateNestedAttributes(attributes[key]); // Recursively update nested objects
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
upateNestedAttributes(blockAttributes);
|
|
|
|
setTimeout(() => {
|
|
dispatch('core/block-editor').updateBlockAttributes(blockId, blockAttributes).then(() => {
|
|
const blockIds = Object.keys(this.updateBlockStore);
|
|
if (blockIds.length > 0) {
|
|
this.updateBlockId.push(blockId);
|
|
dispatch('core/block-editor').selectBlock(null);
|
|
this.removeLoader();
|
|
const firstBlockId = blockIds.find(id => !this.updateBlockId.includes(id));
|
|
if (firstBlockId) {
|
|
this.replaceBlockContent(firstBlockId);
|
|
}
|
|
}
|
|
});
|
|
}, 500);
|
|
}
|
|
|
|
skeletonLoader = () => {
|
|
const loader = document.createElement('div');
|
|
|
|
const loaderContainer = () => {
|
|
const container = '<style>.atfp-loader-wrapper{position:absolute;width:100%;height:100%;top:0;left:0;z-index:99999;}.atfp-loader-container{width:100%;height:100%;}.atfp-loader-skeleton{--skbg:hsl(227deg, 13%, 50%, 0.2);display:grid;gap:20px;width:100%;height:100%;background:#ffffff;padding:15px;border-radius:8px;box-shadow:0 4px 12px rgba(0, 0, 0, 0.1);transition:transform 0.3s ease;transform:scale(1.02);}.atfp-loader-shimmer{display:flex;aspect-ratio:2/1;width:100%;height:100%;background:var(--skbg);border-radius:4px;overflow:hidden;position:relative;}.atfp-loader-shimmer::before{content:"";position:absolute;width:100%;height:100%;background-image:linear-gradient(-90deg,transparent 8%,rgba(255,255,255,0.28) 18%,transparent 33%);background-size:200%;animation:shimerAnimate 1.5s ease-in-out infinite;}@keyframes shimerAnimate{0%{background-position:100% 0;}100%{background-position:-100% 0;}}</style>'
|
|
|
|
return '<div class="atfp-loader-container">' + container + '<div class="atfp-loader-skeleton"><span class="atfp-loader-shimmer"></span></div></div>';
|
|
}
|
|
|
|
loader.className = 'atfp-loader-wrapper'; // Add the atfp class to the loader
|
|
loader.innerHTML = loaderContainer();
|
|
|
|
this.loader = loader;
|
|
}
|
|
}
|
|
|
|
|
|
window.addEventListener('load', () => {
|
|
const atfpCreateBlockObj = new atfpCreateNewBlock();
|
|
|
|
atfpCreateBlockObj.copyBtnInitialize();
|
|
atfpCreateBlockObj.noticeInitialize();
|
|
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
let newBlock = '';
|
|
|
|
if (urlParams.has('atfp_new_block') && '' !== urlParams.get('atfp_new_block').trim()) {
|
|
newBlock = urlParams.get('atfp_new_block');
|
|
atfpCreateBlockObj.addBlockInitialize(newBlock);
|
|
}
|
|
});
|
|
})();
|