Display UTC and local time using analogue clocks. This document uses Javascript and inline SVG code in an XHTML document. It can be viewed using a SVG-capable browser such as Chrome. I wrote this page nearly a decade ago and only ported it to Blogger.
Nuts and bolts about programming applications, databases and spreadsheets. Note: Comments are moderated to filter comment spam. Mobile version
2015-08-23
2009-08-09
Read 'Times Online' article comments earliest first
The comments appearing after articles in the Times Online are displayed in reverse chronological order (latest first), which I find difficult to read, so I wrote this GreaseMonkey jQuery script to click the Oldest first link after the page is loaded:
// ==UserScript== // @name Timesonline.co.uk earliest comment first // @namespace kamhungsoh.com // @description Show an article's comments, earliest comment first. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js // @include http://*.timesonline.co.uk/* // ==/UserScript== var evt = document.createEvent('HTMLEvents'); evt.initEvent('click', true, true); $("a:contains('Oldest first')").each(function() { this.dispatchEvent(evt); });
The script is a little more complicated than I expected. Apparently jQuery cannot send events (see the last response in the thread) that it itself did not bind to objects, so my script has to create a click event object and send it to the link. Otherwise, I would written $("a:contains('Oldest first')").trigger('click');
Also, the script's a little hacky because it will send a click event to all links containing the text 'Oldest first', though it seems pretty unlikely that a page will have more than one link of that type in the first place.
2009-06-10
Localize dates in Scientific American
Scientific American formats dates in its pages as m/d/yy, while I prefer d/m/yy. Like an earlier post about formatting dates in Blogger's Dashboard, this Greasemonkey script uses a regular expression to find date strings in a page, and switches the month and day values.
// ==UserScript== // @name Scientific American localize dates // @namespace kamhungsoh.com // @description Convert dates from mm/dd/yy to dd/mm/yy format // @require http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js // @include http://www.scientificamerican.com/* // ==/UserScript== $('span').each(function() { var s = $(this).text().replace(/(.*)(\d+)\/(\d+)\/(\d+)/, '$1$3/$2/$4'); $(this).text(s); });
The script only works for the home page and I haven't figured out why I can't construct an expression to locate date strings in articles. Another thing to note is that jQuery's .text() function returns all the text values in a node, so some of the formatting, such as strong tags, are lost when the script replaces the text.
2009-06-07
Reformatting post dates in Blogger Dashboard
In the Blogger Dashboard, the posting date of your entries are in mm/dd/yy format and Google doesn't provide a way to localize it or choose a date format. Here's how you can use a Greasemonkey script to convert dates in Dashboard to dd/mm/yy format.
The dates in Dashboard have this structure:
<td class="date"> <span>3/6/09</span> </td>
The following script uses jQuery to iterate through all span nodes of td elements with a date class attribute, then applies the Javascript string replace() function to swap the first two numbers in the span node. To change the output string, just modify the second argument of the replace() function.
// ==UserScript== // @name blogger.com localize dashboard date // @namespace kamhungsoh.com // @description Convert date format from m/d/yy to d/m/yy. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js // @include http://www.blogger.com/posts.g* // ==/UserScript== $("td.date > span").each(function() { var s = $(this).text().replace(/(\d+)\/(\d+)/, '$2\/$1'); $(this).text(s); });
The first argument of the replace() function is a regular expression where \d is a meta-character for a digit, + matches one or more of the preceding character (e.g. 4 or 23) and the parentheses group the characters to be memorised. The forward slash has to be escaped, \/, to allow us to match it in the input string. In the second argument, the $2/$1 represents the second and first memorised strings.
2009-05-31
Simple loading of HTML fragment using jQuery AJAX
jQuery provides a simple load() function to load an HTML fragment using AJAX. To test it, create a test data file called data.html:
<html> <body> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li>Item 4</li> </ul> </body> </html>
Next, create a target HTML file called testLoad.html in the same folder with the following jQuery statement:
<html> <head> <title>jQuery load HTML test</title> <script type='text/javascript' src='js/jquery-1.3.2.min.js'></script> <script type="text/javascript"> $(document).ready(function() { $('#myLinks').load('data.html ul li'); }); </script> </head> <body> <ul id="myLinks"></ul> </body> </html>
When you view testLoad.html, you should see the list items in data.html inserted into the target file, in the unordered list named myLinks.
It was a little fiddly to get this working the first time. If your source HTML file has an error, nothing seems to happen; in that case, check your browser's error console to see what went wrong. For instance, in Firefox, when my source HTML file wasn't well-formed, I found this error:
Error: mismatched tag. Expected: </ul>. Source File: Line: 8, Column: 5 Source Code: </body>
Another thing I found is that you can't include an XML processing instruction (<? ... ?> lines) in your data file because when load() tries to insert your XML file into your target document, you would get an error like this:
Error: XML or text declaration not at start of entity Source File: Line: 1, Column: 43 Source Code: <div xmlns="http://www.w3.org/1999/xhtml"><?xml version="1.0" encoding="UTF-8"?>
2009-05-29
Selecting parent or ancestor of a node in jQuery
When manipulating an HTML document (especially one that you didn't generate), it can be easier to find a node by matching its descendant's unique id or class attribute and value first, then selecting that descendant's ancestor (which is the node you wanted to in the first place), compared to finding that node by referring to its position in the DOM, which is not obvious and isn't easy to maintain.
For example, in the Australian Government Bureau of Meterology site, you might want to highlight temperature and forecast for Melbourne, so the simplest thing to do is change the style of the row containing that string, but there's no unique attribute you can use to select that row (or tr node):
<tr> … </tr> <tr> <td> <div> <table> <tbody> <tr> <td><a href='…'>Sydney</a></td> <td>20</td> <td>Shower or two</td> </tr> <tr> <td><a href='…'>Melbourne</a></td> <td>16</td> <td>Shower or two</td> </tr> … </tbody> </table> <table> … </table> </div> </td> </tr>
For this site, the trick
is to select the td node containing Melbourne
, then find the first tr ancestor. Here's a sample script using jQuery:
// ==UserScript== // @name www.bom.gov.au Highlight City // @namespace kamhungsoh.com // @description Highlight row of a specific city. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js // @include http://www.bom.gov.au // ==/UserScript== $("a:contains(Melbourne)").each(function() { $(this).parents('tr:eq(0)').css('background-color', 'grey'); });
In this script, for each a node with a value of Melbourne
, find the first tr parent using :eq(0) and change its background colour. You have to constrain the selection of parents to the first parent, otherwise all the tr ancestors will be selected; on this site, nested tables are used for layout so without this constraint, the enclosing tr node of the table will also be found and modified.
2009-05-27
Zebra-stripe table rows with jQuery's custom selectors
I thought I had a simple way to zebra-stripe table rows in jQuery:
$('table tbody tr').each(function(i) { $(this).addClass(i%2 ? 'OddRow' : 'EvenRow'); });
While I was looking up jQuery selectors, I found that the library has two custom selectors, :odd and :even, to select the odd and even elements in a matched element set, respectively, so you could zebra-stripe a table like this:
$('table tbody tr:odd').addClass('OddRow'); $('table tbody tr:even').addClass('EvenRow');
The second example seems a little more obvious.
See Also
- jQuery Selectors
2009-05-26
Read 'The Economist' article comments earliest first
A simple GreaseMonkey script using jQuery to show the comments to articles in The Economist, from earliest first. Basically, this script looks for <a> tags with specific text in their href attribute and appends &sort=asc. It's shorter and easier to read than the original plain Javascript version.
See Also
- GreaseMonkey jQuery script in userscripts.org
- GreaseMonkey plain Javascript version, Modify URL to read comments from beginning
2009-05-08
Modify URL to Read Comments From Beginning
When I read responses or comments to articles, I prefer to read them from the earliest to the latest. Some sites order comments in reverse (that is, latest to earliest). If a site's comment link can take an 'order' argument, just modify that URL to specify your preferred order and save yourself an extra click. Below is a sample GreaseMonkey script that can specify the order of comments in The Economist, which are ordered from latest to earliest, by default.
var pattern = 'mode=comment'; var sortOrder = '&sort=asc'; var links = document.getElementsByTagName('a'); for (var i = links.length - 1; i >= 0; --i) { var link = links[i]; var url = link.getAttribute('href'); if (url.search(pattern) != -1) { link.setAttribute('href', url.replace(pattern, pattern + sortOrder)); } }
To use it on other sites that have similar URLs, just modify the values of pattern and sortOrder.
2009-05-06
Simple Data Grid Using PHP and jQuery
Introduction
This article walks though the process of writing a simple Web-based data grid application for browsing a database table, using the PHP Web scripting language, jQuery Javascript library and MySQL DBMS.
Requirement and Design
The grid is just an HTML table, with filters for each column and pagination controls at the bottom of the table. The filters are implemented using drop down lists, and the pagination can be done using two buttons, one to move to the next page, the other to move to the previous page of data:
+-------------+-------------+ |Column header|Column header| | Filter | Filter | +-------------+-------------+ |Data row1 | |Data row2 | |Data row3 | +-------------+-------------+ |Pagination controls | +-------------+-------------+
Two other requirements are to ensure that the data grid can be used with or without Javascript, and that it can be used in Firefox, MSIE and Opera.
One We Prepared Earlier …
To orient you, check out the data grid implementation first. Try it with Javascript enabled and disabled on your browser. When Javascript is disabled, you have to first select a filter value, then press the Submit button before the grid is updated.
When Javascript is enabled, just changing a filter value will update the grid and you can reset all the filters at once by pressing the Reset button. Also, the presentation is slightly enhanced by zebra-striping the rows to make them easier to view.
As you filter or paginate the data, the SQL query, below the grid, is updated.
Test Data
To allow us to develop and test the grid, we create some test data in the MySQL database. I use the same schema and and data from an earlier posting. Below is the SQL statement to create the table:
create table if not exists p0020_shirt (Region varchar(8), Category varchar(8), Shirt_Style varchar(8), ShipDate date, Units integer, Price decimal(4,2), Cost decimal(4,2));
We add data into the table using a series of insert
statements, like the following:
insert into p0020_shirt values ('East','Boys','Tee',date('2005-01-01'),11,5.25,4.66); insert into p0020_shirt values ('East','Boys','Golf',date('2005-01-01'),12,5.26,4.57); insert into p0020_shirt values ('East','Boys','Polo',date('2005-01-01'),13,5.27,5.01); insert into p0020_shirt values ('East','Girls','Tee',date('2005-01-01'),14,5.28,5.01); …
We filter and paginate our data in one select
statement using the where
, and limit
and offset
clauses:
select * from [table reference] [filter] limit [number of rows] offset [position]
The filter is just a where
clause, generated when the user selects a column and value to filter the rows.
The filter controls are implemented using drop down lists, and to populate them, we fetch all unique values for each string column using the distinct
option in a select
statement, such as: select distinct [column name] from [table reference] order by 1 asc
.
When populating the drop down lists, we should also let the user reset the filter. To this end, we add a dummy value 'All' into the drop down list. Rather than having a special step in the PHP code when it generates the drop down lists, we can use union
to combine the results of two select
statements into one result set, then use a loop to populate the drop down list:
select 'All'
union
select distinct [column name] from [table reference] order by 1 asc
For example, the statement above would generate a list like (All, East, North, South, West).
The pagination controls just modify the offset position by adding or subtracting a constant and the current offset. We can easily stop the user from paging before the first row by ensuring that the offset value is always 0 or more. To stop the user from paging beyond the last row, we use another query to count the number of rows a query would return: select count(*) from [table reference] [filter]
. (In the PHP code, we also pad the table with empty rows if there are fewer rows in the dataset than the standard number of rows so that the height of the table doesn't change in the last page.)
PHP Data Grid Implementation
By moving as much of the logic into SQL statements, the PHP implementation of the data grid control is straightforward. If you view the PHP source code, you will see that the entry point, the main()
function, initializes variables using default values or from a previous form submission, connects to the database, then paints the drop down lists, data rows and pagination controls.
Enhance Data Grid UI with Javascript and jQuery
HTML forms should be viewable and usable without Javascript. If Javascript is enabled, then we can enhance the presentation and usability. With this in mind, the PHP code should just generate the non-Javascript form and create no event handlers, and if Javascript is enabled, the browser should use Javascript to add event handlers to HTML elements.
One library that makes it easier to manipulate the DOM in a browser is jQuery. For instance, the laborious DOM function calls such as document.getElementsById()
are replaced by simpler ones such as $()
.
In this data grid example, the Javascript functions to enhance the presentation or add interactivity can be found page's head
element.
Perhaps one odd feature is to hide the Submit button if Javascript is enabled. If Javascript is disabled, then the user must press the Submit button to submit the form. On the other hand, if Javascript is enabled, just changing the drop down list causes the onchange event handler to submit the form, enabled, so the Submit button is redundant.
Unexpected Problems
While developing this data grid control, I stumbled upon two unexpected problems.
The first problem is that the form can't reset select
elements (the filters) to the first option in the list. Resetting the select
elements just sets them to the default option, which is the option chosen when this form is generated in PHP.
The second problem was the Internet Explorer Submit Button Bug.
Improvements
One obvious improvement to this data grid is to reduce the number of database queries required just to update the data rows or filters. At the moment, there are 5 queries (one for each filter, one for the data rows, and one for counting the number of rows) each time the page is updated. While this is not a problem for a small dataset or a small number of users, it may quickly overload a server with a lot of users and more complex queries. This improvement can be implemented using AJAX to update each control without refreshing the entire page.
Another improvement is to auto-generate the filter lists based on rules of the number of unique values and the column types. For example, a filter for a text column could allow the user to enter a regular expression or to auto-complete as the user enters more letters. A filter for numeric values could automatically generate quartiles. Finally, a filter for dates could automatically contain months, quarters or years.
Conclusion
This article has presented a way to implement a simple data grid control using PHP and jQuery. SQL queries are used as much as possible to simplify the page generation logic in PHP. PHP is used to provide the business logic to query the database and generate a basic form. jQuery (and Javascript) are used to enhance the usability and presentation of the page. I'll keep exploring this approach to see if it would make it easier to develop and maintain.
2009-04-22
Make Columns Narrower with GreaseMonkey or Stylish
It is hard to read a lot of text in a wide browser window, so below are two GreaseMonkey scripts to make the text columns narrower. They both work by changing an element's CSS width to a percentage of the window width.
If the text is within a known element tag (e.g. p), try the following script, which iterates through the collection of elements and sets the elements CSS width.
for each (e in document.getElementsByTagName('p')) { e.style.width = '60%'; }
If all the text is all within a single containing element, such as the body element, then the script can be shortened to …
document.getElementsByTagName('body')[0].style.width = '60%';.
If you want to also centre the text in the window, just change move the left margin by adding e.style.marginLeft = '20%';
. marginLeft is the Javascript equivalent of CSS' margin-left property.
Later … I realised that since we're only changing CSS properties, it's a lot easier to use the Stylish add-in. Just add a style sheet like this:
body { margin-left : 20%; width : 60%; }
See also
- (28-Nov-2008) Theme a Site with GreaseMonkey and Stylish
2008-11-28
Theme a site with Greasemonkey and Stylish
Motivated by Gmail's Terminal theme, I hacked a similar theme for an internal Web site using Firefox's Greasemonkey and Stylish add-ins. My approach was to write some small Greasemonkey scripts to touch up different parts of all pages independently, then use Stylish to apply style definitions (the theme) from one CSS file. If you want to create another theme for this site, just create a new CSS file.
- First, I identified logical components of each web page, for example navigation bar, header, footers, forms and tables.
- Wrote a Greasemonkey script for each logical component that:
- Removed any physical formatting such as border or bgcolor.
- Labelled each component with an ID and / or a class name.
- When naming each script, prefixed each script name with the site name to make them easy to find in Greasemonkey's Manage User Scripts dialog.
- Configured Greasemonkey's Included and Excluded pages to call each script as required.
- Wrote a site-wide CSS file, using the IDs and class names that were previously defined.
- Added the CSS file to Stylish. The CSS file name is prefixed with the site and theme name.
Instant theme!
See Also
2008-08-27
What's the time?
14 quick ways to find the current time on your computer.
Cmd.exe has two built-in commands for the date and time. You have to add the /t option when calling these commands otherwise you are prompted to set the system time:
> date /t Wed 27/08/2008 > time /t 07:42 PM
GnuWin's date command prints the date, time and time zone:
> date Wed Aug 27 19:43:23 AUS Eastern Standard Time 2008
You can use the POSIX module in Perl to get the current date and time:
> perl -e "use POSIX; print asctime(localtime());" Wed Aug 27 19:44:21 2008
Python has a time module similar to Perl's:
> python -c "import time; print time.asctime()" Wed Aug 27 19:48:07 2008
PHP's time and date functions return an array, which you can dump using the print_r()
function:
> php -r "print_r(get_date());" Array ( [seconds] => 49 [minutes] => 34 [hours] => 14 [mday] => 30 [wday] => 6 [mon] => 8 [year] => 2008 [yday] => 242 [weekday] => Saturday [month] => August [0] => 1220070889 )
Ruby has a Time class:
> ruby -e "print Time.now" Wed Aug 27 19:45:32 +1000 2008
PowerShell has a get-date cmdlet:
> get-date Wednesday, 27 August 2008 7:50:13 PM
Or use the .Net System.DateTime.Now property in PowerShell:
> [System.DateTime]::Now Thursday, 28 August 2008 9:53:21 AM
Firefox can tell you the time using the Javascript Date() object. Enter the following statement in your browser's address bar:
javascript:Date() Wed Aug 27 2008 20:11:27 GMT+1000 (AUS Eastern Standard Time)
MSIE6 has a similar object but the output is different from Firefox's:
javascript:Date() Thu Aug 28 10:06:59 2008
Groovy (and Java) has a java.util.Date object which defaults to the current time:
new java.util.Date() Result: Thu Aug 28 09:58:45 EST 2008
2008-01-27
Javascript Input Focus Annoyance
Many web sites have forms that move the keyboard cursor into an input field. For example, view your favourite search engine page and note that the cursor is in the search field. Enter a query, press RETURN, wait for the results, move the cursor out of the search field by hitting the TAB key, click on a link (don't open a new tab or window) then return to the search page. You should find that the cursor is back in the search field. If you usually just use the keyboard instead of the mouse, you have to hit TAB to move the cursor out of that field before you can scroll the page up or down. Some web sites have a search field in every page, so it is even more annoying to hit the TAB key in every page. (Why do I even persist in using these web sites?)
Web pages that display this behaviour usually use Javascript's focus()
function. If you view the source code of such pages, you should see something like this: document. … .focus()
.
There's several solutions to this annoyance in Firefox.
The most general method is to disable Javascript by unchecking the Tools / Options / Content / Enable Javascript option, rather like using a sledgehammer to kill an ant.
If you just want to stop web pages from using the focus()
method for the text fields (the INPUT
tag), you can modify Firefox's security policy by editing your user.js preferences file:
user_pref("capability.policy.default.HTMLInputElement.focus", "noAccess");
Note: The policy named default is applied for all sites.
If you only want to stop certain sites from using the focus()
method, create a new policy and specify when it should be applied, for instance:
user_pref("capability.policy.policynames", "noinputfocus"); user_pref("capability.policy.noinputfocus.sites", "<site list>"); user_pref("capability.policy.noinputfocus.HTMLInputElement.focus", "noAccess");
In this example, the noinputfocus policy is applied to the list of sites specified in noinputfocus.sites property.
28-Jan-2008: You have to restart Firefox before your policy is applied.
2006-03-12
Software: Javascript Text to HTML Update 1
After using the text to HTML convertor for a bit, I found it useful and easy to add the following features:
- Convert ampersand (&) into an HTML entity.
- Convert whitespace to .
- Add <pre> tags at the start and end of the output.
2006-03-06
Software: Javascript Text to HTML Convertor
When entering bugs in our local bug reporting system, I forget to enter reserved HTML characters such as < (less-than) and > (greater-than) as character codes < and >. When I submit my bugs, our server swallows up these reserved characters and my bug reports look rather silly (mind you, a lot of bugs are silly to start with). A similar problem happens when I write a blog with code fragments containing these characters or if I want my source code to be indented nicely. So, here's a simple Javascript Web page to handle these conversions.
The nice bit of code (IMHO) is using string.slice()
in the regular expression to replace tabs with a user-specified number of space characters: sIn.replace(/\t/g, ' '.slice(0,iTabSpace)).
2005-09-22
Software: Simple Javascript Regular Expression Search and Replace
Here's a simple regular expression search and replace in Javascript (for JScript, replace alert with WScript.Echo). I wrote it as a test for another script to modify a configuration file.
var s1 = "Hello World" var s2 = s1.replace(/Hello/, "Goodbye") alert(s1 + "," + s2) var s3 = s1.replace(/(Hello)/, "$1 Googly") alert(s1 + "," + s3)
If you run this script in a Web page, you should see the first alert dialog containing "Hello World,Goodbye World" and a second alert dialog containing "Hello World,Hello Googly World".
In this example, the parentheses (()) enclose a match pattern and the dollar ($) symbol represents the matched string (i.e. $1 is the first matched string, $2 is the second matched string, etc.).
2005-09-02
JScript To Launch Applications
Here's a quickie JScript program to launch a set of applications in Windows. I wrote it because I didn't want to always start these applications when I logged in to my workstation (which is what happens to programs in the Windows Startup folder). Save the text in a *.js file in your desktop, edit the list of applications, then click on the icon to run it.
var apps = new Array() apps[0] = '"C:\\Program Files\\Bozinis\\2xExplorer\\2xExplorer.exe"' apps[1] = '"C:\\Program Files\\Mozilla Firefox\\firefox.exe"' apps[2] = '"C:\\Program Files\\Microsoft Office\\Office\\EXCEL.EXE"' apps[3] = '"C:\\Program Files\\Microsoft Office\\Office\\OUTLOOK.EXE"' function runApps() { var wshell = WScript.CreateObject("WScript.shell") for (var i = 0; i < apps.length; ++i) { var appPath = apps[i] wshell.Run(appPath, 1, false) // Don't wait for command to finish } wshell = null } runApps()
JScript and Windows notes
If your application file paths have white spaces, you need to delimit them by double quotes so that the Windows shell can find them. The outer-most single quotes tell JScript the start and end of a string. Backslashes in Windows paths need to be escaped by another backslash.
2005-07-18
JScript in IE6 to read database
Inspired by this Kuro5hin article, I hacked up a slightly nicer JScript implementation to read database tables and generate HTML tables in a browser using DOM functions such as insertRow()
and insertCell()
.
Try it out
If you want to try it out, first create an Excel workbook called Test.xls with a page named DataTest. In DataTest, create one column with a heading StringValue and another column with a heading NumericValue. Enter some test data in those columns, then save the file.
Next, copy the HTML code at the end of this article, change the DSN path appropriately and save it in a file.
Finally, load the HTML file in IE6. When you select the Test button, the data in your workbook should be displayed in the browser.
Notes
If you start Excel and the user interface doesn't initialize properly, the cause is usually the Excel automation server not exiting. Just start Windows Task Manager, and kill the errant Excel.exe
process in the Processes tab.
I chose Excel instead of Access as the database because it is easier to test simple programs without having to create a table design.
Sample JScript and HTML to read database
<html> <head> <title>DBTest for IE6</title> <script type="text/javascript"> function readDb(tableId) { var conn = new ActiveXObject("ADODB.Connection") var dsn = "Provider=Microsoft.Jet.OLEDB.4.0;" dsn += "Data Source=C:\\CVS_STUFF\\HTML\\Database\\Test.xls;" dsn += 'Extended Properties="Excel 8.0;HDR=Yes;IMEX=1"' conn.Open(dsn) var rs = new ActiveXObject("ADODB.Recordset") rs.Open("[DataTest$]", conn) var outputTable = document.getElementById(tableId) if (!outputTable) { alert("Cannot find " + tableId) return } if (!rs.bof) { var rowIndex = 1 rs.MoveFirst() while (!rs.eof) { var row = outputTable.insertRow(rowIndex) var c1 = row.insertCell(0) var data1 = rs.Fields('StringValue').value var text1 = document.createTextNode(data1) c1.appendChild(text1) var c2 = row.insertCell(1) var data2 = rs.Fields('NumericValue').value var text2 = document.createTextNode(data2) c2.appendChild(text2) ++rowIndex rs.MoveNext() } } rs.Close() conn.Close() } </script> </head> <body> <h1>DBTest for IE6</h1> <form action="javascript:readDb('testOut')"> <input type="submit" value="Test"/> </form> <table id="testOut"> <tr><th>StringValue</th><th>NumericValue</th></tr> </table> </body> </html>
2005-07-06
Software: HTML behaviours
Tags in DHTML pages quickly get cluttered with numerous on-some-event="fn(id)" attributes, making it nightmarish to maintain hand-coded pages. Instead bind elements and behaviours (events and functions) separately from tags. Microsoft introduced behaviours for Internet Explorer 5.5 for special effects in a page but their implementation uses non-standard additions (unsurprisingly) to CSS. Ben Nolan wrote a browser independent behaviour library and Lambda-the-ultimate forum has a discussion. Using CSS selectors to specify elements allows multiple HTML elements to have the same behaviour and multiple behaviours to be mapped to one HTML element (as long as the events don't overlap). Très cool indeed!