Charles Crume wrote:
"Richard Cornford" wrote:
[snip] It isn't anything like as simple as "the object model" as only a
limited part of the browser object model is standardised, browsers
do not necessarily fully (or correctly) implement the standards that
do exist, and some provide additional features.
This is gonna make it kinda difficult to learn.
<snip>
Unfortunately, cross-browser scripting for the Internet is not easy, and
so it is not easy to learn. But things that are easy don't make for an
entertaining intellectual challenge. The main problem is that scripts
have to be written without any certainty about the environment in which
they will be executing (even whether it will be executing scripts at
all).
That is quite different form most other programming contexts, where the
environment, object model, APIs, etc, are known and (ore or less)
reliable (at least consistent). But the situation is not so bad that
browser scripting is impossible, there is a core of common browser
features that can be used (and increasingly so as the W3C DOM standards
are more widely adopted). It is just that (almost) nothing can be taken
for granted and assumed to exist in the unknown browser that will be
operating on the client side.
So the first thing that needs to be learnt for successful cross-browser
scripting is how to cope with the unknown execution environment. In the
face of the unknown you proceed with caution, testing the ground every
step of the way. Only attempting to use a browser feature once you have
verified that it exists. So, for example, wishing to assign a URL to
location object of another frame:-
if((typeof parent != 'undefined')&&(parent != window)){
// The parent reference is distinct from the current window
if(parent.frames){
// the frames collection exists on this browser.
if(parent.frames['logo']){
// The target frame is referenceable as a named member of
// the frames collection.
if(parent.frames['logo'].location){
// The parent frame has a loction object.
// Assigning to the location should be effective
parent.frames['logo'].location = URL;
}
}
}
}
In the event that the browser does not implement any of the required
objects, the above code will not attempt to act in a way that uses them,
and so it will not error. Obviously the logic of the - if - tests can be
re-arranged to more suitably/efficiently address the situation, and -
else - branches added to consider possible alternative/fall-back
approaches when features may exist to facilitate that, or to allow a
positive controlled response to failure of the browser to implement the
desired features.
(It is also usually inefficient to actually structure tests in this way,
so that they are repeated each time a feature needs to be detected. If a
frame/window has a - location - object the first time you test it it
will have one for all subsequent tests. The design of feature detecting
tests for efficiency is something that needs some consideration, and the
dynamic nature of javascript allows some interesting possibilities.)
The second major aspect of cross-browser scripting is appropriate script
design. To design a script such that it provides a positive benefit when
it is supported by the unknown browser, but does not make anything worse
when it is not. This is termed "clean degradation", and should be
implemented such that it happens under control and transparently to the
user (there is no point telling the user that their browser is
inadequate in your opinion, because they are likely to be incapable or
unwilling to do anything about that (else they probably would have)).
Clean degradation is achieved by planning for the total failure of the
script (all scripts will fail on some browsers, not least because some
browsers cannot execute scripts at all).
An example might be the use of HTML SELECT elements for navigation. It
is apparently quite common for a SELECT element to be used to list
pages, and, when an item is selected, for a script to used to navigate
the browser to a corresponding URL. But if the script fails the user is
left fiddling with SELECT element that is promising them some sort of
action, but doing nothing useful.
An alternative (and more appropriate) design might start with an HTML
list of links, contained within suitable DIV (or similar) elements, and
use DHTML techniques to modify the presentation of that list so that it
acts like a SELECT element (presenting the contained link elements as a
drop-down when activated). Now total failure of the script will only
result in the HTML list remaining in it's fully exposed form as part of
the page, the contained links will be accessible and the navigation
achievable. The worst case only impacts on how that list is presented to
the user.
The transformation of the underlying HTML would be done in such a was as
to ensure that the list remained in its original form until browser
support for the required features had been verified, and any evidence of
lack of support would just leave the script needing to exit quietly to
leave the user with a page that was completely usable (clean
degradation), but maybe falling short of the intended presentation.
Now, it is true that the DHTML option will only work in dynamic
browsers, while almost any javascript capable browser can use the SELECT
based navigation, but most browsers are dynamic and javascript enabled,
so most of the time they are equivalent. The difference comes in the
response of the two designs to failure of the script. The SELECT design
is totally dependent on javascript execution (it is useless without it),
while the DHTML version does not render the navigation dependent on
javascript, the worst case is still a viable HTML page.
When a script is designed to have a path of clean degradation to viable
underlying HTML it is always possible to employ feature detection to
ensure that a script can enhance a page when the browser can facilitate
it, without detracting from the page when it cannot.
Richard.