Showing posts with label wmd-editor. Show all posts
Showing posts with label wmd-editor. Show all posts

Monday, November 23, 2009

WMD Editor & jQuery

I've been using Dana Robinson's WMD Editor fork for a couple of months now. It was a great place to start. The problem is, it's becoming a real pain to customize. Small things were taking huge amounts of time to accomplish so I had a tough decision to make: Continue to use WMD Editor and have to spend hours for customization that should only take a minute or two -OR- re-write the UI myself on top of the existing Markdown rendering component?

Introducing: MarkEdit -- the Javascript MarkDown editor built on jQuery (to replace WMD Editor). It's currently being hosted on BitBucket.

  • Built On jQuery/UI -- Lighter weight code and less cross-browser issues
  • Themeroller Support -- Use existing or custom jQuery UI Themeroller themes
  • International -- Supports the loading of an alternate language
  • Sensible Defaults -- You should be able to get up and running with 1 line of javascript
  • Configurable -- Almost all defaults can be overridden very easily upon initialization
  • Public API -- Interact with whatever part you're interested in
  • Documented

Since everybody loves screenshots, here's the editor running under a jQuery theme and using the Chinese language translation.





And again here's a translated popup asking for the URL to insert an image...




And here's preview mode using a different theme but still in Chinese...




So far I've invested about 15 hours into the project with it being probably around 95% complete for initial coding. There is still a TON of testing to be done. I haven't even tried to fire it up in any of the fussy browsers yet.

I actually wrote a whole lot about it so far -- it's all up on the Wiki. There is still lots more documentation to come.

Thursday, October 1, 2009

Hacking wmd-editor into using a custom image gallery

Oh man, I feel accomplished. I just finished hacking wmd editor to use a custom image gallery being generated server-side.

If you don't know, WMD editor is a WYSIWYG editor written in Javascript.
Photobucket

By default, when you click on the 'Insert Image' button you get a prompt allowing you to enter a URL.

Insert Image Screen
Photobucket

The functionality I was looking for was instead of showing you a text box where you could paste in the URL, I wanted to see more of a gallery type interface, that showed media that both you and others had uploaded. I also wanted to have a system where multiple files could be uploaded at once, and multiple files could be inserted at once.

There were primarily two challenges in attempting to accomplish that plan:

  • The WMD editor code doesn't really come with documentation. There are a handful of in-line comments and that's all you get. For the most part, I ignored them and read the code instead.
  • The WMD editor code is a little strange in areas.
Modifying WMD Editor
For the most part, I ended up not needing to change really all that much code. WMD editor is odd, yes, but workable.

The first task was to replace the default prompt function, with my own....
command.doLinkOrImage = function(chunk, postProcessing, isImage){

// ...

if (isImage) {
// OLD: util.prompt(imageDialogText, imageDefaultText, makeLinkMarkdown);
// WMD_IMAGE_GALLERY_URL loaded from a global settings elsewhere
util.imageGallery(WMD_IMAGE_GALLERY_URL, makeLinkMarkdown);
}
else {
util.prompt(linkDialogText, linkDefaultText, makeLinkMarkdown);
}
}

This was an easy change, and allowed to to write a pretty much drop-in replacement for util.promt().

This particular bit of code is jQuery-specific. It uses a div already existing on the page, #wmd-media-gallery, and applies jQuery UI's $.dialog() method to it, converted it into a popup modal dialog. The contents of the dialog is then loaded by AJAX. The URL that is loads is being specified in a global variable that is passed to it (WMD_IMAGE_GALLERY_URL).

util.imageGallery = function(gallery_url, makeLinkFunction){
gallery = $('#wmd-media-gallery');

if (gallery.html()) {
gallery.dialog('open');
}
else {
gallery.css('visibility', 'visible');
gallery.load(gallery_url, function(){
gallery.dialog({
title: 'Media Gallery',
bgiframe: true,
height: 550,
width: 900,
modal: true,
buttons: {
'Insert': function(){
// Enumerate images; insert those checked.
$('#wmd-media-gallery .media-insert').each(function(){
if ($(this).is(':checked')) {
img_path = $(this).attr('rel');
console.log(img_path);
makeLinkFunction(img_path);
}
});
$(this).dialog('close');
},
'Cancel': function() {$(this).dialog('close'); }
}
});
});
}
};

Pretty simple so far, right?

Well, here's the tricky part. If you notice what happens when the 'Insert' button is clicked, the code will scan the HTML of the dialog, and look for any input:checked element that has class "media-insert". For those elements which are found, it searches for ones which are checked. If a checked item is found, it will grab the Image URL out of the rel="" attribute, and pass that back to WMD editor for insertion into the edit box.

Ah, but not so fast. The problem comes in that WMD editor was not originally written to insert multiple images in such a way. With the stock code, what happens is it will inset one image inside another, thus only rendering 1 image properly, and leaving a mish-mash of code around it.

It should render this:
![alt text][1]
![alt text][2]

[1]: /some/url.jpg
[2]: /some/image.jpg
What it was rendering was this:
![alt text![alt text][1]][1]
The particular code in question lies int he command.addLinkDef() function. What needs to happen is that before that function processes the 'chunk', it must first clear the settings from the previous image out of it.

var getLink = function(wholeMatch, link, id, end){
// ...
};

// This goes after the getLink function

if (chunk.after.substring(0,2) == "][") {
chunk.before += chunk.selection + chunk.after.substring(0,2);
chunk.after = chunk.after.substring(2);
var linkEnd = chunk.after.indexOf(']');
linkEnd++;

chunk.before += chunk.after.substring(0, linkEnd);
chunk.selection = "";
chunk.after = chunk.after.substring(linkEnd + 1);
}

// ...and before the chunk.before [...] code

chunk.before = chunk.before.replace(regex, getLink);

And there you have it, you can now run custom image galleries from WMD editor. I'll leave it up to your imagination as to what you can do with that, but here's what mine ended up looking like:

Editor Window

Photobucket


Inserted Image
Photobucket

If you noticed, the django-uploadify app is being used in the gallery (hence why I began working on it).

  © Blogger template 'Minimalist G' by Ourblogtemplates.com 2008

Back to TOP