Temporary disable button on ckeditor - ckeditor

How can i enable or disable the paragraph button of CKEditor on selection of an image. I did not want to remove it completely.
am currently using ckeditor version 4.4

Use editor.getCommand() + CKEDITOR.command API (enable and disable):
editor.getCommand( 'justifyleft' ).disable();
editor.getCommand( 'justifyleft' ).enable();
For example:
CKEDITOR.instances.editor1.on( 'selectionChange', function( evt ) {
var jLeftCommand = this.getCommand( 'justifyleft' ),
jRightCommand = this.getCommand( 'justifyright' );
if ( evt.data.path.lastElement.is( 'img' ) ) {
jLeftCommand.disable();
jRightCommand.disable();
} else {
jLeftCommand.enable();
jRightCommand.enable();
}
} );

Related

CKEDITOR insert special symbol with Keyboard shortcut

I am working on a project which has a requirement is: if user press a shortcut then a symbol will insert in text editor. Like:
if press Shift+1 then insert ✓
if press Shift+2 then insert ✗
I have done this in textarea but I am using CKEDITOR in this project and I have tried by 'keystrokes' like this but didn't work:
CKEDITOR.config.keystrokes = [
[ CKEDITOR.SHIFT + 76, function(){
console.log('sdsd');
} ]
];
Can somebody help me out please?
You can use command to execute a function like follow.
CKEDITOR.plugins.add('foo',
{
init: function( editor ) {
editor.addCommand( 'sample', {
exec: function( editor ) {
alert( 'Executing a command for the editor name "' + editor.name + '"!' );
}
} );
editor.setKeystroke( CKEDITOR.CTRL + 81, 'sample' ); // CTRL+Q
}
});
or in your way but after defining the command.
CKEDITOR.config.keystrokes = [
[ CKEDITOR.SHIFT + 76, 'sample' ]
];
The second value for the CKEDITOR.config.keystrokes expects a command name not a function.
NB: As the implementation is using plugin. You also have to configure the editor to use the plugin using extraPlugins configuration
CKEDITOR.replace('editor', {
extraPlugins : 'foo'
});
As your need is simply to map a keystroke to a symbol. You can use this plugin.
disclaimer: I'm the author of that plugin
You need to use setkystroke method like this :
For 4.x, use editor.setKeystroke:
CKEDITOR.plugins.add( 'test', {
init: function( editor ) {
editor.setKeystroke( CKEDITOR.CTRL + 81, 'bold' ); // CTRL+Q
}
} );
For 3.x:
CKEDITOR.plugins.add( 'test', {
init: function( editor ) {
editor.on( 'instanceReady', function( evt ) {
evt.removeListener();
this.keystrokeHandler.keystrokes[ CKEDITOR.CTRL + 81 ] = 'bold'; // CTRL+Q
} );
}
} );

How to callback on certain text

I'm trying to find a reliable way to perform a callback when certain text is typed into the editor. I want to run certain code when an # is typed (to then allow a selection of user's to link to).
Currently I am doing it by using the "change" event and then trying to look back at what is before the current selection:
CKEDITOR.plugins.add( 'ipsmentions', {
init: function( editor ) {
/* When the content of the editor is changed, check if it was an # */
editor.on( 'change', function(e) {
/* If we currently have just normal text selected, we're typing normally and there might be an # */
var selection = editor.getSelection();
if ( selection.getType() == CKEDITOR.SELECTION_TEXT ) {
/* Loop the ranges... */
var ranges = selection.getRanges( true );
for ( var i = 0; i < ranges.length; i++ ) {
/* If the start container and end container are the same (meaning we just have a normal caret, indicating normal typing, nothing highlighted) and that is a text node... */
if ( ranges[i].startContainer.equals( ranges[i].endContainer ) && ranges[i].endContainer instanceof CKEDITOR.dom.text ) {
if ( ranges[i].startContainer.getText().substr( ranges[i].startOffset - 1, 1 ) == '#' ) {
console.log('# pressed!');
}
}
}
}
});
}
});
But I'm guessing this isn't the best way. In particular, I notice that if I type # and then hit enter (to start a new paragraph) I get "# pressed" in the console again.
Is there a better way to go about this?
Asynchronous check should help with enter key. I would also use some backwards range.cloneContents because you never know in what type of node the selection might be anchored. JSFiddle.
CKEDITOR.replace( 'editor', {
on: {
change: function() {
CKEDITOR.tools.setTimeout( function() {
var sel = this.getSelection(),
range = sel.getRanges()[ 0 ];
if ( !range.collapsed ) {
console.warn( 'non–collapsed range' );
return;
}
if ( !range.startOffset ) {
console.warn( 'at the beginning of the node' );
return;
}
range.setStart( range.startContainer, 0 );
if ( range.cloneContents().$.textContent.substr( -1 ) == '#' ) {
console.log( '# inserted' );
}
}, 0, this );
}
}
} );

CKEditor: strip element without attributes?

I've configured extraAllowedContent in "config.js" to allow div elements with specific classes, per the Advanced Content Filtering guide, which is working.
However, I need to strip any div elements that have no attributes. Is this possible?
You can specify config.disallowedContent with match function:
CKEDITOR.replace( 'editor1', {
disallowedContent: {
div: {
match: function( el ) {
return CKEDITOR.tools.isEmpty( el.attributes );
}
}
}
} );
While it correctly filters out the contents, for some reason (a bug), it also disables the Div plugin and its dialog. Thus I'd rather suggest something like this at the moment:
CKEDITOR.replace( 'editor1', {
on: {
pluginsLoaded: function( evt ) {
var editor = evt.editor,
rules = {
elements: {
div: function( el ) {
if ( CKEDITOR.tools.isEmpty( el.attributes ) ) {
// Return false to get rid of an element with children.
return false;
// The element can also be removed preserving children.
// el.replaceWithChildren();
}
},
}
};
// Filter what comes out of an editor.
editor.dataProcessor.htmlFilter.addRules( rules );
// Filter what comes into an editor.
editor.dataProcessor.dataFilter.addRules( rules );
}
}
} );

CKEditor ACF image width and height

I am trying to force CKEditor to set image width and height as attributes not styles. According to docs i need to set in CKEditor config allowedContent = img[!src,alt,width,height] but when i do this CKEditor mode changes from automatic to custom and filters all other html tags.
How to change allowedContent only this specific case?
As i understand correctly each plugin registers its own allowedContent, so i changed in image plugin following line allowed = 'img[alt,!src] to allowed = 'img[alt,!src, width, height] but it does not work
ACF lacks one thing - #feature event. There's currently no convenient way to alter allowedContent of a feature being registered.
In your case, you will be able to use a temporary solution I described on CKEditor forum.
Your previous attempt to alter image's allowedContent wasn't successful most likely because you haven't fully replaced it. This is a code from image plugin:
var allowed = 'img[alt,!src]{border-style,border-width,float,height,margin,margin-bottom,margin-left,margin-right,margin-top,width}',
required = 'img[alt,src]';
if ( CKEDITOR.dialog.isTabEnabled( editor, pluginName, 'advanced' ) )
allowed = 'img[alt,dir,id,lang,longdesc,!src,title]{*}(*)';
So if you have changed just the first occurrence, then the second overrides it.
Many thanks Rainmar for help. It seems that dialog is removing the attributes. I managed to fix that changing commit function for width and height in image/dialogs/image.js file.
The old function looked like this (for width only):
commit: function( type, element, internalCommit ) {
var value = this.getValue();
if ( type == IMAGE ) {
if ( value )
element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );
else
element.removeStyle( 'width' );
!internalCommit && element.removeAttribute( 'width' );
} else if ( type == PREVIEW ) {
var aMatch = value.match( regexGetSize );
if ( !aMatch ) {
var oImageOriginal = this.getDialog().originalElement;
if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
element.setStyle( 'width', oImageOriginal.$.width + 'px' );
} else
element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );
} else if ( type == CLEANUP ) {
element.removeAttribute( 'width' );
element.removeStyle( 'width' );
}
}
And change it to this:
commit: function( type, element, internalCommit ) {
var value = this.getValue();
if ( type == IMAGE ) {
if ( value ) {
element.setAttribute('width', value + 'px');
element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );
}else {
element.removeAttribute('width');
element.removeStyle( 'width' );
}
!internalCommit && element.removeStyle( 'width' );
} else if ( type == PREVIEW ) {
var aMatch = value.match( regexGetSize );
if ( !aMatch ) {
var oImageOriginal = this.getDialog().originalElement;
if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
element.setStyle( 'width', oImageOriginal.$.width + 'px' );
} else
element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );
} else if ( type == CLEANUP ) {
element.removeAttribute( 'width' );
element.removeStyle( 'width' );
}
}
This is now super simple:
config.allowedContent = {
$1: {
// Use the ability to specify elements as an object.
elements: CKEDITOR.dtd,
attributes: true,
styles: true,
classes: true
}
};
config.disallowedContent = 'img{width,height}';
Which will alow everything, and convert inline image width/height to attributes.
http://docs.ckeditor.com/#!/guide/dev_acf-section-example%3A-disallow-inline-styles-and-use-attributes-instead

CKEditor: Controlling Entermode with a toolbar button

By default, CKEditor's enter key behavior is adding a <p> tag and starting a new paragraph. But that behavior can be modified in the configuration with a .EnterMode parameter.
I'm wondering if there is a way to change Enter key behavior in the runtime, by putting a button into its tool bar, to switch between <p> and <br> (single line vs double line), just like as in Word.
Any ideas on how to do this?
Save the following to editor_dir/plugins/entermode/plugin.js:
'use strict';
(function() {
CKEDITOR.plugins.add( 'entermode', {
icons: 'entermode',
init: function( editor ) {
var enterP = new enterModeCommand( editor, CKEDITOR.ENTER_P );
var enterBR = new enterModeCommand( editor, CKEDITOR.ENTER_BR );
editor.addCommand( 'entermodep', enterP );
editor.addCommand( 'entermodebr', enterBR );
if ( editor.ui.addButton ) {
editor.ui.addButton( 'EnterP', {
label: 'Enter mode P',
command: 'entermodep',
toolbar: 'paragraph,10'
});
editor.ui.addButton( 'EnterBR', {
label: 'Enter mode BR',
command: 'entermodebr',
toolbar: 'paragraph,20'
});
}
editor.on( 'dataReady', function() {
refreshButtons( editor );
});
}
});
function refreshButtons( editor ) {
editor.getCommand( 'entermodep' ).setState(
editor.config.enterMode == CKEDITOR.ENTER_P ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
editor.getCommand( 'entermodebr' ).setState(
editor.config.enterMode == CKEDITOR.ENTER_BR ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
}
function enterModeCommand( editor, mode ) {
this.mode = mode;
}
enterModeCommand.prototype = {
exec: function( editor ) {
editor.config.enterMode = this.mode;
refreshButtons( editor );
},
refresh: function( editor, path ) {
refreshButtons( editor );
}
};
})();
Now add the following to toolbar.css in your skin file:
.cke_button__enterp_icon, .cke_button__enterbr_icon { display: none !important; }
.cke_button__enterp_label, .cke_button__enterbr_label { display: inline !important; }
...or paint some icons, if you want.
Enable the plugin when running the editor:
CKEDITOR.replace( 'id', { extraPlugins: 'entermode' } );
Now you can control config.enterMode from the toolbar.

Resources