artabro/wire/modules/Inputfield/InputfieldCKEditor/plugins/pwimage/plugin.js
2024-08-27 11:35:37 +02:00

380 lines
14 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(function() {
CKEDITOR.plugins.add('pwimage', {
requires: 'dialog',
init: function(editor) {
var pluginName = 'pwimage';
// These are the allowed and required elements & attributes for images.
// It should clean all other classes but hidpi and three align classes that are generated by ProcessWire
var allowed =
'img[alt,id,!src,title,width](align_left,align_center,align_right,hidpi,align-left,align-center,align-right);' +
'a[!href];' +
'figure{width}(align_left,align_center,align_right,hidpi,align-left,align-center,align-right);' +
'figcaption;';
var required = 'img[alt,src]';
// add pwimage command (opens the ProcessWire image selection iFrame)
editor.addCommand(pluginName, {
allowedContent: allowed,
requiredContent: required,
exec: loadIframeImagePicker
});
editor.ui.addButton('PWImage', {
label: editor.lang.common.image,
command: pluginName,
hidpi: true,
icon: (CKEDITOR.env.hidpi ? this.path + 'images/hidpi/pwimage.png' : this.path + 'images/pwimage.png')
});
// On double click we execute the command (= we open the pw image selection iFrame defined above)
editor.on( 'doubleclick', function( evt ) {
var element = evt.data.element;
if ( (element.is( 'img' ) ) && !element.data( 'cke-realelement' ) && !element.isReadOnly() ) {
//var selection = editor.getSelection();
//editor.lockSelection();
//selection.lock();
evt.cancel(); // prevent CKE's link dialog from showing up (if image is linked)
editor.commands.pwimage.exec();
}
});
// If the "menu" plugin is loaded, register the menu items.
if ( editor.addMenuItems ) {
editor.addMenuItems({
image: {
label: editor.lang.image.menu,
command: 'pwimage',
group: 'image'
}
});
}
// If the "contextmenu" plugin is loaded, register the listeners.
if ( editor.contextMenu ) {
editor.contextMenu.addListener( function( element, selection ) {
if ( getSelectedImage( editor, element ) )
return { image: CKEDITOR.TRISTATE_OFF };
});
}
}
});
function getSelectedImage( editor, element ) {
if ( !element ) {
var sel = editor.getSelection();
element = sel.getSelectedElement();
}
if ( element && element.is( 'img' ) && !element.data( 'cke-realelement' ) && !element.isReadOnly() )
return element;
}
function loadIframeImagePicker(editor) {
var $in = jQuery("#Inputfield_id");
var page_id;
if($in.length) {
page_id = $in.val();
} else {
page_id = jQuery("#" + editor.name).closest('.Inputfield').attr('data-pid');
}
var edit_page_id = page_id;
var file = '';
var imgClass = '';
var imgWidth = 0;
var imgHeight = 0;
var imgDescription = '';
var imgLink = '';
var hidpi = false;
var selection = editor.getSelection();
var se = selection.getSelectedElement();
var node = selection.getStartElement();
var $node = jQuery(node);
var nodeParent = node.getParent();
var nodeGrandparent = nodeParent.getParent();
var src = $node.attr('src');
var $linkWrapper = null; // if img is wrapped in link, this is it
var $figureWrapper = null;
var $figureCaption = null;
var nodeParentName = nodeParent.$.nodeName.toUpperCase();
var nodeGrandparentName = nodeGrandparent ? nodeGrandparent.$.nodeName.toUpperCase() : '';
var figureNodeSafari = null;
var $repeaterItem = jQuery("#" + editor.name).closest('.InputfieldRepeaterItem');
if(selection.getType() == CKEDITOR.SELECTION_TEXT) {
// Safari doesnt support independent selection of figure elements without display:block,
// so restart selection after changing display property of <figure> to block which then
// makes it selectable in Safari
if(nodeParentName == 'FIGURE') {
figureNodeSafari = nodeParent;
} else if(nodeGrandparentName == 'FIGURE') {
figureNodeSafari = nodeGrandparent;
}
if(figureNodeSafari) {
selection.reset();
selection.removeAllRanges();
figureNodeSafari.$.style.display = 'block';
selection.selectElement(figureNodeSafari);
}
}
if($repeaterItem.length && $repeaterItem.find('.InputfieldImage').length) {
var dataPageAttr = $repeaterItem.attr('data-page');
if(typeof dataPageAttr !== 'undefined') page_id = parseInt(dataPageAttr);
}
/*
// pwAssetPageID for potential future use
else if(typeof ckeGetProcessWireConfig != "undefined") {
// note: ckeGetProcessWireConfig not yet present in front-end editor
var pwCkeSettings = ckeGetProcessWireConfig(editor);
if(pwCkeSettings && pwCkeSettings['pwAssetPageID']) page_id = pwCkeSettings['pwAssetPageID'];
}
*/
selection.lock();
editor.lockSelection();
if(nodeGrandparentName == 'FIGURE') {
$figureWrapper = jQuery(nodeGrandparent.getOuterHtml());
$figureCaption = $figureWrapper.find("figcaption");
$figureWrapper.find('img').remove();
} else if(nodeParentName == 'FIGURE') {
$figureWrapper = jQuery(nodeParent.getOuterHtml());
$figureCaption = $figureWrapper.find("figcaption");
$figureWrapper.find('img').remove();
}
if(nodeParentName === 'A') {
$linkWrapper = jQuery(nodeParent.getOuterHtml());
$linkWrapper.find('img').remove();
}
if(src) {
imgClass = $figureWrapper ? $figureWrapper.attr('class') : $node.attr('class');
hidpi = imgClass && imgClass.indexOf('hidpi') > -1;
imgWidth = $node.attr('width');
imgHeight = $node.attr('height');
imgDescription = $node.attr('alt');
imgLink = nodeParentName === "A" ? nodeParent.$.href : '';
var parts = src.split('/');
file = parts.pop();
parts = parts.reverse();
page_id = '';
// pull page_id out of img[src]
for(var n = 0; n < parts.length; n++) {
// accounts for either /1/2/3/ or /123/ format
if(parts[n].match(/^\d+$/)) {
page_id = parts[n] + page_id;
} else if(page_id.length) {
break;
}
}
page_id = parseInt(page_id);
}
var modalUri = ProcessWire.config.urls.admin + 'page/image/';
var queryString = '?id=' + page_id + '&edit_page_id=' + edit_page_id + '&modal=1';
if(file.length) queryString += "&file=" + file;
if(imgWidth) queryString += "&width=" + imgWidth;
if(imgHeight) queryString += "&height=" + imgHeight;
if(imgClass && imgClass.length) queryString += "&class=" + encodeURIComponent(imgClass);
queryString += '&hidpi=' + (hidpi ? '1' : '0');
if(imgDescription && imgDescription.length) {
queryString += "&description=" + encodeURIComponent(imgDescription);
}
if($figureCaption) queryString += "&caption=1";
if(imgLink && imgLink.length) queryString += "&link=" + encodeURIComponent(imgLink);
queryString += ("&winwidth=" + (jQuery(window).width() - 30));
// create iframe dialog box
var modalSettings = {
title: "<i class='fa fa-fw fa-folder-open'></i> " + ProcessWire.config.InputfieldCKEditor.pwimage.selectLabel, // "Select Image",
open: function() {
if(jQuery(".cke_maximized").length > 0) {
// the following is required when CKE is maximized to make sure dialog is on top of it
jQuery('.ui-dialog').css('z-index', 9999);
jQuery('.ui-widget-overlay').css('z-index', 9998);
}
}
};
var $iframe = pwModalWindow(modalUri + queryString, modalSettings, 'large');
$iframe.on('load', function() {
// when iframe loads, pull the contents into $i
var $i = $iframe.contents();
var buttons;
if($i.find("#selected_image").length > 0) {
// if there is a #selected_image element on the page...
buttons = [
{
html: "<i class='fa fa-camera'></i> " + ProcessWire.config.InputfieldCKEditor.pwimage.insertBtn, // "Insert This Image",
click: function() {
function insertImage(src) {
var $i = $iframe.contents();
var $img = jQuery("#selected_image", $i);
var width = $img.attr('width');
var height = $img.attr('height');
var alt = jQuery("#selected_image_description", $i).val();
var caption = jQuery("#selected_image_caption", $i).is(":checked") ? true : false;
var hidpi = jQuery("#selected_image_hidpi", $i).is(":checked") ? true : false;
var cls = $img.removeClass('ui-resizable No Alignment resizable_setup')
.removeClass('rotate90 rotate180 rotate270 rotate-90 rotate-180 rotate-270')
.removeClass('flip_vertical flip_horizontal').attr('class');
var $linkToLarger = jQuery('#selected_image_link', $i);
var link = $linkToLarger.is(":checked") ? $linkToLarger.val() : ''; // link to larger version
var $insertHTML = jQuery("<img />").attr('src', src).attr('alt', alt);
if(hidpi) cls += (cls.length > 0 ? ' ' : '') + 'hidpi';
// note: class is added to figureWrapper (rather than <img>) when this is a caption
if(caption === false) $insertHTML.addClass(cls);
if(width > 0 && $img.attr('data-nosize') != '1') $insertHTML.attr('width', width);
if($linkWrapper) {
// img was wrapped in an <a>...</a> and/or <figure>
if(link && link.length > 0) {
$linkWrapper.attr('href', link).attr('data-cke-saved-href', link); // populate existing link with new href
} else if($linkToLarger.attr('data-was-checked') == 1) {
// box was checked but no longer is
$linkWrapper = null;
}
if($linkWrapper !== null) {
$linkWrapper.append($insertHTML);
$insertHTML = $linkWrapper;
}
} else if(link && link.length > 0) {
var $a = jQuery("<a />").attr('href', link).append($insertHTML);
$insertHTML = $a;
}
if(caption) {
var $figure = jQuery("<figure />");
//$figure.css('width', width + 'px');
if(cls.length) $figure.addClass(cls);
if(!$figureCaption) {
$figureCaption = jQuery("<figcaption />");
if(alt.length > 1) {
$figureCaption.append(alt);
} else {
$figureCaption.append(ProcessWire.config.InputfieldCKEditor.pwimage.captionLabel);
}
}
if($figureCaption) $figure.append($figureCaption);
$figure.prepend($insertHTML);
$insertHTML = $figure;
}
// select the entire element surrounding the image so that we replace it all
if(nodeGrandparentName === 'FIGURE') {
editor.unlockSelection();
selection.unlock();
selection.selectElement(nodeGrandparent);
} else if(nodeParentName === "A" || nodeParentName == 'FIGURE') {
editor.unlockSelection();
selection.unlock();
// @todo does not work in inline mode for some reason
selection.selectElement(nodeParent);
}
var html = $insertHTML[0].outerHTML;
if(figureNodeSafari) figureNodeSafari.remove(); // Safari inserts an extra <figure>, so remove the original
editor.insertHtml(html);
editor.fire('change');
$iframe.dialog("close");
}
/*** INSERT BUTTON CLICKED *********************************/
var $i = $iframe.contents();
var $img = jQuery("#selected_image", $i);
$iframe.dialog("disable");
$iframe.setTitle(ProcessWire.config.InputfieldCKEditor.pwimage.savingNote); // Saving Image
$img.removeClass("resized");
var width = $img.attr('width');
if(!width) width = $img.width();
var height = $img.attr('height');
if(!height) height = $img.height();
var file = $img.attr('src');
var page_id = jQuery("#page_id", $i).val();
var hidpi = jQuery("#selected_image_hidpi", $i).is(":checked") ? 1 : 0;
var rotate = parseInt(jQuery("#selected_image_rotate", $i).val());
file = file.substring(file.lastIndexOf('/')+1);
var resizeURL = modalUri + 'resize?id=' + page_id +
'&file=' + file +
'&width=' + width +
'&height=' + height +
'&hidpi=' + hidpi;
if(rotate) resizeURL += '&rotate=' + rotate;
if($img.hasClass('flip_horizontal')) resizeURL += '&flip=h';
else if($img.hasClass('flip_vertical')) resizeURL += '&flip=v';
jQuery.get(resizeURL, function(data) {
var $div = jQuery("<div></div>").html(data);
var src = $div.find('#selected_image').attr('src');
insertImage(src);
});
}
}, {
html: "<i class='fa fa-folder-open'></i> " + ProcessWire.config.InputfieldCKEditor.pwimage.selectBtn, // "Select Another Image",
'class': 'ui-priority-secondary',
click: function() {
var $i = $iframe.contents();
var page_id = jQuery("#page_id", $i).val();
$iframe.attr('src', modalUri + '?id=' + page_id + '&modal=1');
$iframe.setButtons({});
}
}, {
html: "<i class='fa fa-times-circle'></i> " + ProcessWire.config.InputfieldCKEditor.pwimage.cancelBtn, // "Cancel",
'class': 'ui-priority-secondary',
click: function() { $iframe.dialog("close"); }
}
];
$iframe.setButtons(buttons);
$iframe.setTitle($i.find('title').html());
} else {
buttons = [];
jQuery("button.pw-modal-button, button[type=submit]:visible", $i).each(function() {
var $button = jQuery(this);
var button = {
html: $button.html(),
click: function() {
$button.trigger('click');
}
}
buttons.push(button);
if(!$button.hasClass('pw-modal-button-visible')) $button.hide();
});
var cancelButton = {
html: "<i class='fa fa-times-circle'></i> " + ProcessWire.config.InputfieldCKEditor.pwimage.cancelBtn, // "Cancel",
'class': "ui-priority-secondary",
click: function() { $iframe.dialog("close"); }
};
buttons.push(cancelButton);
$iframe.setButtons(buttons);
}
});
}
})();