From d960db581653c7f73e6344397fe6c241b7e5f473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Schneider?= Date: Thu, 19 Apr 2012 08:58:52 +0200 Subject: [PATCH] Working on Web admin --- .../Frameworks/Baikal/Model/AddressBook.php | 19 +- .../Frameworks/Baikal/Model/Calendar.php | 22 +- .../Frameworks/Baikal/Model/Config.php | 923 ++++++++++-------- .../Frameworks/Baikal/Model/User.php | 25 +- .../Resources/Templates/Page/index.html | 14 +- .../Frameworks/Formal/Core/Message.php | 6 +- .../Baikal_0.1/Frameworks/Formal/Element.php | 2 + .../Frameworks/Formal/Element/Checkbox.php | 16 +- .../Frameworks/Formal/Element/Listbox.php | 15 +- .../Frameworks/Formal/Element/Text.php | 17 +- .../js/bootstrap-popover.js | 95 ++ .../js/bootstrap-tooltip.js | 270 +++++ Specific/db/baikal.sqlite | Bin 19456 -> 19456 bytes 13 files changed, 987 insertions(+), 437 deletions(-) create mode 100644 CoreVersions/Baikal_0.1/Frameworks/Versions/TwitterBootstrap.2.0.2/js/bootstrap-popover.js create mode 100644 CoreVersions/Baikal_0.1/Frameworks/Versions/TwitterBootstrap.2.0.2/js/bootstrap-tooltip.js diff --git a/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/AddressBook.php b/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/AddressBook.php index d847ff0..d7933cd 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/AddressBook.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/AddressBook.php @@ -71,13 +71,21 @@ class AddressBook extends \Flake\Core\Model\Db { $oMorpho->add(new \Formal\Element\Text(array( "prop" => "uri", "label" => "Address Book token ID", - "validation" => "required,tokenid" + "validation" => "required,tokenid", + "popover" => array( + "title" => "Address Book token ID", + "content" => "The unique identifier for this address book.", + ) ))); $oMorpho->add(new \Formal\Element\Text(array( "prop" => "displayname", "label" => "Display name", - "validation" => "required" + "validation" => "required", + "popover" => array( + "title" => "Display name", + "content" => "This is the name that will be displayed in your CardDAV client.", + ) ))); $oMorpho->add(new \Formal\Element\Text(array( @@ -86,7 +94,12 @@ class AddressBook extends \Flake\Core\Model\Db { "validation" => "required" ))); - if(!$this->floating()) { + if($this->floating()) { + $oMorpho->element("uri")->setOption( + "help", + "Allowed characters are digits, lowercase letters and the dash symbol '-'." + ); + } else { $oMorpho->element("uri")->setOption("readonly", TRUE); } diff --git a/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/Calendar.php b/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/Calendar.php index 51898af..650373d 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/Calendar.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/Calendar.php @@ -113,13 +113,21 @@ class Calendar extends \Flake\Core\Model\Db { $oMorpho->add(new \Formal\Element\Text(array( "prop" => "uri", "label" => "Calendar token ID", - "validation" => "required,tokenid" + "validation" => "required,tokenid", + "popover" => array( + "title" => "Calendar token ID", + "content" => "The unique identifier for this calendar.", + ) ))); $oMorpho->add(new \Formal\Element\Text(array( "prop" => "displayname", "label" => "Display name", - "validation" => "required" + "validation" => "required", + "popover" => array( + "title" => "Display name", + "content" => "This is the name that will be displayed in your CalDAV client.", + ) ))); $oMorpho->add(new \Formal\Element\Text(array( @@ -130,10 +138,16 @@ class Calendar extends \Flake\Core\Model\Db { $oMorpho->add(new \Formal\Element\Checkbox(array( "prop" => "todos", - "label" => "Todos" + "label" => "Todos", + "help" => "If checked, todos will be enabled on this calendar.", ))); - if(!$this->floating()) { + if($this->floating()) { + $oMorpho->element("uri")->setOption( + "help", + "Allowed characters are digits, lowercase letters and the dash symbol '-'." + ); + } else { $oMorpho->element("uri")->setOption("readonly", TRUE); } diff --git a/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/Config.php b/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/Config.php index 5eb5d53..362f8bc 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/Config.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/Config.php @@ -52,7 +52,7 @@ class Config extends \Flake\Core\Model\NoDb { "type" => "integer", ), "BAIKAL_ADMIN_PASSWORDHASH" => array( - "type" => "calculated", + "type" => "string", ) ); @@ -133,6 +133,8 @@ class Config extends \Flake\Core\Model\NoDb { } $aRes[$sConstant] = $sValue; + } elseif($iNbRes === 0) { + throw new \Exception("Baikal\Model\Config->parseConfig(): Unable to find constant '" . $prop . "' in config file"); } } @@ -155,415 +157,12 @@ class Config extends \Flake\Core\Model\NoDb { "prop" => "BAIKAL_TIMEZONE", "label" => "Time zone", "validation" => "required", - "options" => array( - "Africa/Abidjan", - "Africa/Accra", - "Africa/Addis_Ababa", - "Africa/Algiers", - "Africa/Asmara", - "Africa/Bamako", - "Africa/Bangui", - "Africa/Banjul", - "Africa/Bissau", - "Africa/Blantyre", - "Africa/Brazzaville", - "Africa/Bujumbura", - "Africa/Cairo", - "Africa/Casablanca", - "Africa/Ceuta", - "Africa/Conakry", - "Africa/Dakar", - "Africa/Dar_es_Salaam", - "Africa/Djibouti", - "Africa/Douala", - "Africa/El_Aaiun", - "Africa/Freetown", - "Africa/Gaborone", - "Africa/Harare", - "Africa/Johannesburg", - "Africa/Juba", - "Africa/Kampala", - "Africa/Khartoum", - "Africa/Kigali", - "Africa/Kinshasa", - "Africa/Lagos", - "Africa/Libreville", - "Africa/Lome", - "Africa/Luanda", - "Africa/Lubumbashi", - "Africa/Lusaka", - "Africa/Malabo", - "Africa/Maputo", - "Africa/Maseru", - "Africa/Mbabane", - "Africa/Mogadishu", - "Africa/Monrovia", - "Africa/Nairobi", - "Africa/Ndjamena", - "Africa/Niamey", - "Africa/Nouakchott", - "Africa/Ouagadougou", - "Africa/Porto-Novo", - "Africa/Sao_Tome", - "Africa/Tripoli", - "Africa/Tunis", - "Africa/Windhoek", - "America/Adak", - "America/Anchorage", - "America/Anguilla", - "America/Antigua", - "America/Araguaina", - "America/Argentina/Buenos_Aires", - "America/Argentina/Catamarca", - "America/Argentina/Cordoba", - "America/Argentina/Jujuy", - "America/Argentina/La_Rioja", - "America/Argentina/Mendoza", - "America/Argentina/Rio_Gallegos", - "America/Argentina/Salta", - "America/Argentina/San_Juan", - "America/Argentina/San_Luis", - "America/Argentina/Tucuman", - "America/Argentina/Ushuaia", - "America/Aruba", - "America/Asuncion", - "America/Atikokan", - "America/Bahia", - "America/Barbados", - "America/Belem", - "America/Belize", - "America/Blanc-Sablon", - "America/Boa_Vista", - "America/Bogota", - "America/Boise", - "America/Cambridge_Bay", - "America/Campo_Grande", - "America/Cancun", - "America/Caracas", - "America/Cayenne", - "America/Cayman", - "America/Chicago", - "America/Chihuahua", - "America/Costa_Rica", - "America/Cuiaba", - "America/Curacao", - "America/Danmarkshavn", - "America/Dawson", - "America/Dawson_Creek", - "America/Denver", - "America/Detroit", - "America/Dominica", - "America/Edmonton", - "America/Eirunepe", - "America/El_Salvador", - "America/Felipe_Carrillo", - "America/Fortaleza", - "America/Glace_Bay", - "America/Godthab", - "America/Goose_Bay", - "America/Grand_Turk", - "America/Grenada", - "America/Guadeloupe", - "America/Guatemala", - "America/Guayaquil", - "America/Guyana", - "America/Halifax", - "America/Havana", - "America/Hermosillo", - "America/Indiana/Indianapolis", - "America/Indiana/Knox", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Tell_City", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac", - "America/Inuvik", - "America/Iqaluit", - "America/Jamaica", - "America/Juneau", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/La_Paz", - "America/Lima", - "America/Los_Angeles", - "America/Maceio", - "America/Managua", - "America/Manaus", - "America/Marigot", - "America/Martinique", - "America/Matamoros", - "America/Mazatlan", - "America/Menominee", - "America/Merida", - "America/Mexico_City", - "America/Miquelon", - "America/Moncton", - "America/Monterrey", - "America/Montevideo", - "America/Montreal", - "America/Montserrat", - "America/Nassau", - "America/New_York", - "America/Nipigon", - "America/Nome", - "America/Noronha", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Ojinaga", - "America/Panama", - "America/Pangnirtung", - "America/Paramaribo", - "America/Phoenix", - "America/Port-au-Prince", - "America/Porto_Velho", - "America/Port_of_Spain", - "America/Puerto_Rico", - "America/Rainy_River", - "America/Rankin_Inlet", - "America/Recife", - "America/Regina", - "America/Resolute", - "America/Rio_Branco", - "America/Santarem", - "America/Santa_Isabel", - "America/Santiago", - "America/Santo_Domingo", - "America/Sao_Paulo", - "America/Scoresbysund", - "America/Shiprock", - "America/St_Barthelemy", - "America/St_Johns", - "America/St_Kitts", - "America/St_Lucia", - "America/St_Thomas", - "America/St_Vincent", - "America/Swift_Current", - "America/Tegucigalpa", - "America/Thule", - "America/Thunder_Bay", - "America/Tijuana", - "America/Toronto", - "America/Tortola", - "America/Vancouver", - "America/Whitehorse", - "America/Winnipeg", - "America/Yakutat", - "America/Yellowknife", - "Antarctica/Casey", - "Antarctica/Davis", - "Antarctica/DumontDUrville", - "Antarctica/Mawson", - "Antarctica/McMurdo", - "Antarctica/Palmer", - "Antarctica/Rothera", - "Antarctica/South_Pole", - "Antarctica/Syowa", - "Antarctica/Vostok", - "Arctic/Longyearbyen", - "Asia/Aden", - "Asia/Almaty", - "Asia/Amman", - "Asia/Anadyr", - "Asia/Aqtau", - "Asia/Aqtobe", - "Asia/Ashgabat", - "Asia/Baghdad", - "Asia/Bahrain", - "Asia/Baku", - "Asia/Bangkok", - "Asia/Beirut", - "Asia/Bishkek", - "Asia/Brunei", - "Asia/Choibalsan", - "Asia/Chongqing", - "Asia/Colombo", - "Asia/Damascus", - "Asia/Dhaka", - "Asia/Dili", - "Asia/Dubai", - "Asia/Dushanbe", - "Asia/Gaza", - "Asia/Harbin", - "Asia/Hong_Kong", - "Asia/Hovd", - "Asia/Ho_Chi_Minh", - "Asia/Irkutsk", - "Asia/Jakarta", - "Asia/Jayapura", - "Asia/Jerusalem", - "Asia/Kabul", - "Asia/Kamchatka", - "Asia/Karachi", - "Asia/Kashgar", - "Asia/Kathmandu", - "Asia/Kolkata", - "Asia/Krasnoyarsk", - "Asia/Kuala_Lumpur", - "Asia/Kuching", - "Asia/Kuwait", - "Asia/Macau", - "Asia/Magadan", - "Asia/Makassar", - "Asia/Manila", - "Asia/Muscat", - "Asia/Nicosia", - "Asia/Novokuznetsk", - "Asia/Novosibirsk", - "Asia/Omsk", - "Asia/Oral", - "Asia/Phnom_Penh", - "Asia/Pontianak", - "Asia/Pyongyang", - "Asia/Qatar", - "Asia/Qyzylorda", - "Asia/Rangoon", - "Asia/Riyadh", - "Asia/Sakhalin", - "Asia/Samarkand", - "Asia/Seoul", - "Asia/Shanghai", - "Asia/Singapore", - "Asia/Taipei", - "Asia/Tashkent", - "Asia/Tbilisi", - "Asia/Tehran", - "Asia/Thimphu", - "Asia/Tokyo", - "Asia/Ulaanbaatar", - "Asia/Urumqi", - "Asia/Vientiane", - "Asia/Vladivostok", - "Asia/Yakutsk", - "Asia/Yekaterinburg", - "Asia/Yerevan", - "Atlantic/Azores", - "Atlantic/Bermuda", - "Atlantic/Canary", - "Atlantic/Cape_Verde", - "Atlantic/Faroe", - "Atlantic/Madeira", - "Atlantic/Reykjavik", - "Atlantic/South_Georgia", - "Atlantic/Stanley", - "Atlantic/St_Helena", - "Australia/Adelaide", - "Australia/Brisbane", - "Australia/Broken_Hill", - "Australia/Currie", - "Australia/Darwin", - "Australia/Eucla", - "Australia/Hobart", - "Australia/Lindeman", - "Australia/Lord_Howe", - "Australia/Melbourne", - "Australia/Perth", - "Australia/Sydney", - "Europe/Amsterdam", - "Europe/Andorra", - "Europe/Athens", - "Europe/Belgrade", - "Europe/Berlin", - "Europe/Bratislava", - "Europe/Brussels", - "Europe/Bucharest", - "Europe/Budapest", - "Europe/Chisinau", - "Europe/Copenhagen", - "Europe/Dublin", - "Europe/Gibraltar", - "Europe/Guernsey", - "Europe/Helsinki", - "Europe/Isle_of_Man", - "Europe/Istanbul", - "Europe/Jersey", - "Europe/Kaliningrad", - "Europe/Kiev", - "Europe/Lisbon", - "Europe/Ljubljana", - "Europe/London", - "Europe/Luxembourg", - "Europe/Madrid", - "Europe/Malta", - "Europe/Mariehamn", - "Europe/Minsk", - "Europe/Monaco", - "Europe/Moscow", - "Europe/Oslo", - "Europe/Paris", - "Europe/Podgorica", - "Europe/Prague", - "Europe/Riga", - "Europe/Rome", - "Europe/Samara", - "Europe/San_Marino", - "Europe/Sarajevo", - "Europe/Simferopol", - "Europe/Skopje", - "Europe/Sofia", - "Europe/Stockholm", - "Europe/Tallinn", - "Europe/Tirane", - "Europe/Uzhgorod", - "Europe/Vaduz", - "Europe/Vatican", - "Europe/Vienna", - "Europe/Vilnius", - "Europe/Volgograd", - "Europe/Warsaw", - "Europe/Zagreb", - "Europe/Zaporozhye", - "Europe/Zurich", - "Indian/Antananarivo", - "Indian/Chagos", - "Indian/Christmas", - "Indian/Cocos", - "Indian/Comoro", - "Indian/Kerguelen", - "Indian/Mahe", - "Indian/Maldives", - "Indian/Mauritius", - "Indian/Mayotte", - "Indian/Reunion", - "Pacific/Apia", - "Pacific/Auckland", - "Pacific/Chatham", - "Pacific/Easter", - "Pacific/Efate", - "Pacific/Enderbury", - "Pacific/Fakaofo", - "Pacific/Fiji", - "Pacific/Funafuti", - "Pacific/Galapagos", - "Pacific/Gambier", - "Pacific/Guadalcanal", - "Pacific/Guam", - "Pacific/Honolulu", - "Pacific/Johnston", - "Pacific/Kiritimati", - "Pacific/Kosrae", - "Pacific/Kwajalein", - "Pacific/Majuro", - "Pacific/Marquesas", - "Pacific/Midway", - "Pacific/Nauru", - "Pacific/Niue", - "Pacific/Norfolk", - "Pacific/Noumea", - "Pacific/Pago_Pago", - "Pacific/Palau", - "Pacific/Pitcairn", - "Pacific/Ponape", - "Pacific/Port_Moresby", - "Pacific/Rarotonga", - "Pacific/Saipan", - "Pacific/Tahiti", - "Pacific/Tarawa", - "Pacific/Tongatapu", - "Pacific/Truk", - "Pacific/Wake", - "Pacific/Wallis", - ) + "options" => self::timezones(), + "help" => "Time zone of the server", + "popover" => array( + "title" => "Time zone", + "content" => "Time zone of the server", + ), ))); $oMorpho->add(new \Formal\Element\Checkbox(array( @@ -578,7 +177,11 @@ class Config extends \Flake\Core\Model\NoDb { $oMorpho->add(new \Formal\Element\Checkbox(array( "prop" => "BAIKAL_ADMIN_ENABLED", - "label" => "Enable Web Admin" + "label" => "Enable Web Admin", + "popover" => array( + "title" => "Warning !", + "content" => "If disabled, you'll lose access to this very admin interface !", + ), ))); $oMorpho->add(new \Formal\Element\Checkbox(array( @@ -600,10 +203,12 @@ class Config extends \Flake\Core\Model\NoDb { $oMorpho->add(new \Formal\Element\Password(array( "prop" => "BAIKAL_ADMIN_PASSWORDHASH_CONFIRM", - "label" => "Web admin password confirm", + "label" => "Web admin password confirmation", "placeholder" => $sNotice, + "validation" => "sameas:BAIKAL_ADMIN_PASSWORDHASH", ))); - + + return $oMorpho; } @@ -636,23 +241,90 @@ class Config extends \Flake\Core\Model\NoDb { for($k = ($iLines - 1); $k >= 0; $k--) { if(preg_match($sPattern, $aLines[$k])) { - debug($aLines[$k]); + # Found the last matching line + + $sValue = $this->aData[$prop]; + $bCalculated = (isset($this->aConstants[$prop]["type"]["calculated"]) && $this->aConstants[$prop]["type"]["calculated"] === TRUE); + + switch($this->aConstants[$prop]["type"]) { + case "string": { + $sValue = '"' . addcslashes($sValue, "\"\\\0\n\r") . '"'; # Add quotes, and escape " and all string-termination chars + break; + } + case "integer": { + $sValue = intval($sValue); # Cast as integer + break; + } + case "boolean": { + + if(intval($sValue) === 1) { # Note as a BOOLEAN PHP constant + $sValue = "TRUE"; + } else { + $sValue = "FALSE"; + } + + break; + } + default: { + $sValue = '""'; + break; + } + } + + $aLines[$k] = "define(\"" . $prop . "\", " . $sValue . ");"; } } } + + $sLines = implode("\n", $aLines); + + $sSandboxedCode = str_replace(array(""), "", $sLines); + $sRand = (string)rand(); + $sCode = "if(0) {" . $sSandboxedCode . "}; echo '" . $sRand . "';"; + ob_start(); + eval($sCode); + $sRes = ob_get_contents(); + ob_end_clean(); + + if($sRes !== $sRand) { + throw new \Exception("Parse error in new config file. Aborting, nothing has been changed."); + } + + # We asserted that the syntax is OK; + # We now check that all the constants are present, and with the right value + $aNewConfig = $this->parseConfig($sLines); + $aWrittenConfig = $this->aData; + + asort($aNewConfig); + asort($aWrittenConfig); + + if($aNewConfig != $aWrittenConfig) { + throw new \Exception("New config does not correspond to expected config. Aborting, nothing has been changed."); + } + + file_put_contents($this->sConfigFilePath, $sLines); } public function set($sProp, $sValue) { - if($sProp === "BAIKAL_ADMIN_PASSWORDHASH_CONFIRM") { - return; + if($sProp === "BAIKAL_ADMIN_PASSWORDHASH" || $sProp === "BAIKAL_ADMIN_PASSWORDHASH_CONFIRM") { + # Special handling for password and passwordconfirm + + if($sProp === "BAIKAL_ADMIN_PASSWORDHASH" && $sValue !== "") { + parent::set( + "BAIKAL_ADMIN_PASSWORDHASH", + \BaikalAdmin\Core\Auth::hashAdminPassword($sValue) + ); + } + + return $this; } parent::set($sProp, $sValue); } public function get($sProp) { - if($sProp === "BAIKAL_ADMIN_PASSWORDHASH_CONFIRM") { - return "yyyy"; + if($sProp === "BAIKAL_ADMIN_PASSWORDHASH" || $sProp === "BAIKAL_ADMIN_PASSWORDHASH_CONFIRM") { + return ""; } return parent::get($sProp); @@ -661,4 +333,419 @@ class Config extends \Flake\Core\Model\NoDb { public function destroy() { } + + protected static function timezones() { + $aZones = array( + "Africa/Abidjan", + "Africa/Accra", + "Africa/Addis_Ababa", + "Africa/Algiers", + "Africa/Asmara", + "Africa/Bamako", + "Africa/Bangui", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Blantyre", + "Africa/Brazzaville", + "Africa/Bujumbura", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Ceuta", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Douala", + "Africa/El_Aaiun", + "Africa/Freetown", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Kigali", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Lome", + "Africa/Luanda", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Malabo", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Africa/Mogadishu", + "Africa/Monrovia", + "Africa/Nairobi", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Porto-Novo", + "Africa/Sao_Tome", + "Africa/Tripoli", + "Africa/Tunis", + "Africa/Windhoek", + "America/Adak", + "America/Anchorage", + "America/Anguilla", + "America/Antigua", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/Catamarca", + "America/Argentina/Cordoba", + "America/Argentina/Jujuy", + "America/Argentina/La_Rioja", + "America/Argentina/Mendoza", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Aruba", + "America/Asuncion", + "America/Atikokan", + "America/Bahia", + "America/Barbados", + "America/Belem", + "America/Belize", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Bogota", + "America/Boise", + "America/Cambridge_Bay", + "America/Campo_Grande", + "America/Cancun", + "America/Caracas", + "America/Cayenne", + "America/Cayman", + "America/Chicago", + "America/Chihuahua", + "America/Costa_Rica", + "America/Cuiaba", + "America/Curacao", + "America/Danmarkshavn", + "America/Dawson", + "America/Dawson_Creek", + "America/Denver", + "America/Detroit", + "America/Dominica", + "America/Edmonton", + "America/Eirunepe", + "America/El_Salvador", + "America/Felipe_Carrillo", + "America/Fortaleza", + "America/Glace_Bay", + "America/Godthab", + "America/Goose_Bay", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guatemala", + "America/Guayaquil", + "America/Guyana", + "America/Halifax", + "America/Havana", + "America/Hermosillo", + "America/Indiana/Indianapolis", + "America/Indiana/Knox", + "America/Indiana/Marengo", + "America/Indiana/Petersburg", + "America/Indiana/Tell_City", + "America/Indiana/Vevay", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Inuvik", + "America/Iqaluit", + "America/Jamaica", + "America/Juneau", + "America/Kentucky/Louisville", + "America/Kentucky/Monticello", + "America/La_Paz", + "America/Lima", + "America/Los_Angeles", + "America/Maceio", + "America/Managua", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Matamoros", + "America/Mazatlan", + "America/Menominee", + "America/Merida", + "America/Mexico_City", + "America/Miquelon", + "America/Moncton", + "America/Monterrey", + "America/Montevideo", + "America/Montreal", + "America/Montserrat", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Nome", + "America/Noronha", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Ojinaga", + "America/Panama", + "America/Pangnirtung", + "America/Paramaribo", + "America/Phoenix", + "America/Port-au-Prince", + "America/Porto_Velho", + "America/Port_of_Spain", + "America/Puerto_Rico", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Recife", + "America/Regina", + "America/Resolute", + "America/Rio_Branco", + "America/Santarem", + "America/Santa_Isabel", + "America/Santiago", + "America/Santo_Domingo", + "America/Sao_Paulo", + "America/Scoresbysund", + "America/Shiprock", + "America/St_Barthelemy", + "America/St_Johns", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Swift_Current", + "America/Tegucigalpa", + "America/Thule", + "America/Thunder_Bay", + "America/Tijuana", + "America/Toronto", + "America/Tortola", + "America/Vancouver", + "America/Whitehorse", + "America/Winnipeg", + "America/Yakutat", + "America/Yellowknife", + "Antarctica/Casey", + "Antarctica/Davis", + "Antarctica/DumontDUrville", + "Antarctica/Mawson", + "Antarctica/McMurdo", + "Antarctica/Palmer", + "Antarctica/Rothera", + "Antarctica/South_Pole", + "Antarctica/Syowa", + "Antarctica/Vostok", + "Arctic/Longyearbyen", + "Asia/Aden", + "Asia/Almaty", + "Asia/Amman", + "Asia/Anadyr", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Baghdad", + "Asia/Bahrain", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Beirut", + "Asia/Bishkek", + "Asia/Brunei", + "Asia/Choibalsan", + "Asia/Chongqing", + "Asia/Colombo", + "Asia/Damascus", + "Asia/Dhaka", + "Asia/Dili", + "Asia/Dubai", + "Asia/Dushanbe", + "Asia/Gaza", + "Asia/Harbin", + "Asia/Hong_Kong", + "Asia/Hovd", + "Asia/Ho_Chi_Minh", + "Asia/Irkutsk", + "Asia/Jakarta", + "Asia/Jayapura", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Kashgar", + "Asia/Kathmandu", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Kuwait", + "Asia/Macau", + "Asia/Magadan", + "Asia/Makassar", + "Asia/Manila", + "Asia/Muscat", + "Asia/Nicosia", + "Asia/Novokuznetsk", + "Asia/Novosibirsk", + "Asia/Omsk", + "Asia/Oral", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Pyongyang", + "Asia/Qatar", + "Asia/Qyzylorda", + "Asia/Rangoon", + "Asia/Riyadh", + "Asia/Sakhalin", + "Asia/Samarkand", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Thimphu", + "Asia/Tokyo", + "Asia/Ulaanbaatar", + "Asia/Urumqi", + "Asia/Vientiane", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Bermuda", + "Atlantic/Canary", + "Atlantic/Cape_Verde", + "Atlantic/Faroe", + "Atlantic/Madeira", + "Atlantic/Reykjavik", + "Atlantic/South_Georgia", + "Atlantic/Stanley", + "Atlantic/St_Helena", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Broken_Hill", + "Australia/Currie", + "Australia/Darwin", + "Australia/Eucla", + "Australia/Hobart", + "Australia/Lindeman", + "Australia/Lord_Howe", + "Australia/Melbourne", + "Australia/Perth", + "Australia/Sydney", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Athens", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Bratislava", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Chisinau", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Gibraltar", + "Europe/Guernsey", + "Europe/Helsinki", + "Europe/Isle_of_Man", + "Europe/Istanbul", + "Europe/Jersey", + "Europe/Kaliningrad", + "Europe/Kiev", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/Luxembourg", + "Europe/Madrid", + "Europe/Malta", + "Europe/Mariehamn", + "Europe/Minsk", + "Europe/Monaco", + "Europe/Moscow", + "Europe/Oslo", + "Europe/Paris", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/San_Marino", + "Europe/Sarajevo", + "Europe/Simferopol", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Tirane", + "Europe/Uzhgorod", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Europe/Zaporozhye", + "Europe/Zurich", + "Indian/Antananarivo", + "Indian/Chagos", + "Indian/Christmas", + "Indian/Cocos", + "Indian/Comoro", + "Indian/Kerguelen", + "Indian/Mahe", + "Indian/Maldives", + "Indian/Mauritius", + "Indian/Mayotte", + "Indian/Reunion", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Chatham", + "Pacific/Easter", + "Pacific/Efate", + "Pacific/Enderbury", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Funafuti", + "Pacific/Galapagos", + "Pacific/Gambier", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Kiritimati", + "Pacific/Kosrae", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Marquesas", + "Pacific/Midway", + "Pacific/Nauru", + "Pacific/Niue", + "Pacific/Norfolk", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Palau", + "Pacific/Pitcairn", + "Pacific/Ponape", + "Pacific/Port_Moresby", + "Pacific/Rarotonga", + "Pacific/Saipan", + "Pacific/Tahiti", + "Pacific/Tarawa", + "Pacific/Tongatapu", + "Pacific/Truk", + "Pacific/Wake", + "Pacific/Wallis", + ); + + reset($aZones); + return $aZones; + } } \ No newline at end of file diff --git a/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/User.php b/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/User.php index 79c8e12..60b2ad0 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/User.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Baikal/Model/User.php @@ -204,13 +204,21 @@ class User extends \Flake\Core\Model\Db { $oMorpho->add(new \Formal\Element\Text(array( "prop" => "username", "label" => "Username", - "validation" => "required,tokenid,unique" + "validation" => "required,tokenid,unique", + "popover" => array( + "title" => "Username", + "content" => "The login for this user account.
It has to be unique.", + ) ))); $oMorpho->add(new \Formal\Element\Text(array( "prop" => "displayname", "label" => "Display name", - "validation" => "required" + "validation" => "required", + "popover" => array( + "title" => "Display name", + "content" => "This is the name that will be displayed in your CalDAV/CardDAV clients.", + ) ))); $oMorpho->add(new \Formal\Element\Text(array( @@ -231,11 +239,22 @@ class User extends \Flake\Core\Model\Db { ))); if($this->floating()) { + $oMorpho->element("username")->setOption("help", "Allowed characters are digits, lowercase letters and the dash symbol '-'."); $oMorpho->element("password")->setOption("validation", "required"); } else { - $sNotice = "-- Leave empty to keep current password --"; $oMorpho->element("username")->setOption("readonly", true); + + $oMorpho->element("password")->setOption("popover", array( + "title" => "Password", + "content" => "Write something here only if you want to change the user password." + )); + + $oMorpho->element("passwordconfirm")->setOption("popover", array( + "title" => "Confirm password", + "content" => "Write something here only if you want to change the user password." + )); + $oMorpho->element("password")->setOption("placeholder", $sNotice); $oMorpho->element("passwordconfirm")->setOption("placeholder", $sNotice); } diff --git a/CoreVersions/Baikal_0.1/Frameworks/BaikalAdmin/Resources/Templates/Page/index.html b/CoreVersions/Baikal_0.1/Frameworks/BaikalAdmin/Resources/Templates/Page/index.html index e14cbf2..76c90da 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/BaikalAdmin/Resources/Templates/Page/index.html +++ b/CoreVersions/Baikal_0.1/Frameworks/BaikalAdmin/Resources/Templates/Page/index.html @@ -11,7 +11,7 @@ - + + +
@@ -41,6 +44,15 @@ + + + {javascript} \ No newline at end of file diff --git a/CoreVersions/Baikal_0.1/Frameworks/Formal/Core/Message.php b/CoreVersions/Baikal_0.1/Frameworks/Formal/Core/Message.php index 1e7ff24..b8fb35b 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Formal/Core/Message.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Formal/Core/Message.php @@ -32,7 +32,7 @@ class Message { public static function error($sMessage) { $sHtml =<< +

Validation error

{$sMessage}
@@ -42,7 +42,7 @@ HTML; public static function notice($sMessage) { $sHtml =<< +
× {$sMessage}
@@ -52,7 +52,7 @@ HTML; public static function warningConfirmMessage($sHeader, $sDescription, $sActionUrl, $sActionLabel, $sCancelUrl, $sCancelLabel="Cancel") { $sHtml =<< +

{$sHeader}

{$sDescription} diff --git a/CoreVersions/Baikal_0.1/Frameworks/Formal/Element.php b/CoreVersions/Baikal_0.1/Frameworks/Formal/Element.php index 1904e05..090d6d8 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Formal/Element.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Formal/Element.php @@ -33,6 +33,8 @@ abstract class Element { "validation" => "", "error" => FALSE, "placeholder" => "", + "help" => "", + "popover" => "", ); protected $sValue = ""; diff --git a/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Checkbox.php b/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Checkbox.php index ea29cf1..2ed3da8 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Checkbox.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Checkbox.php @@ -43,6 +43,8 @@ class Checkbox extends \Formal\Element { $checked = ($value === TRUE ? " checked=\"checked\" " : ""); $label = $this->option("label"); $prop = $this->option("prop"); + $helpblock = ""; + $popover = ""; if($this->option("readonly") === TRUE) { $inputclass .= " disabled"; @@ -53,12 +55,22 @@ class Checkbox extends \Formal\Element { $groupclass .= " error"; } - + if(($sHelp = trim($this->option("help"))) !== "") { + $helpblock = "

" . $sHelp . "

"; + } + + if(($aPopover = $this->option("popover")) !== "") { + $inputclass .= " popover-hover "; + $popover = " title=\"" . htmlspecialchars($aPopover["title"]) . "\" "; + $popover .= " data-content=\"" . htmlspecialchars($aPopover["content"]) . "\" "; + } + $sHtml =<<
- + + {$helpblock}
HTML; diff --git a/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Listbox.php b/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Listbox.php index 1e4abb0..db41b0a 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Listbox.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Listbox.php @@ -37,6 +37,8 @@ class Listbox extends \Formal\Element { $value = $this->value(); $label = $this->option("label"); $prop = $this->option("prop"); + $helpblock = ""; + $popover = ""; if($this->option("readonly") === TRUE) { $inputclass .= " disabled"; @@ -52,6 +54,16 @@ class Listbox extends \Formal\Element { throw new \Exception("\Formal\Element\Listbox->render(): 'options' has to be an array."); } + if(($sHelp = trim($this->option("help"))) !== "") { + $helpblock = "

" . $sHelp . "

"; + } + + if(($aPopover = $this->option("popover")) !== "") { + $inputclass .= " popover-focus "; + $popover = " title=\"" . htmlspecialchars($aPopover["title"]) . "\" "; + $popover .= " data-content=\"" . htmlspecialchars($aPopover["content"]) . "\" "; + } + $clientvalue = htmlspecialchars($value); $aRenderedOptions = array(); @@ -80,9 +92,10 @@ class Listbox extends \Formal\Element {
- {$sRenderedOptions} + {$helpblock}
HTML; diff --git a/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Text.php b/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Text.php index cc3dc36..2009c8b 100644 --- a/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Text.php +++ b/CoreVersions/Baikal_0.1/Frameworks/Formal/Element/Text.php @@ -41,7 +41,9 @@ class Text extends \Formal\Element { $value = $this->value(); $label = $this->option("label"); $prop = $this->option("prop"); - $placeholder = $this->option("placeholder"); + $placeholder = ""; + $helpblock = ""; + $popover = ""; if($this->option("readonly") === TRUE) { $inputclass .= " disabled"; @@ -60,11 +62,22 @@ class Text extends \Formal\Element { $sInputType = $this->inputtype(); + if(($sHelp = trim($this->option("help"))) !== "") { + $helpblock = "

" . $sHelp . "

"; + } + + if(($aPopover = $this->option("popover")) !== "") { + $inputclass .= " popover-focus "; + $popover = " title=\"" . htmlspecialchars($aPopover["title"]) . "\" "; + $popover .= " data-content=\"" . htmlspecialchars($aPopover["content"]) . "\" "; + } + $sHtml =<<
- + + {$helpblock}
HTML; diff --git a/CoreVersions/Baikal_0.1/Frameworks/Versions/TwitterBootstrap.2.0.2/js/bootstrap-popover.js b/CoreVersions/Baikal_0.1/Frameworks/Versions/TwitterBootstrap.2.0.2/js/bootstrap-popover.js new file mode 100644 index 0000000..e1aa5ac --- /dev/null +++ b/CoreVersions/Baikal_0.1/Frameworks/Versions/TwitterBootstrap.2.0.2/js/bootstrap-popover.js @@ -0,0 +1,95 @@ +/* =========================================================== + * bootstrap-popover.js v2.0.2 + * http://twitter.github.com/bootstrap/javascript.html#popovers + * =========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================================================== */ + + +!function( $ ) { + + "use strict" + + var Popover = function ( element, options ) { + this.init('popover', element, options) + } + + /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js + ========================================== */ + + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, { + + constructor: Popover + + , setContent: function () { + var $tip = this.tip() + , title = this.getTitle() + , content = this.getContent() + + $tip.find('.popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title) + $tip.find('.popover-content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content) + + $tip.removeClass('fade top bottom left right in') + } + + , hasContent: function () { + return this.getTitle() || this.getContent() + } + + , getContent: function () { + var content + , $e = this.$element + , o = this.options + + content = $e.attr('data-content') + || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) + + content = content.toString().replace(/(^\s*|\s*$)/, "") + + return content + } + + , tip: function() { + if (!this.$tip) { + this.$tip = $(this.options.template) + } + return this.$tip + } + + }) + + + /* POPOVER PLUGIN DEFINITION + * ======================= */ + + $.fn.popover = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('popover') + , options = typeof option == 'object' && option + if (!data) $this.data('popover', (data = new Popover(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.popover.Constructor = Popover + + $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, { + placement: 'right' + , content: '' + , template: '

' + }) + +}( window.jQuery ); \ No newline at end of file diff --git a/CoreVersions/Baikal_0.1/Frameworks/Versions/TwitterBootstrap.2.0.2/js/bootstrap-tooltip.js b/CoreVersions/Baikal_0.1/Frameworks/Versions/TwitterBootstrap.2.0.2/js/bootstrap-tooltip.js new file mode 100644 index 0000000..49b5f72 --- /dev/null +++ b/CoreVersions/Baikal_0.1/Frameworks/Versions/TwitterBootstrap.2.0.2/js/bootstrap-tooltip.js @@ -0,0 +1,270 @@ +/* =========================================================== + * bootstrap-tooltip.js v2.0.2 + * http://twitter.github.com/bootstrap/javascript.html#tooltips + * Inspired by the original jQuery.tipsy by Jason Frame + * =========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + +!function( $ ) { + + "use strict" + + /* TOOLTIP PUBLIC CLASS DEFINITION + * =============================== */ + + var Tooltip = function ( element, options ) { + this.init('tooltip', element, options) + } + + Tooltip.prototype = { + + constructor: Tooltip + + , init: function ( type, element, options ) { + var eventIn + , eventOut + + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.enabled = true + + if (this.options.trigger != 'manual') { + eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' + eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' + this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this)) + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + , getOptions: function ( options ) { + options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay + , hide: options.delay + } + } + + return options + } + + , enter: function ( e ) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (!self.options.delay || !self.options.delay.show) { + self.show() + } else { + self.hoverState = 'in' + setTimeout(function() { + if (self.hoverState == 'in') { + self.show() + } + }, self.options.delay.show) + } + } + + , leave: function ( e ) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (!self.options.delay || !self.options.delay.hide) { + self.hide() + } else { + self.hoverState = 'out' + setTimeout(function() { + if (self.hoverState == 'out') { + self.hide() + } + }, self.options.delay.hide) + } + } + + , show: function () { + var $tip + , inside + , pos + , actualWidth + , actualHeight + , placement + , tp + + if (this.hasContent() && this.enabled) { + $tip = this.tip() + this.setContent() + + if (this.options.animation) { + $tip.addClass('fade') + } + + placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + inside = /in/.test(placement) + + $tip + .remove() + .css({ top: 0, left: 0, display: 'block' }) + .appendTo(inside ? this.$element : document.body) + + pos = this.getPosition(inside) + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + switch (inside ? placement.split(' ')[1] : placement) { + case 'bottom': + tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'top': + tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'left': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} + break + case 'right': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} + break + } + + $tip + .css(tp) + .addClass(placement) + .addClass('in') + } + } + + , setContent: function () { + var $tip = this.tip() + $tip.find('.tooltip-inner').html(this.getTitle()) + $tip.removeClass('fade in top bottom left right') + } + + , hide: function () { + var that = this + , $tip = this.tip() + + $tip.removeClass('in') + + function removeWithAnimation() { + var timeout = setTimeout(function () { + $tip.off($.support.transition.end).remove() + }, 500) + + $tip.one($.support.transition.end, function () { + clearTimeout(timeout) + $tip.remove() + }) + } + + $.support.transition && this.$tip.hasClass('fade') ? + removeWithAnimation() : + $tip.remove() + } + + , fixTitle: function () { + var $e = this.$element + if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') + } + } + + , hasContent: function () { + return this.getTitle() + } + + , getPosition: function (inside) { + return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { + width: this.$element[0].offsetWidth + , height: this.$element[0].offsetHeight + }) + } + + , getTitle: function () { + var title + , $e = this.$element + , o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + title = (title || '').toString().replace(/(^\s*|\s*$)/, "") + + return title + } + + , tip: function () { + return this.$tip = this.$tip || $(this.options.template) + } + + , validate: function () { + if (!this.$element[0].parentNode) { + this.hide() + this.$element = null + this.options = null + } + } + + , enable: function () { + this.enabled = true + } + + , disable: function () { + this.enabled = false + } + + , toggleEnabled: function () { + this.enabled = !this.enabled + } + + , toggle: function () { + this[this.tip().hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* TOOLTIP PLUGIN DEFINITION + * ========================= */ + + $.fn.tooltip = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('tooltip') + , options = typeof option == 'object' && option + if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.tooltip.Constructor = Tooltip + + $.fn.tooltip.defaults = { + animation: true + , delay: 0 + , selector: false + , placement: 'top' + , trigger: 'hover' + , title: '' + , template: '
' + } + +}( window.jQuery ); \ No newline at end of file diff --git a/Specific/db/baikal.sqlite b/Specific/db/baikal.sqlite index 9306d1aab195d50e083f9e16c09c1f48a9cf8114..9c2ce5ab171e45267e7703c90ccb3f667009fb00 100755 GIT binary patch delta 417 zcmZpe!Pqc^ae_3X#zYxsMvaXL%b3}`7?@Wwdu?pAW0r_zVrS4cl}_a?D9X%B&MZjG zDb_DZEiRdSnB7F!C9}97C$Ul?Pdza+H&p>7zIi2kGzS+G;{pc84~z?##WyxiVwCY? z;%3m+m1flC<>ggHH%LH8T$a%#H7&6;r$iw+F()-IC9x>XHO$p7L?zRX?{xMx)TFR8cx=Pz%V&pU2gMFC2mGBHfC8SW?AL~%u|`)Fh?^RL*T~7>r9hBs!e19Ds55E5D{k9 zW<;}seUkQ ukeHfklx&ikYLUpr{FVWz)8sX?02c!oa4?H9f^;%%X0%`v*v#hfix~hQwRSTA delta 253 zcmZpe!Pqc^ae_3X@Fn(apWES7p_>hs2Y4Zm`5k4_irYnrh`b{Sm5Wu;a(Sl82VgTD_c8{OT0GTjD#Q*>R