JavaScript

These scripts are evolving mostly driven by what I need in BoilerPlate. Nevertheless, they can stand on their own feet and may be useful to others. So here they go.

[Important] Important
All of these scripts require the excellent Prototype.js library. Protoplus and Validator also need util.js from the script.aculo.us scripts.

Behavior

Behaviors unobtrusively wire structural (X)HTML markups with JavaScript functionality by way of CSS selectors. My version is heavily refactored from Ben Nolan's original. Apart from corrections it is fully backward compatible. The changes mostly affect the included document.getElementsBySelector by Simon Willison. Selectors now can contain

  • child selectors (">")
  • multiple class names ("input")
  • :first-child pseudo-class

Also, duplicate matches for the same element by a selector are now ignored.

Additional arguments to a behavior can be stuffed URL-encoded in the class attribute of the selected element in the form name:url-encoded value. For extraction there's the utility function Behavior.extractOptions(element, name1, ..., nameN).

StdExt

There's some functionality missing in the core JavaScript language. That much is obvious -- well, to me anyway. With this script I'm trying to fix this to some extend.

What's in there?

  • Array.prototype.some = function (f, obj)
  • Array.prototype.difference = function(minusArray, compareFunc)
  • Array.prototype.equals = function(other)
  • Array.flatten = function(array, excludeUndefined)
  • Array.prototype.flatten = function(excludeUndefined)
  • Array.prototype.moveElement = function(fromPos, toPos)
  • Array.prototype.pushUnlessNull = function(element)
  • Function.equality = function(a, b)
  • Function.identity = function(a, b)
  • Function.trueFunc = function()
  • Function.sequence = function()
  • Function.andCombiner = function(funcs)
  • Object.atPath = function(obj, path, separator)
  • Object.addDefaults = function(obj, defaults, allowUndefinedValue)
  • Object.equals = function(obj1, obj2)
  • String.prototype.startsWith = function(prefix)
  • String.prototype.endsWith = function(suffix)
  • String.prototype.withoutPrefix = function(prefix)
  • String.prototype.withoutSuffix = function(suffix)
  • String.prototype.strip = function()
  • String.prototype.format = function()
  • String.isBlank = function(s)
  • String.compare = function(s1, s2)
  • StdExt.inspect = function(object, showFunctions)

ProtoPlus

Following the spirit of Prototype.js this script adds still more. There are a couple of overlaps with code in Thomas Fuchs's dragdrop.js that I hope to resolve soon.

What's in there?

  • function $$(element, msgPrefix, expectedTagName)
  • Event.observe = function(element, name, observer, useCapture)
  • Event.stopObserving = function(element, name, observer, useCapture)
  • Event.getTargetElement = function(evt)
  • Element.getTextContent = function(element)
  • Element.getAbsolutePos = function(element)
  • Element._getAbsolutePos = function(element)
  • Element.getAncestorByTagName = function(element, tagName)
  • Element.getPositionInAncestorByTagName = function(element, tagName)
  • Element.hasClassName = function(element, className)
  • Element.toggleClassName = function(element, className, present)
  • Element.findFirstMatchingChild = function(parent, matchingFunc)
  • Element.findMatchingChildren = function(parent, matchingFunc)
  • Element.reparentChildren = function(fromParent, toParent, matchingFunc)
  • Form.Label.getFor: function(element)
  • Form.Label.getTextFor: function(element)
  • Form.Select.allValues: function(selectElement)
  • Form.Select.allSelectedValues: function(selectElement)
  • Form.Select.selectAll: function(selectElement)
  • Form.Select.deselectAll: function(selectElement)
  • Form.Select.setSelectedForAll: function(selectElement, selected)
  • Form.Select.selectAllOnSubmit: function(selectElement)
  • Form.Select.optionsAsArray: function(selectElement)
  • Form.Select.sort: function(selectElement, compareFunc)
  • Form.Select.moveSelectedOptions: function(fromSelect, toSelect)
  • Form.Select.removeOptions: function(selectElement, minusSelect)
  • Form.Select.setOptions: function(selectElement, options)
  • ProtoPlus.IndicatorShower

Validator

Yes, there are probably hundreds of client-side validators written in JavaScript. What makes this one worthwhile is that it aims at being as declarative as possible.

You, as the programmer, still need to write validation functions. But the wiring is mostly automatic, purely driven by the class attribute of form elements. Still, this does not confine validation to the value of single input elements; see validators.js for an example.

When a form does not validate, its submit buttons are disable and the offending input elements are marked with the (additional) class "invalid".

Also, the validator continuously checks forms for validity. This is quite possible with the speed of current computers.

ChangeMarker

If this is actually useful I really can't say yet. The idea is to give the user feedback about the changes they have applied to a form. This script keeps an eye on the form and when one of its input elements is changed, the element is marked with the (additional) class "changed".