|
Computer Tips
Web Development
|
Visit us often. Computer tips updated
daily. Click here to--> "Tell a friend" so they can get updated
computer tips, too. Please visit our clients, as they support the
computer tips page.
If you would like to submit a tip send us an email with
your tip to
info@businesswebsitelinks.com.
______________________________________________________________
Tip: Don't let your HTML form
validation drive visitors away!
- One way to learn how to create a more usable
website is to analyze the world’s worst sites and learn what not to do.
- Here’s an example of a particularly poor web
form:
- 1. You submit the form and wait because
the site is validating your information on the server.
- 2. The form comes back with the message
that you filled something out wrong. You scroll down and see a message that
the problem is that your username is already taken.
- 3. You choose a different username. After
awaiting validation, you find that your username isn’t valid because it
contains capital letters (So did the one it said was already taken; go
figure).
- 4. You type a username you think is valid,
although you aren’t sure at this point.
- 5. The website says that some other piece
of information you already filled in (e.g., state, credit card, or zip code)
is blank. Now, you have to go through the whole thing and check that the
other fields are still filled in.
- Key rules to follow:
- You’re probably aware of the importance of
validating form data on the client whenever possible. To avoid the other
mistakes in this nightmarish form, keep in mind these crucial rules:
- If a form fails validation, report on all
reasons why it failed. Don’t stop form validation until your code detects
all the problems—and don’t make the user scroll to see why the form failed.
- Test that every field maintains state when
a form fails validation.
- If possible, avoid unnecessary rules;
although your code should enter data into the database in a consistent
manner, try to handle different common ways of entering data at the client
end.
- If you need the data in a certain format,
make that clear in the form—and (when appropriate) use JavaScript to prevent
the user from typing the wrong thing even before he submits the form.
Tip: Use query strings to give users
the convenience of bookmarking
- You may have heard some developers say
"Don't use query strings." Certainly, posting confidential data to a query
string is usually a bad idea. However, when used properly, query strings are
quite helpful. To see a perfect example of just how useful they are, just
point your browser to a major search engine such as www.google.com.
- Because Google stores a user's search
criteria in the query string, a user can conveniently store the search by
bookmarking the page (e.g., adding to Favorites in Microsoft Internet Explorer
or Bookmarks in Mozilla Firefox). When the user relaunches the page from the
bookmark, she gets the latest search results based on her original search
criteria.
- One reason this scenario works so well is
that Google also modifies the contents of the <title> element to match the
search. Hence, browsers recognize the uniqueness of the search criteria, so
users don't have to bother creating their own unique name every time they
bookmark a search.
Tip: Sophisticated ways hackers may
direct users to their site
- Phishing scams involving sites that look
like yours can hurt your customers and your business.
- Although spam is the most common way
scammers direct users to fraudulent sites, there are other ways they may lure
even highly experienced web users:
- * The scammer hacks an insecure site that
links to yours. Once hacked, the links that used to go to your site now go
to the hacker's look-alike site.
- * The hacker creates multiple pages
linking a site imitating yours. Pretty soon, the phony site is competing for
rankings in the search engines with your real site. Users may instinctively
trust results in well-known search engines—especially when these pages steal
your branding.
- You can help prevent long-term damage from
such look-alike sites by periodically checking search engines for sites that
use your trademarks and other keywords from your website.
Tip: Visually group items with <optgroup>
elements
- Sometimes you may want to increase
readability in dropdown lists by visually grouping items within a single
dropdown list. You can do so with the <optgroup> tag. The label attribute
determines the group header that appears inside the dropdown list.
- For instance, the following code, when
inserted within a <select> element, produces option values Apples and Oranges
below the heading Fruit:
- <optgroup label="Fruit">
- <option value="Apples" >
- Apples
- </option>
- <option value="Oranges">
- Oranges
- </option>
- </optgroup>
Tip: Two essentials for keeping your
site safe
- If you store any user input on your server
or post it to your site or URL, you may be vulnerable to hacker attacks.
- If you do nothing else to promote web
security, take these two measures at the very minimum:
- * Encode any user input you pass into SQL
calls to the database.
- * Encode any text and data you dynamically
write to a web page or URL.
- Most major server-side coding languages
contain an intrinsic HTML encoding function:
- * ASP: Server.HtmlEncode()
- * PHP: htmlentities();
- Most major server-side coding languages also
contain an intrinsic URL encoding function:
- * ASP: Server.URLEncode()
- * PHP: urlencode();
Tip: JavaScript's equivalents to
VBScript character functions
- If you've used Microsoft Visual Basic,
VBScript, or a number of other languages, you convert characters to character
codes and back again with the functions Chr() and Asc(), or something similar.
- In JavaScript, the corresponding functions
are charCodeAt() and fromCharCode(). Unfortunately, these commands are
notoriously difficult to find in the indexes of JavaScript reference
books--or, for that matter, in online user groups. So, you'll just have to
memorize them (or save this tip!).
Tip: Process forms more easily by
synchronizing numeric field values with JavaScript arrays
- You may want to display information based on
a visitor's form field selection. For instance, a dropdown list or radio
button group may trigger specific text to appear in a designated element on
the page. Naturally, you could force the page to reload with the new
information each time the user selects an option, but JavaScript offers a
better, client-side solution:
- 1. Fill a JavaScript array with all the
information associated with the various form fields.
- 2. When the visitor makes a selection, use
client-side script to pull the appropriate information and display it.
- With this kind of system, it's best to
synchronize the array indexes with the form field values. That way, you can
simply plug in the value as the array index, and--voila!--you've retrieved the
appropriate information. Here's a page demonstrating how this works:
- <html><head><script type="text/javascript">
var barks = new Array()
barks[1] = "wwwWoof! wwwWoof-woof? "
barks[2] = "Arf! Arf! Rf!"
barks[3] = "ruff-Ruff! ruff-Ruff!"
-
- function showBark(val) {
alert(barks[val])
}
</script>
<body>
-
- <input type="radio" name="barks"
onclick="showBark(this.value)"
value="1">Spot</input>
<input type="radio" name="barks"
onclick="showBark(this.value)"
value="2">Spottie</input>
<input type="radio" name="barks"
onclick="showBark(this.value)"
value="3">Caesar</input>
</body></html>
Tip: When is an applet not an applet?
- Not everything that looks like a Java applet
is one. Some web pages for Microsoft Internet Explorer use Microsoft's ActiveX
controls and plug-ins. Plug-ins for Firefox typically employ Mozilla's XUL
dialect of XML, together with related technologies. In addition, some sites
create applet-like functionality with Macromedia Flash or Shockwave.
- However, while solutions with these tools
are sometimes easier to develop than Java applets, they generally either lack
the cross-browser appeal, or else require that the user download a proprietary
plug-in.
Tip: Why phishing expeditions can harm
your website
- Sometimes, one idea triggers another,
triggering another. In a previous tip related to several other tips, we
mentioned security problems caused by writing information from a query string
directly to your page using document.write().
- One reader wondered if perhaps we were
overstating the problem. After all, if a user enters a query string that
causes your site to appear incorrectly, that would only affect the one user,
right?
- Well, not necessarily. The problem is that
if a person sends out email to other people with links that look like they go
to your site (i.e., they have your URL, but the sender's query string), the
users who click on those links might consider you accountable for what
happens. At the very least, they might associate you with the "bad" guy
because the URL has your domain name.
- Moreover, if you aren't careful about what
your code does with query strings, a hacker can make a phishing expedition
more credible. As you may know, phishing expeditions are scams where someone
dupes others into giving that person their passwords. The last thing your web
business needs is for this to happen to your loyal customers who trust your
site.
- So, although the hacker isn't really
changing your site, this kind of thing can be dangerous to your reputation,
your customers, and ultimately, to your business.
Tip: Easily differentiate the first
element of a series with this XSL technique
- You may notice that certain publications
format the first paragraph different from every other paragraph. So, you may
wonder how to create that effect automatically in web pages that you generate
from the server. If you're using XML, you can do so with a technique called
the preceding-sibling axis.
- Let's take a quick look at an example in
which the first paragraph is shown as plain, bold text, and the other
paragraphs are <p> elements. For instance, say you have an XML document that
contains the following structure:
- <section>
- <title>Title Text</title>
- <para>First para text.</para>
- <para>Second para text.</para>
- <para>Third para text.</para>
- </section>
- In HTML, you want the final output to look
like this:
- <b>Title Text:</b> First para text.
- <p>Second para text.</p>
- <p>Third para text.</p>
- You can use the preceding-sibling axis
within a choose rule to specify when to output an HTML <p> element, and when
to simply output text in an element you've marked para, as shown in the
following XSL template:
- <xsl:template match="para">
- <xsl:choose>
- <xsl:when test="preceding-sibling::para">
- <p><xsl:apply-templates/></p>
- </xsl:when>
- <xsl:otherwise>
- <xsl:apply-templates/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
- Why choose para as the preceding-sibling
instead of title? You should do so because the title element may have more
than one use in your document (e.g., book title). So, it's safer to state that
a para following a para would get a <p> tag; then, add new "when" tests if
needed for other specific instances, where the default simply outputs the
content.
Tip: Instantiate user-defined classes
in JavaScript
- If your experience of objects is mainly
through writing JavaScript, you might not think in terms of classes. Unlike
classic object-oriented languages such as C++, Java, and Visual Basic .NET,
JavaScript doesn't have the notion of a class per se.
- However, you can accomplish essentially the
same thing by defining an object with a constructor function and using the new
keyword to create instances. For example, the following code creates the
template (i.e., class) for an Account object, which has the property CredNum
and the method payBill:
- function Account(strCredNum) {
- this.CredNum = strCredNum;
- }
-
- Account.prototype.payBill =
function() { /* Code to process payments*/}
- The variable declaration below creates an
instance of that Account object:
- var oCurrentAccount = new
Account('1234123412341234');
- If later we set oCurrentAccount to equal a
new Account() again, or we let it go out of scope (e.g., by leaving a function
or reloading a page in which we defined it), then we've effectively dropped
the original instance and all its information.
Tip: Follow this quick usability rule
to save users from unnecessary frustration
- You may have heard of the three clicks rule:
- * Don't make the user click more than three times to get anywhere important.
- But, if you really want happy users, follow the information parity rule:
- * Don't require any more clicks or other information from the user than a
logician would require to deduce exactly where the user wants to go.
- For instance, suppose your website sells bus and boat tours to various
destinations. If the user selects Hawaii, presumably you only offer boat
trips, not bus trips. So, don't send him to a menu where he has to click on a
link that says By Boat. Just send him through to the Hawaii Boat Trip page
since that's the only possible option.
- Of course, you may wonder what the big deal is if the user only has to click
three or fewer times. The problem is that users can get annoyed if they think
that the clicks or information your site requests are unnecessary. All the
rationalization in the world means little if the user intuitively knows
there's a better way.
Tip: Active users don't appreciate
being called idle
- In certain web applications, you may need to
time out a user who's idle for a long period. Usually, you set the timeout
value on the web server. Unfortunately, if your page has a lot of reading
material or client-side JavaScript, your user may think he's actively using
your application only to find out it's logged him out due to inactivity!
- For this reason, you may want to increase
the timeout value on the server for pages that contain a lot of reading
material or client-side script. For a more comprehensive solution, consider
trapping browser actions with JavaScript and submitting information to the
server (without resubmitting the whole page), just to let the server know the
user is still active.
Tip: Don't be lulled into leaving units out
of your CSS code
- Internet Explorer browsers are notoriously
easy-going when it comes to putting unit indicators after CSS properties.
For instance, even IE 6.0 will accept the following property setting:
- <style type="text/css">
- someClass {border:solid 6 green}
- </style>
- even though the border's width value
(6) doesn't indicate which unit to use. In the absence of a specific
unit, IE uses a default. Other browsers, however, like Mozilla and
Netscape Navigator 6.2 and 7.0 won't. Instead, they ignore the property
setting all together. With this behavior in mind, make sure to add units
where appropriate to all your CSS properties.
Tip: Coordinate website changes with
your marketing department
- Marketing communications departments
frequently have the responsibility of maintaining corporate identity
standards. Often, these departments develop corporate identity manuals that
define design and usage standards for such items as corporate logos, colors,
and fonts. These manuals may specify website layout standards too. When doing
development for an external client, check if such standards exist, and become
familiar with them before starting any design and development work on the
site.
Tip: Use maxlength properly to match
client-side user expectations with server-side capabilities
- As we mentioned in a previous tip, one of
the worst things you can do on your site is to mislead users. One way
you may unintentionally mislead users is if your input field lacks the correct
maxlength value.
- For example, suppose your site has an input
field for searching, and someone types in a search string of 300 characters.
If your server-side code can only handle 50 characters, then you'll get an
error. Even if you report the error properly, why did you let the user
type in 300 when you knew you could only accept 50? To avoid making your users
frustrated, your input tag should include a maxlength attribute like this:
- <input name="search" size="50" maxlength="50">
- Of course, when you use maxlength, make sure
you use it properly. Two of the most common mistakes with
maxlength are confusing it with the width attribute, and letting it get out of
sync with the server. For instance, the following tag doesn't set the
maximum number of characters that can be entered; the size attribute only
tells the browser how wide to make the field appear:
- <input name="search" size="50">
- Similarly, even if you set the maxlenght, it
won't do any good if it isn't up-to-date! For that reason, it's best not
to hardcode this value. Instead, write it with your server-side code,
filling it with whatever variable your server-side code is using.
Tip: Use CSS to repeat background images along a single axis
- If you've ever used CSS to display a background image, you
probably know that you can also control whether or not the
browser repeats the image. By default, when you supply an image
for a background, like so:
- background-image:url(funky.gif)
- the browsers automatically repeat the image across the entire
background. To turn this repetition off, you can use the
- background-repeat:no-repeat
- option. With this setting in place, the browser will only
display the image once.
- However, there may be times when you want to repeat an image in
just one section of the element or page. Fortunately, CSS
provides a way for you to do just that. What's more, the settings
are supported in today's major browsers: IE 5.0+, NN 6.2+, and
Mozilla 1.0.
- To repeat a background image along a single axis, use the two
background-repeat settings repeat-x and repeat-y. The following XHTML shows how these settings work:
- <html>
- <head>
- <style type="text/css" rel="stylesheet">
- body {
- background-image:url(swirly.gif);
- background-repeat:repeat-y;
- }
- </style>
- </head>
- <body>
- </body>
- </html>
- In addition, you can also position a tiled or single background
image, relative to the page's content. To do so, use the
background-position option. As its name implies, this CSS
property lets you position a background image. It offers several
setting values: percentages, length (x, y coords), and preset.
Presets include:
- top left
- top
- top center
- right top
- left
- left center
- center
- right
- right center
- bottom
- bottom center
- right
- right bottom
- So, using this property to position a background image at the
bottom right corner of the browser window, you'd use CSS similar to:
- <html>
- <head>
- <style type="text/css" rel="stylesheet">
- body {
- background-image:url(swirly.gif);
- background-repeat:no-repeat;
- background-position:bottom right;
- }
- </style>
-
- </head>
- <body>
- </body>
- </html>
- Keep in mind that the browser positions the image relative to
the content, not the viewport. So, in our example, if we added
additional text that extended down beyond the browser window's
viewport, the browsers would place the background image at the
bottom right of the content, which currently is below the bottom
of the viewport.
Tip: Finding the right size units for your CSS
layouts
- CSS gives you a lot of power over the
various graphical dimensions of your page, such as borders. But to wield
this power, you need to figure out which values CSS allows. In a
previous tip, we showed you the importance of specifying the correct units.
There are three units you can use for size, as follows:
- em is equal to the font size of the
relevant font.
- ex is equal to the size of a lower case
"x" in the relevant font.
- px is equal to one pixel.
- Note that the first two are based on
whatever font would apply to the element affected by the style. To find
out more about the units CSS accepts for size, visit:
- www.w3.org/TR/CSS2/syndata.html#value-def-length
Tip: Properly report search request errors to
users
- One of the most important commodities on the
Internet is trust, and you don't get much trust if you mislead users.
Now you may think you'd never mislead your users. But suppose the search
utility on your site has an error, causing your results to be empty.
It's common to simply return the phrase, "No results matched your search
criteria." But that's misleading. Users walk away thinking the
item they searched for isn't in the database, when that's just not the case.
If you're unable to report anything more specific, at least say "Could not
process your search request. Please change your search criteria."
And make sure you simulate error situations in your testing to ensure that the
appropriate message is coming back. The last thing you want is to
convince users you don't have what they want, when you really do.
Tip: Create your own set of design standards
- Finding the optimal balance between download
times, navigation ease, and aesthetics can be difficult if you're constantly
reinventing the wheel. If a number of developers are working on a site,
managing the design can be even more challenging. To help achieve consistency,
define your target audience, and set standards for each of the following
items:
- * frame width
- * color depth
- * image file type
- * maximum image size
Tip: The trick to Comparing a hard-coded date with a JavaScript
system date
- Granted, much of JavaScript's date complexity results from its
need to use GMT date formats, but even so, manipulating dates in
JavaScript can often be somewhat difficult. Comparing a
hard-coded date with a system date provides a perfect example of this.
- For instance, suppose you have a website that needs to compare
today's date with a stored date--the visitor's birthday, for
instance. Unfortunately, you can't simply convert the hard-coded
date into a JavaScript date and compare it to the value returned by:
- var today = new Date()
- var bday = new Date("5/15/2005")
- document.write (today==bday)
- That's because the today object also contains the time at which
you created the variable, whereas your hard-coded date won't have
a time value.
- To accommodate this difference in formats, you can break down
the system-generated date into its relevant components, like so:
- var d = new Date() //Get today's date
- var today = new Date((d.getMonth() +1) + "/" + d.getDate() + "/"
- + d.getFullYear())
- Unfortunately, for some reason, you still won't be able to
compare the two dates. Instead, you'll need to further convert
the dates to their millisecond equivalents, as seen in the
following code:
- <html>
- <head>
- </head>
- <body>
- <h1>
- <script type="text/javascript">
- var d = new Date() //Get today's date
- var today = new Date((d.getMonth() +1) + "/" + d.getDate() + "/"
- + d.getFullYear())
- var bday = new Date("5/15/2005") // Hard-coded date goes here
- document.write(today + "<br>")
- document.write(bday + "<br>")
- document.write((today==bday) + "<br>")
- document.write(Date.parse(today)==Date.parse(bday))
- </script>
- </h1>
- </body>
- </html>
Tip: Alias Web servers on local machines
(Windows)
- If clients of your Web application want to
use an alias for the server, there's an easy way for them to do this in
Windows. They simply have to edit the HOST file. For instance, in
Windows XP, go to the C:\Windows\system32\drivers\etc folder. In there,
find the file called HOSTS, and then add the IP and alias name to the list.
You can alias the server as "mydomain" with the following entry (where
xxx.xxx.xx.xx stands for the IP address of the Web server):
- Now, instead of typing
"http://xxx.xxx.xx.xx/address.html," users can type "http://mydomain/address.html."
Tip: Plan for language expansion when your site
goes global
- Think you can plan all your Web layout in
English and then get a translator to translate it into other languages?
Pas aussi rapidement! You need to consider that some languages require more
characters than what you've written in English. So remember to plan in
advance and make sure that your site will still lay out properly if the text
is 30 percent longer.
Tip: Be wary of putting database code on the client side
- For convenience's sake, developers sometimes write their SQL
right into their client-side code, or even into a query string,
like this:
- http://www.doobadoo.com/orders.php?query=
- query=SELECT%20*%20FROM%20ITEMS
- While doing so may be easy, it also may tempt an unscrupulous
visitor to type the following, just to see what happens:
- http://www.doobadoo.com/orders.php?query=
- DELETE%20FROM%20ITEMS
- Hopefully, you've set the permissions in your database to
prevent users from deleting your data like that. But just in
case the security is off momentarily, you're better off making
the front end a little less transparent. Even if you've set up
safeguards on the server end to prevent unauthorized changes to
data, putting SQL queries into query strings, hidden fields, or
client-side JavaScript code may tell hackers more about your
database than you'd want them to know.
Tip: Liberate code from element names with the JavaScript eval() function
- In a previous tip, we showed you how useful the eval() function
can be for dynamically testing the values of various JavaScript
properties. Another effective use of eval() is to refer to form
elements no matter what you've named them.
- For example, suppose you have an HTML form whose name attribute
is frmOrder. Let's say it has 5 different <input> elements with
the attribute settings type="checkbox" and name="myItem". To read
whether each check box is checked, you might use code like this:
- var bChecked;
- for(var i = 0; i < 5; i++) {
- window.status = i;
- bChecked = document.frmOrder.myItem[i].checked;
- //Code doing something with bChecked
}
- However, that only works if you know the form's name is frmOrder
and the check box name is myItem. What if, instead, you have
multiple forms, but you want one function to handle them all? In
cases such as this, the eval() function comes in handy, since it
executes any string you feed it as if you had written that string
directly in code. This feature allows you to generalize your code
so you don't have to write an unmanageable plethora of different
versions. Here's a sample function using this technique:
- function processForm(frm, chkboxes)
- var bChecked;
- for(var i = 0; i < 5; i++) {
- window.status = i;
- bChecked = eval("document." + frm + "." +
- chkboxes + "[" + i + "].value")
- //Code doing something with bChecked
- }
Tip: For future compatibility, use hexadecimal character encoding
- To display a character to the user instead of having the browser
try to interpret it as code, you use character entities (i.e.,
escape sequences). You may be used to writing these in decimal
format; for instance, to display the less-than symbol (<), you
may write the following (with leading 0s being optional):
- However, the latest W3C proposed recommendation "Character Model
for the World Wide Web 1.0" recommends that you write such escape
sequences in hexadecimal. The reasoning is that now that Unicode
is the standard text format (to accommodate the use of characters
different languages), hexadecimal will become more common, and
decimal representations of characters less common. Hence, to
write the less-than symbol, insert the letter "x" to show the
number is hexadecimal, and then write 60 in base 16, which comes
out to "3c." As a result, you'll get this:
- Of course, both < and < display as the character
"<" in modern browsers. But in the future, the second form may
become easier to look up in reference sources.
- You can find the Character Model for the World Wide Web 1.0 at
the following address:
Tip: Dynamically change a Web page from the
client side with innerHTML and innerTEXT
- If you need your Web page to change in
response to a user action, but no new information is needed from the server,
it's often desirable to make the changes take place on the client side.
As long as users have JavaScript enabled, page changes can take place much
quicker and more smoothly on the client side than they could if you had to
reload the page. The innerHTML and innerTEXT properties of the document
object can help you make these quick page changes. Both properties
replace the contents inside a tag with the text you specify. However,
innerText encodes any markup symbols you use so that they're displayed as
text, whereas innerHTML interprets whatever you pass it as HTML.
- As you may know, these properties originated
in the Microsoft Internet Explorer browser. The developers of the
Mozilla Web browser have added them to their JavaScript DOM as well. As
a result, you have the ability to dynamically change Web page content in IE
4.0+, NN 6.0+, and Mozilla 0.9+, like so:
- <head>
- <script language="JavaScript" type="text/javascript">
- function changeMe(){
- var mylink =
document.getElementByID("myLink")
- mylink.innerText = "Wow, I changed it!"
- }
- </script></head>
-
- My Other Page
- <form><input type="button" value="Click"
onclick="changeMe()"/></form>
- Do keep in mind that when you make changes
this way, the altered version of the page won't show up in the browser
history; so if the user goes to another page and returns using the Back or
Forward button, the original version of the page will show. Also,
remember that the related properties, outerHTML and outer Text, aren't
supported by Netscape.
Tip: Quickly validate your markup against W3C specifications
- As part of any production QA testing, you'll naturally want to
test your site to see how it stacks up against the World Wide Web
Consortium (W3C) specifications. While many tools exist for doing
so, one of the best comes straight from the W3C itself.
With this tool, you can test HTML or XHTML in all versions -
everything from HTML 2.0 to XHTML 1.1. To use this tool, head on
over to http://validator.w3.org/,
enter the URL that you want to validate, and follow the steps
from there.
Tip: Don't let your error messages give hackers
any ideas
- Unless you make sure that you have a good
error handling covering your entire Web site, the user may see certain things
that could compromise security. For example, error messages may give
away what type of database is being used, what the driver is, what the table
and fields are, etc.. Hackers can use this information to work their
mischief. Of course, simply having a message that says "Sorry, there was
an error" isn't very helpful for debugging purposes. Therefore, it's
very important to make sure you log any errors, as well as a recommendation to
save that information. You might also give the user some sort of ID
number referencing the error that's being logged. Make sure that during
a support call, you have all the information you need to fix the problem, but
don't give too much information away to potential hackers in the process.
Tip: Display dynamic forms based on user selections
- One great way to save web page real estate is to only display as
much content to the user as they need at any one time.
Fortunately, CSS and JavaScript offer you a great way to do just
that. For instance, suppose you have several different forms that
you want to display based on additional user selections. The
following code shows an example of how to do so:
- <html>
- <head>
- <style type="text/css" rel="stylesheet">
.answers {display:none;}
- </style>
- <script language="JavaScript">
- function showForm(obj) {
- var formName = "form" + obj.value
-
var theForms = document.getElementsByTagName("form")
- for (var x=0; x < theForms.length; x++) {
- theForm = theForms[x]
- if (theForm.className == "answers") {
- vis = (theForm.id == formName) ? "block": "none"
- theForm.style.display = vis
-
}
- }
- }
- </script>
- </head>
- <body>
- <form>
- <h3>Choose a test from the list:</h3>
- <div><input type="radio" name="choice"
- onclick="showForm(this)" value="1">Mathmatics</input></div>
- <div><input type="radio" name="choice"
- onclick="showForm(this)" value="2">English</input></div>
- <div><input type="radio" name="choice"
- onclick="showForm(this)" value="3">History</input></div>
- </form>
- <form class="answers" id="form1">
- <div>Enter answers to the following:</div>
- <div>2 + 2 = <input name="ans1" size="4"></div>
- <div>5 + 1 = <input name="ans2" size="4"></div>
- <div>5 * 2 = <input name="ans3" size="4"></div>
- <input type="submit"/>
- </form>
- <form class="answers" id="form2">
- <div>Select your favorite book:</div>
- <div><input type="checkbox" name="ans4">Tom Sawyer</input></div>
- <div><input type="checkbox" name="ans4">Moby Dick</input></div>
- <div><input type="checkbox" name="ans4">Oliver Twist</input></div>
- <input type="submit"/>
- </form>
- <form class="answers" id="form3">
- <div>Enter five important dates: </div>
- <div><textarea rows="10" cols="60"></textarea></div>
- <input type="submit"/>
- </form>
- </body>
- </html>
Tip: Don't let your query string design turn your site into a
hacker's playground
- In a previous tip, a reader recommended a useful way to
architect a site for showing photos embedded within web pages for
fuller functionality. His solution was to pass in the photo name
with a query string, like so:
- <a href="picture.html?photo=photoA.jpg"><img
src="th_photoA.jpg"
alt="Thumbnail of photo A"></a>
- Then, in picture.html, at the place where you want to display
the photo, you could write something like this:
- <script language="JavaScript">
- // Get the value of the "photo" query item
- var photoFile = window.location.search.substring(1).split("=")[1];
-
- // Use that to write out the <img> tag
document.write('<img src="' + photoFile + '">');
</script>
- While this simple example demonstrates a good design for
avoiding creating a zillion web pages (one for each photo), you'd
need to adapt it a bit for security purposes to use it in a real
site. In the example, we simply write information from the query
string from the page, all with client-side code. This enables us
to demonstrate the technique without
getting into server-side code, etc. But in a real-life
situation, you'd need to validate the data from the query string
against known, valid choices, or at least encode it properly.
- Here's why: If you
use query string data to compose your page on the fly, you now
run the risk of somebody composing a malicious link to your site
and sending it to other users to click on with potentially
disastrous results. An email that originally said "Check out this
sweater, I think it'll go great with my hot pink leather pants"
and a link along the lines of
- "picture.html?photo=photoA.jpg"
- could easily be changed by a bad guy so the link is:
- This new link will show questionableImage.jpg from
evilhacker.com. Or the bad guy could change the link to the following:
- The URL is from your site, but will cause your page to redirect
users to evilhacker.com/lookslikeyoursite.html. Any script could
work here, including one that sends your cookies to
evilhacker.com for collection.
There are a ton of evil things somebody could do with this type
of setup (session riding, cross-site scripting, and others). So
if you want to use the query string, first validate/sanitize the
data before using it to render the page.
Tip: Be careful of how skipped lines affect
formatting in your HTML and XSLT code
- It's generally best to make your HTML code
as readable as possible. Indenting and skipping lines can help if you or
someone else ever needs to modify the code later on. However, you have
to be careful that you don't adversely affect the document formatting in the
process. For example, consider this HTML code:
- Contact
-
- ___Edgar
- __
-
- or
-
- ___Alicia
- __.
- The way the beginning and end tags are put
on separate lines looks very pretty. But unfortunately, the links will
look a bit odd on a browser because you'll see an underlined space after the
names. So it's better to put the end tags immediately after the names:
- Contact
-
- _____Edgar
-
- or
-
-
- _____Alicia.
- If you're working in XSTL, the same
principle applies. With XSLT, code readability is crucial, but it's
often too easy to forget that skipping lines can affect formatting. In
the following code, if you move the end tag () to the end of the previous
line, you'll fix the problem:
- ____<xsl:value-of
select="contacts/first" />
- __
Tip: Use query strings to organize your images
- In a previous tip, we suggested that if you fashion your site's
thumbnail images into links so that visitors can click to view a
larger image, it may be nice to actually link to an HTML page
that includes more information than just the picture. As we
noted, if a user wants to take further action on the item (e.g.,
buy it), this design allows him to do so without having to use
the back button (and possibly changing his mind).
- If you
implement this approach by creating a separate web page for each
picture, you could end up with unruly code that's a pain to maintain.
- Here's the solution to make the design more manageable:
- To provide an online photo album you might have a whole array of
thumbnails, each of which take you to a page that displays the
larger photo (potentially with additional information). Rather
than creating a separate HTML page for each large photo, just
pass the photo name in on the URL:
- <a href="picture.html?photo=photoA.jpg"><img src="th_photoA.jpg"
alt="Thumbnail of photo A"></a>
- Then, in picture.html, at the place where the photo is to be displayed:
- <script language="JavaScript">
// Get the value of the "photo" query item var photoFile = window.location.search.substring(1).split("=")[1];
- // Use that to write out the <img> tag
document.write('<img src="' + photoFile + '">'); </script>
- Now it will display whichever file is passed
in.
Tip: Force Internet Explorer to display
design-time changes to a Flash animation (IE 5.x+, Macromedia Flash MX)
- While Macromedia Flash MX lets you quickly
test a Flash movie at design-time, you'll often want to see how the animation
works in the browser. If you've ever worked with a Flash animation in
IE, however, you may have encountered some bizarre results. In short, if
you load an animation in Internet Explorer, modify the underlying Flash file,
resave the movie, and then press [F5] to refresh the browser window, the movie
in IE won't reflect the changes.
- This problem occurs because ID always uses
the Flash file that it has cached on the local PC. To fix this behavior,
you'll need to erase the files from the cache. In IE, to do so, select
Tools | Internet Options from the main menu. Then, when IE displays the
Internet Options dialog box, click the Delete Files button in the Temporary
Internet Files section on the General tab. Click OK after IE completes
the operation. Now, press [F5] to refresh the Web page. When you
do, IE updates the animation to reflect your recent changes.
Tip: Extract a query string from client-side JavaScript
- One of the most commons ways to communicate information to a web
page is through a query string. As you may know, a query string
is a string of characters in the URL that follow the filename and
begin with a question mark. For instance, if you search for
JavaScript on Google, you might see this query string at the end
of the URL in your address bar:
- Unless there's a problem with allowing the data to appear in the
address bar, query strings are extraordinarily helpful--especially
if you need to process the data before any hidden fields or other
portions of your page have had time to load.
- The common wisdom is that to extract the query string, you'll
need server-side code, such as ASP, Perl, or PHP. However, as
long as your page is being accessed through a web server, you can
actually grab the query string from the client side. You do this
from the location property of the window object. This property
has a child property called search, which contains the query
string, beginning with the ? character. Removing this character
via the substring method, you can now write out the query string,
like so:
- var querystring = window.location.search.substring(1);
- Of course, you may want to access certain parts of the query
string. You can do this with various string methods, such as
split. For instance, suppose your application points the browser
window to the following URL:
- http://www.my_application.com?color=yellow&size=2
- You can parse out the pairs (color, yellow) and (size, 2), with
code similar to the following demo:
- var querystring = window.location.search.substring(1);
- var pairs = querystring.split("&");
- var i;
- var pair;
- for(i in pairs) {
- pair = pairs[i].split("=");
- alert(pair);
- }
Tip: Tools for using XML with XSLT
- If you're working with XSLT, you'll want to
have the right tools to be able to develop, text, and debug your code.
You'll also want to make sure you have an XML parser that supports XSLT and is
appropriate for your Web server.
- Although Internet Explorer will convert your
document to XHTML for viewing, it won't show you the XHTML code that it
produced. For example, if you right-click the page in the browser window
and select View Source, you'll just see the code in your XML document.
Fortunately, there are many standalone parsers you can use to develop and test
XML with XSLT. One such parser, called XT, is an open source, Java-based
parser available at www.jclark.com/xml/xt.html. You might also consider
xmlspy (http://altova.com/features_xsl.html) and various tools from TopXML
(http://topxml.com/parsers/other_parsers.asp).
- For information on XML parsers for various
servers, here are some useful sites. If you use Internet Information
Server, refer to the Microsoft XML Web site (http://msdn.microsoft.com/xml).
If you use Apache, see http://xml.apache.org. Finally, for IBM WebSphere
users, check out http://www-4.ibm.com/software/webservers/appserv.
Tip: Six reasons why errors occur only for clients
- One of the corollaries of Murphy's Law is
that code breaks as soon as a user tries it. If you're having difficulty
duplicating a user's problem on your own machine, here are some of the most
common reasons:
- * Your server-side code generates the HTML
for the page based on data associated with certain user information (e.g.,
user privileges). Perhaps, since you're logged in as a different user (e.g.,
the administrator), you aren't viewing the same HTML as the user is, even
though you're pointing to the same URL.
- * You're connected to a development
version of the site, whereas the user is connected to the production
version, and there's a difference between the two sites, their databases, or
their web server settings.
- * Something in a web page points to an
address on your machine or local intranet that isn't available to the
client.
- * The application is relying on a
client-side component that's on your machine, but not on the user's.
- * You and the user have different browser
versions.
- * The code makes assumptions about
settings that a user can configure; these may include browser settings, as
well as operating system settings (e.g., Windows settings under Regional and
Language Options, or under Display Options).
Tip: Do a quick test of Perl CGI code with -c (Perl)
- Sometimes, you may want to test whether your Perl syntax is
correct, without actually running the script. For instance, a
complex CGI script may not make sense when you just run it from
the Command Prompt, but at least you can check for obvious
errors. You can do so with the following command (substituting
your actual filename for filename):
- This command checks syntax only--not whether
your code will run without error. Just make sure the c is lowercase.
Tip: Simplify your code by using a single cross-browser solution
- In the old days, cross-browser JavaScript effects relied heavily
on branching cases in code for just about everything that had to
do with referring to and positioning elements. However, getting
into the habit of using commands that work across modern
browsers--instead of always branching--saves you a lot of time in
the long run. Hence, even if you're coding a workaround for IE,
it's still a good idea to construct a solution with commands most
likely to work in other browsers. That way, if you extend the
technique and decide you do want the code to run in those
browsers, you won't have to make too many changes. Consequently,
we favor commands such as document.getElementById instead of
document.all, and style.left instead of style.pixelLeft.
Tip: Leverage your JavaScript skills with
Flash's Action Script (Macromedia Flash MX)
- If you've wanted to generate dynamic Flash
animation content but were afraid you'd have to learn a whole new language,
don't worry. Flash's scripting language--called ActionScript--is very
similar in syntax and functionaity to JavaScript. That's because
Macromedia based ActionScript on the W3C's ECMAScript specification. So,
even though some of the Flash functionality via ActionScript will be the same
as any other client-side script.
Tip: Create your own custom modal dialog boxes for intranet web applications
(IE 5+)
- One common feature of desktop applications
is the modal dialog box. This is a dialog box that a user must close (or,
typically, perform an action triggering the window to close) before she can
bring the application's main window back into focus. While it's very important
not to abuse this power over the user, there may be times when you want a
modal dialog box in your web application. Obviously, you can do this with
JavaScript's alert() method, but that can be somewhat limiting. However, if
you're writing your application for an intranet and everybody's using
Microsoft Internet Explorer, you can create your own custom modal window with
the showModalDialog() method. For instance, to open a web page in a modal
browser window, just use this JavaScript code:
- vReturned = window.showModalDialog("http://www.elementkjournals.com");
- This works similarly to window.open(), but
the arguments are a little different. For instance, there's an optional second
argument that helps you to pass data to the new window, and an optional third
argument to control window features, such as size. Finally, if the new window
sets its returnValue property to a value, it will get passed back to
showModalDialog(). When the user closes the new window, showModalDialog()
returns that value. For instance, suppose you write this JavaScript:
- vReturned =
window.showModalDialog("myDialog.html"); alert(vReturned);
- Then, suppose you write this JavaScript in
myDialog.html:
- After the user closes myDialog.html, a
dialog box will appear with the number 5. Pretty nifty! Of course, if the user
clicks on something other than either of the two browser windows, she can get
back to your main window without closing the dialog box window; so it's not
100% modal.
- Finally, one other alternative you can use
that works similarly (minus the features to pass data back and forth) is to
simply open a window with window.open() and add the following onBlur event to
the new window's body tag:
- <body onBlur='javascript:this.focus()'>
- Unlike showModalDialog, this will work on
non-IE browsers without error, although you still may not get the modal effect
with the other browsers.
Tip: What's worse: a false positive or a false
negative? Scenario planning helps minimize the damage
- As a Web developer, you probably know that
even with perfect code, a number of factors can get you in trouble - different
browsers, adventuresome users, and other developers changing things.
That's why it's good to do some "What if..." scenarios. For example, if
your code checks for a certain condition, consider the potential consequences
of failure: Is it worse if your code reports finding something that
isn't really there (false positive)? Or is it worse if your code fails
to detect something that is there (false negative)? By analyzing
potential scenarios from the user's perspective, you can guide your
programming decisions and error-handling to minimize the damage when things go
wrong.
Tip: Use a diagnostic function to help test JavaScript properties
- When experimenting with JavaScript properties, it's helpful to
test which values they're returning so you know you're using the
right property in the right way. To quicken the testing process,
you can write the results of various properties with the
following function:
- function testit(strElem,strProperty) {
- var elem = document.getElementById(strElem);
- document.write(strElem +
- strProperty + ": <b>" +
- eval("elem" + strProperty) + "</b><br>");}
- You pass the ID for the element you're testing into the strElem
parameter, and the property (starting with the period) into the
strProperty parameter. The function creates a reference to your
element, and then writes out a diagnostic line on your page,
showing the ID and property for easy reference. Finally, it uses
the eval() function to turn that property (which you passed in as
a string) into an actual property that JavaScript can process.
- To make it easier for you to identify which properties match
what you see on the page, you can also take advantage of IE's innerText property to return characters displayed in the element.
For this variant, replace the line starting document.write with
code similar to the following:
- if(elem.innerText) {
- var strRef = "Line starting “" +
- elem.innerText.substr(0,18) + " ...” "
}
- else {var strRef = strElem;}
- document.write(strRef +
Tip: Create dynamic, custom-named JavaScript variables with eval()
- At times, you may need to generate variable names dynamically
and then use those variables in a larger JavaScript function. For
instance, you may want to pass in a variable name to a JavaScript
function, perform some calculations on that variable, and then
display the results along with the variable name.
- JavaScript's eval() function provides the perfect way to
accomplish this task. This function forces an expression
evaluation on a string. In other words, JavaScript will treat
whatever you place in the function as if it were a code
statement, and then it will return the results of that statement.
So, the following expression:
- would return the number 6.
- We can use this behavior to our advantage when creating
customized variable names. The following web page shows how to do so:
- <html><head>
<title>Customized variable names</title>
<script language="JavaScript" type="text/javascript">
function test(varName) {
eval("var " + varName + " = 3")
eval(varName + "+= 7")
document.write("<h3>The current value of " + varName + " is: " +
eval(varName) + "</h3>")
}
</script></head>
<body>
<script language="JavaScript" type="text/javascript">
test('MyVariable')
</script>
</body>
</html>
- Of course, as you can see, the one disadvantage of this
technique is that you must use eval() in your code whenever you
want to use the actual variable value and not simply its name.
Tip: Shorten absolute URLs with the <base> element
- If your page features lots of absolute links all with the same
base URL, this means your HTML code is repeating practically the
same address over and over. All this duplication can make your
code less manageable--especially if the base URL is long, or
liable to change.
- You can streamline your code by including the base URL inside a
<base> element. Then, all your relative links function as
absolute links having that base address.
- For instance, suppose you have a link like this:
- <a href="http://www.extra_long_domain_name.com/
doc.html">Click
here</a>
You can shorten it by including the following code in your
<head> section:
- <base url="http://www.extra_long_domain_name.com">
With that <base> element in place, you can now link to the same
page by using a relative link, like so:
- <a href="doc.html">Click here</a>
If your page is at http://www.start_here.com, such a link would
normally go to http://www.start_here.com/doc.html. But because
of the <base> element, it now goes to http://www.extra_long_domain_name.com/doc.html instead.
When using the <base> element, you should keep a few things in mind:
* Officially, the <base> element isn't supposed to have an end tag.
* You can only have one <base> element per page
* All your relative links will automatically use the same base
URL. To override this behavior, you'll need to create an absolute link.
* While in theory you can use a relative URL inside the <base>
element, this isn't guaranteed to work--so you're best off
sticking to absolute URLs inside <base>.
Tip: Want to know where Internet protocols are
listed?
- There's probably no better place to look for
information on such things as domain names, MIME Media Types, and other
Internet protocols than the Internet Assigned Numbers Authority at
www.iana.org. For example, at www.iana.org/domain-names.htm, you can see
that there's a .org, a.biz, and a .com - but no .con (though perhaps there
should be). The various MIME Types are listed at
www.iana.org/assignments/media-types/. In addition to the list of MIME
Media Types, this page features links to the specifications that explain in
more detail what MIME is. And the IANA site also contains links to other
organizations involved with Internet standards such as the W3C (www.w3.org/)
and the Internet Architecture Board (www.iab.org/iab/).
Tip: For ultimate cross-browser functionality,
do custom browser-sniffing
- One of the key techniques to make sure your
code works on all standard browsers is to determine the current browser being
used. You can get this information from JavaScript properties such as
navigator.appName and navigator.userAgent. But there's no guarantee that
a non-standard browser won't disguise itself as a more popular browser such as
Internet Explorer or Netscape. And who knows what values will be
returned from appName and userAgent in future browsers?
- So if you need your code to work on any sort
of browser, the ultimate solution is to add your standard browser-sniffing by
looking for those properties you're really interested in. JavaScript
gives you the ability to check if a property exist, as in:
-
if(document.IsThisAPropertyOfTheDocumentObject) {
- //code if it exists
- } else {
- //code if it doesn't exist
- }
- So if the client browser in question
supposedly doesn't support something it should, you still have ways of
protecting yourself. In fact, as the table below shows, you can learn a
lot about browsers just by the way they behave.
- Browser will respond in the affirmative in
an if statement:
- Nextscpe 4.x document.layers
- Internet Explorer 4.x document.all && !document.getElementById
- Internet Explorer 5.x document.all &&
document.getElementById
- Netscape 6.x, 7.x document.getElementById
&& !document.all
Tip: Make sure your business requirements make
sense with Use Cases
- A perfectly-coded Web application isn't much
use if it's based on business requirements that don't make sense to begin
with. Unfortunately, clients may not carefully think through what they
ask for, and the result may be a Web application whose flaws are only apparent
once it's used. The Use Case approach is one way to make sure that you
business requirements are logical.
- Use Cases are basically business
requirements stated in the form of scripts showing how a user interacts with
the system (e.g., Web application). Typically, they document the main
steps and choices that are applicable to the user, and the main responses
returned by the system. They can be very good at helping you think of an
iron out various high-level issues. For example, to create a Use Case
document, you need to continually ask questions of the form "What happens
if.." Getting those key questions answered before development begins is
crucial to avoid the need for last-minute questions--or, worse, the need to
redo development work because of missing or illogical requirements
specifications.
- However, it's important not to expect too
much from you Use Cases. Use Cases aren't the place to document highly
specific user interface information, because that kind of information would
likely distract from the main purpose of the Use Case method, which is to
ensure that high-level requirements are thought though. So you'll still
need to do some further UI design work after the Use Case documentation has
been finalized.
Tip: HTML comment gotchas to be aware of with (JavaScript)
- You've probably heard about using HTML comments (<!-- and -->)
to hide JavaScript code from really old browsers that doesn't
support JavaScript. While this practice can sometimes come in
handy, you need to be a little bit careful, because browsers
don't always honor the comments 100 percent. For example,
consider the following JavaScript code:
- <script type="text/javascript" language="JavaScript">
- <!--
- alert("</script>");
- -->
- </script>
- Although this works in IE, we've found that in Strict mode,
Netscape 7 and Mozilla read the "</script>" string as signifying
the end of the script, completely ignoring that it's inside an
HTML comment.
Another mistake that people sometimes make in comments is
putting some of their JavaScript on the same line as the HTML
closing comment symbol. For example, the following code will give
you an error:
- <script type="text/javascript" language="JavaScript">
- <!--
- function MyFunction() {
-
//code
- }-->
- </script>
Tip: Don't get taken in by the domain name myths
- Coming up with a good domain name for your Web site doesn't have
to be a chore--as long as you stay clear of some common
misconceptions. For instance, people often assume that having a
domain name similar to another site is a bad thing. This is
generally true for large corporations and portals servicing
business clients. But it isn't necessarily true for a small
consumer-oriented business. In fact, many eCommerce sites get a
lot of business by having a domain that's similar to an existing
one. Web surfers get confused, type in the wrong address, and end
up on your site--which hopefully is so wonderful that it wins
them over before they recognize their mistake.
- Another common misconception is that your domain name needs to
be a common word. While owning an obvious name choice can give
you some hits and lend certain credibility in the eyes of Web
users, memo ability is probably the most important criterion if
you're trying to build a brand. So, your name doesn't really need
to mean anything relevant, as long as it has the right emotional
appeal. Just think of Google, Yahoo!, and Amazon. And don't
forget that you can always buy up some related domain names and
redirect them to your site.
Tip: Don't get carried away with CSS classes
- CSS classes give you tremendous power to
make your styles completely contradict the standard structure of available
tags. You could use classes to make
- sometimes very big, and sometimes very
small, and sometimes much smaller than
- or .
You could make cause text to be slanted and
to make it bold. But don't get carried away! Using classes in this way
will cause your code to be undecipherable and hard to manage. And it
may make your site look unorganized - especially if you add an element and
forget to add your special class. So be careful; use CSS classes
wisely!
Tip: Make sure your Web page content contains
itself
- Often, when coding a Web page, you may be
tempted to leave specific portions of text without any XHTML markup
whatsoever, as seen in the following snippet:
- This content can't contain itself!
- <div class="header">This text is very
contained.</div>
- While for the most part, this markup will
work in most browsers, we encourage you not to code this way for several
reasons.
- First, in order to format the container-less
text, you must style the tag. Under CSS guidelines, the tag's formatting
cascades to the text. However, that's the *only* way you'll be able to
format the text. Without placing the text inside a container, you won't
have the fine control over formatting and positioning that you often need in a
Web page.
- Second, if a browser uses XHTML and the
Strict DTD to access the Web page, the site will fail. That's because
the Strict DTD requires that all content be contained.
- Of course, providing such containers is a
breeze. Simply lace any such orphaned text into a <div> or <span>, like
so:
- <div>This content can't contain
itself!</div>
- <div class="header">This text is very
contained.</div>
Tip: If you don't want margins, you need to let the browser know (CSS)
- Sometimes, you may want the ability to put content right up
against the edges of the browser's viewport. While you can force
this to happen using absolute positioning, you may have found it
difficult when such a workaround isn't what you want.
- The reason why content doesn't start right
at the top-left edge is because of margins. If you don't set the top and left
margins for the <body> element, you may think this is equivalent to
setting them to 0px. But that's not actually true. Browsers have
built-in stylesheets that cause the <body> element to display as
if you had set some margins. For example, in Microsoft Internet
Explorer, you actually get a default left margin of 10px and a
top margin of 15px. If you need to override these defaults, you
can do so with the following code:
- <style>
-
body {margin-left:0px; margin-top:0px;}
- </style>
Tip: Create nice background colors with pastels
- Often, when using a background color on your
Web page, you'll want something light-colored enough to allow the text to
stand out. there are many pastel colors you can use that provide a nice
color flair to your site while not being overly dark. Instead of
sticking with boring colors such as light blue, for example, try lavenderblush,
seashel, and mintcream.
Tip: Don't let short-sighted browser detection cause embarrassing messages
and malfunctions
- Few Web experiences are sillier than when a
user browses to a site with Microsoft Internet Explorer 6 and gets a dialog
box saying "This site is best viewed on Internet Explorer 5 or above. Please
update your browser!" The next-silliest thing is when a page's JavaScript
silently fails, merely because the latest browser didn't register in the
outdated browser-sniffing routine as being new enough.
- These problems happen because of
browser-checking code that looks for an exact match with a particular version
and assumes that any other version won't work. For instance, here's a typical
browser-checking line:
- if(navigator.appVersion.indexOf("MSIE 5")
!= -1) {isIE5=true;}
- If the variable isIE5 doesn't have the value
of true, the code then assumes the browser isn't up to date. If you must check
for a certain browser version (instead of just checking for certain
properties), a more extensible solution would be to at least check for
versions greater or equal to a given number. For instance, the following code
checks for MSIE 6 and above:
- var result = navigator.appVersion.match(/MSIE
[\d]+/g); if(result[0]) { if(result[0].slice(4) >= 6) {isIE6Plus = true}; }
- While it's true that we don't know if there
will ever be a backward-compatible browser returning MSIE 7, we do know that
something will probably replace IE 6 in the future, and IE 7 is as good of a
guess as any.
Tip: Assign different styles to different
elements of the same CSS class
- Often, when you create a Web page with CSS,
it makes sense to assign the same class name to different HTML elements.
For instance, you might have a 'para' class that will contain paragraph text,
but you want two different HTML element types assigned that class, as
in:
- <div class="para">Nutgraf 1 </div>
- Nutgraf 2
- To assign these elements the same
font-family, you'd use something like so:
- However, you may have wondered how to assign
different fomats to the same CSS class, without further assigning each element
with a unique ID attribute, that is.
- Fortunately, all you need to do is
fully-qualify the CSS declaration for each element. So, for instance, to
make the text in a <div> of class 'para' red, you'd use:
- and to make the text in the element of class
'para' green, you'd use:
- Presumably, these two elements would share
similar CSS formatting. However, you'd probably also want to assign
different formats to each element, as well.
Tip: A quick little JavaScript email validation routine using regular expressions
- There are lots of ways to verify that you have a valid email
address. JavaScript's regular expressions capability provides one
of the most concise methods. Here's a quick little function you
can use to verify that the argument sEmail follows the standard
email format:
- function isEmail(sEmail) {
var regEmail =
/^([\w-]+\.?)*\w+@([\da-zA-z-]+\.)+[a-zA-z]{2,6}$/;
return regEmail.test(sEmail);
}
- Note that this only checks the length of the extension, not
whether it's an actual top-level domain. Currently, the
extensions for top-level domains consist of anywhere from two
letters (for country codes) to six letters, such as .museum. If
you want to further and verify the top-level domain (perhaps in
your server-side code), you'll need to get a hold of the official
list. You can get all the current domain suffixes and information
on organizations that register and maintain these names from the
Internet Assigned Numbers Authority (IANA) site at www.iana.org.
Tip: Use "return" to make JavaScript form
validation work
- Perhaps the first thing people talk about
when discussing the role of client-side JavaScript is form validation. You've
probably heard something like this: "Use JavaScript to validate form entries
so you don't waste the user's time with unnecessary trips to the server."
- But as simple and obvious as that advice is,
there's a little piece that's easy to forget: namely, how to properly hook
your validation code into the submission process. For instance, let's say you
have a nice little form. When the user presses the Submit button, it posts to
another page--say, EmailFormPost.asp. Then, you write a nice little validation
script to check that the form is entered correctly (e.g., all required fields
are filled, no obvious syntax errors). If everything's correct, you make your
function return true, otherwise false.
- But one little tiny thing's lacking: How do
you make sure the submit takes place only if the function returns true, and
not if it returns false? You might get a bit frustrated if you try something
like the following <form> tag:
- <form method="post" onSubmit="ValidateForm()"
action="EmailFormPost.asp" name="mailform">
- This looks as if it should work, because
ValidateForm() is a function, and we set the onSubmit equal to it. But
actually, it doesn't work that way. Instead, you need to use the word "return"
to actually feed the value back so it halts the submission if the function
returns false. Here's the correct way to call the function:
- <form method="post" onSubmit="return
ValidateForm()" action="EmailFormPost.asp" name="mailform">
Tip: Expert tips for crating HTML emails
- Since most modern email clients have the
ability to display emails as full HTML documents instead of plain text,
there's no reason not to take advantage of this new option. When you do
create HTML emails, however, keep these following tips in mind:
- The offer's landing pages should be
designed in a clean, yet inviting way. Limit graphics. Design is
key. As you know, designing for the Web is different than designing
for print. Make sure your design maps to the medium.
- Integrate the look and fell of your Web
site in the message's design. The more your email ties in with your
Web site, the more comfortable and familiar it will appear to its
recipients.
- Keep it simple. Concentrate on one
topic at a time, and don't use complex HTML tags, Flash, nested tables, or
JavaScript.
- Send multiple formats. You should
have a version created just for AOL, a text version, and a HTML version.
- Use tables to organize information.
Stack multiple tables to keep things neat; don't nest tables within tables.
While many email clients will accept HTML emails, CSS support is still
spotty.
Tip: When you need to develop at a breakneck
pace, keep your toolset manageable
- Sometimes, you need to develop something in
a hurry and there's no time for frills. The secret to fast Web development is
to keep the total amount of needed information low. Your production process
comes to a halt every time you must look something up, so avoid doing that.
Instead, concentrate on a small, well-known set of tags and styles--ones you
can recite from memory straight into the document. You might pick a handful of
tags from the HTML 4.01 standard, and a handful of style properties from the
CSS2 standard; use those and no more. A smallish set that relies heavily on
use of class and id attributes is: * HTML tags: <html>, <head>, <title>,
<script>, <style>, <body>, <div>, <span>, <img>, <ul>, <ol>, <li>, <a>,
<form>, <input>, <select>, <option>, <textarea>, <table>, <tr>, <td>,
<object>. * CSS properties: background, border, color, display, float, font,
list-style, margin, position, text-align, vertical-align, z-index. Add top,
left, width, and height if you must. The flexible HTML parser will forgive you
for small errors, and if you resist the urge to specify spacing between
elements, then you can avoid a lot of layout effort. Efficient page design
really stems from controlling what you pour into the page in the first place.
If the page needs a fancy feature, you can always step back and add that
later, when the routine content is finished.
Tip: Watch your use of single and double
quotes in JavaScript
- Some syntax errors are just waiting to
happen. Sure, they're easy to correct, but it's better to find ways to
avoid them in the first place than having to take the time to debug them
later. One of the JavaScript areas where it's easy to make a mistake
is quotation marks.
- As you probably know, in JavaScript, you
can encapsulate strings with either single or double quotations. This
becomes useful when you're writing JavaScript with JavaScript - for example:
- document.write("strTitle = 'Here I
am!'")
- You can also nest double quotes inside
single quotes, instead of the other way around:
- document.write('strTitle = "Here I
am!"')
- A similar case occurs when calling
JavaScript from an event in HTML, such as:
- <input type=button onclick="JavaScript:alert('Here
I am')">
- You can also switch the single and double
quotes here, although that's non-standard.
- the biggest potential problem comes when
you include a a quote or apostrophe that's part of a literal English phrase.
In that case, you have to use an escape sequence (e.g., \' to stand for '):
- <input type=button onclick="JavaScript:alert('It\'s
me!')">
- An escape sequence inside the JavaScript
is only going to work if it can't be confused by the HTML, and you can't
nest quotes more than two deep. For example, neither of these are
going to work:
- <input type=button onclick="JavaScript:alert('I
said, \"Here I am\"!'')">
-
- document.write("<input type=button
onclick='JavaScript:alert("Oh?")'>") //Won't work.
- You may think the only way to prevent
these errors is just to be more careful. There's another thing you can
do, however: Reduce the levels of nested quotations by storing strings
containing information to the user (e.g., English) into variables.
While this may take a little extra upfront time, it prevents the need for
corrections later on. and of course, if you do make a mistake, it's
easier to troubleshoot if the line that comes up with the error is just a
variable declaration.
- var strExclamation = "I said, \"Here I
am\"!"
- document.write("<input type=button
onclick='JavaScript:alert(strExclamation)'>")
Tip: Get information from the source to
write Web pages for hand-held devices
- If you're writing Web pages to be viewed
on hand-held devices, you'll need to know about the current standards and
specifications. Some of the places you can start are
- 1) www.wapforum.org to learn about the
WAP 2.0 standard
- 2) www.w3.org/TR/xhtml1/ and
www.xhtml.org to learn about XHTML
- 3) www.w3.rog/TR/xhtml-basic and
www.wapforum.org/what/whitepapers.htm to learn how to adapt XHTML to
hand-held devices.
Tip: More usable Web sites on usability
- In an earlier tip, we told you about the
site www.useit.com as a great source on usability. Here are a few
other usability sources.
- IBM' usability site is www-3.ibm.com/ibm/easy/eou_ext.nsf/Publish/558.
This site makes a lot of insightful points, not just the typical truisms you
sometimes find. The site is structured as a tutorial with some
interactive elements. We like that it's easy to see what the topic
areas are and where we are in the site. We also like that it doesn't
hit us with direct advertising (although we're sure there's probably some
sort of subliminal message going on there).
- Another Web site we found useful is
www.webstyleguide.com, which is really a book on the Web. We like that
it mentions specific examples and goes into some degree of depth.
Being an online book, it starts from the beginning, and doesn't assume that
the reader has a lot of Web-related background. You may find that
annoying if you're trying to get information very quickly; however, it's
worth reading through. A lot of the recommendations in this Web book
seem to be common sense, although they don't back back up their points with
lots of research the way useit.com does. Nevertheless, the site does
feature a good reference section.
- Finally, a simple but very useful
usability site you might not find unless you're looking carefully is
www.ss64.com/docs/site.html. This is part of an Oracle/NT/Linux
reference site (www.ss64.com/index.html), and it has some great links and
suggestions.
Tip: Learn how to improve your UI design: A
usable Web site on usability
- The decisions we make as Web developers
often have a big influence on whether people find our Web sites easy and
satisfying to use, and ultimately, whether they come back.
Unfortunately, it can take a long time to become a usability expert.
Worse, when you do look for information on usability, you may have to sort
through "mother and apple pie" sentiments such as recommendations to "be
sure to make your site easy to use" before you find any usable information.
Fortunately, we've found some Web sites to be very useful (and usable)
sources on usability.
- Here's one such site to get you started:
www.useit.com. We like several things about this site. The
articles get right to the point. They say things that aren't obvious.
They offer specific solutions that you can apply. They constantly
update it with new information. And, they back up their pints with
research results, which they sometimes display in some detail (although they
don't necessarily make it easy to find more information about how the
studies were performed). As you browse the site, you'll probably
eventually come to pages about various conferences, seminars, and other
information that isn't cheep. However, there's plenty of usable
information, even in the free section. this site may appear to have a
bias toward blander designs, but it makes a good case. It uses a very
bare-bones architecture, with no frames or menus, so it's clear that
useit.com practices the simplicity philosophy the preach.
Tip: Debug more effectively using the
window.status property
- When things aren't working quite right, it
isn't uncommon to try to debug what's happening by putting up message boxes
with information to help us figure things out, like this:
- alert("It got to this point. The
value of strMyVariable is " + strMyVariable);
- However, sometimes putting up an alert box
like that can change program flow enough to prevent a realistic view of
what's really going on. It's kind of like the Heisenberg Uncertainty
Principle in physics, where, in certain cases, what we do to look at the
problem changes it so much that we can't reliably tell what's going on.
- One quick and easy way out of this
conundrum is to use the window.status property instead. For example,
the following line puts the value of strMyVariable and the current date and
time onto the status bar at the bottom left-hand side of the browser window:
- window.status = strMyVariable + "" +
Date();
Tip: Resolve anomalies in testing
environments and on client sites by deleting or replacing the localstore.rdf
(Netscape Navigator 6.2+, Mozilla 1.0)
- When creating your Web application, it's
important to have a reliable browser for testing, so you're not spending
forever tracking down problems that aren't really in your code.
Sometimes settings on a browser can cause it to do unusual things, and there
isn't always a obvious way to fix these through the UI. In Gecko-based
browsers (Netscape, Mozilla), some key settings for the browser's behavior
are stored in the localsttore.rdg. Therefore, if you're experiencing
unusual behavior, such as browser windows that open to the size and other
odd problems, you can just delete that file, instead of deleting the entire
profile and losing all other settings. You can find the localstore.rdf
by looking for the path of the Cache under the Advanced option in
Preferences, which you may fine under the edit or Netscape menu, depending
on your operating system.
- The localstore.rdf and other files in that
directory may also be good places to look at if a client using Netscape is
experiencing problems that you can't duplicate in-house. Try having
the client create another profile to see if hat fixes the problem.
Also, have the client send you his localstore.rdf (or to be safe, that whole
directory) to help you duplicate the behavior. Keeping a profile with
some weird settings on hand and ready to go for testing may be helpful if
you get clients with these types of problems frequently. After all,
you know that some clients will manage to have these odd problems, and it's
always nice to make sure your application still works for them.
Tip: Let CSS position background images
exactly where you want them: Part 2
- In a previous tip, we showed you haw to
use the background-position CSS property to place a non-repeating background
image some place other than the default upper left-hand corner. We
described how CSS offered five built-in words to set this positioning: top,
bottom, left, right, and center. So, you might use these words to
define an image's position like so:
- background-position:bottom right
- However, in addition to these words, you
can also use actual values to assign a more detailed position to an image.
To this end, CSS lets you assign either percentages or actual length values
to the coordinates. So, for instance the property declaration:
- background-position: 50% 30%
- would position the image fifty percent
across and thirty percent down the element/page.
- When using length units, conforming
browsers will accept any of the standard units, like pixels, centimeters,
inches, and even ems. You apply these units the same as you do
percentages, as seen here:
- background-position: 135px 225px
- As you can see, these settings let you
have much more control over placement of background images than the built-in
words.
Tip: Let CSS position background images
exactly where you want them: Part 1
- If you've ever used CSS to display a
background image, you probably know that you can also control whether the
browser repeats the image. By default when you supply an image for a
background, like so:
- background-image;url(funky.gif)
- the browsers automatically repeat the
image across the entire background. To turn this repetition off, you
can use the
- background-repeat:no-repeat
- option. With this setting in place,
the browser will only display the image once.
- By default the browsers position the
background image in the element's upper-left corner. But what if you
want to place it elsewhere?
- Fortunately, CSS offers the
background-position property to do just that. With this property, you
must supply two setting values: one that defines the image's horizontal
position, and one that defines the vertical position, along the lines of:
- background-position:x-pos, y-pos
- The CSS spec offers you three ways to
assign these positioning values. We'll cover the first one in this
tip. and the remaining two in a follow-up
- The quickest way to assign a position to a
background image is to use a series of built-in positioning words: top,
bottom, left, right, and center. Naturally you can use center to
describe either vertical or horizontal positioning. Simply place them
in the CSS declaration and separate them with a space. So, to place a
background image in the center of an element, you might use the following:
- background-position:center center;
- or to place it at the bottom right corner:
- background-position:bottom right
Tip: Quickly sharpen the focus of blurred
images in Fireworks (4/MX)
- If you have images that are a bit blurry,
you can quickly correct them using the Sharpen filter. The Sharpen
filter offers three different options to choose from: Sharpen, Sharpen
More, and Unsharp Mask. The Sharpen option increases the contrast of
adjacent pixels to add focus to a blurred image. The Sharpen More
option increases the contrast of adjacent pixels three times as much as the
Sharpen option. To sharpen an image using one of these two options,
select an image in either vector or bitmap mode and choose Xtras > Sharpen >
Sharpen or Sharpen More, or choose Sharpen or Sharpen More from the Effect
pop-up menu on the Effect panel. To get the best results with the most
control, follow the previous steps, but choose the Unsharp Mask option.
With it, you can sharpen an image by adjusting the contrast of the image
edges by adjusting the Sharpen Amount, Pixel Radius, and Threshold sliders.
Tip: Easily loop through HTML form field
names with deft use of the elements[] property
- Often, you may want to refer to a form
field by number, so your code can process it automatically in a loop.
However, when you try this, sometimes the naming convention of those fields
can get the better of you. If the IDs of your fields are 1field,
2field, 3field, etc., then you can easily convert these into numbers with
parselnt(). However, it's a little more complicated when the number is
at the end, as in txt_1, txt_2, txt_3. And unfortunately, changing all
the field names late in the game could mess up other code.
- Of course, you can use regular expressions
and the slice() command to get at the numbers, but another approach is to
set up your loop in a way that avoids all that parsing. For instance,
suppose you have the following form:
- <form id="myForm" name="myForm">
- <input type="text"
size="20" id="txt_1"/>
- <input type="text"
size="20" id="txt_2"/>
- <input type="text"
size="20" id="txt_3"/>
- <input type="text"
size="20" id="txt_4"/>
- <input type="text"
size="20" id="txt_5"/>
- </form>
- Now suppose you want to set a range of
textboxes to a certain value, starting from a certain field number, and
ending at another field number (e.g., change fields with IDs containing the
numbers 2, 3, or 4, but not 1 or 5). You can do so with the following
JavaScript function:
- function fill(val,start,finish) {
- for (var x=start;x<=finish;x++){
-
document.myForm.elements["txt_" + x].value=val;
- }
- }
- As this function shows, you can easily
make a loop fill the correct range of fields by using the elements[]
property in a manner that reflects the fielding convention for your fields.
Tip: Quickly clear all HTML form elements
using JavaScript's reset() function
- While including a reset button (e.g.,
<input type="reset">) allows the user to clear all the elements on the form,
there may also be times when you want to clear all form elements
programmatically. At first, you may be tempted to loop through all the
elements on a form and clear them one by one--something along the lines of:
- for (x=0; x <document.form.elements.length;x++)
{
-
document.form.elements[x].value = ";
- }
- Of course, as you may have noticed, this
code immediately runs into difficulty when it encounters, say, a button or
some other non-text field-based element. Fortunately, JavaScript
provides a quick way to clear element values in a form with the rest()
function. You use this function like so:
- document.forms["Form1"].reset()
- Executing this command resets all the
elements in Form1. And if your page has more than one form, your code
can simply loop through the collection of forms, calling the reset()
function as it goes, as in:
- for (x=0; x <document.forms.length;x++)
{
-
document.forms[x].value = ";
- }
Tip: Do a quick test of a JavaScript
command in your browser's address bar
- When you're in a rush, sometimes every
second makes a difference. Creating a new Web page and testing it in
different browsers--just to make sure you have the right syntax--can get
wearisome when you're under a lot of pressure. However, most modern
Web browsers allow you to test a limited amount of JavaScript right in the
address bar where you normally type a URL. Just type the word
"JavaScript" followed by a colon, and experiment to your heart's content.
You can even use semicolons to write multiple lines of code. For
example, the following typed in the address bar gives you a dialog box that
says 3:
- JavaScript:var x=34;alert(x)
- You can also write to the screen, using
window.status. (Even though that property normally writes to the
status bar, it writes to the screen when you execute code from the address
bar.) For instance, the following code in the address bar writes a
bold number 4 on the screen:
- JavaScript:var x=4;window.status = "" +
x + ""
- One last thing to keep in mind is that
Gecko-based browsers (e.g., Netscape and Mozilla) and Opera leave your code
in the address bar as is, whereas IE converts your spaces to "%20"--so it
may be a little harder for you to see what you've typed.
Tip: Use browser sidebars to speed up
development
- Web development requires constant access
to a large amount of reference material available online from Web sites,
suca as www.w3.org, www.msdn.com, and devedge.netscape.com. Most
Internet browsers provide a feature called sidebars. Sidebars are
customizable frames where you can keep items that you need to use all the
time. Internet Exxplorer provides Explorer Bars (on the View |
Explorer Bar menu.)
- When writing code, it's nice to have a
reference for all of the object and data types, methods, and exceptions
available to you. Sidebars make this task as easy as possible.
- You can get some useful tabs for
javaScript, CSS, XML Schema, and other Web-related technologies from
http://devedge.netscape.com/toolbox/sidebars/ and www.zvon.org/Output/bar_list.html.
Tip: Create private methods in your
constructor functions for JavaScript objects
- When you create a custom JavaScript object
with a constructor function and add methods to it, generally those methods
are public. However, sometimes you may want to create more structure
for your object by writing some private methods that developers can only
access through one or more public methods. There's a way to create
private methods. You just define a function the normal way, except
place it inside your constructor function, like the function
MyPrivateFunction() below:
- function MyConstructor(){
- function MyPrivateFunction(){
- //code
- }
- this.publicMedthod = function(){
- //code
- }
- Your private method can call variables you
set up in your constructor function. However, it never executes unless
you call it with public methods defined inside the function (such as
publicMethod).
Tip: Make sure your thumbnail image links
send users to someplace useful!
- One typical way of ensuring that your Web
page downloads quickly is to include thumbnail images--ie, very small images
that the user can click on to see the full image. Here's a typical
implementation:
- <img src="thumbnail.jpg" height="100"
width="150" alt="Thumbnail of my wonderful product. Click here to see the
big picture.">
- A potential problem with this, however, is
that users often expect that clicking on something will take them someplace
useful. This is especially important in eCommerce sites, where
anything that causes your users who haven't brought anything yet to lose
interest means YOU lose.
- In the example shown here, the users will
see a larger image, but that's all. If the user wants to find out more
about your product--or to buy it--he now has to press the Back button on his
browser. What a waste. So why make the link go to a nice Web page that
includes the bigger picture, but also a description, price information, and
a way to buy your product? Just change the link as follows:
- Then, design big-picture.html so it
contains everything a user would want.
Tip: Round up and down with Math.ceil()
and Math.floor() in JavaScript
- When you want to round a number, your
instinct may be to look up the word "round" in whatever JavaScript reference
you're using, which will probably lead you to the Math.round() function.
That rounds numbers up if the decimal it .5 or higher, and down otherwise.
If you want to force the number to round up or down, you won't find your
unction under the letter R. Instead, use Math.ceil() to round up and
Math.floor() to round down.
Tip: Save your Web images properly for
future edits
- Make sure you save the original,
high-quality versions of the images for your Web site in a central place
that all your developers know about. If you have to make changes to an
image or base an image on an existing one, you shouldn't make those changes
on a JPEG file, or you're liable to suffer continual quality degradation.
Instead, save in a format such as uncompressed TIFF, and also document the
exact settings you used for the JPEG version.
- To keep track of your images more easily,
you might also want to maintain an internal Web page with links to all your
images so that developers can easily spot the ones they need. The last
thing you need is developers wasting valuable time tracking down the image
for "that little triangle thing."
Tip: Build your own mathematical
algorithms right in JavaScript
- Naturally, you don't usually use
client-side JavaScript to perform the kind of math required to send a probe
up to Mars. (Just imagine the folks at NASA doing everything in
Internet Explorer.) But if you do need to do a calculation that
JavaScript's built-in math functionality can't handle, you may want to look
at the following Web site:
-
www.ecs.umass.edu/ece/koren/arith/simulator/
- This companion site to Israel Koren's book
"Computer Arithmetic Algorithms" contains some serious math--all in
JavaScript!
Tip: Be careful to avoid infinite loops
with setinterval()
- Be careful with setinterval() (and any
other command that causes a loop) to make sure that nothing your user does
could spur and annoying infinite loop. Especially dangerous are loops
tat involve some sort of modal dialog box (e.g., window.alert()), since the
constant appearance of a dialog box may prevent the user from even closing
the browser.
Tip: Consolidate your code by creating
wrapper functions
- You may find that you frequently use
JavaScript functions in a certain sequence. If you see such patterns
in your code, it's good to consolidate these by creating wrapper functions.
For example, people often issue the focus() method after calling window.open()
to redirect an existing window. Instead of having two lines of code
every time we need to call window.open(), we can write a wrapper function.
Make sure that any parameters usually used are available, and that your
function passes back whatever the function being wrapped would normally pass
back. Also, try to make it as flexible as possible. For example,
the following function includes an on/off switch called bFocus so that you
can always use the same wrapper function even if, in some cases, you don't
want it to call focus():
- function
smartopen(strURL,strWindowName,strParameters,bRedirect,bFocus)
- {
- var hWindow;
- hWindow =
-
window.open(strURL,strWindowName,strParameters,bRedirect);
- if(!(bFocus && bFocus == false))
- {
-
hWindow.focus();
- }
- return
- }
Tip: Don't forget to edit URLs in free
scripts
- Are you using free scripts you downloaded
from some site? Beware: Sometimes these contain links back to the site
they came from. For example, we know of one person who used a script
for a mouse trail. Well, about every 20th time a user clicks on that
site now, he's redirected to the site the script came from. Now, we're
certainly not saying you should deny credit to authors who share their
scripts. Go ahead and give credit, create a link to the author's site,
etc. But just don't let that code randomly direct your users to some
free scripts site when they least expect it! It's always good to
search for URL's in the script to make sure that doesn't happen.
Otherwise, you might annoy your users--not to mention, embarrass yourself.
TO VISIT BUSINESS WEBSITE LINKS'
INTERNET DIRECTORY
CLICK HERE---->INTERNET
DIRECTORY ONLINE.COM
Home | Company Info | Pricing | Contacts |
Client Directory | Computer
Tips | News |
Testimonials |
Disclaimer |
Our Privacy
Policy | Terms of Use |
Site Map
Business Website Links, LLC
• 8041 Via Hacienda
•
Palm Beach Gardens
• Florida
•
33418
(561)-452-0401
•
info@businesswebsitelinks.com
Copyright ©2005 all rights reserved by
Business Website Links, LLC
Web Host and Design by Business Website Links, LLC
|