Dijit Diamonds: Focus

By on November 6, 2008 10:59 pm

Lately, a lot has been made of the small and powerful Dojo Base, as a stand-alone JavaScript library that handles the basic needs of most Ajax developers. But recently I’ve been working on a difficult project, and was saved by some brilliant work done in Dijit.

In my project, I’m improving the Table Plugins to work with the new version of the Dijit Editor (not yet released), which is phasing out the iframe dependency. The iframe Editor was difficult to code to, since talking to an iframe is similar to talking to another browser window, introducing the difficulties of the global context of communication. But it also had some benefits. After selecting text in the iframe, and changing focus to the main window, the iframe would remember its selection. The new Editor makes full use of a contenteditable DIV, and I found I had a major issue remembering selections.

To find a solution, I spent hours experimenting with text ranges (W3C & MSDN) and window selections. I had a lot of difficulty getting things to work in Internet Explorer and Firefox, and when I did have the rare success, it wasn’t compatible with the other (we haven’t started tackling Safari or Opera yet for this particular project).

While combing through the Dojo code for an answer, I stumbled upon dijit._base.focus. Two simple but powerful methods: dijit.getBookmark() and dijit.moveToBookmark() saved the (work) day for me. Bookmark is a misleading term, because of the common lexical usage of saving a link to web page. But it’s actually standard DOM terminology which makes sense, and refers to saving a selected position on a page.

Getting back to my problem, when I clicked on a button to execute a command, the selection shifted to that button, and the editor didn’t know where to, for example, place the new table HTML.

Note that the Editor does have a mechanism to handle this: restoreFocus() does basically what I’m about to describe. Why it doesn’t work is both complicated and unclear, but it’s safe to say that this part of the new Editor is unfinished.

The solution was: onblur, save the bookmark; then onfocus, restore the bookmark. My actual implementation in the Table Plugin is not important at this point, as I’m going to show a simple demo of Dijit’s bookmark features.

Here’s the HTML for our test:

First text
My Text is just that. Text .....

It’s purposely layered with multiple elements, as that makes it more challenging to track the selection range.

Now we’ll link to dojo.js, and require Dijit Base. We’ll also add a quick style that allows us to click anywhere on the page (in most browsers, if you don’t set the HTML and/or body to 100% height, they will collapse to a minimum height, like a standard block element.)




Now our code. We’re connecting a mouseup event to the main DOM node, and when triggered, it stores the bookmark of the current selection. It then adds another connection for a click which, when triggered, restores the selection.

dojo.addOnLoad(function(){
	
	dojo.connect(dojo.byId("container"), "onmouseup", this, function(){
		var b = dijit.getBookmark();
		var c = dojo.connect(document.body, "click", function(){
			dijit.moveToBookmark(b);
			dojo.disconnect(c);
		});
	});
});

Select some text, then click off of the text, as you would to deselect it. After the click, the selection reappears.

Visit the Dijit focus test; but because the test is purposefully simple, I also created a Dijit focus demo where you can cycle back and forth through a selection list.

dijit.focus() is just one of the many “diamonds in the rough” in Dijit. I’ll cover more of them in future posts.