Commit 00072bb7ef6411c888fbc9f33e09eeb7d13b432d

Authored by AntonioTerceiro
1 parent 235be306

ActionItem0: prototype artwork for new top bar



git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@408 3f533792-8f58-4932-b0fe-aaf55b0a4547
public/artwork/newbar/menu.css 0 → 100644
... ... @@ -0,0 +1,87 @@
  1 +#accessibility_menu {
  2 + float: left;
  3 +}
  4 +
  5 +#navigation_bar {
  6 + float: right;
  7 +}
  8 +#search_box {
  9 + clear: both;
  10 +}
  11 +
  12 +
  13 +#navigation_bar ul{
  14 + margin: 0px;
  15 + padding: 0px;
  16 +}
  17 +
  18 +#navigation_bar ul li{
  19 + list-style: none;
  20 + margin: 0px 0px 0px 15px;
  21 + position: relative;
  22 + display: inline;
  23 + font-family: sans-serif;
  24 + font-weight: 800;
  25 + font-size: 12px;
  26 +}
  27 +
  28 +#navigation_bar ul ul li{
  29 + font-weight: 500;
  30 + float: none;
  31 + margin: 0px 0px 0px -40px;
  32 + padding: 0px;
  33 + border: none;
  34 + border-top: 1px solid #F8F8F8;
  35 + border-bottom: 1px solid #C0C0C0;
  36 + display: block;
  37 + float: left;
  38 + width: 100px;
  39 +}
  40 +#navigation_bar.msie ul ul li{
  41 + margin-left: 0px;
  42 +}
  43 +
  44 +#navigation_bar ul ul{
  45 + margin: 0px;
  46 + clear: left;
  47 + display: none;
  48 + position: absolute;
  49 + top: 20px;
  50 + left: 0px;
  51 + background-color: #E0E0E0;
  52 + border: 1px solid #808080;
  53 + width: 150px;
  54 +}
  55 +#navigation_bar.msie ul ul{
  56 + width: 180px;
  57 +}
  58 +
  59 +#navigation_bar ul ul ul{
  60 + top: 5px;
  61 + left: 50px;
  62 +}
  63 +
  64 +#navigation_bar a:link,
  65 +#navigation_bar a:active,
  66 +#navigation_bar a:visited{
  67 + text-decoration: none;
  68 + color: #707070;
  69 + overflow: hidden;
  70 +}
  71 +
  72 +#navigation_bar ul ul a{
  73 + padding: 0px 2px 0px 5px;
  74 + display: block;
  75 + width: 100px;
  76 + background-color: #DCDCDC;
  77 +}
  78 +
  79 +#navigation_bar ul ul a:hover{
  80 + background-color: #EEE;
  81 +}
  82 +
  83 +#navigation_bar ul ul a.linkSubMenu:link,
  84 +#navigation_bar ul ul a.linkSubMenu:active,
  85 +#navigation_bar ul ul a.linkSubMenu:visited{
  86 + font-weight: 800;
  87 +}
... ...
public/artwork/newbar/menu.html 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +<html>
  2 + <head>
  3 + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  4 + <title>HTML pra Lessinho</title>
  5 + <link rel='stylesheet' type='text/css' href='menu.css'>
  6 + <script type="text/javascript" src="prototype.js"></script>
  7 + <script type="text/javascript" src="menu.js"></script>
  8 + </head>
  9 + <body>
  10 +
  11 + <div id='accessibility_menu'>
  12 + <a href='#'>Acesibilidade</a> |
  13 + <a href='#'>Central de Buscas</a> |
  14 + <a href='#'>Ir para conteúdo</a>
  15 + </div><!-- accessibility_menu -->
  16 +
  17 + <div id='navigation_bar'>
  18 + <ul>
  19 + <li id='category1'>
  20 + Noosfero
  21 + <ul>
  22 + <li><a href=''><span>Item 1</span></a></li>
  23 + <li><a href=''><span>Item 2</span></a></li>
  24 + <li><a href=''><span>Item 3</span></a></li>
  25 + <li><a href=''><span>Item 4</span></a></li>
  26 + <li><a href=''><span>Item 5</span></a></li>
  27 + </ul>
  28 + </li>
  29 +
  30 + <li id='category2'>
  31 + Territorios
  32 + <ul>
  33 + <li><a href=''><span>Item 1</span></a></li>
  34 + <li><a href=''><span>Item 2</span></a></li>
  35 + <li><a href=''><span>Item 3</span></a></li>
  36 + <li><a href=''><span>Item 4</span></a></li>
  37 + <li><a href=''><span>Item 5</span></a></li>
  38 + </ul>
  39 + </li>
  40 +
  41 + <li id='category2'>
  42 + Lalala
  43 + <ul>
  44 + <li><a href=''><span>Item 1</span></a></li>
  45 + <li><a href=''><span>Item 2</span></a></li>
  46 + <li><a href=''><span>Item 3</span></a></li>
  47 + <li><a href=''><span>Item 4</span></a></li>
  48 + <li><a href=''><span>Item 5</span></a></li>
  49 + </ul>
  50 + </li>
  51 + </ul>
  52 + </div><!-- id='navigation_bar' -->
  53 + <script type="text/javascript">
  54 + prepareMenu('navigation_bar');
  55 + </script>
  56 +
  57 + <div id='search_box'>
  58 + <form action="" method="GET">
  59 + <input type='text' name='q' value='sua busca aqui ...'>
  60 + <input type='submit' value='Buscar'>
  61 + </form>
  62 + </div><!-- id='search_box' -->
  63 +
  64 + </body>
  65 +</html>
  66 +
... ...
public/artwork/newbar/menu.js 0 → 100644
... ... @@ -0,0 +1,110 @@
  1 +function prepareMenu(id) {
  2 +
  3 + if ( document.all ) {
  4 + // add a class for work arround msie&#180;s css bugs
  5 + $(id).className += " msie";
  6 + }
  7 +
  8 + var zIndex = 10;
  9 +
  10 + $$("#" + id + " ul ul").each( function( ul ) { // para cada UL de sub-menu faça:
  11 + // Pega o link que abre este sub-menu:
  12 + var linkText = ul.parentNode.firstChild;
  13 + // Retira espaço em branco sobrando nas bordas deste:
  14 + linkText.nodeValue = linkText.nodeValue.replace( /^\s*|\s*$/g, "" );
  15 +
  16 + // Create a link to open this sub-menu:
  17 + var link = document.createElement("a");
  18 + link.href = "#";
  19 + link.className = "linkSubMenu";
  20 + linkText.parentNode.insertBefore( link, linkText );
  21 + link.appendChild( linkText );
  22 + link.parentNode.style.zIndex = zIndex++;
  23 + link.subMenu = ul;
  24 + ul.linkControle = link;
  25 +
  26 + link.openSubMenu =
  27 + function ( isMouseClick ) {
  28 + if( this.subMenu.style.display == "block" ) {
  29 + if( isMouseClick ) {
  30 + this.subMenu.style.display = "none";
  31 + } else {
  32 + clearTimeout(this.timeOutClose);
  33 + clearTimeout(this.subMenu.timeOutClose);
  34 + return false;
  35 + }
  36 + } else {
  37 + this.subMenu.style.display = "block";
  38 + clearTimeout(this.timeOutClose);
  39 + clearTimeout(this.subMenu.timeOutClose);
  40 + }
  41 + }
  42 + link.closeSubMenu = function(){ this.subMenu.style.display = "none" }
  43 +
  44 + link.onclick = function(){ this.openSubMenu(true); return false }
  45 +
  46 + // onmouseout e onmouseover manipulam o menu para pessoas normais
  47 + // onblur e onfocus manipulam o menu para pessoas que precisam navegar com tab
  48 +
  49 + link.onmouseover = link.onfocus =
  50 + function () {
  51 + this.openSubMenu(false);
  52 + };
  53 + link.onmouseout = link.onblur =
  54 + function () {
  55 + this.timeOutClose = setTimeout( this.closeSubMenu.bind(this), 333 );
  56 + };
  57 +
  58 + ul.closeSubMenu = function(){ this.style.display = "none" }
  59 +
  60 + ul.onmouseover = ul.onfocus =
  61 + function () {
  62 + this.blurCalledByIEWorkArroundBug = false;
  63 + clearTimeout(this.timeOutClose);
  64 + clearTimeout(this.linkControle.timeOutClose);
  65 + };
  66 + ul.onmouseout = ul.onblur =
  67 + function () {
  68 + if ( this.blurCalledByIEWorkArroundBug ) { return false }
  69 + this.blurCalledByIEWorkArroundBug = true;
  70 + this.timeOutClose = setTimeout( this.closeSubMenu.bind(this), 333 );
  71 + };
  72 + });
  73 +
  74 +
  75 + ////// INI - Work Arround Bug da disgraça do M$IE /////////////////////
  76 + if ( document.all ) {
  77 + function forceUlFocusFromLink ( a ) {
  78 + var stop = false;
  79 + a.ancestors().each( function(el) {
  80 + if ( el.id == "menu" ) { stop = true }
  81 + if ( ! stop && el.onfocus ) { el.onfocus() }
  82 + } );
  83 + }
  84 + function forceUlBlurFromLink ( a ) {
  85 + var stop = false;
  86 + a.ancestors().each( function(el) {
  87 + if ( el.id == "menu" ) { stop = true }
  88 + if ( ! stop && el.onblur ) { el.onblur() }
  89 + } );
  90 + }
  91 + $$("#" + id + " ul ul a").each( function( a ) {
  92 + // os links do sub menu forçarão o foco do ul
  93 + if ( a.className == "linkSubMenu" ) {
  94 + a.onfocus = function() {
  95 + forceUlFocusFromLink(this);
  96 + this.openSubMenu(false);
  97 + };
  98 + a.onblur = function() {
  99 + forceUlBlurFromLink(this);
  100 + this.timeOutClose = setTimeout( this.closeSubMenu.bind(this), 333 );
  101 + };
  102 + } else {
  103 + a.onfocus = function() { forceUlFocusFromLink(this) };
  104 + a.onblur = function() { forceUlBlurFromLink(this) };
  105 + }
  106 + });
  107 + }
  108 +
  109 +}
  110 +////// END - Work Arround Bug da disgraça do M$IE /////////////////////
... ...
public/artwork/newbar/prototype.js 0 → 100644
... ... @@ -0,0 +1,2006 @@
  1 +/* Prototype JavaScript framework, version 1.5.0_rc0
  2 + * (c) 2005 Sam Stephenson <sam@conio.net>
  3 + *
  4 + * Prototype is freely distributable under the terms of an MIT-style license.
  5 + * For details, see the Prototype web site: http://prototype.conio.net/
  6 + *
  7 +/*--------------------------------------------------------------------------*/
  8 +
  9 +var Prototype = {
  10 + Version: '1.5.0_rc0',
  11 + ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
  12 +
  13 + emptyFunction: function() {},
  14 + K: function(x) {return x}
  15 +}
  16 +
  17 +var Class = {
  18 + create: function() {
  19 + return function() {
  20 + this.initialize.apply(this, arguments);
  21 + }
  22 + }
  23 +}
  24 +
  25 +var Abstract = new Object();
  26 +
  27 +Object.extend = function(destination, source) {
  28 + for (var property in source) {
  29 + destination[property] = source[property];
  30 + }
  31 + return destination;
  32 +}
  33 +
  34 +Object.inspect = function(object) {
  35 + try {
  36 + if (object == undefined) return 'undefined';
  37 + if (object == null) return 'null';
  38 + return object.inspect ? object.inspect() : object.toString();
  39 + } catch (e) {
  40 + if (e instanceof RangeError) return '...';
  41 + throw e;
  42 + }
  43 +}
  44 +
  45 +Function.prototype.bind = function() {
  46 + var __method = this, args = $A(arguments), object = args.shift();
  47 + return function() {
  48 + return __method.apply(object, args.concat($A(arguments)));
  49 + }
  50 +}
  51 +
  52 +Function.prototype.bindAsEventListener = function(object) {
  53 + var __method = this;
  54 + return function(event) {
  55 + return __method.call(object, event || window.event);
  56 + }
  57 +}
  58 +
  59 +Object.extend(Number.prototype, {
  60 + toColorPart: function() {
  61 + var digits = this.toString(16);
  62 + if (this < 16) return '0' + digits;
  63 + return digits;
  64 + },
  65 +
  66 + succ: function() {
  67 + return this + 1;
  68 + },
  69 +
  70 + times: function(iterator) {
  71 + $R(0, this, true).each(iterator);
  72 + return this;
  73 + }
  74 +});
  75 +
  76 +var Try = {
  77 + these: function() {
  78 + var returnValue;
  79 +
  80 + for (var i = 0; i < arguments.length; i++) {
  81 + var lambda = arguments[i];
  82 + try {
  83 + returnValue = lambda();
  84 + break;
  85 + } catch (e) {}
  86 + }
  87 +
  88 + return returnValue;
  89 + }
  90 +}
  91 +
  92 +/*--------------------------------------------------------------------------*/
  93 +
  94 +var PeriodicalExecuter = Class.create();
  95 +PeriodicalExecuter.prototype = {
  96 + initialize: function(callback, frequency) {
  97 + this.callback = callback;
  98 + this.frequency = frequency;
  99 + this.currentlyExecuting = false;
  100 +
  101 + this.registerCallback();
  102 + },
  103 +
  104 + registerCallback: function() {
  105 + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  106 + },
  107 +
  108 + onTimerEvent: function() {
  109 + if (!this.currentlyExecuting) {
  110 + try {
  111 + this.currentlyExecuting = true;
  112 + this.callback();
  113 + } finally {
  114 + this.currentlyExecuting = false;
  115 + }
  116 + }
  117 + }
  118 +}
  119 +Object.extend(String.prototype, {
  120 + gsub: function(pattern, replacement) {
  121 + var result = '', source = this, match;
  122 + replacement = arguments.callee.prepareReplacement(replacement);
  123 +
  124 + while (source.length > 0) {
  125 + if (match = source.match(pattern)) {
  126 + result += source.slice(0, match.index);
  127 + result += (replacement(match) || '').toString();
  128 + source = source.slice(match.index + match[0].length);
  129 + } else {
  130 + result += source, source = '';
  131 + }
  132 + }
  133 + return result;
  134 + },
  135 +
  136 + sub: function(pattern, replacement, count) {
  137 + replacement = this.gsub.prepareReplacement(replacement);
  138 + count = count === undefined ? 1 : count;
  139 +
  140 + return this.gsub(pattern, function(match) {
  141 + if (--count < 0) return match[0];
  142 + return replacement(match);
  143 + });
  144 + },
  145 +
  146 + scan: function(pattern, iterator) {
  147 + this.gsub(pattern, iterator);
  148 + return this;
  149 + },
  150 +
  151 + truncate: function(length, truncation) {
  152 + length = length || 30;
  153 + truncation = truncation === undefined ? '...' : truncation;
  154 + return this.length > length ?
  155 + this.slice(0, length - truncation.length) + truncation : this;
  156 + },
  157 +
  158 + strip: function() {
  159 + return this.replace(/^\s+/, '').replace(/\s+$/, '');
  160 + },
  161 +
  162 + stripTags: function() {
  163 + return this.replace(/<\/?[^>]+>/gi, '');
  164 + },
  165 +
  166 + stripScripts: function() {
  167 + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  168 + },
  169 +
  170 + extractScripts: function() {
  171 + var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
  172 + var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
  173 + return (this.match(matchAll) || []).map(function(scriptTag) {
  174 + return (scriptTag.match(matchOne) || ['', ''])[1];
  175 + });
  176 + },
  177 +
  178 + evalScripts: function() {
  179 + return this.extractScripts().map(function(script) { return eval(script) });
  180 + },
  181 +
  182 + escapeHTML: function() {
  183 + var div = document.createElement('div');
  184 + var text = document.createTextNode(this);
  185 + div.appendChild(text);
  186 + return div.innerHTML;
  187 + },
  188 +
  189 + unescapeHTML: function() {
  190 + var div = document.createElement('div');
  191 + div.innerHTML = this.stripTags();
  192 + return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
  193 + },
  194 +
  195 + toQueryParams: function() {
  196 + var pairs = this.match(/^\??(.*)$/)[1].split('&');
  197 + return pairs.inject({}, function(params, pairString) {
  198 + var pair = pairString.split('=');
  199 + params[pair[0]] = pair[1];
  200 + return params;
  201 + });
  202 + },
  203 +
  204 + toArray: function() {
  205 + return this.split('');
  206 + },
  207 +
  208 + camelize: function() {
  209 + var oStringList = this.split('-');
  210 + if (oStringList.length == 1) return oStringList[0];
  211 +
  212 + var camelizedString = this.indexOf('-') == 0
  213 + ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
  214 + : oStringList[0];
  215 +
  216 + for (var i = 1, len = oStringList.length; i < len; i++) {
  217 + var s = oStringList[i];
  218 + camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
  219 + }
  220 +
  221 + return camelizedString;
  222 + },
  223 +
  224 + inspect: function() {
  225 + return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
  226 + }
  227 +});
  228 +
  229 +String.prototype.gsub.prepareReplacement = function(replacement) {
  230 + if (typeof replacement == 'function') return replacement;
  231 + var template = new Template(replacement);
  232 + return function(match) { return template.evaluate(match) };
  233 +}
  234 +
  235 +String.prototype.parseQuery = String.prototype.toQueryParams;
  236 +
  237 +var Template = Class.create();
  238 +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
  239 +Template.prototype = {
  240 + initialize: function(template, pattern) {
  241 + this.template = template.toString();
  242 + this.pattern = pattern || Template.Pattern;
  243 + },
  244 +
  245 + evaluate: function(object) {
  246 + return this.template.gsub(this.pattern, function(match) {
  247 + var before = match[1];
  248 + if (before == '\\') return match[2];
  249 + return before + (object[match[3]] || '').toString();
  250 + });
  251 + }
  252 +}
  253 +
  254 +var $break = new Object();
  255 +var $continue = new Object();
  256 +
  257 +var Enumerable = {
  258 + each: function(iterator) {
  259 + var index = 0;
  260 + try {
  261 + this._each(function(value) {
  262 + try {
  263 + iterator(value, index++);
  264 + } catch (e) {
  265 + if (e != $continue) throw e;
  266 + }
  267 + });
  268 + } catch (e) {
  269 + if (e != $break) throw e;
  270 + }
  271 + },
  272 +
  273 + all: function(iterator) {
  274 + var result = true;
  275 + this.each(function(value, index) {
  276 + result = result && !!(iterator || Prototype.K)(value, index);
  277 + if (!result) throw $break;
  278 + });
  279 + return result;
  280 + },
  281 +
  282 + any: function(iterator) {
  283 + var result = true;
  284 + this.each(function(value, index) {
  285 + if (result = !!(iterator || Prototype.K)(value, index))
  286 + throw $break;
  287 + });
  288 + return result;
  289 + },
  290 +
  291 + collect: function(iterator) {
  292 + var results = [];
  293 + this.each(function(value, index) {
  294 + results.push(iterator(value, index));
  295 + });
  296 + return results;
  297 + },
  298 +
  299 + detect: function (iterator) {
  300 + var result;
  301 + this.each(function(value, index) {
  302 + if (iterator(value, index)) {
  303 + result = value;
  304 + throw $break;
  305 + }
  306 + });
  307 + return result;
  308 + },
  309 +
  310 + findAll: function(iterator) {
  311 + var results = [];
  312 + this.each(function(value, index) {
  313 + if (iterator(value, index))
  314 + results.push(value);
  315 + });
  316 + return results;
  317 + },
  318 +
  319 + grep: function(pattern, iterator) {
  320 + var results = [];
  321 + this.each(function(value, index) {
  322 + var stringValue = value.toString();
  323 + if (stringValue.match(pattern))
  324 + results.push((iterator || Prototype.K)(value, index));
  325 + })
  326 + return results;
  327 + },
  328 +
  329 + include: function(object) {
  330 + var found = false;
  331 + this.each(function(value) {
  332 + if (value == object) {
  333 + found = true;
  334 + throw $break;
  335 + }
  336 + });
  337 + return found;
  338 + },
  339 +
  340 + inject: function(memo, iterator) {
  341 + this.each(function(value, index) {
  342 + memo = iterator(memo, value, index);
  343 + });
  344 + return memo;
  345 + },
  346 +
  347 + invoke: function(method) {
  348 + var args = $A(arguments).slice(1);
  349 + return this.collect(function(value) {
  350 + return value[method].apply(value, args);
  351 + });
  352 + },
  353 +
  354 + max: function(iterator) {
  355 + var result;
  356 + this.each(function(value, index) {
  357 + value = (iterator || Prototype.K)(value, index);
  358 + if (result == undefined || value >= result)
  359 + result = value;
  360 + });
  361 + return result;
  362 + },
  363 +
  364 + min: function(iterator) {
  365 + var result;
  366 + this.each(function(value, index) {
  367 + value = (iterator || Prototype.K)(value, index);
  368 + if (result == undefined || value < result)
  369 + result = value;
  370 + });
  371 + return result;
  372 + },
  373 +
  374 + partition: function(iterator) {
  375 + var trues = [], falses = [];
  376 + this.each(function(value, index) {
  377 + ((iterator || Prototype.K)(value, index) ?
  378 + trues : falses).push(value);
  379 + });
  380 + return [trues, falses];
  381 + },
  382 +
  383 + pluck: function(property) {
  384 + var results = [];
  385 + this.each(function(value, index) {
  386 + results.push(value[property]);
  387 + });
  388 + return results;
  389 + },
  390 +
  391 + reject: function(iterator) {
  392 + var results = [];
  393 + this.each(function(value, index) {
  394 + if (!iterator(value, index))
  395 + results.push(value);
  396 + });
  397 + return results;
  398 + },
  399 +
  400 + sortBy: function(iterator) {
  401 + return this.collect(function(value, index) {
  402 + return {value: value, criteria: iterator(value, index)};
  403 + }).sort(function(left, right) {
  404 + var a = left.criteria, b = right.criteria;
  405 + return a < b ? -1 : a > b ? 1 : 0;
  406 + }).pluck('value');
  407 + },
  408 +
  409 + toArray: function() {
  410 + return this.collect(Prototype.K);
  411 + },
  412 +
  413 + zip: function() {
  414 + var iterator = Prototype.K, args = $A(arguments);
  415 + if (typeof args.last() == 'function')
  416 + iterator = args.pop();
  417 +
  418 + var collections = [this].concat(args).map($A);
  419 + return this.map(function(value, index) {
  420 + return iterator(collections.pluck(index));
  421 + });
  422 + },
  423 +
  424 + inspect: function() {
  425 + return '#<Enumerable:' + this.toArray().inspect() + '>';
  426 + }
  427 +}
  428 +
  429 +Object.extend(Enumerable, {
  430 + map: Enumerable.collect,
  431 + find: Enumerable.detect,
  432 + select: Enumerable.findAll,
  433 + member: Enumerable.include,
  434 + entries: Enumerable.toArray
  435 +});
  436 +var $A = Array.from = function(iterable) {
  437 + if (!iterable) return [];
  438 + if (iterable.toArray) {
  439 + return iterable.toArray();
  440 + } else {
  441 + var results = [];
  442 + for (var i = 0; i < iterable.length; i++)
  443 + results.push(iterable[i]);
  444 + return results;
  445 + }
  446 +}
  447 +
  448 +Object.extend(Array.prototype, Enumerable);
  449 +
  450 +if (!Array.prototype._reverse)
  451 + Array.prototype._reverse = Array.prototype.reverse;
  452 +
  453 +Object.extend(Array.prototype, {
  454 + _each: function(iterator) {
  455 + for (var i = 0; i < this.length; i++)
  456 + iterator(this[i]);
  457 + },
  458 +
  459 + clear: function() {
  460 + this.length = 0;
  461 + return this;
  462 + },
  463 +
  464 + first: function() {
  465 + return this[0];
  466 + },
  467 +
  468 + last: function() {
  469 + return this[this.length - 1];
  470 + },
  471 +
  472 + compact: function() {
  473 + return this.select(function(value) {
  474 + return value != undefined || value != null;
  475 + });
  476 + },
  477 +
  478 + flatten: function() {
  479 + return this.inject([], function(array, value) {
  480 + return array.concat(value && value.constructor == Array ?
  481 + value.flatten() : [value]);
  482 + });
  483 + },
  484 +
  485 + without: function() {
  486 + var values = $A(arguments);
  487 + return this.select(function(value) {
  488 + return !values.include(value);
  489 + });
  490 + },
  491 +
  492 + indexOf: function(object) {
  493 + for (var i = 0; i < this.length; i++)
  494 + if (this[i] == object) return i;
  495 + return -1;
  496 + },
  497 +
  498 + reverse: function(inline) {
  499 + return (inline !== false ? this : this.toArray())._reverse();
  500 + },
  501 +
  502 + inspect: function() {
  503 + return '[' + this.map(Object.inspect).join(', ') + ']';
  504 + }
  505 +});
  506 +var Hash = {
  507 + _each: function(iterator) {
  508 + for (var key in this) {
  509 + var value = this[key];
  510 + if (typeof value == 'function') continue;
  511 +
  512 + var pair = [key, value];
  513 + pair.key = key;
  514 + pair.value = value;
  515 + iterator(pair);
  516 + }
  517 + },
  518 +
  519 + keys: function() {
  520 + return this.pluck('key');
  521 + },
  522 +
  523 + values: function() {
  524 + return this.pluck('value');
  525 + },
  526 +
  527 + merge: function(hash) {
  528 + return $H(hash).inject($H(this), function(mergedHash, pair) {
  529 + mergedHash[pair.key] = pair.value;
  530 + return mergedHash;
  531 + });
  532 + },
  533 +
  534 + toQueryString: function() {
  535 + return this.map(function(pair) {
  536 + return pair.map(encodeURIComponent).join('=');
  537 + }).join('&');
  538 + },
  539 +
  540 + inspect: function() {
  541 + return '#<Hash:{' + this.map(function(pair) {
  542 + return pair.map(Object.inspect).join(': ');
  543 + }).join(', ') + '}>';
  544 + }
  545 +}
  546 +
  547 +function $H(object) {
  548 + var hash = Object.extend({}, object || {});
  549 + Object.extend(hash, Enumerable);
  550 + Object.extend(hash, Hash);
  551 + return hash;
  552 +}
  553 +ObjectRange = Class.create();
  554 +Object.extend(ObjectRange.prototype, Enumerable);
  555 +Object.extend(ObjectRange.prototype, {
  556 + initialize: function(start, end, exclusive) {
  557 + this.start = start;
  558 + this.end = end;
  559 + this.exclusive = exclusive;
  560 + },
  561 +
  562 + _each: function(iterator) {
  563 + var value = this.start;
  564 + do {
  565 + iterator(value);
  566 + value = value.succ();
  567 + } while (this.include(value));
  568 + },
  569 +
  570 + include: function(value) {
  571 + if (value < this.start)
  572 + return false;
  573 + if (this.exclusive)
  574 + return value < this.end;
  575 + return value <= this.end;
  576 + }
  577 +});
  578 +
  579 +var $R = function(start, end, exclusive) {
  580 + return new ObjectRange(start, end, exclusive);
  581 +}
  582 +
  583 +var Ajax = {
  584 + getTransport: function() {
  585 + return Try.these(
  586 + function() {return new XMLHttpRequest()},
  587 + function() {return new ActiveXObject('Msxml2.XMLHTTP')},
  588 + function() {return new ActiveXObject('Microsoft.XMLHTTP')}
  589 + ) || false;
  590 + },
  591 +
  592 + activeRequestCount: 0
  593 +}
  594 +
  595 +Ajax.Responders = {
  596 + responders: [],
  597 +
  598 + _each: function(iterator) {
  599 + this.responders._each(iterator);
  600 + },
  601 +
  602 + register: function(responderToAdd) {
  603 + if (!this.include(responderToAdd))
  604 + this.responders.push(responderToAdd);
  605 + },
  606 +
  607 + unregister: function(responderToRemove) {
  608 + this.responders = this.responders.without(responderToRemove);
  609 + },
  610 +
  611 + dispatch: function(callback, request, transport, json) {
  612 + this.each(function(responder) {
  613 + if (responder[callback] && typeof responder[callback] == 'function') {
  614 + try {
  615 + responder[callback].apply(responder, [request, transport, json]);
  616 + } catch (e) {}
  617 + }
  618 + });
  619 + }
  620 +};
  621 +
  622 +Object.extend(Ajax.Responders, Enumerable);
  623 +
  624 +Ajax.Responders.register({
  625 + onCreate: function() {
  626 + Ajax.activeRequestCount++;
  627 + },
  628 +
  629 + onComplete: function() {
  630 + Ajax.activeRequestCount--;
  631 + }
  632 +});
  633 +
  634 +Ajax.Base = function() {};
  635 +Ajax.Base.prototype = {
  636 + setOptions: function(options) {
  637 + this.options = {
  638 + method: 'post',
  639 + asynchronous: true,
  640 + contentType: 'application/x-www-form-urlencoded',
  641 + parameters: ''
  642 + }
  643 + Object.extend(this.options, options || {});
  644 + },
  645 +
  646 + responseIsSuccess: function() {
  647 + return this.transport.status == undefined
  648 + || this.transport.status == 0
  649 + || (this.transport.status >= 200 && this.transport.status < 300);
  650 + },
  651 +
  652 + responseIsFailure: function() {
  653 + return !this.responseIsSuccess();
  654 + }
  655 +}
  656 +
  657 +Ajax.Request = Class.create();
  658 +Ajax.Request.Events =
  659 + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
  660 +
  661 +Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  662 + initialize: function(url, options) {
  663 + this.transport = Ajax.getTransport();
  664 + this.setOptions(options);
  665 + this.request(url);
  666 + },
  667 +
  668 + request: function(url) {
  669 + var parameters = this.options.parameters || '';
  670 + if (parameters.length > 0) parameters += '&_=';
  671 +
  672 + try {
  673 + this.url = url;
  674 + if (this.options.method == 'get' && parameters.length > 0)
  675 + this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
  676 +
  677 + Ajax.Responders.dispatch('onCreate', this, this.transport);
  678 +
  679 + this.transport.open(this.options.method, this.url,
  680 + this.options.asynchronous);
  681 +
  682 + if (this.options.asynchronous) {
  683 + this.transport.onreadystatechange = this.onStateChange.bind(this);
  684 + setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
  685 + }
  686 +
  687 + this.setRequestHeaders();
  688 +
  689 + var body = this.options.postBody ? this.options.postBody : parameters;
  690 + this.transport.send(this.options.method == 'post' ? body : null);
  691 +
  692 + } catch (e) {
  693 + this.dispatchException(e);
  694 + }
  695 + },
  696 +
  697 + setRequestHeaders: function() {
  698 + var requestHeaders =
  699 + ['X-Requested-With', 'XMLHttpRequest',
  700 + 'X-Prototype-Version', Prototype.Version,
  701 + 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
  702 +
  703 + if (this.options.method == 'post') {
  704 + requestHeaders.push('Content-type', this.options.contentType);
  705 +
  706 + /* Force "Connection: close" for Mozilla browsers to work around
  707 + * a bug where XMLHttpReqeuest sends an incorrect Content-length
  708 + * header. See Mozilla Bugzilla #246651.
  709 + */
  710 + if (this.transport.overrideMimeType)
  711 + requestHeaders.push('Connection', 'close');
  712 + }
  713 +
  714 + if (this.options.requestHeaders)
  715 + requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
  716 +
  717 + for (var i = 0; i < requestHeaders.length; i += 2)
  718 + this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
  719 + },
  720 +
  721 + onStateChange: function() {
  722 + var readyState = this.transport.readyState;
  723 + if (readyState != 1)
  724 + this.respondToReadyState(this.transport.readyState);
  725 + },
  726 +
  727 + header: function(name) {
  728 + try {
  729 + return this.transport.getResponseHeader(name);
  730 + } catch (e) {}
  731 + },
  732 +
  733 + evalJSON: function() {
  734 + try {
  735 + return eval('(' + this.header('X-JSON') + ')');
  736 + } catch (e) {}
  737 + },
  738 +
  739 + evalResponse: function() {
  740 + try {
  741 + return eval(this.transport.responseText);
  742 + } catch (e) {
  743 + this.dispatchException(e);
  744 + }
  745 + },
  746 +
  747 + respondToReadyState: function(readyState) {
  748 + var event = Ajax.Request.Events[readyState];
  749 + var transport = this.transport, json = this.evalJSON();
  750 +
  751 + if (event == 'Complete') {
  752 + try {
  753 + (this.options['on' + this.transport.status]
  754 + || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
  755 + || Prototype.emptyFunction)(transport, json);
  756 + } catch (e) {
  757 + this.dispatchException(e);
  758 + }
  759 +
  760 + if ((this.header('Content-type') || '').match(/^text\/javascript/i))
  761 + this.evalResponse();
  762 + }
  763 +
  764 + try {
  765 + (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
  766 + Ajax.Responders.dispatch('on' + event, this, transport, json);
  767 + } catch (e) {
  768 + this.dispatchException(e);
  769 + }
  770 +
  771 + /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
  772 + if (event == 'Complete')
  773 + this.transport.onreadystatechange = Prototype.emptyFunction;
  774 + },
  775 +
  776 + dispatchException: function(exception) {
  777 + (this.options.onException || Prototype.emptyFunction)(this, exception);
  778 + Ajax.Responders.dispatch('onException', this, exception);
  779 + }
  780 +});
  781 +
  782 +Ajax.Updater = Class.create();
  783 +
  784 +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  785 + initialize: function(container, url, options) {
  786 + this.containers = {
  787 + success: container.success ? $(container.success) : $(container),
  788 + failure: container.failure ? $(container.failure) :
  789 + (container.success ? null : $(container))
  790 + }
  791 +
  792 + this.transport = Ajax.getTransport();
  793 + this.setOptions(options);
  794 +
  795 + var onComplete = this.options.onComplete || Prototype.emptyFunction;
  796 + this.options.onComplete = (function(transport, object) {
  797 + this.updateContent();
  798 + onComplete(transport, object);
  799 + }).bind(this);
  800 +
  801 + this.request(url);
  802 + },
  803 +
  804 + updateContent: function() {
  805 + var receiver = this.responseIsSuccess() ?
  806 + this.containers.success : this.containers.failure;
  807 + var response = this.transport.responseText;
  808 +
  809 + if (!this.options.evalScripts)
  810 + response = response.stripScripts();
  811 +
  812 + if (receiver) {
  813 + if (this.options.insertion) {
  814 + new this.options.insertion(receiver, response);
  815 + } else {
  816 + Element.update(receiver, response);
  817 + }
  818 + }
  819 +
  820 + if (this.responseIsSuccess()) {
  821 + if (this.onComplete)
  822 + setTimeout(this.onComplete.bind(this), 10);
  823 + }
  824 + }
  825 +});
  826 +
  827 +Ajax.PeriodicalUpdater = Class.create();
  828 +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  829 + initialize: function(container, url, options) {
  830 + this.setOptions(options);
  831 + this.onComplete = this.options.onComplete;
  832 +
  833 + this.frequency = (this.options.frequency || 2);
  834 + this.decay = (this.options.decay || 1);
  835 +
  836 + this.updater = {};
  837 + this.container = container;
  838 + this.url = url;
  839 +
  840 + this.start();
  841 + },
  842 +
  843 + start: function() {
  844 + this.options.onComplete = this.updateComplete.bind(this);
  845 + this.onTimerEvent();
  846 + },
  847 +
  848 + stop: function() {
  849 + this.updater.onComplete = undefined;
  850 + clearTimeout(this.timer);
  851 + (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  852 + },
  853 +
  854 + updateComplete: function(request) {
  855 + if (this.options.decay) {
  856 + this.decay = (request.responseText == this.lastText ?
  857 + this.decay * this.options.decay : 1);
  858 +
  859 + this.lastText = request.responseText;
  860 + }
  861 + this.timer = setTimeout(this.onTimerEvent.bind(this),
  862 + this.decay * this.frequency * 1000);
  863 + },
  864 +
  865 + onTimerEvent: function() {
  866 + this.updater = new Ajax.Updater(this.container, this.url, this.options);
  867 + }
  868 +});
  869 +function $() {
  870 + var results = [], element;
  871 + for (var i = 0; i < arguments.length; i++) {
  872 + element = arguments[i];
  873 + if (typeof element == 'string')
  874 + element = document.getElementById(element);
  875 + results.push(Element.extend(element));
  876 + }
  877 + return results.length < 2 ? results[0] : results;
  878 +}
  879 +
  880 +document.getElementsByClassName = function(className, parentElement) {
  881 + var children = ($(parentElement) || document.body).getElementsByTagName('*');
  882 + return $A(children).inject([], function(elements, child) {
  883 + if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
  884 + elements.push(Element.extend(child));
  885 + return elements;
  886 + });
  887 +}
  888 +
  889 +/*--------------------------------------------------------------------------*/
  890 +
  891 +if (!window.Element)
  892 + var Element = new Object();
  893 +
  894 +Element.extend = function(element) {
  895 + if (!element) return;
  896 + if (_nativeExtensions) return element;
  897 +
  898 + if (!element._extended && element.tagName && element != window) {
  899 + var methods = Element.Methods, cache = Element.extend.cache;
  900 + for (property in methods) {
  901 + var value = methods[property];
  902 + if (typeof value == 'function')
  903 + element[property] = cache.findOrStore(value);
  904 + }
  905 + }
  906 +
  907 + element._extended = true;
  908 + return element;
  909 +}
  910 +
  911 +Element.extend.cache = {
  912 + findOrStore: function(value) {
  913 + return this[value] = this[value] || function() {
  914 + return value.apply(null, [this].concat($A(arguments)));
  915 + }
  916 + }
  917 +}
  918 +
  919 +Element.Methods = {
  920 + visible: function(element) {
  921 + return $(element).style.display != 'none';
  922 + },
  923 +
  924 + toggle: function() {
  925 + for (var i = 0; i < arguments.length; i++) {
  926 + var element = $(arguments[i]);
  927 + Element[Element.visible(element) ? 'hide' : 'show'](element);
  928 + }
  929 + },
  930 +
  931 + hide: function() {
  932 + for (var i = 0; i < arguments.length; i++) {
  933 + var element = $(arguments[i]);
  934 + element.style.display = 'none';
  935 + }
  936 + },
  937 +
  938 + show: function() {
  939 + for (var i = 0; i < arguments.length; i++) {
  940 + var element = $(arguments[i]);
  941 + element.style.display = '';
  942 + }
  943 + },
  944 +
  945 + remove: function(element) {
  946 + element = $(element);
  947 + element.parentNode.removeChild(element);
  948 + },
  949 +
  950 + update: function(element, html) {
  951 + $(element).innerHTML = html.stripScripts();
  952 + setTimeout(function() {html.evalScripts()}, 10);
  953 + },
  954 +
  955 + replace: function(element, html) {
  956 + element = $(element);
  957 + if (element.outerHTML) {
  958 + element.outerHTML = html.stripScripts();
  959 + } else {
  960 + var range = element.ownerDocument.createRange();
  961 + range.selectNodeContents(element);
  962 + element.parentNode.replaceChild(
  963 + range.createContextualFragment(html.stripScripts()), element);
  964 + }
  965 + setTimeout(function() {html.evalScripts()}, 10);
  966 + },
  967 +
  968 + getHeight: function(element) {
  969 + element = $(element);
  970 + return element.offsetHeight;
  971 + },
  972 +
  973 + classNames: function(element) {
  974 + return new Element.ClassNames(element);
  975 + },
  976 +
  977 + hasClassName: function(element, className) {
  978 + if (!(element = $(element))) return;
  979 + return Element.classNames(element).include(className);
  980 + },
  981 +
  982 + addClassName: function(element, className) {
  983 + if (!(element = $(element))) return;
  984 + return Element.classNames(element).add(className);
  985 + },
  986 +
  987 + removeClassName: function(element, className) {
  988 + if (!(element = $(element))) return;
  989 + return Element.classNames(element).remove(className);
  990 + },
  991 +
  992 + // removes whitespace-only text node children
  993 + cleanWhitespace: function(element) {
  994 + element = $(element);
  995 + for (var i = 0; i < element.childNodes.length; i++) {
  996 + var node = element.childNodes[i];
  997 + if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
  998 + Element.remove(node);
  999 + }
  1000 + },
  1001 +
  1002 + empty: function(element) {
  1003 + return $(element).innerHTML.match(/^\s*$/);
  1004 + },
  1005 +
  1006 + childOf: function(element, ancestor) {
  1007 + element = $(element), ancestor = $(ancestor);
  1008 + while (element = element.parentNode)
  1009 + if (element == ancestor) return true;
  1010 + return false;
  1011 + },
  1012 +
  1013 + scrollTo: function(element) {
  1014 + element = $(element);
  1015 + var x = element.x ? element.x : element.offsetLeft,
  1016 + y = element.y ? element.y : element.offsetTop;
  1017 + window.scrollTo(x, y);
  1018 + },
  1019 +
  1020 + getStyle: function(element, style) {
  1021 + element = $(element);
  1022 + var value = element.style[style.camelize()];
  1023 + if (!value) {
  1024 + if (document.defaultView && document.defaultView.getComputedStyle) {
  1025 + var css = document.defaultView.getComputedStyle(element, null);
  1026 + value = css ? css.getPropertyValue(style) : null;
  1027 + } else if (element.currentStyle) {
  1028 + value = element.currentStyle[style.camelize()];
  1029 + }
  1030 + }
  1031 +
  1032 + if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
  1033 + if (Element.getStyle(element, 'position') == 'static') value = 'auto';
  1034 +
  1035 + return value == 'auto' ? null : value;
  1036 + },
  1037 +
  1038 + setStyle: function(element, style) {
  1039 + element = $(element);
  1040 + for (var name in style)
  1041 + element.style[name.camelize()] = style[name];
  1042 + },
  1043 +
  1044 + getDimensions: function(element) {
  1045 + element = $(element);
  1046 + if (Element.getStyle(element, 'display') != 'none')
  1047 + return {width: element.offsetWidth, height: element.offsetHeight};
  1048 +
  1049 + // All *Width and *Height properties give 0 on elements with display none,
  1050 + // so enable the element temporarily
  1051 + var els = element.style;
  1052 + var originalVisibility = els.visibility;
  1053 + var originalPosition = els.position;
  1054 + els.visibility = 'hidden';
  1055 + els.position = 'absolute';
  1056 + els.display = '';
  1057 + var originalWidth = element.clientWidth;
  1058 + var originalHeight = element.clientHeight;
  1059 + els.display = 'none';
  1060 + els.position = originalPosition;
  1061 + els.visibility = originalVisibility;
  1062 + return {width: originalWidth, height: originalHeight};
  1063 + },
  1064 +
  1065 + makePositioned: function(element) {
  1066 + element = $(element);
  1067 + var pos = Element.getStyle(element, 'position');
  1068 + if (pos == 'static' || !pos) {
  1069 + element._madePositioned = true;
  1070 + element.style.position = 'relative';
  1071 + // Opera returns the offset relative to the positioning context, when an
  1072 + // element is position relative but top and left have not been defined
  1073 + if (window.opera) {
  1074 + element.style.top = 0;
  1075 + element.style.left = 0;
  1076 + }
  1077 + }
  1078 + },
  1079 +
  1080 + undoPositioned: function(element) {
  1081 + element = $(element);
  1082 + if (element._madePositioned) {
  1083 + element._madePositioned = undefined;
  1084 + element.style.position =
  1085 + element.style.top =
  1086 + element.style.left =
  1087 + element.style.bottom =
  1088 + element.style.right = '';
  1089 + }
  1090 + },
  1091 +
  1092 + makeClipping: function(element) {
  1093 + element = $(element);
  1094 + if (element._overflow) return;
  1095 + element._overflow = element.style.overflow;
  1096 + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
  1097 + element.style.overflow = 'hidden';
  1098 + },
  1099 +
  1100 + undoClipping: function(element) {
  1101 + element = $(element);
  1102 + if (element._overflow) return;
  1103 + element.style.overflow = element._overflow;
  1104 + element._overflow = undefined;
  1105 + }
  1106 +}
  1107 +
  1108 +Object.extend(Element, Element.Methods);
  1109 +
  1110 +var _nativeExtensions = false;
  1111 +
  1112 +if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  1113 + var HTMLElement = {}
  1114 + HTMLElement.prototype = document.createElement('div').__proto__;
  1115 +}
  1116 +
  1117 +Element.addMethods = function(methods) {
  1118 + Object.extend(Element.Methods, methods || {});
  1119 +
  1120 + if(typeof HTMLElement != 'undefined') {
  1121 + var methods = Element.Methods, cache = Element.extend.cache;
  1122 + for (property in methods) {
  1123 + var value = methods[property];
  1124 + if (typeof value == 'function')
  1125 + HTMLElement.prototype[property] = cache.findOrStore(value);
  1126 + }
  1127 + _nativeExtensions = true;
  1128 + }
  1129 +}
  1130 +
  1131 +Element.addMethods();
  1132 +
  1133 +var Toggle = new Object();
  1134 +Toggle.display = Element.toggle;
  1135 +
  1136 +/*--------------------------------------------------------------------------*/
  1137 +
  1138 +Abstract.Insertion = function(adjacency) {
  1139 + this.adjacency = adjacency;
  1140 +}
  1141 +
  1142 +Abstract.Insertion.prototype = {
  1143 + initialize: function(element, content) {
  1144 + this.element = $(element);
  1145 + this.content = content.stripScripts();
  1146 +
  1147 + if (this.adjacency && this.element.insertAdjacentHTML) {
  1148 + try {
  1149 + this.element.insertAdjacentHTML(this.adjacency, this.content);
  1150 + } catch (e) {
  1151 + var tagName = this.element.tagName.toLowerCase();
  1152 + if (tagName == 'tbody' || tagName == 'tr') {
  1153 + this.insertContent(this.contentFromAnonymousTable());
  1154 + } else {
  1155 + throw e;
  1156 + }
  1157 + }
  1158 + } else {
  1159 + this.range = this.element.ownerDocument.createRange();
  1160 + if (this.initializeRange) this.initializeRange();
  1161 + this.insertContent([this.range.createContextualFragment(this.content)]);
  1162 + }
  1163 +
  1164 + setTimeout(function() {content.evalScripts()}, 10);
  1165 + },
  1166 +
  1167 + contentFromAnonymousTable: function() {
  1168 + var div = document.createElement('div');
  1169 + div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
  1170 + return $A(div.childNodes[0].childNodes[0].childNodes);
  1171 + }
  1172 +}
  1173 +
  1174 +var Insertion = new Object();
  1175 +
  1176 +Insertion.Before = Class.create();
  1177 +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  1178 + initializeRange: function() {
  1179 + this.range.setStartBefore(this.element);
  1180 + },
  1181 +
  1182 + insertContent: function(fragments) {
  1183 + fragments.each((function(fragment) {
  1184 + this.element.parentNode.insertBefore(fragment, this.element);
  1185 + }).bind(this));
  1186 + }
  1187 +});
  1188 +
  1189 +Insertion.Top = Class.create();
  1190 +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  1191 + initializeRange: function() {
  1192 + this.range.selectNodeContents(this.element);
  1193 + this.range.collapse(true);
  1194 + },
  1195 +
  1196 + insertContent: function(fragments) {
  1197 + fragments.reverse(false).each((function(fragment) {
  1198 + this.element.insertBefore(fragment, this.element.firstChild);
  1199 + }).bind(this));
  1200 + }
  1201 +});
  1202 +
  1203 +Insertion.Bottom = Class.create();
  1204 +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  1205 + initializeRange: function() {
  1206 + this.range.selectNodeContents(this.element);
  1207 + this.range.collapse(this.element);
  1208 + },
  1209 +
  1210 + insertContent: function(fragments) {
  1211 + fragments.each((function(fragment) {
  1212 + this.element.appendChild(fragment);
  1213 + }).bind(this));
  1214 + }
  1215 +});
  1216 +
  1217 +Insertion.After = Class.create();
  1218 +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  1219 + initializeRange: function() {
  1220 + this.range.setStartAfter(this.element);
  1221 + },
  1222 +
  1223 + insertContent: function(fragments) {
  1224 + fragments.each((function(fragment) {
  1225 + this.element.parentNode.insertBefore(fragment,
  1226 + this.element.nextSibling);
  1227 + }).bind(this));
  1228 + }
  1229 +});
  1230 +
  1231 +/*--------------------------------------------------------------------------*/
  1232 +
  1233 +Element.ClassNames = Class.create();
  1234 +Element.ClassNames.prototype = {
  1235 + initialize: function(element) {
  1236 + this.element = $(element);
  1237 + },
  1238 +
  1239 + _each: function(iterator) {
  1240 + this.element.className.split(/\s+/).select(function(name) {
  1241 + return name.length > 0;
  1242 + })._each(iterator);
  1243 + },
  1244 +
  1245 + set: function(className) {
  1246 + this.element.className = className;
  1247 + },
  1248 +
  1249 + add: function(classNameToAdd) {
  1250 + if (this.include(classNameToAdd)) return;
  1251 + this.set(this.toArray().concat(classNameToAdd).join(' '));
  1252 + },
  1253 +
  1254 + remove: function(classNameToRemove) {
  1255 + if (!this.include(classNameToRemove)) return;
  1256 + this.set(this.select(function(className) {
  1257 + return className != classNameToRemove;
  1258 + }).join(' '));
  1259 + },
  1260 +
  1261 + toString: function() {
  1262 + return this.toArray().join(' ');
  1263 + }
  1264 +}
  1265 +
  1266 +Object.extend(Element.ClassNames.prototype, Enumerable);
  1267 +var Selector = Class.create();
  1268 +Selector.prototype = {
  1269 + initialize: function(expression) {
  1270 + this.params = {classNames: []};
  1271 + this.expression = expression.toString().strip();
  1272 + this.parseExpression();
  1273 + this.compileMatcher();
  1274 + },
  1275 +
  1276 + parseExpression: function() {
  1277 + function abort(message) { throw 'Parse error in selector: ' + message; }
  1278 +
  1279 + if (this.expression == '') abort('empty expression');
  1280 +
  1281 + var params = this.params, expr = this.expression, match, modifier, clause, rest;
  1282 + while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
  1283 + params.attributes = params.attributes || [];
  1284 + params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
  1285 + expr = match[1];
  1286 + }
  1287 +
  1288 + if (expr == '*') return this.params.wildcard = true;
  1289 +
  1290 + while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
  1291 + modifier = match[1], clause = match[2], rest = match[3];
  1292 + switch (modifier) {
  1293 + case '#': params.id = clause; break;
  1294 + case '.': params.classNames.push(clause); break;
  1295 + case '':
  1296 + case undefined: params.tagName = clause.toUpperCase(); break;
  1297 + default: abort(expr.inspect());
  1298 + }
  1299 + expr = rest;
  1300 + }
  1301 +
  1302 + if (expr.length > 0) abort(expr.inspect());
  1303 + },
  1304 +
  1305 + buildMatchExpression: function() {
  1306 + var params = this.params, conditions = [], clause;
  1307 +
  1308 + if (params.wildcard)
  1309 + conditions.push('true');
  1310 + if (clause = params.id)
  1311 + conditions.push('element.id == ' + clause.inspect());
  1312 + if (clause = params.tagName)
  1313 + conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
  1314 + if ((clause = params.classNames).length > 0)
  1315 + for (var i = 0; i < clause.length; i++)
  1316 + conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
  1317 + if (clause = params.attributes) {
  1318 + clause.each(function(attribute) {
  1319 + var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
  1320 + var splitValueBy = function(delimiter) {
  1321 + return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
  1322 + }
  1323 +
  1324 + switch (attribute.operator) {
  1325 + case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
  1326 + case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
  1327 + case '|=': conditions.push(
  1328 + splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
  1329 + ); break;
  1330 + case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
  1331 + case '':
  1332 + case undefined: conditions.push(value + ' != null'); break;
  1333 + default: throw 'Unknown operator ' + attribute.operator + ' in selector';
  1334 + }
  1335 + });
  1336 + }
  1337 +
  1338 + return conditions.join(' && ');
  1339 + },
  1340 +
  1341 + compileMatcher: function() {
  1342 + this.match = new Function('element', 'if (!element.tagName) return false; \
  1343 + return ' + this.buildMatchExpression());
  1344 + },
  1345 +
  1346 + findElements: function(scope) {
  1347 + var element;
  1348 +
  1349 + if (element = $(this.params.id))
  1350 + if (this.match(element))
  1351 + if (!scope || Element.childOf(element, scope))
  1352 + return [element];
  1353 +
  1354 + scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
  1355 +
  1356 + var results = [];
  1357 + for (var i = 0; i < scope.length; i++)
  1358 + if (this.match(element = scope[i]))
  1359 + results.push(Element.extend(element));
  1360 +
  1361 + return results;
  1362 + },
  1363 +
  1364 + toString: function() {
  1365 + return this.expression;
  1366 + }
  1367 +}
  1368 +
  1369 +function $$() {
  1370 + return $A(arguments).map(function(expression) {
  1371 + return expression.strip().split(/\s+/).inject([null], function(results, expr) {
  1372 + var selector = new Selector(expr);
  1373 + return results.map(selector.findElements.bind(selector)).flatten();
  1374 + });
  1375 + }).flatten();
  1376 +}
  1377 +var Field = {
  1378 + clear: function() {
  1379 + for (var i = 0; i < arguments.length; i++)
  1380 + $(arguments[i]).value = '';
  1381 + },
  1382 +
  1383 + focus: function(element) {
  1384 + $(element).focus();
  1385 + },
  1386 +
  1387 + present: function() {
  1388 + for (var i = 0; i < arguments.length; i++)
  1389 + if ($(arguments[i]).value == '') return false;
  1390 + return true;
  1391 + },
  1392 +
  1393 + select: function(element) {
  1394 + $(element).select();
  1395 + },
  1396 +
  1397 + activate: function(element) {
  1398 + element = $(element);
  1399 + element.focus();
  1400 + if (element.select)
  1401 + element.select();
  1402 + }
  1403 +}
  1404 +
  1405 +/*--------------------------------------------------------------------------*/
  1406 +
  1407 +var Form = {
  1408 + serialize: function(form) {
  1409 + var elements = Form.getElements($(form));
  1410 + var queryComponents = new Array();
  1411 +
  1412 + for (var i = 0; i < elements.length; i++) {
  1413 + var queryComponent = Form.Element.serialize(elements[i]);
  1414 + if (queryComponent)
  1415 + queryComponents.push(queryComponent);
  1416 + }
  1417 +
  1418 + return queryComponents.join('&');
  1419 + },
  1420 +
  1421 + getElements: function(form) {
  1422 + form = $(form);
  1423 + var elements = new Array();
  1424 +
  1425 + for (var tagName in Form.Element.Serializers) {
  1426 + var tagElements = form.getElementsByTagName(tagName);
  1427 + for (var j = 0; j < tagElements.length; j++)
  1428 + elements.push(tagElements[j]);
  1429 + }
  1430 + return elements;
  1431 + },
  1432 +
  1433 + getInputs: function(form, typeName, name) {
  1434 + form = $(form);
  1435 + var inputs = form.getElementsByTagName('input');
  1436 +
  1437 + if (!typeName && !name)
  1438 + return inputs;
  1439 +
  1440 + var matchingInputs = new Array();
  1441 + for (var i = 0; i < inputs.length; i++) {
  1442 + var input = inputs[i];
  1443 + if ((typeName && input.type != typeName) ||
  1444 + (name && input.name != name))
  1445 + continue;
  1446 + matchingInputs.push(input);
  1447 + }
  1448 +
  1449 + return matchingInputs;
  1450 + },
  1451 +
  1452 + disable: function(form) {
  1453 + var elements = Form.getElements(form);
  1454 + for (var i = 0; i < elements.length; i++) {
  1455 + var element = elements[i];
  1456 + element.blur();
  1457 + element.disabled = 'true';
  1458 + }
  1459 + },
  1460 +
  1461 + enable: function(form) {
  1462 + var elements = Form.getElements(form);
  1463 + for (var i = 0; i < elements.length; i++) {
  1464 + var element = elements[i];
  1465 + element.disabled = '';
  1466 + }
  1467 + },
  1468 +
  1469 + findFirstElement: function(form) {
  1470 + return Form.getElements(form).find(function(element) {
  1471 + return element.type != 'hidden' && !element.disabled &&
  1472 + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
  1473 + });
  1474 + },
  1475 +
  1476 + focusFirstElement: function(form) {
  1477 + Field.activate(Form.findFirstElement(form));
  1478 + },
  1479 +
  1480 + reset: function(form) {
  1481 + $(form).reset();
  1482 + }
  1483 +}
  1484 +
  1485 +Form.Element = {
  1486 + serialize: function(element) {
  1487 + element = $(element);
  1488 + var method = element.tagName.toLowerCase();
  1489 + var parameter = Form.Element.Serializers[method](element);
  1490 +
  1491 + if (parameter) {
  1492 + var key = encodeURIComponent(parameter[0]);
  1493 + if (key.length == 0) return;
  1494 +
  1495 + if (parameter[1].constructor != Array)
  1496 + parameter[1] = [parameter[1]];
  1497 +
  1498 + return parameter[1].map(function(value) {
  1499 + return key + '=' + encodeURIComponent(value);
  1500 + }).join('&');
  1501 + }
  1502 + },
  1503 +
  1504 + getValue: function(element) {
  1505 + element = $(element);
  1506 + var method = element.tagName.toLowerCase();
  1507 + var parameter = Form.Element.Serializers[method](element);
  1508 +
  1509 + if (parameter)
  1510 + return parameter[1];
  1511 + }
  1512 +}
  1513 +
  1514 +Form.Element.Serializers = {
  1515 + input: function(element) {
  1516 + switch (element.type.toLowerCase()) {
  1517 + case 'submit':
  1518 + case 'hidden':
  1519 + case 'password':
  1520 + case 'text':
  1521 + return Form.Element.Serializers.textarea(element);
  1522 + case 'checkbox':
  1523 + case 'radio':
  1524 + return Form.Element.Serializers.inputSelector(element);
  1525 + }
  1526 + return false;
  1527 + },
  1528 +
  1529 + inputSelector: function(element) {
  1530 + if (element.checked)
  1531 + return [element.name, element.value];
  1532 + },
  1533 +
  1534 + textarea: function(element) {
  1535 + return [element.name, element.value];
  1536 + },
  1537 +
  1538 + select: function(element) {
  1539 + return Form.Element.Serializers[element.type == 'select-one' ?
  1540 + 'selectOne' : 'selectMany'](element);
  1541 + },
  1542 +
  1543 + selectOne: function(element) {
  1544 + var value = '', opt, index = element.selectedIndex;
  1545 + if (index >= 0) {
  1546 + opt = element.options[index];
  1547 + value = opt.value || opt.text;
  1548 + }
  1549 + return [element.name, value];
  1550 + },
  1551 +
  1552 + selectMany: function(element) {
  1553 + var value = [];
  1554 + for (var i = 0; i < element.length; i++) {
  1555 + var opt = element.options[i];
  1556 + if (opt.selected)
  1557 + value.push(opt.value || opt.text);
  1558 + }
  1559 + return [element.name, value];
  1560 + }
  1561 +}
  1562 +
  1563 +/*--------------------------------------------------------------------------*/
  1564 +
  1565 +var $F = Form.Element.getValue;
  1566 +
  1567 +/*--------------------------------------------------------------------------*/
  1568 +
  1569 +Abstract.TimedObserver = function() {}
  1570 +Abstract.TimedObserver.prototype = {
  1571 + initialize: function(element, frequency, callback) {
  1572 + this.frequency = frequency;
  1573 + this.element = $(element);
  1574 + this.callback = callback;
  1575 +
  1576 + this.lastValue = this.getValue();
  1577 + this.registerCallback();
  1578 + },
  1579 +
  1580 + registerCallback: function() {
  1581 + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  1582 + },
  1583 +
  1584 + onTimerEvent: function() {
  1585 + var value = this.getValue();
  1586 + if (this.lastValue != value) {
  1587 + this.callback(this.element, value);
  1588 + this.lastValue = value;
  1589 + }
  1590 + }
  1591 +}
  1592 +
  1593 +Form.Element.Observer = Class.create();
  1594 +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  1595 + getValue: function() {
  1596 + return Form.Element.getValue(this.element);
  1597 + }
  1598 +});
  1599 +
  1600 +Form.Observer = Class.create();
  1601 +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  1602 + getValue: function() {
  1603 + return Form.serialize(this.element);
  1604 + }
  1605 +});
  1606 +
  1607 +/*--------------------------------------------------------------------------*/
  1608 +
  1609 +Abstract.EventObserver = function() {}
  1610 +Abstract.EventObserver.prototype = {
  1611 + initialize: function(element, callback) {
  1612 + this.element = $(element);
  1613 + this.callback = callback;
  1614 +
  1615 + this.lastValue = this.getValue();
  1616 + if (this.element.tagName.toLowerCase() == 'form')
  1617 + this.registerFormCallbacks();
  1618 + else
  1619 + this.registerCallback(this.element);
  1620 + },
  1621 +
  1622 + onElementEvent: function() {
  1623 + var value = this.getValue();
  1624 + if (this.lastValue != value) {
  1625 + this.callback(this.element, value);
  1626 + this.lastValue = value;
  1627 + }
  1628 + },
  1629 +
  1630 + registerFormCallbacks: function() {
  1631 + var elements = Form.getElements(this.element);
  1632 + for (var i = 0; i < elements.length; i++)
  1633 + this.registerCallback(elements[i]);
  1634 + },
  1635 +
  1636 + registerCallback: function(element) {
  1637 + if (element.type) {
  1638 + switch (element.type.toLowerCase()) {
  1639 + case 'checkbox':
  1640 + case 'radio':
  1641 + Event.observe(element, 'click', this.onElementEvent.bind(this));
  1642 + break;
  1643 + case 'password':
  1644 + case 'text':
  1645 + case 'textarea':
  1646 + case 'select-one':
  1647 + case 'select-multiple':
  1648 + Event.observe(element, 'change', this.onElementEvent.bind(this));
  1649 + break;
  1650 + }
  1651 + }
  1652 + }
  1653 +}
  1654 +
  1655 +Form.Element.EventObserver = Class.create();
  1656 +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  1657 + getValue: function() {
  1658 + return Form.Element.getValue(this.element);
  1659 + }
  1660 +});
  1661 +
  1662 +Form.EventObserver = Class.create();
  1663 +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  1664 + getValue: function() {
  1665 + return Form.serialize(this.element);
  1666 + }
  1667 +});
  1668 +if (!window.Event) {
  1669 + var Event = new Object();
  1670 +}
  1671 +
  1672 +Object.extend(Event, {
  1673 + KEY_BACKSPACE: 8,
  1674 + KEY_TAB: 9,
  1675 + KEY_RETURN: 13,
  1676 + KEY_ESC: 27,
  1677 + KEY_LEFT: 37,
  1678 + KEY_UP: 38,
  1679 + KEY_RIGHT: 39,
  1680 + KEY_DOWN: 40,
  1681 + KEY_DELETE: 46,
  1682 +
  1683 + element: function(event) {
  1684 + return event.target || event.srcElement;
  1685 + },
  1686 +
  1687 + isLeftClick: function(event) {
  1688 + return (((event.which) && (event.which == 1)) ||
  1689 + ((event.button) && (event.button == 1)));
  1690 + },
  1691 +
  1692 + pointerX: function(event) {
  1693 + return event.pageX || (event.clientX +
  1694 + (document.documentElement.scrollLeft || document.body.scrollLeft));
  1695 + },
  1696 +
  1697 + pointerY: function(event) {
  1698 + return event.pageY || (event.clientY +
  1699 + (document.documentElement.scrollTop || document.body.scrollTop));
  1700 + },
  1701 +
  1702 + stop: function(event) {
  1703 + if (event.preventDefault) {
  1704 + event.preventDefault();
  1705 + event.stopPropagation();
  1706 + } else {
  1707 + event.returnValue = false;
  1708 + event.cancelBubble = true;
  1709 + }
  1710 + },
  1711 +
  1712 + // find the first node with the given tagName, starting from the
  1713 + // node the event was triggered on; traverses the DOM upwards
  1714 + findElement: function(event, tagName) {
  1715 + var element = Event.element(event);
  1716 + while (element.parentNode && (!element.tagName ||
  1717 + (element.tagName.toUpperCase() != tagName.toUpperCase())))
  1718 + element = element.parentNode;
  1719 + return element;
  1720 + },
  1721 +
  1722 + observers: false,
  1723 +
  1724 + _observeAndCache: function(element, name, observer, useCapture) {
  1725 + if (!this.observers) this.observers = [];
  1726 + if (element.addEventListener) {
  1727 + this.observers.push([element, name, observer, useCapture]);
  1728 + element.addEventListener(name, observer, useCapture);
  1729 + } else if (element.attachEvent) {
  1730 + this.observers.push([element, name, observer, useCapture]);
  1731 + element.attachEvent('on' + name, observer);
  1732 + }
  1733 + },
  1734 +
  1735 + unloadCache: function() {
  1736 + if (!Event.observers) return;
  1737 + for (var i = 0; i < Event.observers.length; i++) {
  1738 + Event.stopObserving.apply(this, Event.observers[i]);
  1739 + Event.observers[i][0] = null;
  1740 + }
  1741 + Event.observers = false;
  1742 + },
  1743 +
  1744 + observe: function(element, name, observer, useCapture) {
  1745 + var element = $(element);
  1746 + useCapture = useCapture || false;
  1747 +
  1748 + if (name == 'keypress' &&
  1749 + (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
  1750 + || element.attachEvent))
  1751 + name = 'keydown';
  1752 +
  1753 + this._observeAndCache(element, name, observer, useCapture);
  1754 + },
  1755 +
  1756 + stopObserving: function(element, name, observer, useCapture) {
  1757 + var element = $(element);
  1758 + useCapture = useCapture || false;
  1759 +
  1760 + if (name == 'keypress' &&
  1761 + (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
  1762 + || element.detachEvent))
  1763 + name = 'keydown';
  1764 +
  1765 + if (element.removeEventListener) {
  1766 + element.removeEventListener(name, observer, useCapture);
  1767 + } else if (element.detachEvent) {
  1768 + element.detachEvent('on' + name, observer);
  1769 + }
  1770 + }
  1771 +});
  1772 +
  1773 +/* prevent memory leaks in IE */
  1774 +if (navigator.appVersion.match(/\bMSIE\b/))
  1775 + Event.observe(window, 'unload', Event.unloadCache, false);
  1776 +var Position = {
  1777 + // set to true if needed, warning: firefox performance problems
  1778 + // NOT neeeded for page scrolling, only if draggable contained in
  1779 + // scrollable elements
  1780 + includeScrollOffsets: false,
  1781 +
  1782 + // must be called before calling withinIncludingScrolloffset, every time the
  1783 + // page is scrolled
  1784 + prepare: function() {
  1785 + this.deltaX = window.pageXOffset
  1786 + || document.documentElement.scrollLeft
  1787 + || document.body.scrollLeft
  1788 + || 0;
  1789 + this.deltaY = window.pageYOffset
  1790 + || document.documentElement.scrollTop
  1791 + || document.body.scrollTop
  1792 + || 0;
  1793 + },
  1794 +
  1795 + realOffset: function(element) {
  1796 + var valueT = 0, valueL = 0;
  1797 + do {
  1798 + valueT += element.scrollTop || 0;
  1799 + valueL += element.scrollLeft || 0;
  1800 + element = element.parentNode;
  1801 + } while (element);
  1802 + return [valueL, valueT];
  1803 + },
  1804 +
  1805 + cumulativeOffset: function(element) {
  1806 + var valueT = 0, valueL = 0;
  1807 + do {
  1808 + valueT += element.offsetTop || 0;
  1809 + valueL += element.offsetLeft || 0;
  1810 + element = element.offsetParent;
  1811 + } while (element);
  1812 + return [valueL, valueT];
  1813 + },
  1814 +
  1815 + positionedOffset: function(element) {
  1816 + var valueT = 0, valueL = 0;
  1817 + do {
  1818 + valueT += element.offsetTop || 0;
  1819 + valueL += element.offsetLeft || 0;
  1820 + element = element.offsetParent;
  1821 + if (element) {
  1822 + p = Element.getStyle(element, 'position');
  1823 + if (p == 'relative' || p == 'absolute') break;
  1824 + }
  1825 + } while (element);
  1826 + return [valueL, valueT];
  1827 + },
  1828 +
  1829 + offsetParent: function(element) {
  1830 + if (element.offsetParent) return element.offsetParent;
  1831 + if (element == document.body) return element;
  1832 +
  1833 + while ((element = element.parentNode) && element != document.body)
  1834 + if (Element.getStyle(element, 'position') != 'static')
  1835 + return element;
  1836 +
  1837 + return document.body;
  1838 + },
  1839 +
  1840 + // caches x/y coordinate pair to use with overlap
  1841 + within: function(element, x, y) {
  1842 + if (this.includeScrollOffsets)
  1843 + return this.withinIncludingScrolloffsets(element, x, y);
  1844 + this.xcomp = x;
  1845 + this.ycomp = y;
  1846 + this.offset = this.cumulativeOffset(element);
  1847 +
  1848 + return (y >= this.offset[1] &&
  1849 + y < this.offset[1] + element.offsetHeight &&
  1850 + x >= this.offset[0] &&
  1851 + x < this.offset[0] + element.offsetWidth);
  1852 + },
  1853 +
  1854 + withinIncludingScrolloffsets: function(element, x, y) {
  1855 + var offsetcache = this.realOffset(element);
  1856 +
  1857 + this.xcomp = x + offsetcache[0] - this.deltaX;
  1858 + this.ycomp = y + offsetcache[1] - this.deltaY;
  1859 + this.offset = this.cumulativeOffset(element);
  1860 +
  1861 + return (this.ycomp >= this.offset[1] &&
  1862 + this.ycomp < this.offset[1] + element.offsetHeight &&
  1863 + this.xcomp >= this.offset[0] &&
  1864 + this.xcomp < this.offset[0] + element.offsetWidth);
  1865 + },
  1866 +
  1867 + // within must be called directly before
  1868 + overlap: function(mode, element) {
  1869 + if (!mode) return 0;
  1870 + if (mode == 'vertical')
  1871 + return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
  1872 + element.offsetHeight;
  1873 + if (mode == 'horizontal')
  1874 + return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
  1875 + element.offsetWidth;
  1876 + },
  1877 +
  1878 + clone: function(source, target) {
  1879 + source = $(source);
  1880 + target = $(target);
  1881 + target.style.position = 'absolute';
  1882 + var offsets = this.cumulativeOffset(source);
  1883 + target.style.top = offsets[1] + 'px';
  1884 + target.style.left = offsets[0] + 'px';
  1885 + target.style.width = source.offsetWidth + 'px';
  1886 + target.style.height = source.offsetHeight + 'px';
  1887 + },
  1888 +
  1889 + page: function(forElement) {
  1890 + var valueT = 0, valueL = 0;
  1891 +
  1892 + var element = forElement;
  1893 + do {
  1894 + valueT += element.offsetTop || 0;
  1895 + valueL += element.offsetLeft || 0;
  1896 +
  1897 + // Safari fix
  1898 + if (element.offsetParent==document.body)
  1899 + if (Element.getStyle(element,'position')=='absolute') break;
  1900 +
  1901 + } while (element = element.offsetParent);
  1902 +
  1903 + element = forElement;
  1904 + do {
  1905 + valueT -= element.scrollTop || 0;
  1906 + valueL -= element.scrollLeft || 0;
  1907 + } while (element = element.parentNode);
  1908 +
  1909 + return [valueL, valueT];
  1910 + },
  1911 +
  1912 + clone: function(source, target) {
  1913 + var options = Object.extend({
  1914 + setLeft: true,
  1915 + setTop: true,
  1916 + setWidth: true,
  1917 + setHeight: true,
  1918 + offsetTop: 0,
  1919 + offsetLeft: 0
  1920 + }, arguments[2] || {})
  1921 +
  1922 + // find page position of source
  1923 + source = $(source);
  1924 + var p = Position.page(source);
  1925 +
  1926 + // find coordinate system to use
  1927 + target = $(target);
  1928 + var delta = [0, 0];
  1929 + var parent = null;
  1930 + // delta [0,0] will do fine with position: fixed elements,
  1931 + // position:absolute needs offsetParent deltas
  1932 + if (Element.getStyle(target,'position') == 'absolute') {
  1933 + parent = Position.offsetParent(target);
  1934 + delta = Position.page(parent);
  1935 + }
  1936 +
  1937 + // correct by body offsets (fixes Safari)
  1938 + if (parent == document.body) {
  1939 + delta[0] -= document.body.offsetLeft;
  1940 + delta[1] -= document.body.offsetTop;
  1941 + }
  1942 +
  1943 + // set position
  1944 + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
  1945 + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
  1946 + if(options.setWidth) target.style.width = source.offsetWidth + 'px';
  1947 + if(options.setHeight) target.style.height = source.offsetHeight + 'px';
  1948 + },
  1949 +
  1950 + absolutize: function(element) {
  1951 + element = $(element);
  1952 + if (element.style.position == 'absolute') return;
  1953 + Position.prepare();
  1954 +
  1955 + var offsets = Position.positionedOffset(element);
  1956 + var top = offsets[1];
  1957 + var left = offsets[0];
  1958 + var width = element.clientWidth;
  1959 + var height = element.clientHeight;
  1960 +
  1961 + element._originalLeft = left - parseFloat(element.style.left || 0);
  1962 + element._originalTop = top - parseFloat(element.style.top || 0);
  1963 + element._originalWidth = element.style.width;
  1964 + element._originalHeight = element.style.height;
  1965 +
  1966 + element.style.position = 'absolute';
  1967 + element.style.top = top + 'px';;
  1968 + element.style.left = left + 'px';;
  1969 + element.style.width = width + 'px';;
  1970 + element.style.height = height + 'px';;
  1971 + },
  1972 +
  1973 + relativize: function(element) {
  1974 + element = $(element);
  1975 + if (element.style.position == 'relative') return;
  1976 + Position.prepare();
  1977 +
  1978 + element.style.position = 'relative';
  1979 + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
  1980 + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
  1981 +
  1982 + element.style.top = top + 'px';
  1983 + element.style.left = left + 'px';
  1984 + element.style.height = element._originalHeight;
  1985 + element.style.width = element._originalWidth;
  1986 + }
  1987 +}
  1988 +
  1989 +// Safari returns margins on body which is incorrect if the child is absolutely
  1990 +// positioned. For performance reasons, redefine Position.cumulativeOffset for
  1991 +// KHTML/WebKit only.
  1992 +if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  1993 + Position.cumulativeOffset = function(element) {
  1994 + var valueT = 0, valueL = 0;
  1995 + do {
  1996 + valueT += element.offsetTop || 0;
  1997 + valueL += element.offsetLeft || 0;
  1998 + if (element.offsetParent == document.body)
  1999 + if (Element.getStyle(element, 'position') == 'absolute') break;
  2000 +
  2001 + element = element.offsetParent;
  2002 + } while (element);
  2003 +
  2004 + return [valueL, valueT];
  2005 + }
  2006 +}
0 2007 \ No newline at end of file
... ...