Do not allow multiple custom formats Tinymce - tinymce

When playing around in the online editor at this url: https://www.tiny.cloud/docs/demo/format-custom/ it is quite possible to apply multiple custom formats.
I would claim multiple custom formats is the default behaviour, however we have a request to change this. Is it even possible to configure Tinymce to allow only one custom format at a time? Given the screenshot example, let's say it's not allowed to combine "red header" with "bold text"?

This isn't really Episerver-specific, but rather about TinyMCE.
There are examples of people creating a custom format button which only allows one (1) format to be selected: https://codepen.io/thibbiuf/pen/JKBkXy?editors=1000
You could create your own TinyMCE plugin and then add it to the editor in Episerver:
[ModuleDependency(typeof(TinyMceInitialization))]
public class ExtendedTinyMceInitialization : IConfigurableModule
{
public void Initialize(InitializationEngine context)
{
}
public void Uninitialize(InitializationEngine context)
{
}
public void ConfigureContainer(ServiceConfigurationContext context)
{
context.Services.Configure<TinyMceConfiguration>(config =>
{
config.Default()
.AddPlugin("custom_styleselect")
.AppendToolbar("custom_styleselect");
});
}
}
There are multiple ways to add a TinyMCE plugin, but one way is to load a custom script file when TinyMCE loads in Episerver by adding something like the following to module.config:
<?xml version="1.0" encoding="utf-8"?>
<module name="Your.Website" >
<clientResources>
<add name="epi-addon-tinymce.main" path="ClientResources/tinymce/custom_styleselect/Plugin.js" resourceType="Script" />
</clientResources>
</module>

Related

How to use a method with SafeHtml param instead of String in UiBinder (XML)?

We're migrating our application from GXT 3 to GXT 4 (and also from GWT 2.5 to 2.8.2) and one of the things that changed is that lot of components' body/text/heading/etc. now have two separate setters. One accepts String param and the other one accepts SafeHtml.
Here's an example:
public void setToolTip(SafeHtml html) {
...
}
public void setToolTip(String text) {
...
}
The difference in those is that the method accepting String does not render html elements. The other one, however, does, which is perfectly fine if one uses Java code to build UI.
Unfortunately, we do have a lot of our UI built using GWT's XML method and I would like it to stay this way.
The problem is that I cannot figure out how to show e.g. a tooltip with SafeHtml body. When I try to do that I get compilation errors.
This is what I put in my XML file:
...
<form:TextArea ui:field="testField" toolTip="{messages.testMesssage}" >
...
And this is the error:
[ERROR] java.lang.String required, but {testMess.test} returns com.google.gwt.safehtml.shared.SafeHtml: <form:TextArea toolTip='{messages.testMesssage}' ui:field='testField'> (:184)
Thanks!
You may want to look at the GXT examples for tooltips in UiBinder. In there, it shows using the ToolTipConfig instead of trying to set "tooltip" directly.
<ui:with type="com.sencha.gxt.widget.core.client.tips.ToolTipConfig"
field="toolTipConfig">
<ui:attributes title="Information" body="Prints the current document" />
</ui:with>
...
<form:TextArea ui:field="testField" toolTipConfig="{toolTipConfig}" />

How do I not include scripts and clientlibs in an experience fragment when exporting to Adobe Target?

I'm trying to build an experience fragment (XF) template in AEM 6.5. We have some custom clientlibs that I want to include when designers are authoring the experience fragment but I don't want to include when the experience fragment is injected via Adobe Target as the clientlibs will already be included on the base page template.
I want the clientlibs on the XF template so components render properly while designing. I've tried building a new page component based on /libs/cq/experience-fragments/components/xfpage and then checking the runmode for author or publish and using the result of that in a data-sly-test to conditionally include them. But I think because the Export to Target option happens on Author, it's including the scripts in the html output when it's exported to Target.
How do I conditionally include clientlibs during authoring of an XF, but not include them when the experience fragment is exported to target and added to a page from there?
There are couple of things you need to do in order to achieve this.
AEM offers the Link Rewriter Provider Interface. This is a ConsumerType interface that you can implement in your bundles, as a service.
It bypasses the modifications AEM performs on internal links of an HTML offer as rendered from an Experience Fragment. This interface allows you to customize the process of rewriting internal HTML links to align with your business needs.
To use the interface you first need to create a bundle containing a new service component that implements the Link Rewriter Provider interface.
This service will be used to plug into the Experience Fragment Export to Target rewriting in order to have access to the various links.
import com.adobe.cq.xf.ExperienceFragmentLinkRewriterProvider;
import com.adobe.cq.xf.ExperienceFragmentVariation;
import org.osgi.service.component.annotations.Service;
import org.osgi.service.component.annotations.Component;
#Component
#Service
public class GeneralLinkRewriter implements ExperienceFragmentLinkRewriterProvider {
#Override
public String rewriteLink(String link, String tag, String attribute) {
return null;
}
#Override
public boolean shouldRewrite(ExperienceFragmentVariation experienceFragment) {
return false;
}
#Override
public int getPriority() {
return 0;
}
}
shouldRewrite
You need to indicate to the system whether it needs to rewrite the links when a call is made for Export to Target on a certain Experience Fragment variation. You do this by implementing the method:
shouldRewrite(ExperienceFragmentVariation experienceFragment);
For example:
#Override
public boolean shouldRewrite(ExperienceFragmentVariation experienceFragment) {
return experienceFragment.getPath().equals("/content/experience-fragment/master");
}
This method receives, as a parameter, the Experience Fragment Variation that the Export to Target system is currently rewriting.
In the example above, we would like to rewrite:
links present in src
href attributes only
for a specific Experience Fragment:
/content/experience-fragment/
Any other Experience Fragments that pass through the Export to Target system are ignored and not affected by changes implemented in this Service.
rewriteLink
For the Experience Fragment variation impacted by the rewriting process, it will then proceed to let the service handle the link rewriting. Everytime a link is encountered in the internal HTML, the following method is invoked:
rewriteLink(String link, String tag, String attribute)
As input, the method receives the parameters:
link
The String representation of the link that is currently being processed. This is usually a relative URL pointing to the resource on the author instance.
tag
The name of the HTML element that is currently being processed.
attribute
The exact attribute name.
If, for example, the Export to Target system is currently processing this element, you can define CSSInclude as:
<link rel="stylesheet" href="/etc.clientlibs/foundation/clientlibs/main.css" type="text/css">
The call to the rewriteLink() method is done using these parameters:
rewriteLink(link="/etc.clientlibs/foundation/clientlibs/main.css", tag="link", attribute="href" )
When you create the service you can make decisions based on the given input, and then rewrite the link accordingly.

Add source button to Magnolia CMS richText control

I need to enable source button on my richText control ( I have to put there HTML code ) and I have follow this tutorial:
https://documentation.magnolia-cms.com/display/DOCS/Rich+text
So I have added following settings source - true - Boolean in standard-templating-kit/dialogs/generic/controls/text but it doesn't work for me.
I'm using Magnolia CMS 5.2.4. Can anybody please tell me how I can turn on this button or maybe if there is another control to put there html code ?
Best Regards
Jan
Have you defined your dialogs using Blossom? If so, they are completely distinct from the STK dialogs. If you have something like the following example, you will need to change your code to set up the rich text area with a source button.
#TabFactory("heading")
public void headingTab(UiConfig cfg, TabBuilder tab) {
FieldConfig fields = cfg.fields;
tab.fields(
fields.text("headingtitle").i18n().required(),
fields.richText("headingtext").i18n().required()
);
}
The above example would be modified by defining the rich text field and then modifying the definition.
#TabFactory("heading")
public void headingTab(UiConfig cfg, TabBuilder tab) {
FieldConfig fields = cfg.fields;
RichTextFieldBuilder richText = fields.richText("headingtext").i18n().required();
richText.definition().setSource(true);
tab.fields(
fields.text("headingtitle").i18n().required(),
richText
);
}

How to create custom image decorator in java file using eclipse plugin

I would like to use some decorators in my Eclipse plugin. I have created a plugin where I created my own editor for my own .test file. If the user edits .test file and saves it. The file must show some decorations not only the .test file but also the project must show the decorator. I am stuck with this problem I can't find any good tutorial to create decorators.
I Have seen some of the websites like https://www.eclipse.org/articles/Article-Decorators/decorators.html but I couldn't get the exact point.
Will some one please tell me how to create custom decorator for my eclipse plugin.
A ILightweightLabelDecorator is the most common type of decorator
Declare this in your plugin.xml with something like this:
<extension point="org.eclipse.ui.decorators">
<decorator
id="my.decorator.id"
class="my.decorator.Decorator"
label="My Decorator"
state="true"
lightweight="true"
adaptable="true">
<enablement>
<objectClass name="org.eclipse.core.resources.IResource"/>
</enablement>
</decorator>
</extension>
You will have to adjust the enablement to suit what you want.
Your decorator class would be something like:
public class Decorator extends BaseLabelDecorator implements ILightweightLabelDecorator
{
#Override
public void decorate(final Object element, final IDecoration decoration)
{
// TODO call decoration methods to add overlay images or prefix / suffix text
}
}

GWT validation framework, how to specify location of internationalization bundle

This one is related to my previous post. Is it possible in GWT validation framework to specify location of ValidationMessages.properties files and their names? I already have messages translations in my application and I'd prefer them to be in one location.
You could create a custom UserValidationMessagesResolver:
public class CustomValidationMessagesResolver extends AbstractValidationMessageResolver implements UserValidationMessagesResolver {
protected CustomValidationMessagesResolver() {
super((ConstantsWithLookup) GWT.create(ValidationConstants.class));
}
}
In the above code, ValidationConstants is the class resulting from running I18NSync on my properties file.
Then in *.gwt.xml:
<replace-with class="yourpackage.client.validation.CustomValidationMessagesResolver">
<when-type-is class="com.google.gwt.validation.client.UserValidationMessagesResolver" />
</replace-with>
You can find a complete example here.