Christian Heilmann

You are currently browsing the archives for the General category.

Archive for the ‘General’ Category

Scripting Enabled is what keeps me busy

Thursday, June 26th, 2008

I am very happy to announce that I am organizing my first big event. After years of fighting the good fight and getting people to embrace accessibility I was ready to give up on it. Instead I took a new angle on it and used APIs to create alternative interfaces to systems that just will not get more accessible any time soon.

Readers of this blog will have seen the outcome of these, and last weekend at mashed08 I showed another hack and explained the idea of it. I also gauged if there was any interest by the assembled hackers in an event like this and got some good response.

Even better was that I won a prize – some financial support to get an “accessibility hack day” on the road.

So here goes, check out Scripting Enabled

Scripting Enabled is a conference and hack day in London, England in September 2008.

The aim of the conference is to break down the barriers between disabled users and the social web as much as giving ethical hackers real world issues to solve. We talked about improving the accessibility of the web for a long time – let’s not wait, let’s make it happen.

Right now I am still looking for, well, everything. I have some money, I need a location and other speakers. I got a lot of ideas, though.

Check out the site, the calls for participation and if you want to help, please contact me!

Big companies are like marching bands

Friday, June 20th, 2008

I just read another amazing novel by Douglas Coupland on my 5 hour flight to Ankara called “Eleanor Rigby”. This is a quote I really enjoyed:


Jeremy asked if I liked my job.
“I think big companies are like marching bands. You know the big secret about marching bands, don’t you?”
“No, what is it?”
“Even if half the band is playing random notes, it still sounds kind of like music. The concealment of failure is built right into them. It’s like the piano – as long as you play only the black keys, not the white ones, it’ll sound okay, but on the other hand it’ll never sound like real music either.

Now this sounds negative, but I also like the idea that big companies can have failure without totally vanishing. That’s where research departments and incubators come in.

How to stop event delegation(obvious fact #12132)

Monday, June 9th, 2008

This was a question I got in the office today and there is no shame in asking it:

I am using Event Delegation on one of my products and I need to stop the main handler on the body from firing when I click a certain button. How do I do that?

The answer is of course to use stopPropagation() or cancelBubble(), both nicely wrapped in YAHOO.util.Event.stopPropagation():

HTML:

JavaScript:

YAHOO.util.Event.onContentReady('buttons',function(){
YAHOO.util.Event.on(document.body,'click',function(e){
var t = YAHOO.util.Event.getTarget(e);
snitch('

It was the ' + t + ' that was clicked

'); }); YAHOO.util.Event.on('tease','click',function(e){ snitch('

that was the first button

'); YAHOO.util.Event.stopPropagation(e); }); YAHOO.util.Event.on('tease2','click',function(e){ snitch('

that was the second button

'); }); function snitch(msg){ document.getElementById('littlesnitch').innerHTML += msg; } });

Try it out here: Overriding Event Delegation with stopPropagation

[tags]events,javascript,eventdelegation,webdevtrick[/tags]

@media2008 report live on YDN

Friday, May 30th, 2008

It is 1.14am after the first day of @media2008 and I just finished my report over on the YDN blog:

See you there tomorrow morning for day two, I am off to bed.

Providing script configuration in-line and programatically

Friday, May 23rd, 2008

One of the things I’ve been quite consistent and pushy about when writing code is to separate out all the things that should be customizable into an own configuration object.

A normal script I write these days would look like this:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
 
  };
  // ... more methods and other code ...
 
  // make init a public method
  return {
    init:init
  };
}();
module.init();

The benefits should be quite obvious:

  • Implementers don’t need to hunt through the whole script to find what they need to change
  • There’s a clear separation of “change what you need to change here” and “only touch this if you know what you are doing” – allowing more developers to use your code.
  • You show implementers in a single location where you overlap with other development layers, for example by defining IDs of HTML elements you use and CSS class names you apply to generated elements.
  • Having all the strings in one place makes for easier localisation and also speeds up the script (IE6 creates a string object for every string – even in conditions inside loops for example!)

I was quite OK with that until Ara Pehlivanian asked for an option to programatically override the configuration files, much like the YUI allows you to do with the YAHOO.util.Config utility. He is right of course, sometimes you’d want to change the config and re-initiate the script (the other way of course is to write a module with instantiation).

The easiest way to approach that is to make the config object public:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
 
  };
  // ... more methods and other code ...
 
  // make init and config a public method
  return {
    init:init,
    config:config
  };
}();

That way you can override the properties you need before you call init():

module.config.CSS.ids.container = 'header';
module.config.userID = 'alanwhite';  
module.init();

However, Ara thought it more convenient to be able to provide an object as a parameter to init() that overrides certain properties. You can do that by checking for this object, looping through its properties and recursively trying to find and match a property of the config object:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
    // check if the first argument is an object
    var a = arguments;
    if(isObj(a[ 0 ])){
      var cfg = a[ 0 ];
 
      // loop through arguments and alter the configuration
      for(var i in cfg){
        setConfig(config,i,cfg[i]);
      }
    }
  };
 
  function setConfig(o,p,v){
    // loop through all the properties of he object
    for(var i in o){
      // when the value is an object call this function recursively
      if(isObj(o[i])){
        setConfig(o[i],p,v);
 
      // otherwise compare properties and set their value accordingly
      } else {
        if(i === p){o[p] = v;};
      }
    }
  };
 
  // tests if a parameter is an object (and not an array)
  function isObj(o){
    return (typeof o === 'object' && typeof o.splice !== 'function');
  }
  // ... more methods and other code ...
  // make init a public method
  return {
    init:init
  };
}();
module.init({
  container:'header',
  'timeout':1000
});

This works swimmingly when all the configuration properties are unique. It fails though when a property in a nested object has the same name as another one on a higher level. In order to allow for this, we can offer the option to send a string with the path to the property as the property name. Then it gets messy as we need to eval() that string and make sure we return the value in the right format. All in all it could look like this:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
    if(isObj(arguments[ 0 ])){
      var cfg = arguments[ 0 ];
      for(var i in cfg){
        if(i.indexOf('.')!== -1){
          var str = '["' + i.replace(/\./g,'"]["') + '"]';
          var val = getValue(cfg[i]);
          eval('config' + str + '=' + val);
        } else {
          setConfig(config,i,cfg[i]);
        }
      }
    }
  };
  function setConfig(o,p,v){
    for(var i in o){
      if(isObj(o[i])){
        setConfig(o[i],p,v);
      } else {
        if(i === p){o[p] = v;};
      }
    }
  };
  function isObj(o){
    return (typeof o === 'object' && typeof o.splice !== 'function');
  };
  function getValue(v){
    switch(typeof v){
      case 'string':
        return "'" + v + "'";
      break;
      case 'number':
        return v;
      break;
      case 'object':
        if(typeof v.splice === 'function'){
          return '[' + v + ']';
        } else {
          return '{' + v + '}';
        }
      break;
      case NaN:
      break;
    };
  };
 
  // ... more methods and other code ...
  // make init a public method
  return {
    init:init
  };
}();
module.init({
  'container':'header',
  'CSS.classes.active':'now',
  'timeout':1000
});

In order to make that readable, let’s encapsulate all the configuration alteration code in an own module:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
    console.log(config);
  };
 
  // ... more methods and other code ...
 
  // Configuration changes 
  var changeConfig = function(){
    function set(o){
      var reg = /\./g;
      if(isObj(o)){
        for(var i in o){
          if(i.indexOf('.')!== -1){
            var str = '["' + i.replace(reg,'"]["') + '"]';
            var val = getValue(o[i]);
            eval('config' + str + '=' + val);
          } else {
            findProperty(config,i,o[i]);
          }
        }
      }
    };
    function findProperty(o,p,v){
      for(var i in o){
        if(isObj(o[i])){
          findProperty(o[i],p,v);
        } else {
          if(i === p){o[p] = v;};
        }
      }
    };
    function isObj(o){
      return (typeof o === 'object' && typeof o.splice !== 'function');
    };
    function getValue(v){
      switch(typeof v){
        case 'string': return "'"+v+"'"; break;
        case 'number': return v; break;
        case 'object':
          if(typeof v.splice === 'function'){
            return '['+v+']';
          } else {
            return '{'+v+'}';
          }
        break;
        case NaN: break;
      };
    };
    return{set:set};
  }();
  // make init a public method
  return {
    init:init
  };
}();
module.init({
    'container':'header',
    'CSS.classes.active':'now',
    'timeout':1000
});

And that is one way to provide a configuration object and make it possible to change it programatically in the init() method. Can you think of a better one?