|
SYS-CON.TV Webcasts
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
Top Links You Must Click On
General Java Prototyping an Advanced Calendar Class Using JavaScript
Prototyping an Advanced Calendar Class Using JavaScript
Sep. 1, 1997 12:00 AM
It is possible to create a very attractive look-and-feel prototype of a Calendar-based browser application in JavaScript, but to compete with tough-minded mainframe legacy systems such as MEMO requires a highly functional and scalable working prototype to justify the continued investment and potential encapsulation of a large mainframe system. After it was suggested that an existing MEMO-based system was to be superceded, an opportunity arose to port some of the legacy application functionality to the new Intranet and browser medium, hopefully gaining a more attractive interface, platform independence and the ability to interact with other desktop clients. A functional prototype was implemented using JavaScript. The approach taken was to implement an object model that would not need redesign once the back end was attached. For simplicity, elementary datasets are implemented using cookies on the client. Almost all of the user interface is written dynamically on the client using JavaScript to generate the HTML and object references between windows. Practical snippets of JavaScript and HTML are included which demonstrate the more advanced features of JavaScript required by an application that attempts to supercede an older and more mature user interface. The overall technical detail will show how JavaScript can be used to generate HTML, parse formatted data streams and handle events asynchronously. The implementation details covered can be used in any JavaScript application for which scalability and upward compatibility are critical design constraints. In Part One, the application functionality, design constraints and prototyping approach is outlined. A simple event-action model is implemented in JavaScript that allows for arbitrarily complex rules. This is designed to manage window-to-window communication and other events via asynchronous event handling using JavaScript threads'. The screen shots used here are taken from Navigator 3.0 running under NT4.0.
Calendar Functionality
Calendar Data The term cookie database' refers to a collection of objects called cookies' which, under Navigator, are stored in a browser-generated file on the user's PC called cookies.txt'. A cookie represents persistent' information, which means that, where the stateless HTTP protocol itself cannot store information about anything except its current action, a cookie can be used to store that information, which may be as simple as the user's name or favorite URL.
The HTTP protocol allows the setting of cookies in the HTTP header when the page loads. However, using JavaScript to manage cookie data allows us the freedom to: Only the browser, or the user sitting at the PC, can write to cookies.txt, but the browser generates the file so any in-line updates are almost certain to be lost at some point.
Table 1 shows the components that make up a cookie string. JavaScript has access to the set of cookies on the client using the property document.cookie'. There are restrictions however. Web browsers are not required to retain the value of more than 20 cookies per Web server (not just your site). A name/value pair cannot be more than 4k in length. For the purpose of functional prototyping, however, using cookies as described in this article is an acceptable short-term method for storing data.
Calendar Screens
User Defined Month View
Browse Meetings in Day
Maintain Calendar Events As you will see later, all the functions in Table 2 are implemented by using JavaScript to generate HTML frames which include embedded references to Calendar objects.
Select Participants
Automatically Mail Participants
Configure Calendar
Constraints and Design Decisions For example, Navigator 2.02 running on 12MB 486 PCs is the default corporate platform, but there exist many other variations on top of this within the organization. Mindful of the need to justify both the prototyping exercise and the cost of rolling out future enhancements across a heterogeneous surface, the decision was made to build against JavaScript 1.0 with a view to upward compatibility. The following sections list the major constraints and decisions taken.
Screens Written Dynamically Using JavaScript 1.0
Event Handling and Parent/Child Window Communication
16-bit Target platform (NS2.02) - No Java and Back End not available
JavaScript Classes Store Format and Content of Data Meeting.today() overrides DayEvent.today() but invokes super.today() to fetch the day number within the specific formatting context. Because the requirement is to render the screens dynamically, formatting becomes a method of the class. And because calendar events are nested within calendar objects (such as a Calendar Window, Month and a Day), they have a formatting context. It would be nice to be able to invoke super() to create a string that contains the HTML tags and links which enable an object such as a Meeting to be correctly formatted within the display context of its containing window. Because inheritance is not available, a dependency structure was introduced that would allow the creation of a parent dependency when constructing the child, similar to constructor chaining in Java. What seems like over-engineering yields effective results when passing objects or object references between windows with different display requirements for the child object's data.
Cookies and Client Side Persistent Data
Upward Scalability of JavaScript Code
There are major differences between versions, which mean that some properties and methods have been moved to different objects. However, JavaScript 1.1 has some excellent features that save programming time. In particular: Relisting is useful for maintaining summary lists dynamically and will save some execution time by eliminating the need to regenerate the screen to display a different list, but does not reduce the coding overhead particularly. Native parsing, however, does reduce the coding overhead significantly because it is the JavaScript interpreter that parses the string and reduces string processing iterations to a simple statement, as in the following code fragment:
s = "Team Meeting~Meeting Room 2" +
Managing JavaScript RunTime Resources In JavaScript 1.0, garbage collection occurs at page unload or reload, whereas in version 1.1, similar to Java, garbage collection is reference-based, which means that if an object has its reference count decremented to 0, the space is reclaimed. The decision was made to read data and create the associated objects on demand. For the main browse and update screen (see Figure 3), clicking on a day in the bottom left window will read all meetings for that day of the month and display them in the top left window. Although all the data in the Month cookie is read, only those meetings for the selected day are extracted and created as Meeting objects. This strategy will, in most cases, manage resources better than if we read all meetings for the month and created a whole set of objects since we are managing the uncertainty of volume, and the strategy will also migrate effectively to using a server-based datastore, which will return results sets per query.
Legacy Application Functionality
The prototyping of an interface to the existing MEMO database was out of scope, but with such a mature product in a large installation, replacing the database would be required only if: Clearly, a more attractive interface, platform independence and the ability to interact with other desktop clients are good enough reasons to attempt the prototyping.
Managing User Expectation
Functional Prototyping A functional prototype is a Rapid Application Development (RAD) term that defines a system in which the application functions are demonstrated and the user interface defined. On a client/server platform, a functional prototype would contain all the screens and navigation buttons and menus that belong to an application sitting on the user's PC. The idea is to get user-buy in to how they want the system to look and feel while delivering the critical functionality. Again, RAD defines a metric that 80 percent of the critical system functions are contained in 20 percent of the build. If you build a functional prototype of a spreadsheet, then most of the functionality will be delivered in the prototype so the subsequent build activity should be reduced. On the other hand, a look and feel prototype (e.g., screens in a shopping cart) would be delivered to a build phase in which the main deliverable to the build was a set of screens; the skeletal code with each screen would be filled in by adding code to handle the database, network, event handling, etc. However, the intention was to avoid rewriting the software once server resources were available. So, an interface to data was developed, using cookies, such that the rest of the prototype could be implemented as a working model. Cookies are seen as a disposable resource, with cookie data seen as a formatted data stream which may be superceded by server data, giving rise to the requirement for a transparent data interface. It could be argued that with simple scripting languages which are used in a prototyping context, there is no need for a thought out design; it is better to start building a look and feel prototype which acts like a shell into which the non-functional back-end can be coded later. In a lot of cases this is appropriate; for example, using Visual Basic for the user interface with a follow-up in C++ for critical sections of functionality (e.g., calculations). For a browser-based application, the simplest model assumes that the screens in the application are coded in HTML first (with dummy data) to establish the look and feel of each screen and the navigation between screens. Then, the HTML and JavaScript is built to support the rendering of those screens dynamically. A working prototype, however, requires actual data; hence, the need for working code is introduced early on. Proving working code early on is also important because the requirements of JavaScript may render the application unworkable due to the amount of code being interpreted on the client PC. But, remember the analogy with spreadsheets. You can't really prototype spreadsheet functions unless you have almost built a fully working spreadsheet. The same applies to client-based browser applications when the decision is taken to generate the format and content of screens on the client. By the time the JavaScript has been written to generate the HTML for all the windows which are being prototyped, the application code has, in fact, been written; unless you intend to rewrite it later, which only makes sense if it doesn't work in the first place.
Critical Success Factors
JavaScript Threads Using Asynchronous Wait and Event Handling
Managing Popup Windows using Simple Asynchronous Event Handling Each class shares the same reference to an event handling method, pollEvent(). Each class also has a reference to an object (CalendarChild) which manages child objects, principally child windows. The CalendarChild object is used in the event handler.
On Event then Action - Opening the Popup Browse Meetings Window and Passing Object References to it The window is opened as described in Listing 2. Because of the latency involved when the browser opens a window and displays the screen detail, an asynchronous thread is set up which polls the child window every half second until the basic frames are loaded. Once loaded, the thread invokes the methods which draw the frames in the popup window. Each class (Calendar, Day, Meeting) has the ability to create a child dependency (e.g., a window), and the default assumption is that any children are managed asynchronously. The dependencies are handled using the rule on Event then Action'. Hence, each class has a reference to an instance of the class CalendarChild', which contains the properties described in Table 3. In the prototype implementation, this is a very basic object to capture the arbitrary complexity of the on Event' rule. Extra functionality can be handled as a property of the data by adding action and event functions. Function references are assigned to the action and event properties as required. Listing 2 contains the code to open a window and spawn a thread to poll for the event which states that the child window has successfully loaded. The Day object then writes a substring of the dependent Meeting object to that window; namely, the Meeting subject. The event is tested against using the check_frame()' method reference. The event is listened on' by the render_subject()' method of the Day object. References to both the event method and the action method (which belong to the Day object) are assigned to instance variables in the CalendarChild class described above, and it is pollEvent code which runs both. An alternative way of handling communication between windows is by using cookies, especially when the frame and object references are longwinded or complicated. A cookie is used to store the signal that the window has posted some data. Another cookie contains the data. The event' property is set to reference a JavaScript function, as follows: this.CalendarChild.event = f_poll_signal; The statement this.CalendarChild.event() invokes the f_poll_signal() in Listing 3, which tests the cookie called SIGNAL for the value READY. If found, the cookie is set to NONE. The event handler ensures that the f_poll_signal() method is called every half second. In summary, JavaScript allows the CalendarChild class to be a useful container for storing variable references to methods that are to be actioned in background when an event occurs.
Automatic Generation of Mail Headers In order to allow the prototype to have a minimal, working implementation, each participant of the scheduled event is mailed a copy of the event information instead of having the information stored on a central database. The mail contents are generated automatically as far as possible. With Netscape Navigator 2.02+, JavaScript allows us to generate a mail message in a Mail window. All of the vital pieces of information are contained in the header. The addressee, CC and subject can all be set, using JavaScript, from the data contained in the form. However, the body of the message cannot be set (at the time of this writing) if there is any text to set it. The quick workaround is to cut and paste the text into the body of the mail window. The JavaScript to do this is tricky because we have to set a hyperlink dynamically, action the link and then manage the return from the link. The basic link that will be manipulated is expressed in HTML and JavaScript as follows:
<A href="javascript:void" name='notify' The link named notify' in the above code fragment is referenced as document.links[0] by the subsequent JavaScript code. The subject_mail_format() function is invoked when the user clicks the red postbox. The return true statement tells the browser that no further action needs to be taken. The function will set the HREF property of the hyperlink, and then action it.
The problem is compounded by the fact that the participant list is a textarea; each member of the list needs to be extracted and formatted for the addressee section.
The expression document.MEETING. Listing 5 shows the detailed JavaScript in the subject_mail_format() function, referenced in the onClick' event handler in the JavaScript code fragment shown above. For the screen in Figure 3, this will yield the mail header in Figure 4 when the red postbox is pressed.
Conclusion Reader Feedback: Page 1 of 1
Enterprise Open Source Magazine Latest Stories . . .
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||