(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 doesn’t support independent selection of figure elements without display:block, // so restart selection after changing display property of
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: " " + 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: " " + 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("").attr('src', src).attr('alt', alt); if(hidpi) cls += (cls.length > 0 ? ' ' : '') + 'hidpi'; // note: class is added to figureWrapper (rather than ) 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 ... and/or
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("").attr('href', link).append($insertHTML); $insertHTML = $a; } if(caption) { var $figure = jQuery("
"); //$figure.css('width', width + 'px'); if(cls.length) $figure.addClass(cls); if(!$figureCaption) { $figureCaption = jQuery("
"); 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
, 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("
").html(data); var src = $div.find('#selected_image').attr('src'); insertImage(src); }); } }, { html: " " + 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: " " + 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: " " + ProcessWire.config.InputfieldCKEditor.pwimage.cancelBtn, // "Cancel", 'class': "ui-priority-secondary", click: function() { $iframe.dialog("close"); } }; buttons.push(cancelButton); $iframe.setButtons(buttons); } }); } })();