Array#compact Useful JavaScript Game Extension #31

###*
Returns a copy of the array without null and undefined values.
 
@name compact
@methodOf Array#
@type Array
@returns An array that contains only the non-null values.
###
Array::compact = ->
  this.select (element) ->
    element?

This array compact method is pretty useful. Prototype.js got it from Ruby and I got it from both. Now it’s a proud member of my CoffeeScript corelib.

Not much interesting behavior wise, but one thing to take note of is how short and sweet the code is thanks to using CoffeeScript.

31 down, 225 to go. Peace!

LiveEdit

You know those edit in place plugins for jQuery? Well I couldn’t find any that met these two criteria:

  1. Work on elements not yet in the DOM
  2. Didn’t post anything to the server

Now the first requirement probably makes a lot of sense to you, but I bet you’re wondering about the second one. In these crazy mixed up times with rich HTML5 apps, I don’t want to post to the server often. Maybe I’m using local storage, or perhaps I just want to send a big heap of JSON now and again, but I definitely don’t want to post every time anyone changes the value of an editable field.

So after examining all the terrible options (classic first step when choosing jQuery plugins) I decided to throw my own terrible option into the mix.

(($) ->
  $.fn.liveEdit = () ->
    this.live 'dblclick', () ->
      $this = $(this)
 
      return if $this.is("input")
 
      textInput = $("<input/>",
        class: $this.attr("class")
        "data-origType": this.tagName
        id: if id = $this.attr("id") then id else null
        type: "text"
        value: $.trim($this.text())
      )
 
      $this.replaceWith textInput
 
      textInput.focus().select()
 
    this.live 'blur keydown', (event) ->
      if event.type == "keydown"
        return unless event.which == 13 || event.which == 9
 
      $this = $(this)
 
      return if $this.data("removed")
      return unless $this.is("input")
 
      $this.attr("data-removed", true)
 
      $this.replaceWith $("<" + $this.data("origType") + " />",
        class: $this.attr("class")
        id: if id = $this.attr("id") then id else null
        text: $this.val()
      )
 
    return this
 
)(jQuery)

There are two tricks here. The first is that this plugin is really a macro that makes two calls to live. The second is that the editable content keeps it’s same id and class when switched out to a text field, so as long as your selector is not based on the element type it will work. There’s plenty of room for improvements, but this is a super simple first step that meets my needs. Enjoy!

jQuery Plugin: TakeClass

This comes up all the time, you have an element, and you want to select it to be the sole active element from among it’s siblings. With jQuery that is simple enough:

element.addClass("active").siblings().removeClass("active")

Though it is not as simple as it can be and it also fails to chain well. The solution is a super simple jQuery plugin:

(($) ->
  $.fn.takeClass = (name) ->
    this.addClass(name).siblings().removeClass(name)
 
    return this
)(jQuery)

Now you can really go nuts!

newElement.appendTo(layerSelect).takeClass("active").find(".name").mousedown()

Optimizing JSDoc Toolkit for Large JS Files

Recently I was running into a problem with JSDock Toolkit where it would throw an error saying js: exception from uncaught JavaScript throw: java.lang.OutOfMemoryError: Java heap space.

The solution was to add the -s flag so that it would not try and generate a large, marked-up source file for viewing with the docs.

java -jar jsdoc-toolkit/jsrun.jar jsdoc-toolkit/app/run.js gamelib.js -d=docs -n -s

I also added the -n flag to prevent it from documenting methods that didn’t have comments, such as minified jQuery or Box2d, though this was irrelevant in preventing the js: exception from uncaught JavaScript throw: java.lang.OutOfMemoryError: Java heap space error.

Array#extremes Useful JavaScript Game Extension #30

###*
 * Returns an object containing the extremes of this array.
 * 
 * @param {Function} [fn] An optional funtion used to evaluate 
 * each element to calculate its value for determining extremes.
 * @returns {min: minElement, max: maxElement}
 * @type Object
### 
Array::extremes = (fn) ->
  fn ||= (n) -> n
 
  min = max = undefined
  minResult = maxResult = undefined
 
  this.each (object) ->
    result = fn(object)
 
    if min?
      if result < minResult
        min = object
        minResult = result
    else
      min = object
      minResult = result
 
    if max?
      if result > maxResult
        max = object
        maxResult = result
    else
      max = object
      maxResult = result
 
  min: min
  max: max

Usage:

[-1, 3, 0].extremes() # => {min: -1, max: 3}

test "#extremes", ->
  array = [-7, 1, 11, 94]
 
  extremes = array.extremes()
 
  equals extremes.min, -7, "Min is -7"
  equals extremes.max, 94, "Max is 94"
 
  extremes = array.extremes (value) ->
    value.mod 11
 
  equals extremes.min, 11
  equals extremes.max, 94

Array#wrap Useful JavaScript Game Extension #29

/**
 * Pretend the array is a circle and grab a new array containing length elements. 
 * If length is not given return the element at start, again assuming the array 
 * is a circle.
 *
 * @param {Number} start The index to start wrapping at, or the index of the 
 * sole element to return if no length is given.
 * @param {Number} [length] Optional length determines how long result 
 * array should be.
 * @returns The element at start mod array.length, or an array of length elements, 
 * starting from start and wrapping.
 * @type Object or Array
 */
Array.prototype.wrap = function(start, length) {
  if(length != null) {
    var end = start + length;
    var result = [];
 
    for(var i = start; i < end; i++) {
      result.push(this[i.mod(this.length)]);
    }
 
    return result;
  } else {
    return this[start.mod(this.length)];
  }
};

Simple use:

[1, 2, 3].wrap(-1) => 3

[1, 2, 3].wrap(6) => 1

Or get fancy and tile your kitchen:

["w", "o", "o", "o"].wrap(0, 16) => ["w", "o", "o", "o", "w", "o", "o", "o", "w", "o", "o", "o", "w", "o", "o", "o"]

Array#clear Useful JavaScript Game Extension #28

Here’s a useful little method that empties out an array. Sure you could type myArray.length = 0; but that is kind of weird. For some reason myArray.clear() just makes more sense to me.

/**
* Empties the array of it's contents. It is modified in place.
*
* @type Array
* @returns this, now emptied.
*/
Array.prototype.clear = function() {
  this.length = 0;
  return this;
};

The series continues…

Capistrano Rails: A group writable tmp directory

Maybe you’ve run into [out :: ...] rm: cannot remove `/…/releases/20110221192810/tmp/restart.txt’: Permission denied

I did. The reason was because we were deploying with multiple users and when the tmp directory was being created it was not set to group writable.

Fortunately it is an easy fix, just add this into your cap deploy script:

after :deploy do
  run "chmod -R g+w #{release_path}/tmp"
end