Tuesday, October 17, 2006

 

Extending dojo.widget.Tooltip

I have been playing with Dojo for past few weeks (since we are using it for AJAX stuff at BlogScope). While it is a nice library, many parts are not well documented. One such area is extending widgets to add to their functionality. Tooltip is a good example of widget that requires improvement, since it does not provide an option to have some custom text displayed while the contents of tooltip are being fetched. For BlogScope, I wanted to have an loading icon displayed while the tooltip is being fetched in background. This article explains the code that I am using for this purpose. Note: I am no Dojo guru. This code may not be the best way to do this, but it works.

Demo: We have a demo page displaying the extended tooltip. This demo page also has javascript to resize the tooltip to specified max-height and max-width. While CSS can be used for max-height and max-width, to make it work in IE, javascript is required. View source of the demo page to get the complete javascript code.

Below is the HTML code for the tooltip. There are three main components. One is the link (with id=one), mouseover on which displays the tooltip. Second is the div element with dojoType="PostTooltip", which specifies the url from where contents of tooltip are to be fetched. Third component is the div block (id=two) that is the tooltip itself. After the contents are being fetched, innerHTML of this div block is updated.

<a href="some-page" id="one">bring your mouse here</a>
<div dojoType="PostTooltip" style="display:none;"
    dojo:connectId="one"
    dojo:uniqId="two"
    dojo:contentUrl="tooltip.php?id=two"
    dojo:executeScripts="true"
    >
    <div id="two" style="background-color: white; border: 1px dashed #aaaaaa;">
            this is a custom loading message.
    </div>
</div>

Below is the code for fetching the contents of tooltip and adjusting its dimensions. uniqId is the id of div block for the tooltip. Since the mimetype is text/javascript, the fetched contents must be a javascript source which when executed updates the innerHTML of tooltip's div block (something like document.getElementById(uniqId).innerHTML = 'This is the new content';).

function updatePostTooltip(postUrl, uniqId) {
        dojo.io.bind({
            url: postUrl,
            load: function(type, evalObject){
                dojo.debug("data received from "+postUrl);
                adjustPostTooltipDimensions(uniqId);
            },
            mimetype: "text/javascript"
        });
}

function adjustPostTooltipDimensions(uniqId) {
        var sHeight = document.getElementById(uniqId).scrollHeight;
        var sWidth = document.getElementById(uniqId).scrollWidth;
        var maxHeight = 450;
        var maxWidth = 480;
        dojo.debug("height and width are "+sHeight+" and "+sWidth+" for "+uniqId);
        if (sHeight > maxHeight) {
                dojo.debug("resizing to max height "+maxHeight);
                document.getElementById(uniqId).style.height = maxHeight + "px";
                document.getElementById(uniqId).style.overflow = "auto";
        }
        if (sWidth > maxWidth) {
                dojo.debug("resizing to max width "+maxWidth);
                document.getElementById(uniqId).style.width = maxWidth + "px";
                document.getElementById(uniqId).style.overflow = "auto";
        }
    }

And finally below is the code for extended Tooltip widget.

dojo.provide("my.widget.PostTooltip");
    dojo.widget.manager.registerWidgetPackage("my.widget");

    dojo.widget.defineWidget(
        "my.widget.PostTooltip",
        dojo.widget.html.Tooltip,
        {
                //we have added three new variables, uniqId, contentUrl and hasContents
                uniqId: "",
                contentUrl: "",
                hasContents: 0,
                //We modify this function from the original in dojo.widget.html.Tooltip
                onShow: function() {
                        // copied as is from dojo/src/widget/html/Tooltip.js
                        dojo.widget.html.Tooltip.superclass.onShow.call(this);
                        this.state="displayed";
                        if(this.eraseScheduled){
                                this.hide();
                                this.eraseScheduled=false;
                        }
                        //end of copied code
                        //this is our code
                        if (this.hasContents == 0) {
                                updatePostTooltip(this.contentUrl, this.uniqId);
                                this.hasContents = 1;
                        }
                }
        }
    );

This page is powered by Blogger. Isn't yours?