开发者

How can my custom CKEditor plugin properly insert special iframes with a unique placeholder image?

There exists an iframe plugin currently built into CKEditor that allows iframes to be inserted into the editor, but displays a rather ugly placeholder no matter what is in the iframe. I am working on a plugin that takes in a video ID from the user and builds an iframe that points to a page for displaying videos on our website. I would like for my users to see a placeholder that makes it clear that they have inserted a video:

Ugly iframe placeholder:

How can my custom CKEditor plugin properly insert special iframes with a unique placeholder image?

Pretty video placeholder:

How can my custom CKEditor plugin properly insert special iframes with a unique placeholder image?

In order to get this far I added this bit of Javascript to my plugin's onOk function. I've included context:

onOk: function () {
    var videoID = this.getValueOf('info', 'video_id');
    va开发者_如何学JAVAr caption = this.getValueOf('info', 'caption');
    var display = this.getValueOf('info', 'display');
    var size = this.getValueOf('info', 'size');
    var width = size * 160;
    var height = size * 120;

    if (videoID.length > 0) {
        if (display == 0) {
            e.insertHtml("<a onclick=window.open(this.href,this.target,'width=" + width + ",height=" + height + "'); return false; target=newVideo href=/kbs/Video.aspx?videoId=" + videoID + "&amp;Width=" + width + "&amp;Height=" + height + ">" + caption + "</a>");
        } else {/*Here is the relevant code that is applied when display is set to embedded*/
            var iframeNode;
            //iframeNode = "<iframe height='" + (height + 40) + "' width='" + (width + 40) + "' src='/kbs/Video.aspx?videoId=1&height=" + height + "&width=" + width + "' frameBorder='0' scrolling='no'></iframe>");
            iframeNode = new CKEDITOR.dom.element('iframe');
            iframeNode.setAttribute('class', 'GROK-Video');
            iframeNode.setAttribute('height', height+40);
            iframeNode.setAttribute('width', width + 40);
            iframeNode.setAttribute('src', '/kbs/Video.aspx?videoId=1&height=' + height + '&width=' + width);
            iframeNode.setAttribute('frameBorder', 0);
            iframeNode.setAttribute('scrolling', 'no');
            var newFakeImage = e.createFakeElement(iframeNode, 'cke_GROKVideo', 'iframe', true);
            e.insertElement(newFakeImage);
        }
    }
}

The magic is in the editor's createFakeElement function. It replaces my iframe with a dummy element that is displayed as whatever image I choose with this bit of CSS in my plugin.js:

editor.addCss(
    'img.cke_GROKVideo' +
    '{' +
        'background-image: url(' + CKEDITOR.getUrl(this.path + 'images/YouTubePlayButton.png') + ');' +
        'background-position: center center;' +
        'background-repeat: no-repeat;' +
        'border: 1px solid #a9a9a9;' +
        'width: 80px;' +
        'height: 80px;' +
    '}'
);

Well I've gotten pretty far, but the problem arises when the source is viewed. The image turns back into an iframe and the iframe plugin replaces it with its own placeholder! Even worse, when the document is saved and reopened for editing, the same thing happens. How can I keep my play-button placeholder without breaking or replacing the built in iframe plugin placeholder? The pagebreak plugin seems to do something similar with div, but I'm not sure how CKEditor distinguishes between a pagebreak div and an ordinary div when it puts the fake elements in the editor. Has anyone tried something like this? I would prefer to not create a custom HTML element on my website just for this.


The solution consists of only two changes to your files:

Add this to your plugin.js

(function () {
    [...]
    CKEDITOR.plugins.add('yourPluginNName', {
        init: .... ,
        afterInit: function(editor){
            var dataProcessor = editor.dataProcessor,
                dataFilter = dataProcessor && dataProcessor.dataFilter;

            if ( dataFilter )
            {
                dataFilter.addRules(
                    {
                        elements :
                        {
                            iframe : function( element )
                            {
                               if( element.attributes["class"] && element.attributes["class"].indexOf( "GROK-Video" ) >= 0 ){
                                 var e = editor.createFakeParserElement( element, 'cke_GROKVideo', 'iframe', true );

                                 // if you want add a thumbnail background or other 
                                 // styles then do it here. 
                                 // but note that it's a parser element, not an html 
                                 // element, it goes something like this: 
                                 e.attributes["style"] += "background: url( ... );"; 
                                 return e;
                               }
                               else{
                                 return element;
                               }
                            }
                        }
                    }, 3); //Priority allows this to overrule the iframe plugin.
            }
        }
    })
})();

What this effectively does is it hooks into the editors initial transformation step, if it encouters an iframe element it replaces it with a fake element.

Also note that it only replaces the element if it's class-name is GROK-Video, all other iframe's will remain unharmed.

This is great if you have multiple different media plugins.

Disable the iframe plugin in your config:

That's easy:

config.removePlugins = "iframe";

Maybe you can tell the iframe plugin to be friends with your plugin, but I don't needed it and I just couldn't be bothered.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜