Blog

2011-06-20 01:12:52

TinyMCE Media Library Integration

To integrate a media library with TinyMCE, the first place to start is by adding some buttons to the editor. You can do this by providing a 'setup' function in your TinyMCE initialisation parameters, something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tinyMCE.init({

    // ... stuff ...

    setup : function(ed)
    {
        try
        {
            setupEditorExtensions(ed);
        }
        catch(error)
        {
        }
    }
});

setupEditorExtensions is a function you define which should exist in a javascript file that is linked (included) by the page that contains the TinyMCE editor instance. As you can guess from the name, it sets up the extensions for the editor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function setupEditorExtensions(ed)
{
    // add a custom button
    ed.addButton('insertMediaBtn',
    {
        class: 'custom-mce-btn',
        title : 'Insert/Edit Media',
        image : '/img/insertMediaBtn.png',
        onclick : function()
        {
            openMediaDialog();
        }
    });
    // add another custom button
    ed.addButton('increaseHeightBtn',
    {
        class: 'custom-mce-btn',
        title : 'Increase Height',
        image : '/img/increaseHeightBtn.png',
        onclick : function()
        {
            toggleEditorHeight();
        }
    });        
    // add another custom button
    ed.addButton('highlightCodeBtn',
    {
        class: 'custom-mce-btn',
        title : 'Highlight Code',
        image : '/img/highlightCodeBtn.png',
        onclick : function()
        {
            openHighlightCodeDialog();
        }
    });        
}

Each button is given a unique name, title, image and onclick handler. The handler for the media library button in this case has two functions;

  • If an image is selected in the editor, it'll open an 'Edit Media' dialog where you can change how the image looks (size, position etc)
  • If there isn't an image selected, itll open the 'Insert Media' dialog where you can browse a media library and click on an image to insert it

This switch is hidden away in the openMediaDialog function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
function openMediaDialog()
{    
    var selectedText = tinyMCE.activeEditor.selection.getContent();
       
    var pattern = /]+>/;
    pattern.compile(pattern);

    if(pattern.test(selectedText))
    {
        // parse parameters from image url
        var imgWidth = -1;
        var imgHeight = -1;
        var imgSrc = '';
        var imgMode = '';
       
           var srcAttrPattern = /src="([^"]+)"/;
           var classAttrPattern = /class="([^"]+)"/;          
           
        var srcPatternMatches = selectedText.match(srcAttrPattern);          
        if(srcPatternMatches.length < 2)
        {
            return;
        }
       
        var imgURL = srcPatternMatches[1];

        // class attr isnt required
        var classPatternMatches = selectedText.match(classAttrPattern);                  
        var imgClass = '';
        if(classPatternMatches != null)
        {
            if(classPatternMatches.length > 1)
            {
                imgClass = classPatternMatches[1];          
            }
        }
               
        var urlParams = imgURL.split('&');
       
        if(urlParams.length > 1 && urlParams[0] == '/media/render')
       
        for(var urlParam in urlParams)
        {                
            var urlParamParts = urlParams[urlParam].split('=');
           
            if(urlParamParts.length > 1)
            {
                var key = urlParamParts[0];
                var value = urlParamParts[1];            
               
                switch(key)
                {
                case 'name':
                    imgSrc = value;
                    break;
                case 'width':
                    imgWidth = value;
                    break;
                case 'height':
                    imgHeight = value;
                    break;
                case 'mode':
                    imgMode = value;
                    break;
                }
            }    
        }        
       
        var dialogHTML = '';

        $.get("/media/ajax&renderPage=edit",
        {
            name: imgSrc,
            width: imgWidth,
            height: imgHeight,
            mode: imgMode,
            class: imgClass
        },
        function(data)
        {
            // populate dialog controls
            $editMediaDialog.html(data);
            // open image editor dialog
            $editMediaDialog.dialog('open');            
        });        
    }
    else
    {
        var mediaLibraryURL = '/media/ajax&renderPage=library';
        $('#mediaLibraryFrame').attr('src', mediaLibraryURL);
        $('#mediaLibraryFrame').load(function()
        {
            $dialog.dialog('open');
            resizeMediaLibraryFrame();
        });
    }
}

This function serves only as an example and needs to be cleaned up - but basically what it does is check the the selected text in the editor to see if it matches against a regular expression for img tags (of a certain format). If it does match, the 'Edit Media' dialog is shown - if it doesnt match, the 'Insert Media'' dialog is shown.

The block of code before the line that opens the edit media dialog strips out the parameters in the img source url which is used to populate the dialog controls. The block of code before the line that opens the insert media dialog loads an iframe with the media library inside, and waits for the load to complete before opening the dialog.

I leave it as an exercise for the reader to implement the dialogs :)