Archive for category Javascript

Randomizing Javascript Arrays

An array in JavaScript is like a collection of data. When one variable usually stores one value, an array stores multiple values. Each value is associated with an index position, otherwise known as ‘array key’. If you would like to learn more about arrays and how they work, read this article: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array

If an array were a deck of cards, one might say that we need to “shuffle the deck”. That’s exactly what we need to do in this situation, but it’s better referred to as “sorting the array”. We need to change the order that the array is sorted in. The Array data type is really an object in JavaScript, and like most objects, it comes pre-built with methods (functions) that we can take advantage of. One method of interest is ‘sort’.

The Array’s ‘sort’ method accepts a callback function as an argument and uses it to compare the data inside the array. A callback function is a reference to a function that can be executed at a later time in your code. This can be better referred to as a ‘compare function’, because that’s what it’s there for, to compare the data. When executed, the ‘compare function’ is passed two valus from the array. If the ‘compare function’ is not provided, the array will be sorted in alphabetical order. See this website for detailed information on the Array’s ‘sort’ method: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort.

The idea is, you compare the data that gets passed to the ‘compare function’ and return a numerical value. The array gets sorted based on the values you return. The values can be less than 0, greater than 0, or exactly 0. Each value has special importance for how the data gets sorted. So, basically, we need a random number that meets this definition. For this, we use Math.random().

Math.random() returns a random number between 0 and 1. This is almost perfect, but we miss an entire number range, less than 0. Since the value from Math.random() could be 0.12, or 0.5, or 1, or even 0, we can subtract 0.5 from it to include the negative numbers in our range, and we still have the possibility of getting 0 or a value greater than 0. And so we have the following code:

?View Code JAVASCRIPT
var my_array = ['one','two','three'];
 
my_array.sort(function(){
	return Math.round(Math.random()) - 0.5;
});

A Not So Shuffled Array

At a glance, this looks like it should be perfect for what we need. When observed more carefully, though, we find inconsistancies in how the items actually get shuffled. This is due to the way the ‘sort’ method actually works. It’s based off the Bubble Sort algorithm. The bubble sort says, if A < B and B < C then there's no need to compare A and C. Because of this, some items may not actually get shuffled, and we end up with a not so shuffled array.

Fisher-Yates Shuffle

In 1938, two men known as Ronald Fisher and Frank Yates, outlined a way to randomize a list of numbers. We refer to it now as, the Fisher-Yates Shuffle. This method was released in their book, Statistical tables for biological, agricultural and medical research, and was designed to be implemented using pencil and paper. The method worked like this:

  1. Write down the numbers from 1 to N
  2. Pick a random number, k, between one and the number of unstruck numbers remaining (inclusive)
  3. Counting from the low end, strike out the kth number not yet struck out, and write it down elsewhere.
  4. Repeat from step 2 until all the numbers have been struck out.

Knuth Shuffle

If you were going to code the Fisher-Yates Shuffle using JavaScript, you would most likely model it off what we know as the Knuth Shuffle. In 1964, Richard Durstenfeld modernized the Fisher-Yates Shuffle for computer use in his book, Communications of the ACM, volume 7. This modernization was made popular as the Knuth Shuffle, by Donald E. Knuth, in volume 2 of his book, The Art of Computer Programming.

This approach is a little more difficult to implement than using ‘sort’, but the results are worth it. It works by looping the array backwards, and each time through, swapping the current item with a random item. The range that it uses to generate a random number follows the rule, 0 <= random number <= current index. If given an array with 4 items, the 4th item in the array will be swapped with an item at index positions 0, 1, or 2. The 3rd item will be swapped with the item at index positions 0 or 1. The 2nd item won't actually be so random, it will swap with the item at index position 0, the first item. At this point, the first item may or may not have already been swapped. By the time the fourth iteration occurres, all of the items in the array should have been shuffled, so it only loops n - 1 times, where 'n' represents the amount of items in the array. Here's what it looks like in JavaScript. I've attached it to the Array's prototype object so that every array has access to it.

?View Code JAVASCRIPT
Array.prototype.randomize = function()
{
	var i = this.length, j, temp;
	while ( --i )
	{
		j = Math.floor( Math.random() * (i - 1) );
		temp = this[i];
		this[i] = this[j];
		this[j] = temp;
	}
}
 
var my_array = ['one','two','three'];
my_array.randomize();

Contrasted Example

View: Live Example.

VN:F [1.9.22_1171]
Rating: 9.6/10 (16 votes cast)
VN:F [1.9.22_1171]
Rating: +4 (from 4 votes)
Share/Save

1 Comment

jQuery Autocomplete With MySQL And PHP

Making an auto-suggestion script, something that reads your input and shows related matches as you type, can be quite a challenge. It’s been made very popular by the big search engines. Yahoo did it first, and now Google has Instant which is killing its competitors. But how do you get one on your site? Luckily, jQuery has given us a very simple solution: http://jqueryui.com/demos/autocomplete/.

Let’s pretend you are making a website for a client who has multiple locations all throughout the United States. They ask you to build a form which takes a zipcode and spits out locations surrounding that zipcode. They also request, that, as the user types their zipcode, a suggestion box appears showing them relevant matches.

jQuery’s autocomplete makes this an easy task. The first thing you need to do, obviously, is create your form. Make sure you give your search box an id attribute, as it’s easier to work with that way.

<form action="search.php" method="post">
	Enter your zipcode:
	<input type="text" id="zipsearch" />
 
	<br />
	<input type="submit" value="Search" />
</form>

The second thing you need to do is tell jQuery to use its auto-complete User Interface (UI) on the search box you just made. When the auto-complete UI searches a database, you need to specify the website address for the PHP script that will be querying the database and returning results. Let’s call our script, ‘suggest_zip.php’ since it will be suggesting zip codes from partial searches. Also, to limit the amount of queries that are made, we can tell the auto-complete UI not to send anything to the server unless the user has typed at least ‘x’ amount of characters, or numbers in our case. Let’s limit ‘x’ to 2 numbers. We can stick this all in the ‘ready’ event, so it doesn’t fire until the document has loaded.

?View Code JAVASCRIPT
jQuery(document).ready(function($){
	$('#zipsearch').autocomplete({source:'suggest_zip.php', minLength:2});
});

And that’s it for the HTML and JavaScript side of things. Just make sure you are loading the required jQuery libraries to make this work. See the link for dependancies: http://jqueryui.com/demos/autocomplete/. You can download jQuery at the following locations: http://docs.jquery.com/Downloading_jQuery and http://jqueryui.com/download. Our script also uses jQuery’s ‘smoothness’ UI styles, which come bundled on their site. The UI styles style the results for us. You can make your own theme or use one of the pre-built themes jQuery has: http://jqueryui.com/themeroller/.

Now, let’s take a look at how we need to build our PHP script to work with the auto-complete UI that we just added to our form. First, we need to make a connection to the database. Since I use MySQL for my database, I’ll use mysql_connect and the mysql_* functions to make this script. After we have a valid connection to the database and the database we are using has been selected, mysql_select_db(), we can write our database query. Now, jQuery’s auto-complete expects two values to be returned along with each result: ‘value’ and ‘label’. Our script will be returning an array of data. Each item in that array needs to have ‘value’ and / or ‘label’. If ‘label’ is provided, jQuery shows your results using this, but when you select a result, it uses ‘value’ to populate your textbox. If ‘label’ is not provided, jQuery will use ‘value’ for both. So, our array in PHP looks like this: $data = array( array(‘label’=>’Item One’, ‘value’=>1) , array(‘label’=>’Item Two’, ‘value’=>2) ); If you need help with arrays in PHP, see the following webpage: http://php.net/array. When we return this data back to jQuery, we have to put it into a format that jQuery understands, which is JSON, aka. Javascript Object Notation. In order to turn an array of data from PHP into JSON, we use PHP’s built-in function json_encode. Use echo or print to transfer the data from PHP to jQuery: echo json_encode( $data ); If we take our array example above, what would be returned actually looks like this: [{“label”:”Item One”,”value”:1},{“label”:”Item Two”,”value”:2}], and that is JSON.

When jQuery sends the HTTP request to our suggest_zip.php script, it will send the text that’s being searched in the variable labeled, ‘term’. We can use $_REQUEST[‘term’] to access it. $_REQUEST allows us to access variables that were sent along with HTTP Requests, so if it was sent by an HTML Form Post, or over the URL: www.website.com?term=text, $_REQUEST will allow us to access it.

Let’s take a look at the PHP code inside of suggest_zip.php:

<?php
 
// if the 'term' variable is not sent with the request, exit
if ( !isset($_REQUEST['term']) )
	exit;
 
// connect to the database server and select the appropriate database for use
$dblink = mysql_connect('server', 'username', 'password') or die( mysql_error() );
mysql_select_db('database_name');
 
// query the database table for zip codes that match 'term'
$rs = mysql_query('select zip, city, state from zipcode where zip like "'. mysql_real_escape_string($_REQUEST['term']) .'%" order by zip asc limit 0,10', $dblink);
 
// loop through each zipcode returned and format the response for jQuery
$data = array();
if ( $rs && mysql_num_rows($rs) )
{
	while( $row = mysql_fetch_array($rs, MYSQL_ASSOC) )
	{
		$data[] = array(
			'label' => $row['zip'] .', '. $row['city'] .' '. $row['state'] ,
			'value' => $row['zip']
		);
	}
}
 
// jQuery wants JSON data
echo json_encode($data);
flush();

Here’s the SQL structure necessary for the zipcode table, written in MySQL:

create table zipcode
(
	id int not null primary key auto_increment ,
	zip varchar(20) not null ,
	city varchar(100) not null ,
	state varchar(5) not null 
);
create index idx_zipcode on zipcode ( zip(5) );

And that’s it. Now you have a form that will auto-suggest zipcodes as you type.

View: Live Example; suggest_zip.php

Download: ZIP Bundle – Grab this for a complete zipcode table and all the code bundled together.

Join us on DALNet for questions and discussion; irc.dal.net #php (requires IRC client)

Live Example

Grouped Results

As requested, here is an example demonstrating how to group the results in the autocomplete UI. Since this blog is rather old, I have chosen to demonstrate this using PDO instead of the deprecated mysql_* functions.

First, we need to create a custom autocomplete widget, so we can overload the method used to render the menu. When the UI renders the menu, it needs to read the current category, and if it’s not the same as the last category, it should print an LI with a special class on it, so the autocomplete knows it’s not a result. This assumes that the results are sorted by category, otherwise you will get the category listed multiple times.

?View Code JAVASCRIPT
$.widget('custom.groupedSearch', $.ui.autocomplete,
{
	_renderMenu: function(ul, items)
	{
		var currentCategory = "";
		$.each( items, $.proxy(function(index, item)
		{
			// evaluate the category and render an LI tag
			if (item.category != currentCategory)
			{
				ul.append("<li class='ui-autocomplete-category'>" + item.category + "</li>");
				currentCategory = item.category;
			}
 
			// render the item (this returns the LI DOMNode instance)
			var li = this._renderItem(ul, item);
		}, this));
	}
});
 
// initialize the custom autocomplete widget
$('.zipcode').groupedSearch({
	source : 'groupedZipcodeSearch.php' ,
	minLength : 2
});

The PHP just needs to order the mysql results by the category in question. In my example, the category consists of two fields, state taking precedence. Given a zipcode that starts with “123”, we could demonstrate this query as follows:

select zip, city, state
from zipcode
where zip like "123%" 
order by state asc, city asc, zip asc
limit 0,10

Next, include ‘category’ in the response array and javascript will be able to group it. This example groups the results by city and state, but the javascript will support any grouping, so long as its provided a ‘category’ key in the array returned from the suggestion script.

$data[] = array(
	'label' => 'Displayed Result' ,
	'value' => 'Chosen Result Value' ,
	'category' => 'Grouped Category'
);

View: Live Example; PHP Source

Live Example

Populating Related Fields

As requested, here is an example demonstrating how we might populate related form fields when an item is selected from the search results. This is actually a simple task. To demonstrate this, I’ll be populating the related City and State for the selected Zipcode.

The first step to this is structuring the query so it can fetch and return the desired fields with each row in the search results. It’s easy for my example because all of the data is stored in the same table.

select zip, city, state 
from zipcode 
where zip like '123%'
order by zip asc 
limit 0,10

The second step is formatting the data array before it gets JSON encoded. The related fields need to be included with each result.

$data[] = array(
	'value' => $row->zip ,
	'city' => $row->city ,
	'state' => $row->state
);

The third and final step is setting up the on-select handler for the jQuery Autocomplete UI. All we need to do is populate the related form fields from the data associated with the selected item.

My example is straight forward, all of the fields are in the same form, and I’m not modifying any HTML. You may have different logic in your on-select handler, but the idea is the same.

Please see http://api.jqueryui.com/autocomplete/#event-select for more information.

?View Code JAVASCRIPT
jQuery(document).ready(function(){
	$('.zipsearch').autocomplete({
		source:'jQueryAutocompleteRelatedFields.php', 
		minLength:2,
		select:function(evt, ui)
		{
			// when a zipcode is selected, populate related fields in this form
			this.form.city.value = ui.item.city;
			this.form.state.value = ui.item.state;
		}
	});
});

View: Live Example; PHP Source

Live Example

VN:F [1.9.22_1171]
Rating: 8.9/10 (325 votes cast)
VN:F [1.9.22_1171]
Rating: +52 (from 94 votes)

, , ,

105 Comments

Guess That Letter

Writing a guess-that-letter is almost exactly like writing Guess That Number, except instead of storing a numerical value, we store a character from A – Z. When the user guesses, we use the ascii value of the character to hint to the user, higher or lower.

?View Code JAVASCRIPT
var guess_ascii, guess_char, guess_tries = 0;
 
function RandomRange(low,high)
{
    return( Math.floor((high-low-1)*Math.random()) + low );
}
 
/* http://sharkysoft.com/tutorials/jsa/content/018.html */
function AsciiValue(c)
{
	// restrict input to a single character
	c = c.charAt (0);
 
	// loop through all possible ASCII values
	var i;
	for (i = 0; i < 256; ++ i)
	{
		// convert i into a 2-digit hex string
		var h = i . toString (16);
		if (h . length == 1)
			h = "0" + h;
 
		// insert a % character into the string
		h = "%" + h;
 
		// determine the character represented by the escape code
		h = unescape (h);
 
		// if the characters match, we've found the ASCII value
		if (h == c)
			break;
	}
	return i;
}
 
/**
* @desc Think of a number from 1 to x
* @param number range to guess within
**/
function GuessChar( num )
{
	guess_tries = 0;
	guess_range = num;
	guess_ascii = RandomRange(97,122);				// a is ascii char 97, z is ascii char 122
	guess_char = String.fromCharCode( guess_ascii );
}
 
function Guess( frm )
{
	var g = frm.guess1.value.toLowerCase();				// we are dealing with a-z not A-Z
	var ascii = AsciiValue(g);
 
	if ( ascii < 97 || ascii > 122 )
	{
		alert("Please insert a letter from A - Z.");
		return;
	}
 
	guess_tries += 1;
	status = "Tries: "+ guess_tries;
 
	if ( g == guess_char )
	{
		if ( guess_tries == 1 )
			alert("Correct!  You guessed it in 1 try!  Wow, good job!!");
		else
			alert("Correct!  You guessed it in "+ guess_tries +" tries!");
 
		GuessOver();
	} else if ( guess_tries >= 10 ) {
 
		alert("Sorry, time's up. The letter was: "+ guess_char);
		GuessOver();
	} else if ( ascii < guess_ascii )
		frm.hint.value = "No, guess higher.";
	else if ( ascii > guess_ascii )
 
		frm.hint.value = "No, guess lower.";
}
 
/**
* @desc Prompt to start the guessing game over
**/
function GuessOver()
{
	if ( !confirm('Would you like to play again?') )
	{
		alert("Thanks for playing!  :)");
		location.reload();
	} else {
		GuessChar();
		document.forms.form1.hint.value = "Enter your Guess.";
	}
}
 
// initialize the guessing game
GuessChar();

View: Open Source Copy


Guess That Letter

I'm thinking of a letter between A and Z. Try to guess it in less than 10 tries.



Guess:


VN:F [1.9.22_1171]
Rating: 6.8/10 (6 votes cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)

,

2 Comments

Guess That Number

Writing a guess-that-number script in javascript is notorious in low-level javascript classes. I can’t tell you how many times someone has approached me on IRC asking about, “how to make a guess that number script?”. Since I wrote it so many times, I figured I would post it here for the world to access.

Isn’t sharing fun?

?View Code JAVASCRIPT
var guess_num = 0, guess_range, guess_tries = 0;
 
/**
* @desc Think of a number from 1 to x
* @param number range to guess within
**/
function GuessNum( num )
{
	if ( isNaN(num) )
		throw "Invalid Number Provided For GuessNum()";
 
	guess_tries = 0;
	guess_range = num;
	guess_num = Math.floor(Math.random() * num) + 1;
}
 
function Guess( frm )
{
	var g = parseInt(frm.guess1.value);
 
	if ( isNaN(g) )
	{
		alert("Please insert a numerical value.");
		return;
	} else if ( g < 1 || g > guess_range ) {
		alert("You must select a number between 1 and "+ guess_range);
		return;
	}
 
	guess_tries += 1;
	status = "Tries: "+ guess_tries;
 
	if ( g == guess_num )
	{
		if ( guess_tries == 1 )
			alert("Correct!  You guessed it in 1 try!  Wow, good job!!");
		else
			alert("Correct!  You guessed it in "+ guess_tries +" tries!");
 
		GuessOver();
	} else if ( guess_tries >= 10 ) {
 
		alert("Sorry, time's up. The number was: "+ guess_num);
		GuessOver();
	} else if ( g < guess_num )
		frm.hint.value = "No, guess higher.";
	else if ( g > guess_num )
 
		frm.hint.value = "No, guess lower.";
}
 
/**
* @desc Prompt to start the guessing game over
**/
function GuessOver()
{
	if ( !confirm('Would you like to play again?') )
	{
		alert("Thanks for playing!  :)");
		location.reload();
	} else {
		GuessNum( 100 );
		document.forms.form1.hint.value = "Enter your Guess.";
	}
}
 
// initialize the guessing game
GuessNum( 100 );

View: Open Source Copy


Guess That Number

I'm thinking of a number between 1 and 100. Try to guess it in less than 10 tries.



Guess:


VN:F [1.9.22_1171]
Rating: 7.3/10 (3 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

,

No Comments