Wednesday, January 20, 2010

Django FileBrowser and MarkItUp

What I wanted to do was override the default action for the insert Picture in the markItUp edditor with the FileBrowser manager popup, and have the image selection flow back into the edditor.

Thats right, it will be a nerdy post.

I used django-filebrowser 3 without grappelli found here:
http://code.google.com/p/django-filebrowser/source/browse/#svn/branches/filebrowser3-no-grappelli

First I changed the sets.js, which defines your settings (in JSON).

I copied the markitup/sets/textile folder to my own js folder and added the MARKITUP_SETS to my settings.py to point to the new location. Check the django-markitup docs for more about settings.

After that I changed the "sets.js" file to this:

mySettings = {
 previewParserPath: '/markitup/preview/',
 onShiftEnter:  {keepDefault:false, replaceWith:'\n\n'},
 markupSet: [
        ... snip ...
     {name:'Picture', replaceWith: function(markItUp) {
         FileBrowserHelper.show(markItUp);
         return false;
  }},
        ... snip ...
 ]
}

/**
I added the FileBrowserHelper object so that it can store the original markitup
object that fired the event / popup, so that I can use it when trying to return 
to the edittor.
**/
var FileBrowserHelper = {
    markItUp: false,

    show: function(markItUp) {
        this.markItUp = markItUp
        var textarea_id = $(markItUp.textarea).attr('id');
        FileBrowser.show(textarea_id, '/admin/filebrowser/browse/?pop=1&type=');
    },
    
    triggerInsert: function(url) {
        $(this.markItUp.textarea).trigger('insertion', 
            [{replaceWith: '!(left)'+url+'(beschrijving)!'}]);
    }
};

I used Mark Story's story for inspiration.

The problem I had was that the code which does the roundtrip for the default FileBrowserField does not support a textarea. So I had to create a seperate piece of code and override the template which handles the file selection view (filebrowser/templates/index.html) and change the default FB_FileBrowserField.js for my own.

I changed this (original):

    ... snip ...
    {% ifequal query.pop '1' %} <!-- FileBrowseField -->
    <script language="javascript" type="text/javascript" 
      src="{{ settings_var.URL_FILEBROWSER_MEDIA }}js/FB_FileBrowseField.js">
    </script>
    {% endifequal %}
    ... snip ...


For this (my filebrowser/templates/index.html):

    ... snip ...
    {% ifequal query.pop '1' %} <!-- FileBrowseField -->
    <script language="javascript" type="text/javascript" 
      src="{{ settings_var.MEDIA_URL }}js/filebrowser/FB_FileBrowseField.js">
    </script>
    {% endifequal %}
    ... snip ...


Next I copied the FB_FileBrowseField.js and placed it in my own js directory. I changed the FileSubmit method to the following code so that it triggers the right event and injects your image into the textarea on the position of your cursor:

function FileSubmit(FileURL, ThumbURL, FileType) {
    
    // var input_id=window.name.split("___").join(".");
    var input_id=window.name.replace(/____/g,'-').split("___").join(".");
    var preview_id = 'image_' + input_id;
    var link_id = 'link_' + input_id;
    var help_id = 'help_' + input_id;
    input = opener.document.getElementById(input_id);
    preview = opener.document.getElementById(preview_id);
    link = opener.document.getElementById(link_id);
    help = opener.document.getElementById(help_id);
    // set new value for input field
    
    if(input.type == "textarea") {
        
        opener.FileBrowserHelper.triggerInsert(FileURL);
        
    } else {
    
        input.value = FileURL;
        
        if (ThumbURL && FileType != "") {
            // selected file is an image and thumbnail is available:
            // display the preview-image (thumbnail)
            // link the preview-image to the original image
            link.setAttribute("href", FileURL);
            link.setAttribute("target", "_blank");
            preview.setAttribute("src", ThumbURL);
            help.setAttribute("style", "display:block");
        } else {
            // hide preview elements
            link.setAttribute("href", "");
            link.setAttribute("target", "");
            preview.setAttribute("src", "");
            help.setAttribute("style", "display:none");
        }
    }
    this.close();
}

And that's that really.

3 comments:

Matt Ots said...

I tried this, but get a javascript error on the 6th line of the FileBrowserHelper object: 'FileBrowser is not defined'. What object is this referencing and where?

Matt Ots said...
This comment has been removed by the author.
Matt Ots said...

Solved it! There were a few more steps involved that weren't documented here, but I guess as this was written 2 years ago the version of FileBrowser and MarkItUp I'm using will probably be different.