Enabling the Image and File Browser/Upload Functionality for FCKeditor
Contents
Problem
I recently had to get FCKeditor working for a PHP based internal wiki. My thinking was that it probably wouldn't be radically different in MoinMoin, so I'll describe what I did with the hope that the techniques I used would be compatible, at least for the most part, with MoinMoin. I did not get every feature working, but the ones that mattered to me.
What I cared about was being able to upload and select the files and images from within the dialog. I didn't care as much that the images were not displayed in the GUI editor. There may be a way to have FCKeditor parse the wiki code for an internal image, but I haven't solved that problem. For my purposes, I had it generate a URL to the document management code that returns the appropriate image or file, so it is a valid URL. That way, the GUI would correctly display it.
The main complications arise because FCKeditor is assuming there is a directory of images or files. Since this isn't the case, we need to do a little redirection.
The examples below are implemented in PHP, since that's what I needed, but they should be adaptable. I can work with someone to translate this to python as needed.
Solution
In order to use custom routines for browsing and uploading files or images, we need to tell FCKeditor where to find these routines. This is done by specifying a Javascript config file:
$oFCKeditor = new FCKeditor($var_name) ; $oFCKeditor->Config['CustomConfigurationsPath'] = '../../editor/editor.js';
That config file would overwrite a number of values relating to the browsers:
FCKConfig.LinkBrowserURL = FCKConfig.BasePath + '../../editor/linkbrowser.html'; FCKConfig.LinkBrowserWindowWidth = FCKConfig.ScreenWidth * 0.5 ; // 50% FCKConfig.LinkBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70% FCKConfig.LinkUploadURL = FCKConfig.BasePath + '../../editor/linkupload.php' ; FCKConfig.ImageBrowserURL = FCKConfig.BasePath + '../../editor/imagebrowser.html'; FCKConfig.ImageBrowserWindowWidth = FCKConfig.ScreenWidth * 0.5 ; // 50% ; FCKConfig.ImageBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70% ; FCKConfig.ImageUploadURL = FCKConfig.BasePath + '../../editor/imageupload.php' ; FCKConfig.ImageUploadAllowedExtensions = ".(jpg|gif|jpeg|png|zip|tar|tar.gz|tgz)$" ;
We'll start with files.
Browsing Files
This file browser is the first place where I use redirection to deal with the nature of the wiki code. The contents are mostly Javascript and serve to redirect the page to a specified URL in the wiki:
<html> <body> <script language="JavaScript"> var current = window.opener.top.opener.top.location.href; var op = current.match('op=([a-z]+)')[1]; var id = current.match('id=([0-9]+)')[1]; var prev = window.opener; window.location.href = '../cms.php?op=' + op + '&' + op + '_op=link_dialog&content_only=yes&id=' + id; window.opener = prev; </script> Loading... </body> </html>
The first step is to identify the current URL. In the case I had, this involved the GET variables op and id. These variables are then used to construct the URL in the wiki that will provide a list of files appropriate for the given wiki page. These files link to a Javascript function:
function SetDialogLinkUrl(url) { window.opener.SetUrl(url); window.close(); }
For example, the wiki list code would look something like:
wiki_show_files($id); echo "<input type='button' value='Cancel' class='Button' onclick='javascript:window.close();' />";
Where the wiki_show_files function simply iterates through the available files and generates a Javascript URL link for each file:
$url = $href_base . "cms.php?op=wiki&wiki_op=get_file&id=$id&name=$file"; echo "<a href='Javascript:SetDialogLinkUrl(\"$url\");'>$file</a><br>";
Note that this code should not display all of the sidebar links and header typically shown in the wiki, but only a list of files. You'll notice that in the initial redirection page, there was a GET variable named content_only that took care of that in my code.
Uploading Files
Uploading files is a little bit easier than browsing them, because we don't need to display anything. The general idea is to capture the uploaded files to a temporary location and then pass that location to a URL which places the files in the appropriate location. There are two sections of code involved, a Javascript function:
<script> function EditorUploadFiles($name, $fullname) { var current = window.top.opener.top.location.href; var op = current.match('op=([a-z]+)')[1]; var id = current.match('id=([0-9]+)')[1]; window.location.href = '../cms.php?op=' + op + '&' + op + '_op=link_upload&content_only=yes&id=' + id + '&name=' + $name + '&fullname=' + $fullname; } </script>
and the PHP code:
$fullname = $_FILES['NewFile']['tmp_name']; $name = $_FILES['NewFile']['name']; $upload_dir = '/tmp/cms_upload_dir'; if ( !is_dir($upload_dir) ) { mkdir($upload_dir,0700); } $file = $upload_dir. "/" . $name; move_uploaded_file($fullname, $file); echo "<script>EditorUploadFiles('$name','$file')</script>"
The URL referenced by the Javascript function just moves the files in the same way as the non-FCKeditor upload function does.
Browsing and Uploading Images
The code for browsing and uploading images is essentially the same as that for files, especially for MoinMoin. The listing function may just want to limit the listed files to one of the appropriate extensions.
Discussion
There are a couple of issues remaining. The standard MoinMoin markup for an image will not be recognizable to FCKeditor, so the preview and GUI will not show the image. It will still facilitate the uploading and browsing/selecting of images, however.
The obvious question is whether or not this approach works with MoinMoin/Python. I don't see why not, especially considering much of it is Javascript. You might also consider the above solution to be an abomination. If so, you are obviously free to ignore it. - G. Bach <glenn AT caltech DOT edu>