Javascript, Loading/Processing notice display.
Project example
To see the code for this project in action, pull my finger.
Ok, since you have obviously heard that one before and not going to fall for it again, try this
You will also have an opportunity to download a demo of the code described here at the end of the code portion of this project.
Nothing is instantaneous.
Click, nothing happens. Wait, still nothing happens. Just as you begin to leave the site, what you initiated begins to happen but it's too late. You are lost to the site and likely won't return. Even worse than a visitor having to wait for something to happen is the visitor having to wonder if anything is going to happen at all.
While most interactive applications are built to provide an almost instantaneous reply, even the most powerful of servers or even clusters of servers can get overloaded causing replies to be delayed or once a reply is initiated, take some time before there is a noticeable change for the visitor. But, problems can ocurr not only when an in page process is initiated but during the initial page loading itself.
Static pages/content
When one clicks a link to go to a new page, virtually all browsers have some way to let the user know that the new page is loading and that although it may take a while, something is actually happening. Firefox and Internet Explorer have their rotating circle of dots and fluttering Windows image, respectively, as well as an updating status line area indicating what is being loaded and from where. Opera is slightly different in the status line area, as by defualt generally doesn't have one where the other browsers do but instead, includes an update of what is going on closer to where one might look in the first place, up near the address bar.
But, even with the information provided by the browsers, it may not be enough as it may sometimes appear that a process has frozen when dots are spinning and images are fluttering but nothing seems to be happening in the area the visitor is most concerned with, in the actual display area itself.
Also, browsers will usually indicate that a given page has completed loading when in fact there are still elements being loaded by an onload event handler so even if things appear complete, they often may not be.
AJAX in action
Or is it? Unless an image is being loaded as part of a given AJAX process, more often than not there is very little indication that anything is ocurring during most AJAX processes. Having something automagically appear on the page is all well and good but if it takes too long for the automagic to happen or the visitor has no idea that anything is going to happen in the first place, a function or feature that one may have spent a lot of time to provide may end up going totally unnoticed at best or at worst, driving visitors away.
That said, there sometimes may be some indication provided by the browser itself in the form of status line updates but even when those are displayed, hidden down at the bottom of the browser, they very often get overlooked or simply ignored as they are usually cryptic or at least minimalistic in their 'explanation' of what is happening.
An informed user is a happy user
A user is more comfortable when their expectations are realized. While providing opportunities for a user to experiment with new functions and features they likely are not familiar with does help give them a feeling of doing something new, expecting them to step too far outside the 'box' without guidance is not necessarily a safe thing to do. On the other hand, giving them positive reinforcement every step of the way helps build confidence not only in their abilities but more so, helps to build trust leading them to let you lead them even further outside of the box within which they spend most of their time on the Internet.
Event driven vs. Process driven
One can try to predict how visitors to one's site will move through and interact with one's site but unless there is virtually no interactivity other than static menus to static pages, reality often tosses all predictions out the window.
Unless one takes specific steps to prevent or disable other interactivity options while in the middle of a given interactive process, which leads to complexity and usability issues by itself, one basically has to account for the possibility of one initiating multiple processes concurrently.
In this scenario, one has to be careful that one's method for keeping the user informed as to what is going on during a given process isn't hidden or totally overwritten by information pertaining to another process initiated by the user.
To this end, any solution considered must be able to support multiple notices existing at the same time with each having the ability to operate independantly while at the same time, none effecting or otherwise interferring with any other that may be in operation at any given point.
Independant notification agents
The solution chosen for this project is agent based in that objects are created with specific instructions as to how they should react to different conditions or input and then let go to do as they will.
There are two Javascript classes used, one to recieve requests for new notifications and their destruction and another, to implement the notification agents themselves.
Managed process initiation, agent process control
All interactions with the notification system is through the Manager/Factory object. 'All' being rather simple in this case with one only needing to request notifications to be constructed and destroyed.
Once constructed, the notification agents pretty much carry out their duties with minimal help from the Manager as they are agent aware and cooperate amongst each other to perform their tasks.
The tasks the notification agents are expected to carry out are fairly simple though, basically to position themselves as new notification agents are added and removed.
Stacked notifications
To keep notices from hiding one another or otherwise obscuring each other, this implementation simply stacks each one on top of another. Other placement schemes are possible although this one seems to be about the simplest to implement.
It might seem that a non-agent based system likely could be more easily built, with the manager/factory class controlling the position of all the agents but it ends up being easier just to make each agent aware of its neighbors and then let them keep each other informed as to where each is and where each should be. In this way, the manager/factory only has to keep track of a given agent of interest, one being created or destroyed and then letting that agent inform surrounding agents as to its positioning and/or movement.
The system in operation
For this walkthrough, we'll assume that there is already one notification agent existing.
- The Manager/Factory receives a request for a new notification to be displayed. The request includes an ID, generated by the requesting process (Note 1) that the requesting process can use when it wishes to dismiss the notice and the "text" (Note 2) the notification agent should display.
- The Manager/Factory creates a new agent passing it the ID assigned by the requesting process.
- The Manager/Factory creates an array record it will use to keep track of the agent it created. This record includes the ID as well as a pointer to the agent through which it will communicate with the agent.
- After the agent is constructed, the Manager/Factory checks for existing agents and finding one, in this example, passes a pointer to it to the newly created agent. (Note 3)
- The newly created agent passes a pointer to itself to the 'previous' agent it was just passed a pointer to.
- The 'previous' agent then causes the 'next'/new agent to position itself just below the 'previous' agent.
Note 1 : The ID may be any string and only need be unique among all notification agents. If a given notification agent to which a given ID has been assigned no longer exists, the ID may be used again. However, in this implementation no check is made to ensure uniqueness.
Note 2 : "text" could actually be HTML, an image, div or any other element or elements as well.
Note 3 : Only the agent being created need be notified by the Manager/Factory of the presence of other agents and only be notified of the agent previous to it in the stack of agents. Any further inter-agent processing is carried out amongst the agents themselves.
Removing a notification agent
When a process that caused the instantiation of a notification agent no longer requires the notification to be displayed, it uses the Manager/Factory to kill the notification agent by passing in the ID it provided during the request to have the notification agent created and displayed initially.
The process used to remove the requested agent and adjust the position of any effected agent, i.e. those agents displayed below the agent in question is as follows :
- The Manager/Factory searches its list of agents and finding the agent requested to be destroyed, tells the agent to destroy itself. The Manager/Factory then deletes the entry from its list of agents.
- The agent being destroyed checks to see if it has a 'previous' AND a 'next' agent.
- If it has both, it informs the 'previous' agent about its 'next' agent and deletes itself. Meanwhile the 'previous' agent will perform the same process regarding its new 'next' agent as was performed initially by the Manager/Factory when creating a new agent.
- If it has a 'previous' but no 'next', it informs the 'previous' that there are now no longer any agents following it and then deletes itself.
- If it has a 'next' but no "previous", it causes the 'next' to position itself to replace the agent being removed and then sets the 'next''s 'previous' pointer to null
- The agent being removed is then deleted.
Agent position adjustment
Any agent, other than an agent being removed, whose position was adjusted during either of the previous two process will in turn cause any 'next' agent's position to be adjusted as well. So, as each agent's position is adjusted by its 'previous' agent, they will in turn adjust the position of their 'next' on down the line. In this way, all notification agents' positions are adjusted causing them to appear to slide upwards without the Manager/Factory having to keep track of each agent's position and only having to initiate the process by telling the notification agent in question to delete itself. All further processing, changing of pointers and repositioning is performed among the agents themselves.
On to the code
You can find the code for this project here.








