Business Website Links
Website Design, PR, and Surveys
Your One-Stop Shop for the
Internet & Beyond

Home Company Info Pricing Contact Client Directory Computer Tips News Testimonials


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):
    • xxx.xxx.xx.xx mydomain
  • 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):
    • &#00060;
  • 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:
    • &#x003c;
  • Of course, both &#00060; and &#x003c; 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:
    • www.w3.org/TR/charmod/

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:
    • ?hl=en&q=Javascript
  • 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):
    • perl -c 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:
    • self.returnValue = 5;
  • 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:
    • &lt;body onBlur='javascript:this.focus()'&gt;
  • 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 &ldquo;" +
    •           elem.innerText.substr(0,18) + " ...&rdquo; " }
    • 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:
    • eval("3 + 3")
  • 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:
    • para {font-family:arial}
  • 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:
    • div.para {color:red}
  • and to make the text in the element of class 'para' green, you'd use:
    • p.para {color:green}
  • 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 | NewsTestimonials |
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