QUERY_STRING information is extracted by a CGI program in a number of different ways. In UNIX, the most common is through environment variables. Within a Borne shell script, you can reference it as in this example: #!/bin/sh In Perl, this same mini-program would be written as the following: #!/usr/bin/perl The QUERY_STRING is the heart and soul of imagemaps. A Web browser will generate a QUERY_STRING appropriate to the x,y value of a mouse-click upon an image when the following HTML is used: <A HREF=URL><IMG SRC=image_URL ISMAP></A> Note that it takes a combination of both the ISMAP attribute within the <IMG> tag and the presence of an <A HREF> statement for x,y QUERY_STRING information to be produced. To use a slightly less generic example, let's say I had an image file called mercator.gif that had dimensions of 600¥300 pixels. I place my mouse pointer somewhere around Toronto, which might be located at 200,90. I want this information to be processed by a CGI program called imagemap.cgi. Some possible HTML that could be written to accomplish all this is <A HREF=http://www.anyfirm.com/cgi-bin/imagemap.cgi><IMG SRC=http://Âwww.anyfirm.com/pics/mercator.gif ISMAP></A> If I were to then click on Toronto, the URL the browser would try to invoke would be http://www.anyfirm.com/cgi-bin/imagemap.cgi?200,90 Flatland Revisited-An Introduction to the Standard Imagemap SystemTo begin, I'll start by telling you that you won't be seeing any imagemap-handling source code any time soon. I hate to say this as it gives me great joy to both read and write the stuff. Conventional imagemap source code has become so standardized that there's no point in my going into it immediately. However, I will write my own nonconventional imagemap handler later on in this chapter to show you that you don't have to rely on the standard software if it doesn't fit your purposes. Instead, right now I'll go into the theory of how imagemaps work. In the 19th century, a Shakespearean scholar named Edwin Abbott wrote a book called Flatland. It was a satirical description of the lives of two-dimensional creatures inhabiting a plane. The social status of a flatlander was almost entirely based on their geometry. I'm reminded of flatland when it comes to standard imagemaps, as they are a description of what to do when a particular two-dimensional geometry is encountered. Imagemap.c-The Standard Imagemap HandlerThe National Center for Supercomputing Applications (ncSA) released the first HTTP server that really caught on as well as the first Web browser, called Mosaic. It has also supported quite a lot of other Web-related projects, including the creation and distribution of imagemap.c, the standard imagemap handler. This C source code comes with the ncSA HTTPd distribution and will be automatically compiled with the HTTPd and installed in the /cgi-bin/ directory of the Web server. However, if this isn't the case with your installation or if you wish to get a newer version of the code, you may find it through the following URL: http://hoohoo.ncsa.uiuc.edu/docs/tutorials/imagemapping.html In fact, this link will tell you just about everything you need to know about the standard imagemap system.
I'll start here where I left off in the previous section. Through HTML, an x,y coordinate pair corresponding to a mouse-click on an image can be generated and sent to a CGI program. This program is then responsible for obtaining this information from the QUERY_STRING string environment variable. So, the question now becomes what to do with this coordinate pair. The ncSA standard imagemap system offers one possible solution. Consider the following URL: <A HREF=http://www.anyfirm.com/cgi-bin/imagemap.cgi/pathinfo/mapfile.map><IMG ÂSRC=imageURL ISMAP></A> This HTML is almost identical to the HTML in the previous section, except that now imagemap.cgi has more information following it. This information tells imagemap.cgi to look into a .map file; .map files contain a geometrical description of the image in question and tell imagemap.cgi what to do when it finds a mouse-click lying within a given shape. The next section is an in-depth examination of .map files.
pathinfo is a strange fixture of CGI programming at best, but it becomes even stranger in the context of the standard imagemap handler. A path string can be appended after any URL that terminates in a file. The CGI programmer can find this string in the PATH_INFO environment variable. In the case of the standard imagemap handler, one of two things can be done with this string: It can be used to directly reference the .map file associated with the image that has been ISMAPed. It can be used as an alias by the imagemap program to reference the imagemap.conf file. The HTML code given earlier shows the usage when PATH_INFO is used to directly reference a .map file. In this context, imagemap.cgi will try to access the .map file that could be referenced by the URL: http://www.anyfirm.com/pathinfo/mapfile.map Note that pathinfo could have many different directory levels included within.
If pathinfo is used as an alias, imagemap.cgi will look in its own directory for a file called imagemap.conf. If imagemap.conf is found, imagemap.cgi will parse it for references that match the pathinfo. Following these references, there will be map file names, which are then used. I have grabbed the following from http://www.anadas.com/ at my UNIX shell to show how it would look directly: % ls -l *.map *.conf
Finally, an example of how pathinfo aliases and the imagemap.conf files are put into practice: <A HREF="exe/imagemap.cgi/swatch"><IMG SRC="pics/swatch.jpg" ISMAP></A> .map Files-Describing Shapes the Imagemap WaySince the time of the Babylonians, people have been obsessed with geometry. Farmers, architects, and mathematicians-even lowly computer programmers-have all found it useful to be able to precisely describe shapes. We've come up with quite a few systems of doing so and a bunch of standardized shapes to work with. Of this vast storehouse of knowledge, the standard imagemap system recognizes only four methods: rectangles, circles, polygons, and points. The basic idea behind the standard imagemap system is that whenever a mouse-click is registered corresponding with one of these shapes in an imagemap, a URL is invoked. This is accomplished by having the imagemap handler issue a Location directive via the Web server. A .map file is the means through which shapes are defined and the standard imagemap program knows how to tie which URL to what shape. The imagemap program gets the mouse-click coordinates and determines which shape contains the click.
A rectangle can be uniquely identified by specifying its top-left and bottom-right coordinates within an image as x1,y1 and x2,y2. A circle can be uniquely identified by specifying its center, xcen,ycen, and any point on its circumference, xcir,ycir. A polygon can be uniquely specified by a list of all its vertices: x1,y1, x2,y2, x3,y3, .. xn,yn. To make computation easier, imagemap handlers usually limit the number of vertices a polygon may possess to some large number, usually 100. For the purposes of .map files, rectangles are abbreviated to rect and polygons to poly. Obviously, a point is fully described by itself: x,y. In the context of imagemap.cgi, if a mouse-click lies outside of any defined region (rect, circle, or poly), it is compared against all specified point coordinates. The imagemap handler will redirect the user to the URL specified on the point line whose coordinates are nearest to the mouse-click. As it is stated so eloquently in the ncSA Imagemap tutorial, "The nearest point wins." The point method makes sense only if there is more than one point line in a file. Otherwise, the one point that is defined would always "win." If that's what you actually want to happen, you should use the default method. This is invoked when two conditions are met: The mouse-click isn't found to lie within any of the described shapes, and there are no point lines in the .map file. Every line in a .map file has a very straightforward syntax. For all lines except default, it is shape URL coordinates This syntax differs for default to make it even simpler: default URL Putting all these concepts together, we get a logical .map file: rect URL x1,y1 x2,y2 You may have as many rect, circle, poly, and point lines in a .map file as you need. Also, blank lines are skipped, and lines beginning with the # character (also known as "number," "pound," or finally "hash" to the truly hackish) are ignored as comments.
Client-Side Imagemaps and Magic MIME TypesThe best and worst labor-saving devices are those things that save you the trouble of thinking. Thinking is difficult and time consuming, and if you can get the job done without as much thought as you might normally have to invest, then great. However, by accepting someone else's prepackaged thought, you can fall into the trap of accepting the limits they decided to put on the problem. This undesirable condition runs rampant in the field of imagemap handling. As I've vented before in this chapter, canned imagemap code is far too good. It's reasonably easy to install, easy to use, sufficiently powerful enough that it covers just about all imagemap cases, and allows people to forget that imagemaps can be treated as a creative CGI challenge. But it gets even worse; the canonical imagemap format has been considered a "standard" to the point where some Web browsers and servers now have special features that allow you to bypass imagemap.cgi altogether. These features are client-side imagemaps and the .map Magic MIME type. Client-Side ImagemapsNewer versions of Netscape, Microsoft Internet Explorer, and Spyglass Mosaic support a variant on the idea of an imagemap called a client-side imagemap. This technique places the burden of processing the x,y pair produced by the ISMAP attribute on the Web browser (the client) rather than on a remote CGI program. As far as a Web page developer is concerned, this is accomplished through completely nonstandard, nonsupported extensions to HTML.
A client-side map is defined within the body of an HTML file. The logic of the map structure is very similar to that found in the .map files used by the ncSA imagemap.cgi program. I will include a portion of an HTML file as an example and discuss it here. You can see this example in action at http://www.anadas.com/ As you can see in Figure 12.3, the mouse-pointer shows its "pointing hand" disposition as it is positioned to click on a client-side imagemap. Note that the URL this click will invoke is displayed at the bottom of the screen. This URL display appears only with client-side imagemaps and not server-side imagemaps. Figure 12.3: A client-side imagemap about to be invoked. <MAP NAME=anyname> Here's a quick review of this syntax:
A complete review of Spyglass-style client-side imagemaps can be found online at http://www.spyglass.com/techspec/tutorial/img_maps.html But Master, How Can I Depend on Client-Side Imagemaps When So Many Browsers Don't Support Them?An excellent question, grasshopper! The answer is that you don't have to. You can set up a redundant scheme whereby an image is tied to both a client-side and a server-side imagemap. To do this, you must define a map in your HTML file as I talked about earlier. You must also create a .map file and store it on the server. Then, reference the image with the following: <A HREF="/cgi-bin/imagemap.cgi/pathinfo/file.map"><IMG SRC="images/Âmapped_image.gif" USEMAP="#anyname" ISMAP></A> As always, insert an appropriate URL for the imagemap.cgi executable, the pathinfo, and map file names. When this format is used, the client-side imagemap is executed if the browser being used supports client-side imagemaps. If it doesn't, then all HTML having to do with client-side imagemaps is ignored and then the markups relating to server-side imagemaps kick in.
The .map Magic MIME TypeSome CGI programmers are lucky enough to be able to control their httpd configuration, either directly or by being "tight" with the sysadmin. If you happen to be among these lucky few, then this section could be of use to you. Even if you aren't, you might be fortunate enough to have a sysadmin who pays special attention to their httpd. By way of a small refresher, the World Wide Web is a client/server environment. Your Web browser (Netscape, Mosaic, MSIE, or Lynx) is the client. Each time you try to load a Web page, it makes a request of the Web server.
The ncSA and Apache Web servers are quite configurable. One of the more interesting sections when configuring one of these Web server is the "Magic MIME Type" area. This can be found in the ~/conf/srm.conf file, where ~ represents the home-level directory of the Web server installation, also known as ServerRoot. I'll quote a portion of this file here:
# The following are known to the server as "Magic Mime Types" They allow The .map Magic MIME type is supported by the new ncSA/1.5 httpd and in the beta release of Apache httpd 1.1. It is unlikely that your sysadmin will upgrade to either of these newer httpds without it being brought explicitly to their attention, but beware! Sysadmins are quick to anger and their vengeance is mighty. This about says it all except for the conclusion: Removing the # character from the front of any of these lines and then rebooting the httpd will give you access to that Magic MIME type. If you enable .shtml as a Magic MIME type, then server-parsed HTML files can be accessed outside of directories that are specifically assigned to this role. Enabling the .cgi line will allow the Web server to run CGI files in directories outside of /cgi-bin/. Enabling the .map line will give you awesome cosmic powers!
Seriously, enabling the .map Magic MIME type allows you to write your imagemap HTML statements in a slightly altered format: <A HREF="map_URL"><IMG SRC="image.gif" ISMAP></A> What ncSA has essentially done is incorporate their imagemap.c source code into the httpd.c source code, making the standard imagemap handler part of the standard Web server! Rather than unloading imagemap handling onto an external imagemap handling program that references an auxiliary map file, the server references that map file directly and deals with it internally. I have composed a working (if simple) example of this in action: http://www.anadas.com/cgiunleashed/imagemaps/magic.html<HTML> The ncSA/1.5 server is instructed by this HTML to reference the following map file: default /cgiunleashed/imagemaps/elsewhere.html Take a Walk on the Server-Side-Developing Imagemap CodeSo far in this chapter, I've talked the talk. Now, I think it's time to walk the walk. For your viewing pleasure, I've written an imagemap handler that is functionally similar to the standard ncSA code but includes a fair number of differences, as well. Being the creative guy that I am, I have decided to call my masterpiece im.cgi. im.cgi is written in Perl and developed for a UNIX platform. By now I'm sure you've all heard that Perl is the best language for CGI development. I would call this statement a justified simplification. Perl is an excellent language for writing programs that handle strings and files and that are reasonably small and uncomplicated. This description would fit the vast majority of CGI programs. I've written CGI programs in C and C++ when it was appropriate to do so, but for CGI programs, I always go to Perl first. I'm not going to spend any time in this chapter discussing Perl as a language. Information about it is very available on the Internet and in bookstores-that's how I learned it, after all. im.cgi is fairly well documented, and you should be able to get the meaning of most Perl commands and structures from the context in which they are used. im.cgi gets the ISMAP-produced x,y pair through the QUERY_STRING environment variable. This coordinate pair is compared against geometries found in an .imap file; .imap files are not structured in exactly the same way as an .map file, though. Valid methods in an .imap file are rect, ellipse, point, and default. The area that a rect or ellipse delimits is described in a new format I have outlined in a logical .imap example later in the chapter. For the sake of simplicity, I have eliminated the poly method.
Figure 12.4: Problem polygons. Here are examples of a concave polygon and a multiply connected polygon. Shapes that fall under these categories are difficult to work with in computer programs. To help make the job easier, assumptions are usually made that simplify (though possibly misrepresent) the situation. In addition to (slightly) changing the allowable methods, I've changed the structure of each line. URLs follow rather than precede the geometry-specifying information. Also, im.cgi doesn't handle relative URLs-they have to be specified in full, including the http:// at the front. Blank lines are skipped, and lines starting with # are treated as comments and are ignored. The first line of an .imap file contains the alias meant to be compared against the PATH_INFO environment variable. Only uppercase and lowercase alphabetic characters are valid for this alias name; im.cgi doesn't support direct references to .imap files as imagemap.cgi does for .map files-pathinfo aliases must be used. As a result, .imap files must be in the same directory as im.cgi. If a mouse-click is found to be contained within a rect or ellipse, the program will "short-circuit" and immediately bring the user to the URL specified by that shape. The consequence of this is that if rects or ellipses overlap, the shape described first in the .imap file takes precedence. It is possible to specify a shape that lies outside the boundaries of the actual image file the .imap file relates to-this could be useful if you want to have a clickable semicircle at the edge of an image. The point method works the same as it did in imagemap.cgi. If a file has any point methods specified, any default methods are ignored. There are no restrictions on where methods are placed within a file apart from that the first line is reserved for the alias name. This is all very similar to the structure of a .map file. I have added one "twist" to it all, though. rect, ellipse, and default methods may be specified by more than one URL. If more than one URL is specified for any one of these methods, im.cgi will choose one randomly. Also, there can be more than one default line-a convenience to allow for the input of many alternative default URLs to be randomly chosen from, without putting many URLs on one line. To be honest, I can't think of a really good application for this. However, I wanted to demonstrate that things that are completely outside the capabilities of imagemap.cgi are possible when you write your own imagemap handler. All these principles are demonstrated by the following logical .imap file: # mapfilealias
Figure 12.5: Anatomy of an ellipse. You can see an example of my im.cgi program (shown in Listing 12.1) at work at the following URL: http://www.anadas.com/cgiunleashed/imagemaps/immap.html Listing 12.1. im.cgi program-an alternative imagemap handler. #!/usr/bin/perl
Creative Imagemap Programming-Breaking the Paradigm with GlorgloxThroughout this chapter, I've been an advocate of thinking for oneself when creating imagemap code. The im.cgi code I wrote departs from the standard imagemap code, but not very much. It still follows the same basic principle of click-on-a-shape-and-we'll-take-you-there. That doesn't have to be the only way to deal with imagemaps, though. Shape-based imagemap handlers are very good at describing shapes that can be described through simple analytic geometry but very bad at describing arbitrary curvy shapes, such as what one might find on an isometric (contour) map. And what useful maps these are! For the next few days, try keeping you eyes peeled for examples of contour maps in your everyday life. I think you'll be surprised with how many you see. In addition to isometric maps, text isn't processed very well by shape-based imagemap handlers. It's possible to plot out the various cusps of a nice Geoslab font, I suppose, but it wouldn't be desirable. And brush script... forget it! You'll need every one of those 100 vertices you've got to play with in your poly method and more. How could an imagemap handler be constructed to deal with these sorts of situations? Glorglox presents us with one possible answer. Glorglox is an advanced imagemapping program written by Tom Rathborne, a University of Waterloo mathematics and computer science student. He came up with an elegant solution to the problems I discussed earlier. The key is to essentially forget about geometry. Imagemaps are images, period. Forget about the shapes we artificially impose on them and consider their basic property: color. Figure 12.6 shows the Glorglox home page and, in my opinion, immediately gives away its methodology. Figure 12.6: The Gloralox home page. The Glorglox Home Page contains two images that show what Glorglox is all about: http://www.uunet.ca/~tomr/glorglox/demo/. The HTML used to invoke Glorglox is structurally identical to the HTML used to invoke imagemap.cgi. An example is <A HREF="/cgi-bin/glorglox/glorglox-demo"><IMG SRC="demo.gif" ALT="[glorglox demo When an x,y coordinate pair is provided to the Glorglox through QUERY_STRING, a .gmap file is referenced. This referencing is done through PATH_INFO and can be done either directly or through an alias found in the glorglox.conf file. The preceding HTML shows the alias method in use, and the glorglox.conf file is identical in form to the standard imagemap.conf file: glorglox-demo : /u/tomr/www/glorglox/demo/demo.gmap A Glorglox .gmap file is used to provide glorglox.cgi with information regarding what to do with its x,y pairs. Glorglox operates through pairs of image files: the one that is output to the Web and an auxiliary .gif file. When a click is registered on the viewable image, Glorglox determines the color of the pixel at that location in the auxiliary .gif file. The .gmap file is a look-up table of colors and URLs. Here is an example of a .gmap file: /www/staff/tomr/glorglox/demo/demo-map.gif Notice that colors are specified as numbers between 0 and 255 in a Glorglox .gmap file. This is due to the fact that GIF images use indexed color mode. Consequently, a Glorglox-based imagemap has a maximum of 256 links it can invoke. This should be enough for most purposes.
The usefulness of Glorglox hinges on that it is often easier to create an auxiliary image than to define geometrical shapes in terms of the vertices of their pixels. Quite often, this is indeed the case. As a final note on Glorglox, take a look at the following URL and ponder for a moment how you'd make the imagemap you'll find there using a standard imagemap system: http://www.erin.gov.au/land/regions/ibra_spatial/ibra.html Imagebuttons-The End of Imagemaps Is NighHTML was originally conceived as a content-description language. Its major conceptual step forward was the inclusion of native ways to deal with hypertextual links. Within these limits, HTML worked well. Eventually, the demands of real life started to pull HTML in all sorts of funny directions. The pervasiveness of HTML documents and Web browsers and the flexibility of HTTP gave people the idea to start using the Web as a vehicle for information gathering as well as information distributing. ISINDEX tags and the CGI appeared back in the days of text-only browsing. The CGI layer and GUI-based Web browsers with inline images made room for the concept of an imagemap. HTML was no longer as simple as it once was, but it wasn't made so complicated that there was any real reason to complain. This same CGI revolution also brought forms onto the scene. Forms blew ISINDEX out of the water. The basic set of form input elements very closely mimics the various dialog box options you'll find in a GUI-based operating system such as radio buttons, checkboxes, and selection lists. What forms didn't contain was any sort of graphical interaction capability...until now. It has been noticed that throughout history, great conceptual advances tend to be independently developed at almost the same time. In the 1600s Leibnitz and Newton developed calculus within years of each other. In the 1800s a gaggle of mathematicians almost simultaneously challenged Euclid's 9th and 10th axioms and independently derived non-Euclidian geometry. In late 1995, I remarked to my programming partners that I wished there was a way to combine forms and imagemaps. About two months later, I noticed imagebuttons online. Funny how these things happen. The HTML Side of ImagebuttonsI will assume that the reader has a knowledge of the working of HTML forms and will concentrate only on the imagebutton-related tags. <HTML><BODY> There are some things here that should be familiar by now-the structure of the form statement, a CGI program as its action, and a specified method: in this case, GET. Beyond the familiar, this form has two slightly unusual aspects to it. First, the explicit strangeness: the <INPUT TYPE=IMAGE> tag. It is this tag that creates an imagebutton within an HTML document. The second and implicit unusual point is that this form has no <INPUT TYPE=SUBMIT> tag! As people who are experienced with forms know, without such a tag, the form will not connect to its action, making the form absolutely useless apart from didactic purposes. Contrary to what you may think, that is not my goal-at least not right here. This is an honest-to-goodness working form. I'll go into how the imagebutton tag makes it so shortly. An <INPUT TYPE=IMAGE> tag can be inserted into any form just as one would insert any other INPUT tag. The NAME attribute is optional but highly recommended for a reason I'll talk about soon. The VALUE attribute isn't forbidden, but it does nothing in the context of an imagebutton. Beyond these attributes, the ones that are normally found in INPUT tags, any attributes that are legal in IMG tags are legal here: SRC is necessary while ALT, HEIGHT, WIDTH, and BORDER are optional. Move your mouse pointer on top of the image produced by the <INPUT TYPE=IMAGE> tag. Notice that the pointer doesn't transform itself into a "pointing hand" icon. However, when you click on the image, the form action is invoked. I have created an example of an imagebutton that you can view at the following URL: http://www.anadas.com/cgiunleashed/imagemaps/imagebtn.html The action of the form that is found at the preceding URL is a program that "spills its guts," as it were. Listing 12.2 is that program. Listing 12.2. A Perl program that prints GET/POST query information and environment variables. #!/usr/bin/perl I'll include the report this form/CGI pair generates here, narrowed down to the relevant items:
But What Does It All Mean?To begin, imagebuttons are a logical superset of imagemaps for all CGI applications. Put simply, this means that, with only a little fiddling around, you can use imagebuttons anywhere you use imagemaps. For instance, when using the im.cgi code I developed, the following HTML <A HREF="imagemap.cgi/pathinfo"><IMG SRC="image.gif" ISMAP></A> can be replaced with <FORM ACTION="imagemap.cgi/pathinfo"><INPUT TYPE=IMAGE SRC="image.gif"></FORM> as long as the im.cgi Perl code is modified so that ($x,$y)=split(/,/,$ENV{QUERY_STRING}); is replaced with ($qs=$ENV{QUERY_STRING})=~ tr/=xy//d; ($x,$y)=split(/&/,$qs);
Through this direct correspondence between imagemaps and imagebuttons, you can do at least everything with an imagebutton that you can with an imagemap. But there are added benefits to imagebuttons, as well, should you choose to exploit them. Imagebuttons are by their nature form related. This means that you can tie more information to an imagebutton submission than just the x and y coordinates of the mouse-click. This has been all but impossible with imagemaps. The unique way in which imagemap coordinate information is passed to the CGI program requires special (though minimal) treatment. Because information created by imagebuttons is passed to the CGI program through the same method as any other GET or POST created data, a standard CGI-handling package can be used to extract the information. This is demonstrated by the code I used earlier to show the environment variables in the imagebutton example. As has been the case in the past, a multistate CGI based on form input has required the HTML code to possess multiple <INPUT TYPE=SUBMIT> tags, each with a different NAME attribute. This same multistate effect can now be accomplished by having the CGI program react differently depending on the x,y coordinate information supplied by the imagebutton-based form submission. Imagemaps are still the right choice in many situations; they are both intrinsically simple to deal with and have a wealth of preexisting support. There is more documentation for imagemaps, and there are standard code libraries and "built-in" features supported by some browsers and servers (client-side imagemaps and the server-side .map Magic MIME type). However, there is a limit to the capabilities of imagemaps. Imagebuttons can transcend this limit. SummaryFor those of you who have survived reading these past 32 pages, I salute you. Here is a quick summary of what I have covered in this chapter. Imagemaps are special, but they aren't mystical. What makes imagemaps special are the HTML markups that support their use and the unique way that information is passed from client to server. There is a wealth of pre-existing imagemap-handling programs. In most cases, it will be sufficient to tackle your CGI problem at hand. But still try to understand how these programs work, as well. At their core, they output a specific Location HTTP header based on a comparison of the coordinate information supplied and various geometries gleaned from a map file. Imagemap handling has become so common that the "labor-saving devices" of client-side imagemaps and server-parsed imagemaps (the .map Magic MIME type) have been introduced. Know how they work and use them as appropriate. If necessary, or even if just plain desired, you can build your own imagemap handler. If you take this approach, you inherit a lot of responsibility but at the same time you acquire the power to create a CGI solution that fits the needs of your project. Don't be afraid to jump completely beyond the click-in-a-shape paradigm that has come to dominate the imagemap field when you develop your own code. Finally, if imagemaps can almost (but not quite) do what you want them to, maybe imagebuttons are better suited for your project. Conversely, if you have a form you'd like to "spruce up" and make more attractive or user-friendly, imagebuttons might provide the kick you want. Happy hacking!
Хостинг от uCoz
|