Customising RTE Plugin for uploadasset | Community
Skip to main content
Level 3
Apr 12, 2023 3:43 PM UTC
Solved

Customising RTE Plugin for uploadasset

Dear All,

 

I am customizing RTE plugin  by following blog https://aemlab.blogspot.com/2019/07/aem-rte-custom-plugins-1.html for upload asset and facing below two issues.

 

1) My upload ICON should come as below highlighted in yellow but it is not coming.

 

 

I have written below JavaScript and added below node in RTE plugins as below.

 

************ BELOW JAVASCRIPT *************

 

(function ($, $document) { console.log("inside asset upload"); var EAEM_PLUGIN_ID = "assetuploadButton", EAEM_ASSETUPLOAD_FEATURE = "assetUploadButton", EAEM_ASSETUPLOAD_ICON = EAEM_PLUGIN_ID + "#" + EAEM_ASSETUPLOAD_FEATURE, BUTTON_FORM_URL = "/apps/cfm-rte-plugins/rte-assetUpload-form.html", SENDER = "experience-aem-button", REQUESTER = "requester", $eaemButtonFormModal; var url = document.location.pathname; console.log("EAEM_ASSETUPLOAD_ICON ==== " + EAEM_ASSETUPLOAD_ICON); var assetUploadPath; var SUPPORTED_TYPES = [ { "type": "image", "mimeTypeDetector": function (mimeType) { if (CUI.rte.Common.strStartsWith(mimeType, "image/")) { return true; } return false; }, createHTML: function (path) { return "<img src=\"" + encodeURI(path) + "\">"; } }, { "type": "video", "mimeTypeDetector": function (mimeType) { if (CUI.rte.Common.strStartsWith(mimeType, "video/")) { return true; } return false; }, createHTML: function (path) { return "<video src=\"" + path + "\" controls=\"controls\"></video>"; } } ]; if (url.indexOf("/editor.html") == 0) { extendButtonPlugin(); registerPlugin(); } else if (url.indexOf(BUTTON_FORM_URL) == 0) { handleForm(); } function handleForm() { $document.on("foundation-contentloaded", fillDefaultValues); setTimeout(function () { $('a[data-foundation-wizard-control-action="cancel"]').click(sendCancelMessage); $('button[data-foundation-wizard-control-action="next"]').hide(); validateForm(); }, 100); } function replaceLastString(str) { var myArr = str.split("/"); var lastIndex = str.lastIndexOf("/"); str = str.slice(0, lastIndex); return str; } function initSelectBehavior($form) { $(window.document).unbind("foundation-validation-valid"); $(window.document).unbind("foundation-validation"); var $form = $("coral-panel"); $form.addClass("coral-Form coral-Form--vertical foundation-layout-util-maximized-container"); $form.find('button[data-foundation-wizard-control-action="next"]').prop('disabled', true); var $buttonSelect = $form.find('coral-select[name="button_select"]'); $buttonSelect[0].addEventListener('change', function (event) { validateForm(); }); assetUploadPath = getParent().location.pathname.replace("/editor.html", "").replace(getcontentFragmentType(), "assets/images"); assetUploadPath = replaceLastString(assetUploadPath); var $altTextInput = $form.find('input[name="altText"]'); $altTextInput.on('change', validateForm); var $assetNameInput = $form.find('input[name="assetName"]'); $assetNameInput.on("change", function (event) { if (validateAssetName(this.value)) { addOrReplaceInCustomPatameter(document.querySelector('coral-fileupload[name="file"]')._uploadQueue[0], "fileName", this.value); } validateForm(); }); var $rteAssetUpload = $('coral-fileupload[name="file"]'); $rteAssetUpload.attr('action', assetUploadPath + '.createasset.html'); $assetNameInput.parent().appendTo($rteAssetUpload); $altTextInput.parent().appendTo($rteAssetUpload); var uploadButton = new Coral.Button().set({ label: { innerHTML: "Upload Asset" }, icon: "upload", iconSize: "S", id: 'uploadButton', class: 'coral3-Button coral3-Button--secondary', size: 'S', variant: 'secondary', title: 'Upload Asset', type: 'button' }); $(uploadButton).attr('coral-fileupload-submit', ''); $(uploadButton).appendTo($rteAssetUpload); uploadButton.on('click', function (event){ var loadingDialog = FORM.createLoadingModal(); loadingDialog.show(); }); $rteAssetUpload.width('100%'); $rteAssetUpload.on('coral-fileupload:fileadded', function (event) { //validate/change filename var item = event.detail.item; var isAssetNameValid = validateAssetName(item.file.name); var $assetName = $('input[name="assetName"]'); if (!isAssetNameValid) { $assetName.addClass('is-invalid'); $(uploadButton).prop('disabled', true); } else { $assetName.removeClass('is-invalid'); $(uploadButton).prop('disabled', false); addOrReplaceInCustomPatameter(item, "fileName", item.file.name); } $assetName.val(item.file.name); }); $rteAssetUpload.on('coral-fileupload:load', function (event) { var item = event.detail.item; var altText = $('input[name="altText"]').val(); //alert("altText is : " + altText); if (item.status === 200) { var assetPath = assetUploadPath + '/' + item.name; $.ajax({ type: 'GET', url: '/bin/updateproperty', data: { assetpath: assetPath, AltText: altText }, dataType: 'json', success: function (data) { console.log("success"); } }); var message = { sender: SENDER, action: "submit", data: {} }; message.assetPath = assetPath; parent.postMessage(JSON.stringify(message), "*"); } if (item._xhr.statusText !== "OK") { var errorDialog = document.querySelector('#uploadErrorDialog'); loadingDialog.hide(); errorDialog.show(); } }); $rteAssetUpload.parent().hide(); function addOrReplaceInCustomPatameter(item, name, value) { item.parameters = item.parameters ? item.parameters : []; var isPresent = false; item.parameters.forEach(function (itm) { isPresent = true; if (itm.name === name) { itm.value = value; } }); if (!isPresent) { item.parameters.push({ name: name, value: value }); } // Specific handling for file name. As file object also contains name if (name === "fileName") { item.name = value; } }; } function getcontentFragmentType() { return getParent().location.pathname.split("/")[6]; } function validateForm() { $assetName = $('input[name="assetName"]'); var isAssetNameValid = validateAssetName($assetName.val()); $rteAssetUpload = $('coral-fileupload[name="file"]'); if (!isAssetNameValid) { $assetName.addClass('is-invalid'); $('#uploadButton').prop('disabled', true); } else { $assetName.removeClass('is-invalid'); $('#uploadButton').prop('disabled', false); addOrReplaceInCustomPatameter($rteAssetUpload, "fileName", $assetName.val()); } $buttonSelect = $('coral-select[name="button_select"]'); if ($buttonSelect[0].selectedItem.value !== '') { $buttonSelect.prop('invalid', false); $rteAssetUpload.parent().show(); setTimeout(function () { $buttonSelect.prop('invalid', false); }); if ($buttonSelect[0].selectedItem.value === 'Image') { $('input[name="altText"]').parent().show(); $rteAssetUpload.attr('accept', 'image/*'); assetUploadPath = getParent().location.pathname.replace("/editor.html", "").replace(getcontentFragmentType(), "assets/images"); assetUploadPath = replaceLastString(assetUploadPath); $rteAssetUpload.attr('action', assetUploadPath + '.createasset.html'); } else { $rteAssetUpload.attr('accept', 'video/*'); $('input[name="altText"]').val(''); $('input[name="altText"]').parent().hide(); assetUploadPath = getParent().location.pathname.replace("/editor.html", "").replace(getcontentFragmentType(), "assets/videos"); assetUploadPath = replaceLastString(assetUploadPath); $rteAssetUpload.attr('action', assetUploadPath + '.createasset.html'); } } else { setTimeout(function () { $buttonSelect.prop('invalid', true); }); $rteAssetUpload.parent().hide(); $buttonSelect.prop('invalid', true); $('#uploadButton').prop('disabled', true); } } function addOrReplaceInCustomPatameter(item, name, value) { item.parameters = item.parameters ? item.parameters : []; var isPresent = false; item.parameters.forEach(function (itm) { isPresent = true; if (itm.name === name) { itm.value = value; } }); if (!isPresent) { item.parameters.push({ name: name, value: value }); } // Specific handling for file name. As file object also contains name if (name === "fileName") { item.name = value; } } function validateAssetName(assetName) { var illegalCharacters = ["*", "/", ":", "[", "\\", "]", "|", "#", "%", "{", "}", "?", "`", "‘", "’", "'", "!", "$", "<", ">", "~", "@", "&", "^", "+", "=", ",", "é", "à", "è", "ù", "â", "ê", "î", "ô", "û", "ä", "ë", "ü", "ç", "ó", "ï", "Ç", "œ", "«", "»", ";", "æ", "€", "—", "–", "À", "Â", "Ä", "Æ", "Ç", "È", "É", "Ê", "Ë", "Î", "Ï", "Ô", "Œ", "Ù", "Û", "Ü", " "]; var pattern = /\.[0-9a-z]{3,4}$/i; if (typeof assetName === "string") { if (contains(assetName, illegalCharacters) || !assetName.match(pattern)) { return false; } else { return true; } } } function contains(str, chars) { for (var i = 0; i < chars.length; i++) { if (str.indexOf(chars[i]) > -1) { return true; } } return false; } function fillDefaultValues() { var $form = $("coral-panel"), form = $("form")[0]; initSelectBehavior($form); } function sendCancelMessage() { var message = { sender: SENDER, action: "cancel" }; getParent().postMessage(JSON.stringify(message), "*"); } function getParent() { if (window.opener) { return window.opener; } return parent; } function closePicker(event) { event = event.originalEvent || {}; if (_.isEmpty(event.data)) { return; } var message, action; try { message = JSON.parse(event.data); } catch (err) { return; } if (!message || message.sender !== SENDER) { return; } action = message.action; if (action === "submit") { if (message.assetPath !== undefined) { getData(message.assetPath, function (assetToInsert) { // create HTML and insert it if (assetToInsert) { var assetPath = assetToInsert.path; var type = assetToInsert.type; var html = type.createHTML(assetPath); $eaemButtonFormModal.eaemButtonPlugin.editorKernel.execCmd("insertprocessed", html); } else { // TODO error handling? } if ($eaemButtonFormModal) { var modal = $eaemButtonFormModal.data('modal'); modal.hide(); modal.$element.remove(); } var uploadAssetSuccessDialog = new Coral.Dialog().set({ id: "uploadAssetSuccessDialog", header: { innerHTML: Granite.I18n.get('Asset Uploaded') }, backdrop: Coral.Dialog.backdrop.STATIC, content: { innerHTML: `Your asset is saved at ${assetPath || message.assetPath}` }, footer: { innerHTML: "<button is=\"coral-button\" variant=\"primary\" coral-close=\"\" class=\"coral3-Button coral3-Button--primary\" size=\"M\"><coral-button-label>Ok</coral-button-label></button>" }, variant: "success" }); var loadingDialog = FORM.createLoadingModal(); loadingDialog.hide(); uploadAssetSuccessDialog.show(); }); } } if (action === "cancel") { if ($eaemButtonFormModal) { var modal = $eaemButtonFormModal.data('modal'); modal.hide(); modal.$element.remove(); } } } function getMetaData(data) { var metaData = undefined; if (data.hasOwnProperty("jcr:content")) { metaData = data["jcr:content"]["metadata"]; } return metaData; } function getAssetTypeFromMimeType(mimeType) { if (!mimeType) { return undefined; } for (var t = 0; t < SUPPORTED_TYPES.length; t++) { var type = SUPPORTED_TYPES[t]; if (type.mimeTypeDetector(mimeType)) { return type; } } return undefined; } function getData(path, callback) { $.ajax(path + ".2.json", { success: function (data) { var assetData = undefined; if (data) { if (data["jcr:primaryType"] === "dam:Asset") { var metaData = getMetaData(data); if (metaData) { var mimeType = metaData["dam:MIMEtype"] || metaData["dc:format"]; var assetType = getAssetTypeFromMimeType(mimeType); if (assetType) { assetData = { "type": assetType, "path": path, "metaData": metaData }; } } } } if (callback) { callback(assetData); } }, error: function () { if (callback) { callback(undefined); } } }); } function extendButtonPlugin() { var origFn = Dam.CFM.StyledTextEditor.prototype._start; Dam.CFM.StyledTextEditor.prototype._start = function () { addRTEPluginSettings(this); origFn.call(this); } } function addRTEPluginSettings(editor) { var config = editor.$editable.data("config"); config.rtePlugins[EAEM_PLUGIN_ID] = { features: "*" }; config.uiSettings.cui.multieditorFullscreen.toolbar.push(EAEM_ASSETUPLOAD_ICON); } function registerPlugin() { var EAEM_CFM_ASSETUPLOAD_PLUGIN = new Class({ toString: "eaemCFMUploadPlugin", extend: CUI.rte.plugins.Plugin, buttonFormUI: null, getFeatures: function () { return [EAEM_ASSETUPLOAD_FEATURE]; }, notifyPluginConfig: function (pluginConfig) { var defaults = { tooltips: {} }; defaults.tooltips[EAEM_ASSETUPLOAD_FEATURE] = { title: "Upload Asset from your desktop..." }; CUI.rte.Utils.applyDefaults(pluginConfig, defaults); this.config = pluginConfig; }, initializeUI: function (tbGenerator) { if (!this.isFeatureEnabled(EAEM_ASSETUPLOAD_FEATURE)) { return; } this.buttonFormUI = new tbGenerator.createElement(EAEM_ASSETUPLOAD_FEATURE, this, false, this.config.tooltips[EAEM_ASSETUPLOAD_FEATURE]); tbGenerator.addElement(EAEM_ASSETUPLOAD_FEATURE, 999, this.buttonFormUI, 999); if (tbGenerator.registerIcon) { tbGenerator.registerIcon(EAEM_ASSETUPLOAD_ICON, "upload"); } $(window).off('message', closePicker).on('message', closePicker); }, isValidSelection: function () { var winSel = window.getSelection(); return winSel && winSel.rangeCount == 1 && winSel.getRangeAt(0).toString().length > 0; }, execute: function (pluginCommand, value, envOptions) { var context = envOptions.editContext; if (pluginCommand != EAEM_ASSETUPLOAD_FEATURE) { return; } var selection = CUI.rte.Selection.createProcessingSelection(context), ek = this.editorKernel, startNode = selection.startNode; var winSel = window.getSelection(); if (winSel && winSel.rangeCount == 1 && winSel.getRangeAt(0).toString().length == 0 && ($(window.getSelection().baseNode).prop('tagName') !== 'A' && $(window.getSelection().baseNode).parent().prop("tagName") !== 'A')) { if ((selection.startOffset === startNode.length) && (startNode != selection.endNode)) { startNode = startNode.nextSibling; } this.showModal(this.getButtonFormFrameUrl()); } }, showModal: function (url) { var self = this, $iframe = $('<iframe id="rteAssetUploadFrame">'), $modal = $('<div>').addClass('eaem-cfm-font-size-rte coral-Modal'); $iframe.attr('src', url).appendTo($modal); $modal.appendTo('body').modal({ type: 'default', buttons: [], visible: true }); $eaemButtonFormModal = $modal; $eaemButtonFormModal.eaemButtonPlugin = self; $modal.nextAll(".coral-Modal-backdrop").addClass("cfm-coral2-backdrop-rte"); }, getButtonFormFrameUrl: function () { return Granite.HTTP.externalize(BUTTON_FORM_URL) + "?" + REQUESTER + "=" + SENDER; }, updateState: function (selDef) { var hasUC = this.editorKernel.queryState(EAEM_ASSETUPLOAD_FEATURE, selDef); if (this.buttonFormUI != null && this.buttonFormUI.$ui != null) { var winSel = window.getSelection(), isTextSelected = winSel && winSel.rangeCount == 1 && winSel.getRangeAt(0).toString().length == 0 && ($(window.getSelection().baseNode).prop('tagName') !== 'A' && $(window.getSelection().baseNode).parent().prop("tagName") !== 'A'); isTextSelected ? this.buttonFormUI.$ui.removeClass('is-disabled') : this.buttonFormUI.$ui.addClass('is-disabled'); this.buttonFormUI.setSelected(isTextSelected); } } }); CUI.rte.plugins.PluginRegistry.register(EAEM_PLUGIN_ID, EAEM_CFM_ASSETUPLOAD_PLUGIN); } }(jQuery, jQuery(document)));

 

and I have added below highlighted in yellow in RTE Plugins

 

 

and then I have added assetupload#assetUploadButton  in both inline and dialogFullscreen under UIsettings , as shown below.

 

 

But after adding all upload asset ICON is coming blank , as shown below

 

 

2) The second issue is that I am getting below error in my console for dam is not defined for button plugin as shown below.

 

 

 

function extendButtonPlugin() {
var origFn = Dam.CFM.StyledTextEditor.prototype._start;

 

Can anybody please help me here.

 

 

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
AsifChowdhury
AsifChowdhuryAccepted solution
New Participant
Apr 13, 2023 10:31 AM UTC

It seems the problem is in your code. Maybe the "selection" is getting null so that "startNode" is not going to be read as a property. Please do some debugging in your code. I hope you will find the problem asap.

 

Thanks.

3 replies

AsifChowdhury
New Participant
Apr 13, 2023 8:27 AM UTC

Hello @subnaik, 

If everything is ok that means you have registered the icon properly and added "assetupload#assetUploadButton" properly you can check this thing for you "icon" not showing issue

You may have a category for your custom RTE plugin

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="cq:ClientLibraryFolder" allowProxy="{Boolean}true" categories="[your.custom.rte-upload-plugin]"/>

You need to add this category into your "Text" component's dialog by extraClientlib

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured" extraClientlibs="[your.custom.rte-upload-plugin]">

 

Translate
subnaikAuthor
Level 3
Apr 13, 2023 10:07 AM UTC

@asifchowdhury  Thanks for your reply.

 

Now my icon is coming fine after I add below in category but my function is not working properly and upload asset is going to back , as shown below

 

 

 

Upload Asset is coming as below.

 

 

and getting below error in console for js.

 

 

var selection = CUI.rte.Selection.createProcessingSelection(context),
ek = this.editorKernel, startNode = selection.startNode;

 

Also can we call upload asset (dam library) under RTE Plugin in AEM 6.5 ?

Translate
AsifChowdhury
AsifChowdhuryAccepted solution
New Participant
Apr 13, 2023 10:31 AM UTC

It seems the problem is in your code. Maybe the "selection" is getting null so that "startNode" is not going to be read as a property. Please do some debugging in your code. I hope you will find the problem asap.

 

Thanks.

Translate