Monthly Archives August 2013

ZK + TimelineJS + JQuery = Visualizing Business Data Along The Time Dimension : Part Two

Posted by admin on August 13, 2013  /   Posted in BI and Custom Development, Business, Web Development, ZK

by Cancan Gunadi

In our previous blog, Visualizing Business Data Along The Time Dimension, we have shown one of the ways to visualize business data along the time dimension in a meaningful and engaging way.

In this blog, we’ll show you the technical detail behind the implementation. We used TimelineJS, an interactive web-based timeline tool, and integrated it into the system that we’re building for our client. The system itself is built using ZK Framework.

First, in case you haven’t already, you can visit the actual Live Demo of this timeline on our server here (log on using the provided credential).

We assume some familiarities with the ZK Framework and TimelineJS libraries. We recommend you to visit their respective documentations.

Detail

The timeline area is contained inside a ZK iframe tag inside one of the ZK .zul file as such:

<window id="mainWin" apply="${mainCtrl}">
    ...
    <iframe id="iframe" src="jsp/timeline.jsp>
    

The iframe loads a JSP file which contains the TimelineJS script which is shown below. Some of the details of the JSP and zul file have been removed for the sake of simplicity.

// normal JSP import stuffs... here...

<head>
   <!-- jQuery -->
   <script type="text/javascript" src="../timelinelib/jquery-min.js"></script>
   <!-- BEGIN TimelineJS -->
   <script type="text/javascript" src="../timelinejs/storyjs-embed.js"></script>

   <script type="text/javascript">
       $(document).ready(function() {
       <% if (docs != null && docs.size() > 0) { %>
           var dataObject = 
                
           {
               "timeline":
               {
                   "headline":"Progress Info",
                   "type":"default",
                   "text":"<%= user.getFullName() %>",
                   <% if (startDate != null) { %>
                   "startDate":"<%=Util.formatDateTimeline(startDate)%>",
                   <% } %>
                   "date": [  
                   <%for (Document doc : docs) {%>
            
                       {
                           "startDate":"<%= doc.getDate() %>",
                           "headline":
                              "<a class='timeline-doc-link' 
                                  doc_id='<%= doc.getId() %>' 
                                  href='#'><%= doc.getTitle() %></a>",
                           "text":"<%= doc.getText() %>",
                           "asset":
                           {
                               "media":"",
                               "credit":"",
                               "caption":""
                           }
                       },
                   <% } %>            

        
                   ]
               }
           };

           createStoryJS({
               type:       'timeline',       
               source:     dataObject,
               embed_id:   'timelineContainer',
               font:       'Arvo-PTSans',
               start_at_end: true,
           });
           
           // div with id "timelineContainer" is the div that wraps 
           // around the entire timeline area, defined in the <body>
           // section.
           $('div#timelineContainer').click(function(event) {
               var clickedElem = 
                   document.elementFromPoint(event.pageX, event.pageY);
               if (clickedElem.nodeName == 'A' 
                       && clickedElem.className == 'timeline-doc-link') {
                   
                   // parent is [object Window] according to firebug
                   parent.zAu.send(
                      new parent.zk.Event(
                         parent.zk.Widget.$('$mainWin'), 
                         "onDocRequestedFromIframe", 
                         clickedElem.getAttribute('doc_id')));
               }
               
               return event;
           });
    
       <% } else { // if no item to be shown ... %>

           $('div#timelineContainer').html(
               '<span style="font-size:75%;color:grey;">
               No progress information submitted yet.</span>');

       <% } %>    
       });


    </script>
        
       
    <!-- END TimelineJS -->
</head>

<body>  
    <div id="timelineContainer"></div>
</body>

Line 12-53 of the JSP is the TimelineJS script which is dynamically generated using the JSP scriplet for-loop (line 24) to insert the available items (or “documents” in this case) into the timeline.

Making the Timeline More Useful

To make the timeline more useful, hyperlinks were added to the timeline, which can be clicked to open new ZK Tabs containing the detail of the timeline item. To achieve this, the javascript code in the timeline script needs to be able to send an event to the enclosing ZK container so the ZK application can respond and open a new ZK Tab.

Line 28-31 shows the <a> element which is tagged with a CSS class “timeline-doc-link” and a custom attribute “doc-id” which contains the id of the document.

On line 58-73, JQuery code is used to add a click handler to the “div” element with id “timelineContainer”, which is a wrapper around the timeline (The div is defined in the of the HTML).

Line 59-62 retrieves the element which received the click and checks if it’s really the anchor element with the special css class.

Line 65-69 is the real key to enable the interaction between the timeline and the rest of the application, it takes advantage of a very useful ZK feature for sending Event to parent element. Using the “parent.zAu.send” method, we sent an event (called “onDocRequestedFromIframe”) to the parent ZK component “mainWin” (refer to the ZUL snippet shown earlier). From there, the ZK main controller (Java code) that is attached to the main Window component can respond by opening a new ZK Tab to show the requested document.

The result is nicely integrated timeline which can interact with the rest of the ZK application via ZK Events as shown in the following figure. Eventhough the timeline script resides within an iframe, this approach allows the timeline script to invoke Tabs, Menus, and other component within the containing ZK application.

Figure 1 - Seamless Integration of TimelineJS into ZK Application

Figure 1 – Seamless Integration of TimelineJS into ZK Application

In a Nutshell

We have shown one of the ways to visualize business data along the time dimension in a meaningful and engaging way, and how to implement it using the ZK Framework, TimelineJS and a little bit of JQuery and Javascript codes. We have shown how to enable seamless interactions between the TimelineJS script and the containing ZK Application using ZK’s Events.

We hope this post can be beneficial for anyone who may be looking to implement similar functionality.

Please also check out our main blog page where you can find useful information regarding Data Management, Business Intelligence, and more (click here).


We serve businesses of any type and size
Contact Us Today