Monday, October 31, 2011

[js] Currying functions

The concept of currying a function is not inherent to Javascript but is easy to provide and useful. It allows you to preset the value of one (or more) of a function's argument list, so that when the function is called later it "remembers" what had been preset.

Consider the common scenario of building a record table, where each row contains an anchor for editing/selecting that row's record. Currying allows you, in effect, to bind a record to its anchor's onclick event:

rec = {'id':12,'name':'George'};
anchor = document.getElementById('some_anchor');
anchor.onclick = some_function.curry(rec);

function some_function(rec) {
  alert(rec.name);
}

A little trumped up for demonstration purposes, as in reality we'd be iterating through records and creating (not referencing) anchors, but the important part's the same. We can't point the anchor's onclick directly to some_function, because that function expects a rec argument which, of course, a fired onclick won't provide. So we invoke the target function's curry method to preset that argument for when it's called later (e.g. when the anchor is clicked).

Again, curry isn't native Javascript, but is part of any decent framework and otherwise easy to implement:

Function.prototype.curry = function() {
  var fn = this;
  var args = Array.prototype.slice.call(arguments);
  return function() {
    return fn.apply(fn, args.concat(Array.prototype.slice.call(arguments)));
  }
}

Technically what happens when you invoke a function's curry method is that you get a reference to a new function that wraps the original. When the new function is later invoked, the inner (original) function is called with the arguments that had been provided to curry, which are still in scope by virtue of the closure formed when the new function was created, plus any arguments now provided to the new function.

Sunday, October 30, 2011

[js] Forwarding arguments

If you want to call another function with all arguments supplied to this function, use the function's apply method:

pop:function() {
  this.onpop.apply(this, arguments);
  // stuff
}

[php] Calling parent's _construct()

To call the parent __construct() from an overridden constructor:

public function __construct() {
  $args = func_get_args();
  call_user_func_array(array(get_parent_class($this), '__construct'), $args);
  // do other stuff
}

Saturday, October 29, 2011

[js] IE input select() bug

Do a select() focus() on an input box with contents. Now click on another control (e.g. checkbox). The input box contents remain "selected" even though the focus is now on the other control.

To fix, I had to assign an onblur handler to the input box:

input.onblur = function() {
  var value = this.value;
  this.value = '';
  this.value = value;
}

Pretty stupid.

About

This is my repository of application development things. Nerd threat level is elevated.