Ben Sinclair
Ben Sinclair

Reputation: 3986

CKEditor 4 Images and dataProcessor API

I have set-up my CKEditor instance so that when viewing the WYSIWYG (live) mode [image:abc123] is replaced with the actual URL to the image.

So for example in the HTML source view, you see this:

<img src="[image:abc123]" />

But when you view the WYSIWYG (live) mode, it shows this:

<img src="/file/image/abc123" />

Here is the plugin code I added as a plugin that does the trick:

CKEDITOR.plugins.add( 'myplugin',
{
    requires : ['richcombo'],
    init : function( editor )
    {
        var config = editor.config, lang = editor.lang.format;

        /* Images */
        editor.dataProcessor.dataFilter.addRules({
            elements: {
                img: function( element ) {
                    var file_id = element.attributes.src.match(/\[image:([a-zA-Z0-9-]+)\]/);
                    if (file_id)
                        element.attributes.src = site_url + 'file/image/' + file_id[1];
                }
            }
        });

    }
});

Now this all works fine until I edit the image using the Image properties dialog. When I hit save, it removes my plugin code above and displays the image as a 404.

I found some code that detects if the Image Dialog is saved so that I could apply the same code. Here is the updated plugin code:

CKEDITOR.plugins.add( 'myplugin',
{
    requires : ['richcombo'],
    init : function( editor )
    {
        var config = editor.config, lang = editor.lang.format;

        /* Images */
        editor.dataProcessor.dataFilter.addRules({
            elements: {
                img: function( element ) {
                    var file_id = element.attributes.src.match(/\[image:([a-zA-Z0-9-]+)\]/);
                    if (file_id)
                        element.attributes.src = site_url + 'file/image/' + file_id[1];
                }
            }
        });

        /* When image properties saved, make sure image retains its URL */
        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;

            if (dialogName == 'image') {
               dialogDefinition.onOk = function(e) {

                     /* Images */
                    editor.dataProcessor.dataFilter.addRules({
                        elements: {
                            img: function( element ) {
                                var file_id = element.attributes.src.match(/\[image:([a-zA-Z0-9-]+)\]/);
                                if (file_id)
                                    element.attributes.src = site_url + 'file/image/' + file_id[1];
                            }
                        }
                    });

               };
            }
        });

    }
});

It works but none of the properties that I set in the Image Dialog are added to the image. It's almost like my code overwrites the plugin code... Any ideas what I need to add to make this work?

Upvotes: 1

Views: 1079

Answers (1)

oleq
oleq

Reputation: 15895

It's enough to overwrite commit function in dialog definition (jsFiddle). Inspect WYSIWYG source with browser's inspector to see that src is correct:

function convertSrc( src ) {
    var match = src.match(/\[image:([a-zA-Z0-9-]+)\]/);

    if ( match )
        return 'http://foo.bar/file/image/' + match[ 1 ];
    else
        return src;
}

CKEDITOR.replace( 'editor', {
    plugins: 'wysiwygarea,sourcearea,toolbar,basicstyles,image',
    on: {
        pluginsLoaded: function() {
            this.dataProcessor.dataFilter.addRules( {
                elements: {
                    img: function( el ) {
                        el.attributes.src = convertSrc( el.attributes.src );
                    }
                }
            } );             
        }
    }
} );

CKEDITOR.on( 'dialogDefinition', function( evt ) {
    if ( evt.data.name == 'image' ) {
        var def = evt.data.definition,
            defUrl = def.getContents( 'info' ).get( 'txtUrl' ),
            orgCommit = defUrl.commit;

        defUrl.commit = function( type, element ) { 
            orgCommit.call( this, type, element );

            // Here's the magic:                
            element.setAttribute( 'src', convertSrc( this.getValue() ) );            
        }
    }
} );

Upvotes: 1

Related Questions