Your Guide to Website Design and Management

Text Size:
small_A.gif small_A.gif
Bookmark and Share

Rating: 5.0/5 (1 vote)

Site Design (Architecture, Coding, UI, etc.) >> AJAX >>

AJAX Select Box (Other) Form Element

"For people who make websites" - A List Apart Magazine explores the design, development, and meaning of web content, with a special focus on web standards and best practices.
HTML Validator is a Mozilla extension that adds HTML validation inside Firefox and Mozilla. The number of errors of a HTML page is seen in the form of an icon in the status bar when browsing. The details of the errors are seen when looking the HTML source of the page.

The extension is based on Tidy and OpenSP. Both algorithms were originally developed by the Web Consortium W3C. Both algorithms are embedded inside Mozilla/Firefox and makes the validation locally on your machine, without sending HTML to a third party server.
This project aims to create an archive of user contributed clip art that can be freely used.
Starting at the beginning, this reference explains everything you need to know about using core JavaScript. It assumes you have the following basic background: a general understanding of the Internet and the World Wide Web and a good working knowledge of HTML. An excellent resource.
Edit your images on the fly online with Splashup, a web-based image editor that integrates with Flickr, Facebook, and Picasa. Splashup offers up a surprising array of image editing tools, far beyond the usual crop of resize and contrast-- you can also edit multiple images, play with filters and layers, use a variety of brushes, and more. Splashup is one of the best image editors in a long line of image editors; i.e., Picnik, Pixoh, and Resizr, to name just a few.[Lifehacker Annotation]
This website will let you:
  • Create an XML sitemap format that can be submitted to Google to help them crawl your website better.
  • Create a Text sitemap to submit to Yahoo.
  • Create a ROR sitemap, which is an independant XML format for any search engine.
  • Generate an HTML site map to allow human visitors to easily navigate on your site.
Clearspring's free Launchpad widget builder lets you easily turn your website's content into a widget which site visitors can use to place your content on all the major social media sites (MySpace, FaceBook, Google, hi5, Live, Yahoo, Wordpress, Blogger, etc.). The service also provides tracking and analysis.
This site features online text and html changing, modifying, converting tools designed to save you time making web pages or preparing text for web publication. If you've ever needed to capitalize sentences or convert line breaks to <p> or <br /> then this site can save you needless manual labor. There are other useful tools as well, like the one to uncompress html to make it readable and the ones to uppercase or lowercase text. Basically, the most common tasks that someone who works in an office or does freelance web development might encounter. Most of the tools have been created using javascript so you should be able to change large amounts of text as the processing is done on your computer instead of being limited by a server script.
dTree is a free JavaScript tree menu. That is very simple to set up and use. You don't have to worry about adding pages to the tree in a specific order, which makes it ideal for generating a tree from a database.
webmaster toolkit offers this CSS Menu Generator to generate both the CSS and the HTML code required to produce a text-based yet appealing set of navigation buttons.
Amaya is an open source Web editor endorsed by the W3C. Browsing features are seamlessly integrated with the editing and remote access features in a uniform environment. This follows the original vision of the Web as a space for collaboration and not just a one-way publishing medium.

Amaya started as an HTML + CSS style sheets editor. Since that time it was extended to support XML and an increasing number of XML applications such as the XHTML family, MathML, and SVG. It allows all those vocabularies to be edited simultaneously in compound documents.
A very flexible unlimited-level, drop down JavaScript menu that uses UL/LI list data formatted with a CSS menu layout. It's powerful, lightweight and extremely easy to use!
CSS Tab Designer is unique and easy to use software to help you design css-based lists and tabs visually and without any programming knowledge required! Read a review.
This document guides you through the process of using JavaScript and the DOM to build a three-state toolbar that accurately and efficiently handles different button states (normal, highlighted, selected), and the interdependencies between them.
The Search Engine Friendly Layouts website has been created for both the webmaster and the search engine optimization specialist. The layouts on the site are all designed to be web standards-compliant, yet also search engine friendly. These layouts have all been created by Adam Senour, and he gives them to you at no cost whatsoever.
Open Source Web Design is a site to download free web design templates and share yours with others. We help make the internet a prettier place.
Some of us have a great eye for complementary colors and matches--and then some of us still don't understand why brown shoes and black pants are a bad idea. For anyone looking to set an image against a complementary background or find a color scheme, Whats Its Color (their grammar, not mine) is a free web app that can help. Upload an image and the site creates a palette page with a complementary background and a list of unique and dominant colors in your image. Photoshop and GIMP gurus might already know how to sift these kind of things already, but the visible color matching could be a boon for presentation slides or small design projects.
This tutorial will teach you all you need to know to be able to craft powerful time-saving regular expressions. It starts with the most basic concepts, so that you can follow this tutorial even if you know nothing at all about regular expressions yet. It will also explain how a regular expression engine works on the inside, and alert you at the consequences. This will help you to understand quickly why a particular regex does not do what you initially expected. It will save you lots of guesswork and head scratching when you need to write more complex regexes.
FastStone Capture is a powerful screen capture utility with built-in editing tools. It allows you to capture anything on the screen including windows, objects, menus, full screen, rectangular/freehand regions and scrolling windows/web pages. It sends captures to editor, file, clipboard, printer, email, Word/PowerPoint document or even your website. Editing tools include resizing, cropping, sharpening, annotating, applying effects, watermarks and many more. It saves captures in BMP, GIF, JPEG, PCX, PNG, TGA, TIFF and PDF formats. Additional features include a small handy capture panel that offers quick access to its capture tools and output options, global hotkeys, automatic filename generation, support for external editors, a color picker, a screen magnifier and a screen ruler.
An online picture editor, pikifx.com emphasizes special effects. You can use it to: - Resize and Crop, - Add creative effects, - Add borders, - Add creative text
Don't embarrass yourself by busting out the same tired stock clip art for your next Power Point tour de force. WPClipart has a pile of royalty free images to share.

The archive currently has 23,872 images, covering thousands of subjects. A significant portion of them are in lossless formats. The site is organized into categories, but if casual browsing fails to find you the perfect gem you've been searching for there is always keyword based searches. You can even download the entire collection as a single archive, making it easier to use offline. [Lifehacker Annotation]
If you need a logo but you're lacking the design chops to whip one up, score a free one at LogoInstant. LogoInstant is a design service that cranks out a new logo every day. The logos are completely free for both personal and commercial use and come in a layered Adobe Photoshop source file so you can edit the name or make more advanced changes.[LifeHacker Annotation]
LogoYes is a site offering a flash program to create logos. Just select your industry, a symbol, text, typography and colors for your logo. Once you finish, you can purchase a high-resolution file with your logo for only $69 or include a business card design based on the logo for an additional $30.
99designs helps you run a "design contest", where thousands of designers compete to create the best possible design to meet your needs. All you need is a clear idea of what you want designed and how much you're prepared to pay for it.
If you've been having trouble finding free or Creative Common-licensed photos for use in your projects, Sprixi filters out the fluff to help you find the images you really want.
One of the frustrations of searching for anything on the internet, let alone images, is imprecise search results. If you've ever searched for something and found something completely different—usually because the file name or the associated keywords were strangely or inappropriately applied—then you know what we're talking about.
Sprixi helps circumvent the strangeness of file names and misapplied keywords by letting users vote on whether or not an image is really what they were looking for. Search for "school bus", for example, and get some images of a micro-processor bus and you can flag them as not helpful to your search. Because thousands of users have come before you, analyzing the images, you won't often find misplaced images. Search results are divided into sorted and unsorted images, with the sorted images on top—sorted in this case means that users have verified that the images do in fact contain the thing you are looking for.
Sprixi currently pulls images from Flickr, OpenClipart.org, and from user uploads. Sprixi is a free service and requires no registration or login to use. [Lifehacker Annotation]

If you're like me, you have certain form fields that need to allow users to add an option. For example, if you wanted to ask a user filling out a form for their university, you can't realistically expect to have a table with all the possibilities from around the world. Instead, you can have what I call a select box other field (a.k.a. list box), which is a select box (single or multiple) that includes an accompanying text box field for a user to add a new entry to whatever table is being used to generate the select box options. Interestingly, I have been using such a field for years, but a quick Google search turned up little of reference value.

In the past I wrote special execution code that checked to see if the text box field had any input, performed some basic validation (error checking), and then added the text box text if appropriate. Now that AJAX has come along, I thought why not use it to allow the user addition to be instantaneous. Below I explain how I accomplished my goal. For the impatient among you, I give you the code first.


<script>
// ---------------------------
// --- Browser Support Code
// ---------------------------
function GetXmlHttpObject() {
 var xmlHttp=null;
 try {
   // Firefox, Opera 8.0+, Safari
    xmlHttp=new XMLHttpRequest();
 }
 catch (e) {
    // Internet Explorer
    try {
      xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
      xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
 }
return xmlHttp;
}
 
// ---------------------------
// --- ajaxAddOther
// ---------------------------
function ajaxAddOther (table,field,value,otherid,selectid) {
 var statusid = selectid+'-status';
 
 ajaxRequest=GetXmlHttpObject();
 if (ajaxRequest==null) {
       alert ("Your browser does not support AJAX!");
       return;
 }
 
 var sel = document.getElementById(selectid);
 var other = document.getElementById(otherid);
 var othervalue = other.value;
 
// Create a function that will receive data sent from the server
 ajaxRequest.onreadystatechange=function() {
       if(ajaxRequest.readyState==4) {
          var split = ajaxRequest.responseText.split(" ");
          var otherid = split[0];
          var start = ajaxRequest.responseText.indexOf("<");
          var response = ajaxRequest.responseText.substr(start);
 
       // if we had a successful message, add the "other" text as new selected option
   if (response.match("Added")) {
// if option field and option display are different we assume the value is the next insert id which is returned from the php function, o/w just use the option display for display and value
       if (otherid!="" && field!=value) {
              sel.options[sel.options.length] = new Option(othervalue,otherid,false,true);
       } else {
              sel.options[sel.options.length] = new Option(othervalue,othervalue,false,true);
       }
   }
   document.getElementById(statusid).innerHTML=response;
} else {
          document.getElementById(statusid).innerHTML='<span class="working">Adding</span>';
       }
 }
 
 var url = "ajax.php?function=addother&table="+table+"&field="+field+"&othervalue="+othervalue;
 ajaxRequest.open("GET",url,true);
 ajaxRequest.send(null);
}
</script>

 


<?
// ----------------------------------------------------------------------------
// --- ajax.php
// ----------------------------------------------------------------------------
include_once ("includes/db.php");
$db = new db(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
 
$function = $_GET["function"];
$table = $_GET["table"];
$othervalue = $_GET["othervalue"];
$field = $_GET["field"];
 
switch ($function) {
 case "addother":
       // --- only add if doesn't already exist, so check first...
       $sql = "SELECT * FROM $table WHERE $field = '$othervalue'";
       $get = $db->get_row($sql);
       if ($get) {
              $result = $othervalue . " already exists";
       } else {
              $sql = "INSERT INTO $table ($field) VALUES ('$othervalue')";
              $insert = $db->query($sql);
              $insert_id = mysql_insert_id();
              $result = "Added " . $othervalue;
       }
       $result = $insert_id . ' <span style="color:green;">'.$result.'</span>';
       echo $result;
       break;
}
?>

 


<?
// ----------------------------------------------------------------------------
// --- selectbox_other (AJAX)
// --- NOTES: basic single choice dropdown with ability to add other entry
// ----------------------------------------------------------------------------
function selectbox_other($name="", $list="", $size=1, $option_value="", $option_display="", $default_value="", $event="") {
       $other_name = $name . "_other";
       $value = stripslashes($_POST[$name]);
       if (!$default_value) $default_value = $value;
       $other_value = stripslashes($_POST[$other_name]);
       if (substr(strtolower($list),0,6)=="select") {
              $temp1 = strpos(strtolower($list),"from") + 5;
              $temp2 = substr($list,$temp1);
              $temp3 = strpos($temp2," ");
              $table = substr($temp2,0,$temp3);
              $result = mysql_query($list);
              $options = sprintf("<option value = ""></option>n");
              while ($myrow = mysql_fetch_array($result)) {
                     ($myrow[$option_value]==$default_value || $myrow[$option_display]==$default_value) ? $selected = "selected="selected"" : $selected="";
                     if ($selected) {
                           $selected_options .= sprintf("<option value = "%s" $selected>%s</option>n",cleanup($myrow[$option_value]),cleanup($myrow[$option_display]));
                     } else {
                           $options .= sprintf("<option value = "%s">%s</option>n",cleanup($myrow[$option_value]),cleanup($myrow[$option_display]));
                     }            
              }
       } else {
              if (!is_array($list)) $list = explode(",",$list);
              foreach($list as $key=>$field) {
                     if (stristr($field,"=>")) {
                           $key = substr($field,0,strpos($field,"=>"));
                           $field = substr($field,strpos($field,"=>")+2);
                     }
                     ($key==$default_value) ? $selected = "selected="selected"" : $selected="";
                     if ($selected) {
                           $selected_options .= sprintf("<option value="%s" $selected>%s</option>n",cleanup($key),cleanup($field));
                     } else {
                           $options .= sprintf("<option value="%s">%s</option>n",cleanup($key),cleanup($field));
                     }
              }
       }
 
       $selectid = str_replace("_","-",$name);
       $otherid = str_replace("_","-",$other_name);
       $statusid = $selectid."-status";
 
       printf("<select id="%s" name="$name" size="$size" %s>n",$selectid,$event);
              echo $selected_options;
              echo $options;
       printf("</select>n");
 
       echo "<br />n";
       printf("<input>
       printf("<input>
    printf("<input type=\"text\" id=\"%s\" name=\"%s\" size=\"$other_size\" value=\"%s\" maxlength=\"125\" />\n",$otherid, $other_name,$other_value);
    printf("<input type=\"button\" value=\"Add\" onclick=\"ajaxAddOther('%s','%s','%s','%s','%s','%s')\" />",$table,$option_display,$option_value,$otherid,$selectid,$encoding);
 
       $help = "You only need to fill out the text box if the selectbox doesn't contain the choice you are looking for.";
       printf("<a href="javascript:alert('%s')"><img src="/images/info.gif" alt="Need to Know More?" height="12" width="12" align="bottom" hspace="2" border="0" /></a>n",$help);
       echo '<br /><div style="margin:5px; 0 5px 0;">status: <span id="'.$statusid.'" style="color:#999; border:1px dotted #999; padding:2px 5px 2px 5px;">nothing added yet</span></div>';
}
?>

 

Sample Screenshot
 
 

JavaScript Functions
To begin the explanation, I include two JavaScript functions. Naturally, you could put these in a separate .js file if you prefer. The first function, GetXmlHttpObject is just a standard AJAX enabling function that you can find all over the Web.

The second function, ajaxAddOther, is what we will call when someone presses the Upload button. Note that it accepts five parameters or passed variables. The first is the database table from which we get the select box options. The second is the field from the table that is used to display in the select box. The third parameter is the value that is used in the select box. The fourth parameter is the id value for the "other" text box. The final parameter is the id value for the select box itself.

So, what the ajaxAddOther function does is pretty simple. It opens a PHP page, which I am calling ajax.php. Next, it changes the status field on our form. This is done twice, both using code that looks like:

document.getElementById(statusid).innerHTML=...
 
The first time, we are using class which we have defined as "working" to display a progress .gif file. This will be displayed while our ajax.php file is working. Once it finishes, we will again updated the status field with the results, currently either that the "other" text input was successfully added or that it already exists. If you want, you can add more validation code and produce more possible status responses (e.g., that the inputted text contains profanity, etc.). In case it's not obvious, note that we are using the getElementByID feature to manipulate the HTML of our status field. That's why we passed the id value of that field to our function (as otherid).

Finally, if the "other" text was added successfully, our JavaScript function adds it to the select box display as a selected item at the bottom of the list. Since our response text from the ajax.php file includes the word "Added" if it is successful, we just use the code:

if (response.match("Added")) { }

to see if we had a successful add. If so, we actually add the new select box option via the line:

sel.options[sel.options.length] = new Option(othervalue,otherid,false,true);
or
sel.options[sel.options.length] = new Option(othervalue,othervalue,false,true);
 
In case you aren't familiar with that code, the first variable (othervalue) is what will actually be displayed in the select box, while the second variable (otherid or othervalue) is what will be POSTED when the form is submitted. The third and fourth variables specify whether the new option is a default and selected, respectively.

The reason there are two different new Option lines is related to the field and value parameters that the function accepts. Typically, people will either make the value an id field (integer) and the display a text field or they will use one text field for both. We need to examine these two parameters to see if they are the same or not. In either case, we will add the new "other" text input as the display in the select box. If they are the same, we will add that text input as the value also. If they are different however, we will assume that the value is an integer id field and, in our ajax.php file, we will use the mysql_insert_id() php function to decide what that value should be.

You may also want to note that we are using a variable we define as sel. Just like the status field, we set that variable using getElementByID and the selectid parameter we pass to the function. Since we have to use it several times, it is easier to define it as a variable. Also, note that the sel.options.length is how we specify that the option should be added at the end of the list. With imagination, you could make that the top, but beware that if you specify a number in the list (like 0 for top) it will actually replace the option currently in that place. So, instead you would have to create a loop to go through all the options and redisplay them. For me, I am content with adding it at the end.

ajax.php File
It isn't really that important, but you might want to note that we are using the GET method to open our ajax.php file. We could just as easily use the POST method, but GET works fine for what we want to accomplish. Either way, that file will check to see if the text that a user is trying to enter already exists in the database table which is used to populate the select box. If the text doesn't exist, it adds it to the database and returns a success message. If the text already exists in the database then the page just creates a message to that effect.

Form Field Function
Finally, we use a function called selectbox_other to create the form field. We pass some variables to this function. Specifically, the first is the name of the select box itself. The second is the instructions for how to populate the select box. Basically, there are two possibilities. The first is to use a string containing the option and value list in a format like option=>value. This is not the most likely method, but could be useful for those who aren't using a database. For most others however, our list variable will be in the form of a SQL statement, like SELECT * FROM universities ORDER BY university. The third variable specifies the size of the select box. The fourth variable is the option value to be used. This is used with a SQL statement list variable and represents the field that we will get the value from. Likewise, the fifth variable specifies the field we will use to get the display value. The next variable is any default value you may want to specify. We check this value as a match to each select box options that we generate to decide if that option should be marked as selected. Our last variable is used to specify any kind of JavaScript action you want to specify for your select box (e.g., use the onchange method to update a different field on your form).

Some things to note:
&middot; We use the first four lines to set the default values based on what was POSTED when the form was submitted. This is useful in the case that our form didn't pass the validation after being submitted so is being displayed again. We don't want to lose the selections the user made.
&middot; The if-then-else statement is used to distinguish between whether we are populating the select box via a string containing the option values or via a database SQL query. If the latter, we use some string manipulation to figure out what table is being used (since the table name will logically follow the FROM part of the SQL statement).
&middot; As stated above, for each option we generate, we check if it is a default value or not. If so, we set the selected="selected" flag for that option.
&middot; After the if-then-else code, we define the id values for the various field elements (select box, "other" text input, and the status display div).
&middot; Next we actually display the select box and text input field from the variables we created beforehand. We then add a button field that the user will click to add the new "other" text.
&middot; The last lines of our function are just usability issues. I like to include a little information image that can be clicked to provide usage information for those filling out the form. When someone clicks on the "i" image (see illustration above) a simple JavaScript alert box will display the message defined in the $help variable.
&middot; As stated above, the last thing we include is a status field, which initially shows that the user hasn't added any entries yet. One he or she does the status message will change to the response provided in our ajax.php file.

Error checking
The basic error checking I do right now is simply to see if a user is trying to add a value that already exists. You can modify the PHP function to perform whatever error checks you deem appropriate (profanity, length, presence of potential injection code, etc.). In fact, if anyone develops some useful generic security checks to prevent SQL injection or similar threats, please let me know and I will add it myself to this article.

Conclusion
Well, that's it. A bit wordy, I know. But, I tried to err on the side of explaining too much rather than not enough. I hope you found this custom form field and my explanation of it useful. You may like to know that this is one of the many form elements included in my phpAddEdit free software. If you want to design powerful forms from an interactive menu rather than developing them yourself the hard way, I encourage you to check it out.

 

Text Size:
small_A.gif small_A.gif
Bookmark and Share



Trackbacks »