javascriptimagecontenteditablecontent-editor

Insert image from custom media manager in ContentTools


I am implementing the great Content Tools editor in a PHP Framework I've been developing along the last years, but I've reached a dead end.

I want to insert images from a custom media manager (already implemented) at the cursor position inside the current editable region, just like the default image tool would do.

I have tried to follow the tutorials on developing my own tools, but my not so good knowledge of Coffee Script and JavaScript are holding me back.


From my understading, maybe the steps would be:

  1. Create a new tool based on the image tool
  2. The tools would open the Media Manager on a modal (iframe) instead of the default dialog from ContentTools (thats how the Media Manager works in the FW)
  3. Do my stuff on the Media Manager (upload, crop, classify image, etc.)
  4. Select an image from the list and click "Insert"
  5. The Media Manager iframe calls a parent.someFunction({ image data }) that inserts the imagem just like the default "image" tools would do.
  6. Done!

Some serious doubts:

  1. How to override the default dialog with my modal call?

  2. Do i have to pass the region name and cursor position(?) to the iframe as parameters or is this information stored in the main scope somewhere? (or... do I even have to worry about that at all or the editor handles everything in that matter?)

  3. Is it possible to create a function that could be called somewhat like that:

    parent.insertMediaManagerItem({
      url: 'my-image.png',
      width: '300px',
      height: '200px'
    });
    

Again, I'm very new and lost on the ContentTools subject. Any help would be appreciated.


Solution

  • The best example I can provide is the implementation used for KCFinder, another media manager written in PHP that I believe uses (at least in the implementation I helped with) a new window instead of an iframe but I believe the principal will be the same.

    As you've indicated the simplest solution is to write your own image tool to replace the default tool, that way the responsibility for uploading and/or returning an image is switched to your custom media manager over the CT image dialog and ImageUploader class discussed in the tutorial.

    The following is a modified version of the tool code we used for KCFinder:

    When I say we I'm referring to myself and Wouter Van Marrum who raised and helped create the KCFinder example on github here)

    // So this little bundle of variables is required because I'm using CoffeeScript
    // constructs and this code will potentially not have access to these.
    var __slice = [].slice,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
    
    // Define out custom image tool
    var CustomImageTool = (function(_super) {
        __extends(CustomImageTool, _super);
    
        function CustomImageTool() {
          return CustomImageTool.__super__.constructor.apply(this, arguments);
        }
    
        // Register the tool with ContentTools (in this case we overwrite the 
        // default image tool).
        ContentTools.ToolShelf.stow(CustomImageTool, 'image');
    
        // Set the label and icon we'll use 
        CustomImageTool.label = 'Image';
        CustomImageTool.icon = 'image';
    
        CustomImageTool.canApply = function(element, selection) {    
            // So long as there's an image defined we can alwasy insert an image
            return true;
        };
    
        CustomImageTool.apply = function(element, selection, callback) {
    
            // First define a function that we can send the custom media manager
            // when an image is ready to insert.
            function _insertImage(url, width, height) {
                // Once the user has selected an image insert it
    
                // Create the image element
                var image = new ContentEdit.Image({src: url});
    
                // Insert the image
                var insertAt = CustomImageTool._insertAt(element);
                insertAt[0].parent().attach(image, insertAt[1]);
    
                // Set the image as having focus
                image.focus();
    
                // Call the given tool callback
                return callback(true);
    
                window.KCFinder = null;
            }
    
            // Make the new function accessible to your iframe
            window.parent.CustomMediaManager = {_inserImage: _insertImage};
    
            // Hand off to your custom media manager
            //
            // This bit you'll need to figure out for yourself or provide more
            // details about how your media manager works, for example in 
            // KCFinder here we open a new window and point it at the KCFinder
            // browse.php script. In your case you may be looking to insert an
            // iframe element and/or set the src for that iframe. 
            //
            // When the user uploads/selects an image in your media manager you
            // are ready to call the `_insertImage` function defined above. The
            // function is accessed against the iframe parent using:
            //
            //     window.parent.CustomMediaManager._insertImage(url, width, height);
            //
    
        };
    
        return CustomImageTool;
    
    })(ContentTools.Tool);
    

    I hope that provides enough to help you integrate your media manager but if not can you provide more detail on how your media manager works (perhaps an example I can view) and I'll happily try and offer up a more complete solution.