diff options
| author | bnewbold <bnewbold@manus.(none)> | 2007-07-11 05:35:39 -0400 | 
|---|---|---|
| committer | bnewbold <bnewbold@manus.(none)> | 2007-07-11 05:35:39 -0400 | 
| commit | e152d2f2d1e257b1ec51adb3640e350207fda77d (patch) | |
| tree | 0d459576de630394d810d10a48c30bebbf0ca336 | |
| download | equator-e152d2f2d1e257b1ec51adb3640e350207fda77d.tar.gz equator-e152d2f2d1e257b1ec51adb3640e350207fda77d.zip | |
skeletal start, basic recovery of lost progress
| -rw-r--r-- | __init__.py | 0 | ||||
| -rw-r--r-- | equations/__init__.py | 0 | ||||
| -rw-r--r-- | equations/models.py | 3 | ||||
| -rw-r--r-- | equations/views.py | 1 | ||||
| -rwxr-xr-x | manage.py | 11 | ||||
| -rw-r--r-- | static/default.css | 63 | ||||
| -rw-r--r-- | static/prototype.js | 3277 | ||||
| -rw-r--r-- | templates/base.html | 28 | ||||
| -rw-r--r-- | templates/flatpages/default.html | 6 | ||||
| -rw-r--r-- | templates/go.html | 90 | ||||
| -rw-r--r-- | urls.py | 9 | 
11 files changed, 3488 insertions, 0 deletions
| diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/__init__.py diff --git a/equations/__init__.py b/equations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/equations/__init__.py diff --git a/equations/models.py b/equations/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/equations/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/equations/views.py b/equations/views.py new file mode 100644 index 0000000..60f00ef --- /dev/null +++ b/equations/views.py @@ -0,0 +1 @@ +# Create your views here. diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..5e78ea9 --- /dev/null +++ b/manage.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +try: +    import settings # Assumed to be in the same directory. +except ImportError: +    import sys +    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) +    sys.exit(1) + +if __name__ == "__main__": +    execute_manager(settings) diff --git a/static/default.css b/static/default.css new file mode 100644 index 0000000..12f99d1 --- /dev/null +++ b/static/default.css @@ -0,0 +1,63 @@ +body { +    padding:0px;  +    margin:0px; +    background-color:gray; +    font-family: sans; } + +.main { +    width:651px;  +    position:absolute;  +    top:20px; +    left:50%; +    margin-left:-335px; +    background-color:white; +    padding: 10px; +    padding-bottom:10px; } + +.section { +    font-size:22px;  +    width:94%;  +    font-weight: bold; +    margin-right:2%; +    margin-left: 2%; +    padding-left: 2%; +    border-bottom: 1px solid black; +    margin-top:18px; } + +hr { +    height:1px;  +    border:none;  +    background-color:gray; +    width:80%; } + +p { +    margin-left: 2%; +    margin-right: 2%; +} + +.footer { +    color: gray; +    font-style:italic;  +    font-size:11px;  +    margin-right:10%; +    text-align:center;  +    float:right;  +    width:80%; } + +.caption { +    color: black; +    font-style:italic;  +    font-weight: bold; +    font-size:13px;  +    width:80%; } + +a.imglink { +    border: none; } + +img { +    border: none; } + +.image { +    float: middle; +    text-align: center; +    width: 100%; } diff --git a/static/prototype.js b/static/prototype.js new file mode 100644 index 0000000..a3f21ac --- /dev/null +++ b/static/prototype.js @@ -0,0 +1,3277 @@ +/*  Prototype JavaScript framework, version 1.5.1.1 + *  (c) 2005-2007 Sam Stephenson + * + *  Prototype is freely distributable under the terms of an MIT-style license. + *  For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { +  Version: '1.5.1.1', + +  Browser: { +    IE:     !!(window.attachEvent && !window.opera), +    Opera:  !!window.opera, +    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, +    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 +  }, + +  BrowserFeatures: { +    XPath: !!document.evaluate, +    ElementExtensions: !!window.HTMLElement, +    SpecificElementExtensions: +      (document.createElement('div').__proto__ !== +       document.createElement('form').__proto__) +  }, + +  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', +  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + +  emptyFunction: function() { }, +  K: function(x) { return x } +} + +var Class = { +  create: function() { +    return function() { +      this.initialize.apply(this, arguments); +    } +  } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { +  for (var property in source) { +    destination[property] = source[property]; +  } +  return destination; +} + +Object.extend(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; +    } +  }, + +  toJSON: function(object) { +    var type = typeof object; +    switch(type) { +      case 'undefined': +      case 'function': +      case 'unknown': return; +      case 'boolean': return object.toString(); +    } +    if (object === null) return 'null'; +    if (object.toJSON) return object.toJSON(); +    if (object.ownerDocument === document) return; +    var results = []; +    for (var property in object) { +      var value = Object.toJSON(object[property]); +      if (value !== undefined) +        results.push(property.toJSON() + ': ' + value); +    } +    return '{' + results.join(', ') + '}'; +  }, + +  keys: function(object) { +    var keys = []; +    for (var property in object) +      keys.push(property); +    return keys; +  }, + +  values: function(object) { +    var values = []; +    for (var property in object) +      values.push(object[property]); +    return values; +  }, + +  clone: function(object) { +    return Object.extend({}, object); +  } +}); + +Function.prototype.bind = function() { +  var __method = this, args = $A(arguments), object = args.shift(); +  return function() { +    return __method.apply(object, args.concat($A(arguments))); +  } +} + +Function.prototype.bindAsEventListener = function(object) { +  var __method = this, args = $A(arguments), object = args.shift(); +  return function(event) { +    return __method.apply(object, [event || window.event].concat(args)); +  } +} + +Object.extend(Number.prototype, { +  toColorPart: function() { +    return this.toPaddedString(2, 16); +  }, + +  succ: function() { +    return this + 1; +  }, + +  times: function(iterator) { +    $R(0, this, true).each(iterator); +    return this; +  }, + +  toPaddedString: function(length, radix) { +    var string = this.toString(radix || 10); +    return '0'.times(length - string.length) + string; +  }, + +  toJSON: function() { +    return isFinite(this) ? this.toString() : 'null'; +  } +}); + +Date.prototype.toJSON = function() { +  return '"' + this.getFullYear() + '-' + +    (this.getMonth() + 1).toPaddedString(2) + '-' + +    this.getDate().toPaddedString(2) + 'T' + +    this.getHours().toPaddedString(2) + ':' + +    this.getMinutes().toPaddedString(2) + ':' + +    this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { +  these: function() { +    var returnValue; + +    for (var i = 0, length = arguments.length; i < 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() { +    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); +  }, + +  stop: function() { +    if (!this.timer) return; +    clearInterval(this.timer); +    this.timer = null; +  }, + +  onTimerEvent: function() { +    if (!this.currentlyExecuting) { +      try { +        this.currentlyExecuting = true; +        this.callback(this); +      } finally { +        this.currentlyExecuting = false; +      } +    } +  } +} +Object.extend(String, { +  interpret: function(value) { +    return value == null ? '' : String(value); +  }, +  specialChar: { +    '\b': '\\b', +    '\t': '\\t', +    '\n': '\\n', +    '\f': '\\f', +    '\r': '\\r', +    '\\': '\\\\' +  } +}); + +Object.extend(String.prototype, { +  gsub: function(pattern, replacement) { +    var result = '', source = this, match; +    replacement = arguments.callee.prepareReplacement(replacement); + +    while (source.length > 0) { +      if (match = source.match(pattern)) { +        result += source.slice(0, match.index); +        result += String.interpret(replacement(match)); +        source  = source.slice(match.index + match[0].length); +      } else { +        result += source, source = ''; +      } +    } +    return result; +  }, + +  sub: function(pattern, replacement, count) { +    replacement = this.gsub.prepareReplacement(replacement); +    count = count === undefined ? 1 : count; + +    return this.gsub(pattern, function(match) { +      if (--count < 0) return match[0]; +      return replacement(match); +    }); +  }, + +  scan: function(pattern, iterator) { +    this.gsub(pattern, iterator); +    return this; +  }, + +  truncate: function(length, truncation) { +    length = length || 30; +    truncation = truncation === undefined ? '...' : truncation; +    return this.length > length ? +      this.slice(0, length - truncation.length) + truncation : this; +  }, + +  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(function(script) { return eval(script) }); +  }, + +  escapeHTML: function() { +    var self = arguments.callee; +    self.text.data = this; +    return self.div.innerHTML; +  }, + +  unescapeHTML: function() { +    var div = document.createElement('div'); +    div.innerHTML = this.stripTags(); +    return div.childNodes[0] ? (div.childNodes.length > 1 ? +      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : +      div.childNodes[0].nodeValue) : ''; +  }, + +  toQueryParams: function(separator) { +    var match = this.strip().match(/([^?#]*)(#.*)?$/); +    if (!match) return {}; + +    return match[1].split(separator || '&').inject({}, function(hash, pair) { +      if ((pair = pair.split('='))[0]) { +        var key = decodeURIComponent(pair.shift()); +        var value = pair.length > 1 ? pair.join('=') : pair[0]; +        if (value != undefined) value = decodeURIComponent(value); + +        if (key in hash) { +          if (hash[key].constructor != Array) hash[key] = [hash[key]]; +          hash[key].push(value); +        } +        else hash[key] = value; +      } +      return hash; +    }); +  }, + +  toArray: function() { +    return this.split(''); +  }, + +  succ: function() { +    return this.slice(0, this.length - 1) + +      String.fromCharCode(this.charCodeAt(this.length - 1) + 1); +  }, + +  times: function(count) { +    var result = ''; +    for (var i = 0; i < count; i++) result += this; +    return result; +  }, + +  camelize: function() { +    var parts = this.split('-'), len = parts.length; +    if (len == 1) return parts[0]; + +    var camelized = this.charAt(0) == '-' +      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) +      : parts[0]; + +    for (var i = 1; i < len; i++) +      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + +    return camelized; +  }, + +  capitalize: function() { +    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); +  }, + +  underscore: function() { +    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); +  }, + +  dasherize: function() { +    return this.gsub(/_/,'-'); +  }, + +  inspect: function(useDoubleQuotes) { +    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { +      var character = String.specialChar[match[0]]; +      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); +    }); +    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; +    return "'" + escapedString.replace(/'/g, '\\\'') + "'"; +  }, + +  toJSON: function() { +    return this.inspect(true); +  }, + +  unfilterJSON: function(filter) { +    return this.sub(filter || Prototype.JSONFilter, '#{1}'); +  }, + +  isJSON: function() { +    var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); +    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); +  }, + +  evalJSON: function(sanitize) { +    var json = this.unfilterJSON(); +    try { +      if (!sanitize || json.isJSON()) return eval('(' + json + ')'); +    } catch (e) { } +    throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); +  }, + +  include: function(pattern) { +    return this.indexOf(pattern) > -1; +  }, + +  startsWith: function(pattern) { +    return this.indexOf(pattern) === 0; +  }, + +  endsWith: function(pattern) { +    var d = this.length - pattern.length; +    return d >= 0 && this.lastIndexOf(pattern) === d; +  }, + +  empty: function() { +    return this == ''; +  }, + +  blank: function() { +    return /^\s*$/.test(this); +  } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { +  escapeHTML: function() { +    return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); +  }, +  unescapeHTML: function() { +    return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); +  } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { +  if (typeof replacement == 'function') return replacement; +  var template = new Template(replacement); +  return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { +  div:  document.createElement('div'), +  text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { +  initialize: function(template, pattern) { +    this.template = template.toString(); +    this.pattern  = pattern || Template.Pattern; +  }, + +  evaluate: function(object) { +    return this.template.gsub(this.pattern, function(match) { +      var before = match[1]; +      if (before == '\\') return match[2]; +      return before + String.interpret(object[match[3]]); +    }); +  } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { +  each: function(iterator) { +    var index = 0; +    try { +      this._each(function(value) { +        iterator(value, index++); +      }); +    } catch (e) { +      if (e != $break) throw e; +    } +    return this; +  }, + +  eachSlice: function(number, iterator) { +    var index = -number, slices = [], array = this.toArray(); +    while ((index += number) < array.length) +      slices.push(array.slice(index, index+number)); +    return slices.map(iterator); +  }, + +  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 = false; +    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 || Prototype.K)(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; +  }, + +  inGroupsOf: function(number, fillWith) { +    fillWith = fillWith === undefined ? null : fillWith; +    return this.eachSlice(number, function(slice) { +      while(slice.length < number) slice.push(fillWith); +      return slice; +    }); +  }, + +  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.map(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 (result == undefined || value >= result) +        result = value; +    }); +    return result; +  }, + +  min: function(iterator) { +    var result; +    this.each(function(value, index) { +      value = (iterator || Prototype.K)(value, index); +      if (result == undefined || value < result) +        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.map(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.map(); +  }, + +  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) { +      return iterator(collections.pluck(index)); +    }); +  }, + +  size: function() { +    return this.toArray().length; +  }, + +  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) return []; +  if (iterable.toArray) { +    return iterable.toArray(); +  } else { +    var results = []; +    for (var i = 0, length = iterable.length; i < length; i++) +      results.push(iterable[i]); +    return results; +  } +} + +if (Prototype.Browser.WebKit) { +  $A = Array.from = function(iterable) { +    if (!iterable) return []; +    if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && +      iterable.toArray) { +      return iterable.toArray(); +    } else { +      var results = []; +      for (var i = 0, length = iterable.length; i < length; i++) +        results.push(iterable[i]); +      return results; +    } +  } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) +  Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { +  _each: function(iterator) { +    for (var i = 0, length = this.length; i < length; i++) +      iterator(this[i]); +  }, + +  clear: function() { +    this.length = 0; +    return this; +  }, + +  first: function() { +    return this[0]; +  }, + +  last: function() { +    return this[this.length - 1]; +  }, + +  compact: function() { +    return this.select(function(value) { +      return value != null; +    }); +  }, + +  flatten: function() { +    return this.inject([], function(array, value) { +      return array.concat(value && 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, length = this.length; i < length; i++) +      if (this[i] == object) return i; +    return -1; +  }, + +  reverse: function(inline) { +    return (inline !== false ? this : this.toArray())._reverse(); +  }, + +  reduce: function() { +    return this.length > 1 ? this : this[0]; +  }, + +  uniq: function(sorted) { +    return this.inject([], function(array, value, index) { +      if (0 == index || (sorted ? array.last() != value : !array.include(value))) +        array.push(value); +      return array; +    }); +  }, + +  clone: function() { +    return [].concat(this); +  }, + +  size: function() { +    return this.length; +  }, + +  inspect: function() { +    return '[' + this.map(Object.inspect).join(', ') + ']'; +  }, + +  toJSON: function() { +    var results = []; +    this.each(function(object) { +      var value = Object.toJSON(object); +      if (value !== undefined) results.push(value); +    }); +    return '[' + results.join(', ') + ']'; +  } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { +  string = string.strip(); +  return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ +  Array.prototype.concat = function() { +    var array = []; +    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); +    for (var i = 0, length = arguments.length; i < length; i++) { +      if (arguments[i].constructor == Array) { +        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) +          array.push(arguments[i][j]); +      } else { +        array.push(arguments[i]); +      } +    } +    return array; +  } +} +var Hash = function(object) { +  if (object instanceof Hash) this.merge(object); +  else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { +  toQueryString: function(obj) { +    var parts = []; +    parts.add = arguments.callee.addPair; + +    this.prototype._each.call(obj, function(pair) { +      if (!pair.key) return; +      var value = pair.value; + +      if (value && typeof value == 'object') { +        if (value.constructor == Array) value.each(function(value) { +          parts.add(pair.key, value); +        }); +        return; +      } +      parts.add(pair.key, value); +    }); + +    return parts.join('&'); +  }, + +  toJSON: function(object) { +    var results = []; +    this.prototype._each.call(object, function(pair) { +      var value = Object.toJSON(pair.value); +      if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); +    }); +    return '{' + results.join(', ') + '}'; +  } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { +  key = encodeURIComponent(key); +  if (value === undefined) this.push(key); +  else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { +  _each: function(iterator) { +    for (var key in this) { +      var value = this[key]; +      if (value && value == Hash.prototype[key]) 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(this, function(mergedHash, pair) { +      mergedHash[pair.key] = pair.value; +      return mergedHash; +    }); +  }, + +  remove: function() { +    var result; +    for(var i = 0, length = arguments.length; i < length; i++) { +      var value = this[arguments[i]]; +      if (value !== undefined){ +        if (result === undefined) result = value; +        else { +          if (result.constructor != Array) result = [result]; +          result.push(value) +        } +      } +      delete this[arguments[i]]; +    } +    return result; +  }, + +  toQueryString: function() { +    return Hash.toQueryString(this); +  }, + +  inspect: function() { +    return '#<Hash:{' + this.map(function(pair) { +      return pair.map(Object.inspect).join(': '); +    }).join(', ') + '}>'; +  }, + +  toJSON: function() { +    return Hash.toJSON(this); +  } +}); + +function $H(object) { +  if (object instanceof Hash) return object; +  return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { +  var i = 0, Test = function(value) { this.key = value }; +  Test.prototype.key = 'foo'; +  for (var property in new Test('bar')) i++; +  return i > 1; +}()) Hash.prototype._each = function(iterator) { +  var cache = []; +  for (var key in this) { +    var value = this[key]; +    if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; +    cache.push(key); +    var pair = [key, value]; +    pair.key = key; +    pair.value = value; +    iterator(pair); +  } +}; +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; +    while (this.include(value)) { +      iterator(value); +      value = value.succ(); +    } +  }, + +  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 XMLHttpRequest()}, +      function() {return new ActiveXObject('Msxml2.XMLHTTP')}, +      function() {return new ActiveXObject('Microsoft.XMLHTTP')} +    ) || false; +  }, + +  activeRequestCount: 0 +} + +Ajax.Responders = { +  responders: [], + +  _each: function(iterator) { +    this.responders._each(iterator); +  }, + +  register: function(responder) { +    if (!this.include(responder)) +      this.responders.push(responder); +  }, + +  unregister: function(responder) { +    this.responders = this.responders.without(responder); +  }, + +  dispatch: function(callback, request, transport, json) { +    this.each(function(responder) { +      if (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, +      contentType:  'application/x-www-form-urlencoded', +      encoding:     'UTF-8', +      parameters:   '' +    } +    Object.extend(this.options, options || {}); + +    this.options.method = this.options.method.toLowerCase(); +    if (typeof this.options.parameters == 'string') +      this.options.parameters = this.options.parameters.toQueryParams(); +  } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = +  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { +  _complete: false, + +  initialize: function(url, options) { +    this.transport = Ajax.getTransport(); +    this.setOptions(options); +    this.request(url); +  }, + +  request: function(url) { +    this.url = url; +    this.method = this.options.method; +    var params = Object.clone(this.options.parameters); + +    if (!['get', 'post'].include(this.method)) { +      // simulate other verbs over post +      params['_method'] = this.method; +      this.method = 'post'; +    } + +    this.parameters = params; + +    if (params = Hash.toQueryString(params)) { +      // when GET, append parameters to URL +      if (this.method == 'get') +        this.url += (this.url.include('?') ? '&' : '?') + params; +      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) +        params += '&_='; +    } + +    try { +      if (this.options.onCreate) this.options.onCreate(this.transport); +      Ajax.Responders.dispatch('onCreate', this, this.transport); + +      this.transport.open(this.method.toUpperCase(), this.url, +        this.options.asynchronous); + +      if (this.options.asynchronous) +        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + +      this.transport.onreadystatechange = this.onStateChange.bind(this); +      this.setRequestHeaders(); + +      this.body = this.method == 'post' ? (this.options.postBody || params) : null; +      this.transport.send(this.body); + +      /* Force Firefox to handle ready state 4 for synchronous requests */ +      if (!this.options.asynchronous && this.transport.overrideMimeType) +        this.onStateChange(); + +    } +    catch (e) { +      this.dispatchException(e); +    } +  }, + +  onStateChange: function() { +    var readyState = this.transport.readyState; +    if (readyState > 1 && !((readyState == 4) && this._complete)) +      this.respondToReadyState(this.transport.readyState); +  }, + +  setRequestHeaders: function() { +    var headers = { +      'X-Requested-With': 'XMLHttpRequest', +      'X-Prototype-Version': Prototype.Version, +      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' +    }; + +    if (this.method == 'post') { +      headers['Content-type'] = this.options.contentType + +        (this.options.encoding ? '; charset=' + this.options.encoding : ''); + +      /* 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'; +    } + +    // user-defined headers +    if (typeof this.options.requestHeaders == 'object') { +      var extras = this.options.requestHeaders; + +      if (typeof extras.push == 'function') +        for (var i = 0, length = extras.length; i < length; i += 2) +          headers[extras[i]] = extras[i+1]; +      else +        $H(extras).each(function(pair) { headers[pair.key] = pair.value }); +    } + +    for (var name in headers) +      this.transport.setRequestHeader(name, headers[name]); +  }, + +  success: function() { +    return !this.transport.status +        || (this.transport.status >= 200 && this.transport.status < 300); +  }, + +  respondToReadyState: function(readyState) { +    var state = Ajax.Request.Events[readyState]; +    var transport = this.transport, json = this.evalJSON(); + +    if (state == 'Complete') { +      try { +        this._complete = true; +        (this.options['on' + this.transport.status] +         || this.options['on' + (this.success() ? 'Success' : 'Failure')] +         || Prototype.emptyFunction)(transport, json); +      } catch (e) { +        this.dispatchException(e); +      } + +      var contentType = this.getHeader('Content-type'); +      if (contentType && contentType.strip(). +        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) +          this.evalResponse(); +    } + +    try { +      (this.options['on' + state] || Prototype.emptyFunction)(transport, json); +      Ajax.Responders.dispatch('on' + state, this, transport, json); +    } catch (e) { +      this.dispatchException(e); +    } + +    if (state == 'Complete') { +      // avoid memory leak in MSIE: clean up +      this.transport.onreadystatechange = Prototype.emptyFunction; +    } +  }, + +  getHeader: function(name) { +    try { +      return this.transport.getResponseHeader(name); +    } catch (e) { return null } +  }, + +  evalJSON: function() { +    try { +      var json = this.getHeader('X-JSON'); +      return json ? json.evalJSON() : null; +    } catch (e) { return null } +  }, + +  evalResponse: function() { +    try { +      return eval((this.transport.responseText || '').unfilterJSON()); +    } catch (e) { +      this.dispatchException(e); +    } +  }, + +  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.container = { +      success: (container.success || 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, param) { +      this.updateContent(); +      onComplete(transport, param); +    }).bind(this); + +    this.request(url); +  }, + +  updateContent: function() { +    var receiver = this.container[this.success() ? 'success' : 'failure']; +    var response = this.transport.responseText; + +    if (!this.options.evalScripts) response = response.stripScripts(); + +    if (receiver = $(receiver)) { +      if (this.options.insertion) +        new this.options.insertion(receiver, response); +      else +        receiver.update(response); +    } + +    if (this.success()) { +      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.options.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); +  } +}); +function $(element) { +  if (arguments.length > 1) { +    for (var i = 0, elements = [], length = arguments.length; i < length; i++) +      elements.push($(arguments[i])); +    return elements; +  } +  if (typeof element == 'string') +    element = document.getElementById(element); +  return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { +  document._getElementsByXPath = function(expression, parentElement) { +    var results = []; +    var query = document.evaluate(expression, $(parentElement) || document, +      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); +    for (var i = 0, length = query.snapshotLength; i < length; i++) +      results.push(query.snapshotItem(i)); +    return results; +  }; + +  document.getElementsByClassName = function(className, parentElement) { +    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; +    return document._getElementsByXPath(q, parentElement); +  } + +} else document.getElementsByClassName = function(className, parentElement) { +  var children = ($(parentElement) || document.body).getElementsByTagName('*'); +  var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)"); +  for (var i = 0, length = children.length; i < length; i++) { +    child = children[i]; +    var elementClassName = child.className; +    if (elementClassName.length == 0) continue; +    if (elementClassName == className || elementClassName.match(pattern)) +      elements.push(Element.extend(child)); +  } +  return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { +  var F = Prototype.BrowserFeatures; +  if (!element || !element.tagName || element.nodeType == 3 || +   element._extended || F.SpecificElementExtensions || element == window) +    return element; + +  var methods = {}, tagName = element.tagName, cache = Element.extend.cache, +   T = Element.Methods.ByTag; + +  // extend methods for all tags (Safari doesn't need this) +  if (!F.ElementExtensions) { +    Object.extend(methods, Element.Methods), +    Object.extend(methods, Element.Methods.Simulated); +  } + +  // extend methods for specific tags +  if (T[tagName]) Object.extend(methods, T[tagName]); + +  for (var property in methods) { +    var value = methods[property]; +    if (typeof value == 'function' && !(property in element)) +      element[property] = cache.findOrStore(value); +  } + +  element._extended = Prototype.emptyFunction; +  return element; +}; + +Element.extend.cache = { +  findOrStore: function(value) { +    return this[value] = this[value] || function() { +      return value.apply(null, [this].concat($A(arguments))); +    } +  } +}; + +Element.Methods = { +  visible: function(element) { +    return $(element).style.display != 'none'; +  }, + +  toggle: function(element) { +    element = $(element); +    Element[Element.visible(element) ? 'hide' : 'show'](element); +    return element; +  }, + +  hide: function(element) { +    $(element).style.display = 'none'; +    return element; +  }, + +  show: function(element) { +    $(element).style.display = ''; +    return element; +  }, + +  remove: function(element) { +    element = $(element); +    element.parentNode.removeChild(element); +    return element; +  }, + +  update: function(element, html) { +    html = typeof html == 'undefined' ? '' : html.toString(); +    $(element).innerHTML = html.stripScripts(); +    setTimeout(function() {html.evalScripts()}, 10); +    return element; +  }, + +  replace: function(element, html) { +    element = $(element); +    html = typeof html == 'undefined' ? '' : html.toString(); +    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); +    return element; +  }, + +  inspect: function(element) { +    element = $(element); +    var result = '<' + element.tagName.toLowerCase(); +    $H({'id': 'id', 'className': 'class'}).each(function(pair) { +      var property = pair.first(), attribute = pair.last(); +      var value = (element[property] || '').toString(); +      if (value) result += ' ' + attribute + '=' + value.inspect(true); +    }); +    return result + '>'; +  }, + +  recursivelyCollect: function(element, property) { +    element = $(element); +    var elements = []; +    while (element = element[property]) +      if (element.nodeType == 1) +        elements.push(Element.extend(element)); +    return elements; +  }, + +  ancestors: function(element) { +    return $(element).recursivelyCollect('parentNode'); +  }, + +  descendants: function(element) { +    return $A($(element).getElementsByTagName('*')).each(Element.extend); +  }, + +  firstDescendant: function(element) { +    element = $(element).firstChild; +    while (element && element.nodeType != 1) element = element.nextSibling; +    return $(element); +  }, + +  immediateDescendants: function(element) { +    if (!(element = $(element).firstChild)) return []; +    while (element && element.nodeType != 1) element = element.nextSibling; +    if (element) return [element].concat($(element).nextSiblings()); +    return []; +  }, + +  previousSiblings: function(element) { +    return $(element).recursivelyCollect('previousSibling'); +  }, + +  nextSiblings: function(element) { +    return $(element).recursivelyCollect('nextSibling'); +  }, + +  siblings: function(element) { +    element = $(element); +    return element.previousSiblings().reverse().concat(element.nextSiblings()); +  }, + +  match: function(element, selector) { +    if (typeof selector == 'string') +      selector = new Selector(selector); +    return selector.match($(element)); +  }, + +  up: function(element, expression, index) { +    element = $(element); +    if (arguments.length == 1) return $(element.parentNode); +    var ancestors = element.ancestors(); +    return expression ? Selector.findElement(ancestors, expression, index) : +      ancestors[index || 0]; +  }, + +  down: function(element, expression, index) { +    element = $(element); +    if (arguments.length == 1) return element.firstDescendant(); +    var descendants = element.descendants(); +    return expression ? Selector.findElement(descendants, expression, index) : +      descendants[index || 0]; +  }, + +  previous: function(element, expression, index) { +    element = $(element); +    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); +    var previousSiblings = element.previousSiblings(); +    return expression ? Selector.findElement(previousSiblings, expression, index) : +      previousSiblings[index || 0]; +  }, + +  next: function(element, expression, index) { +    element = $(element); +    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); +    var nextSiblings = element.nextSiblings(); +    return expression ? Selector.findElement(nextSiblings, expression, index) : +      nextSiblings[index || 0]; +  }, + +  getElementsBySelector: function() { +    var args = $A(arguments), element = $(args.shift()); +    return Selector.findChildElements(element, args); +  }, + +  getElementsByClassName: function(element, className) { +    return document.getElementsByClassName(className, element); +  }, + +  readAttribute: function(element, name) { +    element = $(element); +    if (Prototype.Browser.IE) { +      if (!element.attributes) return null; +      var t = Element._attributeTranslations; +      if (t.values[name]) return t.values[name](element, name); +      if (t.names[name])  name = t.names[name]; +      var attribute = element.attributes[name]; +      return attribute ? attribute.nodeValue : null; +    } +    return element.getAttribute(name); +  }, + +  getHeight: function(element) { +    return $(element).getDimensions().height; +  }, + +  getWidth: function(element) { +    return $(element).getDimensions().width; +  }, + +  classNames: function(element) { +    return new Element.ClassNames(element); +  }, + +  hasClassName: function(element, className) { +    if (!(element = $(element))) return; +    var elementClassName = element.className; +    if (elementClassName.length == 0) return false; +    if (elementClassName == className || +        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) +      return true; +    return false; +  }, + +  addClassName: function(element, className) { +    if (!(element = $(element))) return; +    Element.classNames(element).add(className); +    return element; +  }, + +  removeClassName: function(element, className) { +    if (!(element = $(element))) return; +    Element.classNames(element).remove(className); +    return element; +  }, + +  toggleClassName: function(element, className) { +    if (!(element = $(element))) return; +    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); +    return element; +  }, + +  observe: function() { +    Event.observe.apply(Event, arguments); +    return $A(arguments).first(); +  }, + +  stopObserving: function() { +    Event.stopObserving.apply(Event, arguments); +    return $A(arguments).first(); +  }, + +  // removes whitespace-only text node children +  cleanWhitespace: function(element) { +    element = $(element); +    var node = element.firstChild; +    while (node) { +      var nextNode = node.nextSibling; +      if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) +        element.removeChild(node); +      node = nextNode; +    } +    return element; +  }, + +  empty: function(element) { +    return $(element).innerHTML.blank(); +  }, + +  descendantOf: function(element, ancestor) { +    element = $(element), ancestor = $(ancestor); +    while (element = element.parentNode) +      if (element == ancestor) return true; +    return false; +  }, + +  scrollTo: function(element) { +    element = $(element); +    var pos = Position.cumulativeOffset(element); +    window.scrollTo(pos[0], pos[1]); +    return element; +  }, + +  getStyle: function(element, style) { +    element = $(element); +    style = style == 'float' ? 'cssFloat' : style.camelize(); +    var value = element.style[style]; +    if (!value) { +      var css = document.defaultView.getComputedStyle(element, null); +      value = css ? css[style] : null; +    } +    if (style == 'opacity') return value ? parseFloat(value) : 1.0; +    return value == 'auto' ? null : value; +  }, + +  getOpacity: function(element) { +    return $(element).getStyle('opacity'); +  }, + +  setStyle: function(element, styles, camelized) { +    element = $(element); +    var elementStyle = element.style; + +    for (var property in styles) +      if (property == 'opacity') element.setOpacity(styles[property]) +      else +        elementStyle[(property == 'float' || property == 'cssFloat') ? +          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : +          (camelized ? property : property.camelize())] = styles[property]; + +    return element; +  }, + +  setOpacity: function(element, value) { +    element = $(element); +    element.style.opacity = (value == 1 || value === '') ? '' : +      (value < 0.00001) ? 0 : value; +    return element; +  }, + +  getDimensions: function(element) { +    element = $(element); +    var display = $(element).getStyle('display'); +    if (display != 'none' && display != null) // Safari bug +      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; +    var originalDisplay = els.display; +    els.visibility = 'hidden'; +    els.position = 'absolute'; +    els.display = 'block'; +    var originalWidth = element.clientWidth; +    var originalHeight = element.clientHeight; +    els.display = originalDisplay; +    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; +      } +    } +    return element; +  }, + +  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 = ''; +    } +    return element; +  }, + +  makeClipping: function(element) { +    element = $(element); +    if (element._overflow) return element; +    element._overflow = element.style.overflow || 'auto'; +    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') +      element.style.overflow = 'hidden'; +    return element; +  }, + +  undoClipping: function(element) { +    element = $(element); +    if (!element._overflow) return element; +    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; +    element._overflow = null; +    return element; +  } +}; + +Object.extend(Element.Methods, { +  childOf: Element.Methods.descendantOf, +  childElements: Element.Methods.immediateDescendants +}); + +if (Prototype.Browser.Opera) { +  Element.Methods._getStyle = Element.Methods.getStyle; +  Element.Methods.getStyle = function(element, style) { +    switch(style) { +      case 'left': +      case 'top': +      case 'right': +      case 'bottom': +        if (Element._getStyle(element, 'position') == 'static') return null; +      default: return Element._getStyle(element, style); +    } +  }; +} +else if (Prototype.Browser.IE) { +  Element.Methods.getStyle = function(element, style) { +    element = $(element); +    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); +    var value = element.style[style]; +    if (!value && element.currentStyle) value = element.currentStyle[style]; + +    if (style == 'opacity') { +      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) +        if (value[1]) return parseFloat(value[1]) / 100; +      return 1.0; +    } + +    if (value == 'auto') { +      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) +        return element['offset'+style.capitalize()] + 'px'; +      return null; +    } +    return value; +  }; + +  Element.Methods.setOpacity = function(element, value) { +    element = $(element); +    var filter = element.getStyle('filter'), style = element.style; +    if (value == 1 || value === '') { +      style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); +      return element; +    } else if (value < 0.00001) value = 0; +    style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + +      'alpha(opacity=' + (value * 100) + ')'; +    return element; +  }; + +  // IE is missing .innerHTML support for TABLE-related elements +  Element.Methods.update = function(element, html) { +    element = $(element); +    html = typeof html == 'undefined' ? '' : html.toString(); +    var tagName = element.tagName.toUpperCase(); +    if (['THEAD','TBODY','TR','TD'].include(tagName)) { +      var div = document.createElement('div'); +      switch (tagName) { +        case 'THEAD': +        case 'TBODY': +          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>'; +          depth = 2; +          break; +        case 'TR': +          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>'; +          depth = 3; +          break; +        case 'TD': +          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>'; +          depth = 4; +      } +      $A(element.childNodes).each(function(node) { element.removeChild(node) }); +      depth.times(function() { div = div.firstChild }); +      $A(div.childNodes).each(function(node) { element.appendChild(node) }); +    } else { +      element.innerHTML = html.stripScripts(); +    } +    setTimeout(function() { html.evalScripts() }, 10); +    return element; +  } +} +else if (Prototype.Browser.Gecko) { +  Element.Methods.setOpacity = function(element, value) { +    element = $(element); +    element.style.opacity = (value == 1) ? 0.999999 : +      (value === '') ? '' : (value < 0.00001) ? 0 : value; +    return element; +  }; +} + +Element._attributeTranslations = { +  names: { +    colspan:   "colSpan", +    rowspan:   "rowSpan", +    valign:    "vAlign", +    datetime:  "dateTime", +    accesskey: "accessKey", +    tabindex:  "tabIndex", +    enctype:   "encType", +    maxlength: "maxLength", +    readonly:  "readOnly", +    longdesc:  "longDesc" +  }, +  values: { +    _getAttr: function(element, attribute) { +      return element.getAttribute(attribute, 2); +    }, +    _flag: function(element, attribute) { +      return $(element).hasAttribute(attribute) ? attribute : null; +    }, +    style: function(element) { +      return element.style.cssText.toLowerCase(); +    }, +    title: function(element) { +      var node = element.getAttributeNode('title'); +      return node.specified ? node.nodeValue : null; +    } +  } +}; + +(function() { +  Object.extend(this, { +    href: this._getAttr, +    src:  this._getAttr, +    type: this._getAttr, +    disabled: this._flag, +    checked:  this._flag, +    readonly: this._flag, +    multiple: this._flag +  }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { +  hasAttribute: function(element, attribute) { +    var t = Element._attributeTranslations, node; +    attribute = t.names[attribute] || attribute; +    node = $(element).getAttributeNode(attribute); +    return node && node.specified; +  } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { +  window.HTMLElement = {}; +  window.HTMLElement.prototype = document.createElement('div').__proto__; +  Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.hasAttribute = function(element, attribute) { +  if (element.hasAttribute) return element.hasAttribute(attribute); +  return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { +  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + +  if (!methods) { +    Object.extend(Form, Form.Methods); +    Object.extend(Form.Element, Form.Element.Methods); +    Object.extend(Element.Methods.ByTag, { +      "FORM":     Object.clone(Form.Methods), +      "INPUT":    Object.clone(Form.Element.Methods), +      "SELECT":   Object.clone(Form.Element.Methods), +      "TEXTAREA": Object.clone(Form.Element.Methods) +    }); +  } + +  if (arguments.length == 2) { +    var tagName = methods; +    methods = arguments[1]; +  } + +  if (!tagName) Object.extend(Element.Methods, methods || {}); +  else { +    if (tagName.constructor == Array) tagName.each(extend); +    else extend(tagName); +  } + +  function extend(tagName) { +    tagName = tagName.toUpperCase(); +    if (!Element.Methods.ByTag[tagName]) +      Element.Methods.ByTag[tagName] = {}; +    Object.extend(Element.Methods.ByTag[tagName], methods); +  } + +  function copy(methods, destination, onlyIfAbsent) { +    onlyIfAbsent = onlyIfAbsent || false; +    var cache = Element.extend.cache; +    for (var property in methods) { +      var value = methods[property]; +      if (!onlyIfAbsent || !(property in destination)) +        destination[property] = cache.findOrStore(value); +    } +  } + +  function findDOMClass(tagName) { +    var klass; +    var trans = { +      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", +      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", +      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", +      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", +      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": +      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": +      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": +      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": +      "FrameSet", "IFRAME": "IFrame" +    }; +    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; +    if (window[klass]) return window[klass]; +    klass = 'HTML' + tagName + 'Element'; +    if (window[klass]) return window[klass]; +    klass = 'HTML' + tagName.capitalize() + 'Element'; +    if (window[klass]) return window[klass]; + +    window[klass] = {}; +    window[klass].prototype = document.createElement(tagName).__proto__; +    return window[klass]; +  } + +  if (F.ElementExtensions) { +    copy(Element.Methods, HTMLElement.prototype); +    copy(Element.Methods.Simulated, HTMLElement.prototype, true); +  } + +  if (F.SpecificElementExtensions) { +    for (var tag in Element.Methods.ByTag) { +      var klass = findDOMClass(tag); +      if (typeof klass == "undefined") continue; +      copy(T[tag], klass.prototype); +    } +  } + +  Object.extend(Element, Element.Methods); +  delete Element.ByTag; +}; + +var 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) { +        var tagName = this.element.tagName.toUpperCase(); +        if (['TBODY', 'TR'].include(tagName)) { +          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(false).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($A(this).concat(classNameToAdd).join(' ')); +  }, + +  remove: function(classNameToRemove) { +    if (!this.include(classNameToRemove)) return; +    this.set($A(this).without(classNameToRemove).join(' ')); +  }, + +  toString: function() { +    return $A(this).join(' '); +  } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license.  Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { +  initialize: function(expression) { +    this.expression = expression.strip(); +    this.compileMatcher(); +  }, + +  compileMatcher: function() { +    // Selectors with namespaced attributes can't use the XPath version +    if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) +      return this.compileXPathMatcher(); + +    var e = this.expression, ps = Selector.patterns, h = Selector.handlers, +        c = Selector.criteria, le, p, m; + +    if (Selector._cache[e]) { +      this.matcher = Selector._cache[e]; return; +    } +    this.matcher = ["this.matcher = function(root) {", +                    "var r = root, h = Selector.handlers, c = false, n;"]; + +    while (e && le != e && (/\S/).test(e)) { +      le = e; +      for (var i in ps) { +        p = ps[i]; +        if (m = e.match(p)) { +          this.matcher.push(typeof c[i] == 'function' ? c[i](m) : +    	      new Template(c[i]).evaluate(m)); +          e = e.replace(m[0], ''); +          break; +        } +      } +    } + +    this.matcher.push("return h.unique(n);\n}"); +    eval(this.matcher.join('\n')); +    Selector._cache[this.expression] = this.matcher; +  }, + +  compileXPathMatcher: function() { +    var e = this.expression, ps = Selector.patterns, +        x = Selector.xpath, le,  m; + +    if (Selector._cache[e]) { +      this.xpath = Selector._cache[e]; return; +    } + +    this.matcher = ['.//*']; +    while (e && le != e && (/\S/).test(e)) { +      le = e; +      for (var i in ps) { +        if (m = e.match(ps[i])) { +          this.matcher.push(typeof x[i] == 'function' ? x[i](m) : +            new Template(x[i]).evaluate(m)); +          e = e.replace(m[0], ''); +          break; +        } +      } +    } + +    this.xpath = this.matcher.join(''); +    Selector._cache[this.expression] = this.xpath; +  }, + +  findElements: function(root) { +    root = root || document; +    if (this.xpath) return document._getElementsByXPath(this.xpath, root); +    return this.matcher(root); +  }, + +  match: function(element) { +    return this.findElements(document).include(element); +  }, + +  toString: function() { +    return this.expression; +  }, + +  inspect: function() { +    return "#<Selector:" + this.expression.inspect() + ">"; +  } +}; + +Object.extend(Selector, { +  _cache: {}, + +  xpath: { +    descendant:   "//*", +    child:        "/*", +    adjacent:     "/following-sibling::*[1]", +    laterSibling: '/following-sibling::*', +    tagName:      function(m) { +      if (m[1] == '*') return ''; +      return "[local-name()='" + m[1].toLowerCase() + +             "' or local-name()='" + m[1].toUpperCase() + "']"; +    }, +    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]", +    id:           "[@id='#{1}']", +    attrPresence: "[@#{1}]", +    attr: function(m) { +      m[3] = m[5] || m[6]; +      return new Template(Selector.xpath.operators[m[2]]).evaluate(m); +    }, +    pseudo: function(m) { +      var h = Selector.xpath.pseudos[m[1]]; +      if (!h) return ''; +      if (typeof h === 'function') return h(m); +      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); +    }, +    operators: { +      '=':  "[@#{1}='#{3}']", +      '!=': "[@#{1}!='#{3}']", +      '^=': "[starts-with(@#{1}, '#{3}')]", +      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", +      '*=': "[contains(@#{1}, '#{3}')]", +      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", +      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" +    }, +    pseudos: { +      'first-child': '[not(preceding-sibling::*)]', +      'last-child':  '[not(following-sibling::*)]', +      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]', +      'empty':       "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", +      'checked':     "[@checked]", +      'disabled':    "[@disabled]", +      'enabled':     "[not(@disabled)]", +      'not': function(m) { +        var e = m[6], p = Selector.patterns, +            x = Selector.xpath, le, m, v; + +        var exclusion = []; +        while (e && le != e && (/\S/).test(e)) { +          le = e; +          for (var i in p) { +            if (m = e.match(p[i])) { +              v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); +              exclusion.push("(" + v.substring(1, v.length - 1) + ")"); +              e = e.replace(m[0], ''); +              break; +            } +          } +        } +        return "[not(" + exclusion.join(" and ") + ")]"; +      }, +      'nth-child':      function(m) { +        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); +      }, +      'nth-last-child': function(m) { +        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); +      }, +      'nth-of-type':    function(m) { +        return Selector.xpath.pseudos.nth("position() ", m); +      }, +      'nth-last-of-type': function(m) { +        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); +      }, +      'first-of-type':  function(m) { +        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); +      }, +      'last-of-type':   function(m) { +        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); +      }, +      'only-of-type':   function(m) { +        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); +      }, +      nth: function(fragment, m) { +        var mm, formula = m[6], predicate; +        if (formula == 'even') formula = '2n+0'; +        if (formula == 'odd')  formula = '2n+1'; +        if (mm = formula.match(/^(\d+)$/)) // digit only +          return '[' + fragment + "= " + mm[1] + ']'; +        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b +          if (mm[1] == "-") mm[1] = -1; +          var a = mm[1] ? Number(mm[1]) : 1; +          var b = mm[2] ? Number(mm[2]) : 0; +          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + +          "((#{fragment} - #{b}) div #{a} >= 0)]"; +          return new Template(predicate).evaluate({ +            fragment: fragment, a: a, b: b }); +        } +      } +    } +  }, + +  criteria: { +    tagName:      'n = h.tagName(n, r, "#{1}", c);   c = false;', +    className:    'n = h.className(n, r, "#{1}", c); c = false;', +    id:           'n = h.id(n, r, "#{1}", c);        c = false;', +    attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', +    attr: function(m) { +      m[3] = (m[5] || m[6]); +      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); +    }, +    pseudo:       function(m) { +      if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); +      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); +    }, +    descendant:   'c = "descendant";', +    child:        'c = "child";', +    adjacent:     'c = "adjacent";', +    laterSibling: 'c = "laterSibling";' +  }, + +  patterns: { +    // combinators must be listed first +    // (and descendant needs to be last combinator) +    laterSibling: /^\s*~\s*/, +    child:        /^\s*>\s*/, +    adjacent:     /^\s*\+\s*/, +    descendant:   /^\s/, + +    // selectors follow +    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/, +    id:           /^#([\w\-\*]+)(\b|$)/, +    className:    /^\.([\w\-\*]+)(\b|$)/, +    pseudo:       /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, +    attrPresence: /^\[([\w]+)\]/, +    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ +  }, + +  handlers: { +    // UTILITY FUNCTIONS +    // joins two collections +    concat: function(a, b) { +      for (var i = 0, node; node = b[i]; i++) +        a.push(node); +      return a; +    }, + +    // marks an array of nodes for counting +    mark: function(nodes) { +      for (var i = 0, node; node = nodes[i]; i++) +        node._counted = true; +      return nodes; +    }, + +    unmark: function(nodes) { +      for (var i = 0, node; node = nodes[i]; i++) +        node._counted = undefined; +      return nodes; +    }, + +    // mark each child node with its position (for nth calls) +    // "ofType" flag indicates whether we're indexing for nth-of-type +    // rather than nth-child +    index: function(parentNode, reverse, ofType) { +      parentNode._counted = true; +      if (reverse) { +        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { +          node = nodes[i]; +          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; +        } +      } else { +        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) +          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; +      } +    }, + +    // filters out duplicates and extends all nodes +    unique: function(nodes) { +      if (nodes.length == 0) return nodes; +      var results = [], n; +      for (var i = 0, l = nodes.length; i < l; i++) +        if (!(n = nodes[i])._counted) { +          n._counted = true; +          results.push(Element.extend(n)); +        } +      return Selector.handlers.unmark(results); +    }, + +    // COMBINATOR FUNCTIONS +    descendant: function(nodes) { +      var h = Selector.handlers; +      for (var i = 0, results = [], node; node = nodes[i]; i++) +        h.concat(results, node.getElementsByTagName('*')); +      return results; +    }, + +    child: function(nodes) { +      var h = Selector.handlers; +      for (var i = 0, results = [], node; node = nodes[i]; i++) { +        for (var j = 0, children = [], child; child = node.childNodes[j]; j++) +          if (child.nodeType == 1 && child.tagName != '!') results.push(child); +      } +      return results; +    }, + +    adjacent: function(nodes) { +      for (var i = 0, results = [], node; node = nodes[i]; i++) { +        var next = this.nextElementSibling(node); +        if (next) results.push(next); +      } +      return results; +    }, + +    laterSibling: function(nodes) { +      var h = Selector.handlers; +      for (var i = 0, results = [], node; node = nodes[i]; i++) +        h.concat(results, Element.nextSiblings(node)); +      return results; +    }, + +    nextElementSibling: function(node) { +      while (node = node.nextSibling) +	      if (node.nodeType == 1) return node; +      return null; +    }, + +    previousElementSibling: function(node) { +      while (node = node.previousSibling) +        if (node.nodeType == 1) return node; +      return null; +    }, + +    // TOKEN FUNCTIONS +    tagName: function(nodes, root, tagName, combinator) { +      tagName = tagName.toUpperCase(); +      var results = [], h = Selector.handlers; +      if (nodes) { +        if (combinator) { +          // fastlane for ordinary descendant combinators +          if (combinator == "descendant") { +            for (var i = 0, node; node = nodes[i]; i++) +              h.concat(results, node.getElementsByTagName(tagName)); +            return results; +          } else nodes = this[combinator](nodes); +          if (tagName == "*") return nodes; +        } +        for (var i = 0, node; node = nodes[i]; i++) +          if (node.tagName.toUpperCase() == tagName) results.push(node); +        return results; +      } else return root.getElementsByTagName(tagName); +    }, + +    id: function(nodes, root, id, combinator) { +      var targetNode = $(id), h = Selector.handlers; +      if (!nodes && root == document) return targetNode ? [targetNode] : []; +      if (nodes) { +        if (combinator) { +          if (combinator == 'child') { +            for (var i = 0, node; node = nodes[i]; i++) +              if (targetNode.parentNode == node) return [targetNode]; +          } else if (combinator == 'descendant') { +            for (var i = 0, node; node = nodes[i]; i++) +              if (Element.descendantOf(targetNode, node)) return [targetNode]; +          } else if (combinator == 'adjacent') { +            for (var i = 0, node; node = nodes[i]; i++) +              if (Selector.handlers.previousElementSibling(targetNode) == node) +                return [targetNode]; +          } else nodes = h[combinator](nodes); +        } +        for (var i = 0, node; node = nodes[i]; i++) +          if (node == targetNode) return [targetNode]; +        return []; +      } +      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; +    }, + +    className: function(nodes, root, className, combinator) { +      if (nodes && combinator) nodes = this[combinator](nodes); +      return Selector.handlers.byClassName(nodes, root, className); +    }, + +    byClassName: function(nodes, root, className) { +      if (!nodes) nodes = Selector.handlers.descendant([root]); +      var needle = ' ' + className + ' '; +      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { +        nodeClassName = node.className; +        if (nodeClassName.length == 0) continue; +        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) +          results.push(node); +      } +      return results; +    }, + +    attrPresence: function(nodes, root, attr) { +      var results = []; +      for (var i = 0, node; node = nodes[i]; i++) +        if (Element.hasAttribute(node, attr)) results.push(node); +      return results; +    }, + +    attr: function(nodes, root, attr, value, operator) { +      if (!nodes) nodes = root.getElementsByTagName("*"); +      var handler = Selector.operators[operator], results = []; +      for (var i = 0, node; node = nodes[i]; i++) { +        var nodeValue = Element.readAttribute(node, attr); +        if (nodeValue === null) continue; +        if (handler(nodeValue, value)) results.push(node); +      } +      return results; +    }, + +    pseudo: function(nodes, name, value, root, combinator) { +      if (nodes && combinator) nodes = this[combinator](nodes); +      if (!nodes) nodes = root.getElementsByTagName("*"); +      return Selector.pseudos[name](nodes, value, root); +    } +  }, + +  pseudos: { +    'first-child': function(nodes, value, root) { +      for (var i = 0, results = [], node; node = nodes[i]; i++) { +        if (Selector.handlers.previousElementSibling(node)) continue; +          results.push(node); +      } +      return results; +    }, +    'last-child': function(nodes, value, root) { +      for (var i = 0, results = [], node; node = nodes[i]; i++) { +        if (Selector.handlers.nextElementSibling(node)) continue; +          results.push(node); +      } +      return results; +    }, +    'only-child': function(nodes, value, root) { +      var h = Selector.handlers; +      for (var i = 0, results = [], node; node = nodes[i]; i++) +        if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) +          results.push(node); +      return results; +    }, +    'nth-child':        function(nodes, formula, root) { +      return Selector.pseudos.nth(nodes, formula, root); +    }, +    'nth-last-child':   function(nodes, formula, root) { +      return Selector.pseudos.nth(nodes, formula, root, true); +    }, +    'nth-of-type':      function(nodes, formula, root) { +      return Selector.pseudos.nth(nodes, formula, root, false, true); +    }, +    'nth-last-of-type': function(nodes, formula, root) { +      return Selector.pseudos.nth(nodes, formula, root, true, true); +    }, +    'first-of-type':    function(nodes, formula, root) { +      return Selector.pseudos.nth(nodes, "1", root, false, true); +    }, +    'last-of-type':     function(nodes, formula, root) { +      return Selector.pseudos.nth(nodes, "1", root, true, true); +    }, +    'only-of-type':     function(nodes, formula, root) { +      var p = Selector.pseudos; +      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); +    }, + +    // handles the an+b logic +    getIndices: function(a, b, total) { +      if (a == 0) return b > 0 ? [b] : []; +      return $R(1, total).inject([], function(memo, i) { +        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); +        return memo; +      }); +    }, + +    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type +    nth: function(nodes, formula, root, reverse, ofType) { +      if (nodes.length == 0) return []; +      if (formula == 'even') formula = '2n+0'; +      if (formula == 'odd')  formula = '2n+1'; +      var h = Selector.handlers, results = [], indexed = [], m; +      h.mark(nodes); +      for (var i = 0, node; node = nodes[i]; i++) { +        if (!node.parentNode._counted) { +          h.index(node.parentNode, reverse, ofType); +          indexed.push(node.parentNode); +        } +      } +      if (formula.match(/^\d+$/)) { // just a number +        formula = Number(formula); +        for (var i = 0, node; node = nodes[i]; i++) +          if (node.nodeIndex == formula) results.push(node); +      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b +        if (m[1] == "-") m[1] = -1; +        var a = m[1] ? Number(m[1]) : 1; +        var b = m[2] ? Number(m[2]) : 0; +        var indices = Selector.pseudos.getIndices(a, b, nodes.length); +        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { +          for (var j = 0; j < l; j++) +            if (node.nodeIndex == indices[j]) results.push(node); +        } +      } +      h.unmark(nodes); +      h.unmark(indexed); +      return results; +    }, + +    'empty': function(nodes, value, root) { +      for (var i = 0, results = [], node; node = nodes[i]; i++) { +        // IE treats comments as element nodes +        if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; +        results.push(node); +      } +      return results; +    }, + +    'not': function(nodes, selector, root) { +      var h = Selector.handlers, selectorType, m; +      var exclusions = new Selector(selector).findElements(root); +      h.mark(exclusions); +      for (var i = 0, results = [], node; node = nodes[i]; i++) +        if (!node._counted) results.push(node); +      h.unmark(exclusions); +      return results; +    }, + +    'enabled': function(nodes, value, root) { +      for (var i = 0, results = [], node; node = nodes[i]; i++) +        if (!node.disabled) results.push(node); +      return results; +    }, + +    'disabled': function(nodes, value, root) { +      for (var i = 0, results = [], node; node = nodes[i]; i++) +        if (node.disabled) results.push(node); +      return results; +    }, + +    'checked': function(nodes, value, root) { +      for (var i = 0, results = [], node; node = nodes[i]; i++) +        if (node.checked) results.push(node); +      return results; +    } +  }, + +  operators: { +    '=':  function(nv, v) { return nv == v; }, +    '!=': function(nv, v) { return nv != v; }, +    '^=': function(nv, v) { return nv.startsWith(v); }, +    '$=': function(nv, v) { return nv.endsWith(v); }, +    '*=': function(nv, v) { return nv.include(v); }, +    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, +    '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } +  }, + +  matchElements: function(elements, expression) { +    var matches = new Selector(expression).findElements(), h = Selector.handlers; +    h.mark(matches); +    for (var i = 0, results = [], element; element = elements[i]; i++) +      if (element._counted) results.push(element); +    h.unmark(matches); +    return results; +  }, + +  findElement: function(elements, expression, index) { +    if (typeof expression == 'number') { +      index = expression; expression = false; +    } +    return Selector.matchElements(elements, expression || '*')[index || 0]; +  }, + +  findChildElements: function(element, expressions) { +    var exprs = expressions.join(','), expressions = []; +    exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { +      expressions.push(m[1].strip()); +    }); +    var results = [], h = Selector.handlers; +    for (var i = 0, l = expressions.length, selector; i < l; i++) { +      selector = new Selector(expressions[i].strip()); +      h.concat(results, selector.findElements(element)); +    } +    return (l > 1) ? h.unique(results) : results; +  } +}); + +function $$() { +  return Selector.findChildElements(document, $A(arguments)); +} +var Form = { +  reset: function(form) { +    $(form).reset(); +    return form; +  }, + +  serializeElements: function(elements, getHash) { +    var data = elements.inject({}, function(result, element) { +      if (!element.disabled && element.name) { +        var key = element.name, value = $(element).getValue(); +        if (value != null) { +         	if (key in result) { +            if (result[key].constructor != Array) result[key] = [result[key]]; +            result[key].push(value); +          } +          else result[key] = value; +        } +      } +      return result; +    }); + +    return getHash ? data : Hash.toQueryString(data); +  } +}; + +Form.Methods = { +  serialize: function(form, getHash) { +    return Form.serializeElements(Form.getElements(form), getHash); +  }, + +  getElements: function(form) { +    return $A($(form).getElementsByTagName('*')).inject([], +      function(elements, child) { +        if (Form.Element.Serializers[child.tagName.toLowerCase()]) +          elements.push(Element.extend(child)); +        return elements; +      } +    ); +  }, + +  getInputs: function(form, typeName, name) { +    form = $(form); +    var inputs = form.getElementsByTagName('input'); + +    if (!typeName && !name) return $A(inputs).map(Element.extend); + +    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { +      var input = inputs[i]; +      if ((typeName && input.type != typeName) || (name && input.name != name)) +        continue; +      matchingInputs.push(Element.extend(input)); +    } + +    return matchingInputs; +  }, + +  disable: function(form) { +    form = $(form); +    Form.getElements(form).invoke('disable'); +    return form; +  }, + +  enable: function(form) { +    form = $(form); +    Form.getElements(form).invoke('enable'); +    return form; +  }, + +  findFirstElement: function(form) { +    return $(form).getElements().find(function(element) { +      return element.type != 'hidden' && !element.disabled && +        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); +    }); +  }, + +  focusFirstElement: function(form) { +    form = $(form); +    form.findFirstElement().activate(); +    return form; +  }, + +  request: function(form, options) { +    form = $(form), options = Object.clone(options || {}); + +    var params = options.parameters; +    options.parameters = form.serialize(true); + +    if (params) { +      if (typeof params == 'string') params = params.toQueryParams(); +      Object.extend(options.parameters, params); +    } + +    if (form.hasAttribute('method') && !options.method) +      options.method = form.method; + +    return new Ajax.Request(form.readAttribute('action'), options); +  } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { +  focus: function(element) { +    $(element).focus(); +    return element; +  }, + +  select: function(element) { +    $(element).select(); +    return element; +  } +} + +Form.Element.Methods = { +  serialize: function(element) { +    element = $(element); +    if (!element.disabled && element.name) { +      var value = element.getValue(); +      if (value != undefined) { +        var pair = {}; +        pair[element.name] = value; +        return Hash.toQueryString(pair); +      } +    } +    return ''; +  }, + +  getValue: function(element) { +    element = $(element); +    var method = element.tagName.toLowerCase(); +    return Form.Element.Serializers[method](element); +  }, + +  clear: function(element) { +    $(element).value = ''; +    return element; +  }, + +  present: function(element) { +    return $(element).value != ''; +  }, + +  activate: function(element) { +    element = $(element); +    try { +      element.focus(); +      if (element.select && (element.tagName.toLowerCase() != 'input' || +        !['button', 'reset', 'submit'].include(element.type))) +        element.select(); +    } catch (e) {} +    return element; +  }, + +  disable: function(element) { +    element = $(element); +    element.blur(); +    element.disabled = true; +    return element; +  }, + +  enable: function(element) { +    element = $(element); +    element.disabled = false; +    return element; +  } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { +  input: function(element) { +    switch (element.type.toLowerCase()) { +      case 'checkbox': +      case 'radio': +        return Form.Element.Serializers.inputSelector(element); +      default: +        return Form.Element.Serializers.textarea(element); +    } +  }, + +  inputSelector: function(element) { +    return element.checked ? element.value : null; +  }, + +  textarea: function(element) { +    return element.value; +  }, + +  select: function(element) { +    return this[element.type == 'select-one' ? +      'selectOne' : 'selectMany'](element); +  }, + +  selectOne: function(element) { +    var index = element.selectedIndex; +    return index >= 0 ? this.optionValue(element.options[index]) : null; +  }, + +  selectMany: function(element) { +    var values, length = element.length; +    if (!length) return null; + +    for (var i = 0, values = []; i < length; i++) { +      var opt = element.options[i]; +      if (opt.selected) values.push(this.optionValue(opt)); +    } +    return values; +  }, + +  optionValue: function(opt) { +    // extend element because hasAttribute may not be native +    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; +  } +} + +/*--------------------------------------------------------------------------*/ + +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(); +    var changed = ('string' == typeof this.lastValue && 'string' == typeof value +      ? this.lastValue != value : String(this.lastValue) != String(value)); +    if (changed) { +      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() { +    Form.getElements(this.element).each(this.registerCallback.bind(this)); +  }, + +  registerCallback: function(element) { +    if (element.type) { +      switch (element.type.toLowerCase()) { +        case 'checkbox': +        case 'radio': +          Event.observe(element, 'click', this.onElementEvent.bind(this)); +          break; +        default: +          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, +  KEY_HOME:     36, +  KEY_END:      35, +  KEY_PAGEUP:   33, +  KEY_PAGEDOWN: 34, + +  element: function(event) { +    return $(event.target || event.srcElement); +  }, + +  isLeftClick: function(event) { +    return (((event.which) && (event.which == 1)) || +            ((event.button) && (event.button == 1))); +  }, + +  pointerX: function(event) { +    return event.pageX || (event.clientX + +      (document.documentElement.scrollLeft || document.body.scrollLeft)); +  }, + +  pointerY: function(event) { +    return event.pageY || (event.clientY + +      (document.documentElement.scrollTop || document.body.scrollTop)); +  }, + +  stop: function(event) { +    if (event.preventDefault) { +      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, length = Event.observers.length; i < length; i++) { +      Event.stopObserving.apply(this, Event.observers[i]); +      Event.observers[i][0] = null; +    } +    Event.observers = false; +  }, + +  observe: function(element, name, observer, useCapture) { +    element = $(element); +    useCapture = useCapture || false; + +    if (name == 'keypress' && +      (Prototype.Browser.WebKit || element.attachEvent)) +      name = 'keydown'; + +    Event._observeAndCache(element, name, observer, useCapture); +  }, + +  stopObserving: function(element, name, observer, useCapture) { +    element = $(element); +    useCapture = useCapture || false; + +    if (name == 'keypress' && +        (Prototype.Browser.WebKit || element.attachEvent)) +      name = 'keydown'; + +    if (element.removeEventListener) { +      element.removeEventListener(name, observer, useCapture); +    } else if (element.detachEvent) { +      try { +        element.detachEvent('on' + name, observer); +      } catch (e) {} +    } +  } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.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: false, + +  // 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) { +        if(element.tagName=='BODY') break; +        var 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; +  }, + +  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 { +      if (!window.opera || element.tagName=='BODY') { +        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 (Prototype.Browser.WebKit) { +  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]; +  } +} + +Element.addMethods();
\ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..c2e023b --- /dev/null +++ b/templates/base.html @@ -0,0 +1,28 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html><head> +{% block style %} +<link rel="stylesheet" type="text/css" href="/static/default.css"> +{% endblock %} +{% block javascript %} +{% endblock %} +<title>The Equator</title> +</head><body> +<div class="main"> +<div style="width: 100%; text-align: center;"> +<h1>{% block title %}The Equator% endblock %}</h1> +</div> +{% block content %} +no content? +{% endblock %} +<br> +<hr> +<span class="footer"> +<a href="/">home</a> -  +<a href="/go/">do it</a> -  +<a href="/equation/">equations</a> - +<a href="/variable/">variables</a> - +<a href="/symbol/">symbols</a>  +<br>Legalese? Copyright? Fuck no! +<a href="mailto:webmaster@equator.memeschemes.com" style="text-decoration: line-through;">email the webmaster!</a> 2007! +</span> +</div></body></html> diff --git a/templates/flatpages/default.html b/templates/flatpages/default.html new file mode 100644 index 0000000..55baf71 --- /dev/null +++ b/templates/flatpages/default.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} + +{% block title %}{{ flatpage.title }}{% endblock %} +{% block content %} +{{ flatpage.content }} +{% endblock %} diff --git a/templates/go.html b/templates/go.html new file mode 100644 index 0000000..cb1e855 --- /dev/null +++ b/templates/go.html @@ -0,0 +1,90 @@ +{% extends "base.html" %} + +{% block javascript %} +<script type="text/javascript" src="The%20Equator_files/prototype.js"> +</script> +<script type="text/javascript"> +var variables = [] +var equations = [] +function get_variables() { +    $('status_bin').innerHTML= "Fetching..." +    var initialVariablesRequest = new Ajax.Request( +        "/variable/json/all/", +        { method: 'get',  +          onSuccess: handle_variables }); +} + +function handle_variables(transport) { +    json = transport.responseText.evalJSON(); +    $('status_bin').innerHTML = "Recieved: \n" + json; +    $('variables_bin').innerHTML = ''; +    for(i=0; i<json.length; i++) { +        variables[i] = json[i].fields; +        $('variables_bin').innerHTML += '<img src="/static/' +  +            variables[i].render +  +            '" style="padding:2px; border: 2px solid white; margin: 4px;" ' + +            'id="variable'+i+'" ' + +            'alt="'+variables[i].name+'" onClick="toggle_variable('+i+');">'; +        variables[i].isselected = false; +    } + +} +function toggle_variable(vnum) { +    if(variables[vnum].isselected == false) { +        variables[vnum].isselected = true; +        $('variable'+vnum).style["border"] = "2px solid green" +    } else { +        variables[vnum].isselected = false; +        $('variable'+vnum).style["border"] = "2px solid white" +    } +    var whichvars = '' +    for(i=0; i<variables.length; i++){ +        if(variables[i].isselected == true){ +            whichvars += (i+1) + "," +        } +    } +    var freshEquationsRequest = new Ajax.Request( +        "/equation/json/byvariables/" + whichvars, +        { method: 'get',  +          onSuccess: handle_equations}); +} +function handle_equations(transport) { +    json = transport.responseText.evalJSON(); +    $('status_bin').innerHTML = "Recieved: \n" + json; +    $('equations_bin').innerHTML = '<br />'; +    for(i=0; i<json.length; i++) { +        equations[json[i].pk-1] = json[i].fields; +        $('equations_bin').innerHTML += '<a style="text-decoration:none;' + +            'border:none;" href="/equation/'+json[i].pk+'/">' + +            '<img src="/static/' +  +            json[i].fields.render +  +            '" style="padding:2px; border: 2px solid white; margin: 4px;" ' + +            'id="variable'+i+'" ' + +            'alt="'+json[i].fields.name+'"></a>'; +    } + +} + +</script> +{% endblock %} + +{% block title %}<span style="color: orange;">YAY!</span>{% endblock %} +{% block content %} +<b>Variables<!-- <span onClick="get_variables();">(fetch)</span>-->: </b> +<div id="variables_bin" style="border: 2px solid black; width: 100%;"> +(none yet!) +</div> +<br /> +<b>Matching Equations: </b> +<div id="equations_bin" style="border: 2px solid black; width: 100%;"> +(none yet, choose some variables!) +</div> +<span style="visibility: hidden;"> +<b>Status: </b> +<div id="status_bin" style="border: 2px solid black; width: 100%;"> +(nothing...)</div> +</span> +<script type="text/javascript"> +window.onLoad = get_variables(); +</script> +{% endblock %} @@ -0,0 +1,9 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('', +    # Example: +    # (r'^equator/', include('equator.foo.urls')), + +    # Uncomment this for admin: +#     (r'^admin/', include('django.contrib.admin.urls')), +) | 
