Categories

DataTables jQuery plugin

Datatables is a great jQuery plugin for enhancing your HTML tables. I used it extensively in a work project: I found it function-rich, easy to use, and well documented.

jQuery logoI used this jQuery plugin extensively on the last project I worked on. The code below can be seen in action in this demo.

  1. download the plugin: http://datatables.net/download/ (1.9.4 is the current version)
  2. unzip the files into a directory – I called mine js
  3. add jQuery and DataTables to your header
<script type="text/javascript" language="javascript" src="js/DataTables-1.9.4/media/js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="js/DataTables-1.9.4/media/js/jquery.dataTables.js"></script>
  1. initialize the plugin
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
    $('#example').dataTable();
});
</script>
  1. initialize the plugin
<table cellpadding="0" cellspacing="0" border="0" class="display" id="example" width="100%">
<thead>
<tr>
    <th>Rank</th>
    <th>Country (or dependent territory)</th>
    <th>Population</th>
    <th>Date</th>
    <th>&#160;% of world population</th>
    <th>Source</th>
</tr>
</thead>
<tbody>
<tr>
    <td>1</td>
    <td align="left">China</td>
    <td>1,347,350,000</td>
    <td>December 31, 2011</td>
    <td>19.17%</td>
    <td align="left">Official estimate</td>
</tr>
<tr>
    <td>2</td>
    <td align="left">India</td>
    <td>1,210,193,422</td>
    <td>March 1, 2011</td>
    <td>17.21%</td>
    <td align="left">2011 census</td>
</tr>
<tr>
    <td>3</td>
    <td align="left">United States</td>
    <td>314,028,000</td>
    <td>August 2, 2012</td>
    <td>4.47%</td>
    <td align="left">Official population clock</td>
</tr>
<tr>
    <td>4</td>
    <td align="left">Indonesia</td>
    <td>237,641,326</td>
    <td>May 1, 2010</td>
    <td>3.38%</td>
    <td align="left">2010 census</td>
</tr>
</tbody>
</table>

http://datatables.net/

Working with Exif data in PHP

A member of a forum I belong to was asking for information around extracting GPS data from geo-tagged images. I have had some fun with software like GeoSetter and RoboGEO, but neither of these create a simple list of GPS co-ordinates.

The PHP Exif extension allows you to work with image meta data.

For example, you may use exif functions to read meta data of pictures taken from digital cameras by working with information stored in the headers of the JPEG and TIFF images. In this instance, I wanted to get a list of images, and then output the Exif data, specifically the geo data, in different formats. I added a handy little function to recursively list image files in directories.

In its simplest form, if you have an image called dog.jpg in the same directory as your script, you would simply do something like:

<?php
    print_r(exif_read_data("dog.jpg"));
?>

A quick demo here.

Depending entirely on the image, you will get something like what I have pasted in at the bottom of this post. There is a whole heap of stuff in there that doesn’t really make sense,  like the “[UndefinedTag:0x000D] => Array”, much of which I deleted from the output. This is because to a large extent different manufacturers have different ideas of what should be in the Exif data.

However, there is plenty useful stuff for us to consume! I was obviously interested in the GPS data, but there is plenty of other useful info, such as camera and camera setting information.

(
	[FileName] => dog.jpg
	[FileDateTime] => 1395322662
	[FileSize] => 3034999
	[FileType] => 2
	[MimeType] => image/jpeg
	[SectionsFound] => ANY_TAG, IFD0, THUMBNAIL, EXIF, GPS, INTEROP, MAKERNOTE
	[COMPUTED] => Array
		(
			[html] => width="4320" height="3240"
			[Height] => 3240
			[Width] => 4320
			[IsColor] => 1
			[ByteOrderMotorola] => 0
			[CCDWidth] => 6mm
			[ApertureFNumber] => f/4.0
			[UserComment] => 
			[UserCommentEncoding] => UNDEFINED
			[Thumbnail.FileType] => 2
			[Thumbnail.MimeType] => image/jpeg
		)

	[ImageDescription] =>                                
	[Make] => Canon
	[Model] => Canon PowerShot SX210 IS
	[Orientation] => 1
	[XResolution] => 180/1
	[YResolution] => 180/1
	[ResolutionUnit] => 2
	[DateTime] => 2013:09:07 13:49:20
	[YCbCrPositioning] => 2
	[Exif_IFD_Pointer] => 246
	[GPS_IFD_Pointer] => 3410
	[THUMBNAIL] => Array
		(
			[Compression] => 6
			[XResolution] => 180/1
			[YResolution] => 180/1
			[ResolutionUnit] => 2
			[JPEGInterchangeFormat] => 3730
			[JPEGInterchangeFormatLength] => 8192
		)

	[ExposureTime] => 1/60
	[FNumber] => 40/10
	[ISOSpeedRatings] => 80
	[ExifVersion] => 0221
	[DateTimeOriginal] => 2013:09:07 13:49:20
	[DateTimeDigitized] => 2013:09:07 13:49:20
	[ComponentsConfiguration] => 
	[CompressedBitsPerPixel] => 3/1
	[ShutterSpeedValue] => 189/32
	[ApertureValue] => 128/32
	[ExposureBiasValue] => 0/3
	[MaxApertureValue] => 104/32
	[MeteringMode] => 5
	[Flash] => 24
	[FocalLength] => 5000/1000
	[MakerNote] => 0.??"???
	[UserComment] => 
	[FlashPixVersion] => 0100
	[ColorSpace] => 1
	[ExifImageWidth] => 4320
	[ExifImageLength] => 3240
	[InteroperabilityOffset] => 3356
	[FocalPlaneXResolution] => 4320000/243
	[FocalPlaneYResolution] => 3240000/182
	[FocalPlaneResolutionUnit] => 2
	[SensingMethod] => 2
	[FileSource] => 
	[CustomRendered] => 0
	[ExposureMode] => 0
	[WhiteBalance] => 0
	[DigitalZoomRatio] => 4320/4320
	[SceneCaptureType] => 0
	[GPSVersion] => 
	[GPSLatitudeRef] => S
	[GPSLatitude] => Array
		(
			[0] => 34/1
			[1] => 18/1
			[2] => 108503/2345
		)

	[GPSLongitudeRef] => E
	[GPSLongitude] => Array
		(
			[0] => 19/1
			[1] => 0/1
			[2] => 215185/3867
		)

	[GPSAltitudeRef] => 
	[GPSAltitude] => 4645923/8332
	[GPSTimeStamp] => Array
		(
			[0] => 11/1
			[1] => 49/1
			[2] => 20/1
		)

	[GPSMapDatum] => WGS-84
	[GPSDateStamp] => 2013:09:07
	[InterOperabilityIndex] => R98
	[InterOperabilityVersion] => 0100
	[RelatedImageWidth] => 4320
	[RelatedImageHeight] => 3240
	[ModeArray] => Array
		(
			[0] => 96
			[1] => 2
			[2] => 0
			[3] => 3
			[4] => 5
			[5] => 0
			[6] => 0
			[7] => 4
			[8] => 65535
			[9] => 1
			[10] => 0
			[11] => 0
			[12] => 0
			[13] => 0
			[14] => 0
			[15] => 0
			[16] => 15
			[17] => 3
			[18] => 1
			[19] => 16390
			[20] => 0
			[21] => 32767
			[22] => 65535
			[23] => 7000
			[24] => 500
			[25] => 100
			[26] => 104
			[27] => 221
			[28] => 65535
			[29] => 0
			[30] => 0
			[31] => 0
			[32] => 1
			[33] => 0
			[34] => 1
			[35] => 0
			[36] => 4320
			[37] => 4320
			[38] => 0
			[39] => 0
			[40] => 65535
			[41] => 0
			[42] => 32767
			[43] => 32767
			[44] => 0
			[45] => 0
			[46] => 65535
			[47] => 140
		)

	[ImageInfo] => Array
		(
			[0] => 68
			[1] => 65523
			[2] => 160
			[3] => 196
			[4] => 128
			[5] => 189
			[6] => 0
			[7] => 0
			[8] => 0
			[9] => 0
			[10] => 0
			[11] => 0
			[12] => 0
			[13] => 0
			[14] => 0
			[15] => 0
			[16] => 0
			[17] => 0
			[18] => 1
			[19] => 18
			[20] => 0
			[21] => 127
			[22] => 192
			[23] => 0
			[24] => 0
			[25] => 65533
			[26] => 250
			[27] => 0
			[28] => 0
			[29] => 0
			[30] => 0
			[31] => 0
			[32] => 0
			[33] => 0
		)

	[UndefinedTag:0x0000] => Array
		(
			[0] => 0
			[1] => 0
			[2] => 0
			[3] => 0
			[4] => 0
			[5] => 0
		)

	[ImageType] => IMG:PowerShot SX210 IS JPEG
	[FirmwareVersion] => Firmware Version 1.00
	[ImageNumber] => 1337140
	[OwnerName] => 
	[UndefinedTag:0x000D] => Array
		(
			[0] => 6
			[1] => 371
			[2] => 411
			[3] => 0
			[4] => 0
			[5] => 0
			[6] => 383
			[7] => 576
			[8] => -40
			[9] => 0
			[10] => 0
			[11] => 0
			[12] => 0
			[13] => 576
			[14] => 567
			[15] => -154
			[16] => 0
			[17] => 0
			[18] => -10
			[19] => 0
			[20] => 0
			[21] => -8
			[22] => -10
			[23] => 0
			[24] => 0
			[25] => 9
			[26] => 10
			[27] => 588
			[28] => 588
			[29] => 588
			[30] => 383
			[31] => 737
			[32] => -167
			[33] => 0
			[34] => 0
			[35] => 588
			[36] => 588
			[37] => 0
			[38] => 0
			[39] => 7
			[40] => 0
			[41] => 10
			[42] => 0
			[43] => 0
			[44] => 0
			[45] => 0
			[46] => 0
			[47] => 0
			[48] => 0
			[49] => 0
			[50] => 0
			[51] => 240
			[52] => 1024
			[53] => 1024
			[54] => 262
			[55] => 309
			[56] => 0
			[57] => 0
			[58] => 0
			[59] => 0
			[60] => 0
			[61] => 0
			[62] => 156
			[63] => 0
			[64] => 263
			[65] => 307
			[66] => 0
			[67] => 0
			[68] => 0
			[69] => 0
			[70] => 0
			[71] => 0
			[72] => 1024
			[73] => 1019
			[74] => 1029
			[75] => 1286
			[76] => 8
			[77] => 263
			[78] => 307
			[79] => 23
			[80] => 938
			[81] => 1439
			[82] => 1829
			[83] => 938
			[84] => 100
			[85] => 0
			[86] => 0
			[87] => 1
			[88] => 322
			[89] => 799
			[90] => 588
			[91] => 699
			[92] => -167
			[93] => -7
			[94] => 192
			[95] => 511
			[96] => 0
			[97] => 0
			[98] => 820
			[99] => 3
			[100] => 1
			[101] => 861
			[102] => 898
			[103] => 951
			[104] => 0
			[105] => 0
			[106] => 0
			[107] => 0
			[108] => 0
			[109] => 847
			[110] => 866
			[111] => 829
			[112] => 851
			[113] => 867
			[114] => 832
			[115] => 854
			[116] => 862
			[117] => 833
			[118] => 879
			[119] => 838
			[120] => 950
			[121] => 826
			[122] => 865
			[123] => 195
			[124] => 0
			[125] => 0
			[126] => 0
			[127] => 1080
			[128] => 406
			[129] => 250
			[130] => 94
			[131] => 832
			[132] => 313
			[133] => 194
			[134] => 73
			[135] => 0
			[136] => 0
			[137] => 3
			[138] => 3
			[139] => 2
			[140] => 0
			[141] => 0
			[142] => 0
			[143] => 0
			[144] => 0
			[145] => 0
			[146] => -1895
			[147] => -616
			[148] => 49
			[149] => 65443
			[150] => 0
			[151] => -3072
			[152] => 133
			[153] => 614
			[154] => 499
			[155] => 0
			[156] => 170
			[157] => 0
			[158] => 0
			[159] => 192
			[160] => 324
			[161] => 256
			[162] => 324
			[163] => 64
			[164] => 10
			[165] => 0
			[166] => 0
			[167] => 0
			[168] => 16
			[169] => 13
			[170] => 423901588
		)

	[UndefinedTag:0x0013] => Array
		(
			[0] => 0
			[1] => 0
			[2] => 0
			[3] => 0
		)

	[UndefinedTag:0x0018] => 
	[UndefinedTag:0x0019] => 1
	[UndefinedTag:0x001C] => 0
	[UndefinedTag:0x001D] => Array
		(
			[0] => 32
			[1] => 1
			[2] => 0
			[3] => 2
			[4] => 2
			[5] => 2
			[6] => 2
			[7] => 0
			[8] => 0
			[9] => 0
			[10] => 0
			[11] => 0
			[12] => 0
			[13] => 0
			[14] => 0
			[15] => 0
		)

	[UndefinedTag:0x001E] => 16777984

	[UndefinedTag:0x0022] => Array
		(
			[0] => 416
			[1] => 0
			[2] => 0
			[3] => 16
			[4] => 8
			[5] => 1
			[6] => 1
			[7] => 640
			[8] => 480
			[9] => 0
			[10] => 0
			[11] => 0
			[12] => 0
			[13] => 0
			[14] => 8
			[15] => 384
			[16] => 0
			[17] => 0
			[18] => 0
			[19] => 0
			[20] => 0
			[21] => 0
			[22] => 0
			[23] => 0
			[24] => 0
			[25] => 0
			[26] => 0
			[27] => 0
			[28] => 0
			[29] => 0
			[30] => 0
			[31] => 0
			[32] => 0
			[33] => 0
			[34] => 0
			[35] => 0
			[36] => 0
			[37] => 0
			[38] => 0
			[39] => 0
			[40] => 0
			[41] => 0
			[42] => 0
			[43] => 0
			[44] => 0
			[45] => 0
			[46] => 0
			[47] => 0
			[48] => 0
			[49] => 0
			[50] => 0
			[51] => 0
			[52] => 0
			[53] => 0
			[54] => 0
			[55] => 0
			[56] => 0
			[57] => 0
			[58] => 0
			[59] => 0
			[60] => 0
			[61] => 0
			[62] => 0
			[63] => 0
			[64] => 0
			[65] => 0
			[66] => 0
			[67] => 0
			[68] => 0
			[69] => 0
			[70] => 0
			[71] => 0
			[72] => 0
			[73] => 0
			[74] => 0
			[75] => 0
			[76] => 0
			[77] => 0
			[78] => 0
			[79] => 0
			[80] => 0
			[81] => 0
			[82] => 0
			[83] => 0
			[84] => 0
			[85] => 0
			[86] => 0
			[87] => 0
			[88] => 0
			[89] => 0
			[90] => 0
			[91] => 0
			[92] => 0
			[93] => 0
			[94] => 0
			[95] => 0
			[96] => 0
			[97] => 0
			[98] => 0
			[99] => 0
			[100] => 0
			[101] => 0
			[102] => 0
			[103] => 0
			[104] => 0
			[105] => 0
			[106] => 0
			[107] => 0
			[108] => 0
			[109] => 0
			[110] => 0
			[111] => 0
			[112] => 0
			[113] => 0
			[114] => 0
			[115] => 0
			[116] => 0
			[117] => 0
			[118] => 0
			[119] => 0
			[120] => 0
			[121] => 0
			[122] => 0
			[123] => 0
			[124] => 0
			[125] => 0
			[126] => 0
			[127] => 0
			[128] => 0
			[129] => 0
			[130] => 0
			[131] => 0
			[132] => 0
			[133] => 0
			[134] => 0
			[135] => 0
			[136] => 0
			[137] => 0
			[138] => 0
			[139] => 0
			[140] => 0
			[141] => 0
			[142] => 0
			[143] => 0
			[144] => 0
			[145] => 0
			[146] => 0
			[147] => 0
			[148] => 0
			[149] => 0
			[150] => 0
			[151] => 0
			[152] => 0
			[153] => 0
			[154] => 0
			[155] => 0
			[156] => 0
			[157] => 0
			[158] => 0
			[159] => 0
			[160] => 0
			[161] => 0
			[162] => 0
			[163] => 0
			[164] => 0
			[165] => 0
			[166] => 0
			[167] => 0
			[168] => 0
			[169] => 0
			[170] => 0
			[171] => 0
			[172] => 0
			[173] => 0
			[174] => 0
			[175] => 0
			[176] => 0
			[177] => 0
			[178] => 0
			[179] => 0
			[180] => 0
			[181] => 0
			[182] => 0
			[183] => 0
			[184] => 0
			[185] => 0
			[186] => 0
			[187] => 0
			[188] => 0
			[189] => 0
			[190] => 0
			[191] => 0
			[192] => 0
			[193] => 0
			[194] => 0
			[195] => 0
			[196] => 0
			[197] => 0
			[198] => 0
			[199] => 0
			[200] => 0
			[201] => 0
			[202] => 0
			[203] => 0
			[204] => 0
			[205] => 0
			[206] => 0
			[207] => 0
		)

	[UndefinedTag:0x0023] => Array
		(
			[0] => 8
			[1] => 0
		)

	[UndefinedTag:0x0027] => Array
		(
			[0] => 10
			[1] => 0
			[2] => 65535
			[3] => 0
			[4] => 16
			[5] => 18
			[6] => 257
			[7] => 0
			[8] => 0
		)

	[UndefinedTag:0x0028] => ??3W?hZ???????
	[UndefinedTag:0x00D0] => 0
	[UndefinedTag:0x002D] => 0
	[UndefinedTag:0x002E] => Array
		(
			[0] => 8
			[1] => 32767
			[2] => 32767
			[3] => 65535
		)
)

setting webdriver capabilities on BrowserStack

So I am busy with some POC work on BrowserStack. I am battling with network latency, so am attempting to set the timeouts available to be as lenient as possible.

BrowserStack logoBrowserStack supports the out-of-the-box Selenium capabilities, and offers a number of additional capabilities.

this.driver = new webdriver.Builder().withCapabilities({'browserName': "firefox"}).build();

However, when you start searching for the less obvious options, be careful as the documentation is a bit sparse, and the options are not made that clear at all. In addition to this, the way that the capabilities are catered for is a bit loose, so even the following will “work”:

this.driver = new webdriver.Builder().withCapabilities({'you': "mamparra"}).build();

Also note that the times specified on the webpage are maximums – you cannot exceed them.

Automating Selenium Test Suites

We have a set of automated Selenium test suites that run as a nightly batch on an automation box. I decided it would be a worthwhile exercise to set this up on my local dev machine.

  1. Create a new Firefox profile (see this great post here: http://girliemangalo.wordpress.com/2009/02/05/creating-firefox-profile-for-your-selenium-rc-tests/). I called mine selenium
  2. On your root:
      1. Create a folder: C:\my_test_runner
      2. Create a sub-folder: C:\my_test_runner\my_test
      3. Create the following batch files and save them to C:\my_test_runner
        1. run _these_tests.bat@ECHO OFF
          REM created: 2012/03/15 08:30 by David Fox
          call test_runner.bat 127.0.0.1 my_test
        2. test_runner.bat@echo off
          set IP=%1set TEST=%2rem SETUP FIREFOX STUFF ———————————————————
          @set PROFILE=C:\Users\david.fox\AppData\Roaming\Mozilla\Firefox\Profiles\l4xy0w59.selenium
          rem SETUP BASE WEB PAGE ———————————————————
          @set BVSM=http://%IP%/
          rem SETUP SELENIUM STUFF ——————————————————–
          @set SUITE=C:\my_test_runner\%TEST%\%TEST%_suite.html
          @set RESULTS=C:\my_test_runner\%TEST%\%TEST%_results.html
          rem RUN TEST SUITE ————————————————————–
          java -jar C:\Users\Public\Documents\usm-8.0\HCS\selenium\run\selenium-server-standalone-2.20.0.jar -timeout 3000 -firefoxProfileTemplate %PROFILE% -multiWindow -htmlSuite “*firefox” “%BVSM%” “%SUITE%” “%RESULTS%”
      4. Install JRE
      5. Download the latest Selenium Standalone Server http://code.google.com/p/selenium/downloads/detail?name=selenium-server-standalone-2.20.0.jar to C:\my_test_runner
      6. Make certain the path where your bat executable resides must be in your Windows %path% environment variable
      7. Create a new Test suite called my_test_suite.html saved in C:\my_test_runner\my_test

Number output exercise using PHP modulus

And here is a particularly ugly solution to a simple problem:

The code is self-documenting.

<?php

/*
* Write a script that prints the numbers 1 to 100 in black font.
* But for multiples of 3, print the word "Three" in green, and for multiples of 7, print the word "Seven" in blue instead of the number.
* If the number is a multiple of BOTH 3 and 7, then print the word "Both" in red.
* Include HTML line breaks after each number (or word), so the output is legible.
*/

$my_limit = 100;
$counter = 1;

    while($counter <= $my_limit)
    {
        $color_class = '#000000';
        $counter_output = $counter;
        if($counter % 3 == 0 && $counter % 7 == 0)
        {
            $color_class = '#990000';
            $counter_output = 'both';
        } elseif($counter % 7 == 0) {
            $color_class = '#000099';
            $counter_output = 'seven';
        } elseif($counter % 3 == 0) {
            $color_class = '#009900';
            $counter_output = 'three';
        }
        echo '<span style="color: '.$color_class.'">'.$counter_output.'</span><br />';
        $counter++;
    }
?>

jQuery Highlighter plugin

I am currently on the job market, and it seems to be quite fashionable for companies to require candidates to submit code to secure an interview. Some of the tasks have been fairly interesting, like this one.

The task required code to upload a text file and display it in the browser with a specific term highlighted. I wrote and submitted the first version which is a pretty standard approach I guess, but then after submitting it I decided I would quickly improve on it just for fun.

Both start with the upload of a text file:

  1. then the first uses basic HTML, CSS and PHP to return the text to the browser with the search term highlighted, and
  2. the second uses a jQuery plug-in to highlight the search term in the returned text in the browser.

Here is the link to the plugin: http://bartaz.github.com/sandbox.js/jquery.highlight.html

And here is a link to a quick and dirty demo!

jQuery logo

PHP Bingo

This was another little exercise I was asked to submit as part of a job application. I think my code is clear and self documenting, so without further ado, here it is:

<?php

/*
* Create a script in PHP that simulates the extraction of a Bingo game. The goal is to print a list of numbers ranging from one to ninety, randomly shuffled.
*/

$low = 1;
$high = 99;

$bingo_arr = array();
$bingo_arr = range($low, $high);

shuffle($bingo_arr);

echo '<pre>';
print_r($bingo_arr);
echo '</pre>';
?>

Smarterer - rate your skills online

Quite understandably, companies advertising roles for developers are using a variety of different methods to filter applicants. Often this is simply in the form of a request to answer a few questions and / or complete a (sometimes-not-so-small) code example. Recently I was sent a set of links to a site called Smarterer as part of this process.

This is how they describe themselves:

We created Smarterer to provide people a simple, fun, and authentic way to show what they know. Smarterer is a platform designed to score individuals on any and every digital, social, and technical skill under the sun. Using crowdsourced test design and a scoring mechanism similar to the one developed to rank chess masters, in just 10 questions and 60 seconds we can give you a valid score.

Each test is a series of multiple choice questions. There is a time limit on each question (making Googling the answer nigh impossible). The tests are created by the community, and there are options to flag and comment on questions.

You can choose to make your scorecard public so that a prospective employer can see the score you have attained. Mine is here: http://smarterer.com/foxbeefly

smarterer logo

PHP to highlight search text

So here is part of another little problem solving exercise I was confronted with at a recent interview: “You are required to produce some PHP code that highlights a term in some text.”

On my first quick pass I just jammed the following line in to find the search string and replace it with the search string plus some styling:

$highlightedOutput= str_replace($searchTerm, '<span class="highlighted_search_term">'.$searchterm.'</span>', $forHighlighting);

A quick test run, and you will realise this is fine until you start looking at case sensitive, or case insensitive results: because you are searching for a string, it will be case sensitive. If you want to offer case-insensitive results, you will have to look a bit further…

$highlightedOutput = preg_replace("|($searchTerm)|Ui", "<span class=\"highlighted_search_term\">$1</span>", $forHighlighting);

In simple terms, we are replacing the search term with the search term plus some styling. I am not going to go into to much detail on the use of preg_match — that’s a topic on it’s own!

  • the pipe characters are our delimiters
  • the  U is for ungreedy
  • the i is for caseless
  • the parentheses create a pattern for the back reference
  • and the $1 is the back reference

And here is a link to a quick and dirty demo!

PHP logo

Clearing the contents of a form in a dialog in jQuery Mobile

So having a multi-page set-up where the code for a dialog is in the loaded page is pretty handy, but can lead to some problems. For example: if you have a contact form that opens in a dialog from your page and your user fills the form in and then cancels it without submitting it, if he then reopens the form, it will be populated with the data he entered previously.

You could of course provide the user with a reset button, but it would be a whole lot tidier if the form values were cleared automatically.

The important code is contained in the highlighted lines below. As you can see, all that is happening is that the form with id contactForm is being reset before the “page” with id contactPopup is loaded in the browser. This assumes that there is only one form in the entire “page” as we are referring to it by it’s index, 0. You could naturally adjust this to the index of another form should there be multiple forms in the “page”.

<!doctype html>
<body>
<!-- Start of Main page -->
<div data-role="page">
    <div data-role="header">
        <h1>Login</h1>
    </div>
    <div data-role="content">
        <!-- here is the content of the main "page" -->
    </div>
    <div data-role="footer" class="ui-bar" data-position="fixed">
        <a href="#contactPopup" data-rel="dialog" data-mini="true" data-inline="true" data-role="button" data-icon="star" data-transition="flip">Contact</a>
    </div>
</div>
<!-- Start of Contact popup -->
<div data-role="page" id="contactPopup">
    <div data-role="header">
        <h1>Contact</h1>
    </div>
    <div data-role="content">
        <form id="contactForm" method="post">
            <div data-role="fieldcontain">
                <label for="contactName">Full name</label>
                <input name="contactName" id="contactName" placeholder="full name" type="text" required="required" />
            </div>
            <div data-role="fieldcontain">
                <label for="contactEmail">Email</label>
                <input name="contactEmail" id="contactEmail" placeholder="email address" type="email" required="required" />
            </div>
            <div data-role="fieldcontain">
                <label for="contactMessage">Message</label>
                <textarea name="contactMessage" id="contactMessage" placeholder="your message..."></textarea>
            </div>
            <a href="#" data-role="button" data-rel="back" data-inline="true" data-icon="delete" data-theme="e">Cancel</a>
            <input type="submit" name="submit" value="Send" data-inline="true" data-icon="check" data-theme="b" />
        </form>
    </div>
</div> <!-- end of Contact popup -->
<script>
    $(document).on('pagebeforeshow', '#contactPopup', function() {
        $('#contactForm')[0].reset();
    });
</script>
</body>
</html>

jQuery Mobile logo