Monthly Archives: October 2012

Dynamic tooltip using JQuery Ajax and JQuery Tools

At work, the application has been suffering from the performance hit. After the investigation, we found the cause. It was the logic that loads additional object summary information from the DB and set title attributes of dynamic table cell via Ajax call. I want to load the tooltip information on demand when mouse over happens. I’d like to share the road blocks and solution from this implementation. Below screen shot is the Tooltip. I hide business specific information.

Issue

Performance hit when tooltip content is generated at the same time the table data is created.

Road Blocks

  1. Dynamic Table : When page load, send Ajax request to retrieve table data and dynamically populate. No HTML source code for the table.
  2. Object structure : Object has a collection as an attribute. Ajax table needs to display at the collection level. Object ID is not unique.
  3. jQuery Plugin for Tooltip : For the tooltip, I am using jQuery plugin – Tools tooltip. No detail API document.
  4. Dynamic binding : Mouse over sends Ajax request for the content and tooltip content needs to be updated dynamically.
  5. Delay Ajax request : Users can put their mouse over the id, but they may not want to see the tooltip. Another words, I don’t want multiple Ajax requests keep firing whenever mouse over happens.
  6. Prevent multiple Ajax request : No need to send Ajax request if the content is already retrieved and updated. Also, as a part of the solution caused multiple Ajax request firing issue.

Solution

Assign Unique ID & row number : The key was to assign unique ID and row number in TR tag. This information needs to be passed in from the server, so when JSON object is made, I have to populate object ID concatenated with collection index as a unique ID in the TR tag, so I can identify the element correctly. Row number is also important because I need to access default tooltip title to see if tooltip content is updated from the server or not.

Accessing cell.title : This was the key to the solution. Even though cell.title was populated with default value, accessing from DOM element is tricky. I thought I was able to access by using this.title, but it came back with undefined object. Because title is not a part of TR tag attribute, the tooltip uses next element after .tip classname is used as tooltip. Couldn’t find detail API regarding this.

In order to access tooltip content, I need to know the row number where mouse over happens and getTip() function that belongs to the tooltip.

$( $( ‘.tips’ )[rowIndex] ).tooltip().getTip()[0].innerHTML

Above line returns the cell.title content.

Delaying Ajax call : Another challenge that I have is that users typically scroll up and down the rows in the table, so their mouse over action may trigger multiple Ajax request, which I don’t want. I want to control user’s behavior by set mouse over the cell at least 2 seconds, so users can distinguish casual mouse over versus displaying  a tooltip. I used setTimeout() method to to delay the Ajax call. I was able to find the logic from the internet.

Dynamic binding : After successful Ajax request/response, I was not able to refresh the tooltip. It still shows the default content. I need a event after retrieve the content of tooltip. jQuery has .on() and .live(). The .live() is deprecated and used under 1.7 version.

Prevent multiple Ajax requests : After implement all above, I found that somehow Ajax request fires multiple times. Some people suggested that I use .dead() before .live(), but I did a simple approach. I used event.handled check before Ajax request. Also, check the default content if it is already updated. Good resource here.

Table Population

 var cell = row.insertCell(0);
 cell.align = "left";
 cell.className = "tips";
 cell.innerHTML = object.objectId;
 cell.id = object.objectStringId;
 cell.abbr = i;
 cell.title = "Please don't move your cursor to load the details.";

Tools Tooltip

$( '.tips' ).tooltip( {
      position: "center right",
      effect: 'fade',
      opacity: 0.8
    } ).dynamic( { bottom: { direction: 'down', bounce: true } } );

Dynamic content retrieval

    var pendingCall = { timeStamp: null, procID: null };
    var objectid;
    var rowIndex;

    jQuery( '.tips' ).live( 'mouseenter', function( e )
    {
      e.preventDefault();
      var timeStamp = new Date();
      objectid = this.id;
      rowIndex = this.abbr;

      var toolTipCall = function()
      {
        if ( $( $( '.tips' )[rowIndex] ).tooltip().getTip()[0].innerHTML 
            == "Please don't move your cursor to load the details." )
        {
          if ( e.handled != true )
          {
            $.ajax( {
              url: servletUrl,
              dataType : 'json',
              type : 'POST',
              data: {
                Action : "<%=AjaxActionHelper.RETRIEVE_TOOL_TIP%>",
                MouseOverId : objectid
              },
              cache: false,
              success : function( data )
              {
                if ( pendingCall.timeStamp != timeStamp )
                {
                  return false;
                }
                $( $( '.tips' )[data.row] ).tooltip().getTip()[0].innerHTML 
                  = data.summaryToolTip;
                pendingCall.procID = null;
              }
            } );//end ajax

            e.handled = true;
          }
          return false;
        }
      };
      if ( pendingCall.procID )
      {
        clearTimeout( pendingCall.procID )
      }
      //set the time before call 3000 = 3 seconds
      pendingCall = { timeStamp: timeStamp, procID: setTimeout( toolTipCall, 3000 ) };
    } );//mouseover

Conclusion

Debugging Javascript is not easy thing to do unless you have a proper tool. I used FireBug to debug the code which helped me a lot and it gave me an opportunity to understand what’s happening underneath. Also, understanding DOM object tree is important knowledge to reach the goal. I wonder how Coffee Script or TypeScript can help me in terms of resolving this kind of issues…

Advertisements

MMOST – Mind Map Organic Study Technique

Interesting topic, isn’t it? I have been reading Tony Buzan‘s Mind Map books in last few years, but haven’t actively use the techniques that he suggested in his books. Recently, I read a book about Mind Map Organic Study Technique (MMOST). The reason why I was particularly interested in this technique was that it makes me believe the technique will save me great time and effort and  maximize the effects.

Here are the steps of MMOST.

In the big picture, the whole process consists of two phase : Preparation and Application.

Preparation

  1. Browse : Spend about 10 minutes to go through the book as if you are skimming through a book at a bookstore. The goal is to “Feel” for how book is organized by noting its structure, layout, use of diagram.
  2. Budget Time and Amount : Spend 5 minutes to plan how much time you’d spend and amount of data (text) that you’d study. Usually, I am having a hard time to budget my time and amount because naturally you want to accomplish everything that you need/must accomplish. However, without having this step, it will likely demoralize me and eventually nothing get accomplished (from my own experience….).
  3. Mind Map What You Know : Spend 5 minutes or so and do a quick mind map what you know. This step makes your brain to be ready for the learning. Also, I personally think that this can be act as the “Hook” for the new learning.
  4. Questions and Goal : Spend 10 minutes to do another mind map. This will let you measure if you accomplish your goal or not. Also, I personally think this works as “Hook” from the other side. Above “Hook” will help you to connect to existing knowledge and this “Hook” will help you to grab new knowledge.

Preparation : 30 minutes.

Application

  1. Overview : Read headlines, graphics, pictures, diagram, and tables. Don’t read any text. The objective of this phase is to stimulate “Feeling” memory in the brain. By going through this step, you will have a central image of the mind map that you will create at the end of the learning.
  2. Preview : Now beginning to focus on the language structure. Focus on the begging and end of the paragraphs and chapters. Look for the summary or conclusion. The important thing is that you don’t need to read ALL contents. The goal should be to focus on the “Goal” that you set in the Preparation Step 4, so you are in a good position to select or reject the information that you do not need to know.
  3. Inview : Start filling the gaps. It depends on the “Goal” that you set. You can skip this part if you accomplish the goal. Later you set another goal and you can still reiterate the steps.
  4. Continuing Review : Redraw the map. A day later and compare with your original map. If the topic is really important, re-draw it in one week, one month, and one year.
  5. Next step : In my opinion, write something in blog will re-enforce your learning. With the mind map and blog, the learning will stay longer.

The MMOST is very useful technique to learn, understand, and remember new information. Even though I understand and agree all the benefits, often time I find myself reading books without applying this technique. Because of this reason, I am writing this blog post. I want to reiterate the importance and benefit of the MMOST to myself and want to apply this technique more often for all my learning in the future.