+++ /dev/null
-<?php
-
-/** Tell the registry to take everything from this application directory. */
-if (!defined('HORDE_BASE')) {
- define('HORDE_BASE', dirname(__FILE__) . '/..');
-}
-
-/**
- * The Autoloader allows us to omit "require/include" statements.
- */
-require_once 'Horde/Autoloader.php';
-
-/** Configure the Autoloader to handle the "Koward" pattern */
-Horde_Autoloader::addClassPattern('/^Koward_/', 'Koward/');
-
-/** Dispatch the request. */
-try {
- Koward::dispatch(__FILE__);
-} catch (Exception $e) {
- // @TODO Make nicer
- echo '<h1>' . $e->getMessage() . '</h1>';
- echo '<pre>'; var_dump($e); echo '</pre>';
-}
+++ /dev/null
-/*
- Local variables:
- buffer-file-coding-system: utf-8
- End:
-*/
-body {
- color: black;
- background-color: #F8FCF8;
- font-family: verdana,arial,helvetica,sans-serif;
- font-size: 95%;
- border: 0;
- margin: 0;
-}
-a, a:visited {
- font-family: verdana,arial,helvetica,sans-serif;
-}
-
-a { color: #001155; }
-a:hover { color: #113399; }
-
-#page {
- background-repeat: no-repeat;
- background-position: top right;
-}
-
-#topbar {
- display:block;
- background-color: #B0BCD0;
- height: 70px;
- clear: both;
-}
-#toplogo {
- display:block;
- background-image: url(pics/kolab_logo.png);
- background-color: #B0BCD0;
- width: 245px;
- height: 70px;
- margin-left: 1em;
- margin-top: 0.4em;
- float: left;
-}
-#toptitle {
- display:block;
- text-align: right;
- font-size: 200%;
- padding-right: 1em;
- padding-top: 0.5em;
-}
-#topuserinfo {
- display:block;
- background-color: #B0BCD0;
- font-size: 80%;
- padding: 0.1em;
- border-bottom: solid 1px black;
- text-align: right;
-}
-#topmenu {
- background-color: #B0BCD0;
- font-size: 90%;
- border-bottom: solid 1px black;
-}
-#submenu {
- background-color: #EEEEEE;
- border-bottom: solid 1px black;
- font-size: 90%;
-}
-
-.topmenuitem {
- background-color: #B0BCD0;
- border-right: solid 1px black;
- padding-left: 0.5em;
- padding-right: 0.5em;
- margin: 0px;
-}
-.topmenuitemselected {
- background-color: #EEEEEE;
- border-right: solid 1px black;
- padding-left: 0.5em;
- padding-right: 0.5em;
- margin: 0px;
- border-bottom: solid 1px #EEEEEE;
-}
-.submenuitem {
-}
-.submenuitemselected {
-}
-.alphagroupitem {
-}
-.alphagroupitemselected {
- font-weight:bold
-}
-#logout {
- color: red;
-}
-#maintitle {
- font-size: 200%;
-}
-#maincontent {
- display:block;
- padding: 1em;
- margin: 1em;
-}
-#errorcontent {
- display:block;
- padding: 0.2em;
- margin: 1em;
- text-align: left;
- color: red;
- background-color: #EEEEEE;
- border: solid 1px black;
-}
-#errorheader {
- display:block;
- text-align: left;
- color: black;
- background-color: #EEEEEE;
- font-size: 150%;
-}
-#messagecontent {
- display:block;
- padding: 0.2em;
- margin: 1em;
- text-align: left;
- color: green;
- background-color: #EEEEEE;
- border: solid 1px black;
-}
-#messageheader {
- display:block;
- text-align: left;
- color: black;
- background-color: #EEEEEE;
- font-size: 150%;
-}
-.contenttext {
- margin: 10px;
-}
-.contenttable {
- width: 100%;
- background-color: black;
- border: 0px;
-}
-.contentroweven {
- background-color: #C0CDE0;
- margin: 0px;
-}
-.contentrowodd {
- background-color: #D0DDF0;
- margin: 0px;
-}
-.contentcell {
- font-size: 90%;
- padding: .1em .5em .1em .5em;
- margin: 0px;
-/* text-align: center; */
-}
-.actioncell {
- font-size: 90%;
- padding: .1em .5em .1em .5em;
- width: 10%;
- margin: 0px;
- text-align: center;
-}
-.contentform {
- /*float: left;*/
- padding: .1em .5em .1em .5em;
- background-color: #EEEEEE;
- border: solid 1px black;
-}
-.contentformtable {
- font-size: 90%;
-}
-.langcombo {
- font-size: 80%;
-}
-
-#validators {
- text-align: right;
-}
-
-th {
- background-color: #EEEEEE;
- border: 0px;
-}
-
-.ctrl {
- background-color: #E0E3E0;
- border: solid 1px black;
- padding: .2em .5em .2em .5em;
-}
-
-.required_asterisk {
- color: red;
- font-size: 80%;
- text-align: right;
-}
-
-label {
- cursor: pointer;
-}
-
-.align_center {
- text-align: center;
-}
-
-.align_right {
- text-align: right;
-}
-
-.align_left {
- text-align: left;
-}
+++ /dev/null
-/**
- * Style for Koward.
- */
+++ /dev/null
-*.php
-*.local.php
+++ /dev/null
-<?php
-
-$attributes['givenName'] = array(
- 'label' => _("First Name"),
- 'type' => 'text',
- 'required' => true,
- 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
-);
-$attributes['sn'] = array(
- 'label' => _("Last Name"),
- 'type' => 'text',
- 'required' => true,
- 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
-);
-$attributes['mail'] = array(
- 'label' => _("Mail address"),
- 'type' => 'text',
- 'required' => true,
- 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
-);
-$attributes['uid'] = array(
- 'label' => _("User ID"),
- 'type' => 'text',
- 'required' => true,
- 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
-);
+++ /dev/null
-<?php
-
-$conf['use_ssl'] = 2;
-$conf['server']['name'] = $_SERVER['SERVER_NAME'];
-$conf['server']['port'] = $_SERVER['SERVER_PORT'];
-$conf['cookie']['domain'] = $_SERVER['SERVER_NAME'];
-$conf['cookie']['path'] = '/';
-$conf['debug_level'] = E_ALL & ~E_NOTICE;
-$conf['umask'] = 077;
-$conf['compress_pages'] = true;
-$conf['session']['name'] = 'Horde';
-$conf['session']['cache_limiter'] = 'nocache';
-$conf['session']['timeout'] = 0;
-$conf['urls']['token_lifetime'] = 20;
-$conf['server']['token_lifetime'] = 20;
-$conf['auth']['admins'] = array('Administrator');
-$conf['auth']['driver'] = 'kolab';
-$conf['auth']['params'] = array();
-$conf['prefs']['driver'] = 'session';
-$conf['menu']['always'] = false;
-$conf['menu']['links']['logout'] = 'authenticated';
-$conf['portal']['fixed_blocks'] = array();
-$conf['imsp']['enabled'] = false;
-$conf['kolab']['enabled'] = true;
-$conf['kolab']['server']['driver'] = 'ldap';
-$conf['kolab']['imap']['allow_special_users'] = true;
-$conf['log']['priority'] = PEAR_LOG_DEBUG;
-$conf['log']['ident'] = 'HORDE';
-$conf['log']['params'] = array();
-$conf['log']['name'] = '/tmp/horde.log';
-$conf['log']['params']['append'] = true;
-$conf['log']['type'] = 'file';
-$conf['log']['enabled'] = true;
+++ /dev/null
-<?php
-
-$conf['koward']['theme'] = 'silver';
+++ /dev/null
-<?php
-
-$labels['cn'] = _("Common Name");
-$labels['kolabSalutation'] = _("Salutation");
-$labels['givenName'] = _("First Name");
-$labels['middleNames'] = _("Additional Names");
-$labels['sn'] = _("Last Name");
-$labels['snsuffix'] = _("Name Suffix");
-$labels['personalTitle'] = _("Title");
-$labels['userPassword'] = _("Password");
-$labels['telephoneNumber'] = _("Phone");
-$labels['postOfficeBox'] = _("Post Office Box");
-$labels['street'] = _("Street");
-$labels['title'] = _("Job Title");
-$labels['postalCode'] = _("Postal Code");
-$labels['facsimileTelephoneNumber'] = _("Fax");
-$labels['l'] = _("City");
-$labels['jpegPhoto'] = _("Photo");
-$labels['mail'] = _("Mail Address");
-$labels['mobile'] = _("Mobile Phone");
-$labels['homePhone'] = _("Home Phone");
-$labels['homePostalAddress'] = _("Home Postal Address");
-$labels['labeledURI'] = _("Website");
-$labels['o'] = _("Company");
-$labels['birthName'] = _("Birth Name");
-$labels['kolabMaritalStatus'] = _("Marital Status");
-$labels['dateOfBirth'] = _("Date Of Birth");
-$labels['placeOfBirth'] = _("Place Of Birth");
-$labels['gender'] = _("Gender");
-
+++ /dev/null
-<?php
-/**
- * NLS (National Language Support) configuration file.
- *
- * $Horde: horde/config/nls.php.dist,v 1.77 2008/10/14 21:11:47 jan Exp $
- */
-
-/**
- ** Defaults
- **/
-
-/* The language to fall back on if we cannot determine one any other
- way (user choice or preferences). If empty, we will try to negotiate
- with the browser using HTTP_ACCEPT_LANGUAGE. */
-$nls['defaults']['language'] = '';
-
-
-/**
- ** Language
- **/
-
-$nls['languages']['ar_OM'] = '‭Arabic (Oman) ‮(العربية)';
-$nls['languages']['ar_SY'] = '‭Arabic (Syria) ‮(العربية)';
-$nls['languages']['id_ID'] = 'Bahasa Indonesia';
-$nls['languages']['bs_BA'] = 'Bosanski';
-$nls['languages']['bg_BG'] = '‭Bulgarian (Български)';
-$nls['languages']['ca_ES'] = 'Català';
-$nls['languages']['zh_CN'] = '‭Chinese (Simplified) (简体中文)';
-$nls['languages']['zh_TW'] = '‭Chinese (Traditional) (正體中文)';
-$nls['languages']['cs_CZ'] = '‭Czech (Česky)';
-$nls['languages']['da_DK'] = 'Dansk';
-$nls['languages']['de_DE'] = 'Deutsch';
-$nls['languages']['en_US'] = '‭English (American)';
-$nls['languages']['en_GB'] = '‭English (British)';
-$nls['languages']['en_CA'] = '‭English (Canadian)';
-$nls['languages']['es_ES'] = 'Español';
-$nls['languages']['et_EE'] = 'Eesti';
-$nls['languages']['eu_ES'] = 'Euskara';
-$nls['languages']['fr_FR'] = 'Français';
-$nls['languages']['gl_ES'] = 'Galego';
-$nls['languages']['el_GR'] = '‭Greek (Ελληνικά)';
-$nls['languages']['he_IL'] = '‭Hebrew ‮(עברית)';
-$nls['languages']['is_IS'] = 'Íslenska';
-$nls['languages']['it_IT'] = 'Italiano';
-$nls['languages']['ja_JP'] = '‭Japanese (日本語)';
-$nls['languages']['km_KH'] = '‭Khmer (ខ្មែរ)';
-$nls['languages']['ko_KR'] = '‭Korean (한국어)';
-$nls['languages']['lv_LV'] = 'Latviešu';
-$nls['languages']['lt_LT'] = 'Lietuvių';
-$nls['languages']['mk_MK'] = '‭Macedonian (Македонски)';
-$nls['languages']['hu_HU'] = 'Magyar';
-$nls['languages']['nl_NL'] = 'Nederlands';
-$nls['languages']['nb_NO'] = 'Norsk bokmål';
-$nls['languages']['nn_NO'] = 'Norsk nynorsk';
-$nls['languages']['fa_IR'] = '‭Persian ‮(فارسى)';
-$nls['languages']['pl_PL'] = 'Polski';
-$nls['languages']['pt_PT'] = 'Português';
-$nls['languages']['pt_BR'] = 'Português Brasileiro';
-$nls['languages']['ro_RO'] = 'Românä';
-$nls['languages']['ru_RU'] = '‭Russian (Русский)';
-$nls['languages']['sk_SK'] = '‭Slovak (Slovenčina)';
-$nls['languages']['sl_SI'] = '‭Slovenian (Slovenščina)';
-$nls['languages']['fi_FI'] = 'Suomi';
-$nls['languages']['sv_SE'] = 'Svenska';
-$nls['languages']['th_TH'] = '‭Thai (ไทย)';
-if (version_compare(PHP_VERSION, '5', 'lt') || version_compare(PHP_VERSION, '6', 'ge')) {
- $nls['languages']['tr_TR'] = 'Türkçe';
-}
-$nls['languages']['uk_UA'] = '‭Ukrainian (Українська)';
-
-
-/**
- ** Aliases for languages with different browser and gettext codes
- **/
-
-$nls['aliases']['ar'] = 'ar_SY';
-$nls['aliases']['bg'] = 'bg_BG';
-$nls['aliases']['bs'] = 'bs_BA';
-$nls['aliases']['ca'] = 'ca_ES';
-$nls['aliases']['cs'] = 'cs_CZ';
-$nls['aliases']['da'] = 'da_DK';
-$nls['aliases']['de'] = 'de_DE';
-$nls['aliases']['el'] = 'el_GR';
-$nls['aliases']['en'] = 'en_US';
-$nls['aliases']['es'] = 'es_ES';
-$nls['aliases']['et'] = 'et_EE';
-$nls['aliases']['fa'] = 'fa_IR';
-$nls['aliases']['fi'] = 'fi_FI';
-$nls['aliases']['fr'] = 'fr_FR';
-$nls['aliases']['gl'] = 'gl_ES';
-$nls['aliases']['he'] = 'he_IL';
-$nls['aliases']['hu'] = 'hu_HU';
-$nls['aliases']['id'] = 'id_ID';
-$nls['aliases']['is'] = 'is_IS';
-$nls['aliases']['it'] = 'it_IT';
-$nls['aliases']['ja'] = 'ja_JP';
-$nls['aliases']['km'] = 'km_KH';
-$nls['aliases']['ko'] = 'ko_KR';
-$nls['aliases']['lt'] = 'lt_LT';
-$nls['aliases']['lv'] = 'lv_LV';
-$nls['aliases']['mk'] = 'mk_MK';
-$nls['aliases']['nl'] = 'nl_NL';
-$nls['aliases']['nn'] = 'nn_NO';
-$nls['aliases']['no'] = 'nb_NO';
-$nls['aliases']['pl'] = 'pl_PL';
-$nls['aliases']['pt'] = 'pt_PT';
-$nls['aliases']['ro'] = 'ro_RO';
-$nls['aliases']['ru'] = 'ru_RU';
-$nls['aliases']['sk'] = 'sk_SK';
-$nls['aliases']['sl'] = 'sl_SI';
-$nls['aliases']['sv'] = 'sv_SE';
-$nls['aliases']['th'] = 'th_TH';
-if (version_compare(PHP_VERSION, '5', 'lt') || version_compare(PHP_VERSION, '6', 'ge')) {
- $nls['aliases']['tr'] = 'tr_TR';
-}
-$nls['aliases']['uk'] = 'uk_UA';
-
-
-/**
- ** Charsets. These differ somewhat on different systems; see below
- ** for a set of BSD charset names.
- **/
-
-$nls['charsets']['ar_OM'] = 'windows-1256';
-$nls['charsets']['ar_SY'] = 'windows-1256';
-$nls['charsets']['bg_BG'] = 'windows-1251';
-$nls['charsets']['bs_BA'] = 'ISO-8859-2';
-$nls['charsets']['cs_CZ'] = 'ISO-8859-2';
-$nls['charsets']['el_GR'] = 'ISO-8859-7';
-$nls['charsets']['eu_ES'] = 'UTF-8';
-$nls['charsets']['fa_IR'] = 'UTF-8';
-$nls['charsets']['he_IL'] = 'UTF-8';
-$nls['charsets']['hu_HU'] = 'ISO-8859-2';
-$nls['charsets']['ja_JP'] = 'SHIFT_JIS';
-$nls['charsets']['km_KH'] = 'UTF-8';
-$nls['charsets']['ko_KR'] = 'EUC-KR';
-$nls['charsets']['lt_LT'] = 'ISO-8859-13';
-$nls['charsets']['lv_LV'] = 'windows-1257';
-$nls['charsets']['mk_MK'] = 'ISO-8859-5';
-$nls['charsets']['pl_PL'] = 'ISO-8859-2';
-$nls['charsets']['ru_RU'] = 'windows-1251';
-$nls['charsets']['ru_RU.KOI8-R'] = 'KOI8-R';
-$nls['charsets']['sk_SK'] = 'ISO-8859-2';
-$nls['charsets']['sl_SI'] = 'ISO-8859-2';
-$nls['charsets']['th_TH'] = 'TIS-620';
-if (version_compare(PHP_VERSION, '5', 'lt') || version_compare(PHP_VERSION, '6', 'ge')) {
- $nls['charsets']['tr_TR'] = 'ISO-8859-9';
-}
-$nls['charsets']['uk_UA'] = 'windows-1251';
-$nls['charsets']['zh_CN'] = 'GB2312';
-$nls['charsets']['zh_TW'] = 'BIG5';
-
-/**
- * BSD charsets.
- */
-if (strpos(PHP_OS, 'BSD') !== false) {
- $nls['charsets']['ar_OM'] = 'windows-1256';
- $nls['charsets']['ar_SY'] = 'windows-1256';
- $nls['charsets']['bg_BG'] = 'windows-1251';
- $nls['charsets']['bs_BA'] = 'ISO8859-2';
- $nls['charsets']['cs_CZ'] = 'ISO8859-2';
- $nls['charsets']['el_GR'] = 'ISO8859-7';
- $nls['charsets']['eu_ES'] = 'UTF-8';
- $nls['charsets']['fa_IR'] = 'UTF-8';
- $nls['charsets']['he_IL'] = 'UTF-8';
- $nls['charsets']['hu_HU'] = 'ISO8859-2';
- $nls['charsets']['ja_JP'] = 'SHIFT_JIS';
- $nls['charsets']['km_KH'] = 'UTF-8';
- $nls['charsets']['ko_KR'] = 'EUC-KR';
- $nls['charsets']['lt_LT'] = 'ISO8859-13';
- $nls['charsets']['lv_LV'] = 'windows-1257';
- $nls['charsets']['mk_MK'] = 'ISO8859-5';
- $nls['charsets']['pl_PL'] = 'ISO8859-2';
- $nls['charsets']['ru_RU'] = 'windows-1251';
- $nls['charsets']['ru_RU.KOI8-R'] = 'KOI8-R';
- $nls['charsets']['sk_SK'] = 'ISO8859-2';
- $nls['charsets']['sl_SI'] = 'ISO8859-2';
- $nls['charsets']['th_TH'] = 'TIS-620';
- if (version_compare(PHP_VERSION, '5', 'lt') ||
- version_compare(PHP_VERSION, '6', 'ge')) {
- $nls['charsets']['tr_TR'] = 'ISO-8859-9';
- }
- $nls['charsets']['uk_UA'] = 'windows-1251';
- $nls['charsets']['zh_CN'] = 'GB2312';
- $nls['charsets']['zh_TW'] = 'BIG5';
-}
-
-
-/**
- ** Multibyte charsets
- **/
-
-$nls['multibyte']['BIG5'] = true;
-$nls['multibyte']['EUC-KR'] = true;
-$nls['multibyte']['GB2312'] = true;
-$nls['multibyte']['SHIFT_JIS'] = true;
-$nls['multibyte']['UTF-8'] = true;
-
-
-/**
- ** Right-to-left languages
- **/
-
-$nls['rtl']['ar_OM'] = true;
-$nls['rtl']['ar_SY'] = true;
-$nls['rtl']['fa_IR'] = true;
-$nls['rtl']['he_IL'] = true;
-
-
-/**
- ** Preferred charsets for email traffic if not the languages' default
- ** charsets.
- **/
-
-$nls['emails']['ja_JP'] = 'ISO-2022-JP';
-
-
-/**
- ** Available charsets for outgoing email traffic.
- **/
-
-$nls['encodings']['windows-1256'] = _("Arabic (Windows-1256)");
-$nls['encodings']['ARMSCII-8'] = _("Armenian (ARMSCII-8)");
-$nls['encodings']['ISO-8859-13'] = _("Baltic (ISO-8859-13)");
-$nls['encodings']['ISO-8859-14'] = _("Celtic (ISO-8859-14)");
-$nls['encodings']['ISO-8859-2'] = _("Central European (ISO-8859-2)");
-$nls['encodings']['GB2312'] = _("Chinese Simplified (GB2312)");
-$nls['encodings']['BIG5'] = _("Chinese Traditional (Big5)");
-$nls['encodings']['KOI8-R'] = _("Cyrillic (KOI8-R)");
-$nls['encodings']['windows-1251'] = _("Cyrillic (Windows-1251)");
-$nls['encodings']['KOI8-U'] = _("Cyrillic/Ukrainian (KOI8-U)");
-$nls['encodings']['ISO-8859-7'] = _("Greek (ISO-8859-7)");
-$nls['encodings']['ISO-8859-8-I'] = _("Hebrew (ISO-8859-8-I)");
-$nls['encodings']['ISO-2022-JP'] = _("Japanese (ISO-2022-JP)");
-$nls['encodings']['EUC-KR'] = _("Korean (EUC-KR)");
-$nls['encodings']['ISO-8859-10'] = _("Nordic (ISO-8859-10)");
-$nls['encodings']['ISO-8859-3'] = _("South European (ISO-8859-3)");
-$nls['encodings']['TIS-620'] = _("Thai (TIS-620)");
-$nls['encodings']['ISO-8859-9'] = _("Turkish (ISO-8859-9)");
-$nls['encodings']['UTF-8'] = _("Unicode (UTF-8)");
-$nls['encodings']['VISCII'] = _("Vietnamese (VISCII)");
-$nls['encodings']['ISO-8859-1'] = _("Western (ISO-8859-1)");
-$nls['encodings']['ISO-8859-15'] = _("Western (ISO-8859-15)");
-asort($nls['encodings']);
-
-
-/**
- ** Multi-language spelling support
- **/
-
-$nls['spelling']['cs_CZ'] = '-T latin2 -d czech';
-$nls['spelling']['da_DK'] = '-d dansk';
-$nls['spelling']['de_DE'] = '-T latin1 -d deutsch';
-$nls['spelling']['el_GR'] = '-T latin1 -d ellinika';
-$nls['spelling']['en_CA'] = '-d canadian';
-$nls['spelling']['en_GB'] = '-d british';
-$nls['spelling']['en_US'] = '-d american';
-$nls['spelling']['es_ES'] = '-d espanol';
-$nls['spelling']['fr_FR'] = '-d francais';
-$nls['spelling']['it_IT'] = '-T latin1 -d italian';
-$nls['spelling']['nl_NL'] = '-d nederlands';
-$nls['spelling']['pl_PL'] = '-d polish';
-$nls['spelling']['pt_BR'] = '-d br';
-$nls['spelling']['pt_PT'] = '-T latin1 -d portuguese';
-$nls['spelling']['ru_RU'] = '-d russian';
-$nls['spelling']['sl_SI'] = '-d slovensko';
-$nls['spelling']['sv_SE'] = '-d svenska';
-if (isset($nls['charsets']['tr_TR'])) {
- $nls['spelling']['tr_TR'] = '-d tr';
-}
-
-$GLOBALS['nls'] = &$nls;
+++ /dev/null
-<?php
-
-/* $objects['object'] = array( */
-/* 'class' => 'Horde_Kolab_Server_Object', */
-/* 'label' => _("Object"), */
-/* 'list_label' => _("Objects"), */
-/* 'list_attributes' => array( */
-/* 'id' => array( */
-/* 'title' => _("Object id"), */
-/* 'width' => 80, */
-/* 'link_view'=> true, */
-/* ), */
-/* ), */
-/* 'attributes' => array( */
-/* 'override' => true, */
-/* 'fields' => array( */
-/* 'id' => array( */
-/* 'label' => _("Object ID"), */
-/* 'type' => 'text', */
-/* 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255) */
-/* ), */
-/* ), */
-/* ), */
-/* ); */
-
-/* $objects['person'] = array( */
-/* 'class' => 'Horde_Kolab_Server_Object_Person', */
-/* 'label' => _("Person"), */
-/* 'list_label' => _("Persons"), */
-/* 'list_attributes' => array( */
-/* 'cn' => array( */
-/* 'title' => _("Common name"), */
-/* 'width' => 40, */
-/* 'link_view'=> true, */
-/* ), */
-/* 'sn' => array( */
-/* 'title' => _("Last name"), */
-/* 'width' => 40, */
-/* ), */
-/* ), */
-/* 'attributes' => array( */
-/* 'fields' => array( */
-/* 'cn' => array( */
-/* 'required' => false, */
-/* ), */
-/* 'userPassword' => array( */
-/* 'required' => true, */
-/* ), */
-/* ), */
-/* ), */
-/* ); */
-
-/* $objects['organizationalperson'] = array( */
-/* 'class' => 'Horde_Kolab_Server_Object_Organizationalperson', */
-/* 'label' => _("Organizational person"), */
-/* 'list_label' => _("Organizational persons"), */
-/* 'list_attributes' => array( */
-/* 'cn' => array( */
-/* 'title' => _("Common name"), */
-/* 'width' => 40, */
-/* 'link_view'=> true, */
-/* ), */
-/* 'sn' => array( */
-/* 'title' => _("Last name"), */
-/* 'width' => 40, */
-/* ), */
-/* ), */
-/* 'attributes' => array( */
-/* 'fields' => array( */
-/* 'cn' => array( */
-/* 'required' => false, */
-/* ), */
-/* 'userPassword' => array( */
-/* 'required' => true, */
-/* ), */
-/* ), */
-/* ), */
-/* ); */
-
-/* $objects['inetperson'] = array( */
-/* 'class' => 'Horde_Kolab_Server_Object_Inetorgperson', */
-/* 'label' => _("Inet person"), */
-/* 'list_label' => _("Inet persons"), */
-/* 'list_attributes' => array( */
-/* 'cn' => array( */
-/* 'title' => _("Common name"), */
-/* 'width' => 40, */
-/* 'link_view'=> true, */
-/* ), */
-/* 'sn' => array( */
-/* 'title' => _("Last name"), */
-/* 'width' => 40, */
-/* ), */
-/* ), */
-/* 'attributes' => array( */
-/* 'fields' => array( */
-/* 'cn' => array( */
-/* 'required' => false, */
-/* ), */
-/* 'userPassword' => array( */
-/* 'required' => true, */
-/* ), */
-/* ), */
-/* ), */
-/* ); */
-
-/* $objects['user'] = array( */
-/* 'class' => 'Horde_Kolab_Server_Object_Kolab_User', */
-/* 'label' => _("User"), */
-/* 'list_label' => _("Users"), */
-/* 'list_attributes' => array( */
-/* 'sn' => array( */
-/* 'title' => _("Last name"), */
-/* 'width' => 20, */
-/* ), */
-/* 'givenName' => array( */
-/* 'title' => _("First name"), */
-/* 'width' => 20, */
-/* ), */
-/* 'mail' => array( */
-/* 'title' => _("E-mail"), */
-/* 'width' => 20, */
-/* 'link_view'=> true, */
-/* ), */
-/* 'uid' => array( */
-/* 'title' => _("User ID"), */
-/* 'width' => 20, */
-/* ), */
-/* ), */
-/* ); */
-
-/* $objects['admin'] = array( */
-/* 'class' => 'Horde_Kolab_Server_Object_Kolab_Administrator', */
-/* 'label' => _("Administrator"), */
-/* 'list_label' => _("Administrators"), */
-/* 'attributes' => array( */
-/* ), */
-/* ); */
-
-/* $objects['kolabuser'] = array( */
-/* 'class' => 'Horde_Kolab_Server_Object_Kolab_User', */
-/* 'preferred' => true, */
-/* 'label' => _("Kolab user"), */
-/* 'list_label' => _("Kolab users"), */
-/* 'list_attributes' => array( */
-/* 'sn' => array( */
-/* 'title' => _("Last name"), */
-/* 'width' => 20, */
-/* ), */
-/* 'givenName' => array( */
-/* 'title' => _("First name"), */
-/* 'width' => 20, */
-/* ), */
-/* 'mail' => array( */
-/* 'title' => _("E-mail"), */
-/* 'width' => 20, */
-/* 'link_view'=> true, */
-/* ), */
-/* 'uid' => array( */
-/* 'title' => _("User ID"), */
-/* 'width' => 20, */
-/* ), */
-/* ), */
-/* 'attributes' => array( */
-/* 'hide' => array( */
-/* 'objectClass', */
-/* 'seeAlso', */
-/* 'x121Address', */
-/* 'registeredAddress', */
-/* 'destinationIndicator', */
-/* 'preferredDeliveryMethod', */
-/* 'telexNumber', */
-/* 'teletexTerminalIdentifier', */
-/* 'internationaliSDNNumber', */
-/* 'kolabEncryptedPassword', */
-/* 'kolabHomeMTA', */
-/* 'kolabDelegate', */
-/* ), */
-/* 'labels' => array( */
-/* 'mail' => _("Account ID"), */
-/* ), */
-/* 'fields' => array( */
-/* 'kolabSalutation' => array( */
-/* 'type' => 'enum', */
-/* 'params' => array('values' => array(_("Mr.") => _("Mr."), */
-/* _("Mrs.") => _("Mrs.")), */
-/* 'prompt' => true), */
-/* ), */
-/* 'gender' => array( */
-/* 'type' => 'enum', */
-/* 'params' => array('values' => array(_("1") => _("male"), */
-/* _("2") => _("female")), */
-/* 'prompt' => true), */
-/* ), */
-/* 'kolabMaritalStatus' => array( */
-/* 'type' => 'enum', */
-/* 'params' => array('values' => array(_("0") => _("single"), */
-/* _("1") => _("married")), */
-/* 'prompt' => true), */
-/* ), */
-/* 'userPassword' => array( */
-/* 'type' => 'passwordconfirm', */
-/* ), */
-/* ), */
-/* ), */
-/* ); */
-
-if (file_exists(dirname(__FILE__) . '/objects.local.php')) {
- require_once(dirname(__FILE__) . '/objects.local.php');
-}
+++ /dev/null
-<?php
-$order['mail'] = 1;
-$order['kolabSalutation'] = 2;
-$order['givenName'] = 3;
-$order['middleNames'] = 4;
-$order['sn'] = 5;
-$order['snsuffix'] = 6;
-$order['gender'] = 7;
-$order['userPassword'] = 10;
-$order['dateOfBirth'] = 12;
-$order['placeOfBirth'] = 13;
-$order['kolabMaritalStatus'] = 14;
-$order['birthName'] = 15;
-$order['telephoneNumber'] = 30;
-$order['mobile'] = 31;
-$order['facsimileTelephoneNumber'] = 32;
-$order['homePhone'] = 33;
+++ /dev/null
-<?php
-/**
- * registry.php -- Horde application registry.
- *
- * $Horde: horde/config/registry.php.dist,v 1.306 2009/01/14 20:51:07 chuck Exp $
- *
- * This configuration file is used by Horde to determine which Horde
- * applications are installed and where, as well as how they interact.
- *
- * Application registry
- * --------------------
- * The following settings register installed Horde applications.
- * By default, Horde assumes that the application directories live
- * inside the horde directory.
- *
- * Attribute Type Description
- * --------- ---- -----------
- * fileroot string The base filesystem path for the module's files.
- * webroot string The base URI for the module.
- * jsuri string The base URI for static javascript files.
- * jsfs string The base filesystem path for static javascript files.
- * themesuri string The base URI for the themes. This can be used to
- * serve all icons and style sheets from a separate
- * server.
- * themesfs string The base file system directory for the themes.
- * icon string The URI for an icon to show in menus for the module.
- * Setting this will override the default theme-based
- * logic in the code.
- * name string The name used in menus and descriptions for a module
- * status string 'inactive', 'hidden', 'notoolbar', 'heading',
- * 'block', 'admin', or 'active'.
- * provides string Service types the module provides.
- * initial_page string The initial (default) page (filename) for the module.
- * templates string The filesystem path to the templates directory.
- * menu_parent string The name of the 'heading' group that this app should
- * show up under.
- * target string The (optional) target frame for the link.
- * url string The (optional) URL of 'heading' entries.
- */
-
-// We try to automatically determine the proper webroot for Horde here. This
-// still assumes that applications live under horde/. If this results in
-// incorrect results for you, simply change the 'webroot' setting in the
-// 'horde' stanza below.
-
-$this->applications['horde'] = array(
- 'fileroot' => dirname(__FILE__) . '/..',
- 'webroot' => '/',
- 'initial_page' => 'login.php',
- 'name' => _("Horde"),
- 'status' => 'active',
- 'templates' => dirname(__FILE__) . '/../templates',
- 'provides' => 'horde',
- 'themesuri' => '/app/themes',
- 'themesfs' => dirname(__FILE__) . '/../app/themes',
-);
-
-$this->applications['koward'] = array(
- 'fileroot' => dirname(__FILE__) . '/..',
- 'webroot' => $this->applications['horde']['webroot'] . '/app',
- 'name' => _("Koward"),
- 'status' => 'active',
- 'initial_page' => 'index.php',
- 'themesuri' => '/app/themes',
- 'themesfs' => dirname(__FILE__) . '/../app/themes',
-);
+++ /dev/null
-<?php
-
-$mapper->connect('index', array('controller' => 'index'));
-$mapper->connect('index.php', array('controller' => 'index'));
-
-$mapper->connect('check/:action/:id', array('controller' => 'check', 'action' => 'show'));
-$mapper->connect(':controller/:action/:id', array('controller' => 'object'));
-
-// Local route overrides
-if (file_exists(dirname(__FILE__) . '/routes.local.php')) {
- include dirname(__FILE__) . '/routes.local.php';
-}
+++ /dev/null
-<?php
-
-$search = array(
- 'fields' => array(
- 'givenName' => array(
- 'label' => _("First Name"),
- 'type' => 'text',
- 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
- ),
- )
-);
-
-if (file_exists(dirname(__FILE__) . '/search.local.php')) {
- require_once(dirname(__FILE__) . '/search.local.php');
-}
+++ /dev/null
-<?php
-$visible['hide'] = array(
- 'objectClass',
- 'id',
- 'lnfn',
- 'fnln',
- 'seeAlso',
- 'description',
- 'physicalDeliveryOfficeName',
- 'internationaliSDNNumber',
- 'x121Address',
- 'registeredAddress',
- 'destinationIndicator',
- 'preferredDeliveryMethod',
- 'telexNumber',
- 'teletexTerminalIdentifier',
- 'postalAddress',
- 'ou',
- 'st',
- 'manager',
- 'uid',
- 'employeeType',
- 'photo',
- 'x500uniqueIdentifier',
- 'secretary',
- 'userSMIMECertificate',
- 'employeeNumber',
- 'initials',
- 'audio',
- 'pager',
- 'businessCategory',
- 'roomNumber',
- 'carLicense',
- 'userCertificate',
- 'departmentNumber',
- 'preferredLanguage',
- 'displayName',
- 'userPKCS12',
- 'kolabVacationEndDateTime',
- 'kolabVacationReactDomain',
- 'kolabVacationAddress',
- 'kolabForwardKeepCopy',
- 'kolabDeleteflag',
- 'kolabVacationBeginDateTime',
- 'kolabVacationResendInterval',
- 'kolabVacationReplyToUCE',
- 'kolabForwardAddress',
- 'kolabForwardUCE',
- 'kolabAllowSMTPFrom',
- 'unrestrictedMailSize',
- 'kolabInvitationPolicy',
- 'kolabFreeBusyFuture',
- 'calFBURL',
- 'kolabComment',
- 'kolabImapServer',
- 'kolabFreeBusyServer',
- 'usertype',
- 'jpegPhoto',
-);
\ No newline at end of file
--- /dev/null
+<?php
+
+$conf['use_ssl'] = 2;
+$conf['server']['name'] = $_SERVER['SERVER_NAME'];
+$conf['server']['port'] = $_SERVER['SERVER_PORT'];
+$conf['cookie']['domain'] = $_SERVER['SERVER_NAME'];
+$conf['cookie']['path'] = '/';
+$conf['debug_level'] = E_ALL & ~E_NOTICE;
+$conf['umask'] = 077;
+$conf['compress_pages'] = true;
+$conf['session']['name'] = 'Horde';
+$conf['session']['cache_limiter'] = 'nocache';
+$conf['session']['timeout'] = 0;
+$conf['urls']['token_lifetime'] = 20;
+$conf['server']['token_lifetime'] = 20;
+$conf['auth']['admins'] = array('Administrator');
+$conf['auth']['driver'] = 'kolab';
+$conf['auth']['params'] = array();
+$conf['prefs']['driver'] = 'session';
+$conf['menu']['always'] = false;
+$conf['menu']['links']['logout'] = 'authenticated';
+$conf['portal']['fixed_blocks'] = array();
+$conf['imsp']['enabled'] = false;
+$conf['kolab']['enabled'] = true;
+$conf['kolab']['server']['driver'] = 'ldap';
+$conf['kolab']['imap']['allow_special_users'] = true;
+$conf['log']['priority'] = PEAR_LOG_DEBUG;
+$conf['log']['ident'] = 'HORDE';
+$conf['log']['params'] = array();
+$conf['log']['name'] = '/tmp/horde.log';
+$conf['log']['params']['append'] = true;
+$conf['log']['type'] = 'file';
+$conf['log']['enabled'] = true;
--- /dev/null
+<?php
+/**
+ * NLS (National Language Support) configuration file.
+ *
+ * $Horde: horde/config/nls.php.dist,v 1.77 2008/10/14 21:11:47 jan Exp $
+ */
+
+/**
+ ** Defaults
+ **/
+
+/* The language to fall back on if we cannot determine one any other
+ way (user choice or preferences). If empty, we will try to negotiate
+ with the browser using HTTP_ACCEPT_LANGUAGE. */
+$nls['defaults']['language'] = '';
+
+
+/**
+ ** Language
+ **/
+
+$nls['languages']['ar_OM'] = '‭Arabic (Oman) ‮(العربية)';
+$nls['languages']['ar_SY'] = '‭Arabic (Syria) ‮(العربية)';
+$nls['languages']['id_ID'] = 'Bahasa Indonesia';
+$nls['languages']['bs_BA'] = 'Bosanski';
+$nls['languages']['bg_BG'] = '‭Bulgarian (Български)';
+$nls['languages']['ca_ES'] = 'Català';
+$nls['languages']['zh_CN'] = '‭Chinese (Simplified) (简体中文)';
+$nls['languages']['zh_TW'] = '‭Chinese (Traditional) (正體中文)';
+$nls['languages']['cs_CZ'] = '‭Czech (Česky)';
+$nls['languages']['da_DK'] = 'Dansk';
+$nls['languages']['de_DE'] = 'Deutsch';
+$nls['languages']['en_US'] = '‭English (American)';
+$nls['languages']['en_GB'] = '‭English (British)';
+$nls['languages']['en_CA'] = '‭English (Canadian)';
+$nls['languages']['es_ES'] = 'Español';
+$nls['languages']['et_EE'] = 'Eesti';
+$nls['languages']['eu_ES'] = 'Euskara';
+$nls['languages']['fr_FR'] = 'Français';
+$nls['languages']['gl_ES'] = 'Galego';
+$nls['languages']['el_GR'] = '‭Greek (Ελληνικά)';
+$nls['languages']['he_IL'] = '‭Hebrew ‮(עברית)';
+$nls['languages']['is_IS'] = 'Íslenska';
+$nls['languages']['it_IT'] = 'Italiano';
+$nls['languages']['ja_JP'] = '‭Japanese (日本語)';
+$nls['languages']['km_KH'] = '‭Khmer (ខ្មែរ)';
+$nls['languages']['ko_KR'] = '‭Korean (한국어)';
+$nls['languages']['lv_LV'] = 'Latviešu';
+$nls['languages']['lt_LT'] = 'Lietuvių';
+$nls['languages']['mk_MK'] = '‭Macedonian (Македонски)';
+$nls['languages']['hu_HU'] = 'Magyar';
+$nls['languages']['nl_NL'] = 'Nederlands';
+$nls['languages']['nb_NO'] = 'Norsk bokmål';
+$nls['languages']['nn_NO'] = 'Norsk nynorsk';
+$nls['languages']['fa_IR'] = '‭Persian ‮(فارسى)';
+$nls['languages']['pl_PL'] = 'Polski';
+$nls['languages']['pt_PT'] = 'Português';
+$nls['languages']['pt_BR'] = 'Português Brasileiro';
+$nls['languages']['ro_RO'] = 'Românä';
+$nls['languages']['ru_RU'] = '‭Russian (Русский)';
+$nls['languages']['sk_SK'] = '‭Slovak (Slovenčina)';
+$nls['languages']['sl_SI'] = '‭Slovenian (Slovenščina)';
+$nls['languages']['fi_FI'] = 'Suomi';
+$nls['languages']['sv_SE'] = 'Svenska';
+$nls['languages']['th_TH'] = '‭Thai (ไทย)';
+if (version_compare(PHP_VERSION, '5', 'lt') || version_compare(PHP_VERSION, '6', 'ge')) {
+ $nls['languages']['tr_TR'] = 'Türkçe';
+}
+$nls['languages']['uk_UA'] = '‭Ukrainian (Українська)';
+
+
+/**
+ ** Aliases for languages with different browser and gettext codes
+ **/
+
+$nls['aliases']['ar'] = 'ar_SY';
+$nls['aliases']['bg'] = 'bg_BG';
+$nls['aliases']['bs'] = 'bs_BA';
+$nls['aliases']['ca'] = 'ca_ES';
+$nls['aliases']['cs'] = 'cs_CZ';
+$nls['aliases']['da'] = 'da_DK';
+$nls['aliases']['de'] = 'de_DE';
+$nls['aliases']['el'] = 'el_GR';
+$nls['aliases']['en'] = 'en_US';
+$nls['aliases']['es'] = 'es_ES';
+$nls['aliases']['et'] = 'et_EE';
+$nls['aliases']['fa'] = 'fa_IR';
+$nls['aliases']['fi'] = 'fi_FI';
+$nls['aliases']['fr'] = 'fr_FR';
+$nls['aliases']['gl'] = 'gl_ES';
+$nls['aliases']['he'] = 'he_IL';
+$nls['aliases']['hu'] = 'hu_HU';
+$nls['aliases']['id'] = 'id_ID';
+$nls['aliases']['is'] = 'is_IS';
+$nls['aliases']['it'] = 'it_IT';
+$nls['aliases']['ja'] = 'ja_JP';
+$nls['aliases']['km'] = 'km_KH';
+$nls['aliases']['ko'] = 'ko_KR';
+$nls['aliases']['lt'] = 'lt_LT';
+$nls['aliases']['lv'] = 'lv_LV';
+$nls['aliases']['mk'] = 'mk_MK';
+$nls['aliases']['nl'] = 'nl_NL';
+$nls['aliases']['nn'] = 'nn_NO';
+$nls['aliases']['no'] = 'nb_NO';
+$nls['aliases']['pl'] = 'pl_PL';
+$nls['aliases']['pt'] = 'pt_PT';
+$nls['aliases']['ro'] = 'ro_RO';
+$nls['aliases']['ru'] = 'ru_RU';
+$nls['aliases']['sk'] = 'sk_SK';
+$nls['aliases']['sl'] = 'sl_SI';
+$nls['aliases']['sv'] = 'sv_SE';
+$nls['aliases']['th'] = 'th_TH';
+if (version_compare(PHP_VERSION, '5', 'lt') || version_compare(PHP_VERSION, '6', 'ge')) {
+ $nls['aliases']['tr'] = 'tr_TR';
+}
+$nls['aliases']['uk'] = 'uk_UA';
+
+
+/**
+ ** Charsets. These differ somewhat on different systems; see below
+ ** for a set of BSD charset names.
+ **/
+
+$nls['charsets']['ar_OM'] = 'windows-1256';
+$nls['charsets']['ar_SY'] = 'windows-1256';
+$nls['charsets']['bg_BG'] = 'windows-1251';
+$nls['charsets']['bs_BA'] = 'ISO-8859-2';
+$nls['charsets']['cs_CZ'] = 'ISO-8859-2';
+$nls['charsets']['el_GR'] = 'ISO-8859-7';
+$nls['charsets']['eu_ES'] = 'UTF-8';
+$nls['charsets']['fa_IR'] = 'UTF-8';
+$nls['charsets']['he_IL'] = 'UTF-8';
+$nls['charsets']['hu_HU'] = 'ISO-8859-2';
+$nls['charsets']['ja_JP'] = 'SHIFT_JIS';
+$nls['charsets']['km_KH'] = 'UTF-8';
+$nls['charsets']['ko_KR'] = 'EUC-KR';
+$nls['charsets']['lt_LT'] = 'ISO-8859-13';
+$nls['charsets']['lv_LV'] = 'windows-1257';
+$nls['charsets']['mk_MK'] = 'ISO-8859-5';
+$nls['charsets']['pl_PL'] = 'ISO-8859-2';
+$nls['charsets']['ru_RU'] = 'windows-1251';
+$nls['charsets']['ru_RU.KOI8-R'] = 'KOI8-R';
+$nls['charsets']['sk_SK'] = 'ISO-8859-2';
+$nls['charsets']['sl_SI'] = 'ISO-8859-2';
+$nls['charsets']['th_TH'] = 'TIS-620';
+if (version_compare(PHP_VERSION, '5', 'lt') || version_compare(PHP_VERSION, '6', 'ge')) {
+ $nls['charsets']['tr_TR'] = 'ISO-8859-9';
+}
+$nls['charsets']['uk_UA'] = 'windows-1251';
+$nls['charsets']['zh_CN'] = 'GB2312';
+$nls['charsets']['zh_TW'] = 'BIG5';
+
+/**
+ * BSD charsets.
+ */
+if (strpos(PHP_OS, 'BSD') !== false) {
+ $nls['charsets']['ar_OM'] = 'windows-1256';
+ $nls['charsets']['ar_SY'] = 'windows-1256';
+ $nls['charsets']['bg_BG'] = 'windows-1251';
+ $nls['charsets']['bs_BA'] = 'ISO8859-2';
+ $nls['charsets']['cs_CZ'] = 'ISO8859-2';
+ $nls['charsets']['el_GR'] = 'ISO8859-7';
+ $nls['charsets']['eu_ES'] = 'UTF-8';
+ $nls['charsets']['fa_IR'] = 'UTF-8';
+ $nls['charsets']['he_IL'] = 'UTF-8';
+ $nls['charsets']['hu_HU'] = 'ISO8859-2';
+ $nls['charsets']['ja_JP'] = 'SHIFT_JIS';
+ $nls['charsets']['km_KH'] = 'UTF-8';
+ $nls['charsets']['ko_KR'] = 'EUC-KR';
+ $nls['charsets']['lt_LT'] = 'ISO8859-13';
+ $nls['charsets']['lv_LV'] = 'windows-1257';
+ $nls['charsets']['mk_MK'] = 'ISO8859-5';
+ $nls['charsets']['pl_PL'] = 'ISO8859-2';
+ $nls['charsets']['ru_RU'] = 'windows-1251';
+ $nls['charsets']['ru_RU.KOI8-R'] = 'KOI8-R';
+ $nls['charsets']['sk_SK'] = 'ISO8859-2';
+ $nls['charsets']['sl_SI'] = 'ISO8859-2';
+ $nls['charsets']['th_TH'] = 'TIS-620';
+ if (version_compare(PHP_VERSION, '5', 'lt') ||
+ version_compare(PHP_VERSION, '6', 'ge')) {
+ $nls['charsets']['tr_TR'] = 'ISO-8859-9';
+ }
+ $nls['charsets']['uk_UA'] = 'windows-1251';
+ $nls['charsets']['zh_CN'] = 'GB2312';
+ $nls['charsets']['zh_TW'] = 'BIG5';
+}
+
+
+/**
+ ** Multibyte charsets
+ **/
+
+$nls['multibyte']['BIG5'] = true;
+$nls['multibyte']['EUC-KR'] = true;
+$nls['multibyte']['GB2312'] = true;
+$nls['multibyte']['SHIFT_JIS'] = true;
+$nls['multibyte']['UTF-8'] = true;
+
+
+/**
+ ** Right-to-left languages
+ **/
+
+$nls['rtl']['ar_OM'] = true;
+$nls['rtl']['ar_SY'] = true;
+$nls['rtl']['fa_IR'] = true;
+$nls['rtl']['he_IL'] = true;
+
+
+/**
+ ** Preferred charsets for email traffic if not the languages' default
+ ** charsets.
+ **/
+
+$nls['emails']['ja_JP'] = 'ISO-2022-JP';
+
+
+/**
+ ** Available charsets for outgoing email traffic.
+ **/
+
+$nls['encodings']['windows-1256'] = _("Arabic (Windows-1256)");
+$nls['encodings']['ARMSCII-8'] = _("Armenian (ARMSCII-8)");
+$nls['encodings']['ISO-8859-13'] = _("Baltic (ISO-8859-13)");
+$nls['encodings']['ISO-8859-14'] = _("Celtic (ISO-8859-14)");
+$nls['encodings']['ISO-8859-2'] = _("Central European (ISO-8859-2)");
+$nls['encodings']['GB2312'] = _("Chinese Simplified (GB2312)");
+$nls['encodings']['BIG5'] = _("Chinese Traditional (Big5)");
+$nls['encodings']['KOI8-R'] = _("Cyrillic (KOI8-R)");
+$nls['encodings']['windows-1251'] = _("Cyrillic (Windows-1251)");
+$nls['encodings']['KOI8-U'] = _("Cyrillic/Ukrainian (KOI8-U)");
+$nls['encodings']['ISO-8859-7'] = _("Greek (ISO-8859-7)");
+$nls['encodings']['ISO-8859-8-I'] = _("Hebrew (ISO-8859-8-I)");
+$nls['encodings']['ISO-2022-JP'] = _("Japanese (ISO-2022-JP)");
+$nls['encodings']['EUC-KR'] = _("Korean (EUC-KR)");
+$nls['encodings']['ISO-8859-10'] = _("Nordic (ISO-8859-10)");
+$nls['encodings']['ISO-8859-3'] = _("South European (ISO-8859-3)");
+$nls['encodings']['TIS-620'] = _("Thai (TIS-620)");
+$nls['encodings']['ISO-8859-9'] = _("Turkish (ISO-8859-9)");
+$nls['encodings']['UTF-8'] = _("Unicode (UTF-8)");
+$nls['encodings']['VISCII'] = _("Vietnamese (VISCII)");
+$nls['encodings']['ISO-8859-1'] = _("Western (ISO-8859-1)");
+$nls['encodings']['ISO-8859-15'] = _("Western (ISO-8859-15)");
+asort($nls['encodings']);
+
+
+/**
+ ** Multi-language spelling support
+ **/
+
+$nls['spelling']['cs_CZ'] = '-T latin2 -d czech';
+$nls['spelling']['da_DK'] = '-d dansk';
+$nls['spelling']['de_DE'] = '-T latin1 -d deutsch';
+$nls['spelling']['el_GR'] = '-T latin1 -d ellinika';
+$nls['spelling']['en_CA'] = '-d canadian';
+$nls['spelling']['en_GB'] = '-d british';
+$nls['spelling']['en_US'] = '-d american';
+$nls['spelling']['es_ES'] = '-d espanol';
+$nls['spelling']['fr_FR'] = '-d francais';
+$nls['spelling']['it_IT'] = '-T latin1 -d italian';
+$nls['spelling']['nl_NL'] = '-d nederlands';
+$nls['spelling']['pl_PL'] = '-d polish';
+$nls['spelling']['pt_BR'] = '-d br';
+$nls['spelling']['pt_PT'] = '-T latin1 -d portuguese';
+$nls['spelling']['ru_RU'] = '-d russian';
+$nls['spelling']['sl_SI'] = '-d slovensko';
+$nls['spelling']['sv_SE'] = '-d svenska';
+if (isset($nls['charsets']['tr_TR'])) {
+ $nls['spelling']['tr_TR'] = '-d tr';
+}
+
+$GLOBALS['nls'] = &$nls;
--- /dev/null
+<?php
+/**
+ * $Horde: horde/config/prefs.php.dist,v 1.108 2009/03/02 01:23:06 mrubinsk Exp $
+ *
+ * Preferences Information
+ * =======================
+ * Changes you make to the prefs.php file(s) will not be reflected until the
+ * user logs out and logs in again.
+ *
+ * If you change these preferences in a production system, you will
+ * need to delete any horde_prefs in your preferences database.
+ *
+ * prefGroups array
+ * ----------------
+ * $prefGroups are for display purposes when you press the options button.
+ * The options choice will appear when you set your preferences driver
+ * in the horde/config/conf.php file.
+ *
+ * $prefGroups array definition:
+ * column: What column head this group will go under
+ * label: Label for the group of settings
+ * desc: Description that will show under label
+ * members: List of preferences supported by this group
+ *
+ * _prefs array
+ * ------------
+ * The $_prefs array's are listed in the same order as listed in the
+ * members element of $prefGroups.
+ *
+ * value: This entry will hold the default preference value depending on the
+ * preference type:
+ * checkbox: 0 or false for unchecked, 1 or true for checked
+ * enum: Preselected item from associated enumeration
+ * implicit: See Preference type
+ * link: Not used
+ * number: Number value
+ * password: Should be ''
+ * select: Preselected item from associated selection list
+ * special: Not used
+ * text: Text value
+ * textarea: Text value, lines separated with "\n"
+ *
+ * locked: Allow preference to be changed from UI
+ * true: Do not show this preference in the UI.
+ * This has no effect on 'link' type preferences.
+ * false: Show this preference in the UI and allow changing.
+ *
+ * shared: Share with other horde apps
+ * true: Share this pref with other Horde apps
+ * false: Keep this pref local to the current app
+ *
+ * type: Preference type
+ * checkbox: Provides a checkbox.
+ * enum: Provides a selection list in the UI, list is
+ * specified in the associated 'enum' setting.
+ * implicit: Provides storage for 'special' types.
+ * link: Provides a link to another data entry form.
+ * number: Provides a 3-character textbox to enter a natural
+ * number; syntaxcheck is performed after data entry.
+ * password: Provides a textbox for password entry.
+ * select: Provides a selection list in the UI that is built in
+ * lib/prefs.php.
+ * special: Provides an UI widget.
+ * text: Provides a single-line textbox.
+ * textarea: Provides a multi-line textbox.
+ *
+ * enum: Static list of elements for 'type' => 'enum'.
+ *
+ * escaped: For an enum or a select, are the keys and values already
+ * html-escaped? Defaults to false if not present.
+ *
+ * hook: Call a hook function for the value of this preference
+ * true: Will call the function _prefs_hook_<prefname>
+ * to fill in the value of this preference.
+ * See hooks.php for more details.
+ * false: Normal behaviour - no hook is called.
+ */
+
+$prefGroups['identities'] = array(
+ 'column' => _("Your Information"),
+ 'label' => _("Personal Information"),
+ 'desc' => _("Change the name and address that people see when they read and reply to your emails."),
+ 'members' => array('default_identity', 'identityselect', 'deleteidentity',
+ 'id', 'fullname', 'from_addr')
+);
+
+$prefGroups['authentication'] = array(
+ 'column' => _("Your Information"),
+ 'label' => _("Authentication Credentials"),
+ 'desc' => _("Set authentication credentials like user names and passwords for external servers."),
+ 'members' => array('credentialsui'),
+);
+
+$auth = &Auth::singleton($GLOBALS['conf']['auth']['driver']);
+if (is_a($auth, 'Auth') && $auth->hasCapability('update')) {
+ $prefGroups['forgotpass'] = array(
+ 'column' => _("Your Information"),
+ 'label' => _("Account Password"),
+ 'desc' => _("Set options to allow you to reset your password if you ever forget it."),
+ 'members' => array('security_question', 'security_answer', 'alternate_email')
+ );
+}
+
+$prefGroups['language'] = array(
+ 'column' => _("Your Information"),
+ 'label' => _("Locale and Time"),
+ 'desc' => _("Set your preferred language, timezone and date options."),
+ 'members' => array('language', 'timezone', 'twentyFour', 'date_format', 'first_week_day')
+);
+
+$prefGroups['categories'] = array(
+ 'column' => _("Your Information"),
+ 'label' => _("Categories and Labels"),
+ 'desc' => _("Manage the list of categories you have to label items with, and colors associated with those categories."),
+ 'members' => array('categorymanagement')
+);
+
+$prefGroups['display'] = array(
+ 'column' => _("Other Information"),
+ 'label' => _("Display Options"),
+ 'desc' => _("Set your startup application, color scheme, page refreshing, and other display options."),
+ 'members' => array('initial_application', 'show_last_login', 'theme',
+ 'summary_refresh_time', 'show_sidebar', 'sidebar_width',
+ 'moz_sidebar', 'menu_view', 'menu_refresh_time',
+ 'widget_accesskey')
+);
+
+$prefGroups['logintasks'] = array(
+ 'column' => _("Other Information"),
+ 'label' => _("Login Tasks"),
+ 'desc' => sprintf(_("Customize tasks to run upon logon to %s."), $GLOBALS['registry']->get('name')),
+ 'members' => array('do_maintenance', 'confirm_maintenance')
+);
+
+$prefGroups['remote'] = array(
+ 'column' => _("Other Information"),
+ 'label' => _("Remote Servers"),
+ 'desc' => _("Set up remote servers that you want to access from your portal."),
+ 'url' => 'services/portal/rpcsum.php'
+);
+
+if (!empty($GLOBALS['conf']['facebook']['key']) && !empty($GLOBAL['conf']['facebook']['secret'])) {
+ $prefGroups['facebook'] = array(
+ 'column' => _("Other Information"),
+ 'label' => _("Facebook Integration"),
+ 'desc' => _("Set up integration with your Facebook account."),
+ 'url' => 'services/facebook.php'
+ );
+}
+
+// For alternate IMSP authentication.
+if (!empty($GLOBALS['conf']['imsp']['enabled'])) {
+ $prefGroups['imspauth'] = array(
+ 'column' => _("Other Information"),
+ 'label' => _("Alternate IMSP Login"),
+ 'desc' => _("Use if name/password is different for IMSP server."),
+ 'members' => array('imsp_auth_user', 'imsp_auth_pass')
+ );
+}
+
+// Determine functionality of richtext editor
+$prefGroups['richtext'] = array(
+ 'column' => _("Other Information"),
+ 'label' => _("Rich Text Editor Options"),
+ 'desc' => _("Which plugins to enable for the Rich Text editor."),
+ 'members' => array('editor_plugins'),
+);
+
+$prefGroups['syncml'] = array(
+ 'column' => _("Other Information"),
+ 'label' => _("SyncML"),
+ 'desc' => _("Configuration for syncing with PDAs, Smartphones and Outlook."),
+ 'url' => 'services/portal/syncml.php',
+ 'members' => array()
+);
+
+// Personal Information preferences
+
+// default identity
+// Set locked to true if you don't want the users to have multiple identities.
+$_prefs['default_identity'] = array(
+ 'value' => 0,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'enum',
+ 'enum' => (isset($GLOBALS['identity']) && is_object($GLOBALS['identity'])) ? $GLOBALS['identity']->getAll('id') : array(),
+ 'desc' => _("Your default identity:"),
+);
+
+// identities array
+// Don't change anything here.
+$_prefs['identities'] = array(
+ 'value' => 'a:0:{}',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'implicit',
+);
+
+// identify email confirmation
+$_prefs['confirm_email'] = array(
+ 'value' => 'a:0:{}',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'implicit',
+);
+
+// identity selection widget
+$_prefs['identityselect'] = array(
+ 'shared' => true,
+ 'type' => 'special',
+);
+
+// delete button
+$_prefs['deleteidentity'] = array(
+ 'type' => 'special',
+ 'shared' => true,
+);
+
+// identity name
+// If you lock this preference, you must specify a value or a hook for it in
+// horde/config/hooks.php.
+$_prefs['id'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'text',
+ 'desc' => _("Identity's name:")
+);
+
+// user full name for From: line
+// If you lock this preference, you must specify a value or a hook for it in
+// horde/config/hooks.php.
+$_prefs['fullname'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'text',
+ 'desc' => _("Your full name:")
+);
+
+// user preferred email address for From: line
+// If you lock this preference, you must specify a value or a hook for it in
+// horde/config/hooks.php.
+$_prefs['from_addr'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'text',
+ 'desc' => _("Your From: address:")
+);
+
+// Authentication Options
+
+// credentials
+$_prefs['credentials'] = array(
+ 'value' => 'a:0:{}',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'implicit'
+);
+
+// credentials interface
+$_prefs['credentialsui'] = array(
+ 'shared' => true,
+ 'type' => 'special',
+);
+
+// user security question
+$_prefs['security_question'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'text',
+ 'desc' => _("Enter a security question which you will be asked if you need to reset your password, e.g. 'what is the name of your pet?':")
+);
+
+// user security answer
+$_prefs['security_answer'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'text',
+ 'desc' => _("Insert the required answer to the security question:")
+);
+
+// user alternate email
+$_prefs['alternate_email'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'text',
+ 'desc' => _("Insert an email address to which you can receive the new password:")
+);
+
+// user language
+$_prefs['language'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'select',
+ 'escaped' => true,
+ 'desc' => _("Select your preferred language:")
+);
+
+// user time zone
+$_prefs['timezone'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'select',
+ 'desc' => _("Your current time zone:")
+);
+
+// time format
+$_prefs['twentyFour'] = array(
+ 'value' => false,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'checkbox',
+ 'desc' => _("Display 24-hour times?")
+);
+
+// date format
+$_prefs['date_format'] = array(
+ 'value' => '%x',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'enum',
+ 'enum' => array(
+ '%x' => strftime('%x'),
+ '%Y-%m-%d' => strftime('%Y-%m-%d'),
+ '%d/%m/%Y' => strftime('%d/%m/%Y'),
+ '%A %B %d, %Y' => strftime('%A %B %d, %Y'),
+ '%A, %d. %B %Y' => strftime('%A, %d. %B %Y'),
+ '%A, %d %B %Y' => strftime('%A, %d %B %Y'),
+ '%a, %b %e, %Y' => strftime('%a, %b %e, %Y'),
+ '%a, %b %e, %y' => strftime('%a, %b %e, %y'),
+ '%a, %b %e' => strftime('%a, %b %e'),
+ '%a, %e %b %Y' => strftime('%a, %e %b %Y'),
+ '%a, %e %b %y' => strftime('%a, %e %b %y'),
+ '%a %d %b %Y' => strftime ('%a %d %b %Y'),
+ '%a %x' => strftime ('%a %x'),
+ '%a %Y-%m-%d' => strftime ('%a %Y-%m-%d'),
+ '%e %b %Y' => strftime('%e %b %Y'),
+ '%e. %b %Y' => strftime('%e. %b %Y'),
+ '%e. %m %Y' => strftime('%e %m %Y'),
+ '%e. %m.' => strftime('%e. %m.'),
+ '%e. %B' => strftime('%e. %B'),
+ '%e. %B %Y' => strftime('%e. %B %Y'),
+ '%e. %B %y' => strftime('%e. %B %y'),
+ '%B %e, %Y' => strftime('%B %e, %Y'),
+ ),
+ 'desc' => _("Choose how to display dates:"),
+);
+
+// what day should be displayed as the first day of the week?
+$_prefs['first_week_day'] = array(
+ 'value' => '0',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'enum',
+ 'desc' => _("Which day would you like to be displayed as the first day of the week?"),
+ 'enum' => array('0' => _("Sunday"),
+ '1' => _("Monday"))
+);
+
+// UI theme
+$_prefs['theme'] = array(
+ 'value' => 'bluewhite',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'select',
+ 'desc' => _("Select your color scheme.")
+);
+
+// categories
+$_prefs['categories'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'implicit'
+);
+
+// category colors
+$_prefs['category_colors'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'implicit'
+);
+
+// UI for category management.
+$_prefs['categorymanagement'] = array(
+ 'type' => 'special'
+);
+
+$_prefs['summary_refresh_time'] = array(
+ 'value' => 300,
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'enum',
+ 'enum' => array(0 => _("Never"),
+ 30 => _("Every 30 seconds"),
+ 60 => _("Every minute"),
+ 300 => _("Every 5 minutes"),
+ 900 => _("Every 15 minutes"),
+ 1800 => _("Every half hour")),
+ 'desc' => _("Refresh Portal View:")
+);
+
+$_prefs['show_sidebar'] = array(
+ 'value' => true,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'checkbox',
+ 'desc' => sprintf(_("Show the %s Menu on the left?"), $GLOBALS['registry']->get('name', 'horde'))
+);
+
+$_prefs['sidebar_width'] = array(
+ 'value' => 150,
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'number',
+ 'desc' => sprintf(_("Width of the %s menu on the left:"), $GLOBALS['registry']->get('name', 'horde'))
+);
+
+$_prefs['moz_sidebar'] = array(
+ 'type' => 'link',
+ 'xurl' => sprintf('javascript:if (window.sidebar && window.sidebar.addPanel) window.sidebar.addPanel(\'%s\', \'%s\', \'%s\'); else alert(\'%s\');',
+ $GLOBALS['registry']->get('name', 'horde'),
+ Util::addParameter(Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/portal/sidebar.php', true, -1), 'mozbar', '1'),
+ Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/prefs.php', true, -1),
+ addslashes(_("Couldn't find the Mozilla Sidebar. Make sure the sidebar is open."))),
+ 'desc' => sprintf(_("Add the %s Menu as a Mozilla Sidebar"), $GLOBALS['registry']->get('name', 'horde'))
+);
+
+$_prefs['menu_view'] = array(
+ 'value' => 'both',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'enum',
+ 'enum' => array('text' => _("Text Only"),
+ 'icon' => _("Icons Only"),
+ 'both' => _("Icons with text")),
+ 'desc' => _("Menu mode:")
+);
+
+$_prefs['menu_refresh_time'] = array(
+ 'value' => 300,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'enum',
+ 'enum' => array(0 => _("Never"),
+ 30 => _("Every 30 seconds"),
+ 60 => _("Every minute"),
+ 120 => _("Every 2 minutes"),
+ 300 => _("Every 5 minutes")),
+ 'desc' => _("Refresh Dynamic Menu Elements:")
+);
+
+
+// Login/Maintenance Tasks preferences
+
+// To disable maintenance entirely, set 'value' = false and
+// 'locked' = true for all of these. To just turn it off by default,
+// set 'value' false for do_maintenance.
+// perform maintenance operations?
+$_prefs['do_maintenance'] = array(
+ 'value' => true,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'checkbox',
+ 'desc' => _("Perform maintenance operations on login?"),
+ 'help' => 'prefs-do_maintenance');
+
+// last time maintenance was run.
+// value is a UNIX timestamp of the last time maintenance ran for the user.
+$_prefs['last_maintenance'] = array(
+ 'value' => 0,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'implicit'
+);
+
+// confirm when doing maintenance operations? If false, they will
+// be performed with no input from/check with the user.
+$_prefs['confirm_maintenance'] = array(
+ 'value' => true,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'checkbox',
+ 'desc' => _("Ask for confirmation before doing maintenance operations?"),
+ 'help' => 'prefs-confirm_maintenance');
+
+// End Login/Maintenance preferences
+
+
+// what application should we go to after login?
+$_prefs['initial_application'] = array(
+ 'value' => 'horde',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'select',
+ 'desc' => sprintf(_("What application should %s display after login?"), $GLOBALS['registry']->get('name'))
+);
+
+// should we create access keys?
+$_prefs['widget_accesskey'] = array(
+ 'value' => true,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'checkbox',
+ 'desc' => _("Should access keys be defined for most links?")
+);
+
+// the layout of the portal page.
+$_prefs['portal_layout'] = array(
+ 'value' => 'a:0:{}',
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'implicit'
+);
+
+// the remote servers.
+$_prefs['remote_summaries'] = array(
+ 'value' => 'a:0:{}',
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'implicit'
+);
+
+$_prefs['facebook'] = array(
+ 'value' => 'a:0:{}',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'implicit');
+
+// last login time of user
+// value is a serialized array of the UNIX timestamp of the last
+// login, and the host that the last login was from.
+$_prefs['last_login'] = array(
+ 'value' => 'a:0:{}',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'implicit'
+);
+
+// show the last login time of user
+$_prefs['show_last_login'] = array(
+ 'value' => true,
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'checkbox',
+ 'desc' => _("Show last login time when logging in?")
+);
+
+if (!empty($GLOBALS['conf']['imsp']['enabled'])) {
+ $_prefs['imsp_auth_user'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'text',
+ 'desc' => _("Alternate IMSP Username")
+ );
+
+ $_prefs['imsp_auth_pass'] = array(
+ 'value' => '',
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'password',
+ 'desc' => _("Alternate IMSP Password")
+ );
+}
+
+// Rich Text Editor preferences.
+$_prefs['editor_plugins'] = array(
+ 'value' => 'a:2:{i:0;s:8:"ListType";i:1;s:12:"CharacterMap";}',
+ 'locked' => false,
+ 'shared' => true,
+ 'type' => 'multienum',
+ 'enum' => array(
+ 'ContextMenu' => _("Right click context menu"),
+ 'TableOperations' => _("Table operations menu bar"),
+ 'ListType' => _("Allow setting of ordered list type"),
+ 'CharacterMap' => _("Special characters"),
+ 'AnselImage' => _("Insertion of images from Photo Galleries in text")),
+ 'desc' => _("Select editor plugins")
+);
+// End Rich Text Editor preferences.
--- /dev/null
+This directory can hold registry configuration snippets. Any PHP file (*.php)
+is read; all other files are ignored and so are for information only. Snippets
+can contain anything that would go in registry.php - one or more applications,
+tree blocks, conditionals, etc.
+
+Scripts that install or update files in this directory should always touch()
+the registry.d directory after completion to ensure that its modification time
+has changed; that way Horde will know to drop any cached configuration
+information.
--- /dev/null
+<?php
+/**
+ * registry.php -- Horde application registry.
+ *
+ * $Horde: horde/config/registry.php.dist,v 1.306 2009/01/14 20:51:07 chuck Exp $
+ *
+ * This configuration file is used by Horde to determine which Horde
+ * applications are installed and where, as well as how they interact.
+ *
+ * Application registry
+ * --------------------
+ * The following settings register installed Horde applications.
+ * By default, Horde assumes that the application directories live
+ * inside the horde directory.
+ *
+ * Attribute Type Description
+ * --------- ---- -----------
+ * fileroot string The base filesystem path for the module's files.
+ * webroot string The base URI for the module.
+ * jsuri string The base URI for static javascript files.
+ * jsfs string The base filesystem path for static javascript files.
+ * themesuri string The base URI for the themes. This can be used to
+ * serve all icons and style sheets from a separate
+ * server.
+ * themesfs string The base file system directory for the themes.
+ * icon string The URI for an icon to show in menus for the module.
+ * Setting this will override the default theme-based
+ * logic in the code.
+ * name string The name used in menus and descriptions for a module
+ * status string 'inactive', 'hidden', 'notoolbar', 'heading',
+ * 'block', 'admin', or 'active'.
+ * provides string Service types the module provides.
+ * initial_page string The initial (default) page (filename) for the module.
+ * templates string The filesystem path to the templates directory.
+ * menu_parent string The name of the 'heading' group that this app should
+ * show up under.
+ * target string The (optional) target frame for the link.
+ * url string The (optional) URL of 'heading' entries.
+ */
+
+// We try to automatically determine the proper webroot for Horde here. This
+// still assumes that applications live under horde/. If this results in
+// incorrect results for you, simply change the 'webroot' setting in the
+// 'horde' stanza below.
+
+$this->applications['horde'] = array(
+ 'fileroot' => dirname(__FILE__) . '/..',
+ 'webroot' => '/horde',
+ 'initial_page' => 'login.php',
+ 'name' => _("Horde"),
+ 'status' => 'active',
+ 'templates' => dirname(__FILE__) . '/../templates',
+ 'provides' => 'horde',
+ 'themesuri' => '/horde/themes',
+ 'themesfs' => dirname(__FILE__) . '/../../htdocs/horde/themes',
+);
+
+$this->applications['koward'] = array(
+ 'fileroot' => dirname(__FILE__) . '/../../koward',
+ 'webroot' => '/koward',
+ 'name' => _("Koward"),
+ 'status' => 'active',
+ 'initial_page' => 'index',
+ 'themesuri' => '/koward/themes',
+ 'themesfs' => dirname(__FILE__) . '/../../htdocs/koward/themes',
+);
--- /dev/null
+/**
+ * Accesskeys javascript file.
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ */
+var AccessKeys = {
+
+ macos: navigator.appVersion.indexOf("Mac") !=- 1,
+
+ keydownHandler: function(e)
+ {
+ var elt, elts, evt, key;
+
+ if ((this.macos && e.ctrlKey) ||
+ (!this.macos && e.altKey && !e.ctrlKey)) {
+ // Need to search for both upper and lowercase value
+ key = String.fromCharCode(e.keyCode || e.charCode);
+ elts = $$('[accesskey="' + key.toUpperCase() + '"]').concat($$('[accesskey="' + key.toLowerCase() + '"]'));
+
+ if (elt = elts.first()) {
+ // Remove duplicate accesskeys
+ if (elts.size() > 1) {
+ elts.slice(1).invoke('writeAttribute', 'accesskey', null);
+ }
+
+ e.stop();
+
+ // Trigger a mouse event on the accesskey element.
+ if (elt.tagName == 'INPUT') {
+ // NOOP
+ } else if (elt.match('A') && elt.onclick) {
+ elt.onclick();
+ } else if (document.createEvent) {
+ evt = document.createEvent('MouseEvents');
+ evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ elt.dispatchEvent(evt);
+ } else {
+ elt.fireEvent('onclick');
+ }
+ }
+ }
+ }
+};
+
+document.observe('keydown', AccessKeys.keydownHandler.bindAsEventListener(AccessKeys));
--- /dev/null
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + .5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
+ },
+ pulse: function(pos, pulses) {
+ return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ this.render = (function() {
+ function dispatch(effect, eventName) {
+ if (effect.options[eventName + 'Internal'])
+ effect.options[eventName + 'Internal'](effect);
+ if (effect.options[eventName])
+ effect.options[eventName](effect);
+ }
+
+ return function(pos) {
+ if (this.state === "idle") {
+ this.state = "running";
+ dispatch(this, 'beforeSetup');
+ if (this.setup) this.setup();
+ dispatch(this, 'afterSetup');
+ }
+ if (this.state === "running") {
+ pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
+ this.position = pos;
+ dispatch(this, 'beforeUpdate');
+ if (this.update) this.update(pos);
+ dispatch(this, 'afterUpdate');
+ }
+ };
+ })();
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()); }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element);
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ });
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}); }}); }}); }}); }}); }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ );
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { },
+ oldOpacity = element.getInlineOpacity(),
+ transition = options.transition || Effect.Transitions.linear,
+ reverser = function(pos){
+ return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
+ };
+
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ };
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 );
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ );
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+}
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element);
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ };
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
\ No newline at end of file
--- /dev/null
+/**
+ * General Horde UI effects javascript.
+ *
+ * $Horde: horde/js/src/horde.js,v 1.10 2007/09/25 12:57:20 slusarz Exp $
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ */
+
+var ToolTips = {
+ current: null,
+ timeout: null,
+ element: null,
+
+ attachBehavior: function()
+ {
+ links = document.getElementsByTagName('a');
+ for (var i = 0; i < links.length; i++) {
+ if (links[i].title) {
+ links[i].setAttribute('nicetitle', links[i].title);
+ links[i].removeAttribute('title');
+
+ addEvent(links[i], 'mouseover', ToolTips.onMouseover);
+ addEvent(links[i], 'mouseout', ToolTips.out);
+ addEvent(links[i], 'focus', ToolTips.onFocus);
+ addEvent(links[i], 'blur', ToolTips.out);
+ }
+ }
+ },
+
+ onMouseover: function(event)
+ {
+ if (typeof ToolTips == 'undefined') {
+ return;
+ }
+
+ if (ToolTips.timeout) {
+ clearTimeout(ToolTips.timeout);
+ }
+
+ if (event.srcElement) {
+ ToolTips.element = event.srcElement;
+ } else if (event.target) {
+ ToolTips.element = event.target;
+ }
+
+ var pos = mousePos(event);
+ ToolTips.timeout = setTimeout(function() { ToolTips.show(pos); }, 300)
+ },
+
+ onFocus: function(event)
+ {
+ if (typeof ToolTips == 'undefined') {
+ return;
+ }
+
+ if (ToolTips.timeout) {
+ clearTimeout(ToolTips.timeout);
+ }
+
+ if (event.srcElement) {
+ ToolTips.element = event.srcElement;
+ } else if (event.target) {
+ ToolTips.element = event.target;
+ }
+
+ var pos = eltPos(ToolTips.element);
+ ToolTips.timeout = setTimeout(function() { ToolTips.show(pos); }, 300)
+ },
+
+ out: function()
+ {
+ if (typeof ToolTips == 'undefined') {
+ return;
+ }
+
+ if (ToolTips.timeout) {
+ clearTimeout(ToolTips.timeout);
+ }
+
+ if (ToolTips.current) {
+ document.getElementsByTagName('body')[0].removeChild(ToolTips.current);
+ ToolTips.current = null;
+
+ var iframe = document.getElementById('iframe_tt');
+ if (iframe != null) {
+ iframe.style.display = 'none';
+ }
+ }
+ },
+
+ show: function(pos)
+ {
+ try {
+ if (ToolTips.current) {
+ ToolTips.out();
+ }
+
+ var link = ToolTips.element;
+ while (!link.getAttribute('nicetitle') && link.nodeName.toLowerCase() != 'body') {
+ link = link.parentNode;
+ }
+ var nicetitle = link.getAttribute('nicetitle');
+ if (!nicetitle) {
+ return;
+ }
+
+ var d = document.createElement('div');
+ d.className = 'nicetitle';
+ d.innerHTML = nicetitle;
+
+ var STD_WIDTH = 100;
+ var MAX_WIDTH = 600;
+ if (window.innerWidth) {
+ MAX_WIDTH = Math.min(MAX_WIDTH, window.innerWidth - 20);
+ }
+ if (document.body && document.body.scrollWidth) {
+ MAX_WIDTH = Math.min(MAX_WIDTH, document.body.scrollWidth - 20);
+ }
+
+ var nicetitle_length = 0;
+ var lines = nicetitle.replace(/<br ?\/>/g, "\n").split("\n");
+ for (var i = 0; i < lines.length; ++i) {
+ nicetitle_length = Math.max(nicetitle_length, lines[i].length);
+ }
+
+ var h_pixels = nicetitle_length * 7;
+ var t_pixels = nicetitle_length * 10;
+
+ var w;
+ if (h_pixels > STD_WIDTH) {
+ w = h_pixels;
+ } else if (STD_WIDTH > t_pixels) {
+ w = t_pixels;
+ } else {
+ w = STD_WIDTH;
+ }
+
+ // Make sure all of the tooltip is visible
+ var left = pos[0] + 20,
+ innerWidth = window.innerWidth || document.documentElement.clientWidth || document.body.offsetWidth,
+ pageXOffset = window.pageXOffset || document.documentElement.scrollLeft;
+ if (innerWidth && ((left + w) > (innerWidth + pageXOffset))) {
+ left = innerWidth - w - 40 + pageXOffset;
+ }
+ if (document.body.scrollWidth && ((left + w) > (document.body.scrollWidth + pageXOffset))) {
+ left = document.body.scrollWidth - w - 25 + pageXOffset;
+ }
+
+ d.id = 'toolTip';
+ d.style.left = left + 'px';
+ d.style.width = Math.min(w, MAX_WIDTH) + 'px';
+ d.style.top = (pos[1] + 10) + 'px';
+ d.style.display = '';
+
+ document.getElementsByTagName('body')[0].appendChild(d);
+ ToolTips.current = d;
+
+ if (typeof ToolTips_Option_Windowed_Controls != 'undefined') {
+ var iframe = document.getElementById('iframe_tt');
+ if (iframe == null) {
+ iframe = document.createElement('<iframe src="javascript:false;" name="iframe_tt" id="iframe_tt" scrolling="no" frameborder="0" style="position:absolute;top:0;left:0;display:none"></iframe>');
+ document.getElementsByTagName('body')[0].appendChild(iframe);
+ }
+ iframe.style.width = d.offsetWidth;
+ iframe.style.height = d.offsetHeight;
+ iframe.style.top = d.style.top;
+ iframe.style.left = d.style.left;
+ iframe.style.position = 'absolute';
+ iframe.style.display = 'block';
+ d.style.zIndex = 100;
+ iframe.style.zIndex = 99;
+ }
+ } catch (e) {}
+ }
+
+};
+
+/**
+ * Return the [x,y] position of the mouse.
+ */
+function mousePos(event)
+{
+ return [event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop))];
+}
+/**
+ * Return the [x,y] position of an element.
+ */
+function eltPos(elt)
+{
+ if (elt.offsetParent) {
+ for (posX = 0, posY = 0; elt.offsetParent; elt = elt.offsetParent) {
+ posX += elt.offsetLeft;
+ posY += elt.offsetTop;
+ }
+ return [posX, posY];
+ } else {
+ return [elt.x, elt.y];
+ }
+}
+
+/**
+ * Add an event listener as long as the browser supports it. Different
+ * browsers still handle these events slightly differently; in
+ * particular avoid using "this" in event functions.
+ *
+ * @author Scott Andrew
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ */
+function addEvent(obj, evType, fn)
+{
+ if (obj.addEventListener) {
+ obj.addEventListener(evType, fn, true);
+ return true;
+ } else if (obj.attachEvent) {
+ var r = obj.attachEvent('on' + evType, fn);
+ EventCache.add(obj, evType, fn);
+ return r;
+ } else {
+ return false;
+ }
+}
+
+var EventCache = function()
+{
+ var listEvents = [];
+
+ return {
+ listEvents: listEvents,
+
+ add: function(node, sEventName, fHandler, bCapture)
+ {
+ listEvents.push(arguments);
+ },
+
+ flush: function()
+ {
+ var i, item;
+ for (i = listEvents.length - 1; i >= 0; i = i - 1) {
+ item = listEvents[i];
+
+ if (item[0].removeEventListener) {
+ item[0].removeEventListener(item[1], item[2], item[3]);
+ };
+
+ /* From this point on we need the event names to be
+ * prefixed with 'on'. */
+ if (item[1].substring(0, 2) != 'on') {
+ item[1] = 'on' + item[1];
+ }
+
+ if (item[0].detachEvent) {
+ item[0].detachEvent(item[1], item[2]);
+ }
+
+ item[0][item[1]] = null;
+ }
+ }
+ };
+}();
+
+if (document.createElement && document.getElementsByTagName) {
+ addEvent(window, 'load', ToolTips.attachBehavior);
+ addEvent(window, 'unload', ToolTips.out);
+ addEvent(window, 'unload', EventCache.flush);
+}
--- /dev/null
+/* Prototype JavaScript framework, version 1.6.0.3
+ * (c) 2005-2008 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.6.0.3',
+
+ Browser: {
+ IE: !!(window.attachEvent &&
+ navigator.userAgent.indexOf('Opera') === -1),
+ Opera: navigator.userAgent.indexOf('Opera') > -1,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
+ navigator.userAgent.indexOf('KHTML') === -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ SelectorsAPI: !!document.querySelector,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div')['__proto__'] &&
+ 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 }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value;
+ value = (function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method);
+
+ value.valueOf = method.valueOf.bind(method);
+ value.toString = method.toString.bind(method);
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+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.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } 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.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ 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);
+ },
+
+ isElement: function(object) {
+ return !!(object && object.nodeType == 1);
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
+ .replace(/\s+/g, '').split(',');
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ defer: function() {
+ var args = [0.01].concat($A(arguments));
+ return this.delay.apply(this, args);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+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;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ 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);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } 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 = Object.isUndefined(count) ? 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 String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(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 = new Element('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 (!Object.isArray(hash[key])) 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) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ 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;
+ if (str.blank()) return false;
+ 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);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+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.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) 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('')
+});
+
+String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ try {
+ this._each(function(value) {
+ iterator.call(context, value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ var index = -number, slices = [], array = this.toArray();
+ if (number < 1) return array;
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator.call(context, value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator.call(context, value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator.call(context, value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ var result;
+ this.each(function(value, index) {
+ if (iterator.call(context, value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator.call(context, value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator || Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator.call(context, value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ this.each(function(value, index) {
+ memo = iterator.call(context, 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, context) {
+ iterator = iterator || Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator.call(context, value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator.call(context, value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator.call(context, value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator.call(context, value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ return this.map(function(value, index) {
+ return {
+ value: value,
+ criteria: iterator.call(context, 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 (Object.isFunction(args.last()))
+ 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,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ // In Safari, only use the `toArray` method if it's not a NodeList.
+ // A NodeList is a function, has an function `item` property, and a numeric
+ // `length` property. Adapted from Google Doctype.
+ if (!(typeof iterable === 'function' && typeof iterable.length ===
+ 'number' && typeof iterable.item === 'function') && iterable.toArray)
+ return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+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(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ 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;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ 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 (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ 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 (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator, context) {
+ $R(0, this, true).each(iterator, context);
+ 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';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ // simulating poorly supported hasOwnProperty
+ if (this._object[key] !== Object.prototype[key])
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.inject([], function(results, pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return results.concat(values.map(toQueryPair.curry(key)));
+ } else results.push(toQueryPair(key, values));
+ return results;
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ 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 (Object.isFunction(responder[callback])) {
+ 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 = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ 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 = Object.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 {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ 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 (Object.isFunction(extras.push))
+ 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() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || 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.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(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(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ 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 (Object.isString(element))
+ 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(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+ if (element) this.Element.prototype = element.prototype;
+}).call(window);
+
+Element.cache = { };
+
+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 = $(element);
+ element.style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ element = $(element);
+ element.style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ 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 $(element).select("*");
+ },
+
+ 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 (Object.isString(selector))
+ 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 Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ Element.select(element, expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ 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;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // 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);
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (ancestor.contains)
+ return ancestor.contains(element) && ancestor !== element;
+
+ while (element = element.parentNode)
+ if (element == ancestor) return true;
+
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ 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 || value == 'auto') {
+ 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) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = 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 (Prototype.Browser.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.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== '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;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(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.toUpperCase() == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return element;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ 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';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return element;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ 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;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ element = $(element);
+ var op = element.offsetParent, body = document.body, docEl = document.documentElement;
+
+ /* IE with strict doctype may try to return documentElement as offsetParent
+ on relatively positioned elements, we will return body instead */
+ if (op && op !== docEl) return $(op);
+ if (op === docEl || element === docEl || element === body) return $(body);
+
+ while ((element = element.parentNode) && element !== body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(body);
+ },
+
+ viewportOffset: function(forElement) {
+ forElement = $(forElement);
+
+ var element = forElement, valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ } while ((element = element.getOffsetParent()) != document.body);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ 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 = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ 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(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // 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) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ // IE throws an error if element is not in document
+ try { element.offsetParent }
+ catch(e) { return $(document.body) }
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ try { element.offsetParent }
+ catch(e) { return Element._returnOffset(0,0) }
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
+ function(proceed, element) {
+ try { element.offsetParent }
+ catch(e) { return Element._returnOffset(0,0) }
+ return proceed(element);
+ }
+ );
+
+ 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) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName.toUpperCase() == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.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 Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var 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.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName.toUpperCase(), property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+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 (Object.isArray(tagName)) 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;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ 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 (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { }, B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ if (B.WebKit && !document.evaluate) {
+ // Safari <3.0 needs self.innerWidth/Height
+ dimensions[d] = self['inner' + D];
+ } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
+ // Opera <9.5 needs document.body.clientWidth/Height
+ dimensions[d] = document.body['client' + D]
+ } else {
+ dimensions[d] = document.documentElement['client' + D];
+ }
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* 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({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+
+ if (this.shouldUseSelectorsAPI()) {
+ this.mode = 'selectorsAPI';
+ } else if (this.shouldUseXPath()) {
+ this.mode = 'xpath';
+ this.compileXPathMatcher();
+ } else {
+ this.mode = "normal";
+ this.compileMatcher();
+ }
+
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(e))
+ return false;
+
+ return true;
+ },
+
+ shouldUseSelectorsAPI: function() {
+ if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
+
+ if (!Selector._div) Selector._div = new Element('div');
+
+ // Make sure the browser treats the selector as valid. Test on an
+ // isolated element to minimize cost of this check.
+ try {
+ Selector._div.querySelector(this.expression);
+ } catch(e) {
+ return false;
+ }
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ 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(Object.isFunction(c[i]) ? 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(Object.isFunction(x[i]) ? 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;
+ var e = this.expression, results;
+
+ switch (this.mode) {
+ case 'selectorsAPI':
+ // querySelectorAll queries document-wide, then filters to descendants
+ // of the context element. That's not what we want.
+ // Add an explicit context to the selector if necessary.
+ if (root !== document) {
+ var oldId = root.id, id = $(root).identify();
+ e = "#" + id + " " + e;
+ }
+
+ results = $A(root.querySelectorAll(e)).map(Element.extend);
+ root.id = oldId;
+
+ return results;
+ case 'xpath':
+ return document._getElementsByXPath(this.xpath, root);
+ default:
+ return this.matcher(root);
+ }
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ 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: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ 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 (Object.isFunction(h)) 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)]",
+ 'checked': "[@checked]",
+ 'disabled': "[(@disabled) and (@type!='hidden')]",
+ 'enabled': "[not(@disabled) and (@type!='hidden')]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? 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); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); 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]+:)?[\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ 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) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = 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._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) 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])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ 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, 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) {
+ var uTagName = 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() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [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, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ 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, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ 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._countedByPrototype) {
+ 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) 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._countedByPrototype) 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 && (!node.type || node.type !== 'hidden'))
+ 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 == v || nv && nv.startsWith(v); },
+ '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
+ '*=': function(nv, v) { return nv == v || nv && nv.include(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() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ 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;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ 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) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['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, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(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 Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return 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.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, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, value) {
+ if (Object.isUndefined(value))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, currentValue, single = !Object.isArray(value);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ currentValue = this.optionValue(opt);
+ if (single) {
+ if (currentValue == value) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = value.include(currentValue);
+ }
+ }
+ },
+
+ 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 = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ 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, 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(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+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,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ event = Event.extend(event);
+
+ var node = event.target,
+ type = event.type,
+ currentTarget = event.currentTarget;
+
+ if (currentTarget && currentTarget.tagName) {
+ // Firefox screws up the "click" event when moving between radio buttons
+ // via arrow keys. It also screws up the "load" and "error" events on images,
+ // reporting the document as the target instead of the original image.
+ if (type === 'load' || type === 'error' ||
+ (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
+ && currentTarget.type === 'radio'))
+ node = currentTarget;
+ }
+ if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
+ return Element.extend(node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ var docElement = document.documentElement,
+ body = document.body || { scrollLeft: 0, scrollTop: 0 };
+ return {
+ x: event.pageX || (event.clientX +
+ (docElement.scrollLeft || body.scrollLeft) -
+ (docElement.clientLeft || 0)),
+ y: event.pageY || (event.clientY +
+ (docElement.scrollTop || body.scrollTop) -
+ (docElement.clientTop || 0))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+
+ // Internet Explorer needs to remove event handlers on page unload
+ // in order to avoid memory leaks.
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ // Safari has a dummy event handler on page unload so that it won't
+ // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
+ // object when page is returned to via the back button using its bfcache.
+ if (Prototype.Browser.WebKit) {
+ window.addEventListener('unload', Prototype.emptyFunction, false);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+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;
+ },
+
+ // 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 = Element.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 = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.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;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+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);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods();
\ No newline at end of file
--- /dev/null
+/**
+ * Redbox.js
+ *
+ * $Horde: horde/js/src/redbox.js,v 1.10 2008/02/06 09:02:37 slusarz Exp $
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ */
+
+var RedBox = {
+
+ overlay: true,
+ onDisplay: null,
+
+ showInline: function(id)
+ {
+ this.appearWindow();
+ this.cloneWindowContents(id);
+ },
+
+ showHtml: function(html)
+ {
+ this.appearWindow();
+ this.htmlWindowContents(html);
+ },
+
+ appearWindow: function()
+ {
+ var loading = $('RB_loading');
+ if (loading && loading.visible()) {
+ loading.hide();
+ } else {
+ this.showOverlay();
+ }
+ var opts = { duration: 0.4, queue: 'end' },
+ w = $('RB_window');
+ if (this.onDisplay) {
+ opts.afterFinish = this.onDisplay;
+ }
+ new Effect.Appear(w, opts);
+ w.scrollTo();
+ },
+
+ loading: function()
+ {
+ this.showOverlay();
+ var rl = $('RB_loading');
+ if (rl) {
+ rl.show();
+ }
+ this.setWindowPosition();
+ },
+
+ close: function()
+ {
+ new Effect.Fade('RB_window', { duration: 0.4 });
+ if (this.overlay) {
+ new Effect.Fade('RB_overlay', { duration: 0.4 });
+ }
+ },
+
+ showOverlay: function()
+ {
+ var rb = $('RB_redbox');
+ if (!rb) {
+ rb = new Element('DIV', { id: 'RB_redbox', align: 'center' });
+ $(document.body).insert(rb);
+
+ var ov = new Element('DIV', { id: 'RB_overlay' }).hide();
+ rb.insert({ top: new Element('DIV', { id: 'RB_window' }).hide() }).insert({ top: ov });
+
+ if (this.overlay) {
+ ov.insert({ top: new Element('DIV', { id: 'RB_loading' }).hide() });
+ }
+ }
+
+ if (this.overlay) {
+ this.setOverlaySize();
+ new Effect.Appear('RB_overlay', { duration: 0.4, to: 0.6, queue: 'end' });
+ }
+ },
+
+ setOverlaySize: function()
+ {
+ if (window.innerHeight && window.scrollMaxY) {
+ yScroll = window.innerHeight + window.scrollMaxY;
+ } else if (document.body.scrollHeight > document.body.offsetHeight) {
+ // all but Explorer Mac
+ yScroll = document.body.scrollHeight;
+ } else {
+ // Explorer Mac...would also work in Explorer 6 Strict, Mozilla
+ // and Safari
+ yScroll = document.body.offsetHeight;
+ }
+ Element.setStyle('RB_overlay', { height: yScroll + 'px' });
+ },
+
+ setWindowPosition: function()
+ {
+ var win = $('RB_window');
+ var d = win.getDimensions(),
+ v = document.viewport.getDimensions();
+ win.setStyle({ width: 'auto', height: 'auto', left: ((v.width - d.width) / 2) + 'px', top: ((v.height - d.height) / 2) + 'px' });
+ },
+
+ cloneWindowContents: function(id)
+ {
+ $('RB_window').appendChild($($(id).cloneNode(true)).setStyle({ display: 'block' }));
+ this.setWindowPosition();
+ },
+
+ htmlWindowContents: function(html)
+ {
+ $('RB_window').update(html);
+ this.setWindowPosition();
+ },
+
+ getWindowContents: function()
+ {
+ var w = $('RB_window');
+ return w.visible() ? w.down() : null;
+ },
+
+ overlayVisible: function()
+ {
+ var ov = $('RB_overlay');
+ return ov && ov.visible();
+ }
+
+}
--- /dev/null
+/**
+ * $Horde: horde/themes/ie5mac.css,v 1.4 2005/05/10 13:53:40 chuck Exp $
+ *
+ * CSS corrections for IE5/Mac.
+ */
+
+#menu li {
+ width: 40px;
+}
+.tabset {
+ white-space: nowrap;
+}
+.tabset li a {
+ float: left;
+}
+#sidebarPanel {
+ padding-bottom: 30px;
+}
+.header {
+ clear: none;
+}
+.header ul {
+ width: 1%;
+ white-space: nowrap;
+}
--- /dev/null
+/**
+ * $Horde: horde/themes/ie6_or_less.css,v 1.6 2009/04/14 03:47:30 slusarz Exp $
+ *
+ * CSS corrections for IE 6 and below.
+ */
+
+#sidebar-frame {
+ overflow-x: hidden;
+}
+
+.treeRow {
+ overflow: visible;
+ height: 20px;
+}
+
+#menu {
+ overflow: visible;
+ height: 50px;
+}
+
+.clear {
+ clear: none;
+}
--- /dev/null
+/**
+ * $Horde: horde/themes/moz14.css,v 1.1 2005/03/16 11:42:56 jan Exp $
+ *
+ * CSS corrections for Mozilla <= 1.4.
+ */
+
+#menu {
+ overflow: visible;
+ height: 50px;
+}
--- /dev/null
+/**
+ * $Horde: horde/themes/opera.css,v 1.3 2005/10/03 16:22:52 jan Exp $
+ *
+ * CSS corrections for Opera.
+ */
+
+.treeRow {
+ overflow: visible;
+ height: 20px;
+}
+
+#menu {
+ overflow: visible;
+ height: 50px;
+}
--- /dev/null
+/**
+ * $Horde: horde/themes/rtl.css,v 1.10 2009/03/24 22:47:05 slusarz Exp $
+ */
+
+/* Global default styles. */
+body {
+ direction: rtl;
+ font-family: Tahoma,Koodak,Homa,Nazli,Verdana,Geneva,Arial,"Bitstream Vera Sans",Helvetica,sans-serif;
+}
+
+body.scrollbar-quirk {
+ margin-left: 15px;
+}
+
+.header {
+ text-align: right;
+}
+.header ul {
+ float: left;
+ text-align: left;
+}
+.headerbox {
+ text-align: right;
+}
+
+/* Table styles. */
+td, th {
+ text-align: right;
+}
+
+.sortup, .sortdown {
+ padding-left: 1px;
+ background-position: center right;
+ padding-right: 10px;
+}
+
+/* Form styles. */
+form[action^="https://"] input[type="submit"] {
+ background-position: 5% center;
+ padding-right: 6px;
+ padding-left: 10%;
+}
+option {
+ padding: 0 3px 0 5px;
+}
+
+/* Styles for email-like messages. */
+.citation {
+ padding-left: 0;
+ border-left-width: 0;
+ padding-right: 1em;
+ border-right-width: 1px;
+ border-right-style: solid;
+}
+
+/* Various popup and status layers. */
+.notices {
+ text-align: right;
+}
+.notices li, .notice {
+ padding: 1px 5px 1px 1px;
+ }
+.notices img, .notice img {
+ margin-right: 0;
+ margin-left: .5em;
+}
+
+/* Menu styles. */
+#menu {
+ padding-right: 0;
+ padding-left: 8px;
+}
+#menu li {
+ float: right;
+}
+#menu li.rightFloat {
+ float: left;
+}
+#menuBottom {
+ float: left;
+ text-align: left;
+}
+
+/* Sidebar styles. */
+#sidebarPanel {
+ -moz-border-radius-bottomright: 0;
+ -moz-border-radius-bottomleft: 15px;
+ -webkit-border-bottom-right-radius: 0;
+ -webkit-border-bottom-left-radius: 15px;
+}
+
+/* Tab styles. */
+.tabset {
+ float: right;
+}
+.tabset ul {
+ padding-left: 0;
+ padding-right: 8px;
+}
+.tabset li {
+ float: right;
+ margin: -3px 0 0 2px;
+}
+.tabset img {
+ float: right;
+ padding-right: 0;
+ padding-left: 2px;
+}
+
+/* Preferences. */
+#services_prefs .header ul {
+ float: left;
+ text-align: left;
+}
+.prefsOverview div {
+ float: right;
+}
+.prefsOverview div div {
+ padding-left: 0;
+ padding-right: 10px;
+}
+
+/* MIME styles. */
+.download {
+ padding: 2px 0 2px 20px;
+ background-position: center left;
+}
+
+/* Calendar Popup. */
+.calendarPopup tbody {
+ text-align: left;
+}
+
+/* Redbox styles. */
+#RB_window {
+ text-align: right;
+}
+
+/* Color picker styles. */
+#color-picker .north div {
+ float: left;
+}
+#color-picker .south {
+ margin: 32px 0 0 10px;
+ margin: 32px 10px 0 0;
+}
+#color-picker .south img {
+ left: 0;
+ right: -1px;
+}
+#color-picker #color-picker-cursor img {
+ left: 0;
+ right: -1px;
+}
+#color-picker #color-picker-hex {
+ padding: 5px 7px 4px 0;
+ float: right;
+}
+#color-picker #color-picker-resize {
+ float: left;
+ left: 0;
+ right: 7px;
+ cursor: sw-resize;
+}
+
+.leftAlign {
+ text-align: right;
+}
+.rightAlign {
+ text-align: left;
+}
+.leftFloat {
+ float: right;
+}
+.rightFloat {
+ float: left;
+}
--- /dev/null
+/**
+ * $Horde: horde/themes/screen.css,v 1.207 2009/04/23 20:09:28 mrubinsk Exp $
+ */
+
+/* Global default styles. */
+* {
+ /* Zero out all padding and margins to start with for better
+ * cross-browser control. */
+ padding: 0;
+ margin: 0;
+}
+
+body, input, select, textarea, .inProgress {
+ font-family: Geneva,Arial,"Bitstream Vera Sans",Helvetica,sans-serif;
+}
+body {
+ font-size: 75%;
+ background: #fff;
+ color: #000;
+}
+
+body.scrollbar-quirk {
+ margin-right: 15px;
+}
+
+p {
+ margin-bottom: 10px;
+}
+
+img, .img, .img:active, .img:hover, .img:visited, .image {
+ border: none;
+ vertical-align: middle;
+ background: transparent;
+}
+/* This must be declared seperately or IE will ignore all of the selectors. */
+input[type=image] {
+ border: none;
+ vertical-align: middle;
+ background: transparent;
+}
+
+ins {
+ background: #cfc;
+}
+del {
+ background: #fcc;
+}
+
+br.spacer {
+ line-height: 8px;
+}
+
+.box {
+ padding: 3px;
+ border: 1px dashed #999;
+ background: #fff;
+}
+.solidbox {
+ border: 1px solid #000;
+}
+.greybox {
+ border: 1px solid #000;
+ background: #e9e9e9;
+}
+.headerbox {
+ border-left: 1px solid #000;
+ border-right: 1px solid #000;
+ border-bottom: 1px solid #000;
+ background: #fff;
+ vertical-align: top;
+}
+.roundedBox {
+ -moz-border-radius: 15px;
+ -webkit-border-radius: 15px;
+}
+.roundedTop {
+ -moz-border-radius-topright: 15px;
+ -moz-border-radius-topleft: 15px;
+ -webkit-border-top-right-radius: 15px;
+ -webkit-border-top-left-radius: 15px;
+}
+.roundedBottom {
+ -moz-border-radius-bottomright: 15px;
+ -moz-border-radius-bottomleft: 15px;
+ -webkit-border-bottom-right-radius: 15px;
+ -webkit-border-bottom-left-radius: 15px;
+}
+.header {
+ text-align: left;
+ font-weight: bold;
+ font-size: 125%;
+ padding: 3px;
+}
+.header a:hover, a.header:hover {
+ color: #333;
+}
+.header img {
+ vertical-align: bottom;
+}
+.header input, .header select {
+ font-size: 80%;
+}
+.header .smallheader input, .header .smallheader select {
+ font-size: 100%;
+}
+.header .button, .header .smallheader .button {
+ font-size: 72%;
+}
+
+.nowrap {
+ white-space: nowrap;
+}
+.clear {
+ clear: both;
+ line-height: 0;
+ height: 0;
+}
+
+a {
+ color: blue;
+ text-decoration: none;
+}
+a:hover {
+ text-decoration: underline;
+}
+.selected {
+ background: #bbcbff;
+}
+.selected-over {
+ background: #cef;
+}
+
+/* Table styles. */
+table {
+ border: none;
+}
+td, th {
+ padding: 1px;
+}
+th {
+ color: #333;
+}
+td {
+}
+ul.linedRow {
+ list-style-type: none;
+}
+.linedRow, tr.linedRow td, table.linedRow td, ul.linedRow li {
+ color: #000;
+ background: #fff;
+ border-bottom: 1px solid #ddd;
+}
+table.linedRow, ul.linedRow {
+ border-bottom: none;
+}
+.linedRowSelectedCol, td.linedRowSelectedCol, table.linedRow td.linedRowSelectedCol {
+ color: #000;
+ background: #f3f3f3;
+ border-bottom: 1px solid #ddd;
+}
+.selectedRow, tr.selectedRow td {
+ background: #ffc;
+}
+.selectedRow:hover, tr.selectedRow:hover td, .selectedRow-over, tr.selectedRow-over td {
+ background: #ffd;
+}
+table.nopadding td, table.nopadding th {
+ padding: 0;
+}
+.sortup {
+ background: #bbcbff url("graphics/za.png") center left no-repeat;
+ padding-left: 10px;
+}
+.sortdown {
+ background: #bbcbff url("graphics/az.png") center left no-repeat;
+ padding-left: 10px;
+}
+/* Horde UI standard tables */
+table.horde-table {
+ width: 99%;
+ margin: 0 0 8px 5px;
+ border-top: 1px solid #ddd;
+ border-left: 1px solid #ddd;
+}
+table.horde-table th {
+ padding: 3px;
+ background: #e9e9e9;
+ border-right: 1px solid #ccc;
+ text-align: left;
+}
+table.horde-table th.rightAlign {
+ text-align: right;
+}
+table.horde-table td {
+ padding: 3px;
+ border-right: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+}
+table.horde-table th.sortup {
+ background: #bbcbff url("graphics/za.png") center left no-repeat;
+ padding-left: 10px;
+}
+table.horde-table th.sortdown {
+ background: #bbcbff url("graphics/az.png") center left no-repeat;
+ padding-left: 10px;
+}
+/* Alternating styles. item0, item1 are deprecated. */
+.striped, .rowEven, .item0 {
+ background-color: #eee;
+}
+.rowOdd, .item1 {
+ background-color: #ddd;
+}
+
+.widget {
+ font-size: 90%;
+}
+
+.light {
+}
+.smallheader {
+ font-size: 100%;
+ font-weight: bold;
+ padding: 2px;
+}
+.header .smallheader {
+ font-size: 80%;
+}
+.header .smallheader a.smallheader {
+ font-size: 100%;
+}
+small, .small {
+ font-size: 80%;
+}
+.control {
+ color: #000;
+ background: #ccc;
+ border-bottom: 1px solid #999;
+ padding: 1px;
+}
+.item {
+ color: #000;
+ background: #eee;
+}
+.accessKey {
+ text-decoration: underline;
+}
+.text {
+ color: #000;
+ background: #fff;
+}
+
+/* Form styles. */
+.form table {
+ width: 100%;
+ padding: 2px;
+ border-collapse: collapse;
+}
+form[action^="https://"] input[type="submit"] {
+ background-image: url("graphics/locked.png");
+ background-position: 95% center;
+ background-repeat: no-repeat;
+ padding-right: 10%;
+}
+input[disabled], textarea[disabled] {
+ background-color: #e9e9e9;
+ color: #a8a8a8;
+}
+.htmlarea .statusBar .statusBarTree a {
+ font: inherit;
+}
+.htmlarea table {
+ width: auto;
+}
+.form-error {
+ color: #f00;
+}
+input, select, textarea {
+ font-size: 100%;
+ font-weight: normal;
+}
+input {
+ padding: 1px;
+}
+option {
+ padding: 0 5px 0 3px;
+}
+.checkbox, .radio {
+ border: 0;
+ height: 14px;
+ width: 14px;
+ background: transparent;
+}
+.button {
+ cursor: pointer;
+ font-size: 90%;
+ padding: 1px 6px;
+}
+a.button {
+ padding: 2px 8px;
+ font-weight: normal;
+ text-decoration: none;
+}
+
+pre, code, .fixed, ol.code-listing, table.lineNumbered * {
+ font-size: 100%;
+ font-family: "Lucida Console","Bitstream Vera Sans Mono",Courier,"Courier New";
+}
+
+/* Styles for email-like messages. */
+.signature {
+ color: #ccc;
+}
+.signature .fixed {
+ color: #ccc;
+}
+.citation {
+ margin: 1em 0;
+ padding-left: 1em;
+ border-left-width: 1px;
+ border-left-style: solid;
+}
+.quoted1 {
+ color: #606;
+ border-color: #606;
+ background-color: #eee;
+}
+.quoted2 {
+ color: #077;
+ border-color: #077;
+}
+.quoted3 {
+ color: #900;
+ border-color: #900;
+}
+.quoted4 {
+ color: #009;
+ border-color: #009;
+}
+.quoted5 {
+ color: #b60;
+ border-color: #b60;
+}
+
+/* Various popup and status layers. */
+.notices {
+ text-align: left;
+ margin: .5em 8px;
+ list-style-type: none;
+}
+.notices li, .notice {
+ font-weight: bold;
+ color: #000;
+ background: #ffc;
+ border: 1px solid #aaa;
+ padding: 1px 1px 1px 5px;
+}
+.notices img, .notice img {
+ margin-right: .5em;
+}
+.tooltip, div.nicetitle {
+ color: #000;
+ background: #ffc;
+ border: 1px solid #000;
+ padding: 5px;
+ z-index: 1001;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+}
+div.nicetitle {
+ position: absolute;
+ overflow: hidden;
+ opacity: .9;
+}
+.inProgress {
+ font-size: 80%;
+ padding: 2px;
+ color: #fff;
+ background: #f00;
+}
+
+/* Tree styles. */
+.treeRow {
+ overflow: hidden;
+ min-height: 20px;
+ clear: both;
+}
+
+/* Menu styles. */
+#menu {
+ overflow: hidden;
+ min-height: 50px;
+ margin-bottom: 8px;
+ padding-right: 8px;
+}
+#menu ul {
+ padding: 5px;
+}
+#menu li {
+ list-style-type: none;
+ text-align: center;
+ margin: 2px;
+ float: left;
+}
+#menu li.separator {
+ width: 40px;
+}
+#menu a {
+ display: block;
+ white-space: pre;
+ font-size: 90%;
+ text-decoration: none;
+ padding: 3px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+}
+#menu h1 {
+ font-weight: bold;
+ font-size: 150%;
+ line-height: 48px;
+ vertical-align: bottom;
+}
+#menu input, #menu select {
+ margin-top: 16px;
+}
+#menuBottom {
+ margin: -8px 0 0 0;
+ padding: 4px;
+ float: right;
+ text-align: right;
+ font-size: 90%;
+ background: #eee;
+}
+
+/* Sidebar styles. */
+.sidebar #menu {
+ margin: 0;
+}
+#sidebarPanel {
+ -moz-border-radius-bottomright: 15px;
+ -webkit-border-bottom-right-radius: 15px;
+ padding-top: 5px;
+ padding-bottom: 10px;
+ background: #eee;
+ white-space: nowrap;
+}
+#sidebarPanel a, #sidebarPanel span {
+ color: #000;
+ white-space: pre;
+ font-size: 90%;
+ text-decoration: none;
+}
+#sidebarPanel a a, #sidebarPanel a span, #sidebarPanel span a, #sidebarPanel span span {
+ font-size: 100%;
+}
+#sidebarPanel span.accessKey {
+ text-decoration: underline;
+}
+#sidebarPanel span.toggle {
+ cursor: pointer;
+}
+#sidebarPanel a:hover {
+ color: #000;
+}
+
+/* Pager. */
+.pager {
+ text-align: center;
+}
+
+/* Tab styles. */
+.tabset {
+ float: left;
+ width: 100%;
+ font-weight: bold;
+ background: url("graphics/tab_bottom.gif") repeat-x bottom;
+}
+.tabset ul {
+ margin-top: 4px;
+ padding-left: 8px;
+ list-style: none;
+}
+.tabset li {
+ float: left;
+ margin: -3px 2px 0 0;
+ white-space: nowrap;
+}
+.tabset li a {
+ color: #000;
+ background-color: #e9e9e9;
+ padding: 2px 0.5em;
+ display: block;
+ border: 1px solid #000;
+}
+.tabset li a:hover {
+ background-color: #fff;
+}
+.tabset li.activeTab a {
+ border-bottom: 1px solid #000;
+ background-color: #000;
+ color: #fff;
+}
+.tabset li.activeTab a:hover {
+}
+.tabset img {
+ display: block;
+ float: left;
+ padding-right: 2px;
+}
+
+/* Preferences. */
+#services_prefs .header ul {
+ float: right;
+ text-align: right;
+ font-size: 80%;
+}
+#services_prefs .header li {
+ list-style: none;
+ display: inline;
+}
+.prefsOverview div {
+ float: left;
+}
+.prefsOverview div div {
+ padding-left: 10px;
+ width: 95%;
+}
+.prefsOverview h2 {
+ font-size: 150%;
+ font-weight: bold;
+}
+.prefsOverview dt a {
+ display: block;
+ padding: 2px;
+ font-weight: bold;
+ border: 1px solid #000;
+ border-bottom: 1px solid #446;
+ background: #e9e9e9;
+}
+.prefsOverview dd {
+ padding: 2px;
+ margin-bottom: 10px;
+ color: #000;
+ background: #fff;
+ border-left: 1px solid #000;
+ border-right: 1px solid #000;
+ border-bottom: 1px solid #000;
+}
+div.prefsContainer {
+ padding: 1em;
+}
+div.prefsContainer p {
+ padding-top: 1em;
+}
+
+/* Block styles. */
+.currentBlock {
+ border: 2px solid red;
+}
+.blockIcons {
+ padding-top: 5px;
+ display:none;
+}
+.blockHeader:hover .blockIcons {
+ display: block;
+}
+#googlesearch {
+ padding: .3em;
+}
+
+/* Help styles. */
+body.help_about, body.help_entry {
+ margin: 0.5em;
+}
+.helplink {
+ cursor: help;
+}
+.help {
+ background: #fff;
+ color: #000;
+}
+.help h1 {
+ font-size: 125%;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+}
+.help h2 {
+ padding-top: 1em;
+ padding-bottom: 0.5em;
+ font-size: 110%;
+}
+.help p {
+ margin-left: 1em;
+ margin-right: 1em;
+ margin-bottom: 1em;
+}
+.help em {
+ display: block;
+ padding: 5px;
+ margin-left: 1em;
+ margin-right: 1em;
+ margin-bottom: 1em;
+}
+.help em.helpTip {
+ color: #090;
+ background: #e0f0e0;
+}
+.help em.helpWarn {
+ color: #900;
+ background: #f0e0e0;
+}
+
+/* Source markup styles. */
+ol.code-listing {
+ overflow: hidden;
+ color: #999;
+ background-color: #fff;
+ text-align: left;
+ list-style-position: inside;
+ list-style-type: decimal-leading-zero;
+ white-space: nowrap;
+}
+ol.code-listing li {
+ padding: 3px;
+ white-space: pre;
+ padding-left: .5em;
+}
+ol.code-listing .comment {
+ color: #666;
+}
+ol.code-listing .default {
+ color: #00b;
+}
+ol.code-listing .keyword {
+ color: #070;
+}
+ol.code-listing .string {
+ color: #d00;
+}
+
+table.lineNumbered * {
+ line-height: 16px;
+}
+.lineNumbered th {
+ background: #e9e9e9;
+ border-right: 1px solid #e0e0e0;
+ border-bottom: none;
+ padding-left: 10px;
+ padding-right: 10px;
+ text-align: right;
+}
+.lineNumbered td {
+ vertical-align: top;
+ width: 100%;
+ white-space: pre;
+ background: #fff;
+ padding-left: 10px;
+}
+.parentheses {
+ color: #2a6;
+ font-weight: bold;
+}
+.comment {
+ color: #aac;
+}
+.htag {
+ color: #569;
+ background: #d5d6da;
+ font-weight: bold;
+}
+.metac {
+ color: #0ff;
+ background: #d5d6da;
+}
+.id {
+ color: #e82;
+ background: #e4e4e0;
+}
+.attr {
+ color: #6af;
+}
+.value {
+ color: #d46;
+}
+.color {
+ color: #f57;
+}
+.eol {
+ color: #26e;
+}
+.url {
+ color: #962;
+}
+.file {
+ color: #444;
+ background: #fe4;
+}
+.class {
+ font-style: italic;
+}
+
+/* Sound selection. */
+ul.sound-list {
+ list-style: none;
+}
+.sound-list li {
+ height: 24px;
+}
+.sound-list embed {
+ vertical-align: middle;
+ height: 24px;
+}
+
+/* Calendar Popup. */
+table.calendarPopup {
+ border: 1px solid #ccc;
+ background: #fff;
+ width: 12em;
+}
+.calendarPopup thead {
+ font-weight: bold;
+}
+.calendarPopup th {
+ border-bottom: 1px solid #ccc;
+}
+.calendarPopup tbody {
+ text-align: right;
+}
+.calendarPopup a {
+ color: #000;
+ display: block;
+ padding: 2px;
+}
+.calendarPopup tbody a:hover {
+ background: #ffc;
+}
+.calendarPopup .current {
+ font-weight: bold;
+ background: #eef;
+}
+.calendarPopup .today {
+ font-weight: bold;
+}
+
+.hidden {
+ display: none;
+}
+
+/* Redbox styles. */
+#RB_overlay {
+ position: absolute;
+ z-index: 100;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ min-height: 100%;
+ background-color: #000;
+ filter: alpha(opacity=60);
+ -moz-opacity: .6;
+ opacity: .6;
+}
+#RB_loading {
+ z-index: 101;
+ width: 66px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 200px;
+ padding-bottom: 66px;
+ text-align: center;
+ background: url("graphics/redbox_spinner.gif") no-repeat bottom center;
+}
+#RB_window {
+ z-index: 102;
+ background-color: #fff;
+ display: block;
+ text-align: left;
+ overflow: hidden;
+ margin: 20px auto 0 auto;
+ position: absolute;
+}
+
+/* Color picker styles. */
+#color-picker {
+ color: #999;
+ background: #000;
+ padding-bottom: 8px;
+ border: 1px solid #111;
+ width: 148px;
+ height: 155px;
+ z-index: 100;
+}
+#color-picker .north {
+ background: #111;
+ border-bottom: 1px solid #171717;
+ font-size: 11px;
+}
+#color-picker .north div {
+ color: #999;
+ float: right;
+ padding: 5px 7px;
+ cursor: pointer;
+ -moz-user-select: none;
+ -khtml-user-select: none;
+ user-select: none;
+}
+#color-picker .north div:hover {
+ color: #fff;
+}
+#color-picker .south {
+ margin: 32px 0 0 10px;
+ cursor: crosshair;
+ -moz-user-select: none;
+ -khtml-user-select: none;
+ user-select: none;
+}
+#color-picker .south img {
+ height: 100%;
+ width: 100%;
+ position: relative;
+ top: -8px;
+ left: -1px;
+}
+#color-picker #color-picker-cursor {
+ background: url("graphics/color-picker-cursor.gif") no-repeat;
+ position: absolute;
+ height: 9px;
+ width: 9px;
+ z-index: 101;
+}
+#color-picker #color-picker-cursor img {
+ height: 100%;
+ width: 100%;
+ position: relative;
+ top: -8px;
+ left: -1px;
+}
+#color-picker #color-picker-hex {
+ padding: 5px 0 4px 7px;
+ cursor: text;
+ float: left;
+}
+#color-picker #color-picker-hex:hover {
+ color: #fff;
+}
+#color-picker #color-picker-resize {
+ float: right;
+ top: -14px;
+ left: 7px;
+ height: 14px;
+ width: 14px;
+ cursor: se-resize;
+}
+#color-picker-palette-src {
+ background-image: url("graphics/color-picker-palette.png");
+}
+#color-picker-resize-src {
+ background-image: url("graphics/color-picker-resize.gif");
+}
+
+.leftAlign {
+ text-align: left;
+}
+.rightAlign {
+ text-align: right;
+}
+.leftFloat {
+ float: left;
+}
+.rightFloat {
+ float: right;
+}
+
+.toggleQuoteHide, .toggleQuoteShow {
+ font-size: 80%;
+ cursor: pointer;
+ background: #ddd;
+}
+.toggleQuoteHide:hover, .toggleQuoteShow:hover {
+ text-decoration: underline;
+}
+.toggleQuoteParent {
+ margin-bottom: 8px;
+}
+
+/* Growler notice styling. */
+#Growler {
+ width: 340px;
+}
+#Growler div.GrowlerNotice {
+ filter: alpha(opacity=80);
+ -moz-opacity: .8;
+ opacity: .8;
+ zoom: 1;
+ width: 300px;
+ padding: 10px 10px 10px 25px;
+ margin: 5px auto;
+ text-align: left;
+ display: none;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ min-height: 20px;
+ border: 1px #316600 solid;
+ background: 3px center #5db110 no-repeat;
+ color: #fff;
+}
+#Growler div.GrowlerNoticeHead {
+ font-weight: bold;
+}
+#Growler div.GrowlerNoticeExit {
+ float: right;
+ font-weight: bold;
+ cursor: pointer;
+}
+#Growler div.horde-error, #GrowlerLog li.horde-error {
+ background-color: #e81222;
+ background-image: url("graphics/alerts/error.png");
+ border-color: maroon;
+}
+#Growler div.horde-message, #GrowlerLog li.horde-message {
+ background-image: url("graphics/alerts/message.png");
+}
+#Growler div.horde-success, #GrowlerLog li.horde-success {
+ background-image: url("graphics/alerts/success.png");
+}
+#Growler div.horde-warning, #GrowlerLog li.horde-warning {
+ background-color: #ebe20c;
+ background-image: url("graphics/alerts/warning.png");
+ border-color: #807b00;
+ color: #000;
+}
+
+#GrowlerLog {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ max-height: 200px;
+ z-index: 10000;
+ overflow-y: auto;
+}
+#GrowlerLog ul {
+ overflow: auto;
+ filter: alpha(opacity=80);
+ -moz-opacity: .8;
+ opacity: .8;
+}
+#GrowlerLog ul li {
+ color: #333;
+ font-size: 12px;
+ list-style-type: none;
+ overflow: hidden;
+ padding: 10px 30px;
+ border-bottom: 1px dotted;
+ background: 3px center #5db110 no-repeat;
+}
+#GrowlerLog ul li:last-child {
+ border: 0;
+}
+#GrowlerLog li.NoAlerts {
+ font-weight: bold;
+ background: #999;
+}
+#GrowlerLog span.alertdate {
+ font-size: 90%;
+ font-style: italic;
+ padding-left: 10px;
+}
+.hordeACBox {
+ background:white none repeat scroll 0 0;
+ border:1px solid #666699;
+ cursor:default;
+ /*overflow:hidden;*/
+ text-align:left;
+ min-height: 58px;
+}
+
+.hordeACList {
+ display:block;
+ overflow:hidden;
+ width:100%;
+ cursor:default;
+ list-style-type:none;
+ margin:0;
+ padding:0;
+}
+
+.hordeACListMember {
+ display:inline-block;
+ font-size:90%;
+ padding:2px 1px 1px 2px;
+ height: 17px;
+ white-space:nowrap;
+}
+
+.hordeACListItem {
+ background-color:lightblue;
+ border:1px solid #C0C0C0;
+ -moz-border-radius-bottomleft:4px;
+ -moz-border-radius-bottomright:4px;
+ -moz-border-radius-topleft:4px;
+ -moz-border-radius-topright:4px;
+ margin:5px;
+}
+
+.hordeACTrigger, .hordeACTrigger:focus {
+ background:transparent none repeat scroll 0 0;
+ border:0 none;
+ display:inline;
+ position:static;
+ width:80px;
+}
+
+/*.hordeACContainer {
+ height:18px;
+ margin:2px;
+ padding:2px 2px 2px 0;
+}*/
+
+.hordeACItemRemove:hover {
+ cursor:pointer;
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Silver Surfer Theme
+ *
+ * Silk icons are from Mark James
+ * (http://www.famfamfam.com/lab/icons/silk/), used under a Creative
+ * Commons Attribution 2.5 License. [
+ * http://creativecommons.org/licenses/by/2.5/ ]. "This means you may
+ * use it for any purpose, and make any changes you like. All I ask
+ * is that you include a link back to this page in your credits."
+ *
+ * Flag icons are from http://www.famfamfam.com/ and are in the public
+ * domain.
+ *
+ * @author Daniel Dembach http://blog.dembachco.de/
+ *
+ * $Horde: horde/themes/silver/info.php,v 1.2 2008/01/10 04:43:12 chuck Exp $
+ */
+
+$theme_name = ("Silver Surfer");
--- /dev/null
+/**
+ * $Horde: horde/themes/silver/screen.css,v 1.35 2009/04/14 03:38:21 slusarz Exp $
+ */
+
+body, input, select, textarea, .inProgress {
+ font-family: Verdana,Geneva,Arial,"Bitstream Vera Sans",Helvetica,sans-serif;
+ color: #333;
+}
+.solidbox {
+ border: 1px solid #999;
+}
+.greybox {
+ border: 1px solid #999;
+}
+.headerbox {
+ border-left: 1px solid #999;
+ border-right: 1px solid #999;
+ border-bottom: 1px solid #999;
+}
+a, a.fixed {
+ color: #366;
+}
+a.widget {
+ color: #366;
+}
+.header, .smallheader {
+ background: #d7d7d7 url("graphics/menu.png") top center repeat-x;
+ border-top: 1px solid #999;
+ border-bottom: 1px solid #999;
+}
+.header {
+ padding: 2px;
+}
+.header a:hover {
+ color: #699;
+}
+.header .smallheader {
+ background: none;
+ border: none;
+}
+.light {
+ color: #666;
+}
+.smallheader {
+ color: #333;
+}
+.smallheader a {
+ color: #333;
+}
+.control {
+ background: #eee;
+}
+.item {
+ background: #eee;
+}
+
+.sortup {
+ background: #ccc url("graphics/za.png") center left no-repeat;
+}
+.sortdown {
+ background: #ccc url("graphics/az.png") center left no-repeat;
+}
+.linedRow, tr.linedRow td, table.linedRow td, ul.linedRow li {
+ color: #333;
+}
+.linedRowSelectedCol, td.linedRowSelectedCol, table.linedRow td.linedRowSelectedCol {
+ color: #333;
+}
+.control {
+ color: #333;
+}
+.item {
+ color: #333;
+}
+.text {
+ color: #333;
+ background: #fff;
+}
+
+/* Form styles. */
+input, select, textarea {
+ color: #000;
+ background: #f3f3f3;
+ border: 1px solid #999;
+}
+input:focus, textarea:focus {
+ background: #fff;
+}
+.button {
+ color: #333;
+ background: #d7d7d7 url("graphics/menu.png") repeat-x 0 -1px;
+ border: 1px solid #999;
+ padding: 1px 2px;
+ font-weight: bold;
+ cursor: pointer;
+}
+.button:hover {
+ color: #699;
+}
+a.button {
+ padding: 2px 4px;
+ font-weight: bold;
+}
+
+/* Alternating styles. item0, item1 are deprecated. */
+.rowEven, .item0 {
+ background-color: #eee;
+}
+.rowOdd, .item1 {
+ background-color: #fff;
+}
+
+.selected {
+ background: #ccc;
+}
+
+/* Various popup and status layers. */
+.notice {
+ color: #333;
+ background: #ffc;
+ border: 1px solid #aaa;
+}
+.tooltip, div.nicetitle {
+ color: #333;
+ background: #ffc;
+ border: 1px solid #333;
+}
+
+/* Menu styles. */
+#menu {
+ background: #d7d7d7 url("graphics/menu.png") repeat-x;
+}
+#menu h1 {
+ color: #333;
+}
+#menu a {
+ border: 1px solid transparent;
+ color: #333;
+ padding: 3px 3px 0 3px;
+ margin: 0;
+}
+#menu a:hover {
+ border: 1px solid transparent;
+ padding: 3px 3px 0 3px;
+ margin: 0;
+}
+#menu a.current {
+ border: 1px solid #aaa;
+ padding: 3px;
+ margin: 0;
+ background: url("graphics/menu-active.png") repeat-x;
+ -moz-border-radius: 0;
+ -webkit-border-radius: 0;
+}
+#menuBottom {
+ position: relative;
+ top: -1px;
+ background: #d7d7d7;
+ border: 1px solid #999;
+ border-right: none;
+ border-top: none;
+ padding-left: 6px;
+ -moz-border-radius-bottomleft: 10px;
+ -webkit-border-bottom-left-radius: 10px;
+}
+
+/* Sidebar styles. */
+#sidebarPanel {
+ background: #efefef;
+ margin-right: .5em;
+ border: 1px solid #999;
+ border-left: none;
+ border-top: none;
+}
+#sidebarPanel span, #sidebarPanel a {
+ color: #333;
+ font-family: Verdana,sans-serif;
+}
+#sidebarPanel a:hover {
+ color: #333;
+}
+#expandButton {
+ margin-right: .5em;
+}
+
+/* Tab styles. */
+.tabset {
+ background: none;
+}
+.tabset li {
+ background: url("graphics/tab_right.png") no-repeat right top;
+ margin-bottom: -1px;
+}
+.tabset li a {
+ color: #366;
+ background: url("graphics/tab_left.png") no-repeat left top;
+ border: 0;
+ border-bottom: 1px solid #999;
+ padding: 4px 0.8em 3px 0.8em;
+}
+.tabset li a:hover {
+ color: #999;
+ background: url("graphics/tab_left.png") no-repeat left top;
+}
+.tabset li.activeTab {
+ background: url("graphics/currentTab_right.png") no-repeat right top;
+}
+.tabset li.activeTab a {
+ color: #366;
+ background: url("graphics/currentTab_left.png") no-repeat left top;
+ border-bottom: 1px solid #999;
+}
+
+/* Preferences overview. */
+.prefsOverview dt a {
+ background: #d7d7d7 url("graphics/menu.png") repeat-x;
+ border: 1px solid #333;
+}
+.prefsOverview dd {
+ color: #333;
+ background: #fff;
+ border-left: 1px solid #333;
+ border-right: 1px solid #333;
+ border-bottom: 1px solid #333;
+}
+
+/* Help styles. */
+.help {
+ color: #333;
+}
+.help #sidebarPanel {
+ border-top: 1px solid #999;
+}
+
+/* Source markup styles. */
+table.lineNumbered {
+ border: 1px solid #333;
+}
+
+/* MIME styles. */
+.download {
+ background-image: url("graphics/download.png");
+}
+
+/* Growler notification styles. */
+#Growler div.horde-error, #GrowlerLog li.horde-error {
+ background-image: url("graphics/alerts/error.png");
+}
+#Growler div.horde-message, #GrowlerLog li.horde-message {
+ background-image: url("graphics/alerts/message.png");
+}
+#Growler div.horde-success, #GrowlerLog li.horde-success {
+ background-image: url("graphics/alerts/success.png");
+}
+#Growler div.horde-warning, #GrowlerLog li.horde-warning {
+ background-image: url("graphics/alerts/warning.png");
+}
--- /dev/null
+/**
+ * $Horde: horde/themes/webkit.css,v 1.2 2009/02/10 03:57:15 slusarz Exp $
+ *
+ * CSS corrections for Webkit.
+ */
+
+.treeRow {
+ overflow: visible;
+ height: 20px;
+}
+
+.treeRow img {
+ vertical-align: middle;
+}
+
+#menu {
+ overflow: visible;
+ height: 50px;
+}
--- /dev/null
+<?php
+/**
+ * Identify the horde base application.
+ */
+require_once dirname(__FILE__) . '/../../koward/config/base.php';
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+/** Configure the Autoloader to handle the "Koward" pattern */
+Horde_Autoloader::addClassPattern('/^Koward_/', 'Koward/');
+
+/** Dispatch the request. */
+try {
+ Koward::dispatch(__FILE__);
+} catch (Exception $e) {
+ // @TODO Make nicer
+ echo '<h1>' . $e->getMessage() . '</h1>';
+ echo '<pre>'; var_dump($e); echo '</pre>';
+}
--- /dev/null
+/*
+ Local variables:
+ buffer-file-coding-system: utf-8
+ End:
+*/
+body {
+ color: black;
+ background-color: #F8FCF8;
+ font-family: verdana,arial,helvetica,sans-serif;
+ font-size: 95%;
+ border: 0;
+ margin: 0;
+}
+a, a:visited {
+ font-family: verdana,arial,helvetica,sans-serif;
+}
+
+a { color: #001155; }
+a:hover { color: #113399; }
+
+#page {
+ background-repeat: no-repeat;
+ background-position: top right;
+}
+
+#topbar {
+ display:block;
+ background-color: #B0BCD0;
+ height: 70px;
+ clear: both;
+}
+#toplogo {
+ display:block;
+ background-image: url(pics/kolab_logo.png);
+ background-color: #B0BCD0;
+ width: 245px;
+ height: 70px;
+ margin-left: 1em;
+ margin-top: 0.4em;
+ float: left;
+}
+#toptitle {
+ display:block;
+ text-align: right;
+ font-size: 200%;
+ padding-right: 1em;
+ padding-top: 0.5em;
+}
+#topuserinfo {
+ display:block;
+ background-color: #B0BCD0;
+ font-size: 80%;
+ padding: 0.1em;
+ border-bottom: solid 1px black;
+ text-align: right;
+}
+#topmenu {
+ background-color: #B0BCD0;
+ font-size: 90%;
+ border-bottom: solid 1px black;
+}
+#submenu {
+ background-color: #EEEEEE;
+ border-bottom: solid 1px black;
+ font-size: 90%;
+}
+
+.topmenuitem {
+ background-color: #B0BCD0;
+ border-right: solid 1px black;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ margin: 0px;
+}
+.topmenuitemselected {
+ background-color: #EEEEEE;
+ border-right: solid 1px black;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ margin: 0px;
+ border-bottom: solid 1px #EEEEEE;
+}
+.submenuitem {
+}
+.submenuitemselected {
+}
+.alphagroupitem {
+}
+.alphagroupitemselected {
+ font-weight:bold
+}
+#logout {
+ color: red;
+}
+#maintitle {
+ font-size: 200%;
+}
+#maincontent {
+ display:block;
+ padding: 1em;
+ margin: 1em;
+}
+#errorcontent {
+ display:block;
+ padding: 0.2em;
+ margin: 1em;
+ text-align: left;
+ color: red;
+ background-color: #EEEEEE;
+ border: solid 1px black;
+}
+#errorheader {
+ display:block;
+ text-align: left;
+ color: black;
+ background-color: #EEEEEE;
+ font-size: 150%;
+}
+#messagecontent {
+ display:block;
+ padding: 0.2em;
+ margin: 1em;
+ text-align: left;
+ color: green;
+ background-color: #EEEEEE;
+ border: solid 1px black;
+}
+#messageheader {
+ display:block;
+ text-align: left;
+ color: black;
+ background-color: #EEEEEE;
+ font-size: 150%;
+}
+.contenttext {
+ margin: 10px;
+}
+.contenttable {
+ width: 100%;
+ background-color: black;
+ border: 0px;
+}
+.contentroweven {
+ background-color: #C0CDE0;
+ margin: 0px;
+}
+.contentrowodd {
+ background-color: #D0DDF0;
+ margin: 0px;
+}
+.contentcell {
+ font-size: 90%;
+ padding: .1em .5em .1em .5em;
+ margin: 0px;
+/* text-align: center; */
+}
+.actioncell {
+ font-size: 90%;
+ padding: .1em .5em .1em .5em;
+ width: 10%;
+ margin: 0px;
+ text-align: center;
+}
+.contentform {
+ /*float: left;*/
+ padding: .1em .5em .1em .5em;
+ background-color: #EEEEEE;
+ border: solid 1px black;
+}
+.contentformtable {
+ font-size: 90%;
+}
+.langcombo {
+ font-size: 80%;
+}
+
+#validators {
+ text-align: right;
+}
+
+th {
+ background-color: #EEEEEE;
+ border: 0px;
+}
+
+.ctrl {
+ background-color: #E0E3E0;
+ border: solid 1px black;
+ padding: .2em .5em .2em .5em;
+}
+
+.required_asterisk {
+ color: red;
+ font-size: 80%;
+ text-align: right;
+}
+
+label {
+ cursor: pointer;
+}
+
+.align_center {
+ text-align: center;
+}
+
+.align_right {
+ text-align: right;
+}
+
+.align_left {
+ text-align: left;
+}
--- /dev/null
+/**
+ * Style for Koward.
+ */
--- /dev/null
+*.php
+*.local.php
--- /dev/null
+<?php
+
+$attributes['givenName'] = array(
+ 'label' => _("First Name"),
+ 'type' => 'text',
+ 'required' => true,
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+);
+$attributes['sn'] = array(
+ 'label' => _("Last Name"),
+ 'type' => 'text',
+ 'required' => true,
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+);
+$attributes['mail'] = array(
+ 'label' => _("Mail address"),
+ 'type' => 'text',
+ 'required' => true,
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+);
+$attributes['uid'] = array(
+ 'label' => _("User ID"),
+ 'type' => 'text',
+ 'required' => true,
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+);
--- /dev/null
+<?php
+/** Tell the registry where our base lives. */
+if (!defined('HORDE_BASE')) {
+ define('HORDE_BASE', dirname(__FILE__) . '/../../horde');
+}
--- /dev/null
+<?php
+
+$conf['koward']['theme'] = 'silver';
--- /dev/null
+<?php
+
+$labels['cn'] = _("Common Name");
+$labels['kolabSalutation'] = _("Salutation");
+$labels['givenName'] = _("First Name");
+$labels['middleNames'] = _("Additional Names");
+$labels['sn'] = _("Last Name");
+$labels['snsuffix'] = _("Name Suffix");
+$labels['personalTitle'] = _("Title");
+$labels['userPassword'] = _("Password");
+$labels['telephoneNumber'] = _("Phone");
+$labels['postOfficeBox'] = _("Post Office Box");
+$labels['street'] = _("Street");
+$labels['title'] = _("Job Title");
+$labels['postalCode'] = _("Postal Code");
+$labels['facsimileTelephoneNumber'] = _("Fax");
+$labels['l'] = _("City");
+$labels['jpegPhoto'] = _("Photo");
+$labels['mail'] = _("Mail Address");
+$labels['mobile'] = _("Mobile Phone");
+$labels['homePhone'] = _("Home Phone");
+$labels['homePostalAddress'] = _("Home Postal Address");
+$labels['labeledURI'] = _("Website");
+$labels['o'] = _("Company");
+$labels['birthName'] = _("Birth Name");
+$labels['kolabMaritalStatus'] = _("Marital Status");
+$labels['dateOfBirth'] = _("Date Of Birth");
+$labels['placeOfBirth'] = _("Place Of Birth");
+$labels['gender'] = _("Gender");
+
--- /dev/null
+<?php
+
+/* $objects['object'] = array( */
+/* 'class' => 'Horde_Kolab_Server_Object', */
+/* 'label' => _("Object"), */
+/* 'list_label' => _("Objects"), */
+/* 'list_attributes' => array( */
+/* 'id' => array( */
+/* 'title' => _("Object id"), */
+/* 'width' => 80, */
+/* 'link_view'=> true, */
+/* ), */
+/* ), */
+/* 'attributes' => array( */
+/* 'override' => true, */
+/* 'fields' => array( */
+/* 'id' => array( */
+/* 'label' => _("Object ID"), */
+/* 'type' => 'text', */
+/* 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255) */
+/* ), */
+/* ), */
+/* ), */
+/* ); */
+
+/* $objects['person'] = array( */
+/* 'class' => 'Horde_Kolab_Server_Object_Person', */
+/* 'label' => _("Person"), */
+/* 'list_label' => _("Persons"), */
+/* 'list_attributes' => array( */
+/* 'cn' => array( */
+/* 'title' => _("Common name"), */
+/* 'width' => 40, */
+/* 'link_view'=> true, */
+/* ), */
+/* 'sn' => array( */
+/* 'title' => _("Last name"), */
+/* 'width' => 40, */
+/* ), */
+/* ), */
+/* 'attributes' => array( */
+/* 'fields' => array( */
+/* 'cn' => array( */
+/* 'required' => false, */
+/* ), */
+/* 'userPassword' => array( */
+/* 'required' => true, */
+/* ), */
+/* ), */
+/* ), */
+/* ); */
+
+/* $objects['organizationalperson'] = array( */
+/* 'class' => 'Horde_Kolab_Server_Object_Organizationalperson', */
+/* 'label' => _("Organizational person"), */
+/* 'list_label' => _("Organizational persons"), */
+/* 'list_attributes' => array( */
+/* 'cn' => array( */
+/* 'title' => _("Common name"), */
+/* 'width' => 40, */
+/* 'link_view'=> true, */
+/* ), */
+/* 'sn' => array( */
+/* 'title' => _("Last name"), */
+/* 'width' => 40, */
+/* ), */
+/* ), */
+/* 'attributes' => array( */
+/* 'fields' => array( */
+/* 'cn' => array( */
+/* 'required' => false, */
+/* ), */
+/* 'userPassword' => array( */
+/* 'required' => true, */
+/* ), */
+/* ), */
+/* ), */
+/* ); */
+
+/* $objects['inetperson'] = array( */
+/* 'class' => 'Horde_Kolab_Server_Object_Inetorgperson', */
+/* 'label' => _("Inet person"), */
+/* 'list_label' => _("Inet persons"), */
+/* 'list_attributes' => array( */
+/* 'cn' => array( */
+/* 'title' => _("Common name"), */
+/* 'width' => 40, */
+/* 'link_view'=> true, */
+/* ), */
+/* 'sn' => array( */
+/* 'title' => _("Last name"), */
+/* 'width' => 40, */
+/* ), */
+/* ), */
+/* 'attributes' => array( */
+/* 'fields' => array( */
+/* 'cn' => array( */
+/* 'required' => false, */
+/* ), */
+/* 'userPassword' => array( */
+/* 'required' => true, */
+/* ), */
+/* ), */
+/* ), */
+/* ); */
+
+/* $objects['user'] = array( */
+/* 'class' => 'Horde_Kolab_Server_Object_Kolab_User', */
+/* 'label' => _("User"), */
+/* 'list_label' => _("Users"), */
+/* 'list_attributes' => array( */
+/* 'sn' => array( */
+/* 'title' => _("Last name"), */
+/* 'width' => 20, */
+/* ), */
+/* 'givenName' => array( */
+/* 'title' => _("First name"), */
+/* 'width' => 20, */
+/* ), */
+/* 'mail' => array( */
+/* 'title' => _("E-mail"), */
+/* 'width' => 20, */
+/* 'link_view'=> true, */
+/* ), */
+/* 'uid' => array( */
+/* 'title' => _("User ID"), */
+/* 'width' => 20, */
+/* ), */
+/* ), */
+/* ); */
+
+/* $objects['admin'] = array( */
+/* 'class' => 'Horde_Kolab_Server_Object_Kolab_Administrator', */
+/* 'label' => _("Administrator"), */
+/* 'list_label' => _("Administrators"), */
+/* 'attributes' => array( */
+/* ), */
+/* ); */
+
+/* $objects['kolabuser'] = array( */
+/* 'class' => 'Horde_Kolab_Server_Object_Kolab_User', */
+/* 'preferred' => true, */
+/* 'label' => _("Kolab user"), */
+/* 'list_label' => _("Kolab users"), */
+/* 'list_attributes' => array( */
+/* 'sn' => array( */
+/* 'title' => _("Last name"), */
+/* 'width' => 20, */
+/* ), */
+/* 'givenName' => array( */
+/* 'title' => _("First name"), */
+/* 'width' => 20, */
+/* ), */
+/* 'mail' => array( */
+/* 'title' => _("E-mail"), */
+/* 'width' => 20, */
+/* 'link_view'=> true, */
+/* ), */
+/* 'uid' => array( */
+/* 'title' => _("User ID"), */
+/* 'width' => 20, */
+/* ), */
+/* ), */
+/* 'attributes' => array( */
+/* 'hide' => array( */
+/* 'objectClass', */
+/* 'seeAlso', */
+/* 'x121Address', */
+/* 'registeredAddress', */
+/* 'destinationIndicator', */
+/* 'preferredDeliveryMethod', */
+/* 'telexNumber', */
+/* 'teletexTerminalIdentifier', */
+/* 'internationaliSDNNumber', */
+/* 'kolabEncryptedPassword', */
+/* 'kolabHomeMTA', */
+/* 'kolabDelegate', */
+/* ), */
+/* 'labels' => array( */
+/* 'mail' => _("Account ID"), */
+/* ), */
+/* 'fields' => array( */
+/* 'kolabSalutation' => array( */
+/* 'type' => 'enum', */
+/* 'params' => array('values' => array(_("Mr.") => _("Mr."), */
+/* _("Mrs.") => _("Mrs.")), */
+/* 'prompt' => true), */
+/* ), */
+/* 'gender' => array( */
+/* 'type' => 'enum', */
+/* 'params' => array('values' => array(_("1") => _("male"), */
+/* _("2") => _("female")), */
+/* 'prompt' => true), */
+/* ), */
+/* 'kolabMaritalStatus' => array( */
+/* 'type' => 'enum', */
+/* 'params' => array('values' => array(_("0") => _("single"), */
+/* _("1") => _("married")), */
+/* 'prompt' => true), */
+/* ), */
+/* 'userPassword' => array( */
+/* 'type' => 'passwordconfirm', */
+/* ), */
+/* ), */
+/* ), */
+/* ); */
+
+if (file_exists(dirname(__FILE__) . '/objects.local.php')) {
+ require_once(dirname(__FILE__) . '/objects.local.php');
+}
--- /dev/null
+<?php
+$order['mail'] = 1;
+$order['kolabSalutation'] = 2;
+$order['givenName'] = 3;
+$order['middleNames'] = 4;
+$order['sn'] = 5;
+$order['snsuffix'] = 6;
+$order['gender'] = 7;
+$order['userPassword'] = 10;
+$order['dateOfBirth'] = 12;
+$order['placeOfBirth'] = 13;
+$order['kolabMaritalStatus'] = 14;
+$order['birthName'] = 15;
+$order['telephoneNumber'] = 30;
+$order['mobile'] = 31;
+$order['facsimileTelephoneNumber'] = 32;
+$order['homePhone'] = 33;
--- /dev/null
+<?php
+
+$mapper->connect('index', array('controller' => 'index'));
+$mapper->connect('index.php', array('controller' => 'index'));
+
+$mapper->connect('check/:action/:id', array('controller' => 'check', 'action' => 'show'));
+$mapper->connect(':controller/:action/:id', array('controller' => 'object'));
+
+// Local route overrides
+if (file_exists(dirname(__FILE__) . '/routes.local.php')) {
+ include dirname(__FILE__) . '/routes.local.php';
+}
--- /dev/null
+<?php
+
+$search = array(
+ 'fields' => array(
+ 'givenName' => array(
+ 'label' => _("First Name"),
+ 'type' => 'text',
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+ ),
+ )
+);
+
+if (file_exists(dirname(__FILE__) . '/search.local.php')) {
+ require_once(dirname(__FILE__) . '/search.local.php');
+}
--- /dev/null
+<?php
+$visible['hide'] = array(
+ 'objectClass',
+ 'id',
+ 'lnfn',
+ 'fnln',
+ 'seeAlso',
+ 'description',
+ 'physicalDeliveryOfficeName',
+ 'internationaliSDNNumber',
+ 'x121Address',
+ 'registeredAddress',
+ 'destinationIndicator',
+ 'preferredDeliveryMethod',
+ 'telexNumber',
+ 'teletexTerminalIdentifier',
+ 'postalAddress',
+ 'ou',
+ 'st',
+ 'manager',
+ 'uid',
+ 'employeeType',
+ 'photo',
+ 'x500uniqueIdentifier',
+ 'secretary',
+ 'userSMIMECertificate',
+ 'employeeNumber',
+ 'initials',
+ 'audio',
+ 'pager',
+ 'businessCategory',
+ 'roomNumber',
+ 'carLicense',
+ 'userCertificate',
+ 'departmentNumber',
+ 'preferredLanguage',
+ 'displayName',
+ 'userPKCS12',
+ 'kolabVacationEndDateTime',
+ 'kolabVacationReactDomain',
+ 'kolabVacationAddress',
+ 'kolabForwardKeepCopy',
+ 'kolabDeleteflag',
+ 'kolabVacationBeginDateTime',
+ 'kolabVacationResendInterval',
+ 'kolabVacationReplyToUCE',
+ 'kolabForwardAddress',
+ 'kolabForwardUCE',
+ 'kolabAllowSMTPFrom',
+ 'unrestrictedMailSize',
+ 'kolabInvitationPolicy',
+ 'kolabFreeBusyFuture',
+ 'calFBURL',
+ 'kolabComment',
+ 'kolabImapServer',
+ 'kolabFreeBusyServer',
+ 'usertype',
+ 'jpegPhoto',
+);
\ No newline at end of file
--- /dev/null
+To complete the installation of Koward for an apache server you need to add a
+small configuration section to your web server configuration:
+
+<IfModule mod_rewrite.c>
+ RewriteEngine On
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^(.*)$ koward.php [QSA,L]
+</IfModule>
+
+This configuration snippet must apply to the "koward/app" directory. The easiest
+option is to add an .htaccess file with the content provided above in that
+directory.