diff --git a/apps/portlet-documents/src/main/resources/locale/portal/webui_en.properties b/apps/portlet-documents/src/main/resources/locale/portal/webui_en.properties index 9cba3bba486..45bdb513eaa 100644 --- a/apps/portlet-documents/src/main/resources/locale/portal/webui_en.properties +++ b/apps/portlet-documents/src/main/resources/locale/portal/webui_en.properties @@ -44,6 +44,13 @@ CKEditor.image.error.unknownImageFileExtension=Only images of type JPEG, PNG or CKEditor.image.error.imageMaxSizeExceeded=The maximum image size allowed is {0} MB CKEditor.image.MegaByte=MB CKEditor.image.error.uploadingImageError=An error occurred while uploading the image. Please try again. +CKEditor.image.link=Link +CKEditor.image.linkTarget=Open in +CKEditor.image.link.description=Add a link that will open on a click +CKEditor.image.linkTarget.description=Choose where the page opens +CKEditor.image.linkTarget.self=Same tab +CKEditor.image.linkTarget.blank=New tab +CKEditor.image.link.format.error=Incorrect link format ############################################################################# # select from drives ############################################################################# diff --git a/apps/resources-wcm/src/main/webapp/eXoPlugins/selectImage/dialogs/selectImage.js b/apps/resources-wcm/src/main/webapp/eXoPlugins/selectImage/dialogs/selectImage.js index bb80868330a..97da4ee6fb2 100644 --- a/apps/resources-wcm/src/main/webapp/eXoPlugins/selectImage/dialogs/selectImage.js +++ b/apps/resources-wcm/src/main/webapp/eXoPlugins/selectImage/dialogs/selectImage.js @@ -165,11 +165,29 @@ CKEDITOR.dialog.add( 'selectImage', function( editor ) { return; } var dialog = this.getDialog(); + const UrlProtocolRegex = /^(http|ftp|https):\/\/[^ "]+$/; require(["SHARED/jquery"], function($) { var $imageElement = $(dialog.getElement().$).find(".selectedImagePreview img"); + let imageLink = $(dialog.getElement().$).find(".imageLinkArea input").val(); + const imageLinkTarget = $(dialog.getElement().$).find(".imageLinkTargetArea select").find(":selected").val(); widget.setData( 'src', $imageElement.attr("src") ); widget.setData( 'alt', $imageElement.attr("alt") ); - + if (imageLink && !UrlProtocolRegex.test(imageLink)) { + imageLink = 'https://' + imageLink; + } + if (imageLink) { + const url = imageLink.split('://')[1]; + const linkData = { + type: 'url', + url: {url: url, protocol: imageLink.split(url)[0],}, + target: {type: imageLinkTarget}, + } + widget.setData('link', linkData); + widget.setData('href', imageLink); + widget.setData('target', imageLinkTarget); + } else { + widget.setData('link', null); + } if ($imageElement.hasClass("left")) { widget.setData( 'align', 'left' ); } else if ($imageElement.hasClass("right")) { @@ -188,6 +206,6 @@ CKEDITOR.dialog.add( 'selectImage', function( editor ) { require(["SHARED/uiSelectImage"], function(UISelectImage){ UISelectImage.cancel(); }) - } + }, }; } ); diff --git a/apps/resources-wcm/src/main/webapp/eXoPlugins/selectImage/plugin.js b/apps/resources-wcm/src/main/webapp/eXoPlugins/selectImage/plugin.js index 03ab18566cf..d944d283f7d 100644 --- a/apps/resources-wcm/src/main/webapp/eXoPlugins/selectImage/plugin.js +++ b/apps/resources-wcm/src/main/webapp/eXoPlugins/selectImage/plugin.js @@ -7,7 +7,7 @@ ( function() { - var template = '', + var template = '', templateBlock = new CKEDITOR.template( '
' + template + @@ -155,8 +155,9 @@ // non-captioned, block or inline according to what is the // new state of the widget. if ( this.deflated ) { + editor.insertElement( this.element ); this.widget = editor.widgets.initOn( this.element, 'selectImage', this.widget.data ); - + editor.widgets.fire( 'checkWidgets' ) // Once widget was re-created, it may become an inline element without // block wrapper (i.e. when unaligned, end not captioned). Let's do some // sort of autoparagraphing here (http://dev.ckeditor.com/ticket/10853). @@ -179,7 +180,7 @@ // If now widget was destroyed just update wrapper's alignment. // According to the new state. else { - setWrapperAlign( this.widget, alignClasses ); + setWrapperAlign(this.widget, alignClasses); } } @@ -249,6 +250,11 @@ } else { if ( !this.parts.link ) this.parts.link = this.parts.image.getParent(); + + this.parts?.link?.setAttributes({ + href: this.data.href, + target: this.data.target + }); } this.parts.image.setAttributes( { @@ -289,7 +295,6 @@ alt: image.getAttribute( 'alt' ) || '', width: image.getAttribute( 'width' ) || '', height: image.getAttribute( 'height' ) || '', - // Lock ratio is on by default (http://dev.ckeditor.com/ticket/10833). lock: this.ready ? helpers.checkHasNaturalRatio( image ) : true }; @@ -519,7 +524,6 @@ shift.element = imageOrLink; } }, - link: function( shift, oldValue, newValue ) { if ( shift.changed.link ) { var img = shift.element.is( 'img' ) ? @@ -598,7 +602,8 @@ function wrapInLink( img, linkData ) { var link = doc.createElement( 'a', { attributes: { - href: linkData.url + href: linkData?.url, + target: linkData?.target?.type } } ); diff --git a/apps/resources-wcm/src/main/webapp/javascript/eXo/ecm/UISelectImage.js b/apps/resources-wcm/src/main/webapp/javascript/eXo/ecm/UISelectImage.js index e59aca36fdf..1fd1331f8f5 100644 --- a/apps/resources-wcm/src/main/webapp/javascript/eXo/ecm/UISelectImage.js +++ b/apps/resources-wcm/src/main/webapp/javascript/eXo/ecm/UISelectImage.js @@ -1,6 +1,7 @@ (function(UISelectFromDrives, $, base){ var UISelectImage = { urlPattern: new RegExp("(http|ftp|https)://(.*)/(.*)"), + imageLinkUrlPattern: new RegExp("((?:www\\.|(?!www))[a-zA-Z0-9-]+\\.[^\\s]{2,})"), init : function(dialogElement, widgetData, enableOkButtonCallback, disableOkButtonCallback) { this.status = {}; this.$parentDialog = $(dialogElement); @@ -112,6 +113,22 @@ '' + '' + '' + + '' + + '' ); @@ -121,6 +138,9 @@ this.warningMessageCnt = this.$parentDialog.find(".alert"); this.imageURLCnt = this.$parentDialog.find(".imageURLContainer"); this.imageElement = this.imagePreviewCnt.find("img"); + this.imageLink = this.imagePreviewCnt.find("a"); + this.imageLinkOptionsContainer = this.$parentDialog.find(".imageLinkOptions"); + this.linkFormatError = this.$parentDialog.find(".text-error"); this.imageElement.on("load", function (data){ self.showBlock(self.backBtn, false); self.showBlock(self.imageURLCnt, false); @@ -129,6 +149,7 @@ self.showBlock(self.imagePreviewCnt, true); self.showBlock(self.deleteFile, true); self.showBlock(self.altImageContainer, true); + self.showBlock(self.imageLinkOptionsContainer, true); self.enableOKButton(true); self.triggerResizeEvent(); }).on("error", function (data) { @@ -145,6 +166,7 @@ self.showBlock(self.imagePreviewCnt, false); self.showBlock(self.deleteFile, false); self.showBlock(self.altImageContainer, false); + self.showBlock(self.imageLinkOptionsContainer, false); self.displayWarning("${CKEditor.image.error.badURL}"); }); @@ -176,6 +198,7 @@ self.imageURLCnt.find("input").val(""); self.altImageContainer.find("input[type='text']").val(""); self.imageElement.attr("alt", ""); + self.showBlock(self.imageLinkOptionsContainer, false); }); if (base.Browser.isIE()) { $uploadBtn.find("label").attr("for", $input.attr("id")); @@ -249,7 +272,16 @@ self.altValue = self.altImageContainer.find("input[type='text']").val(); self.imageElement.attr("alt", self.altValue); }); - + self.imageLinkOptionsContainer.find("input[type='text']").on("blur, keyup", function (e) { + const linkValue = e.target.value.trim(); + if (linkValue && !self.imageLinkUrlPattern.test(linkValue)) { + self.showBlock(self.linkFormatError, true); + self.enableOKButton(false); + } else { + self.showBlock(self.linkFormatError, false); + self.enableOKButton(true); + } + }); $input.on("change", function() { self.handleFileUpload(this.files, self.$parentDialog); }); @@ -296,6 +328,16 @@ self.altImageContainer.find("input[type='text']").val(""); self.imageElement.attr("alt", ""); } + if (widgetData.link && !widgetData.link.url) { + self.imageLinkOptionsContainer.find("input[type='text']").val(widgetData.link); + } else if (widgetData?.link?.url) { + const linkValue = widgetData.link.url.protocol + widgetData.link.url.url; + self.imageLinkOptionsContainer.find("input[type='text']").val(linkValue); + } + if (widgetData?.link?.target?.type) { + const targetValue = widgetData?.link?.target?.type; + self.imageLinkOptionsContainer.find(".imageLinkTarget").val(targetValue).change(); + } if (widgetData.align == "center") { this.$parentDialog.find(".selectImageAlign .btn-group .btn[data-align=Middle]").trigger("click"); } else if (widgetData.align == "right") {