// SPDX-License-Identifier: EUPL-1.2
// Authors: see README.md
/*global ContentTools ContentEdit Noty*/
(function () {
var Notify = function (type, text) {
new Noty({
type: type,
text: text,
timeout: type == 'success' ? 3000 : 5000
}).show();
};
var ImageUploader = function (dialog) {
var image, xhr, xhrComplete, xhrProgress;
// Cancel the current upload
dialog.addEventListener('imageuploader.cancelupload', function () {
// Stop the upload
if (xhr) {
xhr.upload.removeEventListener('progress', xhrProgress);
xhr.removeEventListener('readystatechange', xhrComplete);
xhr.abort();
}
// Set the dialog to empty
dialog.state('empty');
});
// Clear the current image
dialog.addEventListener('imageuploader.clear', function () {
dialog.clear();
image = null;
});
// Handle upload progress and completion
dialog.addEventListener('imageuploader.fileready', function (ev) {
function xhrProgress(ev) {
// Set the progress for the upload
dialog.progress((ev.loaded / ev.total) * 100);
}
function xhrComplete(ev) {
var response;
// Check the request is complete
if (ev.target.readyState != 4) {
return;
}
// Clear the request
xhr = null
xhrProgress = null
xhrComplete = null
if (parseInt(ev.target.status) != 200) {
// The request failed, notify the user
new ContentTools.FlashUI('no');
return;
}
// Handle the result of the upload
// Unpack the response (from JSON)
try {
response = JSON.parse(ev.target.responseText);
} catch (e) {
console.error('PicoContentEditor : UPLOAD ERROR', ev.target.responseText);
Notify('error', 'There was an error reading the server response');
return;
}
if (response.debug) {
console.log('PicoContentEditor : UPLOAD RESPONSE', response);
}
if (response.file) {
// Store the image details
image = {
url: response.file.path,
name: response.file.name,
width: parseInt(response.file.size[0]),
height: parseInt(response.file.size[1])
};
image.size = [image.width, image.height];
// Populate the dialog
dialog.populate(image.url, image.size);
}
// response notifications
response.status.forEach(status => {
Notify(status.state ? 'success' : 'warning', status.message);
});
}
// Set the dialog state to uploading and reset the progress bar to 0
dialog.state('uploading');
dialog.progress(0);
// Build the form data to post to the server
var file = ev.detail().file;
var formData = new FormData();
formData.append('PicoContentEditorUpload', file);
// Make the request
xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', xhrProgress);
xhr.addEventListener('readystatechange', xhrComplete);
xhr.open('POST', '', true);
xhr.send(formData);
console.log('PicoContentEditor : UPLOAD', file);
});
dialog.addEventListener('imageuploader.save', function () {
var crop, cropRegion, formData;
// Check if a crop region has been defined by the user
if (dialog.cropRegion()) {
crop = dialog.cropRegion()
}
// Trigger the save event against the dialog with details of the
// image to be inserted.
dialog.save(image.url, image.size, {
'alt': image.name,
'data-ce-max-width': image.width
});
console.log('PicoContentEditor : INSERT IMAGE', image);
});
}
window.onload = function () {
var editor;
ContentTools.IMAGE_UPLOADER = ImageUploader;
let applyToImages = function (element) {
return element.content !== undefined || element.type() === 'Image' || element.type() === 'Video';
}
ContentTools.Tools.AlignLeft.canApply = applyToImages;
ContentTools.Tools.AlignRight.canApply = applyToImages;
ContentTools.Tools.AlignCenter.canApply = applyToImages;
editor = ContentTools.EditorApp.get();
editor.init('[data-editable], [data-fixture]', 'data-name');
editor.addEventListener('saved', function (ev) {
var onStateChange, passive, payload, xhr;
var edits = ev.detail().regions,
regions = editor.regions(),
query = {
regions: {}
},
editsNames = Object.keys(edits);
// Check if this was a passive save
passive = ev.detail().passive;
// Check to see if there are any changes to save
if (editsNames.length == 0) return;
// for fixtures, uses dom innerHTML to get rid of outer el.
// see https://github.com/GetmeUK/ContentTools/issues/448
editsNames.forEach(name => {
var el = regions[name].domElement();
// this region is the page meta
if (el.dataset.meta !== undefined) {
query.meta = el.innerHTML
// as we don't use proper region value (see above),
// we need to get rid of utility character
// see https://github.com/GetmeUK/ContentTools/issues/263
query.meta = query.meta.replace(/\u200B/g, '');
delete query.regions[name];
return;
}
query.regions[name] = {
markdown: el.dataset.editable == 'markdown',
html: regions[name].type() == 'Fixture' ? el.innerHTML : regions[name].html()
};
});
// Set the editors state to busy while we save our changes
this.busy(true);
// Collect the contents of each region into a FormData instance
payload = new FormData();
payload.append('PicoContentEditor', JSON.stringify(query));
// Send the update content to the server to be saved
onStateChange = function (ev) {
// Check if the request is finished
if (ev.target.readyState == 4) {
editor.busy(false);
if (ev.target.status != '200') {
// Save failed, Notify the user with a flash
new ContentTools.FlashUI('no');
return;
}
var response;
try {
response = JSON.parse(ev.target.response);
} catch (error) {
// response error
Notify('error', 'There was an error reading the server response');
console.error('PicoContentEditor : SAVE ERROR\n', ev.target.response);
return;
}
if (passive || !response) return;
if (response.debug) {
console.log('PicoContentEditor : SAVE RESPONSE', response);
}
// response notifications
response.status.forEach(status => {
Notify(status.state ? 'success' : 'warning', status.message);
});
// debug notifications
if (response.debug) {
var i = 0;
response.edited.regions.forEach(region => {
var source = region.source ? `(${region.source.split(/[\\/]/).pop()})` : '';
if (!region.message) return;
setTimeout(function () {
Notify(
region.saved ? 'success' : 'error',
`Debug
${region.name} : ${region.message} ${source}`
);
}, 50 * ++i);
});
}
}
};
xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', onStateChange);
xhr.open('POST', '');
xhr.send(payload);
console.log('PicoContentEditor : SAVE', query);
});
// Translation
var el_lang = document.getElementById('ContentToolsLanguage');
if (el_lang && el_lang.dataset.lang) {
let translation = JSON.parse(el_lang.textContent);
ContentEdit.addTranslations(el_lang.dataset.lang, translation);
ContentEdit.LANGUAGE = el_lang.dataset.lang;
}
// Contextual tools
var FIXTURE_TOOLS = [
['bold', 'italic', 'link'],
['undo', 'redo']
],
IMAGE_FIXTURE_TOOLS = [
['undo', 'redo', 'image']
],
PRE_FIXTURE_TOOLS = [
['undo', 'redo']
];
ContentEdit.Root.get().bind('focus', function (element) {
var tools;
if (element.isFixed()) {
if (element.tagName() === 'pre') {
tools = PRE_FIXTURE_TOOLS;
} else if (element.type() === 'ImageFixture') {
tools = IMAGE_FIXTURE_TOOLS;
} else {
tools = FIXTURE_TOOLS;
}
} else {
tools = ContentTools.DEFAULT_TOOLS;
}
if (editor.toolbox().tools() !== tools) {
return editor.toolbox().tools(tools);
}
});
};
}).call(this);