CKEditor: Customized HTML on inserting an image - ckeditor

I'm using CKEditor 3.5 to provide WYSYWYG editing in a website. When inserting an image you can provide width and height of the image, which results in HTML like follows:
<img alt="" src="/Images/Sample.png" style="width: 62px; height: 30px; " />
Since this does the resizing in the browser and in other places on the same website I use Nathanael Jones' Image Resizing Module, I'd like to get the following output instead:
<img alt="" src="Images/Sample.png?width=62&height=30" />
Is there an easy way to control the generated HTML or have I really to write my own dialog/plugin for CKEditor?
EDIT:
Adding the following lines to config.js was the solution that eventually worked for me:
CKEDITOR.on('dialogDefinition', function (ev) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
var dialog = dialogDefinition.dialog;
var editor = ev.editor;
if (dialogName == 'image') {
dialogDefinition.onOk = function (e) {
var imageSrcUrl = e.sender.originalElement.$.src;
var width = e.sender.originalElement.$.width;
var height = e.sender.originalElement.$.height;
var imgHtml = CKEDITOR.dom.element.createFromHtml('<img src=' + imageSrcUrl + '?width=' + width + '&height=' + height + ' alt="" />');
editor.insertElement(imgHtml);
};
}
});
The next problem is then, when editing an image, the width and height naturally are in the URL field and are missing in the dedicated fields for width and height. So I need to come up with a solution for the reverse... :-)

I kind of had the same problem, I needed to remove those attributes from the generated HTML for the image, so what I did was to override the onOK method of the uploader and insert the image element manually using the CKEditor's API, something like this:
CKEDITOR.on('dialogDefinition', function(ev) {
// Take the dialog name and its definition from the event data
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
var editor = ev.editor;
if (dialogName == 'image') {
dialogDefinition.onOk = function(e) {
var imageSrcUrl = e.sender.originalElement.$.src;
var imgHtml = CKEDITOR.dom.element.createFromHtml("<img src=" + imageSrcUrl + " alt='' align='right'/>");
editor.insertElement(imgHtml);
};
}
}
This has worked for us so far.

Look at the "output html" sample, you can find there some code that changes the dimensions in images from styles to attributes, so you can adjust it to rewrite the URL.

I don't have enough points to comment on that previous answer. but in respect to your error: CKEDITOR.currentInstance returns undefined.
That is strange because CKEDITOR is global, but you shouldn't have to resort to that.
Within the OK function invocation, you have access to "editor", you shouldn't have to get the instance.
just a suggestion.

Best bet might be to "recreate" the src (and possibly the style) field's behavior. I've do something similar. (but not as complex)
Start with the original code (from plugins/dialog/image.js) and create setup and commit logic that produces (and parses) the markup you're looking for.
Then during dialog definition
Delete Originals
Add your "custom" fields
style field not sure, maybe just leave it in the dialog, but stub out it's commit logic.
I added my field to the dialog...
var infoTab = dialogDefinition.getContents( 'info' );
// Move the ID field from "advanced" to "info" tab.
infoTab.add( idField_config);
var idField_config = {
type : 'text',
label : 'Name',
id : 'linkId',
setup : function( type, element ) {
//if ( type == IMAGE )
this.setValue( element.getAttribute( 'id' ) );
},
commit : function( type, element ) {
//if ( type == IMAGE ) {
if ( this.getValue() || this.isChanged() )
element.setAttribute( 'id', this.getValue() );
//}
}
};
Issues I faced.
New fields get added to end of
dialog.
Pieces of the original code
( type == IMAGE ) isn't valid (Love to know why but felt comfortable it was safe to comment for my usage)
You might face problems with the markup rules undoing your hard work, but "output html" sample" suggestion should help you weed through that issue.

Related

Ckeditor unable to use percentages for image width and height

I'm trying to use percentages instead of a pixel for images when using CKEditor. I get the error "Width must be a number." when ever I try to add a % into either width or height.
Is there an easy way to disable the validation check or will I need to manually rewrite the validation code?
This is not doable without modifying plugin code.
The image2 plugin you are asking about uses only pixels:
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/image2/dialogs/image2.js#L448
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/image2/dialogs/image2.js#L75-L83
Sure you could use below code on your HTML page to disable validation:
var editor = CKEDITOR.replace( 'editor1', {
extraPlugins : 'image2'
image2_disableResizer : true
});
CKEDITOR.on('dialogDefinition', function(ev) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if (dialogName == 'image2') {
var infoTab = dialogDefinition.getContents( 'info' );
infoTab.get('width').validate = function() {
return true; //more advanced validation rule should be used here
}
infoTab.get('height').validate = function() {
return true; //more advanced validation rule should be used here
}
}
});
Please note however that image2 uses also the resizer which works in pixels and it could mess up your size in %. Even if you disable the resizer like in code snippet above, there is still a rule in plugin code which removes % :
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/image2/plugin.js#L952-L953
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/image2/plugin.js#L17
and even if you do all that, you will probably get into few other obstacles.
To summarize: without changing plugin code you won't be able to use %

How to disable automatic style to img in ckeditor?

There is one problem when I work with ckeditor. I press on icon for adding images, then modal window appears and I put direct image link in the special field, in this moment width and height detected automatically and it writes to style for ex:
<img src='#some images direct link' style='width:SOME WIDTH;height:SOME HEIGHT'>
Can I disable this automatic function? Or I have to delete this style by myself every time?
You could write a rule for your config that would remove the style tag on elements.
var editorRulesObject = {
elements: {
img: function( el ) {
if(el.attributes.style) {
el.attributes.style = '';
}
}
}
};
CKEDITOR.on('instanceReady', function( e ) {
// Ensures that any non-styled text, or text input without any tags will be correctly styled.
CKEDITOR.instances[e.editor.name].dataProcessor.dataFilter.addRules( editorRulesObject );
CKEDITOR.instances[e.editor.name].dataProcessor.htmlFilter.addRules( editorRulesObject );
});
In 2020, since version 4.5.0, it is much easier to switch off the annoying automatic filling in of height and readiness.
New there is the config option "image_prefillDimensions".
config.image_prefillDimensions = false;
Documentation: http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-image_prefillDimensions
The user still has the possibility to fill in the height and width automatically by clicking on the button [Reset size (circle arrow)].

fineuploader - Read file dimensions / Validate by resolution

I would like to validate by file dimensions (resolution).
on the documentation page there is only information regarding file name and size, nothing at all in the docs about dimensions, and I also had no luck on Google.
The purpose of this is that I don't want users to upload low-res photos to my server. Thanks.
As Ray Nicholus had suggested, using the getFile method to get the File object and then use that with the internal instance object qq.ImageValidation to run fineuploader's validation on the file. A promise must be return because this proccess is async.
function onSubmit(e, id, filename){
var promise = validateByDimensions(id, [1024, 600]);
return promise;
}
function validateByDimensions(id, dimensionsArr){
var deferred = new $.Deferred(),
file = uploaderElm.fineUploader('getFile', id),
imageValidator = new qq.ImageValidation(file, function(){}),
result = imageValidator.validate({
minWidth : dimensionsArr[0],
minHeight : dimensionsArr[1]
});
result.done(function(status){
if( status )
deferred.reject();
else
deferred.resolve();
});
return deferred.promise();
}
Remained question:
Now I wonder how to show the thumbnail of the image that was rejected, while not uploading it to the server, the UI could mark in a different color as an "invalid image", yet the user could see which images we valid and which weren't...
- Update - (regarding the question above)
While I do not see how I could have the default behavior of a thumbnail added to the uploader, but not being uploaded, but there is a way to generate thumbnail manually, like so:
var img = new Image();
uploaderElm.fineUploader("drawThumbnail", id, img, 200, false);
but then I'll to create an item to be inserted to qq-upload-list myself, and handle it all myself..but still it's not so hard.
Update (get even more control over dimensions validation)
You will have to edit (currently) the qq.ImageValidation function to expose outside the private function getWidthHeight. just change that function deceleration to:
this.getWidthHeight = function(){
Also, it would be even better to change the this.validate function to:
this.validate = function(limits) {
var validationEffort = new qq.Promise();
log("Attempting to validate image.");
if (hasNonZeroLimits(limits)) {
this.getWidthHeight().done(function(dimensions){
var failingLimit = getFailingLimit(limits, dimensions);
if (failingLimit) {
validationEffort.failure({ fail:failingLimit, dimensions:dimensions });
}
else {
validationEffort.success({ dimensions:dimensions });
}
}, validationEffort.success);
}
else {
validationEffort.success();
}
return validationEffort;
};
So you would get the fail reason, as well as the dimensions. always nice to have more control.
Now, we could write the custom validation like this:
function validateFileDimensions(dimensionsLimits){
var deferred = new $.Deferred(),
file = this.holderElm.fineUploader('getFile', id),
imageValidator = new qq.ImageValidation(file, function(){});
imageValidator.getWidthHeight().done(function(dimensions){
var minWidth = dimensions.width > dimensionsLimits.width,
minHeight = dimensions.height > dimensionsLimits.height;
// if min-width or min-height satisfied the limits, then approve the image
if( minWidth || minHeight )
deferred.resolve();
else
deferred.reject();
});
return deferred.promise();
}
This approach gives much more flexibility. For example, you would want to have different validation for portrait images than landscape ones, you could easily identify the image orientation and run your own custom code to do whatever.

CKEditor dialog input field above tab elements

I'm building a simple dialog plugin to replace the default link tool. The design calls for a particular layout that is difficult to achieve with the CKEdit dialog definition: We want a single field to appear above the tab elements in the dialog (see illustration).
Can anyone suggest a way that this might be implemented? Thanks!
As far as I can tell it is not possible to achieve this using the built-in dialog definition.
I was able to get around this limitation by building my dialog plugin using the iframedialog plugin. This basically pops up a CKEditor dialog window and loads an external URL into it. You can do anything you want in that iframe, and then return the text to CKEditor when the user presses the OK button.
A simple example:
// plugins/iframelink/plugin.js
CKEDITOR.plugins.add('iframelink', {
requires: ['iframedialog'],
init: function(editor){
CKEDITOR.dialog.addIframe('iframelinkDialog',
// title
'Insert a Link',
// src
this.path + 'dialogs/link.html',
// minWidth
500,
// minHeight
250,
// onContentLoad
);
var cmd = editor.addCommand('iframelink', {exec: iframelinkOnclick});
editor.ui.addButton('iframelink', {
label: 'Insert a Link (Special Link Tool)',
command: 'iframelink',
icon: this.path + 'images/world_link.png'
});
}
});
function iframelinkOnclick(editor){
dialog = editor.openDialog('msiteslinkDialog');
};
// plugins/iframelink/dialogs/iframelink.js
$(function() {
if (typeof(window.parent.CKEDITOR) != 'undefined') {
CKEDITOR = window.parent.CKEDITOR;
var dialog = CKEDITOR.dialog.getCurrent();
var editor = dialog.getParentEditor();
// Get value of the selected text:
var selection = editor.getSelection().getSelectedText();
// Do something when the user presses the OK button:
var okListener = function(ev) {
link = yourFunctionToDoSomethingClever();
this._.editor.insertHtml(link);
dialog.removeListener("ok", okListener);
};
// Bind the OK button to your okListener method:
dialog.on("ok", okListener);
};
}
So you can make the dialog look any way you want:

CKEDITOR default tabble width

How do i change the default width of the tables in CKEditor, without doing it manualy in the dialog?
For example, the default is 500, and i want it to be 400.
Regards,Elkas
I Found the answer.
In the plugins folder, look for the table folder and table.js.
Do a litle search by the number "500" (it will be near a id:txtWidth) and change it to the value you want.
Pay attention because on the top of the file there is a minWidth.
Thanks for you're answer guys.
Regards,Elkas
For CKEditor 4, you can define a default width in your config (this info from the CKEditor forums). Open config.js and paste this at the end of it, replacing '100%' with your desired default width:
// http://ckeditor.com/comment/129258#comment-129258
CKEDITOR.on( 'dialogDefinition', function( ev ) {
// Take the dialog name and its definition from the event data.
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
// Check if the definition is from the dialog we're
// interested in (the "Table" dialog).
if ( dialogName == 'table' ) {
// Get a reference to the "Table Info" tab.
var infoTab = dialogDefinition.getContents( 'info' );
txtWidth = infoTab.get( 'txtWidth' );
txtWidth['default'] = '100%';
}
});
Not sure what you mean by 'the dialog'.
Using javascript code...
config.width = 850;
config.width = '75%';
I found this in the docs.
http://docs.cksource.com/CKEditor_3.x/Howto/Editor_Size
Is this any help?

Resources