text:
/*  Prototype JavaScript framework, version 1.4.0_rc3
 *  (c) 2005 Sam Stephenson <sam@conio.net>
 *
 *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
 *  against the source tree, available from the Prototype darcs repository.
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *
 *  For details, see the Prototype web site: http://prototype.conio.net/
 *
/*--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.4.0_rc3',
  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',

  emptyFunction: function() {},
  K: function(x) {return x}
}

var Class = {
  create: function() {
  	return function() {
  		if(this.destroy) Class.registerForDestruction(this);
      if(this.initialize) this.initialize.apply(this, arguments);
    }
  },

  extend: function(baseClassName) {
  	constructor = function() {
  		var i;

			/*
			var tmp = this.initialize;
			this.initialize = window[baseClassName].initialize;
  		window[baseClassName].apply(this, arguments);
  		this.initialize = tmp;
  		*/
  		this[baseClassName] = {}
  		for(i in window[baseClassName].prototype) {
  			if(!this[i]) this[i] = window[baseClassName].prototype[i];
  			if(typeof window[baseClassName].prototype[i] == 'function') {
  				this[baseClassName][i] = window[baseClassName].prototype[i].bind(this);
  			}
  		}

  		if(window[baseClassName].getInheritedStuff) {
  			window[baseClassName].getInheritedStuff.apply(this);
  		}

  		if(this.destroy) Class.registerForDestruction(this);
      if(this.initialize) this.initialize.apply(this, arguments);
  	}
  	constructor.getInheritedStuff = function() {
  		this[baseClassName] = {}
  		for(i in window[baseClassName].prototype) {
  			if(!this[i]) this[i] = window[baseClassName].prototype[i];
  			if(typeof window[baseClassName].prototype[i] == 'function') {
  				this[baseClassName][i] = window[baseClassName].prototype[i].bind(this);
  			}
  		}

  		if(window[baseClassName].getInheritedStuff) {
  			window[baseClassName].getInheritedStuff.apply(this);
  		}
  	}

  	return constructor;

  },

  objectsToDestroy : [],
  registerForDestruction: function(obj) {
  	if(!Class.addedDestructionLoader) {
			Event.observe(window, 'unload', Class.destroyAllObjects);
  		Class.addedDestructionLoader = true;
  	}
  	Class.objectsToDestroy.push(obj);
  },

  destroyAllObjects: function() {
  	var i,item;
  	for(i=0;item=Class.objectsToDestroy[i];i++) {
  		if(item.destroy) item.destroy();
  	}
  	Class.objectsToDestroy = null;
  }
}

/**
 * Extend function used in multiple inheritance
 */
Function.prototype.extend = function(baseClassName) {
	var parentFunc = this;

	var constructor = function() {
		this[baseClassName] = {}
		for(var i in window[baseClassName].prototype) {
			if(!this[i]) this[i] = window[baseClassName].prototype[i];
			this[baseClassName][i] = window[baseClassName].prototype[i].bind(this);
		}

		if(window[baseClassName].getInheritedStuff) {
			window[baseClassName].getInheritedStuff.apply(this);
		}
		if(parentFunc.getInheritedStuff) {
			parentFunc.getInheritedStuff.apply(this);
		}

		parentFunc.apply(this, arguments);
	}

	constructor.getInheritedStuff = function() {
		this[baseClassName] = {}
		for(i in window[baseClassName].prototype) {
			if(!this[i]) this[i] = window[baseClassName].prototype[i];
			this[baseClassName][i] = window[baseClassName].prototype[i].bind(this);
		}

		if(window[baseClassName].getInheritedStuff) {
			window[baseClassName].getInheritedStuff.apply(this);
		}
		if(parentFunc.getInheritedStuff) {
			parentFunc.getInheritedStuff.apply(this);
		}
	}

	return constructor;
}

var Abstract = new Object();

Object.extend = function(destination, source) {
  for (property in source) {
    destination[property] = source[property];
  }
  return destination;
}
Function.prototype.extendPrototype = function(newPrototype) {
	var property;
  for (property in this.prototype) {
    newPrototype[property] = this.prototype[property];
  }
  return newPrototype;
}

Object.inspect = function(object) {
  try {
    if (object == undefined) return 'undefined';
    if (object == null) return 'null';
    return object.inspect ? object.inspect() : object.toString();
  } catch (e) {
    if (e instanceof RangeError) return '...';
    throw e;
  }
}

Function.prototype.bind = function(object) {
  var __method = this;
  return function() {
    return __method.apply(object, arguments);
  }
}

Function.prototype.bindAsEventListener = function(object) {
  var __method = this;
  return function(event) {
    return __method.call(object, event || window.event);
  }
}
Object.extend(Number.prototype, {
  toColorPart: function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
  },

  succ: function() {
    return this + 1;
  },

  times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
  }
});

var Try = {
  these: function() {
    var returnValue;

    for (var i = 0; i < arguments.length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }

    return returnValue;
  }
}

/*--------------------------------------------------------------------------*/

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback();
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}

/*--------------------------------------------------------------------------*/

function $(el) {
	if(typeof el == 'string') return document.getElementById(el);
	else return el;
	/*
  var elements = new Array();

  for (var i = 0; i < arguments.length; i++) {
    var element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);

    if (arguments.length == 1)
      return element;

    elements.push(element);
  }

  return elements;
  */
}
Object.extend(String.prototype, {
  // Added by Silverstripe Ltd. 2007-03-15
  strip: function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  },

  stripTags: function() {
    return this.replace(/<\/?[^>]+>/gi, '');
  },

  stripScripts: function() {
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  },

  extractScripts: function() {
    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
    return (this.match(matchAll) || []).map(function(scriptTag) {
      return (scriptTag.match(matchOne) || ['', ''])[1];
    });
  },

  evalScripts: function() {
    return this.extractScripts().map(eval);
  },

  escapeHTML: function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },

  unescapeHTML: function() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
  },

  toQueryParams: function() {
    var pairs = this.match(/^\??(.*)$/)[1].split('&');
    return pairs.inject({}, function(params, pairString) {
      var pair = pairString.split('=');
      params[pair[0]] = pair[1];
      return params;
    });
  },

  toArray: function() {
    return this.split('');
  },

  camelize: function() {
    var oStringList = this.split('-');
    if (oStringList.length == 1) return oStringList[0];

    var camelizedString = this.indexOf('-') == 0
      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
      : oStringList[0];

    for (var i = 1, len = oStringList.length; i < len; i++) {
      var s = oStringList[i];
      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
    }

    return camelizedString;
  },

  inspect: function() {
    return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
  }
});

String.prototype.parseQuery = String.prototype.toQueryParams;

var $break    = new Object();
var $continue = new Object();

var Enumerable = {
  each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        try {
          iterator(value, index++);
        } catch (e) {
          if (e != $continue) throw e;
        }
      });
    } catch (e) {
      if (e != $break) throw e;
    }
  },

  all: function(iterator) {
    var result = true;
    this.each(function(value, index) {
      result = result && !!(iterator || Prototype.K)(value, index);
      if (!result) throw $break;
    });
    return result;
  },

  any: function(iterator) {
    var result = true;
    this.each(function(value, index) {
      if (result = !!(iterator || Prototype.K)(value, index))
        throw $break;
    });
    return result;
  },

  collect: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      results.push(iterator(value, index));
    });
    return results;
  },

  detect: function (iterator) {
    var result;
    this.each(function(value, index) {
      if (iterator(value, index)) {
        result = value;
        throw $break;
      }
    });
    return result;
  },

  findAll: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (iterator(value, index))
        results.push(value);
    });
    return results;
  },

  grep: function(pattern, iterator) {
    var results = [];
    this.each(function(value, index) {
      var stringValue = value.toString();
      if (stringValue.match(pattern))
        results.push((iterator || Prototype.K)(value, index));
    })
    return results;
  },

  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  },

  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  },

  invoke: function(method) {
    var args = $A(arguments).slice(1);
    return this.collect(function(value) {
      return value[method].apply(value, args);
    });
  },

  max: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (value >= (result || value))
        result = value;
    });
    return result;
  },

  min: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (value <= (result || value))
        result = value;
    });
    return result;
  },

  partition: function(iterator) {
    var trues = [], falses = [];
    this.each(function(value, index) {
      ((iterator || Prototype.K)(value, index) ?
        trues : falses).push(value);
    });
    return [trues, falses];
  },

  pluck: function(property) {
    var results = [];
    this.each(function(value, index) {
      results.push(value[property]);
    });
    return results;
  },

  reject: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator(value, index))
        results.push(value);
    });
    return results;
  },

  sortBy: function(iterator) {
    return this.collect(function(value, index) {
      return {value: value, criteria: iterator(value, index)};
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }).pluck('value');
  },

  toArray: function() {
    return this.collect(Prototype.K);
  },

  zip: function() {
    var iterator = Prototype.K, args = $A(arguments);
    if (typeof args.last() == 'function')
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      iterator(value = collections.pluck(index));
      return value;
    });
  },

  inspect: function() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }
}

Object.extend(Enumerable, {
  map:     Enumerable.collect,
  find:    Enumerable.detect,
  select:  Enumerable.findAll,
  member:  Enumerable.include,
  entries: Enumerable.toArray
});
var $A = Array.from = function(iterable) {
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Object.extend(Array.prototype, Enumerable);

Object.extend(Array.prototype, {
  _each: function(iterator) {
    for (var i = 0; i < this.length; i++)
      iterator(this[i]);
  },

  first: function() {
    return this[0];
  },

  last: function() {
    return this[this.length - 1];
  },

  compact: function() {
    return this.select(function(value) {
      return value != undefined || value != null;
    });
  },

  flatten: function() {
    return this.inject([], function(array, value) {
      return array.concat(value.constructor == Array ?
        value.flatten() : [value]);
    });
  },

  without: function() {
    var values = $A(arguments);
    return this.select(function(value) {
      return !values.include(value);
    });
  },

  indexOf: function(object) {
    for (var i = 0; i < this.length; i++)
      if (this[i] == object) return i;
    return -1;
  },

  reverse: function() {
    var result = [];
    for (var i = this.length; i > 0; i--)
      result.push(this[i-1]);
    return result;
  },

  inspect: function() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }
});
var Hash = {
  _each: function(iterator) {
    for (key in this) {
      var value = this[key];
      if (typeof value == 'function') continue;

      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },

  keys: function() {
    return this.pluck('key');
  },

  values: function() {
    return this.pluck('value');
  },

  merge: function(hash) {
    return $H(hash).inject($H(this), function(mergedHash, pair) {
      mergedHash[pair.key] = pair.value;
      return mergedHash;
    });
  },

  toQueryString: function() {
    return this.map(function(pair) {
      return pair.map(encodeURIComponent).join('=');
    }).join('&');
  },

  inspect: function() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  }
}

function $H(object) {
  var hash = Object.extend({}, object || {});
  Object.extend(hash, Enumerable);
  Object.extend(hash, Hash);
  return hash;
}
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

  _each: function(iterator) {
    var value = this.start;
    do {
      iterator(value);
      value = value.succ();
    } while (this.include(value));
  },

  include: function(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }
});

var $R = function(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}

var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
      function() {return new XMLHttpRequest()}
    ) || false;
  },

  activeRequestCount: 0
}

Ajax.Responders = {
  responders: [],

  _each: function(iterator) {
    this.responders._each(iterator);
  },

  register: function(responderToAdd) {
    if (!this.include(responderToAdd))
      this.responders.push(responderToAdd);
  },

  unregister: function(responderToRemove) {
    this.responders = this.responders.without(responderToRemove);
  },

  dispatch: function(callback, request, transport, json) {
    this.each(function(responder) {
      if (responder[callback] && typeof responder[callback] == 'function') {
        try {
          responder[callback].apply(responder, [request, transport, json]);
        } catch (e) {}
      }
    });
  }
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
  onCreate: function() {
    Ajax.activeRequestCount++;
  },

  onComplete: function() {
    Ajax.activeRequestCount--;
  }
});

Ajax.Base = function() {};
Ajax.Base.prototype = {
  setOptions: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      parameters:   ''
    }
    Object.extend(this.options, options || {});
  },

  responseIsSuccess: function() {
  	try {
	    return (this.transport.responseText.substr(0,6) != 'ERROR:') && (
	    		this.transport.status == undefined
	        || this.transport.status == 0
	        || (this.transport.status >= 200 && this.transport.status < 300));
	  } catch(er) {
	  	return window.exiting ? true : false;
	  }
  },

  responseIsFailure: function() {
    return !this.responseIsSuccess();
  }
}

Ajax.Request = Class.create();
Ajax.Request.Events =
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(url, options) {
    this.transport = Ajax.getTransport();
    this.setOptions(options);
    this.request(url);
  },

  request: function(url) {
    var parameters = this.options.parameters || '';
    if (parameters.length > 0) parameters += '&_=';

    try {
      this.url = url;
      if (this.options.method == 'get' && parameters.length > 0)
        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;

      Ajax.Responders.dispatch('onCreate', this, this.transport);

      this.transport.open(this.options.method, this.url,
        this.options.asynchronous);

      if (this.options.asynchronous) {
        this.transport.onreadystatechange = this.onStateChange.bind(this);
        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
      }

      this.setRequestHeaders();

      var body = this.options.postBody ? this.options.postBody : parameters;
      this.transport.send(this.options.method == 'post' ? body : null);

    } catch (e) {
      this.dispatchException(e);
    }
  },

  setRequestHeaders: function() {
    var requestHeaders =
      ['X-Requested-With', 'XMLHttpRequest',
       'X-Prototype-Version', Prototype.Version ];

    if (this.options.method == 'post') {
      requestHeaders.push('Content-type',
        'application/x-www-form-urlencoded; charset=utf-8');

      /* Force "Connection: close" for older Mozilla browsers to work
       * around a bug where XMLHttpRequest sends an incorrect
       * Content-length header. See Mozilla Bugzilla #246651.
       */
      if (this.transport.overrideMimeType &&
          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
            headers['Connection'] = 'close';
    }

    if (this.options.requestHeaders)
      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

    for (var i = 0; i < requestHeaders.length; i += 2)
      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
  },

  onStateChange: function() {
    var readyState = this.transport.readyState;
    if (readyState != 1)
      this.respondToReadyState(this.transport.readyState);
  },

  header: function(name) {
    try {
      return this.transport.getResponseHeader(name);
    } catch (e) {}
  },

  evalJSON: function() {
    try {
      return eval(this.header('X-JSON'));
    } catch (e) {}
  },

  evalResponse: function() {
    // Modified 2006-11-17 by Silverstripe Ltd. - Needed for Ajax.Evaluator
    //if(this.transport.isEvaluated == true) return false;
    try {
      return eval(this.transport.responseText);
    } catch (e) {
      this.dispatchException(e);
    }
  },

  respondToReadyState: function(readyState) {
    var event = Ajax.Request.Events[readyState];
    var transport = this.transport, json = this.evalJSON();

    if (event == 'Complete') {
        // jquery ondemand integration patch
        prototypeAjax = this;
        completeHandler = function() {
        	// SilverStripe indication that the session has been lost
        	if(prototypeAjax.transport.responseText && prototypeAjax.transport.responseText.substr(0,12) == 'NOTLOGGEDIN:') {
        		if(typeof onSessionLost == 'function') onSessionLost();

        	} else {
    	      //try {
    	      var status = '';
    	      	try { status = prototypeAjax.transport.status } catch(e) {}
    	      	if(prototypeAjax.options) {
    		        (prototypeAjax.options['on' + status]
    		         || prototypeAjax.options['on' + (prototypeAjax.responseIsSuccess() ? 'Success' : 'Failure')]
    		         || Prototype.emptyFunction)(transport, json);
    		      }
    	      /*} catch (e) {
    	        prototypeAjax.dispatchException(e);
    	      }*/

    	      if (prototypeAjax.header('Content-type') == 'text/javascript')
    	        prototypeAjax.evalResponse();
    	    }
	    }

        // jquery ondemand integration patch
	    if(typeof jQuery != 'undefined' && typeof jQuery.processOnDemandHeaders != 'undefined') {
	        jQuery.processOnDemandHeaders(this.transport, prototypeAjax.transport.status, completeHandler);
	    } else {
	        completeHandler();
	    }

    }

    try {
      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
      Ajax.Responders.dispatch('on' + event, this, transport, json);
    } catch (e) {
      this.dispatchException(e);
    }

    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
    if (event == 'Complete')
      this.transport.onreadystatechange = Prototype.emptyFunction;
  },

  dispatchException: function(exception) {
    (this.options.onException || Prototype.emptyFunction)(this, exception);
    Ajax.Responders.dispatch('onException', this, exception);
  }
});

Ajax.Updater = Class.create();

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  initialize: function(container, url, options) {
    this.containers = {
      success: container.success ? $(container.success) : $(container),
      failure: container.failure ? $(container.failure) :
        (container.success ? null : $(container))
    }

    this.transport = Ajax.getTransport();
    this.setOptions(options);

    var onComplete = this.options.onComplete || Prototype.emptyFunction;
    this.options.onComplete = (function(transport, object) {
      this.updateContent();
      onComplete(transport, object);
    }).bind(this);

    this.request(url);
  },

  updateContent: function() {
    var receiver = this.responseIsSuccess() ?
      this.containers.success : this.containers.failure;
    var response = this.transport.responseText;

    if (!this.options.evalScripts)
      response = response.stripScripts();

    if (receiver) {
      if (this.options.insertion) {
        new this.options.insertion(receiver, response);
      } else {
        Element.update(receiver, response);
      }
    }

    if (this.responseIsSuccess()) {
      if (this.onComplete)
        setTimeout(this.onComplete.bind(this), 10);
    }
  }
});

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(container, url, options) {
    this.setOptions(options);
    this.onComplete = this.options.onComplete;

    this.frequency = (this.options.frequency || 2);
    this.decay = (this.options.decay || 1);

    this.updater = {};
    this.container = container;
    this.url = url;

    this.start();
  },

  start: function() {
    this.options.onComplete = this.updateComplete.bind(this);
    this.onTimerEvent();
  },

  stop: function() {
    this.updater.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  },

  updateComplete: function(request) {
    if (this.options.decay) {
      this.decay = (request.responseText == this.lastText ?
        this.decay * this.options.decay : 1);

      this.lastText = request.responseText;
    }
    this.timer = setTimeout(this.onTimerEvent.bind(this),
      this.decay * this.frequency * 1000);
  },

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});

Ajax.SubmitForm = function(form, button, options) {
	var form = $(form);

	var data = Form.serializeWithoutButtons(form) + '&ajax=1';

	if(button) data += '&' + button + '=1';

	if(!options)
	options.method = form.method;
	options.postBody = data;

	if(options.extraData)
		options.postBody += options.extraData;

	new Ajax.Request(form.action, options);
}

Ajax.Evaluator = function(response) {
	//response.isEvaluated = true;

	// Added by Silverstripe Ltd. 2008-09-16
	// similiar to Ajax.Base.responseIsSuccess()
	if(response.status >= 200 && response.status < 300) {
		try {
			eval(response.responseText);
		} catch(er) {
			errorMessage(
				'Javascript Parse Error',
				er.lineNumber + ':\n' + er.message + '\n\n' + response.responseText
			);
		}
	} else {
		errorMessage(
			'Server Error',
			response.responseText
		);
	}

}

// Only define this if no native (and significantly faster) implementation exists.
if(!document.getElementsByClassName) {
	document.getElementsByClassName = function(className, parentElement) {
	  var children = ($(parentElement) || document.body).getElementsByTagName('*');
	  return $A(children).inject([], function(elements, child) {
	    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
	      elements.push(child);
	    return elements;
	  });
	}
}

/*--------------------------------------------------------------------------*/

if (!window.Element) {
  var Element = new Object();
}

Object.extend(Element, {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      Element[Element.visible(element) ? 'hide' : 'show'](element);
    }
  },

  hide: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      if( element )
      	element.style.display = 'none';
    }
  },

  show: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      if( element )
      	element.style.display = '';
    }
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
  },

  update: function(element, html) {
  	try {
    	$(element).innerHTML = html.stripScripts();
    } catch(er) { alert(er.description); }

	  setTimeout(function() {html.evalScripts()}, 10);
  },

  // 11/11/2006 Silverstripe Ltd., transferred from prototype v1.5
  replace: function(element, html) {
	element = $(element);
		if (element.outerHTML) {
			element.outerHTML = html.stripScripts();
		} else {
			var range = element.ownerDocument.createRange();
			range.selectNodeContents(element);
			element.parentNode.replaceChild(
			range.createContextualFragment(html.stripScripts()), element);
		}
		setTimeout(function() {html.evalScripts()}, 10);
	},

  getHeight: function(element) {
    element = $(element);
    return element.offsetHeight;
  },

  classNames: function(element) {
    return new Element.ClassNames(element);
  },

  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    return Element.classNames(element).include(className);
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;

		// 13/3/2006: Sam updated these functions because the original ones were over-engineered
		if(!element.className.match(new RegExp('(^| )' + className + '($| )'))) {
			element.className += ' ' + className;
			element.className = element.className.replace(/(^ +)|( +$)/g, '');
		}
	 },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;

		// 13/3/2006: Sam updated these functions because the original ones were over-engineered
		var old = element.className;
		var newCls = ' ' + element.className + ' ';
		newCls = newCls.replace(new RegExp(' (' + className + ' +)+','g'), ' ');
		element.className = newCls.replace(/(^ +)|( +$)/g, '');
  },

  // removes whitespace-only text node children
  cleanWhitespace: function(element) {
    element = $(element);
    for (var i = 0; i < element.childNodes.length; i++) {
      var node = element.childNodes[i];
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        Element.remove(node);
    }
  },

  empty: function(element) {
    return $(element).innerHTML.match(/^\s*$/);
  },

  scrollTo: function(element) {
    element = $(element);
    var x = element.x ? element.x : element.offsetLeft,
        y = element.y ? element.y : element.offsetTop;
    window.scrollTo(x, y);
  },

  getStyle: function(element, style) {
    element = $(element);
    var value = element.style[style.camelize()];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css.getPropertyValue(style) : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[style.camelize()];
      }
    }

    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';

    return value == 'auto' ? null : value;
  },

  getDimensions: function(element) {
    element = $(element);
    if (Element.getStyle(element, 'display') != 'none')
      return {width: element.offsetWidth, height: element.offsetHeight};

    // All *Width and *Height properties give 0 on elements with display none,
    // so enable the element temporarily
    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = '';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = 'none';
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      // Opera returns the offset relative to the positioning context, when an
      // element is position relative but top and left have not been defined
      if (window.opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
  },

  undoPositioned: function(element) {
    element = $(element);
    if (element._madePositioned) {
      element._madePositioned = undefined;
      element.style.position =
        element.style.top =
        element.style.left =
        element.style.bottom =
        element.style.right = '';
    }
  },

  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return;
    element._overflow = element.style.overflow;
    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
      element.style.overflow = 'hidden';
  },

  undoClipping: function(element) {
    element = $(element);
    if (element._overflow) return;
    element.style.overflow = element._overflow;
    element._overflow = undefined;
  },

	contains: function(parent, child) {
		ancestor = child.parentNode;
		while(ancestor) {
			if(ancestor == parent) return true;
			ancestor = ancestor.parentNode;
		}
		return false;
	},

	ancestorOfType: function(element, tagName) {
		var anc = element.parentNode;
		while(anc && anc.tagName.toLowerCase() != tagName)
			anc = anc.parentNode;
		return anc;
	}
});

var Toggle = new Object();
Toggle.display = Element.toggle;

/*--------------------------------------------------------------------------*/

Abstract.Insertion = function(adjacency) {
  this.adjacency = adjacency;
}

Abstract.Insertion.prototype = {
  initialize: function(element, content) {
    this.element = $(element);
    this.content = content.stripScripts();

    if (this.adjacency && this.element.insertAdjacentHTML) {
      try {
        this.element.insertAdjacentHTML(this.adjacency, this.content);
      } catch (e) {
        if (this.element.tagName.toLowerCase() == 'tbody') {
          this.insertContent(this.contentFromAnonymousTable());
        } else {
          throw e;
        }
      }
    } else {
      this.range = this.element.ownerDocument.createRange();
      if (this.initializeRange) this.initializeRange();
      this.insertContent([this.range.createContextualFragment(this.content)]);
    }

    setTimeout(function() {content.evalScripts()}, 10);
  },

  contentFromAnonymousTable: function() {
    var div = document.createElement('div');
    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
    return $A(div.childNodes[0].childNodes[0].childNodes);
  }
}

var Insertion = new Object();

Insertion.Before = Class.create();
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  initializeRange: function() {
    this.range.setStartBefore(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment, this.element);
    }).bind(this));
  }
});

Insertion.Top = Class.create();
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(true);
  },

  insertContent: function(fragments) {
    fragments.reverse().each((function(fragment) {
      this.element.insertBefore(fragment, this.element.firstChild);
    }).bind(this));
  }
});

Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.appendChild(fragment);
    }).bind(this));
  }
});

Insertion.After = Class.create();
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  initializeRange: function() {
    this.range.setStartAfter(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment,
        this.element.nextSibling);
    }).bind(this));
  }
});

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
  initialize: function(element) {
    this.element = $(element);
  },

  _each: function(iterator) {
    this.element.className.split(/\s+/).select(function(name) {
      return name.length > 0;
    })._each(iterator);
  },

  set: function(className) {
    this.element.className = className;
  },

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set(this.toArray().concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set(this.select(function(className) {
      return className != classNameToRemove;
    }).join(' '));
  },

  toString: function() {
    return this.toArray().join(' ');
  }
}

Object.extend(Element.ClassNames.prototype, Enumerable);
var Field = {
  clear: function() {
    for (var i = 0; i < arguments.length; i++)
      $(arguments[i]).value = '';
  },

  focus: function(element) {
    $(element).focus();
  },

  present: function() {
    for (var i = 0; i < arguments.length; i++)
      if ($(arguments[i]).value == '') return false;
    return true;
  },

  select: function(element) {
    $(element).select();
  },

  activate: function(element) {
    element = $(element);
    element.focus();
    if (element.select)
      element.select();
  }
}

/*--------------------------------------------------------------------------*/

var Form = {
  serialize: function(form) {
    var elements = Form.getElements($(form));
    var queryComponents = new Array();

    for (var i = 0; i < elements.length; i++) {
      var queryComponent = Form.Element.serialize(elements[i]);
      if (queryComponent)
        queryComponents.push(queryComponent);
    }

    return queryComponents.join('&');
  },

  serializeWithoutButtons: function(form) {
    var elements = Form.getElements($(form));
    var queryComponents = new Array();

    for (var i = 0; i < elements.length; i++) {
    	if(elements[i].type == 'submit' || elements[i].type == 'reset') continue;

      var queryComponent = Form.Element.serialize(elements[i]);
      if (queryComponent)
        queryComponents.push(queryComponent);
    }

    return queryComponents.join('&');
  },

  getElements: function(form) {
    form = $(form);
    var elements = new Array();

    for (tagName in Form.Element.Serializers) {
      var tagElements = form.getElementsByTagName(tagName);
      for (var j = 0; j < tagElements.length; j++)
        elements.push(tagElements[j]);
    }
    return elements;
  },

  getInputs: function(form, typeName, name) {
    form = $(form);
    var inputs = form.getElementsByTagName('input');

    if (!typeName && !name)
      return inputs;

    var matchingInputs = new Array();
    for (var i = 0; i < inputs.length; i++) {
      var input = inputs[i];
      if ((typeName && input.type != typeName) ||
          (name && input.name != name))
        continue;
      matchingInputs.push(input);
    }

    return matchingInputs;
  },

  disable: function(form) {
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.blur();
      element.disabled = 'true';
    }
  },

  enable: function(form) {
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.disabled = '';
    }
  },

  findFirstElement: function(form) {
    return Form.getElements(form).find(function(element) {
      return element.type != 'hidden' && !element.disabled &&
        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

  focusFirstElement: function(form) {
    Field.activate(Form.findFirstElement(form));
  },

  reset: function(form) {
    $(form).reset();
  }
}

Form.Element = {
  serialize: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);

    if (parameter)
      return encodeURIComponent(parameter[0]) + '=' +
        encodeURIComponent(parameter[1]);
    else
    	return "";
  },

  getValue: function(element) {
    element = $(element);
    if(element) {
	    if(element.nodeName == "SELECT") var method = 'select'
	    else if(element.length) var method = 'array';
	    else var method = element.tagName.toLowerCase();
	    if(Form.Element.Serializers[method]) {
		   	var parameter = Form.Element.Serializers[method](element);

		    if (parameter)
		      return parameter[1];
		  }
		}
  },

  setValue: function(element, value) {
    element = $(element);
    if(element.setValue) {
    	element.setValue(value);
    } else {
	    if(element.length) var method = 'array';
	    else var method = element.tagName.toLowerCase();
	    Form.Element.ValueSetters[method](element, value);
	  }
	},

  // Added by Silverstripe Ltd. 2007-03-15
  disable: function(element) {
    element = $(element);
    element.disabled = true;
    return element;
  },

  // Added by Silverstripe Ltd. 2007-03-15
  enable: function(element) {
    element = $(element);
    element.blur();
    element.disabled = false;
    return element;
  }
}

Form.Element.Serializers = {
  input: function(element) {
    switch (element.type.toLowerCase()) {
      case 'submit':
      case 'hidden':
      case 'password':
      case 'text':
        return Form.Element.Serializers.textarea(element);
      case 'checkbox':
      case 'radio':
        return Form.Element.Serializers.inputSelector(element);
    }
    return false;
  },

  array: function(element) {
  	var i,item;
  	for(i=0;item=element[i];i++) {
  		if(item.checked) return [item.name, item.value];
  	}
  },

  inputSelector: function(element) {
    if (element.checked)
      return [element.name, element.value];
  },

  textarea: function(element) {
    return [element.name, element.value];
  },

  select: function(element) {
    return Form.Element.Serializers[element.type == 'select-one' ?
      'selectOne' : 'selectMany'](element);
  },

  selectOne: function(element) {
    var value = '', opt, index = element.selectedIndex;
    if (index >= 0) {
      opt = element.options[index];
      value = opt.value;
      if (!value && !('value' in opt))
        value = opt.text;
    }
    return [element.name, value];
  },

  selectMany: function(element) {
    var value = new Array();
    for (var i = 0; i < element.length; i++) {
      var opt = element.options[i];
      if (opt.selected) {
        var optValue = opt.value;
        if (!optValue && !('value' in opt))
          optValue = opt.text;
        value.push(optValue);
      }
    }
    return [element.name, value];
  }
}

Form.Element.ValueSetters = {
  input: function(element, value) {
    switch (element.type.toLowerCase()) {
      case 'submit':
      case 'hidden':
      case 'password':
      case 'text':
  			element.value = value;
      case 'checkbox':
      case 'radio':
		  	element.checked = (element.value == value);
    }
  },

  array: function(element, value) {
  	var i,item;
  	for(i=0;item=element[i];i++) {
  		element[i].checked = (item.value == value);
  	}
  },

  inputSelector: function(element, value) {
  			element.value = value;
  },

  textarea: function(element, value) {
  			element.value = value;
  },

  select: function(element, value) {
		element.value = value;
  }
}

/*--------------------------------------------------------------------------*/

var $F = Form.Element.getValue;

/*--------------------------------------------------------------------------*/

Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;

    this.lastValue = this.getValue();
    this.registerCallback();
  },

  registerCallback: function() {
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  onTimerEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
}

Form.Element.Observer = Class.create();
Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.Observer = Class.create();
Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});

/*--------------------------------------------------------------------------*/

Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
  initialize: function(element, callback) {
    this.element  = $(element);
    this.callback = callback;

    this.lastValue = this.getValue();
    if (this.element.tagName.toLowerCase() == 'form')
      this.registerFormCallbacks();
    else
      this.registerCallback(this.element);
  },

  onElementEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  },

  registerFormCallbacks: function() {
    var elements = Form.getElements(this.element);
    for (var i = 0; i < elements.length; i++)
      this.registerCallback(elements[i]);
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        case 'password':
        case 'text':
        case 'textarea':
        case 'select-one':
        case 'select-multiple':
          Event.observe(element, 'change', this.onElementEvent.bind(this));
          break;
      }
    }
  }
}

Form.Element.EventObserver = Class.create();
Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.EventObserver = Class.create();
Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});
if (!window.Event) {
  var Event = new Object();
}

Object.extend(Event, {
  KEY_BACKSPACE: 8,
  KEY_TAB:       9,
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,

  element: function(event) {
  	if(!event) event = window.Event;
    return event.target || event.srcElement;
  },

  isLeftClick: function(event) {
  	if(!event) event = window.Event;
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },

  pointerX: function(event) {
  	if(!event) event = window.Event;
    return event.pageX || (event.clientX +
      (document.documentElement.scrollLeft || document.body.scrollLeft));
  },

  pointerY: function(event) {
  	if(!event) event = window.Event;
    return event.pageY || (event.clientY +
      (document.documentElement.scrollTop || document.body.scrollTop));
  },

  stop: function(event) {
  	if(event) {
	    if (typeof event.preventDefault != 'undefined') {
	      event.preventDefault();
	      event.stopPropagation();
	    } else {
	      event.returnValue = false;
	      event.cancelBubble = true;
	    }
	  }
  },

  // find the first node with the given tagName, starting from the
  // node the event was triggered on; traverses the DOM upwards
  findElement: function(event, tagName) {
    var element = Event.element(event);
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  },

  observers: false,

  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },

  unloadCache: function() {
    if (!Event.observers) return;
    for (var i = 0; i < Event.observers.length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.attachEvent))
      name = 'keydown';

    this._observeAndCache(element, name, observer, useCapture);
  },

  stopObserving: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.detachEvent))
      name = 'keydown';

    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      element.detachEvent('on' + name, observer);
    }
  }
});

/* prevent memory leaks in IE */
Event.observe(window, 'unload', Event.unloadCache, false);
var Position = {
  // set to true if needed, warning: firefox performance problems
  // NOT neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  includeScrollOffsets: true,

  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  realOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return [valueL, valueT];
  },

  cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return [valueL, valueT];
  },

  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        p = Element.getStyle(element, 'position');
        if (p == 'relative' || p == 'absolute') break;
      }
    } while (element);
    return [valueL, valueT];
  },

  offsetParent: function(element) {
    if (element.offsetParent) return element.offsetParent;
    if (element == document.body) return element;

    while ((element = element.parentNode) && element != document.body)
      if (Element.getStyle(element, 'position') != 'static')
        return element;

    return document.body;
  },

  // caches x/y coordinate pair to use with overlap
  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = this.cumulativeOffset(element);

    return (y >= this.offset[1] &&
            y <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

  withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = this.realOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = this.cumulativeOffset(element);

    return (this.ycomp >= this.offset[1] &&
            this.ycomp <  this.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  // within must be called directly before
  overlap: function(mode, element) {
    if (!mode) return 0;
    if (mode == 'vertical')
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
        element.offsetHeight;
    if (mode == 'horizontal')
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
        element.offsetWidth;
  },

  clone: function(source, target) {
    source = $(source);
    target = $(target);
    target.style.position = 'absolute';
    var offsets = this.cumulativeOffset(source);
    target.style.top    = offsets[1] + 'px';
    target.style.left   = offsets[0] + 'px';
    target.style.width  = source.offsetWidth + 'px';
    target.style.height = source.offsetHeight + 'px';
  },

  page: function(forElement) {
    var valueT = 0, valueL = 0;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent==document.body)
        if (Element.getStyle(element,'position')=='absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      valueT -= element.scrollTop  || 0;
      valueL -= element.scrollLeft || 0;
    } while (element = element.parentNode);

    return [valueL, valueT];
  },

  clone: function(source, target) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || {})

    // find page position of source
    source = $(source);
    var p = Position.page(source);

    // find coordinate system to use
    target = $(target);
    var delta = [0, 0];
    var parent = null;
    // delta [0,0] will do fine with position: fixed elements,
    // position:absolute needs offsetParent deltas
    if (Element.getStyle(target,'position') == 'absolute') {
      parent = Position.offsetParent(target);
      delta = Position.page(parent);
    }

    // correct by body offsets (fixes Safari)
    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    // set position
    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
  },

  absolutize: function(element) {
    element = $(element);
    if (element.style.position == 'absolute') return;
    Position.prepare();

    var offsets = Position.positionedOffset(element);
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    element._originalLeft   = left - parseFloat(element.style.left  || 0);
    element._originalTop    = top  - parseFloat(element.style.top || 0);
    element._originalWidth  = element.style.width;
    element._originalHeight = element.style.height;

    element.style.position = 'absolute';
    element.style.top    = top + 'px';;
    element.style.left   = left + 'px';;
    element.style.width  = width + 'px';;
    element.style.height = height + 'px';;
  },

  relativize: function(element) {
    element = $(element);
    if (element.style.position == 'relative') return;
    Position.prepare();

    element.style.position = 'relative';
    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.height = element._originalHeight;
    element.style.width  = element._originalWidth;
  }
}

// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  Position.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, 'position') == 'absolute') break;

      element = element.offsetParent;
    } while (element);

    return [valueL, valueT];
  }
}

document.getParentOfElement = function( element, tagName, className ) {

	if( !element )
		return null;

	var parent = element.parentNode;

	while( parent ) {
		if( className && Element.hasClassName( parent, className ) && parent.tagName.toLowerCase() == tagName.toLowerCase() )
			return parent;
		else if( parent.tagName.toLowerCase() == tagName.toLowerCase() )
			return parent;

		parent = parent.parentNode;
	}

	return parent;
}


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="generator" content="rustdoc">
    <meta name="description" content="Source to the Rust file `C:/bot/slave/nightly-dist-rustc-win-64/build/src/librustc\util\snapshot_vec.rs`.">
    <meta name="keywords" content="rust, rustlang, rust-lang">

    <title>snapshot_vec.rs.html -- source</title>

    <link rel="stylesheet" type="text/css" href="../../../../main.css">

    <link rel="shortcut icon" href="http://www.rust-lang.org/favicon.ico">

        <form class="search-form js-only">

                <input class="search-input" name="search"
                       autocomplete="off"
                       placeholder="Click or press 'S' to search, '?' for more options..."
                       type="search">

        </form>

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A utility class for implementing "snapshottable" things; a snapshottable data structure permits
//! you to take a snapshot (via `start_snapshot`) and then, after making some changes, elect either
//! to rollback to the start of the snapshot or commit those changes.
//!
//! This vector is intended to be used as part of an abstraction, not serve as a complete
//! abstraction on its own. As such, while it will roll back most changes on its own, it also
//! supports a `get_mut` operation that gives you an arbitrary mutable pointer into the vector. To
//! ensure that any changes you make this with this pointer are rolled back, you must invoke
//! `record` to record any changes you make and also supplying a delegate capable of reversing
//! those changes.
use self::UndoLog::*;

use std::mem;

pub enum UndoLog<D:SnapshotVecDelegate> {
    /// Indicates where a snapshot started.
    OpenSnapshot,

    /// Indicates a snapshot that has been committed.
    CommittedSnapshot,

    /// New variable with given index was created.
    NewElem(uint),

    /// Variable with given index was changed *from* the given value.
    SetElem(uint, D::Value),

    /// Extensible set of actions
    Other(D::Undo)
}

pub struct SnapshotVec<D:SnapshotVecDelegate> {
    values: Vec<D::Value>,
    undo_log: Vec<UndoLog<D>>,
    delegate: D
}

// Snapshots are tokens that should be created/consumed linearly.
pub struct Snapshot {
    // Length of the undo log at the time the snapshot was taken.
    length: uint,
}

pub trait SnapshotVecDelegate {
    type Value;
    type Undo;

    fn reverse(&mut self, values: &mut Vec<Self::Value>, action: Self::Undo);
}

impl<D:SnapshotVecDelegate> SnapshotVec<D> {
    pub fn new(delegate: D) -> SnapshotVec<D> {
        SnapshotVec {
            values: Vec::new(),
            undo_log: Vec::new(),
            delegate: delegate
        }
    }

    fn in_snapshot(&self) -> bool {
        !self.undo_log.is_empty()
    }

    pub fn record(&mut self, action: D::Undo) {
        if self.in_snapshot() {
            self.undo_log.push(Other(action));
        }
    }

    pub fn push(&mut self, elem: D::Value) -> uint {
        let len = self.values.len();
        self.values.push(elem);

        if self.in_snapshot() {
            self.undo_log.push(NewElem(len));
        }

        len
    }

    pub fn get<'a>(&'a self, index: uint) -> &'a D::Value {
        &self.values[index]
    }

    /// Returns a mutable pointer into the vec; whatever changes you make here cannot be undone
    /// automatically, so you should be sure call `record()` with some sort of suitable undo
    /// action.
    pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut D::Value {
        &mut self.values[index]
    }

    /// Updates the element at the given index. The old value will saved (and perhaps restored) if
    /// a snapshot is active.
    pub fn set(&mut self, index: uint, new_elem: D::Value) {
        let old_elem = mem::replace(&mut self.values[index], new_elem);
        if self.in_snapshot() {
            self.undo_log.push(SetElem(index, old_elem));
        }
    }

    pub fn start_snapshot(&mut self) -> Snapshot {
        let length = self.undo_log.len();
        self.undo_log.push(OpenSnapshot);
        Snapshot { length: length }
    }

    pub fn actions_since_snapshot(&self,
                                  snapshot: &Snapshot)
                                  -> &[UndoLog<D>] {
        &self.undo_log[snapshot.length..]
    }

    fn assert_open_snapshot(&self, snapshot: &Snapshot) {
        // Or else there was a failure to follow a stack discipline:
        assert!(self.undo_log.len() > snapshot.length);

        // Invariant established by start_snapshot():
        assert!(
            match self.undo_log[snapshot.length] {
                OpenSnapshot => true,
                _ => false
            });
    }

    pub fn rollback_to(&mut self, snapshot: Snapshot) {
        debug!("rollback_to({})", snapshot.length);

        self.assert_open_snapshot(&snapshot);

        while self.undo_log.len() > snapshot.length + 1 {
            match self.undo_log.pop().unwrap() {
                OpenSnapshot => {
                    // This indicates a failure to obey the stack discipline.
                    panic!("Cannot rollback an uncommitted snapshot");
                }

                CommittedSnapshot => {
                    // This occurs when there are nested snapshots and
                    // the inner is committed but outer is rolled back.
                }

                NewElem(i) => {
                    self.values.pop();
                    assert!(self.values.len() == i);
                }

                SetElem(i, v) => {
                    self.values[i] = v;
                }

                Other(u) => {
                    self.delegate.reverse(&mut self.values, u);
                }
            }
        }

        let v = self.undo_log.pop().unwrap();
        assert!(match v { OpenSnapshot => true, _ => false });
        assert!(self.undo_log.len() == snapshot.length);
    }

    /// Commits all changes since the last snapshot. Of course, they
    /// can still be undone if there is a snapshot further out.
    pub fn commit(&mut self, snapshot: Snapshot) {
        debug!("commit({})", snapshot.length);

        self.assert_open_snapshot(&snapshot);

        if snapshot.length == 0 {
            // The root snapshot.
            self.undo_log.truncate(0);
        } else {
            self.undo_log[snapshot.length] = CommittedSnapshot;
        }
    }
}

Keyboard shortcuts

?

Show this help dialog

S

Focus the search field

⇤

Move up in search results

⇥

Move down in search results

⏎

Go to active search result

Search tricks

                Prefix searches with a type followed by a colon (e.g.
                fn:) to restrict the search to a given type.

                Accepted types are: fn, mod,
                struct, enum,
                trait, typedef (or
                tdef).

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace Bludata\Doctrine\Common\Contracts;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;

interface RepositoryContract
{
    public function getEntityManager(): EntityManager;

    public function getClassMetadata(): ClassMetadata;

    public function createQueryWorker(): QueryWorkerContract;

    public function findAll(): QueryWorkerContract;

    public function findOneBy(array $criteria, bool $abort = true): ?EntityContract;

    public function find($id, bool $abort = true): ?EntityContract;

    public function findAllRemoved(): QueryWorkerContract;

    public function findRemoved($id, bool $abort = true): ?EntityContract;

    public function createEntity(): EntityContract;

    public function remove(EntityContract $entity): EntityContract;
}


text:
class AddColumnAllocatedOnJournalDetails < ActiveRecord::Migration[5.1]
  def change
    add_column :journal_details, :allocated, :boolean, null: false, default: false
  end
end


text:
namespace amgcl {
    profiler<> prof;
}

BOOST_AUTO_TEST_SUITE( test_eigen_solver )

BOOST_AUTO_TEST_CASE(eigen_solver)
{
    std::vector<int>    ptr;
    std::vector<int>    col;
    std::vector<double> val;
    std::vector<double> rhs;

    size_t n = sample_problem(16, val, col, ptr, rhs);
    amgcl::backend::crs<double> A(std::tie(n, ptr, col, val));

    typedef
        amgcl::solver::EigenSolver<Eigen::SparseLU<Eigen::SparseMatrix<double, Eigen::ColMajor, int> > >
        Solver;

    Solver solve(A);

    std::vector<double> x(n);
    std::vector<double> r(n);

    solve(rhs, x);

    amgcl::backend::residual(rhs, A, x, r);

    BOOST_CHECK_SMALL(sqrt(amgcl::backend::inner_product(r, r)), 1e-8);
}

BOOST_AUTO_TEST_SUITE_END()


text:
@class AppController;
@class NoteObject;
@class ETTransparentButton;

@interface PreviewController : NSWindowController
{
  IBOutlet WebView *preview;
	IBOutlet NSTextView *sourceView;
	IBOutlet NSTabView *tabView;
	IBOutlet NSButton *tabSwitcher;
	IBOutlet NSButton *shareButton;
  IBOutlet NSButton *saveButton;
  IBOutlet NSButton *stickyPreviewButton;
  IBOutlet NSButton *printPreviewButton;
	ETTransparentButton *viewOnWebButton;
  BOOL isPreviewOutdated;
  BOOL isPreviewSticky;
	NSMutableData *receivedData;
//    IBOutlet NSWindow *wnd;
	MAAttachedWindow *attachedWindow;
	MAAttachedWindow *confirmWindow;
	IBOutlet NSTextField *urlTextField;
	IBOutlet NSView *shareNotification;
	IBOutlet NSView *shareConfirmation;
	ETTransparentButton *shareCancel;
  ETTransparentButton *shareConfirm;
	NSString *shareURL;
	NSString *cssString;
	NSString *htmlString;

	IBOutlet NSButton *includeTemplate;
  IBOutlet NSTextField *templateNote;
	IBOutlet NSView *accessoryView;

	NoteObject *lastNote;
}

@property (assign) BOOL isPreviewOutdated;
@property (retain) WebView *preview;
@property (assign) BOOL isPreviewSticky;

-(IBAction)saveHTML:(id)sender;
-(IBAction)switchTabs:(id)sender;
-(IBAction)shareNote:(id)sender;
-(IBAction)shareAsk:(id)sender;
-(IBAction)cancelShare:(id)sender;

-(IBAction)makePreviewSticky:(id)sender;
-(IBAction)makePreviewNotSticky:(id)sender;
-(IBAction)printPreview:(id)sender;
-(BOOL)previewIsVisible;
-(void)togglePreview:(id)sender;
-(void)requestPreviewUpdate:(NSNotification *)notification;
+(void)createCustomFiles;
-(SEL)markupProcessorSelector:(NSInteger)previewMode;
-(NSString *)urlEncodeValue:(NSString *)str;
-(void)showShareURL:(NSString *)url isError:(BOOL)isError;
-(IBAction)hideShareURL:(id)sender;
-(void)closeShareURLView;
-(IBAction)openShareURL:(id)sender;
+(NSString *)css;
+(NSString *)html;
@end


text:
#ifdef __IPHONE_8_0

#import "CDVWebViewUIDelegate.h"

@implementation CDVWebViewUIDelegate

- (instancetype)initWithTitle:(NSString*)title
{
  self = [super init];
  if (self) {
    self.title = title;
  }

  return self;
}

- (void)     webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message
    initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)(void))completionHandler
{
  UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
                                                                 message:message
                                                          preferredStyle:UIAlertControllerStyleAlert];

  UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
                                               style:UIAlertActionStyleDefault
                                             handler:^(UIAlertAction* action)
                       {
                         completionHandler();
                         [alert dismissViewControllerAnimated:YES completion:nil];
                       }];

  [alert addAction:ok];

  UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;

  [rootController presentViewController:alert animated:YES completion:nil];
}

- (void)     webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message
    initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)(BOOL result))completionHandler
{
  UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
                                                                 message:message
                                                          preferredStyle:UIAlertControllerStyleAlert];

  UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
                                               style:UIAlertActionStyleDefault
                                             handler:^(UIAlertAction* action)
                       {
                         completionHandler(YES);
                         [alert dismissViewControllerAnimated:YES completion:nil];
                       }];

  [alert addAction:ok];

  UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
                                                   style:UIAlertActionStyleDefault
                                                 handler:^(UIAlertAction* action)
                           {
                             completionHandler(NO);
                             [alert dismissViewControllerAnimated:YES completion:nil];
                           }];
  [alert addAction:cancel];

  UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;

  [rootController presentViewController:alert animated:YES completion:nil];
}

- (void)      webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt
          defaultText:(NSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame
    completionHandler:(void (^)(NSString* result))completionHandler
{
  UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
                                                                 message:prompt
                                                          preferredStyle:UIAlertControllerStyleAlert];

  UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
                                               style:UIAlertActionStyleDefault
                                             handler:^(UIAlertAction* action)
                       {
                         completionHandler(((UITextField*)alert.textFields[0]).text);
                         [alert dismissViewControllerAnimated:YES completion:nil];
                       }];

  [alert addAction:ok];

  UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
                                                   style:UIAlertActionStyleDefault
                                                 handler:^(UIAlertAction* action)
                           {
                             completionHandler(nil);
                             [alert dismissViewControllerAnimated:YES completion:nil];
                           }];
  [alert addAction:cancel];

  [alert addTextFieldWithConfigurationHandler:^(UITextField* textField) {
    textField.text = defaultText;
  }];

  UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;

  [rootController presentViewController:alert animated:YES completion:nil];
}

@end
#endif /* ifdef __IPHONE_8_0 */


text:
package com.eaglesakura.android.margarine;

import android.support.annotation.ArrayRes;
import android.support.annotation.Keep;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Injection
 */
@Keep
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindStringArray {
    /**
     * R.string.**
     */
    @Keep
    @ArrayRes int value() default 0;

    /**
     * R.string."resName"
     */
    @Keep
    String resName() default "";

    /**
     * BinderClass
     */
    @Keep
    Class<? extends FieldBinder> binder() default FieldResourceBinder.FieldBinderStringArray.class;
}


text:
typedef Vectormath::Aos::Vector4 vmVector4;

// reference code for testing purposes
ATTRIBUTE_ALIGNED16(class)
Quat_ref
{
	float mX;
	float mY;
	float mZ;
	float mW;

public:
	// Default constructor; does no initialization
	//
	inline Quat_ref(){};

	// Copy a quaternion
	//
	inline Quat_ref(const Quat_ref &quat);

	// Construct a quaternion from x, y, z, and w elements
	//
	inline Quat_ref(float x, float y, float z, float w);

	// Construct a quaternion from a 3-D vector and a scalar
	//
	inline Quat_ref(const vmVector3 &xyz, float w);

	// Copy elements from a 4-D vector into a quaternion
	//
	explicit inline Quat_ref(const vmVector4 &vec);

	// Convert a rotation matrix to a unit-length quaternion
	//
	explicit inline Quat_ref(const vmMatrix3 &rotMat);

	// Set all elements of a quaternion to the same scalar value
	//
	explicit inline Quat_ref(float scalar);

	// Assign one quaternion to another
	//
	inline Quat_ref &operator=(const Quat_ref &quat);

	// Set the x, y, and z elements of a quaternion
	// NOTE:
	// This function does not change the w element.
	//
	inline Quat_ref &setXYZ(const vmVector3 &vec);

	// Get the x, y, and z elements of a quaternion
	//
	inline const vmVector3 getXYZ() const;

	// Set the x element of a quaternion
	//
	inline Quat_ref &setX(float x);

	// Set the y element of a quaternion
	//
	inline Quat_ref &setY(float y);

	// Set the z element of a quaternion
	//
	inline Quat_ref &setZ(float z);

	// Set the w element of a quaternion
	//
	inline Quat_ref &setW(float w);

	// Get the x element of a quaternion
	//
	inline float getX() const;

	// Get the y element of a quaternion
	//
	inline float getY() const;

	// Get the z element of a quaternion
	//
	inline float getZ() const;

	// Get the w element of a quaternion
	//
	inline float getW() const;

	// Set an x, y, z, or w element of a quaternion by index
	//
	inline Quat_ref &setElem(int idx, float value);

	// Get an x, y, z, or w element of a quaternion by index
	//
	inline float getElem(int idx) const;

	// Subscripting operator to set or get an element
	//
	inline float &operator[](int idx);

	// Subscripting operator to get an element
	//
	inline float operator[](int idx) const;

	// Add two quaternions
	//
	inline const Quat_ref operator+(const Quat_ref &quat) const;

	// Subtract a quaternion from another quaternion
	//
	inline const Quat_ref operator-(const Quat_ref &quat) const;

	// Multiply two quaternions
	//
	inline const Quat_ref operator*(const Quat_ref &quat) const;

	// Multiply a quaternion by a scalar
	//
	inline const Quat_ref operator*(float scalar) const;

	// Divide a quaternion by a scalar
	//
	inline const Quat_ref operator/(float scalar) const;

	// Perform compound assignment and addition with a quaternion
	//
	inline Quat_ref &operator+=(const Quat_ref &quat);

	// Perform compound assignment and subtraction by a quaternion
	//
	inline Quat_ref &operator-=(const Quat_ref &quat);

	// Perform compound assignment and multiplication by a quaternion
	//
	inline Quat_ref &operator*=(const Quat_ref &quat);

	// Perform compound assignment and multiplication by a scalar
	//
	inline Quat_ref &operator*=(float scalar);

	// Perform compound assignment and division by a scalar
	//
	inline Quat_ref &operator/=(float scalar);

	// Negate all elements of a quaternion
	//
	inline const Quat_ref operator-() const;

	// Construct an identity quaternion
	//
	static inline const Quat_ref identity();

	// Construct a quaternion to rotate between two unit-length 3-D vectors
	// NOTE:
	// The result is unpredictable if unitVec0 and unitVec1 point in opposite directions.
	//
	static inline const Quat_ref rotation(const vmVector3 &unitVec0, const vmVector3 &unitVec1);

	// Construct a quaternion to rotate around a unit-length 3-D vector
	//
	static inline const Quat_ref rotation(float radians, const vmVector3 &unitVec);

	// Construct a quaternion to rotate around the x axis
	//
	static inline const Quat_ref rotationX(float radians);

	// Construct a quaternion to rotate around the y axis
	//
	static inline const Quat_ref rotationY(float radians);

	// Construct a quaternion to rotate around the z axis
	//
	static inline const Quat_ref rotationZ(float radians);
};

inline Quat_ref::Quat_ref(const Quat_ref &quat)
{
	mX = quat.mX;
	mY = quat.mY;
	mZ = quat.mZ;
	mW = quat.mW;
}

inline Quat_ref::Quat_ref(float _x, float _y, float _z, float _w)
{
	mX = _x;
	mY = _y;
	mZ = _z;
	mW = _w;
}

inline Quat_ref::Quat_ref(const vmVector3 &xyz, float _w)
{
	this->setXYZ(xyz);
	this->setW(_w);
}

inline Quat_ref::Quat_ref(const vmVector4 &vec)
{
	mX = vec.getX();
	mY = vec.getY();
	mZ = vec.getZ();
	mW = vec.getW();
}

inline Quat_ref::Quat_ref(float scalar)
{
	mX = scalar;
	mY = scalar;
	mZ = scalar;
	mW = scalar;
}

inline const Quat_ref Quat_ref::identity()
{
	return Quat_ref(0.0f, 0.0f, 0.0f, 1.0f);
}

inline void loadXYZW_ref(Quat_ref &quat, const float *fptr)
{
	quat = Quat_ref(fptr[0], fptr[1], fptr[2], fptr[3]);
}

inline void storeXYZW_ref(const Quat_ref &quat, float *fptr)
{
	fptr[0] = quat.getX();
	fptr[1] = quat.getY();
	fptr[2] = quat.getZ();
	fptr[3] = quat.getW();
}

inline Quat_ref &Quat_ref::operator=(const Quat_ref &quat)
{
	mX = quat.mX;
	mY = quat.mY;
	mZ = quat.mZ;
	mW = quat.mW;
	return *this;
}

inline Quat_ref &Quat_ref::setXYZ(const vmVector3 &vec)
{
	mX = vec.getX();
	mY = vec.getY();
	mZ = vec.getZ();
	return *this;
}

inline const vmVector3 Quat_ref::getXYZ() const
{
	return vmVector3(mX, mY, mZ);
}

inline Quat_ref &Quat_ref::setX(float _x)
{
	mX = _x;
	return *this;
}

inline float Quat_ref::getX() const
{
	return mX;
}

inline Quat_ref &Quat_ref::setY(float _y)
{
	mY = _y;
	return *this;
}

inline float Quat_ref::getY() const
{
	return mY;
}

inline Quat_ref &Quat_ref::setZ(float _z)
{
	mZ = _z;
	return *this;
}

inline float Quat_ref::getZ() const
{
	return mZ;
}

inline Quat_ref &Quat_ref::setW(float _w)
{
	mW = _w;
	return *this;
}

inline float Quat_ref::getW() const
{
	return mW;
}

inline Quat_ref &Quat_ref::setElem(int idx, float value)
{
	*(&mX + idx) = value;
	return *this;
}

inline float Quat_ref::getElem(int idx) const
{
	return *(&mX + idx);
}

inline float &Quat_ref::operator[](int idx)
{
	return *(&mX + idx);
}

inline float Quat_ref::operator[](int idx) const
{
	return *(&mX + idx);
}

inline const Quat_ref Quat_ref::operator+(const Quat_ref &quat) const
{
	return Quat_ref(
		(mX + quat.mX),
		(mY + quat.mY),
		(mZ + quat.mZ),
		(mW + quat.mW));
}

inline const Quat_ref Quat_ref::operator-(const Quat_ref &quat) const
{
	return Quat_ref(
		(mX - quat.mX),
		(mY - quat.mY),
		(mZ - quat.mZ),
		(mW - quat.mW));
}

inline const Quat_ref Quat_ref::operator*(float scalar) const
{
	return Quat_ref(
		(mX * scalar),
		(mY * scalar),
		(mZ * scalar),
		(mW * scalar));
}

inline Quat_ref &Quat_ref::operator+=(const Quat_ref &quat)
{
	*this = *this + quat;
	return *this;
}

inline Quat_ref &Quat_ref::operator-=(const Quat_ref &quat)
{
	*this = *this - quat;
	return *this;
}

inline Quat_ref &Quat_ref::operator*=(float scalar)
{
	*this = *this * scalar;
	return *this;
}

inline const Quat_ref Quat_ref::operator/(float scalar) const
{
	return Quat_ref(
		(mX / scalar),
		(mY / scalar),
		(mZ / scalar),
		(mW / scalar));
}

inline Quat_ref &Quat_ref::operator/=(float scalar)
{
	*this = *this / scalar;
	return *this;
}

inline const Quat_ref Quat_ref::operator-() const
{
	return Quat_ref(
		-mX,
		-mY,
		-mZ,
		-mW);
}

inline const Quat_ref operator*(float scalar, const Quat_ref &quat)
{
	return quat * scalar;
}

inline float dot(const Quat_ref &quat0, const Quat_ref &quat1)
{
	float result;
	result = (quat0.getX() * quat1.getX());
	result = (result + (quat0.getY() * quat1.getY()));
	result = (result + (quat0.getZ() * quat1.getZ()));
	result = (result + (quat0.getW() * quat1.getW()));
	return result;
}

inline const Quat_ref lerp(float t, const Quat_ref &quat0, const Quat_ref &quat1)
{
	return (quat0 + ((quat1 - quat0) * t));
}

inline const Quat_ref slerp(float t, const Quat_ref &unitQuat0, const Quat_ref &unitQuat1)
{
	Quat_ref start;
	float recipSinAngle, scale0, scale1, cosAngle, angle;
	cosAngle = dot(unitQuat0, unitQuat1);
	if (cosAngle < 0.0f)
	{
		cosAngle = -cosAngle;
		start = (-unitQuat0);
	}
	else
	{
		start = unitQuat0;
	}
	if (cosAngle < _VECTORMATH_SLERP_TOL)
	{
		angle = acosf(cosAngle);
		recipSinAngle = (1.0f / sinf(angle));
		scale0 = (sinf(((1.0f - t) * angle)) * recipSinAngle);
		scale1 = (sinf((t * angle)) * recipSinAngle);
	}
	else
	{
		scale0 = (1.0f - t);
		scale1 = t;
	}
	return ((start * scale0) + (unitQuat1 * scale1));
}

inline const Quat_ref squad(float t, const Quat_ref &unitQuat0, const Quat_ref &unitQuat1, const Quat_ref &unitQuat2, const Quat_ref &unitQuat3)
{
	Quat_ref tmp0, tmp1;
	tmp0 = slerp(t, unitQuat0, unitQuat3);
	tmp1 = slerp(t, unitQuat1, unitQuat2);
	return slerp(((2.0f * t) * (1.0f - t)), tmp0, tmp1);
}

inline float norm(const Quat_ref &quat)
{
	float result;
	result = (quat.getX() * quat.getX());
	result = (result + (quat.getY() * quat.getY()));
	result = (result + (quat.getZ() * quat.getZ()));
	result = (result + (quat.getW() * quat.getW()));
	return result;
}

inline float length(const Quat_ref &quat)
{
	return ::sqrtf(norm(quat));
}

inline const Quat_ref normalize(const Quat_ref &quat)
{
	float lenSqr, lenInv;
	lenSqr = norm(quat);
	lenInv = (1.0f / sqrtf(lenSqr));
	return Quat_ref(
		(quat.getX() * lenInv),
		(quat.getY() * lenInv),
		(quat.getZ() * lenInv),
		(quat.getW() * lenInv));
}

inline const Quat_ref Quat_ref::rotation(const vmVector3 &unitVec0, const vmVector3 &unitVec1)
{
	float cosHalfAngleX2, recipCosHalfAngleX2;
	cosHalfAngleX2 = sqrtf((2.0f * (1.0f + dot(unitVec0, unitVec1))));
	recipCosHalfAngleX2 = (1.0f / cosHalfAngleX2);
	return Quat_ref((cross(unitVec0, unitVec1) * recipCosHalfAngleX2), (cosHalfAngleX2 * 0.5f));
}

inline const Quat_ref Quat_ref::rotation(float radians, const vmVector3 &unitVec)
{
	float s, c, angle;
	angle = (radians * 0.5f);
	s = sinf(angle);
	c = cosf(angle);
	return Quat_ref((unitVec * s), c);
}

inline const Quat_ref Quat_ref::rotationX(float radians)
{
	float s, c, angle;
	angle = (radians * 0.5f);
	s = sinf(angle);
	c = cosf(angle);
	return Quat_ref(s, 0.0f, 0.0f, c);
}

inline const Quat_ref Quat_ref::rotationY(float radians)
{
	float s, c, angle;
	angle = (radians * 0.5f);
	s = sinf(angle);
	c = cosf(angle);
	return Quat_ref(0.0f, s, 0.0f, c);
}

inline const Quat_ref Quat_ref::rotationZ(float radians)
{
	float s, c, angle;
	angle = (radians * 0.5f);
	s = sinf(angle);
	c = cosf(angle);
	return Quat_ref(0.0f, 0.0f, s, c);
}

inline const Quat_ref Quat_ref::operator*(const Quat_ref &quat) const
{
	return Quat_ref(
		((((mW * quat.mX) + (mX * quat.mW)) + (mY * quat.mZ)) - (mZ * quat.mY)),
		((((mW * quat.mY) + (mY * quat.mW)) + (mZ * quat.mX)) - (mX * quat.mZ)),
		((((mW * quat.mZ) + (mZ * quat.mW)) + (mX * quat.mY)) - (mY * quat.mX)),
		((((mW * quat.mW) - (mX * quat.mX)) - (mY * quat.mY)) - (mZ * quat.mZ)));
}

inline Quat_ref &Quat_ref::operator*=(const Quat_ref &quat)
{
	*this = *this * quat;
	return *this;
}

inline const vmVector3 rotate(const Quat_ref &quat, const vmVector3 &vec)
{
	float tmpX, tmpY, tmpZ, tmpW;
	tmpX = (((quat.getW() * vec.getX()) + (quat.getY() * vec.getZ())) - (quat.getZ() * vec.getY()));
	tmpY = (((quat.getW() * vec.getY()) + (quat.getZ() * vec.getX())) - (quat.getX() * vec.getZ()));
	tmpZ = (((quat.getW() * vec.getZ()) + (quat.getX() * vec.getY())) - (quat.getY() * vec.getX()));
	tmpW = (((quat.getX() * vec.getX()) + (quat.getY() * vec.getY())) + (quat.getZ() * vec.getZ()));
	return vmVector3(
		((((tmpW * quat.getX()) + (tmpX * quat.getW())) - (tmpY * quat.getZ())) + (tmpZ * quat.getY())),
		((((tmpW * quat.getY()) + (tmpY * quat.getW())) - (tmpZ * quat.getX())) + (tmpX * quat.getZ())),
		((((tmpW * quat.getZ()) + (tmpZ * quat.getW())) - (tmpX * quat.getY())) + (tmpY * quat.getX())));
}

inline const Quat_ref conj(const Quat_ref &quat)
{
	return Quat_ref(-quat.getX(), -quat.getY(), -quat.getZ(), quat.getW());
}

inline const Quat_ref select(const Quat_ref &quat0, const Quat_ref &quat1, bool select1)
{
	return Quat_ref(
		(select1) ? quat1.getX() : quat0.getX(),
		(select1) ? quat1.getY() : quat0.getY(),
		(select1) ? quat1.getZ() : quat0.getZ(),
		(select1) ? quat1.getW() : quat0.getW());
}

#define LOOPCOUNT 1000
#define NUM_CYCLES 10000
#define DATA_SIZE 1024

int Test_quat_aos_neon(void)
{
	return 0;
}

#endif


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <io.vov.vitamio.widget.VideoView
        android:id="@+id/videoSurface"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>


text:
require 'infrataster/resources/mysql_query_resource'
require 'infrataster/contexts/mysql_query_context'
require 'infrataster/helpers/mysql_resource_helper'