Add another style without removing the previous (CKEditor 4) - javascript

I've been looking through a lot of documentation and examples, but I haven't found an answer. Here's my problem, I have the following code inside my CKEditor stylesSet:
{name: 'Full Column Photo', element: 'img', attributes: { 'class': 'full-
column' }, childRule: function( element ) {
return !element.is( 'img' );
}},
{ name: 'Disable Image Popup', element: 'img', attributes: { 'class':
'disable-popup' }, childRule: function( element ) {
return !element.is( 'img' );
} },
If I have an element that has the style/class ".full-column" and then add the style/class ".disable-popup" to that same element, '.full-column' gets removed. How can I keep both classes in the element? And how can I remove only the selected style/class if it's already been selected for the element before.
All help greatly appreciated.

In JavaScript you can add a class to an elements existing class list using the classList property. The property exposes the add function which can be used to add a new class name to the list.
You first need to get a reference to the DOM element you wish to manipulate.
const el = document.getElementById('some-element');
Next you can add the class you want to the element
el.classList.add('new-class');
Alternatively if you want to later remove the class you can use the remove function.
el.classList.remove('new-class');
Edit: In light of your comment, would you be able to specify the attributes.class property as a function that returns the object you have. Something like:
{
name: 'Disable Image Popup',
element: 'img',
attributes: {
'class': function() {
element.addClass('disable-popup');
return '';
}
},
childRule: function( element ) {
return !element.is( 'img' );
}
}
Weirdly, I don't think there is a function that will return the CKEDITOR.dom.element classes on the element, only the styles or a hasClass() function.

Related

CKEditor only allow <img> tags with certain attribute

I want CKEditor to allow everything except images tags without a specific data field. e.g. data-test.
I tried what the documentation says. For now not allowing all <img> tags.
But it still accepts all images.
config.allowedContent = {
$1: {
// Use the ability to specify elements as an object.
elements: CKEDITOR.dtd,
attributes: true,
styles: true,
classes: true
}
};
config.disallowedContent = 'img';
With config.disallowedContent = 'img' you are removing whole img element from ACF. Use extraAllowedContent to specify image element.
// Clone CKEDITOR.dtd so we are not modifying CKEditor objects.
var elements = CKEDITOR.tools.object.merge( {}, CKEDITOR.dtd );
delete elements.img;
config.allowedContent: {
$1: {
elements: elements,
attributes: true,
styles: true,
classes: true
}
};
config.extraAllowedContent: 'img[!src,!data-test]';
You can see a working example here: https://codepen.io/jacekbogdanski/pen/gKremp

Use link with image in Javascript

At first I want to say that I'm beginner in Javascript, so I can't edit my function correctly.
For now I have clickable text to remove row, but I want to use image instead of text.
This is part of function:
...
var removeRow = $.fn.optionTest.createColumn($("<a>", options.removeLinkOptions).text('Remove Row'));
row.append(id).append(label).append(from).append(to).append(removeRow);
I can't achieve correct syntax, I've tried something like, but unsuccessfully...
var removeRow = $.fn.optionTest.createColumn($("<a>", options.removeLinkOptions).src("http://linktoimage.com/img.jpg"));
Thank you for understanding and trying to help!
UPDATE
Later I'm using removeRow in following, It have href: 'javascript:;', maybe that's why not working?
$.fn.optionTest.defaults = {
clearOnChange: false,
actionId: '#action',
indexOptions: {
class: 'div-format-test'
},
rowOptions: {
id: 'option',
class: 'div-format',
tag: 'tr'
},
fromOptions: {
name: 'from',
type: 'text',
value: 'from',
size: 20
},
toOptions: {
name: 'to',
type: 'text',
value: 'to',
size: 20
},
removeLinkOptions: {
class: 'removeRow',
href: 'javascript:;'
}
};
For now I've change code like:
var removeRow = $.fn.optionTest.createColumn($("<img>", options.removeLinkOptions).src("http://www.somelink.com/image.png"));
But seems like there is wrong syntax rows not appear at all now...
use an <img> instead of <a> for an image. <a> is used for a link.
Thanks
In addition to the already mentioned changing <a> to <img>, you also need to set the attribute in order to change the image source. Using .attr('src','...') instead of .src('...') should fix it.
Changing this:
var removeRow = $.fn.optionTest.createColumn($("<img>", options.removeLinkOptions).src("http://www.somelink.com/image.png"));
To this:
var removeRow = $.fn.optionTest.createColumn($("<img>", options.removeLinkOptions).attr("src","http://www.somelink.com/image.png"));
That should fix your issue. Hope that helps!

Predefined buttons in CKEditor Mathjax plugin

CKEditor's Mathjax plugin contains several elements in the dialog: one textarea (id: equation) and one div (id: preview).
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/mathjax/dialogs/mathjax.js
When some mathjax code is entered in the textarea, the formula is written in the div. I am trying to add several predefined buttons that add usual formulae mathjax text to the textarea, so users only have to populate these formulae.
Adding a button into the elements works nice, but I can only access to change the div element. Accessing the textarea does not work, it seems that is not available in any scope at all.
id: 'info',
elements: [
{
id: 'testButton',
type: 'button',
button: 'aaaa',
onClick: function() {
// Changing the ID value does work
preview.setValue('Test');
// but changing the textarea does not.
// equation.setValue('Test');
// document.getElementById('equation').setValue('Test');
}
},
{
id: 'equation',
type: 'textarea',
label: lang.dialogInput,
onLoad: function() {
var that = this;
if ( !( CKEDITOR.env.ie && CKEDITOR.env.version == 8 ) ) {
this.getInputElement().on( 'keyup', function() {
// Add \( and \) for preview.
preview.setValue( '\\(' + that.getInputElement().getValue() + '\\)' );
} );
}
},
Sorry if this is a simple question, but how can I access to equation textarea?
After much reading, it seems that this is a way, not sure it's the best way though.
onClick: function() {
this._.dialog.setValueOf("info","equation","TEST");
}

Plugin for CKeditor to add multiple styles

Codewaggle's answer here got me started and I also have looked at Reinmar's answer, but I can't quite put this together.
I want to create a plugin with five custom spans (correction, deletion, suggestion...etc.) that I can then add to my CSS and have a button to apply each style using CKeditor in Drupal 7.
I don't want to use the drop-down for styles and prefer to have buttons with icons for each class added.
I used the basicstyles plugin as a jumping off point, but I have never done anything in javascript before so I am really in the dark.
I have added
config.extraPlugins = 'poligoeditstyles';
to the config file and set up the file structure of my plugin according to the guide on the CKeditor.
I assume that if all has gone according to plan I should see a button to drag into my toolbar, but, alas! No joy. I can see nothing added to my CKeditor toolbar when I add content or on the configuration page in Drupal:
admin/config/content/ckeditor/edit/Advanced
Am I missing something? Any help would be appreciated!
Here's my plugin code:
/**
* POLIGO edit styles plug-in for CKeditor based on the Basic Styles plugin
*/
CKEDITOR.plugins.add( 'poligoeditstyles', {
icons: 'correction,suggestion,deletion,commendation,dontunderstand', // %REMOVE_LINE_CORE%
init: function( editor ) {
var order = 0;
// All buttons use the same code to register. So, to avoid
// duplications, let's use this tool function.
var addButtonCommand = function( buttonName, buttonLabel, commandName, styleDefiniton ) {
// Disable the command if no definition is configured.
if ( !styleDefiniton )
return;
var style = new CKEDITOR.style( styleDefiniton );
// Listen to contextual style activation.
editor.attachStyleStateChange( style, function( state ) {
!editor.readOnly && editor.getCommand( commandName ).setState( state );
});
// Create the command that can be used to apply the style.
editor.addCommand( commandName, new CKEDITOR.styleCommand( style ) );
// Register the button, if the button plugin is loaded.
if ( editor.ui.addButton ) {
editor.ui.addButton( buttonName, {
label: buttonLabel,
command: commandName,
toolbar: 'poligoeditstyles,' + ( order += 10 )
});
}
};
var config = editor.config,
lang = editor.lang;
addButtonCommand( 'Correction', 'That's a mistake', 'correction', config.coreStyles_correction );
addButtonCommand( 'Suggestion', 'That's OK, but I suggest...', 'suggestion', config.coreStyles_suggestion );
addButtonCommand( 'Deletion', 'You don't need that', 'deletion', config.coreStyles_deletion );
addButtonCommand( 'Commendation', 'Great job!', 'commendation', config.coreStyles_commendation );
addButtonCommand( 'Dontunderstand', 'I don't understand what you mean', 'dontunderstand', config.coreStyles_dontunderstand );
}
});
// POLIGO Editor Inline Styles.
CKEDITOR.config.coreStyles_correction = { element : 'span', attributes : { 'class': 'correction' }};
CKEDITOR.config.coreStyles_suggestion = { element : 'span', attributes : { 'class': 'suggestion' }};
CKEDITOR.config.coreStyles_deletion = { element : 'span', attributes : { 'class': 'deletion' }};
CKEDITOR.config.coreStyles_commendation = { element : 'span', attributes : { 'class': 'commendation' }};
CKEDITOR.config.coreStyles_dontunderstand = { element : 'span', attributes : { 'class': 'dontunderstand' }};
Shot in the dark here but have you added your button to your config.toolbar in your initialization or config somewhere else - see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Toolbar

JS/jQuery event does not fire after addEventListener

I'm using a script that creates an HTML structure like this by adding objects with JS and jQuery using createElement and appendChild:
<div id="divLayer">
<div id="divBox">
<!-- stuff -->
<div id="btnSave" class="button small">Save</div>
</div>
</div>
Elements positions are respectively absolute, absolute and relative and displays are block, block and inline-block.
I have defined an array that contains objects attributes like this:
var objects = {
divLayer: {
tag: 'DIV',
id: 'divLayer',
parent: 'body'
},
divBox: {
tag: 'DIV',
id: 'divBox',
parent: '#divLayer'
},
btnSave: {
tag: 'DIV',
HTML: 'Save',
id: 'btnSave',
parent: '#divBox',
events: {
click: function () {
alert ( 'Clicked' );
}
}
}
}
This is the part where I create objects and add listeners to them:
for ( var config in objects ) {
var object = document.createElement ( config.tag );
...Setup other attributes...
for ( var event in config.events ) object.addEventListener ( event, config.events [ event ] );
$ ( config.parent ).get ( 0 ).appendChild ( object );
}
Graphically everything's correct. I can see divLayer on the background, divBox over it and btnSave, inside the box and every attribute is correctly compiled but, when I click the button nothing happens.
If I put the button directly on divLayer it works.
Where am I doing wrong?
Thx in advance!
Aside from using an Object where an Array would be safer, you're trying to access a property on config, but config is just a string representing the property name.
You need to use config to get the value.
for (var config in objects) {
var obj = objects[config]; // get the object
var object = document.createElement(obj.tag);
object.id = obj.id; // set the ID
for (var event in obj.events)
object.addEventListener(event, obj.events[event]);
$(obj.parent).get(0).appendChild(object);
}
Also, you're leaving out some code, so I can't tell if the other properties are being set correctly. I added the ID, and now your code works.
DEMO: http://jsfiddle.net/yBN6V/
Try binding using jQuery itself, delegating the event to a static parent:
for (var event in config.events)
$(document).on(event, object, config.events[event]);
I've bound the event to document in that example, you should really use the closest non-dynamic element which is available on page load.

Categories