Archive

Posts Tagged ‘Browser Compatibility’

Opening New Browser Windows Part 3

June 11th, 2009 Russell No comments

Now we have the design from part 2, we need to do a proof of concept to check browser compatibility, and check that our design meets the requirements outlined in part 1.

We need to create two javascript files:

  • ParentWindow.js
  • ChildWindow.js

We will begin writing the ParentWindow.js.

Firstly, we need to create a parameter object. Javascript objects can behave as “associative arrays”, therefore creating a new Object instance is all we need to do to have a collection of parameters:

var parameters = new Object();

We also want to attach this object to our window object. Then it can be accessed by child windows when required:

window["Parameters"] = parameters;

So far so good. We also need to have a reference to the child window that is currently open:

var childWindow = null;

We want to provide a function that can be used to retrieve parameters as well. This means that the child window can either use a property or call a function:

window.GetParameters = function ()
{
return parameters;
}

We need a function which handles the event when the child window has been closed. It will reset the paramter values, clear the child window reference and call a custom event handler if specified. We want it to only ever get called once. Once a child window has been unloaded, it is no longer in a state to return more data.

window.HandleChildUnloadEvent_Internal = function(args)
{
// Reset parameters.
parameters = new Object();
window["Parameters"] = parameters;

// Remove child window reference.
childWindow = null;

// If the page defines an event handler, we will notify it.
// Will only call this method once.
if (HandleChildUnloadEvent && !ChildUnloadEventHandled)
{
HandleChildUnloadEvent(args);
}

ChildUnloadEventHandled = true;
}

The main function, which opens the child window, checks if a window is already opened and then create a new one. If a window is already open, we will set focus to it.

function OpenWindow(url, width, height)
{
if (childWindow == null)
{
// Reset variable.
ChildUnloadEventHandled = false;

// Set childWindow reference to an empty object.
// We want the childWindow to NOT be null while the window is loading.
// This prevents multiple windows opening.
childWindow = new Object();

childWindow = window.open (url, ”, config=’height=’ + height + ‘, \
width=’ + width + ‘, toolbar=no, menubar=no, scrollbars=yes, resizable=yes, \
location=no, directories=no, status=no’);
}
else
{
childWindow.focus();
}
}

That is all we need for the parent javascript file. In the HTML page that is the parent page, we need to call the correct function to open the window, and updtae the page when the child window has returned:


function OpenSuburbWindow() {
// Set parameter values.
parameters["SuburbText"] = document.getElementById(”txtSuburb”).value;

// Open the window.
OpenWindow(’../SuburbLookup.htm’, ‘520′, ‘600′);
}

function HandleChildUnloadEvent(args) {
if (args != null) {
document.getElementById(”txtSuburb”).value = args["SuburbText"];
}
else {
document.getElementById(”txtSuburb”).value = “”;
}
}

The above code will get the existing value from a text input box and add it as a parameter. It will then open the window. Once the window closes, we handle the child unload event by updated the text input box with the selected parameter. If the parameter is null, (unexpectedly closed), we clear the text input box.

The child window javascript file is even simpler.
We want a parameter variable that will be populated by the parent window:

var parameters = window.opener.GetParameters();

We also want a function that will be called when the window is unloaded. It will notify the parent window of the event and pass back updated parameters:


function NotifyParentWindow(args)
{
window.opener.HandleChildUnloadEvent_Internal(args);
}

We also want a function that will pass back our parameter object, and close the window. This function will be used by the child window HTML page:


function CloseWindow()
{
NotifyParentWindow(parameters);
window.close();
}

Now all we need to do is populate the child window when the page has loaded and update the parameters and close the window. To populate the child window we create a function that is called from the body onload event:


function DoInitialSearch() {
var suburbValue = parameters["SuburbText"];
if (suburbValue) {
document.getElementById(”txtSuburb”).value = suburbValue;
}
}

We also need to create a function that will be called when the window wants to close and pass back values. In this case, when a suburb is selected we will return and close the window:


function SelectSuburb(suburb) {
parameters["SuburbText"] = suburb;
CloseWindow();
}

The proof of concept seems to be working. I encountered the following issues that need resolutions:

  • Opera does not fire the window.unload event.
  • When the site is run as static HTML pages, firefox does not allow the child window access to its parent.
  • Opera has issues with setting focus to a window.

It seems to be a widely known problem that Opera does not fire the unload event consistently with other browsers.  Setting focus to a window is not an issue that will stop functionality. It simply increases usability.

At this stage only the prototype is running as a static HTML page, so this will not be a problem when running under IIS (under the same host).

So proof of concept succeeded, now on to implementation.

Opening New Browser Windows Part 2

June 11th, 2009 Russell No comments

In part 1 I created a prototype of a window that would open in all required browsers.  Now I need to design a message sending process that will allow us to:

  • pass parameters to the new window
  • notify the parent window when an item has been selected
  • manage whether a child window has already been opened

When we create a child window, a window object is returned.  This is the object I plan to leverage to allow communication between windows.  The event we need to use is window.onunload.

As per the final post in this forum, we set up a function in the main window, that is called by the child window when it has finished processing.   It can pass back a parameter which gives us the ability to return a value as necessary. It is also nice because the child window will not need to know anything about its parent.  This helps us separate concerns, and have all the window management done in the parent!

The above design assumes the child object has a reference to its parent.  Luckily there is a property available as part of the window object in w3schools and found the opener property. This returns a reference to the window that opened the child window. This is what we need. This reference gives us a circular reference, which is not ideal.

The next design issue is passing parameters to the child window. Now we have a reference to the parent window, we can call a function to retrieve parameters. That means we can attach a function to the window object which will pass a parameter object (whatever that may be).

We have a set of functionality for the parent and for the child window.  We could put all of this into a single javascript file or separate into two.  If we put it all into one, we can reference it in one place (a master page, for example) and forget about it.  Call the openWindow method in the parent and set up functions to handle the events.  This sounds good because it is build and forget.  However it is unclear which is to be used by the child, and which for the parent.  If we separate it, it will be much easier to understand and simplify maintenance.

In summary, we now have:

A javascript file for the main window that:

  • Contains an array/list of parameters.
  • Contains a variable which contains a reference to the currently open window (or null if no child window is open).
  • Contains a function which returns the parameters.
  • Contains a function which handles an event that the child window has finished processing (passing an object parameter).
  • Attaches the above two functions to the main (current) window object.
  • Contains a function which will open a window (only if one is not already open), and keep a reference to it.

A javascript file for the child window that:

  • Initially retrieves the parameters from the parent window.
  • Handles the window.onunload event and calls the parent window notification function.
  • Passes the above function an object as a return parameter.

Next is to create a proof of concept for the above design, then finally (assuming POC succeeds) implementing it.

Opening New Browser Windows Part 1

June 11th, 2009 Russell No comments

I currently have to open a new window in a web application. Here are my requirements:

  1. Must be browser compatible for IE6/7/8, Firefox (all), Opera (all), Chrome and Safari
  2. Must pass parameters to the new page (without using URL parameters)
  3. Must return a value to the old page
  4. Must know whether a window has already be opened, so only 1 is open at a time

According to this site, the target attribute for the anchor tag is being phased out. Therefore it is a better idea to use DOM in javascript to open the window. We need this anyway to meet the requirements for holding on to the new window reference.

I tried the first code example from this site, however it did not work in IE 7. I think a majority of this code is the correct way to go, so I need to work out why it failed in IE 7. I also noticed the resizable config setting had no effect in any of the browsers. That is fine, as this does not break any of the requirements.

I came across an interesting paragraph on the MSDN site, that mentions IE 7 in Windows Vista has access restrictions across process boundaries. It also mentions that when a new window is opened, it creates a new process. This may be an issue as it will make our requirements more difficult to meet.

The issue with IE 7 was related to the title text. I passed in a parameter like so:


function openWindow(url, title)
{
var win = window.open(url, ‘App - ‘ + title, config=”…”);
}

When I simply used:

var win = window.open(url, ‘App’, config=”…”);

Internet Explorer worked fine.

The resizable config setting appears to only work in Internet Explorer. I want consistent behaviour so I will not use this setting. The default value is resizable=no, so I have to explicitly say yes, I do want the window to be resizable. I am trying to make navigation easier for my users, not restrictive.

An object is returned after the window has been opened. This is the object I intend to use to pass the parameters to, be notified when the window has closed and retrieve the returned value. Here is my code so far:

Javascript

function openWindow(url)
{
var win = window.open (url, 'CHCR', config='height=300, \
width=520, toolbar=no, menubar=no, scrollbars=yes, resizable=yes, \
location=no, directories=no, status=no');

}

HTML
<div onclick=”openWindow(’../SuburbLookup.htm’);”>..</div>
This will open my window and meets requirement 1.

Stay tuned for further progress on my window.