Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Friday, August 27, 2010

Javascript: JQuery DatePicker, Chrome and MAXLENGTH

Having just spent 2 hours swearing violently at my computer, I thought I'd share this little bug tracking story...

I am writing a simple data entry page that contains a couple of date fields, for which I'm using the very nice JQuery UI datepickers.

I have used them all over the place with no problems at all, however on this page I was getting some weird behaviour when the submit button was clicked:

  1. If the date fields were empty, the form submitted fine.
  2. But if a date had been selected, when you clicked submit, the date picker for the first populated date field popped up and the form did not submit.

Some testing revealed this only happened in Chrome - my version of which is the v6 beta release.

An update to the JQuery UI did not fix the problem.

Some debugging code revealed that on submit, the datepicker fields were being focussed - so as far as the datepicker code was concerned, it was working correctly.

However, the object inspector in Chrome showed no unwanted event listeners that could be doing this.

Some more swearing, a minimal test case and a comparison with a working page later revealed the problem - the MAXLENGTH attribute had been set, in a copy/paste debacle, to 8 - clearly too short for a dd/mm/yyyy date.

So, presumably, Chrome allows you to set content longer than the MAXLENGTH from script, but then will not let you submit the form, instead focussing the offending field - it makes perfect sense when you think about it, really.

Firefox and IE both allow you to submit the form with the longer data - although you can make an argument for that making sense too. I don't know what the W3C say on this issue.

Wednesday, June 30, 2010

J2ME: Quickie release of "lightmeter" code

I don't seem to be ever getting around to doing this and now a Java developer with a Nokia has asked me for it, so here is the full source code to the phone EXIFy lightmeter.

Well, I say "full"; it's very simple! If you have seen Java before and have the J2ME SDK you should be able to do something with it.

I will try to do a more informative post on it soon. You will obviously need Java installed and also the J2ME 3.0 SDK.

Quickly, though: /_support contains the Javascript files I ported the EXIF reader from (see this post), /src/akme/mobile/util contains maths routines missing from the mobile edition (check the source for URLs and credits), /src/expinfo contains the hastily hacked together and very horrible code for the MIDlet itself, /src/rext/graphics contains a routine for generating thumbnails that seems to exist across many blog and forum posts, and /src/rext/simpleexif is the main codebase, containing the EXIF reader port and the code for moving around EV values.

I stopped developing the code as soon as it worked for the first time, so it is a fairly parlous state :o)

If you have found this post and are not a developer but just want to try the app, the Flickr group has more useful info.

Wednesday, March 3, 2010

J2ME: EXIF and lightmetering Part 1

I am a bit of a camera obsessive. I got into photography with a digital P&S, progressed to a DSLR, and then got into film. Since then, my camera collection has taken over several surfaces in the flat. I don't have that many, but then I don't have that many surfaces.

Most of the collection consists of old cameras; my theory is that if you want to take crisp "perfect" images, a DSLR is the way to go. This is a theory based mainly on laziness, but it works for me.

In general, the film cameras have been chosen for looks at least as much as quality. The Rolleiflex has both in spades, of course.

Most of the old cameras do not have a light meter, and many with the old selenium cell meters simply do not work any more.

I do own a couple of lightmeters, but I find they are a pain to use, and new ones are basically extremely expensive flash looking versions with exactly the same functionality.

What I have been doing it using the dSLR to take a preview shot, then transferring the settings over to whatever camera I am currently playing with. However, this becomes a bit tedious after a while, and also having, say, the Rolleiflex and the dSLR round my neck results in severe neck strain.

So, ideally, I want a very small camera than can take a preview shot with the ability to tell it the ISO and, usually, the aperture I want. I can then check the preview looks okay, and transfer the settings over with any modifications required. However, P&S cameras with these manual settings are not cheap and often have big limitations on the ISO and f/stop they allow you to set, so an alternative solution is to take the preview with whatever settings the camera wants, then allow me to easily convert them into ones I can use.

This is where my mobile comes in. It is extremely small, I always have it on me, and it has a camera with a full auto mode that takes JPEGs stuffed full with the EXIF data for the exposure. Perfect. Except that, on the phone, there is no way of actually viewing the EXIF.

However, the phone, a Sony Ericsson C903, has mobile Java, and I've seen some Java before, so I decided to give writing an app for it a shot.

It was an interesting exercise, and along the way I discovered several fun things. For example, mobile Java is one of the most frustratingly NON-device independent environments it's been my misfortune to use, the certification requirements are beyond absurd, and my phone has one of the most annoying bugs ever to have existed - when your app works perfectly and is extremely useful, having the phone randomly lose and/or corrupt the memory card it's sitting on is rather irritating.

The first bit of the code, which we have finally come to, is something that will read EXIF data out of JPEGs. I had a fish round for some libraries and found lots of great code that was either extremely big, extremely non J2ME compatible, or both.

Then I discovered this Javascript library, which I have to say, is brilliant. It's a use for client side Javascript and AJAX that simply would never have occurred to me in a million years. It is perfect for my uses because being entirely client side Javascript it uses very basic language features and is very small, ideal for conversion to Java by someone who hasn't used Java for about 8 years :o)

The code was written in the J2ME 3.0 SDK editor, which seems to have mangled the indentation for any other editor, but source code formatters are not exactly hard to find. The basic EXIF when compiled has not J2ME specific imports, so can be linked into any Java project; this is very handy for testing, obviously.

I made a couple of changes; I added X_FNumberAsString as a new data item for laziness, and created a Fraction class to help with maintaining the normal form of shutter speeds when manipulating them (a later post).

The ByteArrayWrapper class duplicates the required functionality from binaryajax.js.

EXIFReader contains the main functionality, and EXIFTags the tag names / descriptions and offsets, and also the list constants for various tags.

The classes live in the package rext.simpleexif.

It is pretty easy to use; you simply load in an image file into a byte[], then create the reader:

EXIFReader reader = new EXIFReader();
  
boolean ok = false;

try
{
 ok = reader.readEXIFFromByteArry(data);
}
catch(Exception e)
{
}

The reader object has three Hashtables for the various tags, EXIF, TIFF and GPS, and a Vector for debug messages called LOG.

Print out all EXIF tags to the console:

Enumeration exifk = reader.EXIF.keys();

while(exifk.hasMoreElements())
{
 String s = (String)exifk.nextElement();
 System.out.println(s + ": " + String.valueOf(reader.EXIF.get(s)));
}

You can get the code from the link below, including a small test console app that will print off the debug info then the EXIF data for a JPEG file.

Thursday, February 18, 2010

JS: Client side templating

I originally created this for an autocomplete widget I needed for a project ages ago; eventually it became too annoying to write all the code for the millions of conditions so I just used the YUI one instead, which is a pain in the arse to set up but works perfectly when you've done it.

Anyway, while looking around at existing solutions, they all seemed to have the problem that the markup was either fixed and styled with CSS, or generated in a callback. Neither of these solutions was ideal; the first results in a widget usable most of the time but very uncustomisable for more unusual uses, and the second is very designer unfriendly if you need to separate your coding and design teams.

So, my idea was to be able to write your HTML as normal, then mark an element as a template container. This template would contain databound variables. It would be removed from the DOM on page load, stored, then repeatedly generated for each item in a provided dataset.

Basically, it is inspired by the ASP.NET repeater control, .NET being my primary development environment.

I recently refactored the code to be more generally useful, and created a jQuery plugin wrapper that enables it to be used using the jQuery selectors and AJAX functionality.

It has uses beyond autocomplete, of course; any AJAXian updatable areas could use it.

Pros and cons are:

  • Keeps the template HTML in the same file as everything else; this can be a pro if the area is specific to a certain page or you are using a "master page" or "header / footer includes" style design, and a con if the template is to be used in several places. In that case you are probably better off with a server-side templating system to generate the HTML and dumping that in using the jQuery native functions.
  • Allows lightweight data transfer; instead of returning all of the HTML you can just return a JSON dataset.

The basic template code and the jQuery wrapper can be downloaded from the links below:

Usage:

First of all, you need a datasource, which will be an array of objects, for example:

[
 {id:1, name:'Alice'},
 {id:2, name:'Bob'},
 {id:3, name:'Carol'}
]

Then, you need to set up the template:

<ul id="testTemplate">
    <li class="@ItemClass">@Text</li>
</ul>

Note the SQL style variable placeholders. When the template is created with the ID of the <ul> element the <li> will be cleared. It is then reproduced for every item in the data array.

Note: EVERYTHING contained within the template element is treated as the data row, so you can have very complex repeating templates; as a very simple example you could have two list items for every data item should you want to. This is more useful for creating table based templates.

The actual call to populate the template looks like this:

// Call using local data and the simple unwrappered template code
var template = new HTemplates.Template('testTemplate');
template.populate(data);

// Call using the jQuery wrapper and an AJAX data source
$('#testTemplate').hTemplate();     
$('#testTemplate').hTemplate().populate(data);

You can download an example page plus an example JSON datasource from the links below:


Note: You will need the jQuery framework; it has been tested with 1.4. You will also need to change the script paths to match your setup.

The jQuery plugin is the first time I have looked at jQuery; I'm not 100% sure this is the best way to create a plugin; the hTemplate().populate() call looks odd to me. Also there is probably a better way of JSON parsing that is less fragile than my check-for-open-bracket-then-eval() method.