// 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);