How to load TypeKit fonts into a CKEditor instance

2019-04-17 11:03发布

问题:

I'm trying to load TypeKit fonts into an instance of the CKEditor via jQuery. Here's my code:

$('.ck-blog textarea').ckeditor(function () {
    CKEDITOR.scriptLoader.load(
      "http://use.typekit.com/zku8fnp.js", 
      function (success) { 
        Typekit.load(); 
        alert(success); }, 
      null, 
      true);
},
{
    resize_enabled: false,
    skin: 'kama',
    height: '500px',
    toolbarCanCollapse: false,
    toolbar_Full: toolbar,
    forcePasteAsPlainText: true,
    autoGrow_onStartup: true,
    templates_replaceContent: false,
    extraPlugins: 'autogrow,wordcount',
    removePlugins: 'resize',
    contentsCss: '/areas/admin/content/css/ckeditor-blog.css',
    templates_files: ['/areas/admin/scripts/ckeditor-templates.js'],
    autoParagraph: false
});

I'm getting the success alert after TypeKit is supposed to load but I am not see the fonts load. Any idea what I may be doing wrong?

回答1:

Here what I've managed to assemble after 3 hours of digging over Internet:

CKEDITOR.on(
    'instanceReady',
    function(ev) {
        var $script = document.createElement('script'),
            $editor_instance = CKEDITOR.instances[ev.editor.name];

        $script.src = '//use.typekit.com/MYKEY.js';
        $script.onload = function() {
            try{$editor_instance.window.$.Typekit.load();}catch(e){}
        };

        $editor_instance.document.getHead().$.appendChild($script);
    }
);

Trick here is to use CKEditor's "window" object, that comes from iframe.



回答2:

CKEDITOR.scriptLoader appears to be used to load assets to the parent window, not into the iframe'd document. This causes your code above to execute and re-apply the Typekit font to the parent window instead of the iframe.

My solution for this is to set document.domain in your parent window, create <script> elements dynamically, append them to the <head> of the iframe document.

1. Your Typekit has a domain whitelist. CKEditor will not set set the <iframe> tag's src attribute to return a valid value in this whitelist unless you specify document.domain in your parent window to be a domain on that whitelist.

document.domain = "example.com";

2. I created the scripts with lines like

script1      = document.newElement('script');
script1.src  = "https://use.typekit.com/MYKEY.js";

script2      = document.newElement('script');
script2.text = "try{Typekit.load();}catch(e){}";

3. I then append these to the dom (I use jQuery in my project, so that's how I target the element)

head = jQuery('textarea.editor').ckeditorGet().document.getHead().$;
head.appendChild(script1);
head.appendChild(script2);

The Typekit fonts are now applied.

Modified for use within the CKEditor setup

  editors.ckeditor(function(){
    var head         = this.document.getHead().$,
        script1      = document.newElement("script"),
        script2      = document.newElement("script");

    script1.src  = sprintf("https://use.typekit.com/%s.js", app_typekit_id);
    script2.text = "setTimeout(function(){ try{Typekit.load();}catch(e){} }, 0);";

    head.appendChild(script1);
    head.appendChild(script2);
  },
  {
    //... your custom config
  });

Maybe there is a better way than the setTimeout(function(){ ... }, 0); (a 0ms delay), but leaving just the try{Typekit.load();}catch(e){} does not give script1 enough time to be appended and interpreted by the browser to begin blocking. Also note, my use of sprintf() above comes from a library (not native JS).