Otaqui.Com

Pete Otaqui’s blog about web development and everything else

Archive for the ‘webdev’ tag

Simple Javascript Validator Library – Validator.js

leave a comment

I had a need to do some data validation in javascript, and all the libraries I looked at seemed quite opinionated about *what* you were going to validate – i.e. form data – let alone the increase in server-side javascript in the last couple of years. My data wasn’t directly tied to a form, so it didn’t quite seem worthwhile trying to shoe horn my needs into what the libraries expected, and I could also see a need for a validation library that could be adapted for Node.

Enter Validator.js.

Validator’s only dependency is on underscore.js from Document Cloud.

Validator has two usage forms: the first for very quick and simple one-off cases:

// Simple use:
var result
result = Validator.isEmail('not_an_email');
console.log(result); // false
result = Validator.isEmail('joe@example.com');
console.log(result); // true

I found this on its own quite a lot more flexible than most of the form-driven libraries out there. However, I also wanted to be able to create more complex sets of validations to run on a piece of data. For that case, you create an instance of Validator and use it’s add() method:

var result,
    myValidator

myValidator = new Validator();

myValidator.add('unique');
myValidator.add('minLength', 6);

result = myValidator.validate( [1, 2, 3, 4, 5, 6, 6] );
console.log(result); // false, the array is long enough but contains non-unique members

This got me a fair bit closer to what I wanted, but you don’t know which part failed, so it’s harder to give reasonable feedback. I added a set of error messages to validator instances which gets populated after a call to validate():

var result,
    myValidator

myValidator = new Validator();

myValidator.add('unique');
myValidator.add('minLength', 6);
myValidator.add('maxLength', 8);

result = myValidator.validate( [1, 2, 3, 4, 5, 6, 6, 8, 9, 10] );
console.log(result); // false, the array is long enough but contains non-unique members
console.log(myValidator.errors);
/*
myValidator.errors == [
    'The list must be made up of unique items',
    'The list is too long'
]
*/

Again, this is pretty good but even though Validator supports adding messages in any language you want and falling back (by default) to English (see the source code), default error messages still aren’t always what you need. I also added the ability to set a custom error message per “validation”.

var result,
    myValidator

myValidator = new Validator();

myValidator.add('unique').message('You are repeating yourself');
myValidator.add('minLength', 6).message('Too tiny!');
myValidator.add('maxLength', 8).message('Too bloated!');

result = myValidator.validate( [1, 2, 3, 4, 5, 6, 6, 8, 9, 10] );
console.log(result); // false, the array is long enough but contains non-unique members
console.log(myValidator.errors);
/*
myValidator.errors == [
    'You are repeating yourself',
    'Too bloated!'
]
*/

You can also chain calls to add() and message():

var result,
    myValidator

myValidator = new Validator();

myValidator.add('unique').message('You are repeating yourself')
    .add('minLength', 6).message('Too tiny!')
    .add('maxLength', 8).message('Too bloated!');

I’ve added some code which should make it easy to use this as a CommonJS AMD javascript module. In it’s default form you can just include it with a script tag.

If you’re interested in developing Validator itself, the project is tested with Jasmine and documented with JSDoc. Both of these can be run with Rake, and the easiest way to get setup is to use Bundler. Once you’ve got the dependencies you get three rake tasks:

# Start the jasmine server, and open http://localhost:8888/ to run the test suite:
$ rake jasmine
# Start the jasmine server and also run a browser through the tests automatically:
$ rake jasmine:ci
# Generate the docs
$ rake jsdoc

If you fork the project and add any more validations, please also add tests and docs.

Written by pete

August 14th, 2011 at 1:58 pm

Posted in Professional

Tagged with ,

Building Conway’s Game of Life in Javascript

leave a comment

As part of an interesting exercise at work, I built an implementation of Conway’s Game Of Life in Javascript. If you haven’t come across the Game Of Life, it’s really quite interesting and worth looking at. My colleagues also made variations, including canvas-based and Web GL 3 dimensional (there was even discussion about n-dimensional, with sliders to view the 4th, 5th and further dimensions). My particular take was to make the game space “infinite” rather than a fixed grid.

It’s not really infinite of course, I haven’t made any attempt to have a position greater than Number.MAX_VALUE. The real point is that it is possible to have a huge playing area, and only the living & possibly-living-next-round cells are taken into account.

I avoided using any ready-made frameworks, in part so that it could be transported to the server-side on top of something like NodeJS – I was imagining a multi-player game where each user could “paint” cells onto the canvas, and maybe even that next-generation cells would take an identifier from their parents, letting people “fight”. I haven’t really got the time for that at the moment, but it seemed a nice idea.

Written by pete

August 2nd, 2011 at 8:00 pm

Posted in Professional

Tagged with ,

RTL Input text with large text-indent value “magically scrolls” in Opera

leave a comment

This is a pretty weird browser bug.

Opera RTL Scrolly Text Indent Bug.

If your content is RTL and you are using the large text-indent CSS property on an input tag (so that you can use a background image, while keeping the text invisible to most users but still available to screen readers) you get a couple of odd behaviours in Opera:

  1. The text is not indented. Well ok, that’s at least a “normal” kind of bug.
  2. If you right-click on the button, and leave the menu open for a few seconds, the text magically starts scrolling out of the way.

I’ve submitted a bug report to Opera. I’d be interested if anyone else is seeing the same behaviour, or any related RTL weirdness.

Written by pete

January 26th, 2011 at 12:32 am

Posted in Professional

Tagged with

Started work on jQuery UI Modal widget

leave a comment

I’ve started working a jQuery UI Modal widget, for use in a project built on top of the widget library.

We have very high accessibility standards, and the current “{modal:true}” option for the dialog widget unfortunately wasn’t as good as we needed. Seeing that the team had identified the need for a standalone Modal widget, the team thought we could try and get the ball rolling.

You can see the work in progress here in the modal widget in my fork of jquery ui.

I’ve also been having a discssion about the modal widget with Scott Gonzalez of the jQuery UI team.

Written by pete

October 13th, 2010 at 10:26 pm

Posted in Professional

Tagged with ,

CSSP: Loading CSS with Javascript – and getting an onload callback.

4 comments

It seems fairly straightforward to require CSS with Javascript. The most obvious method that I thought of was creating a <link> tag and appending it to the head of the document. An alternative would be to load the text of the css file with an ajax XHR call, and then inject that into a <style> tag.

These are both fine for most cases, but what about a situation where you have a hard dependency on the css for the javascript to work correctly? You could take a best-guess at a wait time for the CSS to load, or even set the XHR to be synchronous – however both of these are very poor for both actual and perceived performance of your page (and the former may simply fail).

When might this be the case? Let’s say you have some asynchronously loaded javascript that is intended to create a widget on the page, something like this (which assumes you are using jQuery as your dom library):


function moveLargePanels() {
    // make a panel container for large panels
    $('<div id="largePanelContainer"></div>')
        .appendTo('body');
    $('.panel').each( function(i, panel) {
        if ( panel.outerWidth() > 300 ) {
            panel.appendTo('#largePanelContainer');
        }
    }
}

And some corresponding CSS:

.panel {
    border:1px solid #000;
    padding: 20px;
}

The idea here is that, since there is some interaction between the logic in the javascript (a test for the “outerWidth”) and the styling in the CSS (setting the padding) that the javascript can only work correctly once the CSS has been loaded and applied.

This should be fine right? Start the javascript and the css loading, and have events attached to the load of each letting you know when everything is ready and it’s safe to fire “moveLargePanels()”. Wrong, or at least tricky, and essentially impossible if the CSS is loaded from a different domain to the hosting webpage.

You can get James Burke’s excellent description of this problem here:
http://requirejs.org/docs/faq-advanced.html#css
And a first pass at solving this (in some browsers) here:
http://bugs.dojotoolkit.org/ticket/5402

Burke mentions a using a “well known” style rule to test whether the style is loaded. I suggest a standard pattern for the rule, and also a mechanism for dynamically setting it.

Enter CSSP

You may have heard of JsonP – a way of serving dynamically generated JSON which is padded with a method call (the method name is supplied in the query string of the URL), which allows for cross domain loading of javascript. The idea behind CSSP is similar – it defines a pattern for loading css cross domain. Instead of wrapping in a callback though, we can use the URL query string mechanism to supply the special “test rule” that we use.

Dynamic Rule Pattern

Given this url:

http://someserver.com/stylefile.css?cssp=123456

.panel { ... }
.largePanelsContainer { .. }

/* and the special rule: */
cssp { zIndex:123456; }

So, in whatever loader we want to build, we can add something like this (n.b. this isn’t tested code):

var cssp_counter = 0;
function loadCss(url, callback, className, zIndex) {
    // create a counter for special class names, so they are unique
    className = className || 'cssp' + (cssp_counter++);
    zIndex = zIndex || 123456;
    url = url + '?' + className + '=' + zIndex;
    $('<link>')
        .attr({
            rel: "stylesheet",
            type: "text/css",
            href: url
        .appendTo('head');
    // append a dummy div to the body for the test
    var div = $('<div></div>')
        .addClass(className)
        .appendTo('body');
    // now poll for the z-index value:
    var cssp_interval = setInterval( function() {
        // if the zIndex is applied, we know the css has loaded
        if ( div.css('zIndex') == zIndex ) {
            div.remove();
            // callback:
            callback();
            clearInterval( cssp_interval );
        }
    }, 100);

}

The code above to do the loading and fire a callback is very naive. It would be much better to have an event that can have listeners added, and to have some tests and some failure management like a maximum timeout.

Default Rule Pattern

This obviously presupposes that the CSS is dynamically generated to some degree, even just by adding the special rule to an otherwise static file. I think that an alternative to the performance-conscious would be a “default” special rule, based on the css filename. This needs some thought, and could well be tied to a build-step in your deployment process (you do have one, right?). The pattern comes in two parts:

  • There is a standard zIndex that is always used.
  • The filename includes the “special class name” that is used within.

For example:

Given the file: styles.fhddgso9j.css

.someclass { ... }
.otherclass { ... }

/* and the special rule */
.fhddgso9j { z-index: 123456; }

The javascript to go alone with this might look something like:

var cssp_counter = 0;
function loadCss(url, callback) {
    // create a counter for special class names, so they are unique
    className = getSpecialClassName(url);
    zIndex = 123456;
    $('<link>')
        .attr({
            rel: "stylesheet",
            type: "text/css",
            href: url
        .appendTo('head');
    // append a dummy div to the body for the test
    var div = $('<div></div>')
        .addClass(className)
        .appendTo('body');
    // now poll for the z-index value:
    var cssp_interval = setInterval( function() {
        // if the zIndex is applied, we know the css has loaded
        if ( div.css('zIndex') == zIndex ) {
            div.remove();
            // callback:
            callback();
            clearInterval( cssp_interval );
        }
    }, 100);
}
function getSpecialClassName(url) {
  // get just the filename, e.g. "styles.9ufosdfij.css"
  var filename = url.substring( url.lastIndexOf('/')+1, url.length);
  // split on the "." marks
  var parts = filename.split('.');
  // assume it will be the second-to-last part (since the last should be "css")
  var className = parts[ parts.length-2 ];
  return className;
}

As noted above, this naive, untested code.

Wrapping Up

Ideally I’d like any “css loader” to use actual browser events (or properties) where possible, and to fallback on this setup as a last resort.

If I get time I’ll implement this and put the code on github. Please do get in touch if you’d like to pair on this!

Written by pete

September 28th, 2010 at 10:16 pm

Posted in Professional

Tagged with , , ,