CKEditor plugging to add images from Sharepoint Asset Picker

I know this has nothing to do with functional programming but recently I had a requirement from a client to add images from a SharePoint Library (Sharepoint Asset Picker) into a rich text editor they use for a news intake form hosted in SharePoint 2013 and I wanted to share it and make it open to the public, because maybe this could help someone that has a similar requirement.

The rich text editor they were using was CKEditor 4.6 and they wanted  to integrate the built in SharePoint asset picker into it.

What I did in this case was to look for an existing plugin that would help me get started. I searched into their add-ons library and found the custimage plugin, which is a plugin that allows you replace the built-in image plugin and started from there.

The folder and file structure for the plugin looks like this and every single plugin for the CKEditor has to have a similar structure.

I changed the default names and conventions to identify it more with the SharePoint usage.

One of first things to do is to define the plugin, set the name, assign an Icon and create the reference to the dialog, you do that on the ‘plugin.js’ file:

CKEDITOR.plugins.add('SPImage',
 {
   icons:'SPImage', //ICON
   init: function(editor) {
   //DEFINE DIALOG
   editor.addCommand('SPImage',new CKEDITOR.dialogCommand('SPImageDialog'));
   //ADD BUTTON
   editor.ui.addButton('SPImage', {label: editor.lang.common.image,command:'SPImage',toolbar:'insert'});
   //ADD DIALOG
   CKEDITOR.dialog.add('SPImageDialog',this.path+'dialogs/SPImage.js')
  }
 }
);

Then on the dialog file (dialogs\SPimage.js), which is the file that contains the code that controls the dialog behavior, what I did was to add the fields definitions that I needed. In this case I only needed Image Source, a Browse button, Width and Height, and added the behavior for each of them.

...
contents:[
 {
  id:'SPimgSettings',
  label:'Image Settings',
  elements:[
   {
    type:'text',
    id:'imgSrc',
    label:'Image Source: *',
    validate:CKEDITOR.dialog.validate.notEmpty('Image Source field cannot be empty')
  },
...
 {
   type: 'text',
   id: 'imgWidth',
   label: 'Width:',
   maxLength: 5,
   inputStyle: 'width:50px',
   validate: function() {
        if (this.getValue()) {
          if(isNaN(parseFloat(this.getValue()))) {
           alert('Width must be numeric.' );
           return false;
          }
        }
      }
  },
  {
   type: 'text',
   id: 'imgHeight',
   label: 'Height:',
   maxLength: 5,
   inputStyle: 'width:50px',
   validate: function() {
        if (this.getValue()) {
          if(isNaN(parseFloat(this.getValue()))) {
           alert('Height must be numeric.' );
           return false;
          }
        }
      }
  }

Then added the SharePoint Asset Picker call and tied it to the dialog, so it will open when clicking on the ‘Browse’ button and on close it will give me the path of the image selected by the user inside the SharePoint.

...
{
 type:'button',
 id:'brsButton',
 label:'Browse',
 title:'Browse',
 style: 'float:right',
 onClick: function() {
     var thisDialog = CKEDITOR.dialog.getCurrent(); //get the current instance of the dialog

     with(new AssetPickerConfig('spAssetPickerObj'))
     {{
        DefaultAssetImageLocation='';
        CurrentWebBaseUrl= window._spPageContextInfo.webAbsoluteUrl; //obtain the absolute URL of the Sharepoint Site Collection
        OverrideDialogFeatures='';
        OverrideDialogTitle='';
        OverrideDialogDesc='';
        OverrideDialogImageUrl='';
        AssetUrlClientID=''; //not needed this time
        AssetTextClientID='';
        UseImageAssetPicker=true; //make this false to show Documents
        DefaultToLastUsedLocation=true;
        DisplayLookInSection=true;
        ReturnCallback = function(spi) {
                      thisDialog.setValueOf('SPimgSettings','imgSrc',spi); //set the value of the image source field with the path of the image in SharePoint
                   };
     }}

     APD_LaunchAssetPickerUseConfigCurrentUrl('spAssetPickerObj');
   }
 },
....

And the last thing was to insert the image into the editor after the user hits ‘Ok‘.

onOk:function(){
   var dialog = this;
   var imageObj = editor.document.createElement('img');
   imageObj.setAttribute('src', dialog.getValueOf('SPimgSettings', 'imgSrc'));
   if(dialog.getValueOf('SPimgSettings', 'imgHeight') != '') {
     imageObj.setAttribute('height', dialog.getValueOf('SPimgSettings', 'imgHeight'));
   }

   if(dialog.getValueOf('SPimgSettings', 'imgWidth') != '') {
     imageObj.setAttribute('width', dialog.getValueOf('SPimgSettings', 'imgWidth'));
   }

   editor.insertElement(imageObj); //insert the image
 }

In the load event of the dialog I added a z-index hack because the original z-index of the CKEditor dialogs  were on top of the SharePoint modals z-index and then those dialog were always on top of everything. I added this ugly hack and now the Asset Picker is displayed on top of the editor and the dialog.

 onShow:function(){
   //UGLY hack:
   //set Z-INDEX to be just behind the SharePoint modals Z-Index
   $('div.cke_dialog_background_cover').css('z-index', 1501);
   $('table.cke_dialog.cke_ltr.cke_single_page').css('z-index', 1502);
 },

In order to add the plugin to the CKEditor and use it, just have to add the following call:

CKEDITOR.replace( 'editor1', {
 extraPlugins: 'SPImage' //Add SPimage plugin
});

This is a very simple approach and has almost no added functionality, but it is a good starting point to do a better integration between SharePoint and CKEditor.

You can browse and download the full source code on my GitHub page and from the CKEditor add-ons page.


Sources:

  1. CKEditor documentation | Plugin SDK
  2. CKEditor Custom Image Dialog plugin by Hums
  3. Add Asset picker(Browse and select file) control to Textbox in a Sharepoint list form Or Page

 

Facebook Comments