jsvi and TiddlyWiki
When adding posts to my TiddlyWiki, I oft found myself craving vi, rather than a simple textarea. There were a few options that involved using a plugin for Firefox such as mozEx, and using an external program to edit textareas. However, I found a nice ‘integrated’ option instead.
jsvi is an excellent javascript implementation of vi. I decided to try and integrate it into my TiddlyWiki, and the steps I took are shown below. To try out the final result, use the edit mode on my wiki.
Be warned: this is a bit of a dirty hack, and requires a few files external to the TiddlyWiki file, which makes TiddlyWiki a bit less portable. At some point it’d be nice if this was build as a TiddlyWiki plugin instead, but at the minute I’m not experienced enough with writing plugins for TW. There is also a slight bug which means you can’t scroll up while editing.
First of all, I installed the iFrameEditorPlugin from an old version of the VisualTW site. I don’t think VisualTW uses the plugin anymore, and has instead changed it’s wysiwig editors to using plugins rather than iFrames - a far superior solution, but one I didn’t have the time or ability for. The plugin alone is not quite enough though, and a few changes to it are required.
iFrameEditorPlugin loads an iFrame containing your editor, passes the editor the text from the body of the tiddler, you edit it, and then when you save the page, the plugin gets your changes and saves them to the tiddler. However, it expects you to use a custom field rather than the default text field, which is a slight problem in our case. The function getContent() is what actually performs this:
getContent=function(tiddler, field) {
var t,f;
t=store.getTiddler(tiddler);
f = t ? t.fields[field] : “”;
f = f ? f : “”;
return f;
}
As you can see, it reads the field of the tiddler with t.fields[field]. To read the default text field instead, I added a new function to the plugin:
getContentText=function(tiddler) {
var t,f;
t=store.getTiddler(tiddler);
f = t ? t.text : "";
f = f ? f : "";
return f;
}
Great. So that’s set up. There’s also another problem with the plugin - it was originally intended for use with wysiwig html style editors, but I enjoy editing my wiki content raw. Also, the content has to be passed in a URL to the editor, so strange characters in the URL will mess it up, so there were problem with escaping html entities and things like that. To get around this, I found a handy javascript function that converted html entities back to their original form, and added this to the top of the plugin (thanks to The JavaScript Source):
/* This script and many more are available free online at
The JavaScript Source!! http://javascript.internet.com
Created by: Ultimater | http://webdeveloper.com/forum/member.php?u=30185 */
function html_entity_decode(str) {
var ta=document.createElement("textarea");
ta.innerHTML=str.replace(/</g,"<").replace(/>/g,">");
return ta.value;
}
Ok, now we actually have to use this function, so we edit the plugin a bit more. Look for the line that reads the data back from the iFrame:
if(f) fields[f] = e.contentWindow.getContent();
and change it to:
if(f) fields[f] = html_entity_decode(e.contentWindow.getContent());
The plugin is all ready to go now, so we have to make the actual external editor that’s gonna go in the iFrame, using jsvi. Download these three files, and put them in the same folder as your TiddlyWiki html file.
The first two are the actual jsvi javascript file and it’s style sheet, the second is my own editor iFrame. Let’s have a look at the important lines of the editor.html file:
<script type="text/javascript" src="vi.js"></script>
This includes the jsvi javascript file.
<textarea style="width: 99%" name="theEditor" onfocus="editor(this);"> </textarea>
This builds the actual textarea that’s gonna be edited by jsvi. Ok, now the javascript “meat” of the page:
var oEditor = document.getElementsByName('theEditor')[0];
function getContent() {return oEditor.value;}
tiddlers=/[\\?&]tiddler=([^&#]*)/.exec(unescape(window.location.href));
fields=/[\\?&]field=([^&#]*)/.exec(unescape(window.location.href));
if (tiddlers&&fields) oEditor.value = parent.getContentText(tiddlers[1]);
oEditor.focus();
All that happens here is we write the getContent() function that the iFrameEditorPlugin calls to read your changes. The tiddlers line reads the URL to get which tiddler you’re editing, and the fields line does the same for the field (actually this isn’t even necessary with our getContentText() function). The last two lines read the tiddler’s content, so we can edit it, and set the focus to the textarea to launch jsvi automatically when the iFrame loads.
That’s everything setup now, so all we need to do is tell Tiddlywiki when we want to make our edits with the iFrameEditor instead of with it’s default text field. I made a plugin (based on code from VisualTW’s EasyEditPlugin - thanks a lot!). You can view the plugin here. Hopefully it should add a ‘vi’ button next to the edit button on each tiddler. If no button appears, add ‘jsvi’ to the first line of the ViewTemplate tiddler to look like this:
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler jsvi > fields syncing ....
To make jsvi the default, remove the + from in front of editTiddler and put it in front of jsvi.
Now when you press the vi button, you should be presented with a rather gorgeous vi interface! One note, when you’re done editing a tiddler with jsvi, you must save it using the usual vi write command, :w, or press the “Save and Close” button. Otherwise the textarea does not get updated, and the iFrameEditorPlugin cannot read your changes. Also beware editing config shadow tiddlers with jsvi, as the line “macro=stuff” in some of the tooldbars etc. is interpreted by jsvi as it’s own command and it can end up destroying certain things.
Update: I found a small problem with focusing using this in Firefox (didn’t test in other platforms) - after editing a post I was unable to select other fields and items in the window. This was fixed by changing one line in the vi.js file, line 3588, which needs to be uncommented (the comment line before even refers to a bug in Firefox, possibly in an older version?) to look like this:
document.body.removeChild(backing);
Now it should work perfectly, apart from a few kinks: being able to edit the tiddler title the first time jsvi launches. Save and close vi, and it’s editable again, and still editable when you relaunch jsvi by clicking on the text area. If you cant get focus back on jsvi, right click it.
Hope you enjoy this as much as I do, and hopefully at some point soon when I have a bit more free time, I’ll have it in plugin format so it’s all incorporated into TW. Any problems, leave a comment and I’ll try and get back to you.

[...] actionshrimp.com ยป jsvi and TiddlyWiki Dave Aitken has done a beautiful integrated a version of the venerable Vi command-line editor with TiddlyWiki (tags: tiddlywiki actionshrimp daveaitken jsvi vi webdev) Posted by jermolene Filed in Uncategorized [...]
TiddlyWiki = jsvi…
TiddlyWiki = jsvi…
marvellous(manifold) plot. So to authority!