Thursday, January 26, 2012

Twitter bootstrap popover doesn't work with click event

We were playing with the Twitter bootstrap javascript library lately,  and found out the popover doesn't play well with 'click' event in Chrome (FF works though).  I tried to find solution on the web, but didn't find what we want or the solution doesn't work. Hopefully this post might provide a solution that can help others.

The way we get around this is to wrap the popover call inside a callback which listen to click.
        // ... probably in your initialize function
        $('my-selector').bind('click', this.showPopover);

        // ... somewhere inside an object
        showPopover: function(e){
            var $popTrigger = $(e.target),
                $closeBtn = $('.popover .close-btn');

            $closeBtn.trigger("click");

            (function(that){
                $popTrigger.popover({
                    html:true,
                    placement:'below',
                    offset:8,
                    trigger:'manual',
                    title:function () {
                        return "Well, title!"
                    },
                    content:function () {
                        return that.getContent();
                    }
                });
            })(this);

            $popTrigger.popover("show");

            $closeBtn.live('click', function(e){
                $popTrigger.popover("hide");
                e.preventDefault();
            });

            e.preventDefault();
        }


You can enhance the code by checking if the elements already have desired events attached, so you don't need to trigger that twice.  And if you are designing a one page app, you may need to add function to  hide/remove the popover when the page context is changing.

Wednesday, January 4, 2012

Another good javascript interview question

I was debugging some Node.js code recently and found a bug that is so obvious but very easy to get that  to creep in if you are not careful enough. The following code is just a sample, not reflecting the real code that I'm working on.

The buggy version
Do you see the problem??  That could be one of the interview questions for my next candidate.  I can think of  three different ways to solve this scope issue, two of them are pretty standard, the other one is more elegant :)  Can you think of at least one?

(function() {
//...
for ( key in MyModules){
    if(MyModules.hasOwnProperty(key)){
        module = MyModules[key];
        // if you're not coming from Node.js, the code 
        // inside will get execute during runtime
        app.get(module.regEx ,function(req,res,next){
            module.router(req,res,next,module.collection); 
        });
    }
}
//...
}());

As a javascript developer, the basic minimal concepts we should know before going into an interview would be "prototype, scope and closure".  Because from those concepts, one can generate different patterns out from them.