From 774d10dc8c9df32d8d32a07378dcfcc25ae5a55a Mon Sep 17 00:00:00 2001 From: Shadez Date: Sat, 19 Mar 2011 20:53:01 +0800 Subject: [PATCH] [488] Simple admin panel. At this moment access to this panel has only server administrators (GMLevel 3). --- 3DViewer_info.txt | 6 +- admin/index.php | 128 + admin/template/content_account_edit.php | 76 + admin/template/content_accounts_list.php | 84 + admin/template/content_configuration.php | 14 + .../content_configuration_addrealm.php | 49 + admin/template/content_configuration_edit.php | 140 + admin/template/content_index.php | 38 + admin/template/content_news.php | 88 + admin/template/content_news_redirect.php | 14 + admin/template/css/960.css | 1 + admin/template/css/blue.css | 611 +++++ admin/template/css/iefix.css | 20 + admin/template/css/login.css | 115 + admin/template/css/reset.css | 1 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes admin/template/css/smoothness/ui.css | 395 +++ admin/template/css/text.css | 1 + admin/template/images/arrow_mini_down.gif | Bin 0 -> 79 bytes admin/template/images/bg.gif | Bin 0 -> 401 bytes admin/template/images/bg_content.gif | Bin 0 -> 161 bytes admin/template/images/bg_content_bottom.gif | Bin 0 -> 476 bytes admin/template/images/bg_header_blue.gif | Bin 0 -> 4145 bytes admin/template/images/bg_login.gif | Bin 0 -> 1140 bytes admin/template/images/bg_usertools_left.gif | Bin 0 -> 87 bytes admin/template/images/bg_usertools_right.gif | Bin 0 -> 87 bytes admin/template/images/bullet_blue.gif | Bin 0 -> 282 bytes admin/template/images/bullet_green.gif | Bin 0 -> 282 bytes admin/template/images/bullet_red.gif | Bin 0 -> 282 bytes admin/template/images/but_left_blue.gif | Bin 0 -> 807 bytes admin/template/images/but_left_grey.gif | Bin 0 -> 609 bytes admin/template/images/but_login_left.gif | Bin 0 -> 346 bytes admin/template/images/but_login_span.gif | Bin 0 -> 1070 bytes admin/template/images/but_right_blue.gif | Bin 0 -> 2219 bytes admin/template/images/but_right_grey.gif | Bin 0 -> 2290 bytes admin/template/images/but_round_del_blue.gif | Bin 0 -> 1736 bytes admin/template/images/but_round_left_grey.gif | Bin 0 -> 874 bytes admin/template/images/but_round_ok_blue.gif | Bin 0 -> 1758 bytes admin/template/images/but_round_span_blue.gif | Bin 0 -> 2200 bytes admin/template/images/but_round_span_grey.gif | Bin 0 -> 1830 bytes admin/template/images/forgot_bg_left.gif | Bin 0 -> 337 bytes admin/template/images/forgot_bg_span.gif | Bin 0 -> 481 bytes admin/template/images/icon_clock.png | Bin 0 -> 4817 bytes admin/template/images/icon_content_small.gif | Bin 0 -> 1294 bytes admin/template/images/icon_dashboard.png | Bin 0 -> 4628 bytes .../template/images/icon_dashboard_small.gif | Bin 0 -> 1310 bytes admin/template/images/icon_database.png | Bin 0 -> 4348 bytes admin/template/images/icon_edit.png | Bin 0 -> 4175 bytes admin/template/images/icon_error.gif | Bin 0 -> 1162 bytes admin/template/images/icon_help.png | Bin 0 -> 4492 bytes admin/template/images/icon_info.gif | Bin 0 -> 1160 bytes admin/template/images/icon_mail_small.gif | Bin 0 -> 138 bytes admin/template/images/icon_media.png | Bin 0 -> 4498 bytes admin/template/images/icon_news.png | Bin 0 -> 4237 bytes admin/template/images/icon_reports.png | Bin 0 -> 3639 bytes admin/template/images/icon_settings.png | Bin 0 -> 5126 bytes admin/template/images/icon_success.gif | Bin 0 -> 1176 bytes admin/template/images/icon_updates.png | Bin 0 -> 3781 bytes admin/template/images/icon_users.png | Bin 0 -> 3597 bytes admin/template/images/icon_warning.gif | Bin 0 -> 1139 bytes admin/template/images/icons/action_check.gif | Bin 0 -> 138 bytes admin/template/images/icons/action_delete.gif | Bin 0 -> 145 bytes admin/template/images/icons/action_remove.gif | Bin 0 -> 74 bytes admin/template/images/icons/calendar.gif | Bin 0 -> 1037 bytes admin/template/images/icons/chart_bar.gif | Bin 0 -> 1015 bytes admin/template/images/icons/comments.gif | Bin 0 -> 612 bytes admin/template/images/icons/edit.gif | Bin 0 -> 197 bytes admin/template/images/icons/exclamation.gif | Bin 0 -> 1013 bytes admin/template/images/icons/feed.gif | Bin 0 -> 1082 bytes admin/template/images/icons/lightbulb.gif | Bin 0 -> 1022 bytes admin/template/images/icons/lightbulb_off.gif | Bin 0 -> 616 bytes admin/template/images/icons/user.gif | Bin 0 -> 1001 bytes .../template/images/informationbar_right.gif | Bin 0 -> 551 bytes .../images/navigation_background_blue.gif | Bin 0 -> 583 bytes .../template/images/navigation_first_blue.gif | Bin 0 -> 4866 bytes .../template/images/navigation_last_blue.gif | Bin 0 -> 4867 bytes admin/template/images/tabs_bg.gif | Bin 0 -> 46 bytes admin/template/images/tabs_left.gif | Bin 0 -> 559 bytes admin/template/images/tabs_right.gif | Bin 0 -> 230 bytes admin/template/js/blend/jquery.blend.js | 133 + admin/template/js/effects.js | 118 + admin/template/js/flot/excanvas.pack.js | 1 + admin/template/js/flot/jquery.flot.pack.js | 2396 +++++++++++++++++ admin/template/js/graphs.js | 77 + admin/template/js/jquery.min.js | 19 + admin/template/js/pngfix.js | 208 ++ admin/template/js/ui.core.js | 519 ++++ admin/template/js/ui.datepicker.js | 1630 +++++++++++ admin/template/js/ui.dialog.js | 671 +++++ admin/template/js/ui.sortable.js | 1019 +++++++ admin/template/js/wysiwyg/jquery.wysiwyg.css | 57 + admin/template/js/wysiwyg/jquery.wysiwyg.gif | Bin 0 -> 4478 bytes admin/template/js/wysiwyg/jquery.wysiwyg.js | 652 +++++ admin/template/page_index.php | 267 ++ admin/template/page_login.php | 47 + includes/armory_loader.php | 73 +- includes/classes/class.admin.php | 462 ++++ includes/classes/class.armory.php | 58 +- includes/classes/class.dbhandler.php | 2 +- includes/classes/class.debug.php | 7 +- includes/classes/class.template.php | 109 + includes/classes/class.utils.php | 99 +- includes/revision_nr.php | 2 +- 115 files changed, 10345 insertions(+), 62 deletions(-) create mode 100644 admin/index.php create mode 100644 admin/template/content_account_edit.php create mode 100644 admin/template/content_accounts_list.php create mode 100644 admin/template/content_configuration.php create mode 100644 admin/template/content_configuration_addrealm.php create mode 100644 admin/template/content_configuration_edit.php create mode 100644 admin/template/content_index.php create mode 100644 admin/template/content_news.php create mode 100644 admin/template/content_news_redirect.php create mode 100644 admin/template/css/960.css create mode 100644 admin/template/css/blue.css create mode 100644 admin/template/css/iefix.css create mode 100644 admin/template/css/login.css create mode 100644 admin/template/css/reset.css create mode 100644 admin/template/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 admin/template/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 admin/template/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 admin/template/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 admin/template/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 admin/template/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 admin/template/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 admin/template/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 admin/template/css/smoothness/images/ui-icons_222222_256x240.png create mode 100644 admin/template/css/smoothness/images/ui-icons_2e83ff_256x240.png create mode 100644 admin/template/css/smoothness/images/ui-icons_454545_256x240.png create mode 100644 admin/template/css/smoothness/images/ui-icons_888888_256x240.png create mode 100644 admin/template/css/smoothness/images/ui-icons_cd0a0a_256x240.png create mode 100644 admin/template/css/smoothness/ui.css create mode 100644 admin/template/css/text.css create mode 100644 admin/template/images/arrow_mini_down.gif create mode 100644 admin/template/images/bg.gif create mode 100644 admin/template/images/bg_content.gif create mode 100644 admin/template/images/bg_content_bottom.gif create mode 100644 admin/template/images/bg_header_blue.gif create mode 100644 admin/template/images/bg_login.gif create mode 100644 admin/template/images/bg_usertools_left.gif create mode 100644 admin/template/images/bg_usertools_right.gif create mode 100644 admin/template/images/bullet_blue.gif create mode 100644 admin/template/images/bullet_green.gif create mode 100644 admin/template/images/bullet_red.gif create mode 100644 admin/template/images/but_left_blue.gif create mode 100644 admin/template/images/but_left_grey.gif create mode 100644 admin/template/images/but_login_left.gif create mode 100644 admin/template/images/but_login_span.gif create mode 100644 admin/template/images/but_right_blue.gif create mode 100644 admin/template/images/but_right_grey.gif create mode 100644 admin/template/images/but_round_del_blue.gif create mode 100644 admin/template/images/but_round_left_grey.gif create mode 100644 admin/template/images/but_round_ok_blue.gif create mode 100644 admin/template/images/but_round_span_blue.gif create mode 100644 admin/template/images/but_round_span_grey.gif create mode 100644 admin/template/images/forgot_bg_left.gif create mode 100644 admin/template/images/forgot_bg_span.gif create mode 100644 admin/template/images/icon_clock.png create mode 100644 admin/template/images/icon_content_small.gif create mode 100644 admin/template/images/icon_dashboard.png create mode 100644 admin/template/images/icon_dashboard_small.gif create mode 100644 admin/template/images/icon_database.png create mode 100644 admin/template/images/icon_edit.png create mode 100644 admin/template/images/icon_error.gif create mode 100644 admin/template/images/icon_help.png create mode 100644 admin/template/images/icon_info.gif create mode 100644 admin/template/images/icon_mail_small.gif create mode 100644 admin/template/images/icon_media.png create mode 100644 admin/template/images/icon_news.png create mode 100644 admin/template/images/icon_reports.png create mode 100644 admin/template/images/icon_settings.png create mode 100644 admin/template/images/icon_success.gif create mode 100644 admin/template/images/icon_updates.png create mode 100644 admin/template/images/icon_users.png create mode 100644 admin/template/images/icon_warning.gif create mode 100644 admin/template/images/icons/action_check.gif create mode 100644 admin/template/images/icons/action_delete.gif create mode 100644 admin/template/images/icons/action_remove.gif create mode 100644 admin/template/images/icons/calendar.gif create mode 100644 admin/template/images/icons/chart_bar.gif create mode 100644 admin/template/images/icons/comments.gif create mode 100644 admin/template/images/icons/edit.gif create mode 100644 admin/template/images/icons/exclamation.gif create mode 100644 admin/template/images/icons/feed.gif create mode 100644 admin/template/images/icons/lightbulb.gif create mode 100644 admin/template/images/icons/lightbulb_off.gif create mode 100644 admin/template/images/icons/user.gif create mode 100644 admin/template/images/informationbar_right.gif create mode 100644 admin/template/images/navigation_background_blue.gif create mode 100644 admin/template/images/navigation_first_blue.gif create mode 100644 admin/template/images/navigation_last_blue.gif create mode 100644 admin/template/images/tabs_bg.gif create mode 100644 admin/template/images/tabs_left.gif create mode 100644 admin/template/images/tabs_right.gif create mode 100644 admin/template/js/blend/jquery.blend.js create mode 100644 admin/template/js/effects.js create mode 100644 admin/template/js/flot/excanvas.pack.js create mode 100644 admin/template/js/flot/jquery.flot.pack.js create mode 100644 admin/template/js/graphs.js create mode 100644 admin/template/js/jquery.min.js create mode 100644 admin/template/js/pngfix.js create mode 100644 admin/template/js/ui.core.js create mode 100644 admin/template/js/ui.datepicker.js create mode 100644 admin/template/js/ui.dialog.js create mode 100644 admin/template/js/ui.sortable.js create mode 100644 admin/template/js/wysiwyg/jquery.wysiwyg.css create mode 100644 admin/template/js/wysiwyg/jquery.wysiwyg.gif create mode 100644 admin/template/js/wysiwyg/jquery.wysiwyg.js create mode 100644 admin/template/page_index.php create mode 100644 admin/template/page_login.php create mode 100644 includes/classes/class.admin.php create mode 100644 includes/classes/class.template.php diff --git a/3DViewer_info.txt b/3DViewer_info.txt index a27fd953d..ca00e0b6f 100644 --- a/3DViewer_info.txt +++ b/3DViewer_info.txt @@ -25,6 +25,8 @@ You can find textures archive on filekeeper.org: http://filekeeper.org/download/browser.php?path=shadez1%2Fwowarmory/ Direct link: http://filekeeper.org/download/shadez1/wowarmory/3dviewer_textures_448.7z +Mirror link (user's server, can't guarantee anything): +http://files.alein.org/wow/armory/ ----------------------- @@ -51,4 +53,6 @@ http://getmangos.com/community/topic/12096/world-of-warcraft-armory/ Архив с текстурами можно найти на filekeeper.org: http://filekeeper.org/download/browser.php?path=shadez1%2Fwowarmory/ Прямая ссылка: -http://filekeeper.org/download/shadez1/wowarmory/3dviewer_textures_448.7z \ No newline at end of file +http://filekeeper.org/download/shadez1/wowarmory/3dviewer_textures_448.7z +Зеркало (пользовательский сервер, гарантий нет): +http://files.alein.org/wow/armory/ \ No newline at end of file diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 000000000..ae954c2d8 --- /dev/null +++ b/admin/index.php @@ -0,0 +1,128 @@ +Fatal error: unable to load system files.'); +} +if(isset($_GET['logout'])) { + Admin::PerformLogout(); + header('Location: .'); + exit; +} +if(isset($_POST['username']) && isset($_POST['password'])) { + $username = $_POST['username']; // No SQL Injection + $password = $_POST['password']; // No SQL Injection + Admin::PerformLogin($username, $password); +} +Template::SetPageData('action', isset($_GET['action']) ? $_GET['action'] : 'index'); +Template::SetPageData('subaction', isset($_GET['subaction']) ? $_GET['subaction'] : null); +switch(Template::GetPageData('action')) { + case 'news': + switch(Template::GetPageData('subaction')) { + case 'edit': + if(isset($_POST['date'])) { + $_POST['id'] = $_POST['newsid']; + Template::SetPageData('news_result', Utils::AddNewsItem($_POST, true)); + } + else { + if(isset($_GET['itemid'])) { + Template::SetPageData('news_item', Utils::GetArmoryNews(false, $_GET['itemid'])); + } + } + break; + case 'add': + if(isset($_POST['date'])) { + $_POST['id'] = $_POST['newsid']; + Template::SetPageData('news_result', Utils::AddNewsItem($_POST)); + } + else { + Template::SetPageData('news_item', Utils::GetArmoryNews(0, 0, true)); + } + break; + } + break; + case 'config': + switch(Template::GetPageData('subaction')) { + case 'edit': + if(isset($_POST['subm'])) { + Admin::UpdateConfigFile($_POST); + header('Location: ?action=config'); + exit; + } + break; + case 'addrealm': + if(isset($_POST['subm'])) { + Admin::AddNewRealm($_POST); + } + break; + } + break; + case 'accounts': + Template::SetPageData('page', isset($_GET['page']) ? (int) $_GET['page'] : 1); + switch(Template::GetPageData('subaction')) { + default: + Template::SetPageData('sortby', isset($_GET['sortby']) ? in_array($_GET['sortby'], array('id', 'username', 'gmlevel')) ? $_GET['sortby'] : 'username' : 'username'); + Template::SetPageData('sorttype', isset($_GET['sorttype']) ? in_array(strtoupper($_GET['sorttype']), array('ASC', 'DESC')) ? $_GET['sorttype'] : 'ASC' : 'ASC'); + if(isset($_POST['searchAccount'])) { + $searchAccount = $_POST['searchAccount']; + } + else { + $searchAccount = null; + } + switch(Template::GetPageData('sortby')) { + case 'username': + case 'gmlevel': + Template::SetPageData('accounts_list', Admin::GetAccountsList(Template::GetPageData('page'), Template::GetPageData('sortby'), Template::GetPageData('sorttype'), $searchAccount)); + break; + } + break; + case 'edit': + Template::SetPageData('accountid', isset($_GET['accountid']) ? $_GET['accountid'] : 0); + if(isset($_POST['subm'])) { + Admin::UpdateAccount($_POST); + } + break; + case 'delete': + if(!isset($_GET['accountid'])) { + $accid = 0; + } + else { + $accid = (int) $_GET['accountid']; + } + Admin::DeleteAccount($accid); + header('Location: ?action=accounts'); + exit; + break; + } + break; +} +if(!Admin::IsLoggedIn()) { + Template::LoadTemplate('page_login'); +} +else { + Template::LoadTemplate('page_index'); +} +?> \ No newline at end of file diff --git a/admin/template/content_account_edit.php b/admin/template/content_account_edit.php new file mode 100644 index 000000000..7fd13441e --- /dev/null +++ b/admin/template/content_account_edit.php @@ -0,0 +1,76 @@ + +
+ +
+

Edit Account

+
+ +
+ Go back + + select("SELECT * FROM `account_access` WHERE `id` = %d", $account['id']); + if(is_array($gmlevels)) { + foreach($gmlevels as $gmlevel) { + $gm_levelInfo .= sprintf('', $gmlevel['RealmID'], $gmlevel['RealmID'], $gmlevel['gmlevel']); + } + } + } + else { + $gm_levelInfo = sprintf('', $account['gmlevel']); + } + echo sprintf('
+ + + + + + + + %s + + + + + + + + Yes + No + + + + +
+
+ +
', $account['id'], + $account['id'], + $account['username'], + $account['sha_pass_hash'], + $gm_levelInfo, + $account['email'], + $account['joindate'], + $account['last_ip'], + $account['locked'] == 1 ? ' checked' : null, + $account['locked'] == 0 ? ' checked' : null, + $account['last_login'], + $account['expansion'] == 2 ? ' selected' : null, + $account['expansion'] == 1 ? ' selected' : null, + $account['expansion'] == 0 ? ' selected' : null); + } + ?> + +

+
+
+ diff --git a/admin/template/content_accounts_list.php b/admin/template/content_accounts_list.php new file mode 100644 index 000000000..c38aedead --- /dev/null +++ b/admin/template/content_accounts_list.php @@ -0,0 +1,84 @@ + +
+
+

Accounts

+
+
+
+
+
+
+
Accounts ListAccounts List
+
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + ', $account['username'], $account['sha_pass_hash'], $account['gmlevel'], $account['email'], $account['last_ip'], $account['last_login'], $account['id'], $account['id']); + } + } + ?> + + + + + + + +
UsernameHashGM LevelE-MailIP AddressLast LoginActions
%s%s%d%s%s%s
+
+
+
+
+
+ diff --git a/admin/template/content_configuration.php b/admin/template/content_configuration.php new file mode 100644 index 000000000..5614d9863 --- /dev/null +++ b/admin/template/content_configuration.php @@ -0,0 +1,14 @@ + +
+ +
+

Configuration

+
+ + +
+ diff --git a/admin/template/content_configuration_addrealm.php b/admin/template/content_configuration_addrealm.php new file mode 100644 index 000000000..05c6aae69 --- /dev/null +++ b/admin/template/content_configuration_addrealm.php @@ -0,0 +1,49 @@ + +
+ +
+

Add Realm

+
+ +
+ Go back +
+ + + + + + +
+
+ + + + + + + + + + +
+ + + + + + + + + + +
+ +
+

+
+
+ diff --git a/admin/template/content_configuration_edit.php b/admin/template/content_configuration_edit.php new file mode 100644 index 000000000..6ecd760ad --- /dev/null +++ b/admin/template/content_configuration_edit.php @@ -0,0 +1,140 @@ + +
+ +
+

Edit Configuration

+
+ +
+ Go back +
+ + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + /> Disabled + /> Enabled + + + + + + /> Disabled + /> Enabled + + + + + + + + + + + + + + + + /> Disabled + /> Enabled + + + + + + /> Yes + /> No + + + /> Enabled + /> Disabled + + + + + + +
+ + Realm #%d + + + + + + + + + + +
+ ', $realm_info['id'], + $realm_info['id'], $realm_info['id'], + $realm_info['id'], $realm_info['name'], + $realm_info['id'], $realm_info['type'] == SERVER_MANGOS ? ' selected' : null, $realm_info['type'] == SERVER_TRINITY ? ' selected' : null, + $realm_info['id'], sprintf('%s;%s;%s;%s;%s', $realm_info['host_characters'], $realm_info['user_characters'], $realm_info['pass_characters'], $realm_info['name_characters'], $realm_info['charset_characters']), + $realm_info['id'], sprintf('%s;%s;%s;%s;%s', $realm_info['host_world'], $realm_info['user_world'], $realm_info['pass_world'], $realm_info['name_world'], $realm_info['charset_world']), + $realm_info['id'], $realm_info['name'] + ); + } + ?> +
+ + +
+

+
+
+ diff --git a/admin/template/content_index.php b/admin/template/content_index.php new file mode 100644 index 000000000..dff139cca --- /dev/null +++ b/admin/template/content_index.php @@ -0,0 +1,38 @@ + +
+
+

Home

+
+
+
+
+
+
+
Reports Visitors - Last 30 days
+
+
+
+
+
+
+
+
NotificationsNotifications
+ +
+ %s

', $notify['type'], $notify['message']); + } + } + else { + echo 'Everything is correct.'; + } + ?> +
+
+
+
+
+ diff --git a/admin/template/content_news.php b/admin/template/content_news.php new file mode 100644 index 000000000..4a91cdb4a --- /dev/null +++ b/admin/template/content_news.php @@ -0,0 +1,88 @@ + +
+ +
+

News Manager

+
+ +
+ ' . $title . ''; + } + else { + echo '

Add New Item
Select Item to Edit:

'; + $armory_news = Utils::GetArmoryNews(true); + if(is_array($armory_news)) { + $count = count($armory_news); + echo '
    '; + for($i = 0; $i < $count; ++$i) { + echo sprintf('
  • %s (%s)
  • ', $armory_news[$i]['id'], $armory_news[$i]['title'], $armory_news[$i]['date']); + } + echo '
'; + } + } + ?> +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Display on main +
+ Submit + Clear + ', $news_item['id'], $news_item['id'], date('d.m.Y H:i:s', $news_item['date']), + $news_item['title_de_de'], $news_item['title_en_gb'], + $news_item['title_es_es'], $news_item['title_fr_fr'], $news_item['title_ru_ru'], + $news_item['text_de_de'], $news_item['text_en_gb'], + $news_item['text_es_es'], $news_item['text_fr_fr'], $news_item['text_ru_ru'], + $news_item['display'] == 1 ? ' checked' : null + ); + } + ?> +
+

+ +
+
+ diff --git a/admin/template/content_news_redirect.php b/admin/template/content_news_redirect.php new file mode 100644 index 000000000..524c34acf --- /dev/null +++ b/admin/template/content_news_redirect.php @@ -0,0 +1,14 @@ + +
+ +
+

News Manager

+
+ +
+

News were successfully updated.

+ Go back +
+
+
+ diff --git a/admin/template/css/960.css b/admin/template/css/960.css new file mode 100644 index 000000000..7618d4842 --- /dev/null +++ b/admin/template/css/960.css @@ -0,0 +1 @@ +.container_12,.container_16{margin-left:auto;margin-right:auto;width:960px}.grid_1,.grid_2,.grid_3,.grid_4,.grid_5,.grid_6,.grid_7,.grid_8,.grid_9,.grid_10,.grid_11,.grid_12,.grid_13,.grid_14,.grid_15,.grid_16{display:inline;float:left;margin-left:10px;margin-right:10px}.container_12 .grid_3,.container_16 .grid_4{width:220px}.container_12 .grid_6,.container_16 .grid_8{width:460px}.container_12 .grid_9,.container_16 .grid_12{width:700px}.container_12 .grid_12,.container_16 .grid_16{width:940px}.alpha{margin-left:0}.omega{margin-right:0}.container_12 .grid_1{width:60px}.container_12 .grid_2{width:140px}.container_12 .grid_4{width:300px}.container_12 .grid_5{width:380px}.container_12 .grid_7{width:540px}.container_12 .grid_8{width:620px}.container_12 .grid_10{width:780px}.container_12 .grid_11{width:860px}.container_16 .grid_1{width:40px}.container_16 .grid_2{width:100px}.container_16 .grid_3{width:160px}.container_16 .grid_5{width:280px}.container_16 .grid_6{width:340px}.container_16 .grid_7{width:400px}.container_16 .grid_9{width:520px}.container_16 .grid_10{width:580px}.container_16 .grid_11{width:640px}.container_16 .grid_13{width:760px}.container_16 .grid_14{width:820px}.container_16 .grid_15{width:880px}.container_12 .prefix_3,.container_16 .prefix_4{padding-left:240px}.container_12 .prefix_6,.container_16 .prefix_8{padding-left:480px}.container_12 .prefix_9,.container_16 .prefix_12{padding-left:720px}.container_12 .prefix_1{padding-left:80px}.container_12 .prefix_2{padding-left:160px}.container_12 .prefix_4{padding-left:320px}.container_12 .prefix_5{padding-left:400px}.container_12 .prefix_7{padding-left:560px}.container_12 .prefix_8{padding-left:640px}.container_12 .prefix_10{padding-left:800px}.container_12 .prefix_11{padding-left:880px}.container_16 .prefix_1{padding-left:60px}.container_16 .prefix_2{padding-left:120px}.container_16 .prefix_3{padding-left:180px}.container_16 .prefix_5{padding-left:300px}.container_16 .prefix_6{padding-left:360px}.container_16 .prefix_7{padding-left:420px}.container_16 .prefix_9{padding-left:540px}.container_16 .prefix_10{padding-left:600px}.container_16 .prefix_11{padding-left:660px}.container_16 .prefix_13{padding-left:780px}.container_16 .prefix_14{padding-left:840px}.container_16 .prefix_15{padding-left:900px}.container_12 .suffix_3,.container_16 .suffix_4{padding-right:240px}.container_12 .suffix_6,.container_16 .suffix_8{padding-right:480px}.container_12 .suffix_9,.container_16 .suffix_12{padding-right:720px}.container_12 .suffix_1{padding-right:80px}.container_12 .suffix_2{padding-right:160px}.container_12 .suffix_4{padding-right:320px}.container_12 .suffix_5{padding-right:400px}.container_12 .suffix_7{padding-right:560px}.container_12 .suffix_8{padding-right:640px}.container_12 .suffix_10{padding-right:800px}.container_12 .suffix_11{padding-right:880px}.container_16 .suffix_1{padding-right:60px}.container_16 .suffix_2{padding-right:120px}.container_16 .suffix_3{padding-right:180px}.container_16 .suffix_5{padding-right:300px}.container_16 .suffix_6{padding-right:360px}.container_16 .suffix_7{padding-right:420px}.container_16 .suffix_9{padding-right:540px}.container_16 .suffix_10{padding-right:600px}.container_16 .suffix_11{padding-right:660px}.container_16 .suffix_13{padding-right:780px}.container_16 .suffix_14{padding-right:840px}.container_16 .suffix_15{padding-right:900px}.clear{clear:both;display:block;overflow:hidden;visibility:hidden;width:0;height:0}.clearfix:after{clear:both;content:' ';display:block;font-size:0;line-height:0;visibility:hidden;width:0;height:0}.clearfix{display:inline-block}* html .clearfix{height:1%}.clearfix{display:block} \ No newline at end of file diff --git a/admin/template/css/blue.css b/admin/template/css/blue.css new file mode 100644 index 000000000..0be6cba26 --- /dev/null +++ b/admin/template/css/blue.css @@ -0,0 +1,611 @@ +body { background:url(../images/bg.gif) repeat-x left top #d4d3d3; font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; font-size: 13px; color: #333; } +a, a:active, a:link, a:visited { text-decoration:none; color: #069; } +a:hover { text-decoration: underline; color: #C00; } +#logo { font-size:24px; font-style:italic; font-weight:normal; color:white; line-height:69px; } +#header { background:url(../images/bg_header_blue.gif) left top no-repeat; height:123px; } +#content { background:url(../images/bg_content.gif) left top repeat-x #FFFFFF; width:938px !important; border-left:1px solid #9c9c9c; border-right:1px solid #9c9c9c; padding: 10px 0px;} +#textcontent { padding:10px !important; width:900px !important; } +#wrapper { padding-bottom:10px !important; background:url(../images/bg_content_bottom.gif) center bottom no-repeat; } +#footer { text-align:center; padding:15px 0px; color: #666; font-size:11px; } +.hidden { display:none; } +.text { padding:10px 15px; } +.nopadding { padding:0px !important; } +.floatLeft { float:left; } +.floatRight { float:right; } +a.edit_icon { background:url(../images/icons/edit.gif) no-repeat left top; display:inline-block; width: 16px; height:16px; } +a.delete_icon { background:url(../images/icons/action_delete.gif) no-repeat left top; display:inline-block; width: 16px; height:16px; } +a.approve_icon { background:url(../images/icons/action_check.gif) no-repeat left top; display:inline-block; width: 16px; height:16px; } +a.reject_icon { background:url(../images/icons/action_remove.gif) no-repeat left top; display:inline-block; width: 16px; height:16px; } +a.edit_inline { background:url(../images/icons/edit.gif) no-repeat left top; display:inline-block; line-height:16px; color: #069 !important; font-size:10px; padding-left:20px; margin-right:5px; } +a.delete_inline { background:url(../images/icons/action_delete.gif) no-repeat left top; display:inline-block; line-height:16px; color: #D23333 !important; font-size:10px; padding-left:20px; margin-right:5px; } +a.reject_inline { background:url(../images/icons/action_remove.gif) no-repeat left top; display:inline-block; line-height:16px; color: #D23333 !important; font-size:10px; padding-left:20px; margin-right:5px; } +a.approve_inline { background:url(../images/icons/action_check.gif) no-repeat left top; display:inline-block; line-height:16px; color: #5a801b !important; font-size:10px; padding-left:20px; margin-right:5px; } +.news_items li { margin-left:15px; } +/******************************************************************************* + HEADING CLASSES +*******************************************************************************/ +h1 { font-size:22px; color: #1b486a; display: block; margin-top: 10px;} +h1.dashboard { background:url(../images/icon_dashboard.png) left 3px no-repeat; padding-left:35px;} +h1.content_edit { background:url(../images/icon_content_small.gif) left 3px no-repeat; padding-left:35px;} +h2 { font-size:18px !important; } +h3 { font-size: 13px !important; } +/******************************************************************************* + EVENTBOX (title -> rightbox) +*******************************************************************************/ +#eventbox { + font-size:11px; + text-align:right; + margin-top: 10px; + line-height:35px; + width: 375px !important; + position:relative; +} +a.inline_calendar { padding-left:21px; background:url(../images/icons/calendar.gif) no-repeat left top; } +a.inline_tip { padding-left:21px; background:url(../images/icons/lightbulb_off.gif) no-repeat left top; } +.hidden_calendar { position:absolute; top:35px; right:20px; width:200px; height:200px; display:none; } +.hidden_calendar { line-height:normal !important;} +.hidden_calendar .ui-datepicker .ui-datepicker-prev span, .hidden_calendar .ui-datepicker .ui-datepicker-next span { + text-indent:-99999px !important; +} +/******************************************************************************* + USER TOOLS +*******************************************************************************/ +#user_tools { + background:url(../images/bg_usertools_right.gif) right top no-repeat; + height:34px; + padding-right:9px; + float:right; +} +#user_tools span { + background:url(../images/bg_usertools_left.gif) left top no-repeat #000000; + height:34px; + padding-left:9px; + line-height: 34px; + font-size:10px; + color: #b0b0b0; + display:block; + float:right; +} +#user_tools a { color: #FFF; text-decoration:none; } +#user_tools a:hover { text-decoration:underline; } +#user_tools a.mail { background: url(../images/icon_mail_small.gif) left 2px no-repeat; padding-left:17px; margin-right:5px; } +#user_tools a.mail:hover { text-decoration:none !important; } +.dropdown { background:url(../images/arrow_mini_down.gif) no-repeat right 3px; padding-right:13px; } +#colorchanger { z-index: 8; display: none; position:absolute; color: white; top:33px; right:35px; border-left:1px solid #333; border-right: 1px solid #333; background:black; width:100px;} +#colorchanger a { padding:5px; border-bottom:1px solid #333; color: #FFF; display: block; font-size: 10px; text-decoration:none; } +#colorchanger a:hover { background: #222; } +#colorchanger span.redtheme { background: url(../images/bullet_red.gif) left 0px no-repeat; padding-left:16px; } +#colorchanger span.bluetheme { background: url(../images/bullet_blue.gif) left 0px no-repeat; padding-left:16px; } +#colorchanger span.greentheme { background: url(../images/bullet_green.gif) left 0px no-repeat; padding-left:16px; } +/******************************************************************************* + MENU +*******************************************************************************/ +#menu { + float: left; +} +#menu ul.group { + margin: 12px 0px 0px 14px; + padding: 0px 0px 0px; + list-style: none; + float: left; + z-index:4; +} +#menu ul.group li { + display: inline; + float: left; + position: static; + z-index: 5; + margin-left:0px !important; +} +#menu ul.group li a { + display: block; + float: left; + height: 100px; + width: 114px; + overflow:hidden; + font-size: 12px; + font-weight: bold; + font-style: italic; + color: white; + text-decoration:none; + text-align:center; + z-index:6; +} +#menu ul.group li a * { + cursor: pointer; +} +#menu ul.group li a span.outer { + display: block; + height: 90px; + padding-top: 10px +} +#menu ul.group li a span.inner { + display: block; + padding: 55px 10px 9px 10px; + white-space: nowrap; + background-repeat: no-repeat; + background-position: 50% 3px; +} +#menu ul.group li a { + background:url('../images/navigation_background_blue.gif') repeat-x top left; +} +#menu ul.group li.first a { + background:url('../images/navigation_first_blue.gif') no-repeat top left; +} +#menu ul.group li.last a { + background:url('../images/navigation_last_blue.gif') no-repeat top right; +} +#menu ul.group li.last a span.inner { + border: none !important; +} + +#menu ul.group li a:hover, #menu ul.group li a.hover { + background-position: bottom left; + text-decoration: none; +} +#menu ul.group li.last a:hover, #menu ul.group li.last a.hover { + background-position: bottom right; +} +#menu ul.group li a.current { + background-position: bottom left; + text-decoration: none; +} +#menu ul.group li.last a.current { + background-position: bottom right; +} +#menu ul.group li.first a.current { + background-position: bottom left; +} + +#menu ul.group li a span.inner { + border-right: 1px solid #4985b2; +} +#menu ul.group li a:hover span.inner { + border-right: 1px solid #4985b2; +} +#menu ul.group li a.more { +} +#menu .additional a span { + border-right:1px solid #DFDCBB; +} +#menu .dashboard { background-image: url(../images/icon_dashboard.png); background-repeat: no-repeat; } +#menu .content { background-image: url(../images/icon_edit.png); background-repeat: no-repeat; } +#menu .reports { background-image: url(../images/icon_reports.png); background-repeat: no-repeat; } +#menu .users { background-image: url(../images/icon_users.png); background-repeat: no-repeat; } +#menu .media_library { background-image: url(../images/icon_media.png); background-repeat: no-repeat; } +#menu .event_manager { background-image: url(../images/icon_clock.png); background-repeat: no-repeat; } +#menu .newsletter { background-image: url(../images/icon_news.png); background-repeat: no-repeat; } +#menu .settings { background-image: url(../images/icon_settings.png); background-repeat: no-repeat; } +#menu .updates { background-image: url(../images/icon_updates.png); background-repeat: no-repeat; } +#menu .help { background-image: url(../images/icon_help.png); background-repeat: no-repeat; } +#menu .database { background-image: url(../images/icon_database.png); background-repeat: no-repeat; } +#hidden_submenu { + background:#FFF; + padding:10px; + display:none; + width:918px !important; + border-left: 1px solid #9C9C9C; + border-right: 1px solid #9C9C9C; + border-bottom: 1px solid #CCC; +} +#hidden_submenu .more_menu { float:left; margin: 10px 5px; } +#hidden_submenu .more_menu li { margin-left: 30px; } +/******************************************************************************* + TABS +*******************************************************************************/ + +#tabs { +} + +#tabs .container { + height: 25px; + padding-top: 8px; + border-left: 1px solid #397cae; + border-right: 1px solid #397cae; + border-bottom: 1px solid #346a92; + width: 938px !important; + background: #eee; +} + +#tabs ul { + margin: 0px 0px 0px 10px; + padding: 0px; + list-style: none; +} + +#tabs ul li { + display: inline; +} + +#tabs ul li a { + font-family:Arial, Helvetica, sans-serif; + display: block; + float: left; + height: 25px; + margin-right: 3px; + font-size: 11px; + font-weight: bold; + overflow: hidden; + border-bottom: 0px; + background: #DEDEDE; + text-decoration:none; + color: #1b486a; +} + +#tabs ul li a:hover { + text-decoration: underline; + background-color: #FFFFFF; +} + +#tabs ul li a span { + height: 20px; + padding: 0px 10px; + display: block; + padding-top: 5px; + cursor: pointer; + white-space: nowrap; +} + +#tabs ul li a.current { + background-color: #FFFFFF; +} +#tabs ul li.first a span { + padding-left: 15px; + padding-right: 15px; +} +#tabs { + background: #639ecb; +} + +#tabs .container { + background:url('../images/tabs_bg.gif') repeat-x left top; + border-bottom: none; +} + +#tabs ul li a { + background: url('../images/tabs_left.gif') no-repeat left top; + border: 0px; +} + +#tabs ul li a span { + background: url('../images/tabs_right.gif') no-repeat right top; +} + +#tabs ul li a.current { + background-position: left bottom; +} + +#tabs ul li a.current span { + background-position: right bottom; +} +#tabs ul li a.tempoff { + background-position: left top; +} + +#tabs ul li a.tempoff span { + background-position: right top; +} + +#tabs ul li.first a{ + color: #1b486a !important; +} +/******************************************************************************* + PORTLETS AND GRID +*******************************************************************************/ +#portlets { padding:0px 10px; } +.column { width: 450px; float: left; padding-bottom: 0px; } +.column#left { margin-right:17px; } +.portlet { margin: 0 0em 1em 0; } +.portlet-header { margin: 0em; padding-bottom: 5px; padding-left: 6px; padding-top:4px; padding-right:6px; font-size:12px; border: none !important; color: #333 !important; font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; cursor:move; } +.portlet-header .ui-icon { float: right; cursor:pointer; } +.portlet-header img { float:left; margin-right:5px; } +#portlets .fixed { cursor:auto; } +.portlet-content { padding: 0.8em; font-size:12px !important; color: #333; border-top:1px solid #999 !important; font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; } +.ui-sortable-placeholder { border: 1px dashed #999 !important; visibility: visible !important; height: 100px !important; background: #EBEBEB;} +.ui-sortable-placeholder * { visibility: hidden; } + +/******************************************************************************* + Informational Messages +*******************************************************************************/ +.info { + display: block; + background: url('../images/informationbar_right.gif') no-repeat right top; + height: 30px; + overflow: hidden; + margin-top: 5px; + margin-bottom:10px !important; + padding: 0px !important; + font-size: 12px !important; + font-weight: bold; + cursor: pointer; + border: 0px; + font-style: italic; +} +.info .info_inner { + display: block; + height: 30px; + padding: 6px 10px 0px 35px; +} +#success .info_inner { + color: #5a801b; + background: url('../images/icon_success.gif') no-repeat left top; + border: 0px; +} +#warning .info_inner { + color: #E89326; + background: url('../images/icon_warning.gif') no-repeat left top; + border: 0px; +} +#error .info_inner { + color: #C00; + background: url('../images/icon_error.gif') no-repeat left top; + border: 0px; +} +#info .info_inner { + color: #4985B2; + background: url('../images/icon_info.gif') no-repeat left top; + border: 0px; +} +/******************************************************************************* + TABLE DESIGN +*******************************************************************************/ +#box-table-a { + font-size: 12px; + margin: 0px; + text-align: left; + border-collapse: separate; + border-bottom:none; +} +#box-table-a th { + font-size: 13px; + font-weight: normal; + padding: 8px; + background: #EFEFEF; + border-top: 1px solid #FFF; + color: #333; + text-align: left; +} +#box-table-a td { + padding: 8px; + background: none; + border-top: 1px solid #CCC; + color: #666; + border-bottom: none !important; +} +#box-table-a tr:hover td { + background: #FBFBFB; + color: #333; +} +#box-table-a tr.footer { background: none !important; } +#box-table-a tr.footer:hover td { background: none !important; } + + +/******************************************************************************* + PAGINATION +*******************************************************************************/ +.pagination { border:0; margin:0; padding:0; font-size:10px; } +.pagination a { border:solid 1px #DEDEDE; margin-right:2px; } +.pagination .previous-off, .pagination .next-off { color:#888888; display:inline-block; font-weight:normal; padding:3px 4px; } +.pagination .next a,.pagination .previous a { font-weight:bold; border:solid 1px #FFFFFF; } +.pagination .active{ color:#000000; font-weight:bold; display:inline-block; padding:4px 6px; } +.pagination a:link, .pagination a:visited { display:inline-block; padding:3px 6px; text-decoration:none; } +.pagination a:hover{ text-decoration:none; border: 1px solid #999; } + +/******************************************************************************* + FORMS +*******************************************************************************/ +form label { display:block !important; line-height:normal !important; margin: 5px 0px; font-size:12px; font-weight:bold; } +input[type=text] { display:block !important; } +textarea { display:block; } +.smallInput { padding:3px 3px; border:1px solid #999; background:#FFFFE6; font-size:12px !important; font-family:"Trebuchet MS", Arial, Helvetica, sans-serif !important; color: #333 !important; font-style:italic; } +.largeInput { padding:6px 5px; border:1px solid #999; background:#FFFFE6; font-size:15px !important; font-family:"Trebuchet MS", Arial, Helvetica, sans-serif !important; color: #333 !important; } +form .small { width:150px; } +form .medium { width:350px; } +form .wide { width:890px; } +.button { + margin: 0px; + padding: 0px !important; + border: 0px; + background: transparent url('../images/but_right_blue.gif') no-repeat scroll top right; + color: #1b486a; + display: block; + float: left; + height: 29px; + margin-right: 6px; + margin-top:10px; + padding-right: 12px !important; + text-decoration: none; + overflow: hidden; + font-size: 12px; + outline: none !important; + cursor: pointer; + font-weight: bold; +} +.button span { + background: url('../images/but_left_blue.gif') no-repeat left top; + display: block; + line-height: 29px; + padding: 0px 0px 0px 12px; + outline: none !important; + float:left; +} +.button:hover { + background-position: right bottom; + text-decoration:none !important +} +.button:hover span { + background-position: left bottom; + color: #1b486a; +} +.button_grey { + margin: 0px; + padding: 0px !important; + border: 0px; + background: transparent url('../images/but_right_grey.gif') no-repeat scroll top right; + color: #555; + display: block; + float: left; + height: 30px; + margin-right: 6px; + margin-top:10px; + padding-right: 12px !important; + text-decoration: none; + overflow: hidden; + font-size: 12px; + outline: none !important; + cursor: pointer; + font-weight: bold; +} +.button_grey span { + background: url('../images/but_left_grey.gif') no-repeat left top; + display: block; + line-height: 30px; + padding: 0px 0px 0px 12px; + outline: none !important; + float:left; +} +.button_grey:hover { + background-position: right bottom; + text-decoration:none !important +} +.button_grey:hover span { + background-position: left bottom; + color: #333; +} +.button_ok { + margin: 0px; + padding: 0px !important; + border: 0px; + background: transparent url('../images/but_round_span_blue.gif') no-repeat scroll top right; + color: #1b486a; + display: block; + float: left; + height: 30px; + margin-right: 6px; + margin-top:10px; + padding-right: 15px !important; + text-decoration: none; + overflow: hidden; + font-size: 12px; + outline: none !important; + cursor: pointer; + font-weight: bold; +} +.button_ok span { + background: url('../images/but_round_ok_blue.gif') no-repeat left top; + display: block; + line-height: 30px; + padding: 0px 0px 0px 35px; + outline: none !important; + float:left; +} +.button_ok:hover { + background-position: right bottom; + text-decoration:none !important +} +.button_ok:hover span { + background-position: left bottom; + color: #1b486a; +} +.button_notok { + margin: 0px; + padding: 0px !important; + border: 0px; + background: transparent url('../images/but_round_span_blue.gif') no-repeat scroll top right; + color: #1b486a; + display: block; + float: left; + height: 30px; + margin-right: 6px; + margin-top:10px; + padding-right: 15px !important; + text-decoration: none; + overflow: hidden; + font-size: 12px; + outline: none !important; + cursor: pointer; + font-weight: bold; +} +.button_notok span { + background: url('../images/but_round_del_blue.gif') no-repeat left top; + display: block; + line-height: 30px; + padding: 0px 0px 0px 35px; + outline: none !important; + float:left; + font-style: italic; +} +.button_notok:hover { + background-position: right bottom; + text-decoration:none !important +} +.button_notok:hover span { + background-position: left bottom; + color: #1b486a; +} +.button_grey_round { + margin: 0px; + padding: 0px !important; + border: 0px; + background: transparent url('../images/but_round_span_grey.gif') no-repeat scroll top right; + color: #555; + display: block; + float: left; + height: 30px; + margin-right: 6px; + margin-top:10px; + padding-right: 12px !important; + text-decoration: none; + overflow: hidden; + font-size: 12px; + outline: none !important; + cursor: pointer; + font-weight: bold; +} +.button_grey_round span { + background: url('../images/but_round_left_grey.gif') no-repeat left top; + display: block; + line-height: 30px; + padding: 0px 0px 0px 12px; + outline: none !important; + float:left; +} +.button_grey_round:hover { + background-position: right bottom; + text-decoration:none !important +} +.button_grey_round:hover span { + background-position: left bottom; + color: #333; +} +/******************************************************************************* + MODAL BOX OVERRIDE +*******************************************************************************/ +.ui-dialog { +padding:0px !important; +border: none 0 !important; +font-size: 12px !important; +font-family: "Trebuchet MS", Arial, Helvetica, sans-serif !important; +} +.ui-dialog .ui-dialog-titlebar { +padding-left:5px !important; +padding-top:3px !important; +padding-bottom:3px !important; +padding-right:5px !important; +position:relative; +border-bottom: none !important; +font-size:13px !important; +} +.ui-dialog .ui-corner-all { +-moz-border-radius-bottomleft:0px !important; +-moz-border-radius-bottomright:0px !important; +-moz-border-radius-topleft:4px; +-moz-border-radius-topright:4px; +} +.ui-dialog .ui-dialog-content { +border: 1px solid #AAAAAA !important; +} +.ui-widget-overlay { +background:#000 !important; +opacity:0.7 !important; +} diff --git a/admin/template/css/iefix.css b/admin/template/css/iefix.css new file mode 100644 index 000000000..29b1238d3 --- /dev/null +++ b/admin/template/css/iefix.css @@ -0,0 +1,20 @@ +* html #tabs ul li a span { + width: 1px !important; + position:static !important; + } +* html #tabs ul li a.current { + position: relative; + top: 1px; +} +.group { margin-left:6px !important; } +#hidden_submenu { margin-left:5px !important; } +#wrapper { z-index: 0 !important; } +#user_tools { z-index: 1 !important; } +#header { z-index:2 !important; } +#menu { z-index:3 !important; } +.group { z-index:4 !important; } +.item {z-index:5 !important; } +.item span { z-index:6 !important; } +#colorchanger { z-index:7 !important; } +#colorchanger a { z-index:8 !important; } +#colorchanger a span { z-index:9 !important; } \ No newline at end of file diff --git a/admin/template/css/login.css b/admin/template/css/login.css new file mode 100644 index 000000000..12b248b3d --- /dev/null +++ b/admin/template/css/login.css @@ -0,0 +1,115 @@ +body { background:url(../images/bg.gif) repeat-x left top #d4d3d3; font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; font-size: 13px; color: #333; } +a, a:active, a:link, a:visited { text-decoration:none; color: #FFF; } +a:hover { text-decoration: underline; color: #CCC; } +h1 { + font-size:24px; + font-style:italic; + font-weight:normal; + color:white; + line-height:35px; + margin-bottom:0px; + margin-top:80px; + text-align: center; +} +#login { + margin:10px 0px 0px 0px; + border:1px solid #666; + background:url(../images/bg_login.gif) repeat-x left top #f6f5f5; + padding:20px; +} +#forgot { + margin:0px auto 30px auto; + width:235px; + text-align: center; +} +p.tip { + padding-left:20px; + display:block; + background-image: url(../images/icons/lightbulb.gif); + background-repeat: no-repeat; + background-position: 0 0; +} +p.error { + padding-left:20px; + display:block; + background-image: url(../images/icons/exclamation.gif); + background-repeat: no-repeat; + background-position: 0 0; + color: #900; +} +.black_button { + margin: 0px; + padding: 0px !important; + border: 0px; + background: transparent url('../images/but_login_span.gif') no-repeat scroll top right; + color: #FFF; + display:block; + float: right; + width:105px; + height: 30px; + margin-right: 6px; + margin-top:10px; + padding-right: 12px !important; + text-decoration: none; + overflow: hidden; + font-size: 12px; + outline: none !important; + cursor: pointer; + font-weight: bold; +} +.black_button span { + background: url('../images/but_login_left.gif') no-repeat left top; + display: block; + line-height: 30px; + padding: 0px 0px 0px 12px; + outline: none !important; + float:right; +} +.inputText { + padding:7px; + border:1px solid #999; + font-size:16px; + font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; + color: #333; + width:270px; + margin:5px; + background:#FFFFF8; +} +.forgotlink { + margin: 0px; + padding: 0px !important; + border: 0px; + background: transparent url('../images/forgot_bg_span.gif') no-repeat scroll top right; + color: #888 !important; + display:block; + float: left; + height: 30px; + margin-right: 6px; + padding-right: 15px !important; + text-decoration: none; + overflow: hidden; + font-size: 11px; + outline: none !important; + cursor: pointer; + font-weight: bold; +} +.forgotlink:hover { + color: #666 !important; +} +.forgotlink span { + background: url('../images/forgot_bg_left.gif') no-repeat left top; + display: block; + line-height: 25px; + padding: 0px 0px 0px 15px; + outline: none !important; + float:left; + height:30px; +} +#forgotform { + margin:0px auto; + width:280px; + padding:10px; + border:1px solid #666; + background:#CCC; + display:none; +} diff --git a/admin/template/css/reset.css b/admin/template/css/reset.css new file mode 100644 index 000000000..006e11b4d --- /dev/null +++ b/admin/template/css/reset.css @@ -0,0 +1 @@ +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';}:focus{outline:0}ins{text-decoration:none}del{text-decoration:line-through}table{border-collapse:collapse;border-spacing:0} \ No newline at end of file diff --git a/admin/template/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/admin/template/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/admin/template/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/admin/template/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/admin/template/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/admin/template/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/admin/template/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 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 literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/images/ui-icons_2e83ff_256x240.png b/admin/template/css/smoothness/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..45e8928e5284adacea3f9ec07b9b50667d2ac65f GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/images/ui-icons_454545_256x240.png b/admin/template/css/smoothness/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec70d11bfb2f77374dfd00ef61ba0c3647b5a0c GIT binary patch literal 4369 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 k*Kv;w;*%(i9W@fAqs5i2wiq literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/images/ui-icons_888888_256x240.png b/admin/template/css/smoothness/images/ui-icons_888888_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba708c39172a69e069136bd1309c4322c61f571 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/admin/template/css/smoothness/ui.css b/admin/template/css/smoothness/ui.css new file mode 100644 index 000000000..245ff03dd --- /dev/null +++ b/admin/template/css/smoothness/ui.css @@ -0,0 +1,395 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +/*.ui-widget-content a { color: #222222; }*/ +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; outline: none; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; outline: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; } +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion +----------------------------------*/ +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } +.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* Dialog +----------------------------------*/ +.ui-dialog { position: relative; padding: .2em; width: 300px; } +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider +----------------------------------*/ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs +----------------------------------*/ +.ui-tabs { padding: .2em; zoom: 1; } +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } diff --git a/admin/template/css/text.css b/admin/template/css/text.css new file mode 100644 index 000000000..b6fa301aa --- /dev/null +++ b/admin/template/css/text.css @@ -0,0 +1 @@ +body{font:13px/1.5 "Trebuchet MS", Arial, Helvetica, sans-serif}a:focus{outline:1px dotted invert}hr{border:0 #ccc solid;border-top-width:1px;clear:both;height:0}h1{font-size:25px}h2{font-size:23px}h3{font-size:21px}h4{font-size:19px}h5{font-size:17px}h6{font-size:15px}ol{list-style:decimal}ul{list-style:disc}li{margin-left:0px}p,dl,hr,h1,h2,h3,h4,h5,h6,ol,ul,pre,table,address,fieldset{margin-bottom:20px} \ No newline at end of file diff --git a/admin/template/images/arrow_mini_down.gif b/admin/template/images/arrow_mini_down.gif new file mode 100644 index 0000000000000000000000000000000000000000..d00d038524be81363fe9f3303b9980dfd73dc505 GIT binary patch literal 79 zcmZ?wbhEHbO-m_N1ky-MxGF|Ns9CV4(Pug^`_skwFK<1F2=U?s#L2kuXBL$X<1MIy^CNnTt0{{&L7;yjq literal 0 HcmV?d00001 diff --git a/admin/template/images/bg.gif b/admin/template/images/bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..05771c4d8570a149143f5a3b75290dc670d1d028 GIT binary patch literal 401 zcmV;C0dD?BNk%w1VHE&F0ipl^H8nL}US8DG)8^*p0000Q8X5oq00000A^8LV00000 zEC2ui02Kg30RRL4NV?qqFv?g8sn_DItN&mqj$>wWXGgAVo4#l(&mi2{bk5qm?vuS6 z=STDeaYf=WmMkuXO(ioJ^*vKn-F29yZB^abHxm|5&t)@|n%<$2ZQz?3UybYTH5y-< zL-`_ifPsEkgCBy2h=p8=dXHp|kb9Dem5gAHmYSH6oRfc-poX7clB0B@rmC2yn~JZ8 zv4gXKwS2dDxplj7y=}i~!DYi?#a+i)$yLiy%}viq(N3MG)tRu@uG*}q*3(kno<0EO z=I7|?0qgAT?(gvN^7Hid_V@Vt`uqI-{{H|23LHqVpuvL(6DnNDupz+#5F<*QNU@^D zix@L%+{m$3qsNaRLy8oJq5$&6_xL>fFh*r_Y~2eF_*# vw5ZXeNRujE%CxD|r%<{)Q+3L` literal 0 HcmV?d00001 diff --git a/admin/template/images/bg_content.gif b/admin/template/images/bg_content.gif new file mode 100644 index 0000000000000000000000000000000000000000..9f934df337f47bbe0acbc0e5fa07c203f3e1771a GIT binary patch literal 161 zcmZ?wbhEHbWMSCGu$h73>e;hDe*F0T`}dzefBydc`|H=QfB*jd{Q2|$|NjiwfZ|UU zu&@q@1ew9W;wNy@bM;<}*JpSCPtfR_mpD&t;ks83_N`MmUzB+N+rsx&516Mk6nN-} vRi0R4)R}EH-)vTi*VKdSZmj7(`nD=`#fAzUwVCH%Y^ge%xBLDx4hCxgV>?Rs literal 0 HcmV?d00001 diff --git a/admin/template/images/bg_content_bottom.gif b/admin/template/images/bg_content_bottom.gif new file mode 100644 index 0000000000000000000000000000000000000000..c7ed667b4f59d31fb98fd4d467f6ac952c19d594 GIT binary patch literal 476 zcmZ?wbhEHbT*J)8aFv1K%H_-Z_wPS;?AWQ}$Jei4KX2Z=J9q9pfBt;$-n}0_e7JJy z($}wFU%!6+=g*&g`}XbLwd=~oiyPLjKX>}{>eZ_+oj-r&%9X2EuUsg$wWAy?gQe`CU79+`D&g7H6vvTvzmbz5?t-t;L$DX?L?|=VqXl!cs<`kA=Yw7Cl>Fw*E zFmcl4DN}pdw3r#E&6zuI{(^;z7B5-a&nV8I!oFyx;dB+i`Sl4KRV@%YKpXU|`}bQ5D`zWZK4 zkVA&&)wl0Ie*XI1!XwY2;Il`1g~K6cCT$_Dm=hZo9&Q&<_L}3danaFk3FE9gCpIoV m-ml=?CF8ki$;rtY!K-3UZd!VJx+}buIc3*oa9r!RA1O<$Q91x28>U{ zi%%s>|0`L-h!>0c3q^J z{EKgHKfKmd_h>W|+Bm^}9M^&D((rP|*U^JIJ_;5>R~vSO@A>&0965F-md|)m=>DhR+j4%>E4{&TGEdJj`chy1cKJKDoiI~$`4k9`#< zWdGh0TNV6|F=6{#R#Hn`eOxc+Jr~iF@nNi&JJogfRq0ppBHnaQ`diLF#zh@7;_QX7 z`gn2Y2N`N-<-@qR>*FBy^Dq5i0RPh~!k^CHQE0v^8Xvux^Km3^H!&}Z8*zUBU)9_V*iObg?UiGu?N4(rb9NA=*K z)9K7R;057?h@XL5|rPk4V^&^+N>P5OLE z5R-lH@kya^zASV&Xn}ZXGJT;OqGvCVE}M-D6;ZC=E|RZ#|G4-pHlTg65*D_+Sd|q0 z?Nas4Jxbqh zXn0~?HZ)>ggN=+L?+jxTA%J6SCWfsTTgcJD%dOSP8Ov>y2b^VQUCzofi-8MXVYk*~ zthBS4oD~jFw6enG4+pREgp(Po9e|#*+SzAbS?wBfJ-^0(?fuhQw|v0ol|T`;y4Euh zeSTf|F8QbRUd;pUx@b0MbzQ8(o!hICD|x*;TQ?5~Z=f{Z*6^9!wXKoaVE=9T zx!TO_(I6IYd+dUEZF@X)|KJ{Zz2Zu+9_1H>?Zfm=N1y^{p)15+$wErmxH0uo)Qm z5WBIpHp{-uW_8+Ec;XHFDt{!zu_m0#ayr%lL#Jb-&$8jz9CG`9-}L(Q&-+{Qz^?sm zMfm3a&P2@j2fOcX{d};eN$WZ=&*p9(SakUB53P%}KOfqRtgb`*nt1cjVH)|*|M+5e z>SyPH)zIZU+_!B0Q9%!ei(Bl_5wHpC4r3fSEgy1)n)1DfjH7|EFODHi1t0~(HC+DU zORcWZ-=oPrCidk?nyDxV)^zNa{H3?lR2)id@<@w)1=gBy5Ji(`uKbms-Gq!WeV?MjNGH6VO+6pr4mVtBL##ath|LEElo!`gyxjgBQtx1aNgZ5Pt6k0Z6) zHGrZmBzJWDj(xj!$b%V*zpl6k-l520%!{?7iU-gg>I9K_iFI8W8>XXa6wEO3s4@$^ zL)Uq*AS2gRk7zq}Mi>h^HLA*y?$n!ztjmV$YP5Ez!Kz?gv5cyp+IJf5JZzL(+(ZF* zm*JkkzIu9W0tek~@+xOv3yk}{6uH|BQnI7N$9^ZFcU%0Ax5viBy{V+_wgx4%$Hk)y zYoxnv&d~C9SX$g$ns%27QMSW#$KE#BcUe)#IZ61qcg^5Ec5DLYM(x-;CUmbosho3@ z75AQl+~XjWoMiFX`%d&8_wI2nVkB--K-=S`CvcHdW0NB3UPpF0_qHK!N~+!KL@Bv< zEMrpx_Ps9bao%0Gc+E?&nNLXI-8+qW|2f3mO)lr%4~(B4Lz)E?CGSD___PXb?qMA7 zNRNrvzM+|g?1YYtTjSbEskxV5-jSIWKcm%}MS!v+D|dWm&TbYD9q-J>$Is4#Er5Kl zc8g0x6A%FZ0|_=gR&MW#F6g&K*U+ooCij0w&z^wjvAS!(Gw zm3KWc#DBDFEdy3%*Hg>*$3wei(8ZIFb%W`S_*#eD;rxQr3Y}}D^@SISUla)YbS%~S z5~Ske!WEx9G1gbJf58%BVDl&G*4IJs?$TR|d2gBZw@^|yF%7l=p0N%?RNbUp#e$#1 zIuhk6Amd?+XMJt*Sh%3FRLn9QckCiT=AUnUWoB^a;z+9wEbVe@IFF*?%z zJDDVG4NO>$OSQkDsD#XL1MMz~lyrQFDoIX;+3;yy#dCVIv(XH|&@EXvKN4#!8A6Tpxg+*IJZ zuXAUaJ-k&WT;%>IuL|IGAbhJdb$=eD28P2`TO`c>g8vDLJO;j9N#9=#N|cP~|!RnbbtY!pm7SIpY(i3IcDV13yJ6O-Ikj)z47U|5v21+fPv#2Zs zj)P6?i9VfMqV=Wkp^1>#H~-}i*x|^-EpkQQVql_eEcI}kqVCg&t8FUG;SS?OzcD7! z{)T?I%TDZHxuv#G$`1GV75!^zi4N_|p&3y3Z{(^SbB;sH(1`&PK5>8E*J+g}4s6$| z_w|uZ+eF2{E-Ue1W#OrdMm=B_s}D9XPKWNqpmikiaGUPjHzp3+r__gLne)I@F}QC? zblPW}hgS9Ap+)UHbo?>GAnXwc_9z1Dio&{6u*U$bhX(6u#d?AAPeSsYrx5wxsC*D5 z9}MK5(d7GC^Zg-M&(MN%h=KrAK@g=N7$~@)DG0F^gn|k$LJBV-3d2x^5K18wD7>sG zykaek0u^0_6kS6UMWc#hDMfKWQFPGfaBEQ#sQ3n?_$Hz_8C8s+6eEG++nVA#*5bP$ z+&u{HJ_7dug-fU4G5}nr2A5^UWrOgKAo#}!d=3haqTta0{)q1YEUHAC08%DIl!;Jf0HsU{l=W%KoCDUfArSE;g!mdk97Yl46yg{_RA`7QD{%r; z{svP14pBadD%ViTwLtl-rhLv?t^<+gA*4kFNsl5KDWnyEw5B0#SV<;O#Wtj37g1qG zRahw%cA#QkQ*mgmaPc7@i6E;fF0OfGcPjaqgzPa*_Oy|`e4d?*cy=n~nRnhZ5cL^Y z^6bp?Ge6rif1k>;5tZjsDg*K=gQ%6klFAFyl_9puP@k%c5mlE`s>1TBAk-?Tr0Vi? z)fHP+)Q?r4g;rlnsgBO8j-^(|NvdJf)o@#NlF#!S5zlX?JWtMhj-WnAN}k`IetyUH z{H{;Uy@;CoDK!uBYMklRnhZ%z=5$S#ttQ*2_EALbiLGF|)BR*Uta z6hu&pQYg4Q3V})~l~A(2bs^a(WFKl}1hqPaT9ZemP^mNtwQic)V52g8Xw4C{))X2u zkH)6bI1(Cfn$~Hf@qOrm2)ZzZF3O_=RJv3`@0+F%*yuw(buT08UZ>Oz=hexnbz_n` z#dMv@RyW~O|0bgTT}u5VmF_~W*GlSVr|aiz^*W!1`G|(alm>lXgOS>>B57EgZrHFj zn0y+yBN}&88qIl)R%)YN(zrj}cxY>M0W*$38Ap)}S2V+&#yBQrcxV}(c7_+Y$$1jm zbPCzzjcx+bn!wVgGukFUdy_x7`Dp3q=a9_-=;k0=bFj4eg0?xt-W&>Uxd?5!glq{z zw?JquP-)9$ZOavVOBA^EDzx<)vNamr8cS=9leWUNt#Es561eRKwCyIcEg9X0ptT{T zZMU^;ckFFjkL}cY3G`@bHmLTrWZl)Map__ z&-C7L^xpLq-HR06PZhx*U_|M3QHD&Ed0ymg5@q{}A4Q5Er;2khViaABmWiLth@U#d qSYMzZ5-3Uqa2S9<2TElCaRwkc0J5*7GE!2VDyhLpDt(W-ME)PljDl?d literal 0 HcmV?d00001 diff --git a/admin/template/images/bg_login.gif b/admin/template/images/bg_login.gif new file mode 100644 index 0000000000000000000000000000000000000000..d36be0297f914a1a61460fbb78b9fc7391b080ca GIT binary patch literal 1140 zcmdVX`A?Gv0LJl-Idz~halp`B$Q*LW<~H1LE-ZM!U|QVhWjt}{P6wxlRQz;kzuD&-z40A z%|IYH>~=n%zv^&2TU+DtcmjbyC=}YPR=dq67K?F<#bP#Faa<%4NhA`bQYn>6RVtNS zE|Z;4>WV6|8F4xM+3gQ2-BhPpJ$2|V3uRbB{+0K8x zppaNpTv8fUUUBdKgUYJvnyT~l4UMFxhvepSf48&(l(u%aj?S*`o}N>E{r!Z&A^Pyh z$lkGW#srhOXL{zJSr%*G{KDeXr6qSZhs)!H2}L3gDJYYJpQzMoU!7k6F=8-ynlQ5k z^S9aUK2Db_WPM}9YxBj+truUoxqJFhS|bXN9Spkk2LPNc3G|Dp%K#`(Dttngz{Tnh zODcUM1U}ItN|=n>PB`@+Gc5!&VcFK5fWHi6z0da$4;DH!NejOJ{s;z-|(_FrLqx{8U( zz@w|vC*3@}_W=VsR_Xr66BCn>h+*Meoz=UMajDD<1${bwrPzwpEGU13)u z?WajbzF9hOW4YnI*2lPFEZ68iGcjt@%-lV2D2_SifEH^#QaH?Ur;*q8PE*_@W6ccG zv!Z4vC)RCRR>cSLQ_Sa1R7ktZotoTSw?oS<@zYZ;H#eMS4R?Badz-L3K%2kI8*Itj z>)+K{z(0v<3wa+M(-A%W-c}a*q%V@Q-_1i)f1wuz=(E16%b=9?QoH;zzZpg;71Sr+ z%5R2dr$hJ2=R2SWUt=IxS@uR5c*ry3r{g&>B6ocUX#i@$CCZ2T)6CnjF_a~?LfoESNp5kvGY z|3133xE-bV{tjnER$UL}w;xE#>^|#}cAMAHd^nWXxlP34!`me{ux{5}TjuHBpo%LwOZDM6$!FA0txNxw|GBiWbS?Jtne)#Y>cpV=B=ZBUa iEAz741GUA$)_~@^EbDkfEXB&Od{(eHVc+dWIQ=hwy<(sM literal 0 HcmV?d00001 diff --git a/admin/template/images/bg_usertools_left.gif b/admin/template/images/bg_usertools_left.gif new file mode 100644 index 0000000000000000000000000000000000000000..d92e3733c02cd0d80ab54017ccbd13732cfaac8a GIT binary patch literal 87 zcmZ?wbhEHbdCU$jHdS!NI`5ASETG_>+Z^fq|Vt2gqdr osbyf6$=G%0pT7gc>b(}P&+h)8AR#p23(NTe0|!AFcP0jF06-2B4*&oF literal 0 HcmV?d00001 diff --git a/admin/template/images/bullet_blue.gif b/admin/template/images/bullet_blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c6e4a499d5c743fcaceb300f3857d5cc0c70efb GIT binary patch literal 282 zcmZ?wbhEHb6krfwxT?&+5Zq9A{09TS7(@F71}i@XpW+D@zA^|(HC+13;FiwdSI*#( z!;n3r_T&eKwzCxnpKQGMEAP0uVmmCuQ~Cq_4MbJw|_9u1}OeyVPs%XX3zl{5AqWOoB4r>1s*z5{U??b zowSi-5N?08m_@;A!Z9by4J=Bc{Xxo$Jd7k#8B;iHExa6)4lBgW`mv{OJr5IuH2~;c BOxFMa literal 0 HcmV?d00001 diff --git a/admin/template/images/bullet_green.gif b/admin/template/images/bullet_green.gif new file mode 100644 index 0000000000000000000000000000000000000000..e0f8fb63a703bde3805842e6ec0a821710ab0921 GIT binary patch literal 282 zcmZ?wbhEHb6krfwxT?&c5GyNgDa0ngDq$_mF3cw5FKIf%fQ5^>^;ENbxb)&H3#Xo* zs8g;w^~|L1GhI_JO+E1Nz=T6Roo6~`Uz^S*$h!5;7P%0qxffcR&uY+jD-8#!fW{n%5to`;FS8UQ9H BMalpG literal 0 HcmV?d00001 diff --git a/admin/template/images/bullet_red.gif b/admin/template/images/bullet_red.gif new file mode 100644 index 0000000000000000000000000000000000000000..a677fa9a3255903d15c39e559387ee27726ceb7a GIT binary patch literal 282 zcmZ?wbhEHb6krfwxT?(1z|0`dz#zrQ@S(QWkAbb2k>LU}Lkc(JL}NH z=(%V9|Np=B(#x~ApPsw>GP!?!*}{W`v$ieTf7LX9x_#N4*@qrxOyBKVzdCZ}iTS(E zSywKfwELD@^@5H~7v~;%H2vU%(8&iDpLpUwVSn7*Q`2`{o3Q(~U+a43#trVR8x!W8 znR(!T#LN?klXtE?^Te}ep=;wBpO$rV4nNGCxhJ-N%eKp}mL7Xhy!uMhmYX#ju4ga1 zn7iUq@}l#-yYH5*y_&lCe8I}gt=n!**mJLb(~XQJ7c9${8Rt%87&<`lCkxoIIv^4h zCk*WW8+ds51=U^KJ32dfgmqQ*OnE0wo-&DF+Du7ajBD<^`E$kPj5wAqTfRa@m3jA`z58~%IvqNEEuc;Vuu%NJakuHU$M>$@R#-oAVP#?|ukm#^PGyE6Rx{pas5S34#y84rVmiP9XxS}`3P zI3~0UD0|gJq_iLHmN1UeS+scZ@qPtsF-50MOHNK!>HZUOa?{e&Q(Y@g%<?@boo8_g!4zv6vpdGXwmM2We2Q`Sxt@tmFIUl6voTscm)SYImUD4&#>K_CxVZK7^o@*+Y-(z{xw*Htw%y#^ z@9ys4-`~Eyy@P^+uC1-Syu7`;^N|Z zczDIc#N_1U>gnm!)YReO;qLA2*x1!?)bd^?wk4lfPsEK1%-x(h=o2ojE#4M(W9ivlO`QhNO8gh zm6uU?U{H~zi%l&TD3sYLX2OnsHbB+%phHwnk3C59^bo`pP>)1V5A}dV)lrX2SS$7L z#FbNzQea2*U`19{k6CDA_0Yu@SC3$DfAv5{*I18dc$@XG#+O=;Zh*J-AV*kSk9COC v^^nIHUXOf`?@b^Pu(H1kAQEaeD6<5_&kt38K;a^zX^SBxtU$@SWDo#5=Kx_@ literal 0 HcmV?d00001 diff --git a/admin/template/images/but_login_left.gif b/admin/template/images/but_login_left.gif new file mode 100644 index 0000000000000000000000000000000000000000..0adfac95d45fe6889a070f0ee507a8dbdbcbfa25 GIT binary patch literal 346 zcmZ?wbhEHbWMz8 z$jQlR!GZ;nl9FCtUXG5AQc_ZumX^G{yc`@HA|fKz*49i+OhG|GJUl#ZZf*qy1!7`i z%*@P1MMXkFLgM1$YHDiA%E|@?2D-YsT3TA_>gpyYCW?xRdU|?ta&ig^3Pwgo=H}+6 zrl!Wm#tb9^#h)x-9XcQq5pARr(#G&DCiH#IdiGcz*)00000000000000000000000000000000000 z00000A^8LV00000EC2ui0387y000L6z?yJKEE41ejE#8#Kp$P$jQpf z%+1cv(9zP<)YaD4*xAVqH8bAd;Njxqa3BXsne%Wqe`7hwW`&tShH%~ z%C)Q4uVBN9omwM+*|TWVs$I*rt=qS7(BTJr4xo`~?m@{kM%(=7Y&!9t#9!C>oFt6t5zwdWcFV#}UQySDAy zxO3~?&AYen-@tu z`Sa-0t6$H)z5Dm@`m}aW!rkr-_>8GHED(a}DmTKy$nATvxs;su^>Z`EED(kGY)@tjm zxaO+suDtf@>#xAV`oaY-6l?6U$R?}ovdlK??6c5DEA6z@R%`9G*k-G(vL(cDz_;Lr zEAF`DmTT_0=%%Yn?z-%@>+ZYo#w+i<^p2~+1`r^i@4o!@>+in+2Q2Ww1Q%@Z!3Za; o@WKo??C`_yLyf#tjwWy+FO zMr4GQy;uo^6^0~auq8|hE0aJ%7Sr5o|BCy5_SzCA`_y3%{Uix-M#sh{K2Gwdre|j7=07b67MGS+R)r$5L^@>QaoX#sxv5I6(dxFgcXs#oKkETT z2kjvgWKXi`5to}RN_Ahl`NpF6KdX~IWZ8ZfJI89MWxjK`oM{hjtQ#x@UB}%VY^>*$ zxZh=$w^{TbGW32fof~XI4_EmnA3PS&j2W$k6uR7EH)F@q!LaIh8@}RQYV{^QMcsk++TwZFTik}X`l1kKk24uAwn#@2AbYf~qT;0@4IEJ!x@2Q8*pg}@h6 zZKE-ZY4+Bo#$P$4ftE5Hi{VReK`6{prYlvvl;u7ETF&;EgfHiK3o*;N7q##xOR(|j zl{`P|2P^pyC+v#80Ol!KDGc^My;^i5vlug!qlFJ*{k`8(`w9V5~VQ`+7{B35s5z*P5cw9PFy>w+elv)PJyz zAt(pz6V{YWhjiCXmZMjB%2yyXVUz7jTifKgGhJ0&5B?(+&s#)L4PDf&sfK+`&Z9&5*;z-sNxBbr=0 z8^=7Wn|r~3tebx+BI-W9(#drTNhWSvf)tx4TZ?hd2K`IfUh7-Sd0@Bgm7>rm+pDE9 zq-|k&!uqxdneMhDt}A)6Bf)?xQw#{S^&J_7>9)Jp%zv^gZxxYt*E@9UyBiFXb9;(@ zo2Pq9mh*{r6Hj}=o@xYqZeKkS`gC726+_jdfNKI^wuN}hh+7Ng0ZcgFjI zzc*Ac&*}Hn{HOZ;EfHD&c~7^Y*8_k^fC+?QXs1Xrg&_@XSd0T>8wSd-Bx7et&%toT z8(S{&fETOhaH1mF0a$GchV)t@6e%EB^}$e9uQgqfYQ_EDr`rwwR%!&Zk+A<*n zjzbYfw(e0!`K$p?x-us&yVhO=VfxH8ytR%P@X@lEmv)rzl7Mv%CQ#N7cAG~nOkW== ziZd|rTglJMu5)yT4hDp87L;=9oK&NRryxmsCnT^Q1ctJ&AvTLJuzHu!K?_Szs@1@obZ{=;#O|GTf!ix%HHA}1Bh}@hjOFrRHZB!>f4f|#V4bMWh2=r4>Xh)8?Hi3 zaZ#RMJolS_sd_H}qP>~Wp=StHxfmvb=eAbF(^VCUZ1hDDbU1NFRk`IjWU<{h{OgXY z3SfruH3=AbW2Z*0o{vhmW{;%#sH@F$Fn-PfqnY6ozF>8}zZZKnH&I>dV1|W&1I7v} z#Tj=3umPd$v0}Qq-aQ8kiwU^yc+4W$n}@xUz#gyMQKNm$aKY&a)X6j{1`>q3R>Gb@ z`Dn1gIk+2t`L|!>Pa0g9o`(yeu|JX$HTVcK87|kG)QHd!;6eCsK6{c%*AV0GPg;EG z&!^95NH2N#+d4MCYez$t`$P>M2%PG*(^4{m2vIhisR5tKNU#Uuo^#+dJ6zjX$|FR3 zai)j5)-qxa5#iv#nK6X6852Z|4dsMmj#>On$ss<937nmo(NbG^#3u<~(@vt+X$&(` zTzcT#lAW%V6-0V=D#35{ysm8|hx7s+I4=#?(WiK%HE*QxG0H}}z>NHo8Te@vq3aL_ zkrS~tMpu0lor)atD^cLW&Wx^Wi%0(T1jxwWN019ROi40<2@Jp9VweuxHL~Oi4qVvk TG0&x#rf|FsJ&ONo4!H0?V62^U literal 0 HcmV?d00001 diff --git a/admin/template/images/but_right_grey.gif b/admin/template/images/but_right_grey.gif new file mode 100644 index 0000000000000000000000000000000000000000..748cdbb96e30a65a5f3ce6bf1fc34c35408501ad GIT binary patch literal 2290 zcmdUw`8OK~0>|UFZDca7#Tr%H=_|#kopw?6`eLR-2-<09@zk{Dc%|sI^{}=xo1&R%;rr9)z3=zEZ+Jvl(D|SA79juu z0KnmJlnTWLpDz#yWK!wc+S=6Alv<^lo}SjI)svHxT8(C6V!~)Jn9XJui`7jg%jNR) z)Kn6YD3i(PG@4GUeO^+svb`@^3oEQ%S}y5A$D~E{%`fy9qa$G`~Km7bONw5!$WiP z@}CqG7CkL~hA1h0j(qX5to&6)W!3BIH*ep)uL=F~Ge;1}0gY+G;_%Hat%SDrj?OM3 ziQL`O+t)uZNEsTYjyQxI`@#iun8lu$oSL4Qott0aEPmuJEw8Mu@z(hpn_B{*NX&9_ zJ^J~dlq$7GtJ52dJEq;e{R1<=>W~|hfEvoPKkA)GC)9=<{WA#q7TQ)f`po5Q>N35p zp7z}1+hVtf_J;8?uWQ)E@%9hQO2@yC@IpHp*>8d#N|whv(33TgyhFz#J2BJs&@%5I z8J$hD=qvTBz#}N^JTAT?b%oJ|Ubav)CV*#O5W^ee(um)ODm_r8iq6 zSz(e|*9PHMhux#dgmr4sQJ)(ua@z(C`6cZA+d%ur%&N0#tE}!0;UwzYXYSEGo#I){ zHQWt$PuDhw@C);O^!0~Gck;vSRdz2)u|~-|d_1O)tlFTL`P`i7>(&UT>R~l8{U*7` z+4i)xiT+-Lf=7LJ{PIBGjz%<#yE!?~ziUu#Fl#Ok4*Vt$%@D0k4i1{l09!8}+}bIH z_t^dvhL;Nr5b^TBVP5O`jeosN83cMwlhKf{46Q&U>!QzP$ z363!4y^Zf&NZoEG3$WWQeZ{WUAd0PzlrZ9yCT*ji!b#g%0o&4!sW2Z|=Ui->tZVTW zPDWhLypRsQnC~MeZ&swqyG4ySd5@I1E$>y1`6&9d3u%geqX4HE*wb&H=?>lVP*SX& z)0IQ^o_OUjFi@(bg2R1PBaU(DD)XpIGF~<2mL*luZ0sIT=_f1G)#F}hyqe)llB${h zG+zzt94B4F4ie%u6CnnvW)kwo%^GmY`HprP>e;NFi3*fyXRm~RrJMU9?v8FgKDk-9 zkeDUYagqvu%K)D*zoY+{f^ODx(@8S@(tX-jhUE;-9m7htu-UNs$RIPU!R`ElxS>-? z#`Pl479$@KC^v2(!~J$P%j53uY*i(<>VP_d_(3O}>2or}A-uUkxR-PbQ? zDfSJ#!ZQbE<7Q=Rp9R90CrG{rK=Jy zg@xKUQYf~;%Ew>?%Gwh;bSOcY>%v0W2GWN>Im$c_V6A;PbofZMGT$reC#&N;kS$sH z#2--$OomcjxyphdRxK!tPIWga3n9Qda3OT$gsZ9u8dZ0sk`A}S!>t*BCyr?7sCR;@ zIG$DKM52%SfrhQ>y==f^(6O(pRfv?RdRGp8ETBhKavxFeCWO+0xvJ7^R=vA{PP=GQ zJ%?N8+JCLgyXv@sEQ)G4;XFhl)EiNtaC-5kvu9uOTwiOT_a%qp?>j8FP)nx~5Re;rES^^VkF(Hr~v}#*!HGEjj;)g7C`YX^{)< z)jE7iG%kU|SRjH9+4mRY5`~eR9n~l3+V8mUu7`hI3z$e+k7KdH+graEt&(7C< zJ@&TSkR|wEJz*ai3HtUbHvSgd#v1uAeFw^+IVBv%ovGG$Vxnb3aB$~BkG_jg(wv?Q z`}C@MBKf<&fJerbR!w>m#i8YXA#9oNY9L2g4f86P%YtA-_f$zs1{$^^Nr<}x@pzX> zVy?(@481&u)@&MVRqY3|ABDB%aG0z59z(yfr1g;yc5}gE=#i1#`n!R-c3?6L0zd?~ z9jnid0(fj6L&$Yz@oX;`hrp$T%lV$t0dOMZiOU3`Ads~V`nQql0ctA>-=jEVUOx4T zX)BIn@tt~&qyD9Bh~&Ltr*eo*6|kW+i?!jtYotLy?a0EY%@bwQHu=8ac>n+x{tNK| B(^~)l literal 0 HcmV?d00001 diff --git a/admin/template/images/but_round_del_blue.gif b/admin/template/images/but_round_del_blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..c42bedba349a24332e7e1d346fd02a897494922d GIT binary patch literal 1736 zcmV;(1~>UfNk%w1VIBZH0QUd@T%OFD!r@+@&6&aBV4%)hoy?cO;9{Z9NrJ7l(&?4I z-({oElfK{m{r+K+xM!r$j=SAzrqO++#Q6IBki6b+snh>~fjfDp`uzRwn3#*X-0f{` zmbcJ}xZC`Ge#O`2_<4Erb93WhVCZIMY^TzOw%T&4)N!4^bDzMZ!Pa}P)_Qjxm zx6R*+ugh$p$3K3pOp3T#k-AEVwx7M!X`jbkl)Ztk(r}{4RF%YFmcMPL&{&ebQjEAk zeXC4{vWd3YR+hw2h_s!=;!caWTbjpqsLrd!*;kCTf3em|hP3bW_+OR1x6|o!rpr!< zwP%>UZ=uFlna59#y_&+{QH{D?nZ={T-gBwaoWtR$%H>y*zG9%vUY^W!s?v?{-6s&hYn;UK%6&^AnlJk+Pv<9tc346A8cE&P`lo|;l&4f4pV~0 zxEL`&-MBn(o)8ZnXk!s*D9X+Y z!9T?NfrL=vf)UlIpu!pXp|`<;8~i5_7K5mOKrJx9FvfYajWEItGid1G5tG0`Lpd+J z5XcP}*d~GqLC_Y&ivO)(#tVf!W5SK01Xo=K85B1UkMDUVi3uN=Qo)gY$Yxu2w?V`L z6h~r!fHNeJFvkU@nFdhE~AK9H8g{h_vtnVq55-2q%jwIutmx5TGe0c>sX}7i`q? zMG|1>a7Z7TrmE>n%4i|Ls{#Q3(nJ(x&|`%gQ!D}NuCL;TgfOW9AndTj7F%pt6QqCu zJG?*wNdeGCEA6xeU}g|P4rTigV%H|5?YGEI^zFC|eH79{(0p^tFRQfVE=w;hWXv)( z-IUW#J^d7vPy+ua^K2I*cnHulOnDgErXG9ll@;H7^r&!Og0uDK-(3L? zNRK)PvTYlK4c-Nzg!H_nVqw_TX~?06Wq~LnJ@A-_qKYiK2;)aG(nyaiI3jHvkV#`s zkdQ>ulM9kcRu}X~Pe$2wD^_BOvp`&WNdlPkyhEm$IH$R0oAh84=bUufi6@*F(^KdI zfZAo+pu-<3kPY;BLyn@2K6+QAlU91bPz$NDX{VotI%=t>s+wxN^c16Oth3g7Yp%TR e>gz&LG@(U0#@0V9vdWT6uC)g_pua-_0RTJjdWZ1< literal 0 HcmV?d00001 diff --git a/admin/template/images/but_round_left_grey.gif b/admin/template/images/but_round_left_grey.gif new file mode 100644 index 0000000000000000000000000000000000000000..d2dedfb091bcff5a9ec8c1cb632762e282ce2fb0 GIT binary patch literal 874 zcmV-w1C{(oNk%w1VGjU20OkMy?(OZ;($dt_)bQ``@$m4`(b3S*(DL!|^YZexwYAUB z&-L{5YiVip^Ygj5xN2xwA9nn>+9>{;o-o) zzow+5y1Kftv9aLb;Hs&qg@c2Zm6gxV&febM-Q3)Rf`a}1{gRN7;o#tul9K1<=DfSR z+S%FY=;(uif#l=kuC1-DtgOPq!uR&}mz9-{jEv>v$>gnm&*x1$8)z{b8fGDg000O7fO3L^gmD!P4he*VAv6gVP;NX|i*j8TJ0Bhk3k?m66&qTe2&JWj90ddj z2d%CLgBBwQ1huxdf+!m|1HHb#auXLl9{|S3$Z|6y0AtS2&|^voPHxuM*wz>pZe-ry z;NC7~YUSqV<|J)v?CtLD31MjS^!4-!aQXWC`w2p600RmPm|#Vmg9sBMB*CSP!-o(b zLJ;$&qQ#3AF+gC$v7^V16A}n0L$ahvl5#fWIK#4~OP0YdNH9aQrcE=sd;}1{v!~Bk z5CRAtN)#0Y1qG5SO$v%b1_Mx|8mM&U!WJ3|vSzI$C&Y{dPh4ckV1w%*Lx>cam1BZJ z4Hyr{xR!XqAWH%aZ#+~A5@E=cO`SdwqEN&LDN_gtr4TWO)vH#6WQd@3>z1GsSfc#e zJV1_y2oj1R8!bo0k7m)LO<;f|n`<{MmUIh8n}`l{xXZ`okKj3KV8G&}`7&~vczMbGjOPeAZpy#hL4wcw z0wRMT%0GZ&5G*XU)FKpgkbqQCRZ>L+FIb_~R+W^X0s~Tj;Q$b2t<~0B4+H`LJGqL? A8vpK%$2|2Wuwov(&>}F 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/but_round_span_grey.gif b/admin/template/images/but_round_span_grey.gif new file mode 100644 index 0000000000000000000000000000000000000000..166e3ce025f961ae2c2132750c387e64c8fdb728 GIT binary patch literal 1830 zcmV+>2if>XNk%w1Vdnrm0OkMy($dn@)YS0r@A2^P(b3WK^78WW@zBuF&(F{F^YhNm z&bGC+YG`Qq_xJz*|Gc}qc64<0^z^W=ul@b~zP-Ks`}_R-{CaqJ#l*z#?(X{f`p?eJ z&CJa9_4UHR!ES79jEjrO$;rpY#_jFxxVN{<%F5o}-lU_Wi;9Ysl$45yh}6^5#l^+k z+}yXew$szoxwyE{&(G1&(1?bH%gf8%+}zdF)W*ifot&Jzy1KZyxPyU##>K_q;NZf- z!fa}4>+9>o!oun3=*-K@%E`&@?(Vg;w5O(~=;-L+;NYB_o0gT8jf{-q;^K~sjLyx? zzrMbbkdS!NI|% zq@?BKF~vazwBo}Sj#)%W)Hy1KgV?d{do)$Q!;*VotNEYqw-{0Ts>gwj^ z=G@!c41ejE#N4? z;Njxq8CN<9Sjn=b%a<@?%A85Frp=o;bL!m5vuDmC zCF*cWL$s*Tqezn~UCOkn)2C3QN}Wozs#U2OrcjvRV2#(WV8ecgW6PdRySDAyxO3ySVMC7Z-@td(*t2Wj&b_<$@8H9WA5Xr#`Sa$RJfOqAz5Dm@46(} z)M@9Pc;>0+o_zM{=bwNED(Iku7Ha6Bg$B?V8;myU=%bKED(R$@R%+>`m}aW!rkr-_ zDW^Qt;D8#WmTKy$sHUpws;su^>Z`EED(kGY)@tjl98kbZ0KE3<>#x8DE9|hu7HjOW z$R?}ovdlK?tg--DA(R6ERBP?E*k-Hkw%m5>?YH2DEAF`DmTT_0<9c8ZCj_+X?z`~D zEAPDY)@$#*_~xtczWny<@4xvX-~mLP9ANOl2q&!Y!VEX;@WT*CEb+t?S8VbB#TZ9S z1QqLcg22Zhhb;2QB$sUR$tb6+^2#i??DESn$BZ%-U{D~(HVWjd^Ugf??DNk+2QBo_ zL>F!J(MTt)^wK_u5JC_SyvWNol~ir@)mUe(_12YOqRBR%Fd+8WWS4FB*=VP&_S$T> z?e^Pn$1V5VbesLd3@S)q2iTp=;`iTx2QK*Fgv-*w99%5m1OyLg0Jb!cM=tr~lvi#! zTD+QJdy#Ktzd@r`hdqa5c5CJ?*;QFzRw9{0${KKk*GcA`Q5 zK1Ikv8uE~cOr#Ey2 UNzZ!P^PY9Xo8I`wi9i4VJEtZkasU7T literal 0 HcmV?d00001 diff --git a/admin/template/images/forgot_bg_left.gif b/admin/template/images/forgot_bg_left.gif new file mode 100644 index 0000000000000000000000000000000000000000..f5daa75f83ad5c3496ff9b98559a8efa1388db4e GIT binary patch literal 337 zcmZ?wbhEHbmR1xp?8iym|B1u3fur+qR=ek1k!h zbm78tnsxcorE_P`UcGwt?3pu%4;|XOckiA(d+yx1bM4x-4I4Hr zTefV+_U+fNU%z|z?xRPKwr<&S?AWn0XU=TewCTx{C-?5%yK?#R%$YNvJ$uGLC7}3| z1#FTIhy?kGfi3UA(WfptQr#@)3q4H?XP$d*sHGdUdUp{l)t?219Xy`1b!{*!x!8I)wbXHMp0 a5vy`pFqxHujfY7>X88h6c`hzT25SIdW`i^U literal 0 HcmV?d00001 diff --git a/admin/template/images/forgot_bg_span.gif b/admin/template/images/forgot_bg_span.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e4770bfc004dcaccd366790cdecc17c19a02a1e GIT binary patch literal 481 zcmZ?wbhEHbG-8xvxXQqAeZ|B=FQu?ckkxSo40P+a{1DwZQHgT zJ9g~JlP9xg&3g3c(V8`DR;*YtfByW{t5#jVe*N0DYcprgeD>@a166_IPZqFwIv^6{ zCkD2E2PPGG=t%XSSWAK{YVYdq>FVsAFmY0G|Kw@YXT(mOIcM%X&)M@AEuOJ( z$?_F_D_5^+U$%C`#{Bi0wr)$5mf600PZG1p-h+q2gn14hKjACIdh+Z!7e3zemrpRW zNL;yjP*jrP*8OeVOkDRKJX_1k&hYg4+a-*wuiw1;GDkp>?bFxaGZ^JLKRx>>y&|KL zmE|XsP)tTf0}JCTrgh046Z<;^8Epi1IQTuX5>jyPlJVTMZ-b@Mt3|}M+I2fz}KzP;c literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_clock.png b/admin/template/images/icon_clock.png new file mode 100644 index 0000000000000000000000000000000000000000..8d64bb5a0a0508e8eaca041a465f35243ef451d9 GIT binary patch literal 4817 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_content_small.gif b/admin/template/images/icon_content_small.gif new file mode 100644 index 0000000000000000000000000000000000000000..b3d47f8e1f6501ea91475d773a939a58f260146c GIT binary patch literal 1294 zcmV+p1@ZbvNk%w1VHyA$0QUd@ZiyVvrU0_Cvg+*Z+tSXpwYA;4tl!|^(b3V>)z$d; z_~PQ?v$M0!&CTuY?f3Wh>FMd$*VoU_&&$ipz`($`xVX2sx9Y_J=H}+~^z_is(CFys z_4W1p`}^D5+tk(B@$vEY_V&cY#KOYD`uqLI$H(gG>fzzx*x1gv3^yVlj!bai#_@9(m*t*gR^($v-Q;fltc zoyeB}v9_knnE=VIoYcs{-QC@=u&~3&$m!_l%+A-$h={waq2kt|)2=qFw_7>g)H}+3@f0;>=*rqX6i_skF7U&(YJo z*S5U8yx!j4)YR1AxB%U`tK7J-v$we2vH;4;%H_A1(bCk>($?VN;?&jJ)YjbA*WRhA zsiL8w`uqFY+1b*`!qe2)`P|&x+}z%@0K2=p*~xX#(bCk_*1x~Myt138p`F$6>(bWU z(m_G<%*@t4KI2+ipP!%M;o{=q;o;fT`PbJ`Y69Qi;L^*o?alzq&Cbov&fnIp;Lv>X z-EHsBeCFfg(y^T8etzq7b7p-A-PF;yvZmhM-TeIhxxHZh{{HymX#W2H{On%Z&XLg3 z(ZIsO{QLgnX=#|3m&V4%_1;eL-C@hKt=_Sg=jiU(uMzFmSJK9bmynF)!=mf%^z`-f z*2S0b)&R}X+RS!!>+J07?Ct1NQ{cE@@YhlB*jM`b{Gf^|`}_XS%D2|m*4o{mzRvA)zsA4^ZMZ6 z;Qsyn%$@+%*4od{(b%4z+tSbV*+la4^1;Q$!NI|#qod#9=-c1l%+JvM{r~*^|BQ_V z)709ouCDIx?z^|Q?AT`d-QC~c-`mlX)6>)6wg9@iy0Njb)6~@Dx0&|Y*~7!b{{H^` z{r$|$%>V!YA^8LV00000EC2ui02%-q000R80RIUbNU)$mE%6MBp&(+P!-o(ZiWui3 zlO{$5@3}KEprgl+1A6f~_brvLLwE?jz~Bj-GXgMU#^f{&AC@GB2H%|;irL~J4b3})3_xT+;IDyMvyqU@g2(02pfB=H z85EGALjny5^5$jttP-gxOaOKJM`3P=e-4g7SPTJHDP>o3H4CzY#6NO#A8a!P=M9@a zy5@;u1u4xBD7X6k`!iR8Fd#d^2+DR$){GQ-xUIP3jRWD3NCJ> zGlCNq>`{US3GidkKLT(-M<7D1fr%Y)SdmNt5h#$s26enB5Ch_vfCDW<_yL9l5`bU< zJ=S;-fsg{V;J_GvNK#ES6Lh&j0cs#HC6)hFfI%K5M6{0w?O1>UnF3XC0$KjlS*HXj zATp+q{PZaR1}7{a=%5?8;7^~3CaUNv3>4t#qXoR6fufZ1)6b=tW~%9?oObFdrvU)~ EJ0(^l*8l(j literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_dashboard.png b/admin/template/images/icon_dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..757d5c1c0fc893b21805903b9cbd6c407276e5bb GIT binary patch literal 4628 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 U!>FWQgUKo`rK;+x0tEyBJC;1Ob^rhX literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_database.png b/admin/template/images/icon_database.png new file mode 100644 index 0000000000000000000000000000000000000000..634c313779e0d6d1d43b406f4487751e4ad6e2bb GIT binary patch literal 4348 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_help.png b/admin/template/images/icon_help.png new file mode 100644 index 0000000000000000000000000000000000000000..f4a943c4f5faac9c82525dc0e1c3ee563d19966c GIT binary patch literal 4492 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 Z1PO`$BL|NPWLV8r?EMn7(o2cK8UT1gHlqLl literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_media.png b/admin/template/images/icon_media.png new file mode 100644 index 0000000000000000000000000000000000000000..613969a6ee8a7b25cf6c9585beb2d82fdcd13109 GIT binary patch literal 4498 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_news.png b/admin/template/images/icon_news.png new file mode 100644 index 0000000000000000000000000000000000000000..ad73c81e53074b1f6632bfbee8b9e9aac1864315 GIT binary patch literal 4237 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_reports.png b/admin/template/images/icon_reports.png new file mode 100644 index 0000000000000000000000000000000000000000..fb64439429ba3ecf4a504cbd37e89f188036e142 GIT binary patch literal 3639 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 JPDHLkV1k@g+$I13 literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_settings.png b/admin/template/images/icon_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..83ce6c1863302fb5c8bef5f7d109f1c09ea5638a GIT binary patch literal 5126 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_success.gif b/admin/template/images/icon_success.gif new file mode 100644 index 0000000000000000000000000000000000000000..502a17346784cc2a3bd1d202c2a929073ee55a69 GIT binary patch literal 1176 zcmds${WIGK0Ec7sy4g<4x^BJo5E^WAHLNCjQD-LQdQF{bNV}0VNRfzm>q&7EFQX#e z8Y1mUW~@>pCEp~Ri$s#;RS=yt=#h(LS5?F%M@!hcKVzRCp5LG6?(;o7CGOkY1kf4K zE(m0`S^@LWfouQK^ZQPx({8tKZEfxE?;DNAq2)fkUhi_bh^m6a!@~}J?Hyh5=H}+Y z!h*x$uvjb&`pTW1o%#8Bp?P?EdYYiTRV>WH$>3#5EPaf|S$I%7mO~uN;TRwE8X3UK z;K9KGekzx$C?}~35W+~Z5G%F_2qGk5GV94at3rdTP#2PfIdwYXkdf0Ouc#Tv3@`V0 zYnr4M0dubP<*qe?7E07+hTjPlnt2dn2>wqDhL^suX;^)=Dl`EsBR!_(9GnMvxo7=j zg>`cv^(s55L0r7HWA4&5ouz;+c5~&#kEP-tx|K~R*@aeBRcvh(L)$pA^jP~^0_8wr zX;GP@vHZpU5_ul%9+WK3FH~LPuMDPlUg*?Oiv-sMbAZWY!UNZP40MzPTB{-40APPR z&65^Uks^&GL{+PA+Z>ih`qpw)f&I;Ple)S@o_kkX$X)IvO(AVIn|Z^0nRRh-aS^M4 zkDB^k@4j*!y6!6RFe1moG{-UC3Hzpa=&Eb`yXKTSE8HO&Q)oIFrrN`t6tZCy}_p^JjR%nR=T`k4T z%*-%n+nCcojV}QNDVqO+o5YE(6&2#fuHa?4;uYZOi{J4862?sEm}uvl`gA(o(a{m; z|GuC%?*A!%`Ht^C0rEZq75bpqUT%#@Z~q9CipP;PedKYCckW`+vHDZdxMkJTUM0;_ zm$;WY@|&9G6%Y`o9=Qbvfl!)<%&7O=y5nx-iMmGf)yNQ9>LNX5&NHE?M&Q1F{DZE9 z;1eO+Je>B!J_wUI7^9F<-2%dVy%R&zz8Hi-ZQGVW$+1s-FYD_4u_;_g0Sxz7Getr5 z^8K2!o|H;uABTroouc!-EWhNN2Rs>99+X{5P}Kt>G`cMerC6N>s|LQ|yLXI(W$^s= z9*@rkI9UJBv+J(ryxs2e>o=Z8&u2H-GWz4&3p_@Cb(5b8XV={h5PN$^AQ0(Q5#M8DGd?#RYp96fHSnD1S7-uu6UB2S9aGVtjxf2>K5~V*7#s literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_updates.png b/admin/template/images/icon_updates.png new file mode 100644 index 0000000000000000000000000000000000000000..06664beca50e0b29cef50d9d646072ea56741903 GIT binary patch literal 3781 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_users.png b/admin/template/images/icon_users.png new file mode 100644 index 0000000000000000000000000000000000000000..e246c8975ac244f45fc4ccda139404f8ea7aea74 GIT binary patch literal 3597 zcmV+o4)XDdP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0009xNklBZ5(pE&F3b!wK!H|{z3G!i zbLZUiuFpGj-_uw~DQV=e(ctmFfQAcj0H~_kkWQSKm=F&AVR(4Bu0K99GIHVoKsudn z+$#Vml}ZMf$z&{~?(Xh06KlmW1nlkY8Q}i@K2uXu0L0^QORm7DAnx^4&I*puu0rZB$cAXQBL|h1QhUaiN&^dQ{db$F^prwYzfqT8Zb=`h{%+C{5 zl#_!~az|8S!&V>%RJ=KoiUHKKM{mga0kJ5UAgN}Q& zbUm_gCnqP3La|tkL?U4+ZpLD<*wtQv+v@?~DEEp$AOJuh5a3;Y4Y&6z3)j5DVzGE; z#b&HnEM853$Lj{b+tftaMD+STFmgI~cX!uP?DX?LVHXQ%syYzt>?61I6G(}$*=gdAk#iG$DsZ`3ioAE0;cRbjqpGTLH{(}!AhYoDQrmWRb^yrba%XZnc3$ox0Tn5w?J~9R z<(p6l;Y!ZTr2pF3=&SSh=vyI#QyjYxJih8G0C+0^JK#3=L!HJUP!^5;d;a$T`jW#% TvYy`u00000NkvXXu0mjfLC?u8 literal 0 HcmV?d00001 diff --git a/admin/template/images/icon_warning.gif b/admin/template/images/icon_warning.gif new file mode 100644 index 0000000000000000000000000000000000000000..05f3bbd2441d627060401eee6669b8eac844fde5 GIT binary patch literal 1139 zcmeH`?N1YT0LQNu2#6&Jc3}zzh7&=}B+l94Fi{wmhe$;c)Yd3-TO}@$sF}vd6bhKh z0&3#}iYd?xAL4>tRM4oEs!%KiE!?$d5wW&Zpgrz-S9(vs`tT?0^*%2?@4jz7$#+9; zj^z8@KR^qi83-C~$#goMfb{~_Ls1l9F|*lBqVgc%KLR++;cx%|Se6}bU2Cye;I_5> z{r!NQpwLp5bdV&8<2ZsK7={r9;q`i97zP|U`Md z;(R@imBMEg5q`9cL>2y5+j$yycV++vpK*5a^tk&`nWwjcvKHB|q)?8BaI=E6@1(uR zlwte8zyOZ4PUv@%=niV^CT2e9Hq@ag%3!yB))ErgICeeVeecI0plvoA&rmaNgU|Yx zO;gO%o=NkKz_=Q4#EU=UgFH=HH+hEc0A`%QhCRlk0p}@}Fibqm_K)rvX-W0l<pgPAX}Y}P7-jjQ@5J1>j39B>z~eYgw)?{=l5_S%U7138(CpsvCGs zee&vfNp$+Im_-i~=(74fDpisgf=ub_t`)>QSs;$&8l_du!eh{is$^+Yv}yjT&4*Pf z`R9c@G9*Q$YQ0)=HND&=2oF0a&ipF2X{@dwd2v^0+SZur>c)uJ+Ck$1<|0MO;i4IY7D;NXiD2!ukBgFq}RvX691l|%plJ2X)BN%{Z(KLZ#j{$ycfVBlrY0r5a)FtFHdIO(~1uSNVZjr+$hn)+B&oi-?VRaC{H vz`qb8)9WoXw!qcM~utZ0mKX9hE5&7zjvNsP

2_iw-0w|f6 zFuS4#b)iYT`0g>ZnUAQpb(>qepf*IktyBFOYxV4oqOeZ|FUi@IFfv zRw}I;Snro%r9DVodsK@6;qZ~1juqLmwr3pM#CNL)H^N^^e{AjgWb$WM)mg2}px6s^ zh6U#E!PDz^vIO9DaMQ3dp)-1P28-c7349?0RS*1G{GzT!(3=3>M}SKIoc8Yt?5WOC zl*w5FZ@f3~owW^3akrvj2my5=$#pY;>BgPJdXg+TZaOvsIi(C;JkSpd0 z(Af6KhlOLfX0LY~;|i4v3LMk~MYM#WDlJE#tnA0YE8o(0^1%sAG=&y*D9t4zlgTAE1+UfX?sI;be@iZ3M z7XGYF4&M5uu*X{js9K}L)Y?`NQX*%jAB@Jf@W^k$GGguq?jIHEkSl15?e2|h283h}{rk{y6hWQeEgV%Dp~Y&^~Lp556}3weap&=>lD4J79DzDV_Z{fQ7`6qRx0UY!qkVwn<_1< zZ_YcpsAB1}Z-K$B>t0GFTuk2#rcF4K!y5%h2Oj(<}p zH}CDTX)sOP5H9L^(xuxrxaXc$$&HBzro>Hsls)&^y33pYwKi_Jx>eG?_}{k8Ws9G> zG~X^*@S<=-d2rvu=Cv>WWv1rMf6}`4WzCA`5~1f~CqEE%KH0nZ)n{ABN!#Cq_TG=1 z@*rl?gMXE!UTt@3cQh|J_%40+v)Oyz&D{NVMDf{k2J1% znKtv$%wuzPa@Duq+*Q5&x$iVr0j&ec(;xnei_ThIkTd78W5cby1ux2%y%I7%7TJGa z*yfm!>9LqekN)l4_AfH*Us_V$yeENO_x=^;R&8&Xb7H~2$rDxmYusD!^Q-T#vv2a|<>DcTLtLJ0IxS~f;u;~`h4#B4kJp7I~ zzWi)#VV}Y45Th|6MA>1gbNq~g%r6Hgb$Q#~k*Lp7@4ozc`sT~C_urqq`~K+F=e~94 zKYjoG{>zUazyH4Y@MFUI3k!B%fBWUvz6*~FW*mC;{@e2pKVEdhqho zr|-W$efz!Y;O*u6Z~pxK=lQ#@%MaWtnt6Ebkvrdi{yB8{Y2nPnHH%Ip_3de2c_yZ7 z*RFGq;<|V5yZGee*PpRnyK<);>|J|4fBK>4@4vr%|LyJPUw5B>jBMYr`ta=!-+teI z`u_O!=UGz@JbwM<)yE$%KYV-j>F1k|KWZ19c>VGFw9S`dyLYv%IP>-A@B1%4p1=D# zebT<)fBv1l^Loq4`)@yeKXdyP&|{1CT>tR(_m>~PS0B3l=*_o}-+rII_3Gli*B`(A zeE;=V_nLEGfBgRc|33q{K=CIFBLhPYgAT|5P@FKZA8cSt$ZBcj7YfSh>Jo^^?(a|H zF>&wiV#t=_*7iuuloFAimNSD}K9f~KEOX&vhOpF3!Dur^b4E)^NpAx-E|w@ki9j1U zW@Z)^1wSJ$AstU~aT&Q4E^1;-nViBoiu^oj>ddVEOnmGdOn171<3eS$G?+wRrZ}!y8{Dj9YxUS<|gbG7c>9=#-6d+ZZUsz{{!Z=;jcyI53b` c)^6RDEhfqgqJrAGrHqplmic-&GB8*J0PEgJJ^%m! literal 0 HcmV?d00001 diff --git a/admin/template/images/icons/edit.gif b/admin/template/images/icons/edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..9660fe2f3747d78c30446bed8fdfc319e034822d GIT binary patch literal 197 zcmZ?wbhEHb6krfwI3mRG;K74$krl=3pXM*WU%Bf||Nd8ZT!W{a_|UWSY4N%zGcSId zef?)$U0warFa7&o?%K6$Lr7TclwJS-|7Rc$DE?$&WMB|t&;cn2*~!4_v_PdVC39W| zr=un(E8}f9?i7hnl9ryIo-O4_a&TeroY<5Q*|9*0z3IyX8(RiJSLeX3OdGn_eeKHi Pl<415c{Xpc6N5DX{&_}O literal 0 HcmV?d00001 diff --git a/admin/template/images/icons/exclamation.gif b/admin/template/images/icons/exclamation.gif new file mode 100644 index 0000000000000000000000000000000000000000..c7800791dd083fc4695b466630921c10ae87abde GIT binary patch literal 1013 zcmZ?wbhEHb6krfw_}<9yrXc!NPUPpBgm=X;@5^GJr-y&2i2uEJ<=3X<*LhLDUOoS@ zWx==3>}RQAAFJX&*CqbFe(q^f=%<;${34`YKqOmF_Nb?NuEoG)t@{(bZE^ZI2U=J&mw zKlRJZme=bSz3#02c4r$v8i zNd0l~#QWp>U-eeMTQK$U@>##8)Ex3QdUbH;uRSYXwby=}JK<|z`Hy`YFD3?@OY!^O zQ~IzZ=0c?7-J1MgH!pu}O#0kgcDEq*U3KEqqR5X+XTIsKzfll*Z{gIpjhT;IO20pU z{O#GJmj`z|C{Fm*SAMrP|7CvsyXL&(v2IWMn%^|${8-p=)Zgq(lFz?)uRpGs|0F%; zM_cZhP@C_YmmCXsyqN6sr6v7pg8Q%io4#&X{IwWp+Q2fcl$iUFZpaZfWlqVQCE-^53%6M!@aFjG?nz5po zg_EnfQK3dqIq6^%m+__#8XS$j9n9hq1{a)JSf)xbU)E79WME`+XprOB@VL2?sj>Lf zmKG<*Wz5VhULKi>241YjA}NPd3>X;Z*@v_E9Tads;6H;wh=s#>apwU(`7#FC4=e!; z+^l&anaT!jTw=b$5}ttz99hK8rf|G@e6%-=+d%or3&+zL~|?ik=v}yObpflz1vQ7 literal 0 HcmV?d00001 diff --git a/admin/template/images/icons/feed.gif b/admin/template/images/icons/feed.gif new file mode 100644 index 0000000000000000000000000000000000000000..87e97b68615f2840b6263a0a9168a1fe9ab21ec2 GIT binary patch literal 1082 zcmds$?^6?W0LH)A!ezcdk1o16vhK9y!5!7Q2)!IP291gz$_DJnC{SoQZ-_~t(0;K> zu!HqO7}Sjp4F+t0NMITaLSZ5|Y;b2?SG$uFctZ*1!HYg&e@4%X=hgG#^Lg>4s#6kP zc_%_di2FiNEBI94&13x@o?KR!SYJgYxN@8yEBH2(rc^!<+`mhz;Hnw72EUc@YL@2k z>Tnh@Qo*2+uZwXS`MiLRY{se?v0>TE6&u|-bZIFU{9vFroh~D8Bb`T?_HeNbhmuhX zV&reMZHYc?knn6fiz zqIMsHW(EwD%K2_TemfHuR+pLeq7;nO@Rp!81J{O2F6Z8-Tg!x%Ap_k;It+9eX;EVp zxQdxN%V-rV3pA_o9Hdk*bOK)$ZF)`$>NND1anr+}A?zB4E2$F9Ugq~VKZ4?V$7tH(d8tKt7VPkED^GVqD67rF?fpHkK z;8!091W5v4HK+H{TT7l`WtsE)DHM!<#NtglEd;%Me}dK$`UO|JQrsfW|0vBA*DQc|O|Ao`FwdGx1Pi7GR<;;%!>PvpuM z9*JtO24Wx0*H6mhQ^Lc-HpvtPGpWXiz`1 zC~=D;b*3E=>a@5$IkuqQq`D!~Ip^}7ip?2kbnyf7_W5VEkLk8)CyvzEUyI9%*)n^q z#uwJT(-0o4yy!}f+g0ZXCTh%Y$l?-r`E;()$oAxeCfT;OkZ6h8p0+cvviavHUoDHz femu}4Q@WpcChB%WzkjPErTWv5nTG7Yf+X!dSX%@1Z;hfnMUlit~pKLoDSKEN!ds6;xfbiVh}PUgz^HwF)iV61ykH+^CCzVBILjR3jP{uX@i9^2 z>A2r_d@0Sv!NDO@cjdCO6mbSfkC#4{v${T0YpN3gFei0?tk_s*j{< zjGAq97z$JqeR{ot(X_ET1z7&cXa}sL4Yjq6-0~OBsz+eynfwA`h{g8w%PD7nJqZKm zDLdY09(EThO;ypyYlrF zyD0n`a?H?kcOdoC>2zZM`DX!tme0emYHa6U>+cho+cXyG4t(ZUSGndVH|cg~Z1Gr| zJt)?1Q9P{_Zs=UoL*()Oyie@k(PR-QYuAVKN#5}^VVNJ_jo&H#Q7n&jsqc`CM7zJh zcnt#Oy|g$tS;+Q?*HTI0Cigv{g&hfeC~!R$nDrrmELiCgRW`M@-_!xE8M1h{8!yS=n=Us#^)8k(A&Eb;9d!M ug&?R17thtl&dbt5Z1MhEzw2Zt#WONOK9VlG{yb6I-7~zXa&dLR!v6rXxzQ>B literal 0 HcmV?d00001 diff --git a/admin/template/images/icons/lightbulb_off.gif b/admin/template/images/icons/lightbulb_off.gif new file mode 100644 index 0000000000000000000000000000000000000000..dea57836ef26fe228540a9e8fb366bef2343f273 GIT binary patch literal 616 zcmZ?wbhEHb6krfwcvi&l_Vf4mUw^#(`1RqNPn*x(z4r9&-+%uez4`R?-RDo=f37%j z^V$0^Uw-^LeecDreU~1*{)Ox|^V$HfO19=`hU?dO_Px0W5d zzU{)j4_|*QoLOGB;&AttGY4-xp0#ksyDvX}|M?r?qIcl><8u#Q{rL6g?#mBH_OHBu z?d0w)bMCx&f93I;qqm-}JaKdB(d)Y|KfM0*?e>fJ1AN_fUwP=}=DJ~J@1mv4syk9% zeE7P1&z^%fo-8?feR^}++S9j}FRZ`${N22RR~pwHj|um$TXXE}{g#@aQ{nzgWhpuk9aPQTt*Sju1SbqFQ+on@JZIwrEK23-W z+IRKQwu|=<-FWi!{g>|kDRU2AncCO9>D=9KKY#!K|DS<4p!k!8k%6IzK?kH96ekSq zM;nToiWsd;vz4_R9Gjbs%vqV47`2&L?G$91*=z(E8JIZOC-IobnKkjVatd+Av#}L& zvleoxHtBN+F%<4Cn>f$)zyM zjfF*{K!=Zk%daUik(VKyB|4?RUobR;vspdJB*1~8&yhWSS4F0Z`Y|@4zymuHFCF5N yZfn|N(%8t#IbD+5fX}GdrMcBC!-cPEv5QYTzhnp(m*G;5Rz=H{S0W-D4AuYyDnDNU literal 0 HcmV?d00001 diff --git a/admin/template/images/icons/user.gif b/admin/template/images/icons/user.gif new file mode 100644 index 0000000000000000000000000000000000000000..95c0aaafea551ac24e0eac0deef9898f020be4b8 GIT binary patch literal 1001 zcmZ?wbhEHb6krfw_}<5mxbt7q&VMVb{Z>@_zB;q|`<3;7e}C`t;BWO2{r2Pc&tHFk z{r>9|&>`=0MBekLrpKxs(`(wj1!qPG&5jV7;4M((BDuOT`rC!&t55v7^5{$aw*S-o zg+dnmEzYW6HMQ;7^=}br^FtT^|NQC8lkHu34x;bQE-$j@pYF}yaPWWPrhgUde!SXT zF?+-H=r#W%m;O6nr+sl{{f-3_W~{v;zyJJo3F+E%^5MU~zneUzmOS~NeBgh}?ys3A|67Evnlf+mngadO z<^`#CGB3_=`TpbgxoVBW*FImY)AF1C@9WoZC(3n89fjsc2%T>-$#zv*l&Np%yWF|= z|GWEVBUk+E^5PF)^zZGCy5KqgV%Pk8b$M4|&CGT${v|u_e>^(9YWk%Ua|-Wo?M&GI z|LN|&|Ns9pi~?$hfZ|UUMh1pH1|5*Wpgh6Aag0HhQ^sS%0!L+g4H<>U2Ok`ekXG|h zNIJnH*52oL=jUS;CMN4#1E)pX79PY?v@n@(zGCAmjw!~hM`nt7GjMVVx*qLQi)RsP3T9z%V3@(k g;Bbkte|96=3l*==EuNFut8+RG8a8fS+`wQB0Lds$1^@s6 literal 0 HcmV?d00001 diff --git a/admin/template/images/informationbar_right.gif b/admin/template/images/informationbar_right.gif new file mode 100644 index 0000000000000000000000000000000000000000..66711e28072d67e2219bd5076a5825399a193f37 GIT binary patch literal 551 zcmV+?0@(dWNk%w1VQ>Q;0K@Cd0v$NUR*}c8J!^6Y4xVY8T z)ym4s#>U3n+}zR8(ap`x`uh6V*x2Xi=kD(A^78WS?d|jP^ZEJt{r&y?{QS<&&d<-! z%*@RH|Nj6000000A^8LV00000EC2ui0B{2y000I5ASaGwX`X1Ru59bRa4gSsZQppV z?|kq7z@TtQEE41ejA<7S7LAgVl$Dm3n3R00E@bU8V^pXGr1M404`Bv}s00RmfNRSMG2nP9smUiGA2;q@L|P|AVZ402B3h+0v$c1j$FyIrOR6Y1jrPSve?U;ICJX61b_g6 z1q*!E)U~sy(W6M~000 zt=pVy-^!g!H)7nnc=PHdcXzMfzkr+d4NSPOVO)a`D_+ca6b22ABTJs_2^8ham@_AO p6iKt^&!FSv+0#LZ>C>oFt6t5zwd>cgW6PdRyLJvHPCA4D06TPCGZO#+ literal 0 HcmV?d00001 diff --git a/admin/template/images/navigation_background_blue.gif b/admin/template/images/navigation_background_blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..98e71b97d5738242fa563f780727c7cd89b8a103 GIT binary patch literal 583 zcmV-N0=WH0Nk%w1VF3Wh0OkMyUY^Z5f3RGh%{h0bU!TocoXc38%UhkzSewf`f3RDf z%shXvJ%6xhqt8Epv2&rsVxP@mpUqjE%xRmzONX_Qz21<#-k8GSoy6i@p3RxV;dHCi zMTE0ThqZyT*oC&*W1r1(p~GdN&W^j?gtXdYpv`Ta!f&V2RE@Y*j=5ZtyJeWZUX;90 zi??y8(sHTOiMiZZkh*=a)_$?qhqv2wqQp#ywvxWzcB|BnyxpC}<8YtDVV}*K!{I)E zutI{el)v9v)PQg+**;lYNXFukh)`+zDb6(LxQq!pu=F5y=a=icdgVxfwD-2 zw0W-8p2g#9oWXOd(`K2!pT*;0mc3e?%sGFs000000000000000A^8LV00000EC2ui z0098V000N1fCG4RIv7Yj8W%@KR6sWs7C9qkPcU0FA0%ZSSu-+HQFCxO8+I=)Crw05 zN@xuYSVba2B_I$GJP{EDya2uc83MurR|m!l$a>1l%n}j>&<4^7)LjDuH4hIVLv1@t zUnX@y6K`C1D{51DZY)|VXK67|DJWr1Eml=F6dh}FW5jR(!{$evBxD>o@Zy63g9Q*1 VNDM$Rz@Cd3Giuz(QR9F>06Q{`7^(mO literal 0 HcmV?d00001 diff --git a/admin/template/images/navigation_first_blue.gif b/admin/template/images/navigation_first_blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..98b7e855886db0b7a86a25ea0194c6115f544e15 GIT binary patch literal 4866 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/navigation_last_blue.gif b/admin/template/images/navigation_last_blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..1b0688e9f78f5a348d359a5613a4748b3ba5aaf5 GIT binary patch literal 4867 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 literal 0 HcmV?d00001 diff --git a/admin/template/images/tabs_left.gif b/admin/template/images/tabs_left.gif new file mode 100644 index 0000000000000000000000000000000000000000..8fbddb78de6c0fb1f00526086d8d018387595ec1 GIT binary patch literal 559 zcmZ?wbhEHbOlCAU+u~ld$erKp0@4pzke^@e=*6LWK}%Rvvt$||Nj~A0>z&!V0j%739^%c^}hlG z3%lXmj8*G$UhgZ=IbV`{zhd3{n)kmMTn-y7kmx_Lr08Uh)%*)9O1#!at-rCR?DX3* z=FUasK6CqXL3tdZ(sj})}Dz| zrcRsQJ!97FIdeTG&s(@?@uVfomaiyYuyW1XbrGxAZ`!=YedE?0JC|+WwRhi)J^K$G z?mBqn_=&n>C(oQMJbmusrIZVouU!wjdgJyTpIdhy+`a$s$+gE%Uz`lG{`&pr@4x>H%v>@z{8%`J?S-^rPHb3sxLrWmD@X8&BO{xrQP!Ok8y6q% zS8(o<@!YiJWIx*ccU(AU0L@djVbB>?#)9lr3~` zSo8PazgHi=+LbTPp0@49`!Aor|FkKY@6oc+G<%X&@jTDgP5=M@XTSjzf3kpObU-A? zP6pQG1XZJldf2}>M`EX z2@6r2$uzy-@rQ!e^8z=2))=fgEO^v9W@h}W;y=;*pUwYUQr1x3)LPkA-BDX6)Ky>1 JBcjM)4FHKFTWbIS literal 0 HcmV?d00001 diff --git a/admin/template/js/blend/jquery.blend.js b/admin/template/js/blend/jquery.blend.js new file mode 100644 index 000000000..1a6bd8159 --- /dev/null +++ b/admin/template/js/blend/jquery.blend.js @@ -0,0 +1,133 @@ +/* + jQuery Blend v1.1 + (c) 2009 Jack Moore - www.colorpowered.com - jack@colorpowered.com + Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php +*/ +(function($){ + /* + Blend creates a 2nd layer on top of the target element. + This layer is faded in and out to create the effect. The orignal, bottom layer + has it's class set to 'hover' and remains that way for the duration to + keep the CSS :hover state from being apparent when the object is moused-over. + */ + + $.fn.blend = function(options, callback) { + + var settings = $.extend({}, $.fn.blend.settings, options); + + $(this).each(function(){ + + var $this = $(this), + $target = $(settings.target ? settings.target : this), + $hover, + target = [], + i, + length, + style = {}, + active = false, + out = 0, + opacity = settings.opacity, + properties = [ + 'background-color', + 'background-image', + 'background-repeat', + 'background-attachment', + 'background-position', + 'background-position-x', + 'background-position-y' + ]; + + length = properties.length; + + if($target[0].style.position != 'absolute'){ + $target.css({position:'relative'}); + } + + if(!$target.hasClass('hover')){ + $target.wrapInner('

'); + } + + for (i=0; i').css(style); + + if(settings.top){ + $hover.appendTo($target); + } else { + $hover.prependTo($target); + } + } else { + $hover = $target.find(".jsblend"); + } + + style = {}; + for (i=0; i 0 ) { + +// We make the .column divs sortable // + $(".column").sortable({ + connectWith: '.column', + // We make the .portlet-header to act as a handle for moving portlets // + handle: '.portlet-header' + }); + // We create the protlets and style them accordingly by script // + $(".portlet").addClass("ui-widget ui-widget-content ui-helper-clearfix ui-corner-all") + .find(".portlet-header") + .addClass("ui-widget-header ui-corner-top") + .prepend('') + .end() + .find(".portlet-content"); + // We make arrow button on any portlet header to act as a switch for sliding up and down the portlet content // + $(".portlet-header .ui-icon").click(function() { + $(this).parents(".portlet:first").find(".portlet-content").slideToggle("fast"); + $(this).toggleClass("ui-icon-triangle-1-s"); + return false; + }); + // We disable the mouse selection on .column divs // + $(".column").disableSelection(); +} + // This function is making the info messages to slide up when the X is clicked // + $(".info").click(function() { + $(this).slideUp("fast"); + }); + // This is creating a modal box from a hidden element on the page with id #inline_example1 // + $("#inline_example1").dialog({ + bgiframe: true, + autoOpen: false, + modal: true + }); + // This is creating a modal box from a hidden element on the page with id #inline_example2 // + $("#inline_example2").dialog({ + bgiframe: false, + autoOpen: false, + modal: true + }); + // This triggers the modal dialog box // + $('.mail').click(function() { + $('#inline_example1').dialog('open'); + }) + // This toggles the color changer menu // + $(".dropdown").click(function() { + $("#colorchanger").slideToggle("fast"); + }); + +// The functions below are made as FX for table operations // +if ( $(".approve_icon").length > 0 ) { + $(".approve_icon").click(function() { + $(this).parents("tr").css({ "background-color" : "#e1fbcd" }, 'fast'); + // THE ALERT BELOW CAN BE REMOVED - you can put any function here linked to the approve icon link in the table // + alert('this is approved'); + }); +} +if ( $(".reject_icon").length > 0 ) { + $(".reject_icon").click(function() { + $(this).parents("tr").css({ "background-color" : "#fbcdcd" }, 'fast'); + // THE ALERT BELOW CAN BE REMOVED - you can put any function here linked to the reject icon link in the table // + alert('this is rejected'); + }); +} + +// This function serves the More submenu ideea - you can attach the class .more to any tabbed link and you will trigger the hidden sub-sub menu to appear when clicked - this can be developed in a nice way if you have an enormous amount of links // +if ( $(".more").length > 0 ) { + $("#tabs .more").click(function() { + $("#hidden_submenu").slideToggle("fast"); + $(this).toggleClass("current"); return false; + }); +} +// This triggers the calendar when clicked on the event tip on the right of the title - dashboard.html - it can be used anywhere in the page // +if ( $(".hidden_calendar").length > 0 ) { + $(".hidden_calendar").datepicker(); + $(".inline_calendar").click(function() { + $(".hidden_calendar").toggle("fast"); + }); +} +// This triggers the 2nd modal box when clicked on the TIP link on the right of the title - forms.html // +if ( $(".inline_tip").length > 0 ) { + $(".inline_tip").click(function() { + $("#inline_example2").dialog('open'); + }); +} +}); +// THE jQuery scripts end here // + +// Below is the "allbox" script for selecting all checkboxes in a table by clicking one of them - usualy the on in the table heading // + +if ( $("#allbox").length > 0 ) { + function checkAll(){ + for (var i=0;i','","");this.element_.insertAdjacentHTML("BeforeEnd",AA.join(""))};J.stroke=function(AF){var k=[];var l=false;var AQ=C(AF?this.fillStyle:this.strokeStyle);var AB=AQ.color;var AL=AQ.alpha*this.globalAlpha;var g=10;var n=10;k.push("x.x){x.x=AJ.x}if(AP.y==null||AJ.yx.y){x.y=AJ.y}}}k.push(' ">');if(!AF){var w=this.lineScale_*this.lineWidth;if(w<1){AL*=w}k.push("')}else{if(typeof this.fillStyle=="object"){var o=this.fillStyle;var u=0;var AI={x:0,y:0};var AC=0;var s=1;if(o.type_=="gradient"){var r=o.x0_/this.arcScaleX_;var e=o.y0_/this.arcScaleY_;var q=o.x1_/this.arcScaleX_;var AR=o.y1_/this.arcScaleY_;var AN=this.getCoords_(r,e);var AM=this.getCoords_(q,AR);var j=AM.x-AN.x;var h=AM.y-AN.y;u=Math.atan2(j,h)*180/Math.PI;if(u<0){u+=360}if(u<0.000001){u=0}}else{var AN=this.getCoords_(o.x0_,o.y0_);var Z=x.x-AP.x;var f=x.y-AP.y;AI={x:(AN.x-AP.x)/Z,y:(AN.y-AP.y)/f};Z/=this.arcScaleX_*A;f/=this.arcScaleY_*A;var AH=S.max(Z,f);AC=2*o.r0_/AH;s=2*o.r1_/AH-AC}var AA=o.colors_;AA.sort(function(p,i){return p.offset-i.offset});var v=AA.length;var z=AA[0].color;var y=AA[v-1].color;var AE=AA[0].alpha*this.globalAlpha;var AD=AA[v-1].alpha*this.globalAlpha;var AG=[];for(var AK=0;AK')}else{k.push('')}}k.push("");this.element_.insertAdjacentHTML("beforeEnd",k.join(""))};J.fill=function(){this.stroke(true)};J.closePath=function(){this.currentPath_.push({type:"close"})};J.getCoords_=function(f,e){var Z=this.m_;return{x:A*(f*Z[0][0]+e*Z[1][0]+Z[2][0])-L,y:A*(f*Z[0][1]+e*Z[1][1]+Z[2][1])-L}};J.save=function(){var Z={};U(this,Z);this.aStack_.push(Z);this.mStack_.push(this.m_);this.m_=D(O(),this.m_)};J.restore=function(){U(this.aStack_.pop(),this);this.m_=this.mStack_.pop()};function G(Z){for(var f=0;f<3;f++){for(var e=0;e<2;e++){if(!isFinite(Z[f][e])||isNaN(Z[f][e])){return false}}}return true}function Y(e,Z,f){if(!G(Z)){return }e.m_=Z;if(f){var g=Z[0][0]*Z[1][1]-Z[0][1]*Z[1][0];e.lineScale_=b(K(g))}}J.translate=function(f,e){var Z=[[1,0,0],[0,1,0],[f,e,1]];Y(this,D(Z,this.m_),false)};J.rotate=function(e){var g=c(e);var f=P(e);var Z=[[g,f,0],[-f,g,0],[0,0,1]];Y(this,D(Z,this.m_),false)};J.scale=function(f,e){this.arcScaleX_*=f;this.arcScaleY_*=e;var Z=[[f,0,0],[0,e,0],[0,0,1]];Y(this,D(Z,this.m_),true)};J.transform=function(h,g,j,i,e,Z){var f=[[h,g,0],[j,i,0],[e,Z,1]];Y(this,D(f,this.m_),true)};J.setTransform=function(h,g,j,i,f,e){var Z=[[h,g,0],[j,i,0],[f,e,1]];Y(this,Z,true)};J.clip=function(){};J.arcTo=function(){};J.createPattern=function(){return new F};function X(Z){this.type_=Z;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}X.prototype.addColorStop=function(e,Z){Z=C(Z);this.colors_.push({offset:e,color:Z.color,alpha:Z.alpha})};function F(){}G_vmlCanvasManager=I;CanvasRenderingContext2D=N;CanvasGradient=X;CanvasPattern=F})()}; \ No newline at end of file diff --git a/admin/template/js/flot/jquery.flot.pack.js b/admin/template/js/flot/jquery.flot.pack.js new file mode 100644 index 000000000..105ed5e57 --- /dev/null +++ b/admin/template/js/flot/jquery.flot.pack.js @@ -0,0 +1,2396 @@ +/* Javascript plotting library for jQuery, v. 0.5. + * + * Released under the MIT license by IOLA, December 2007. + * + */ + +(function($) { + function Plot(target, data_, options_, plugins) { + // data is on the form: + // [ series1, series2 ... ] + // where series is either just the data as [ [x1, y1], [x2, y2], ... ] + // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... } + + var series = [], + options = { + // the color theme used for graphs + colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"], + legend: { + show: true, + noColumns: 1, // number of colums in legend table + labelFormatter: null, // fn: string -> string + labelBoxBorderColor: "#ccc", // border color for the little label boxes + container: null, // container (as jQuery object) to put legend in, null means default on top of graph + position: "ne", // position of default legend container within plot + margin: 5, // distance from grid edge to default legend container within plot + backgroundColor: null, // null means auto-detect + backgroundOpacity: 0.85 // set to 0 to avoid background + }, + xaxis: { + mode: null, // null or "time" + min: null, // min. value to show, null means set automatically + max: null, // max. value to show, null means set automatically + autoscaleMargin: null, // margin in % to add if auto-setting min/max + ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks + tickFormatter: null, // fn: number -> string + labelWidth: null, // size of tick labels in pixels + labelHeight: null, + + // mode specific options + tickDecimals: null, // no. of decimals, null means auto + tickSize: null, // number or [number, "unit"] + minTickSize: null, // number or [number, "unit"] + monthNames: null, // list of names of months + timeformat: null // format string to use + }, + yaxis: { + autoscaleMargin: 0.02 + }, + x2axis: { + autoscaleMargin: null + }, + y2axis: { + autoscaleMargin: 0.02 + }, + series: { + points: { + show: false, + radius: 3, + lineWidth: 2, // in pixels + fill: true, + fillColor: "#ffffff" + }, + lines: { + // we don't put in show: false so we can see + // whether lines were actively disabled + lineWidth: 2, // in pixels + fill: false, + fillColor: null, + steps: false + }, + bars: { + show: false, + lineWidth: 2, // in pixels + barWidth: 1, // in units of the x axis + fill: true, + fillColor: null, + align: "left", // or "center" + horizontal: false // when horizontal, left is now top + }, + shadowSize: 3 + }, + grid: { + show: true, + color: "#545454", // primary color used for outline and labels + backgroundColor: null, // null for transparent, else color + tickColor: "#dddddd", // color used for the ticks + labelMargin: 5, // in pixels + borderWidth: 2, // in pixels + borderColor: null, // set if different from the grid color + markings: null, // array of ranges or fn: axes -> array of ranges + markingsColor: "#f4f4f4", + markingsLineWidth: 2, + // interactive stuff + clickable: false, + hoverable: false, + autoHighlight: true, // highlight in case mouse is near + mouseActiveRadius: 10 // how far the mouse can be away to activate an item + }, + selection: { + mode: null, // one of null, "x", "y" or "xy" + color: "#e8cfac" + } + }, + canvas = null, // the canvas for the plot itself + overlay = null, // canvas for interactive stuff on top of plot + eventHolder = null, // jQuery object that events should be bound to + ctx = null, octx = null, + axes = { xaxis: {}, yaxis: {}, x2axis: {}, y2axis: {} }, + plotOffset = { left: 0, right: 0, top: 0, bottom: 0}, + canvasWidth = 0, canvasHeight = 0, + plotWidth = 0, plotHeight = 0, + hooks = { + processOptions: [], + processRawData: [], + processDatapoints: [], + draw: [], + bindEvents: [], + drawOverlay: [] + }, + plot = this, + // dedicated to storing data for buggy standard compliance cases + workarounds = {}; + + // public functions + plot.setData = setData; + plot.setupGrid = setupGrid; + plot.draw = draw; + plot.clearSelection = clearSelection; + plot.setSelection = setSelection; + plot.getSelection = getSelection; + plot.getCanvas = function() { return canvas; }; + plot.getPlotOffset = function() { return plotOffset; }; + plot.width = function () { return plotWidth; } + plot.height = function () { return plotHeight; } + plot.offset = function () { + var o = eventHolder.offset(); + o.left += plotOffset.left; + o.top += plotOffset.top; + return o; + }; + plot.getData = function() { return series; }; + plot.getAxes = function() { return axes; }; + plot.getOptions = function() { return options; }; + plot.highlight = highlight; + plot.unhighlight = unhighlight; + plot.triggerRedrawOverlay = triggerRedrawOverlay; + plot.pointOffset = function(point) { + return { left: parseInt(axisSpecToRealAxis(point, "xaxis").p2c(+point.x) + plotOffset.left), + top: parseInt(axisSpecToRealAxis(point, "yaxis").p2c(+point.y) + plotOffset.top) }; + } + + + // public attributes + plot.hooks = hooks; + + // initialize + initPlugins(plot); + parseOptions(options_); + constructCanvas(); + setData(data_); + setupGrid(); + draw(); + bindEvents(); + + + function executeHooks(hook, args) { + args = [plot].concat(args); + for (var i = 0; i < hook.length; ++i) + hook[i].apply(this, args); + } + + function initPlugins() { + for (var i = 0; i < plugins.length; ++i) { + var p = plugins[i]; + p.init(plot); + if (p.options) + $.extend(true, options, p.options); + } + } + + function parseOptions(opts) { + $.extend(true, options, opts); + if (options.grid.borderColor == null) + options.grid.borderColor = options.grid.color + // backwards compatibility, to be removed in future + if (options.xaxis.noTicks && options.xaxis.ticks == null) + options.xaxis.ticks = options.xaxis.noTicks; + if (options.yaxis.noTicks && options.yaxis.ticks == null) + options.yaxis.ticks = options.yaxis.noTicks; + if (options.grid.coloredAreas) + options.grid.markings = options.grid.coloredAreas; + if (options.grid.coloredAreasColor) + options.grid.markingsColor = options.grid.coloredAreasColor; + if (options.lines) + $.extend(true, options.series.lines, options.lines); + if (options.points) + $.extend(true, options.series.points, options.points); + if (options.bars) + $.extend(true, options.series.bars, options.bars); + if (options.shadowSize) + options.series.shadowSize = options.shadowSize; + + executeHooks(hooks.processOptions, [options]); + } + + function setData(d) { + series = parseData(d); + fillInSeriesOptions(); + processData(); + } + + function parseData(d) { + var res = []; + for (var i = 0; i < d.length; ++i) { + var s = $.extend(true, {}, options.series); + + if (d[i].data) { + s.data = d[i].data; // move the data instead of deep-copy + delete d[i].data; + + $.extend(true, s, d[i]); + + d[i].data = s.data; + } + else + s.data = d[i]; + res.push(s); + } + + return res; + } + + function axisSpecToRealAxis(obj, attr) { + var a = obj[attr]; + if (!a || a == 1) + return axes[attr]; + if (typeof a == "number") + return axes[attr.charAt(0) + a + attr.slice(1)]; + return a; // assume it's OK + } + + function fillInSeriesOptions() { + var i; + + // collect what we already got of colors + var neededColors = series.length, + usedColors = [], + assignedColors = []; + for (i = 0; i < series.length; ++i) { + var sc = series[i].color; + if (sc != null) { + --neededColors; + if (typeof sc == "number") + assignedColors.push(sc); + else + usedColors.push(parseColor(series[i].color)); + } + } + + // we might need to generate more colors if higher indices + // are assigned + for (i = 0; i < assignedColors.length; ++i) { + neededColors = Math.max(neededColors, assignedColors[i] + 1); + } + + // produce colors as needed + var colors = [], variation = 0; + i = 0; + while (colors.length < neededColors) { + var c; + if (options.colors.length == i) // check degenerate case + c = new Color(100, 100, 100); + else + c = parseColor(options.colors[i]); + + // vary color if needed + var sign = variation % 2 == 1 ? -1 : 1; + var factor = 1 + sign * Math.ceil(variation / 2) * 0.2; + c.scale(factor, factor, factor); + + // FIXME: if we're getting to close to something else, + // we should probably skip this one + colors.push(c); + + ++i; + if (i >= options.colors.length) { + i = 0; + ++variation; + } + } + + // fill in the options + var colori = 0, s; + for (i = 0; i < series.length; ++i) { + s = series[i]; + + // assign colors + if (s.color == null) { + s.color = colors[colori].toString(); + ++colori; + } + else if (typeof s.color == "number") + s.color = colors[s.color].toString(); + + // turn on lines automatically in case nothing is set + if (s.lines.show == null && !s.bars.show && !s.points.show) + s.lines.show = true; + + // setup axes + s.xaxis = axisSpecToRealAxis(s, "xaxis"); + s.yaxis = axisSpecToRealAxis(s, "yaxis"); + } + } + + function processData() { + var topSentry = Number.POSITIVE_INFINITY, + bottomSentry = Number.NEGATIVE_INFINITY, + i, j, k, m, length, + s, points, ps, x, y, axis; + + for (axis in axes) { + axes[axis].datamin = topSentry; + axes[axis].datamax = bottomSentry; + axes[axis].min = options[axis].min; + axes[axis].max = options[axis].max; + axes[axis].used = false; + } + + function updateAxis(axis, min, max) { + if (min < axis.datamin) + axis.datamin = min; + if (max > axis.datamax) + axis.datamax = max; + } + + for (i = 0; i < series.length; ++i) { + s = series[i]; + s.datapoints = { points: [] }; + + executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]); + } + + // first pass: clean and copy data + for (i = 0; i < series.length; ++i) { + s = series[i]; + + if (s.datapoints.pointsize != null) + continue; // already filled in + + var data = s.data, format = [], p; + + // determine the point size + if (s.bars.show) { + s.datapoints.pointsize = 3; + format.push({ d: 0 }); + } + else + s.datapoints.pointsize = 2; + + /* + // examine data to find out how to copy + for (j = 0; j < data.length; ++j) { + }*/ + + ps = s.datapoints.pointsize; + points = s.datapoints.points; + + insertSteps = s.lines.show && s.lines.steps; + s.xaxis.used = s.yaxis.used = true; + + for (j = k = 0; j < data.length; ++j, k += ps) { + p = data[j]; + + if (p != null) { + x = p[0]; + y = p[1]; + } + else + y = x = null; + + if (x != null) { + x = +x; // convert to number + if (isNaN(x)) + x = null; + } + + if (y != null) { + y = +y; // convert to number + if (isNaN(y)) + y = null; + } + + // check validity of point, making sure both are cleared + if (x == null && y != null) { + // extract min/max info before we whack + updateAxis(s.yaxis, y, y); + y = null; + } + + if (y == null && x != null) { + updateAxis(s.xaxis, x, x); + x = null; + } + + if (insertSteps && x != null && k > 0 + && points[k - ps] != null + && points[k - ps] != x && points[k - ps + 1] != y) { + points[k + 1] = points[k - ps + 1]; + points[k] = x; + + // copy the remainding from real point + for (m = 2; m < ps; ++m) + points[k + m] = p[m] == null ? format[m-2].d : p[m]; + k += ps; + } + + for (m = 2; m < ps; ++m) + points[k + m] = p == null || p[m] == null ? format[m-2].d : p[m]; + + points[k] = x; + points[k + 1] = y; + } + } + + for (i = 0; i < series.length; ++i) { + s = series[i]; + + executeHooks(hooks.processDatapoints, [ s, s.datapoints]); + } + + // second pass: find datamax/datamin for auto-scaling + for (i = 0; i < series.length; ++i) { + s = series[i]; + points = s.datapoints.points, + ps = s.datapoints.pointsize; + + var xmin = topSentry, ymin = topSentry, + xmax = bottomSentry, ymax = bottomSentry; + + for (j = 0; j < points.length; j += ps) { + x = points[j]; + + if (x == null) + continue; + + if (x < xmin) + xmin = x; + if (x > xmax) + xmax = x; + + y = points[j + 1]; + + if (y < ymin) + ymin = y; + if (y > ymax) + ymax = y; + } + + if (s.bars.show) { + // make sure we got room for the bar on the dancing floor + var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2; + if (s.bars.horizontal) { + ymin += delta; + ymax += delta + s.bars.barWidth; + } + else { + xmin += delta; + xmax += delta + s.bars.barWidth; + } + } + + updateAxis(s.xaxis, xmin, xmax); + updateAxis(s.yaxis, ymin, ymax); + } + + for (axis in axes) { + if (axes[axis].datamin == topSentry) + axes[axis].datamin = null; + if (axes[axis].datamax == bottomSentry) + axes[axis].datamax = null; + } + } + + function constructCanvas() { + function makeCanvas(width, height) { + var c = document.createElement('canvas'); + c.width = width; + c.height = height; + if ($.browser.msie) // excanvas hack + c = window.G_vmlCanvasManager.initElement(c); + return c; + } + + canvasWidth = target.width(); + canvasHeight = target.height(); + target.html(""); // clear target + if (target.css("position") == 'static') + target.css("position", "relative"); // for positioning labels and overlay + + if (canvasWidth <= 0 || canvasHeight <= 0) + throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight; + + if ($.browser.msie) // excanvas hack + window.G_vmlCanvasManager.init_(document); // make sure everything is setup + + // the canvas + canvas = $(makeCanvas(canvasWidth, canvasHeight)).appendTo(target).get(0); + ctx = canvas.getContext("2d"); + + // overlay canvas for interactive features + overlay = $(makeCanvas(canvasWidth, canvasHeight)).css({ position: 'absolute', left: 0, top: 0 }).appendTo(target).get(0); + octx = overlay.getContext("2d"); + octx.stroke(); + } + + function bindEvents() { + // we include the canvas in the event holder too, because IE 7 + // sometimes has trouble with the stacking order + eventHolder = $([overlay, canvas]); + + // bind events + if (options.selection.mode != null + || options.grid.hoverable) + eventHolder.mousemove(onMouseMove); + + if (options.selection.mode != null) + eventHolder.mousedown(onMouseDown); + + if (options.grid.clickable) + eventHolder.click(onClick); + + executeHooks(hooks.bindEvents, [eventHolder]); + } + + function setupGrid() { + function setTransformationHelpers(axis) { + var s, m; + + // add transformation helpers + if (axis == axes.xaxis || axis == axes.x2axis) { + // precompute how much the axis is scaling a point + // in canvas space + s = axis.scale = plotWidth / (axis.max - axis.min); + m = axis.min; + + // data point to canvas coordinate + axis.p2c = function (p) { return (p - m) * s; }; + // canvas coordinate to data point + axis.c2p = function (c) { return m + c / s; }; + } + else { + s = axis.scale = plotHeight / (axis.max - axis.min) + m = axis.max; + + axis.p2c = function (p) { return (m - p) * s; }; + axis.c2p = function (p) { return m - p / s; }; + } + } + + var axis; + for (axis in axes) + setRange(axes[axis], options[axis]); + + if (options.grid.show) { + for (axis in axes) { + prepareTickGeneration(axes[axis], options[axis]); + setTicks(axes[axis], options[axis]); + } + + setGridSpacing(); + } + else { + plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0; + plotWidth = canvasWidth; + plotHeight = canvasHeight; + } + + for (axis in axes) + setTransformationHelpers(axes[axis]); + + if (options.grid.show) + insertLabels(); + + insertLegend(); + } + + function setRange(axis, axisOptions) { + var min = +(axisOptions.min != null ? axisOptions.min : axis.datamin), + max = +(axisOptions.max != null ? axisOptions.max : axis.datamax); + + if (max - min == 0.0) { + // degenerate case + var widen = max == 0 ? 1 : 0.01; + + if (axisOptions.min == null) + min -= widen; + // alway widen max if we couldn't widen min to ensure we + // don't fall into min == max which doesn't work + if (axisOptions.max == null || axisOptions.min != null) + max += widen; + } + else { + // consider autoscaling + var margin = axisOptions.autoscaleMargin; + if (margin != null) { + if (axisOptions.min == null) { + min -= (max - min) * margin; + // make sure we don't go below zero if all values + // are positive + if (min < 0 && axis.datamin != null && axis.datamin >= 0) + min = 0; + } + if (axisOptions.max == null) { + max += (max - min) * margin; + if (max > 0 && axis.datamax != null && axis.datamax <= 0) + max = 0; + } + } + } + axis.min = min; + axis.max = max; + } + + function prepareTickGeneration(axis, axisOptions) { + // estimate number of ticks + var noTicks; + if (typeof axisOptions.ticks == "number" && axisOptions.ticks > 0) + noTicks = axisOptions.ticks; + else if (axis == axes.xaxis || axis == axes.x2axis) + noTicks = canvasWidth / 100; + else + noTicks = canvasHeight / 60; + + var delta = (axis.max - axis.min) / noTicks; + var size, generator, unit, formatter, i, magn, norm; + + if (axisOptions.mode == "time") { + // pretty handling of time + + // map of app. size of time units in milliseconds + var timeUnitSize = { + "second": 1000, + "minute": 60 * 1000, + "hour": 60 * 60 * 1000, + "day": 24 * 60 * 60 * 1000, + "month": 30 * 24 * 60 * 60 * 1000, + "year": 365.2425 * 24 * 60 * 60 * 1000 + }; + + + // the allowed tick sizes, after 1 year we use + // an integer algorithm + var spec = [ + [1, "second"], [2, "second"], [5, "second"], [10, "second"], + [30, "second"], + [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], + [30, "minute"], + [1, "hour"], [2, "hour"], [4, "hour"], + [8, "hour"], [12, "hour"], + [1, "day"], [2, "day"], [3, "day"], + [0.25, "month"], [0.5, "month"], [1, "month"], + [2, "month"], [3, "month"], [6, "month"], + [1, "year"] + ]; + + var minSize = 0; + if (axisOptions.minTickSize != null) { + if (typeof axisOptions.tickSize == "number") + minSize = axisOptions.tickSize; + else + minSize = axisOptions.minTickSize[0] * timeUnitSize[axisOptions.minTickSize[1]]; + } + + for (i = 0; i < spec.length - 1; ++i) + if (delta < (spec[i][0] * timeUnitSize[spec[i][1]] + + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2 + && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) + break; + size = spec[i][0]; + unit = spec[i][1]; + + // special-case the possibility of several years + if (unit == "year") { + magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10)); + norm = (delta / timeUnitSize.year) / magn; + if (norm < 1.5) + size = 1; + else if (norm < 3) + size = 2; + else if (norm < 7.5) + size = 5; + else + size = 10; + + size *= magn; + } + + if (axisOptions.tickSize) { + size = axisOptions.tickSize[0]; + unit = axisOptions.tickSize[1]; + } + + generator = function(axis) { + var ticks = [], + tickSize = axis.tickSize[0], unit = axis.tickSize[1], + d = new Date(axis.min); + + var step = tickSize * timeUnitSize[unit]; + + if (unit == "second") + d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize)); + if (unit == "minute") + d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize)); + if (unit == "hour") + d.setUTCHours(floorInBase(d.getUTCHours(), tickSize)); + if (unit == "month") + d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize)); + if (unit == "year") + d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize)); + + // reset smaller components + d.setUTCMilliseconds(0); + if (step >= timeUnitSize.minute) + d.setUTCSeconds(0); + if (step >= timeUnitSize.hour) + d.setUTCMinutes(0); + if (step >= timeUnitSize.day) + d.setUTCHours(0); + if (step >= timeUnitSize.day * 4) + d.setUTCDate(1); + if (step >= timeUnitSize.year) + d.setUTCMonth(0); + + + var carry = 0, v = Number.NaN, prev; + do { + prev = v; + v = d.getTime(); + ticks.push({ v: v, label: axis.tickFormatter(v, axis) }); + if (unit == "month") { + if (tickSize < 1) { + // a bit complicated - we'll divide the month + // up but we need to take care of fractions + // so we don't end up in the middle of a day + d.setUTCDate(1); + var start = d.getTime(); + d.setUTCMonth(d.getUTCMonth() + 1); + var end = d.getTime(); + d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize); + carry = d.getUTCHours(); + d.setUTCHours(0); + } + else + d.setUTCMonth(d.getUTCMonth() + tickSize); + } + else if (unit == "year") { + d.setUTCFullYear(d.getUTCFullYear() + tickSize); + } + else + d.setTime(v + step); + } while (v < axis.max && v != prev); + + return ticks; + }; + + formatter = function (v, axis) { + var d = new Date(v); + + // first check global format + if (axisOptions.timeformat != null) + return $.plot.formatDate(d, axisOptions.timeformat, axisOptions.monthNames); + + var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]]; + var span = axis.max - axis.min; + + if (t < timeUnitSize.minute) + fmt = "%h:%M:%S"; + else if (t < timeUnitSize.day) { + if (span < 2 * timeUnitSize.day) + fmt = "%h:%M"; + else + fmt = "%b %d %h:%M"; + } + else if (t < timeUnitSize.month) + fmt = "%b %d"; + else if (t < timeUnitSize.year) { + if (span < timeUnitSize.year) + fmt = "%b"; + else + fmt = "%b %y"; + } + else + fmt = "%y"; + + return $.plot.formatDate(d, fmt, axisOptions.monthNames); + }; + } + else { + // pretty rounding of base-10 numbers + var maxDec = axisOptions.tickDecimals; + var dec = -Math.floor(Math.log(delta) / Math.LN10); + if (maxDec != null && dec > maxDec) + dec = maxDec; + + magn = Math.pow(10, -dec); + norm = delta / magn; // norm is between 1.0 and 10.0 + + if (norm < 1.5) + size = 1; + else if (norm < 3) { + size = 2; + // special case for 2.5, requires an extra decimal + if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) { + size = 2.5; + ++dec; + } + } + else if (norm < 7.5) + size = 5; + else + size = 10; + + size *= magn; + + if (axisOptions.minTickSize != null && size < axisOptions.minTickSize) + size = axisOptions.minTickSize; + + if (axisOptions.tickSize != null) + size = axisOptions.tickSize; + + axis.tickDecimals = Math.max(0, (maxDec != null) ? maxDec : dec); + + generator = function (axis) { + var ticks = []; + + // spew out all possible ticks + var start = floorInBase(axis.min, axis.tickSize), + i = 0, v = Number.NaN, prev; + do { + prev = v; + v = start + i * axis.tickSize; + ticks.push({ v: v, label: axis.tickFormatter(v, axis) }); + ++i; + } while (v < axis.max && v != prev); + return ticks; + }; + + formatter = function (v, axis) { + return v.toFixed(axis.tickDecimals); + }; + } + + axis.tickSize = unit ? [size, unit] : size; + axis.tickGenerator = generator; + if ($.isFunction(axisOptions.tickFormatter)) + axis.tickFormatter = function (v, axis) { return "" + axisOptions.tickFormatter(v, axis); }; + else + axis.tickFormatter = formatter; + if (axisOptions.labelWidth != null) + axis.labelWidth = axisOptions.labelWidth; + if (axisOptions.labelHeight != null) + axis.labelHeight = axisOptions.labelHeight; + } + + function setTicks(axis, axisOptions) { + axis.ticks = []; + + if (!axis.used) + return; + + if (axisOptions.ticks == null) + axis.ticks = axis.tickGenerator(axis); + else if (typeof axisOptions.ticks == "number") { + if (axisOptions.ticks > 0) + axis.ticks = axis.tickGenerator(axis); + } + else if (axisOptions.ticks) { + var ticks = axisOptions.ticks; + + if ($.isFunction(ticks)) + // generate the ticks + ticks = ticks({ min: axis.min, max: axis.max }); + + // clean up the user-supplied ticks, copy them over + var i, v; + for (i = 0; i < ticks.length; ++i) { + var label = null; + var t = ticks[i]; + if (typeof t == "object") { + v = t[0]; + if (t.length > 1) + label = t[1]; + } + else + v = t; + if (label == null) + label = axis.tickFormatter(v, axis); + axis.ticks[i] = { v: v, label: label }; + } + } + + if (axisOptions.autoscaleMargin != null && axis.ticks.length > 0) { + // snap to ticks + if (axisOptions.min == null) + axis.min = Math.min(axis.min, axis.ticks[0].v); + if (axisOptions.max == null && axis.ticks.length > 1) + axis.max = Math.min(axis.max, axis.ticks[axis.ticks.length - 1].v); + } + } + + function setGridSpacing() { + function measureXLabels(axis) { + // to avoid measuring the widths of the labels, we + // construct fixed-size boxes and put the labels inside + // them, we don't need the exact figures and the + // fixed-size box content is easy to center + if (axis.labelWidth == null) + axis.labelWidth = canvasWidth / 6; + + // measure x label heights + if (axis.labelHeight == null) { + labels = []; + for (i = 0; i < axis.ticks.length; ++i) { + l = axis.ticks[i].label; + if (l) + labels.push('
' + l + '
'); + } + + axis.labelHeight = 0; + if (labels.length > 0) { + var dummyDiv = $('
' + + labels.join("") + '
').appendTo(target); + axis.labelHeight = dummyDiv.height(); + dummyDiv.remove(); + } + } + } + + function measureYLabels(axis) { + if (axis.labelWidth == null || axis.labelHeight == null) { + var i, labels = [], l; + // calculate y label dimensions + for (i = 0; i < axis.ticks.length; ++i) { + l = axis.ticks[i].label; + if (l) + labels.push('
' + l + '
'); + } + + if (labels.length > 0) { + var dummyDiv = $('
' + + labels.join("") + '
').appendTo(target); + if (axis.labelWidth == null) + axis.labelWidth = dummyDiv.width(); + if (axis.labelHeight == null) + axis.labelHeight = dummyDiv.find("div").height(); + dummyDiv.remove(); + } + + if (axis.labelWidth == null) + axis.labelWidth = 0; + if (axis.labelHeight == null) + axis.labelHeight = 0; + } + } + + // get the most space needed around the grid for things + // that may stick out + var maxOutset = options.grid.borderWidth; + for (i = 0; i < series.length; ++i) + maxOutset = Math.max(maxOutset, 2 * (series[i].points.radius + series[i].points.lineWidth/2)); + + plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = maxOutset; + + var margin = options.grid.labelMargin + options.grid.borderWidth; + + measureXLabels(axes.xaxis); + measureYLabels(axes.yaxis); + measureXLabels(axes.x2axis); + measureYLabels(axes.y2axis); + + if (axes.xaxis.labelHeight > 0) + plotOffset.bottom = Math.max(maxOutset, axes.xaxis.labelHeight + margin); + if (axes.yaxis.labelWidth > 0) + plotOffset.left = Math.max(maxOutset, axes.yaxis.labelWidth + margin); + + if (axes.x2axis.labelHeight > 0) + plotOffset.top = Math.max(maxOutset, axes.x2axis.labelHeight + margin); + + if (axes.y2axis.labelWidth > 0) + plotOffset.right = Math.max(maxOutset, axes.y2axis.labelWidth + margin); + + plotWidth = canvasWidth - plotOffset.left - plotOffset.right; + plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top; + } + + function draw() { + if (options.grid.show) + drawGrid(); + + for (var i = 0; i < series.length; ++i) + drawSeries(series[i]); + + executeHooks(hooks.draw, [ctx]); + } + + function extractRange(ranges, coord) { + var firstAxis = coord + "axis", + secondaryAxis = coord + "2axis", + axis, from, to, reverse; + + if (ranges[firstAxis]) { + axis = axes[firstAxis]; + from = ranges[firstAxis].from; + to = ranges[firstAxis].to; + } + else if (ranges[secondaryAxis]) { + axis = axes[secondaryAxis]; + from = ranges[secondaryAxis].from; + to = ranges[secondaryAxis].to; + } + else { + // backwards-compat stuff - to be removed in future + axis = axes[firstAxis]; + from = ranges[coord + "1"]; + to = ranges[coord + "2"]; + } + + // auto-reverse as an added bonus + if (from != null && to != null && from > to) + return { from: to, to: from, axis: axis }; + + return { from: from, to: to, axis: axis }; + } + + function drawGrid() { + var i; + + ctx.save(); + ctx.clearRect(0, 0, canvasWidth, canvasHeight); + ctx.translate(plotOffset.left, plotOffset.top); + + // draw background, if any + if (options.grid.backgroundColor) { + ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)"); + ctx.fillRect(0, 0, plotWidth, plotHeight); + } + + // draw markings + var markings = options.grid.markings; + if (markings) { + if ($.isFunction(markings)) + // xmin etc. are backwards-compatible, to be removed in future + markings = markings({ xmin: axes.xaxis.min, xmax: axes.xaxis.max, ymin: axes.yaxis.min, ymax: axes.yaxis.max, xaxis: axes.xaxis, yaxis: axes.yaxis, x2axis: axes.x2axis, y2axis: axes.y2axis }); + + for (i = 0; i < markings.length; ++i) { + var m = markings[i], + xrange = extractRange(m, "x"), + yrange = extractRange(m, "y"); + + // fill in missing + if (xrange.from == null) + xrange.from = xrange.axis.min; + if (xrange.to == null) + xrange.to = xrange.axis.max; + if (yrange.from == null) + yrange.from = yrange.axis.min; + if (yrange.to == null) + yrange.to = yrange.axis.max; + + // clip + if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max || + yrange.to < yrange.axis.min || yrange.from > yrange.axis.max) + continue; + + xrange.from = Math.max(xrange.from, xrange.axis.min); + xrange.to = Math.min(xrange.to, xrange.axis.max); + yrange.from = Math.max(yrange.from, yrange.axis.min); + yrange.to = Math.min(yrange.to, yrange.axis.max); + + if (xrange.from == xrange.to && yrange.from == yrange.to) + continue; + + // then draw + xrange.from = xrange.axis.p2c(xrange.from); + xrange.to = xrange.axis.p2c(xrange.to); + yrange.from = yrange.axis.p2c(yrange.from); + yrange.to = yrange.axis.p2c(yrange.to); + + if (xrange.from == xrange.to || yrange.from == yrange.to) { + // draw line + ctx.strokeStyle = m.color || options.grid.markingsColor; + ctx.beginPath(); + ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth; + //ctx.moveTo(Math.floor(xrange.from), yrange.from); + //ctx.lineTo(Math.floor(xrange.to), yrange.to); + ctx.moveTo(xrange.from, yrange.from); + ctx.lineTo(xrange.to, yrange.to); + ctx.stroke(); + } + else { + // fill area + ctx.fillStyle = m.color || options.grid.markingsColor; + ctx.fillRect(xrange.from, yrange.to, + xrange.to - xrange.from, + yrange.from - yrange.to); + } + } + } + + // draw the inner grid + ctx.lineWidth = 1; + ctx.strokeStyle = options.grid.tickColor; + ctx.beginPath(); + var v, axis = axes.xaxis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axes.xaxis.max) + continue; // skip those lying on the axes + + ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 0); + ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, plotHeight); + } + + axis = axes.yaxis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(0, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + ctx.lineTo(plotWidth, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + } + + axis = axes.x2axis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, -5); + ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 5); + } + + axis = axes.y2axis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(plotWidth-5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + ctx.lineTo(plotWidth+5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + } + + ctx.stroke(); + + if (options.grid.borderWidth) { + // draw border + var bw = options.grid.borderWidth; + ctx.lineWidth = bw; + ctx.strokeStyle = options.grid.borderColor; + ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw); + } + + ctx.restore(); + } + + function insertLabels() { + target.find(".tickLabels").remove(); + + var html = ['
']; + + function addLabels(axis, labelGenerator) { + for (var i = 0; i < axis.ticks.length; ++i) { + var tick = axis.ticks[i]; + if (!tick.label || tick.v < axis.min || tick.v > axis.max) + continue; + html.push(labelGenerator(tick, axis)); + } + } + + var margin = options.grid.labelMargin + options.grid.borderWidth; + + addLabels(axes.xaxis, function (tick, axis) { + return '
' + tick.label + "
"; + }); + + + addLabels(axes.yaxis, function (tick, axis) { + return '
' + tick.label + "
"; + }); + + addLabels(axes.x2axis, function (tick, axis) { + return '
' + tick.label + "
"; + }); + + addLabels(axes.y2axis, function (tick, axis) { + return '
' + tick.label + "
"; + }); + + html.push('
'); + + target.append(html.join("")); + } + + function drawSeries(series) { + if (series.lines.show) + drawSeriesLines(series); + if (series.bars.show) + drawSeriesBars(series); + if (series.points.show) + drawSeriesPoints(series); + } + + function drawSeriesLines(series) { + function plotLine(datapoints, xoffset, yoffset, axisx, axisy) { + var points = datapoints.points, + ps = datapoints.pointsize, + prevx = null, prevy = null; + + ctx.beginPath(); + for (var i = ps; i < points.length; i += ps) { + var x1 = points[i - ps], y1 = points[i - ps + 1], + x2 = points[i], y2 = points[i + 1]; + + if (x1 == null || x2 == null) + continue; + + // clip with ymin + if (y1 <= y2 && y1 < axisy.min) { + if (y2 < axisy.min) + continue; // line segment is outside + // compute new intersection point + x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.min; + } + else if (y2 <= y1 && y2 < axisy.min) { + if (y1 < axisy.min) + continue; + x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.min; + } + + // clip with ymax + if (y1 >= y2 && y1 > axisy.max) { + if (y2 > axisy.max) + continue; + x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.max; + } + else if (y2 >= y1 && y2 > axisy.max) { + if (y1 > axisy.max) + continue; + x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.max; + } + + // clip with xmin + if (x1 <= x2 && x1 < axisx.min) { + if (x2 < axisx.min) + continue; + y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.min; + } + else if (x2 <= x1 && x2 < axisx.min) { + if (x1 < axisx.min) + continue; + y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.min; + } + + // clip with xmax + if (x1 >= x2 && x1 > axisx.max) { + if (x2 > axisx.max) + continue; + y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.max; + } + else if (x2 >= x1 && x2 > axisx.max) { + if (x1 > axisx.max) + continue; + y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.max; + } + + if (x1 != prevx || y1 != prevy) + ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset); + + prevx = x2; + prevy = y2; + ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset); + } + ctx.stroke(); + } + + function plotLineArea(datapoints, axisx, axisy) { + var points = datapoints.points, + ps = datapoints.pointsize, + bottom = Math.min(Math.max(0, axisy.min), axisy.max), + top, lastX = 0, areaOpen = false; + + for (var i = ps; i < points.length; i += ps) { + var x1 = points[i - ps], y1 = points[i - ps + 1], + x2 = points[i], y2 = points[i + 1]; + + if (areaOpen && x1 != null && x2 == null) { + // close area + ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom)); + ctx.fill(); + areaOpen = false; + continue; + } + + if (x1 == null || x2 == null) + continue; + + // clip x values + + // clip with xmin + if (x1 <= x2 && x1 < axisx.min) { + if (x2 < axisx.min) + continue; + y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.min; + } + else if (x2 <= x1 && x2 < axisx.min) { + if (x1 < axisx.min) + continue; + y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.min; + } + + // clip with xmax + if (x1 >= x2 && x1 > axisx.max) { + if (x2 > axisx.max) + continue; + y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.max; + } + else if (x2 >= x1 && x2 > axisx.max) { + if (x1 > axisx.max) + continue; + y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.max; + } + + if (!areaOpen) { + // open area + ctx.beginPath(); + ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom)); + areaOpen = true; + } + + // now first check the case where both is outside + if (y1 >= axisy.max && y2 >= axisy.max) { + ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max)); + lastX = x2; + continue; + } + else if (y1 <= axisy.min && y2 <= axisy.min) { + ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min)); + lastX = x2; + continue; + } + + // else it's a bit more complicated, there might + // be two rectangles and two triangles we need to fill + // in; to find these keep track of the current x values + var x1old = x1, x2old = x2; + + // and clip the y values, without shortcutting + + // clip with ymin + if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) { + x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.min; + } + else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) { + x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.min; + } + + // clip with ymax + if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) { + x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.max; + } + else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) { + x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.max; + } + + + // if the x value was changed we got a rectangle + // to fill + if (x1 != x1old) { + if (y1 <= axisy.min) + top = axisy.min; + else + top = axisy.max; + + ctx.lineTo(axisx.p2c(x1old), axisy.p2c(top)); + ctx.lineTo(axisx.p2c(x1), axisy.p2c(top)); + } + + // fill the triangles + ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); + + // fill the other rectangle if it's there + if (x2 != x2old) { + if (y2 <= axisy.min) + top = axisy.min; + else + top = axisy.max; + + ctx.lineTo(axisx.p2c(x2), axisy.p2c(top)); + ctx.lineTo(axisx.p2c(x2old), axisy.p2c(top)); + } + + lastX = Math.max(x2, x2old); + } + + if (areaOpen) { + ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom)); + ctx.fill(); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + ctx.lineJoin = "round"; + + var lw = series.lines.lineWidth, + sw = series.shadowSize; + // FIXME: consider another form of shadow when filling is turned on + if (lw > 0 && sw > 0) { + // draw shadow as a thick and thin line with transparency + ctx.lineWidth = sw; + ctx.strokeStyle = "rgba(0,0,0,0.1)"; + // position shadow at angle from the mid of line + var angle = Math.PI/18; + plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis); + ctx.lineWidth = sw/2; + plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis); + } + + ctx.lineWidth = lw; + ctx.strokeStyle = series.color; + var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight); + if (fillStyle) { + ctx.fillStyle = fillStyle; + plotLineArea(series.datapoints, series.xaxis, series.yaxis); + } + + if (lw > 0) + plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis); + ctx.restore(); + } + + function drawSeriesPoints(series) { + function plotPoints(datapoints, radius, fillStyle, offset, circumference, axisx, axisy) { + var points = datapoints.points, ps = datapoints.pointsize; + + for (var i = 0; i < points.length; i += ps) { + var x = points[i], y = points[i + 1]; + if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) + continue; + + ctx.beginPath(); + ctx.arc(axisx.p2c(x), axisy.p2c(y) + offset, radius, 0, circumference, false); + if (fillStyle) { + ctx.fillStyle = fillStyle; + ctx.fill(); + } + ctx.stroke(); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + + var lw = series.lines.lineWidth, + sw = series.shadowSize, + radius = series.points.radius; + if (lw > 0 && sw > 0) { + // draw shadow in two steps + var w = sw / 2; + ctx.lineWidth = w; + ctx.strokeStyle = "rgba(0,0,0,0.1)"; + plotPoints(series.datapoints, radius, null, w + w/2, Math.PI, + series.xaxis, series.yaxis); + + ctx.strokeStyle = "rgba(0,0,0,0.2)"; + plotPoints(series.datapoints, radius, null, w/2, Math.PI, + series.xaxis, series.yaxis); + } + + ctx.lineWidth = lw; + ctx.strokeStyle = series.color; + plotPoints(series.datapoints, radius, + getFillStyle(series.points, series.color), 0, 2 * Math.PI, + series.xaxis, series.yaxis); + ctx.restore(); + } + + function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal) { + var left, right, bottom, top, + drawLeft, drawRight, drawTop, drawBottom, + tmp; + + if (horizontal) { + drawBottom = drawRight = drawTop = true; + drawLeft = false; + left = b; + right = x; + top = y + barLeft; + bottom = y + barRight; + + // account for negative bars + if (right < left) { + tmp = right; + right = left; + left = tmp; + drawLeft = true; + drawRight = false; + } + } + else { + drawLeft = drawRight = drawTop = true; + drawBottom = false; + left = x + barLeft; + right = x + barRight; + bottom = b; + top = y; + + // account for negative bars + if (top < bottom) { + tmp = top; + top = bottom; + bottom = tmp; + drawBottom = true; + drawTop = false; + } + } + + // clip + if (right < axisx.min || left > axisx.max || + top < axisy.min || bottom > axisy.max) + return; + + if (left < axisx.min) { + left = axisx.min; + drawLeft = false; + } + + if (right > axisx.max) { + right = axisx.max; + drawRight = false; + } + + if (bottom < axisy.min) { + bottom = axisy.min; + drawBottom = false; + } + + if (top > axisy.max) { + top = axisy.max; + drawTop = false; + } + + left = axisx.p2c(left); + bottom = axisy.p2c(bottom); + right = axisx.p2c(right); + top = axisy.p2c(top); + + // fill the bar + if (fillStyleCallback) { + c.beginPath(); + c.moveTo(left, bottom); + c.lineTo(left, top); + c.lineTo(right, top); + c.lineTo(right, bottom); + c.fillStyle = fillStyleCallback(bottom, top); + c.fill(); + } + + // draw outline + if (drawLeft || drawRight || drawTop || drawBottom) { + c.beginPath(); + + // FIXME: inline moveTo is buggy with excanvas + c.moveTo(left, bottom + offset); + if (drawLeft) + c.lineTo(left, top + offset); + else + c.moveTo(left, top + offset); + if (drawTop) + c.lineTo(right, top + offset); + else + c.moveTo(right, top + offset); + if (drawRight) + c.lineTo(right, bottom + offset); + else + c.moveTo(right, bottom + offset); + if (drawBottom) + c.lineTo(left, bottom + offset); + else + c.moveTo(left, bottom + offset); + c.stroke(); + } + } + + function drawSeriesBars(series) { + function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) { + var points = datapoints.points, ps = datapoints.pointsize; + + for (var i = 0; i < points.length; i += ps) { + if (points[i] == null) + continue; + drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + + // FIXME: figure out a way to add shadows (for instance along the right edge) + ctx.lineWidth = series.bars.lineWidth; + ctx.strokeStyle = series.color; + var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; + var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null; + plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis); + ctx.restore(); + } + + function getFillStyle(filloptions, seriesColor, bottom, top) { + var fill = filloptions.fill; + if (!fill) + return null; + + if (filloptions.fillColor) + return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor); + + var c = parseColor(seriesColor); + c.a = typeof fill == "number" ? fill : 0.4; + c.normalize(); + return c.toString(); + } + + function insertLegend() { + target.find(".legend").remove(); + + if (!options.legend.show) + return; + + var fragments = [], rowStarted = false, + lf = options.legend.labelFormatter, s, label; + for (i = 0; i < series.length; ++i) { + s = series[i]; + label = s.label; + if (!label) + continue; + + if (i % options.legend.noColumns == 0) { + if (rowStarted) + fragments.push(''); + fragments.push(''); + rowStarted = true; + } + + if (lf) + label = lf(label, s); + + fragments.push( + '
' + + '' + label + ''); + } + if (rowStarted) + fragments.push(''); + + if (fragments.length == 0) + return; + + var table = '' + fragments.join("") + '
'; + if (options.legend.container != null) + $(options.legend.container).html(table); + else { + var pos = "", + p = options.legend.position, + m = options.legend.margin; + if (m[0] == null) + m = [m, m]; + if (p.charAt(0) == "n") + pos += 'top:' + (m[1] + plotOffset.top) + 'px;'; + else if (p.charAt(0) == "s") + pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;'; + if (p.charAt(1) == "e") + pos += 'right:' + (m[0] + plotOffset.right) + 'px;'; + else if (p.charAt(1) == "w") + pos += 'left:' + (m[0] + plotOffset.left) + 'px;'; + var legend = $('
' + table.replace('style="', 'style="position:absolute;' + pos +';') + '
').appendTo(target); + if (options.legend.backgroundOpacity != 0.0) { + // put in the transparent background + // separately to avoid blended labels and + // label boxes + var c = options.legend.backgroundColor; + if (c == null) { + var tmp; + if (options.grid.backgroundColor && typeof options.grid.backgroundColor == "string") + tmp = options.grid.backgroundColor; + else + tmp = extractColor(legend); + c = parseColor(tmp).adjust(null, null, null, 1).toString(); + } + var div = legend.children(); + $('
').prependTo(legend).css('opacity', options.legend.backgroundOpacity); + } + } + } + + + // interactive features + + var lastMousePos = { pageX: null, pageY: null }, + selection = { + first: { x: -1, y: -1}, second: { x: -1, y: -1}, + show: false, + active: false + }, + highlights = [], + clickIsMouseUp = false, + redrawTimeout = null, + hoverTimeout = null; + + // returns the data item the mouse is over, or null if none is found + function findNearbyItem(mouseX, mouseY, seriesFilter) { + var maxDistance = options.grid.mouseActiveRadius, + lowestDistance = maxDistance * maxDistance + 1, + item = null, foundPoint = false, i, j; + + for (var i = 0; i < series.length; ++i) { + if (!seriesFilter(series[i])) + continue; + + var s = series[i], + axisx = s.xaxis, + axisy = s.yaxis, + points = s.datapoints.points, + ps = s.datapoints.pointsize, + mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster + my = axisy.c2p(mouseY), + maxx = maxDistance / axisx.scale, + maxy = maxDistance / axisy.scale; + + if (s.lines.show || s.points.show) { + for (j = 0; j < points.length; j += ps) { + var x = points[j], y = points[j + 1]; + if (x == null) + continue; + + // For points and lines, the cursor must be within a + // certain distance to the data point + if (x - mx > maxx || x - mx < -maxx || + y - my > maxy || y - my < -maxy) + continue; + + // We have to calculate distances in pixels, not in + // data units, because the scales of the axes may be different + var dx = Math.abs(axisx.p2c(x) - mouseX), + dy = Math.abs(axisy.p2c(y) - mouseY), + dist = dx * dx + dy * dy; // no idea in taking sqrt + if (dist < lowestDistance) { + lowestDistance = dist; + item = [i, j / ps]; + } + } + } + + if (s.bars.show && !item) { // no other point can be nearby + var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2, + barRight = barLeft + s.bars.barWidth; + + for (j = 0; j < points.length; j += ps) { + var x = points[j], y = points[j + 1], b = points[j + 2]; + if (x == null) + continue; + + // for a bar graph, the cursor must be inside the bar + if (series[i].bars.horizontal ? + (mx <= Math.max(b, x) && mx >= Math.min(b, x) && + my >= y + barLeft && my <= y + barRight) : + (mx >= x + barLeft && mx <= x + barRight && + my >= Math.min(b, y) && my <= Math.max(b, y))) + item = [i, j / ps]; + } + } + } + + if (item) { + i = item[0]; + j = item[1]; + + return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps), + dataIndex: j, + series: series[i], + seriesIndex: i }; + } + + return null; + } + + function onMouseMove(e) { + lastMousePos.pageX = e.pageX; + lastMousePos.pageY = e.pageY; + + if (options.grid.hoverable) + triggerClickHoverEvent("plothover", lastMousePos, + function (s) { return s["hoverable"] != false; }); + + if (selection.active) { + target.trigger("plotselecting", [ getSelection() ]); + + updateSelection(lastMousePos); + } + } + + function onMouseDown(e) { + if (e.which != 1) // only accept left-click + return; + + // cancel out any text selections + document.body.focus(); + + // prevent text selection and drag in old-school browsers + if (document.onselectstart !== undefined && workarounds.onselectstart == null) { + workarounds.onselectstart = document.onselectstart; + document.onselectstart = function () { return false; }; + } + if (document.ondrag !== undefined && workarounds.ondrag == null) { + workarounds.ondrag = document.ondrag; + document.ondrag = function () { return false; }; + } + + setSelectionPos(selection.first, e); + + lastMousePos.pageX = null; + selection.active = true; + $(document).one("mouseup", onSelectionMouseUp); + } + + function onClick(e) { + if (clickIsMouseUp) { + clickIsMouseUp = false; + return; + } + + triggerClickHoverEvent("plotclick", e, + function (s) { return s["clickable"] != false; }); + } + + // trigger click or hover event (they send the same parameters + // so we share their code) + function triggerClickHoverEvent(eventname, event, seriesFilter) { + var offset = eventHolder.offset(), + pos = { pageX: event.pageX, pageY: event.pageY }, + canvasX = event.pageX - offset.left - plotOffset.left, + canvasY = event.pageY - offset.top - plotOffset.top; + + if (axes.xaxis.used) + pos.x = axes.xaxis.c2p(canvasX); + if (axes.yaxis.used) + pos.y = axes.yaxis.c2p(canvasY); + if (axes.x2axis.used) + pos.x2 = axes.x2axis.c2p(canvasX); + if (axes.y2axis.used) + pos.y2 = axes.y2axis.c2p(canvasY); + + var item = findNearbyItem(canvasX, canvasY, seriesFilter); + + if (item) { + // fill in mouse pos for any listeners out there + item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left); + item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top); + } + + if (options.grid.autoHighlight) { + // clear auto-highlights + for (var i = 0; i < highlights.length; ++i) { + var h = highlights[i]; + if (h.auto == eventname && + !(item && h.series == item.series && h.point == item.datapoint)) + unhighlight(h.series, h.point); + } + + if (item) + highlight(item.series, item.datapoint, eventname); + } + + target.trigger(eventname, [ pos, item ]); + } + + function triggerRedrawOverlay() { + if (!redrawTimeout) + redrawTimeout = setTimeout(drawOverlay, 30); + } + + function drawOverlay() { + redrawTimeout = null; + + // draw highlights + octx.save(); + octx.clearRect(0, 0, canvasWidth, canvasHeight); + octx.translate(plotOffset.left, plotOffset.top); + + var i, hi; + for (i = 0; i < highlights.length; ++i) { + hi = highlights[i]; + + if (hi.series.bars.show) + drawBarHighlight(hi.series, hi.point); + else + drawPointHighlight(hi.series, hi.point); + } + + // draw selection + if (selection.show && selectionIsSane()) { + octx.strokeStyle = parseColor(options.selection.color).scale(null, null, null, 0.8).toString(); + octx.lineWidth = 1; + ctx.lineJoin = "round"; + octx.fillStyle = parseColor(options.selection.color).scale(null, null, null, 0.4).toString(); + + var x = Math.min(selection.first.x, selection.second.x), + y = Math.min(selection.first.y, selection.second.y), + w = Math.abs(selection.second.x - selection.first.x), + h = Math.abs(selection.second.y - selection.first.y); + + octx.fillRect(x, y, w, h); + octx.strokeRect(x, y, w, h); + } + octx.restore(); + + executeHooks(hooks.drawOverlay, [octx]); + } + + function highlight(s, point, auto) { + if (typeof s == "number") + s = series[s]; + + if (typeof point == "number") + point = s.data[point]; + + var i = indexOfHighlight(s, point); + if (i == -1) { + highlights.push({ series: s, point: point, auto: auto }); + + triggerRedrawOverlay(); + } + else if (!auto) + highlights[i].auto = false; + } + + function unhighlight(s, point) { + if (s == null && point == null) { + highlights = []; + triggerRedrawOverlay(); + } + + if (typeof s == "number") + s = series[s]; + + if (typeof point == "number") + point = s.data[point]; + + var i = indexOfHighlight(s, point); + if (i != -1) { + highlights.splice(i, 1); + + triggerRedrawOverlay(); + } + } + + function indexOfHighlight(s, p) { + for (var i = 0; i < highlights.length; ++i) { + var h = highlights[i]; + if (h.series == s && h.point[0] == p[0] + && h.point[1] == p[1]) + return i; + } + return -1; + } + + function drawPointHighlight(series, point) { + var x = point[0], y = point[1], + axisx = series.xaxis, axisy = series.yaxis; + + if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) + return; + + var pointRadius = series.points.radius + series.points.lineWidth / 2; + octx.lineWidth = pointRadius; + octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); + var radius = 1.5 * pointRadius; + octx.beginPath(); + octx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, false); + octx.stroke(); + } + + function drawBarHighlight(series, point) { + octx.lineWidth = series.bars.lineWidth; + octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); + var fillStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); + var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; + drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, + 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal); + } + + function getSelection() { + if (!selectionIsSane()) + return null; + + var x1 = Math.min(selection.first.x, selection.second.x), + x2 = Math.max(selection.first.x, selection.second.x), + y1 = Math.max(selection.first.y, selection.second.y), + y2 = Math.min(selection.first.y, selection.second.y); + + var r = {}; + if (axes.xaxis.used) + r.xaxis = { from: axes.xaxis.c2p(x1), to: axes.xaxis.c2p(x2) }; + if (axes.x2axis.used) + r.x2axis = { from: axes.x2axis.c2p(x1), to: axes.x2axis.c2p(x2) }; + if (axes.yaxis.used) + r.yaxis = { from: axes.yaxis.c2p(y1), to: axes.yaxis.c2p(y2) }; + if (axes.y2axis.used) + r.y2axis = { from: axes.y2axis.c2p(y1), to: axes.y2axis.c2p(y2) }; + return r; + } + + function triggerSelectedEvent() { + var r = getSelection(); + + target.trigger("plotselected", [ r ]); + + // backwards-compat stuff, to be removed in future + if (axes.xaxis.used && axes.yaxis.used) + target.trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]); + } + + function onSelectionMouseUp(e) { + // revert drag stuff for old-school browsers + if (document.onselectstart !== undefined) + document.onselectstart = workarounds.onselectstart; + if (document.ondrag !== undefined) + document.ondrag = workarounds.ondrag; + + // no more draggy-dee-drag + selection.active = false; + updateSelection(e); + + if (selectionIsSane()) { + triggerSelectedEvent(); + clickIsMouseUp = true; + } + else { + // this counts as a clear + target.trigger("plotunselected", [ ]); + target.trigger("plotselecting", [ null ]); + } + + return false; + } + + function setSelectionPos(pos, e) { + var offset = eventHolder.offset(); + pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plotWidth); + pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plotHeight); + + if (options.selection.mode == "y") { + if (pos == selection.first) + pos.x = 0; + else + pos.x = plotWidth; + } + + if (options.selection.mode == "x") { + if (pos == selection.first) + pos.y = 0; + else + pos.y = plotHeight; + } + } + + function updateSelection(pos) { + if (pos.pageX == null) + return; + + setSelectionPos(selection.second, pos); + if (selectionIsSane()) { + selection.show = true; + triggerRedrawOverlay(); + } + else + clearSelection(true); + } + + function clearSelection(preventEvent) { + if (selection.show) { + selection.show = false; + triggerRedrawOverlay(); + if (!preventEvent) + target.trigger("plotunselected", [ ]); + } + } + + function setSelection(ranges, preventEvent) { + var range; + + if (options.selection.mode == "y") { + selection.first.x = 0; + selection.second.x = plotWidth; + } + else { + range = extractRange(ranges, "x"); + + selection.first.x = range.axis.p2c(range.from); + selection.second.x = range.axis.p2c(range.to); + } + + if (options.selection.mode == "x") { + selection.first.y = 0; + selection.second.y = plotHeight; + } + else { + range = extractRange(ranges, "y"); + + selection.first.y = range.axis.p2c(range.from); + selection.second.y = range.axis.p2c(range.to); + } + + selection.show = true; + triggerRedrawOverlay(); + if (!preventEvent) + triggerSelectedEvent(); + } + + function selectionIsSane() { + var minSize = 5; + return Math.abs(selection.second.x - selection.first.x) >= minSize && + Math.abs(selection.second.y - selection.first.y) >= minSize; + } + + function getColorOrGradient(spec, bottom, top, defaultColor) { + if (typeof spec == "string") + return spec; + else { + // assume this is a gradient spec; IE currently only + // supports a simple vertical gradient properly, so that's + // what we support too + var gradient = ctx.createLinearGradient(0, top, 0, bottom); + + for (var i = 0, l = spec.colors.length; i < l; ++i) { + var c = spec.colors[i]; + gradient.addColorStop(i / (l - 1), typeof c == "string" ? c : parseColor(defaultColor).scale(c.brightness, c.brightness, c.brightness, c.opacity)); + } + + return gradient; + } + } + } + + $.plot = function(target, data, options) { + var plot = new Plot($(target), data, options, $.plot.plugins); + /*var t0 = new Date(); + var t1 = new Date(); + var tstr = "time used (msecs): " + (t1.getTime() - t0.getTime()) + if (window.console) + console.log(tstr); + else + alert(tstr);*/ + return plot; + }; + + $.plot.plugins = []; + + // returns a string with the date d formatted according to fmt + $.plot.formatDate = function(d, fmt, monthNames) { + var leftPad = function(n) { + n = "" + n; + return n.length == 1 ? "0" + n : n; + }; + + var r = []; + var escape = false; + if (monthNames == null) + monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + for (var i = 0; i < fmt.length; ++i) { + var c = fmt.charAt(i); + + if (escape) { + switch (c) { + case 'h': c = "" + d.getUTCHours(); break; + case 'H': c = leftPad(d.getUTCHours()); break; + case 'M': c = leftPad(d.getUTCMinutes()); break; + case 'S': c = leftPad(d.getUTCSeconds()); break; + case 'd': c = "" + d.getUTCDate(); break; + case 'm': c = "" + (d.getUTCMonth() + 1); break; + case 'y': c = "" + d.getUTCFullYear(); break; + case 'b': c = "" + monthNames[d.getUTCMonth()]; break; + } + r.push(c); + escape = false; + } + else { + if (c == "%") + escape = true; + else + r.push(c); + } + } + return r.join(""); + }; + + // round to nearby lower multiple of base + function floorInBase(n, base) { + return base * Math.floor(n / base); + } + + function clamp(min, value, max) { + if (value < min) + return min; + else if (value > max) + return max; + else + return value; + } + + // color helpers, inspiration from the jquery color animation + // plugin by John Resig + function Color (r, g, b, a) { + + var rgba = ['r','g','b','a']; + var x = 4; //rgba.length + + while (-1<--x) { + this[rgba[x]] = arguments[x] || ((x==3) ? 1.0 : 0); + } + + this.toString = function() { + if (this.a >= 1.0) { + return "rgb("+[this.r,this.g,this.b].join(",")+")"; + } else { + return "rgba("+[this.r,this.g,this.b,this.a].join(",")+")"; + } + }; + + this.scale = function(rf, gf, bf, af) { + x = 4; //rgba.length + while (-1<--x) { + if (arguments[x] != null) + this[rgba[x]] *= arguments[x]; + } + return this.normalize(); + }; + + this.adjust = function(rd, gd, bd, ad) { + x = 4; //rgba.length + while (-1<--x) { + if (arguments[x] != null) + this[rgba[x]] += arguments[x]; + } + return this.normalize(); + }; + + this.clone = function() { + return new Color(this.r, this.b, this.g, this.a); + }; + + var limit = function(val,minVal,maxVal) { + return Math.max(Math.min(val, maxVal), minVal); + }; + + this.normalize = function() { + this.r = clamp(0, parseInt(this.r), 255); + this.g = clamp(0, parseInt(this.g), 255); + this.b = clamp(0, parseInt(this.b), 255); + this.a = clamp(0, this.a, 1); + return this; + }; + + this.normalize(); + } + + var lookupColors = { + aqua:[0,255,255], + azure:[240,255,255], + beige:[245,245,220], + black:[0,0,0], + blue:[0,0,255], + brown:[165,42,42], + cyan:[0,255,255], + darkblue:[0,0,139], + darkcyan:[0,139,139], + darkgrey:[169,169,169], + darkgreen:[0,100,0], + darkkhaki:[189,183,107], + darkmagenta:[139,0,139], + darkolivegreen:[85,107,47], + darkorange:[255,140,0], + darkorchid:[153,50,204], + darkred:[139,0,0], + darksalmon:[233,150,122], + darkviolet:[148,0,211], + fuchsia:[255,0,255], + gold:[255,215,0], + green:[0,128,0], + indigo:[75,0,130], + khaki:[240,230,140], + lightblue:[173,216,230], + lightcyan:[224,255,255], + lightgreen:[144,238,144], + lightgrey:[211,211,211], + lightpink:[255,182,193], + lightyellow:[255,255,224], + lime:[0,255,0], + magenta:[255,0,255], + maroon:[128,0,0], + navy:[0,0,128], + olive:[128,128,0], + orange:[255,165,0], + pink:[255,192,203], + purple:[128,0,128], + violet:[128,0,128], + red:[255,0,0], + silver:[192,192,192], + white:[255,255,255], + yellow:[255,255,0] + }; + + function extractColor(element) { + var color, elem = element; + do { + color = elem.css("background-color").toLowerCase(); + // keep going until we find an element that has color, or + // we hit the body + if (color != '' && color != 'transparent') + break; + elem = elem.parent(); + } while (!$.nodeName(elem.get(0), "body")); + + // catch Safari's way of signalling transparent + if (color == "rgba(0, 0, 0, 0)") + return "transparent"; + + return color; + } + + // parse string, returns Color + function parseColor(str) { + var result; + + // Look for rgb(num,num,num) + if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str)) + return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10)); + + // Look for rgba(num,num,num,num) + if (result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str)) + return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10), parseFloat(result[4])); + + // Look for rgb(num%,num%,num%) + if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str)) + return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55); + + // Look for rgba(num%,num%,num%,num) + if (result = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str)) + return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55, parseFloat(result[4])); + + // Look for #a0b1c2 + if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str)) + return new Color(parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)); + + // Look for #fff + if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str)) + return new Color(parseInt(result[1]+result[1], 16), parseInt(result[2]+result[2], 16), parseInt(result[3]+result[3], 16)); + + // Otherwise, we're most likely dealing with a named color + var name = $.trim(str).toLowerCase(); + if (name == "transparent") + return new Color(255, 255, 255, 0); + else { + result = lookupColors[name]; + return new Color(result[0], result[1], result[2]); + } + } + +})(jQuery); diff --git a/admin/template/js/graphs.js b/admin/template/js/graphs.js new file mode 100644 index 000000000..a2ac95933 --- /dev/null +++ b/admin/template/js/graphs.js @@ -0,0 +1,77 @@ +// JavaScript Document +$(function () { + var d = [[1201647600000, 1521], [1201734000000, 1477], [1201820400000, 1442], [1201906800000, 1252], [1201993200000, 1236], [1202079600000, 1525], [1202166000000, 1477], [1202252400000, 1386], [1202338800000, 1409], [1202425200000, 1408], [1202511600000, 1237], [1202598000000, 1193], [1202684400000, 1357], [1202770800000, 1414], [1202857200000, 1393], [1202943600000, 1353], [1203030000000, 1364], [1203116400000, 1215], [1203202800000, 1214], [1203289200000, 1456], [1203375600000, 1399], [1203462000000, 1434], [1203548400000, 1348], [1203634800000, 1243], [1203721200000, 1126], [1203807600000, 1500]]; + + // first correct the timestamps - they are recorded as the daily + // midnights in UTC+0100, but Flot always displays dates in UTC + // so we have to add one hour to hit the midnights in the plot + for (var i = 0; i < d.length; ++i) + d[i][0] += 60 * 60 * 1000; + + // helper for returning the weekends in a period + function weekendAreas(axes) { + var markings = []; + var d = new Date(axes.xaxis.min); + // go to the first Saturday + d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) % 7)) + d.setUTCSeconds(0); + d.setUTCMinutes(0); + d.setUTCHours(0); + var i = d.getTime(); + do { + // when we don't set yaxis the rectangle automatically + // extends to infinity upwards and downwards + markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000 } }); + i += 7 * 24 * 60 * 60 * 1000; + } while (i < axes.xaxis.max); + + return markings; + } + + var options = { + xaxis: { mode: "time" }, + selection: { mode: "xy" }, + lines: { show: true, fill: 0.5 }, + points: { show: true }, + yaxis: { min: 800, max: 2000 }, + grid: { markings: weekendAreas, hoverable: true, clickable: true, labelMargin: 10 }, + colors: ["#639ecb"], //639ecb //e03c42 + shadowSize: 2 + }; + function showTooltip(x, y, contents) { + $('
' + contents + '
').css( { + position: 'absolute', + display: 'none', + top: y - 35, + left: x + 0, + color: '#333', + border: '1px solid #999', + padding: '2px', + 'background-color': '#EFEFEF', + opacity: 0.80 + }).appendTo("body").fadeIn(200); + } + + var plot = $.plot($("#placeholder"), [d], options); + var previousPoint = null; + $("#placeholder").bind("plothover", function (event, pos, item) { + $("#x").text(pos.x.toFixed(2)); + $("#y").text(pos.y.toFixed(2)); + if (item) { + if (previousPoint != item.datapoint) { + previousPoint = item.datapoint; + + $("#tooltip").remove(); + var x = item.datapoint[0].toFixed(2), + y = item.datapoint[1].toFixed(2); + + showTooltip(item.pageX, item.pageY, + y + "visitors"); + } + } + else { + $("#tooltip").remove(); + previousPoint = null; + } + }); +}); \ No newline at end of file diff --git a/admin/template/js/jquery.min.js b/admin/template/js/jquery.min.js new file mode 100644 index 000000000..b1ae21d8b --- /dev/null +++ b/admin/template/js/jquery.min.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/admin/template/js/pngfix.js b/admin/template/js/pngfix.js new file mode 100644 index 000000000..93e7ae899 --- /dev/null +++ b/admin/template/js/pngfix.js @@ -0,0 +1,208 @@ +/** +* DD_belatedPNG: Adds IE6 support: PNG images for CSS background-image and HTML . +* Author: Drew Diller +* Email: drew.diller@gmail.com +* URL: http://www.dillerdesign.com/experiment/DD_belatedPNG/ +* Version: 0.0.3a +* Licensed under the MIT License: http://dillerdesign.com/experiment/DD_belatedPNG/#license +* +* Example usage: +* DD_belatedPNG.addRule('.png_bg'); // argument is a CSS selector +**/ + +var DD_belatedPNG = { + ns: 'DD_belatedPNG', + createVmlNameSpace: function() { /* enable VML */ + if (document.namespaces && !document.namespaces[this.ns]) { + document.namespaces.add(this.ns, 'urn:schemas-microsoft-com:vml'); + } + }, + createVmlStyleSheet: function() { /* style VML, enable behaviors */ + /* + Just in case lots of other developers have added + lots of other stylesheets using document.createStyleSheet + and hit the 31-limit mark, let's not use that method! + further reading: http://msdn.microsoft.com/en-us/library/ms531194(VS.85).aspx + */ + var style = document.createElement('style'); + document.documentElement.firstChild.insertBefore(style, document.documentElement.firstChild.firstChild); + var styleSheet = style.styleSheet; + styleSheet.addRule(this.ns + '\\:*', '{behavior:url(#default#VML)}'); + styleSheet.addRule(this.ns + '\\:rect', 'position:absolute;'); + styleSheet.addRule('img.' + this.ns + '_sizeFinder', 'position:absolute; z-index:-1; visibility:hidden;'); + this.styleSheet = styleSheet; + }, + + /** + * This is the method to use in a document. + * @param {String} selector - REQUIRED - a CSS selector, such as '#doc .container' + **/ + fix: function(selector) { + var selectors = selector.split(','); /* multiple selectors supported, no need for multiple calls to this anymore */ + for (var i=0; i= document.body.clientWidth) {--size.W;} + for (var r=0; r<2; r++) { + this.rects[r].style.width = size.W + 'px'; + this.rects[r].style.height = size.H + 'px'; + this.rects[r].style.left = (size.L + size.bLW) + 'px'; + this.rects[r].style.top = (size.T + size.bTW) + 'px'; + } + var bg = {'X':0, 'Y':0}; + var figurePercentage = function(axis, position) { + var fraction = true; + switch(position) { + case 'left': + case 'top': + bg[axis] = 0; + break; + case 'center': + bg[axis] = .5; + break; + case 'right': + case 'bottom': + bg[axis] = 1; + break; + default: + if (position.search('%') != -1) { + bg[axis] = parseInt(position)*.01; + } + else { + fraction = false; + } + } + var horz = (axis == 'X'); + bg[axis] = Math.ceil(fraction ? ( (size[horz?'W':'H'] * bg[axis]) - (size[horz?'w':'h'] * bg[axis]) ) : parseInt(position)); + }; + for (var b in bg) { + figurePercentage(b, thisStyle['backgroundPosition'+b]); + } + this.imgFill.position = (bg.X/size.W) + ',' + (bg.Y/size.H); + var bgR = thisStyle.backgroundRepeat; + var dC = {'T':0, 'R':size.W, 'B':size.H, 'L':0}; // these are defaults for repeat of any kind + var altC = { 'X': {'b1':'L', 'b2':'R', 'd':'W'}, 'Y': {'b1':'T', 'b2':'B', 'd':'H'} }; + if (bgR != 'repeat') { + var c = {'T':bg.Y, 'R':bg.X+size.w+((size.bLW==0)?1:0), 'B':bg.Y+size.h, 'L':bg.X+((size.bLW==0)?1:0)}; // these are defaults for no-repeat - clips down to the image location - the parseInt() with the modulo operator is thanks to a rounding error somewhere + if (bgR.search('repeat-') != -1) { + var v = bgR.split('repeat-')[1].toUpperCase(); + c[altC[v].b1] = 0; + c[altC[v].b2] = size[altC[v].d]; + } + this.imgRect.style.clip = 'rect('+c.T+'px '+c.R+'px '+c.B+'px '+c.L+'px)'; + } + else { + this.imgRect.style.clip = 'rect(auto)'; + } + }; + this.handlePseudoHover = function() { + setTimeout(function() { /* wouldn't work as intended without setTimeout */ + self.runtimeStyle.backgroundColor = ''; + self.runtimeStyle.backgroundImage = ''; + self.updateVmlFill.call(self); + }, 1); + }; + + /* add change handlers */ + if (this.nodeName == 'A') { + this.attachEvent('onmouseleave', this.handlePseudoHover); + this.attachEvent('onmouseenter', this.handlePseudoHover); + } + + /* set up element */ + setTimeout(function() { + self.updateVmlFill.call(self); + }, 1); + + /* add change handlers */ + this.attachEvent('onpropertychange', this.interceptPropertyChanges); + var onResize = function() { + self.updateVmlDimensions.call(self); + }; + this.attachEvent('onresize', onResize); + this.attachEvent('onmove', onResize); + } +}; +DD_belatedPNG.createVmlNameSpace(); +DD_belatedPNG.createVmlStyleSheet(); \ No newline at end of file diff --git a/admin/template/js/ui.core.js b/admin/template/js/ui.core.js new file mode 100644 index 000000000..5493e0aeb --- /dev/null +++ b/admin/template/js/ui.core.js @@ -0,0 +1,519 @@ +/* + * jQuery UI 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI + */ +;jQuery.ui || (function($) { + +var _remove = $.fn.remove, + isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9); + +//Helper functions and ui object +$.ui = { + version: "1.7.2", + + // $.ui.plugin is deprecated. Use the proxy pattern instead. + plugin: { + add: function(module, option, set) { + var proto = $.ui[module].prototype; + for(var i in set) { + proto.plugins[i] = proto.plugins[i] || []; + proto.plugins[i].push([option, set[i]]); + } + }, + call: function(instance, name, args) { + var set = instance.plugins[name]; + if(!set || !instance.element[0].parentNode) { return; } + + for (var i = 0; i < set.length; i++) { + if (instance.options[set[i][0]]) { + set[i][1].apply(instance.element, args); + } + } + } + }, + + contains: function(a, b) { + return document.compareDocumentPosition + ? a.compareDocumentPosition(b) & 16 + : a !== b && a.contains(b); + }, + + hasScroll: function(el, a) { + + //If overflow is hidden, the element might have extra content, but the user wants to hide it + if ($(el).css('overflow') == 'hidden') { return false; } + + var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop', + has = false; + + if (el[scroll] > 0) { return true; } + + // TODO: determine which cases actually cause this to happen + // if the element doesn't have the scroll set, see if it's possible to + // set the scroll + el[scroll] = 1; + has = (el[scroll] > 0); + el[scroll] = 0; + return has; + }, + + isOverAxis: function(x, reference, size) { + //Determines when x coordinate is over "b" element axis + return (x > reference) && (x < (reference + size)); + }, + + isOver: function(y, x, top, left, height, width) { + //Determines when x, y coordinates is over "b" element + return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width); + }, + + keyCode: { + BACKSPACE: 8, + CAPS_LOCK: 20, + COMMA: 188, + CONTROL: 17, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + INSERT: 45, + LEFT: 37, + NUMPAD_ADD: 107, + NUMPAD_DECIMAL: 110, + NUMPAD_DIVIDE: 111, + NUMPAD_ENTER: 108, + NUMPAD_MULTIPLY: 106, + NUMPAD_SUBTRACT: 109, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SHIFT: 16, + SPACE: 32, + TAB: 9, + UP: 38 + } +}; + +// WAI-ARIA normalization +if (isFF2) { + var attr = $.attr, + removeAttr = $.fn.removeAttr, + ariaNS = "http://www.w3.org/2005/07/aaa", + ariaState = /^aria-/, + ariaRole = /^wairole:/; + + $.attr = function(elem, name, value) { + var set = value !== undefined; + + return (name == 'role' + ? (set + ? attr.call(this, elem, name, "wairole:" + value) + : (attr.apply(this, arguments) || "").replace(ariaRole, "")) + : (ariaState.test(name) + ? (set + ? elem.setAttributeNS(ariaNS, + name.replace(ariaState, "aaa:"), value) + : attr.call(this, elem, name.replace(ariaState, "aaa:"))) + : attr.apply(this, arguments))); + }; + + $.fn.removeAttr = function(name) { + return (ariaState.test(name) + ? this.each(function() { + this.removeAttributeNS(ariaNS, name.replace(ariaState, "")); + }) : removeAttr.call(this, name)); + }; +} + +//jQuery plugins +$.fn.extend({ + remove: function() { + // Safari has a native remove event which actually removes DOM elements, + // so we have to use triggerHandler instead of trigger (#3037). + $("*", this).add(this).each(function() { + $(this).triggerHandler("remove"); + }); + return _remove.apply(this, arguments ); + }, + + enableSelection: function() { + return this + .attr('unselectable', 'off') + .css('MozUserSelect', '') + .unbind('selectstart.ui'); + }, + + disableSelection: function() { + return this + .attr('unselectable', 'on') + .css('MozUserSelect', 'none') + .bind('selectstart.ui', function() { return false; }); + }, + + scrollParent: function() { + var scrollParent; + if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { + scrollParent = this.parents().filter(function() { + return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + }).eq(0); + } else { + scrollParent = this.parents().filter(function() { + return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + }).eq(0); + } + + return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; + } +}); + + +//Additional selectors +$.extend($.expr[':'], { + data: function(elem, i, match) { + return !!$.data(elem, match[3]); + }, + + focusable: function(element) { + var nodeName = element.nodeName.toLowerCase(), + tabIndex = $.attr(element, 'tabindex'); + return (/input|select|textarea|button|object/.test(nodeName) + ? !element.disabled + : 'a' == nodeName || 'area' == nodeName + ? element.href || !isNaN(tabIndex) + : !isNaN(tabIndex)) + // the element and all of its ancestors must be visible + // the browser may report that the area is hidden + && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length; + }, + + tabbable: function(element) { + var tabIndex = $.attr(element, 'tabindex'); + return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable'); + } +}); + + +// $.widget is a factory to create jQuery plugins +// taking some boilerplate code out of the plugin code +function getter(namespace, plugin, method, args) { + function getMethods(type) { + var methods = $[namespace][plugin][type] || []; + return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods); + } + + var methods = getMethods('getter'); + if (args.length == 1 && typeof args[0] == 'string') { + methods = methods.concat(getMethods('getterSetter')); + } + return ($.inArray(method, methods) != -1); +} + +$.widget = function(name, prototype) { + var namespace = name.split(".")[0]; + name = name.split(".")[1]; + + // create plugin method + $.fn[name] = function(options) { + var isMethodCall = (typeof options == 'string'), + args = Array.prototype.slice.call(arguments, 1); + + // prevent calls to internal methods + if (isMethodCall && options.substring(0, 1) == '_') { + return this; + } + + // handle getter methods + if (isMethodCall && getter(namespace, name, options, args)) { + var instance = $.data(this[0], name); + return (instance ? instance[options].apply(instance, args) + : undefined); + } + + // handle initialization and non-getter methods + return this.each(function() { + var instance = $.data(this, name); + + // constructor + (!instance && !isMethodCall && + $.data(this, name, new $[namespace][name](this, options))._init()); + + // method call + (instance && isMethodCall && $.isFunction(instance[options]) && + instance[options].apply(instance, args)); + }); + }; + + // create widget constructor + $[namespace] = $[namespace] || {}; + $[namespace][name] = function(element, options) { + var self = this; + + this.namespace = namespace; + this.widgetName = name; + this.widgetEventPrefix = $[namespace][name].eventPrefix || name; + this.widgetBaseClass = namespace + '-' + name; + + this.options = $.extend({}, + $.widget.defaults, + $[namespace][name].defaults, + $.metadata && $.metadata.get(element)[name], + options); + + this.element = $(element) + .bind('setData.' + name, function(event, key, value) { + if (event.target == element) { + return self._setData(key, value); + } + }) + .bind('getData.' + name, function(event, key) { + if (event.target == element) { + return self._getData(key); + } + }) + .bind('remove', function() { + return self.destroy(); + }); + }; + + // add widget prototype + $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype); + + // TODO: merge getter and getterSetter properties from widget prototype + // and plugin prototype + $[namespace][name].getterSetter = 'option'; +}; + +$.widget.prototype = { + _init: function() {}, + destroy: function() { + this.element.removeData(this.widgetName) + .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled') + .removeAttr('aria-disabled'); + }, + + option: function(key, value) { + var options = key, + self = this; + + if (typeof key == "string") { + if (value === undefined) { + return this._getData(key); + } + options = {}; + options[key] = value; + } + + $.each(options, function(key, value) { + self._setData(key, value); + }); + }, + _getData: function(key) { + return this.options[key]; + }, + _setData: function(key, value) { + this.options[key] = value; + + if (key == 'disabled') { + this.element + [value ? 'addClass' : 'removeClass']( + this.widgetBaseClass + '-disabled' + ' ' + + this.namespace + '-state-disabled') + .attr("aria-disabled", value); + } + }, + + enable: function() { + this._setData('disabled', false); + }, + disable: function() { + this._setData('disabled', true); + }, + + _trigger: function(type, event, data) { + var callback = this.options[type], + eventName = (type == this.widgetEventPrefix + ? type : this.widgetEventPrefix + type); + + event = $.Event(event); + event.type = eventName; + + // copy original event properties over to the new event + // this would happen if we could call $.event.fix instead of $.Event + // but we don't have a way to force an event to be fixed multiple times + if (event.originalEvent) { + for (var i = $.event.props.length, prop; i;) { + prop = $.event.props[--i]; + event[prop] = event.originalEvent[prop]; + } + } + + this.element.trigger(event, data); + + return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false + || event.isDefaultPrevented()); + } +}; + +$.widget.defaults = { + disabled: false +}; + + +/** Mouse Interaction Plugin **/ + +$.ui.mouse = { + _mouseInit: function() { + var self = this; + + this.element + .bind('mousedown.'+this.widgetName, function(event) { + return self._mouseDown(event); + }) + .bind('click.'+this.widgetName, function(event) { + if(self._preventClickEvent) { + self._preventClickEvent = false; + event.stopImmediatePropagation(); + return false; + } + }); + + // Prevent text selection in IE + if ($.browser.msie) { + this._mouseUnselectable = this.element.attr('unselectable'); + this.element.attr('unselectable', 'on'); + } + + this.started = false; + }, + + // TODO: make sure destroying one instance of mouse doesn't mess with + // other instances of mouse + _mouseDestroy: function() { + this.element.unbind('.'+this.widgetName); + + // Restore text selection in IE + ($.browser.msie + && this.element.attr('unselectable', this._mouseUnselectable)); + }, + + _mouseDown: function(event) { + // don't let more than one widget handle mouseStart + // TODO: figure out why we have to use originalEvent + event.originalEvent = event.originalEvent || {}; + if (event.originalEvent.mouseHandled) { return; } + + // we may have missed mouseup (out of window) + (this._mouseStarted && this._mouseUp(event)); + + this._mouseDownEvent = event; + + var self = this, + btnIsLeft = (event.which == 1), + elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false); + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { + return true; + } + + this.mouseDelayMet = !this.options.delay; + if (!this.mouseDelayMet) { + this._mouseDelayTimer = setTimeout(function() { + self.mouseDelayMet = true; + }, this.options.delay); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = (this._mouseStart(event) !== false); + if (!this._mouseStarted) { + event.preventDefault(); + return true; + } + } + + // these delegates are required to keep context + this._mouseMoveDelegate = function(event) { + return self._mouseMove(event); + }; + this._mouseUpDelegate = function(event) { + return self._mouseUp(event); + }; + $(document) + .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + // preventDefault() is used to prevent the selection of text here - + // however, in Safari, this causes select boxes not to be selectable + // anymore, so this fix is needed + ($.browser.safari || event.preventDefault()); + + event.originalEvent.mouseHandled = true; + return true; + }, + + _mouseMove: function(event) { + // IE mouseup check - mouseup happened when mouse was out of window + if ($.browser.msie && !event.button) { + return this._mouseUp(event); + } + + if (this._mouseStarted) { + this._mouseDrag(event); + return event.preventDefault(); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = + (this._mouseStart(this._mouseDownEvent, event) !== false); + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); + } + + return !this._mouseStarted; + }, + + _mouseUp: function(event) { + $(document) + .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + if (this._mouseStarted) { + this._mouseStarted = false; + this._preventClickEvent = (event.target == this._mouseDownEvent.target); + this._mouseStop(event); + } + + return false; + }, + + _mouseDistanceMet: function(event) { + return (Math.max( + Math.abs(this._mouseDownEvent.pageX - event.pageX), + Math.abs(this._mouseDownEvent.pageY - event.pageY) + ) >= this.options.distance + ); + }, + + _mouseDelayMet: function(event) { + return this.mouseDelayMet; + }, + + // These are placeholder methods, to be overriden by extending plugin + _mouseStart: function(event) {}, + _mouseDrag: function(event) {}, + _mouseStop: function(event) {}, + _mouseCapture: function(event) { return true; } +}; + +$.ui.mouse.defaults = { + cancel: null, + distance: 1, + delay: 0 +}; + +})(jQuery); diff --git a/admin/template/js/ui.datepicker.js b/admin/template/js/ui.datepicker.js new file mode 100644 index 000000000..397bbc014 --- /dev/null +++ b/admin/template/js/ui.datepicker.js @@ -0,0 +1,1630 @@ +/* + * jQuery UI Datepicker 1.7.1 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Datepicker + * + * Depends: + * ui.core.js + */ + +(function($) { // hide the namespace + +$.extend($.ui, { datepicker: { version: "1.7.1" } }); + +var PROP_NAME = 'datepicker'; + +/* Date picker manager. + Use the singleton instance of this class, $.datepicker, to interact with the date picker. + Settings for (groups of) date pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Datepicker() { + this.debug = false; // Change this to true to start debugging + this._curInst = null; // The current instance in use + this._keyEvent = false; // If the last event was a key event + this._disabledInputs = []; // List of date picker inputs that have been disabled + this._datepickerShowing = false; // True if the popup picker is showing , false if not + this._inDialog = false; // True if showing within a "dialog", false if not + this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division + this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class + this._appendClass = 'ui-datepicker-append'; // The name of the append marker class + this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class + this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class + this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class + this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class + this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class + this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + closeText: 'Done', // Display text for close link + prevText: '', // Display text for previous month link + nextText: '', // Display text for next month link + currentText: 'Today', // Display text for current month link + monthNames: ['January','February','March','April','May','June', + 'July','August','September','October','November','December'], // Names of months for drop-down and formatting + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting + dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday + dateFormat: 'mm/dd/yy', // See format options on parseDate + firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... + isRTL: false // True if right-to-left language, false if left-to-right + }; + this._defaults = { // Global defaults for all the date picker instances + showOn: 'focus', // 'focus' for popup on focus, + // 'button' for trigger button, or 'both' for either + showAnim: 'show', // Name of jQuery animation for popup + showOptions: {}, // Options for enhanced animations + defaultDate: null, // Used when field is blank: actual date, + // +/-number for offset from today, null for today + appendText: '', // Display text following the input box, e.g. showing the format + buttonText: '...', // Text for trigger button + buttonImage: '', // URL for trigger button image + buttonImageOnly: false, // True if the image appears alone, false if it appears on a button + hideIfNoPrevNext: false, // True to hide next/previous month links + // if not applicable, false to just disable them + navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links + gotoCurrent: false, // True if today link goes back to current selection instead + changeMonth: false, // True if month can be selected directly, false if only prev/next + changeYear: false, // True if year can be selected directly, false if only prev/next + showMonthAfterYear: false, // True if the year select precedes month, false for month then year + yearRange: '-10:+10', // Range of years to display in drop-down, + // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn) + showOtherMonths: false, // True to show dates in other months, false to leave blank + calculateWeek: this.iso8601Week, // How to calculate the week of the year, + // takes a Date and returns the number of the week for it + shortYearCutoff: '+10', // Short year values < this are in the current century, + // > this are in the previous century, + // string value starting with '+' for current year + value + minDate: null, // The earliest selectable date, or null for no limit + maxDate: null, // The latest selectable date, or null for no limit + duration: 'normal', // Duration of display/closure + beforeShowDay: null, // Function that takes a date and returns an array with + // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', + // [2] = cell title (optional), e.g. $.datepicker.noWeekends + beforeShow: null, // Function that takes an input field and + // returns a set of custom settings for the date picker + onSelect: null, // Define a callback function when a date is selected + onChangeMonthYear: null, // Define a callback function when the month or year is changed + onClose: null, // Define a callback function when the datepicker is closed + numberOfMonths: 1, // Number of months to show at a time + showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) + stepMonths: 1, // Number of months to step back/forward + stepBigMonths: 12, // Number of months to step back/forward for the big links + altField: '', // Selector for an alternate field to store selected dates into + altFormat: '', // The date format to use for the alternate field + constrainInput: true, // The input is constrained by the current date format + showButtonPanel: false // True to show button panel, false to not show it + }; + $.extend(this._defaults, this.regional['']); + this.dpDiv = $('
'); +} + +$.extend(Datepicker.prototype, { + /* Class name added to elements to indicate already configured with a date picker. */ + markerClassName: 'hasDatepicker', + + /* Debug logging (if enabled). */ + log: function () { + if (this.debug) + console.log.apply('', arguments); + }, + + /* Override the default settings for all instances of the date picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + /* Attach the date picker to a jQuery selection. + @param target element - the target input field or division or span + @param settings object - the new settings to use for this date picker instance (anonymous) */ + _attachDatepicker: function(target, settings) { + // check for settings on the control itself - in namespace 'date:' + var inlineSettings = null; + for (var attrName in this._defaults) { + var attrValue = target.getAttribute('date:' + attrName); + if (attrValue) { + inlineSettings = inlineSettings || {}; + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + var nodeName = target.nodeName.toLowerCase(); + var inline = (nodeName == 'div' || nodeName == 'span'); + if (!target.id) + target.id = 'dp' + (++this.uuid); + var inst = this._newInst($(target), inline); + inst.settings = $.extend({}, settings || {}, inlineSettings || {}); + if (nodeName == 'input') { + this._connectDatepicker(target, inst); + } else if (inline) { + this._inlineDatepicker(target, inst); + } + }, + + /* Create a new instance object. */ + _newInst: function(target, inline) { + var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars + return {id: id, input: target, // associated target + selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection + drawMonth: 0, drawYear: 0, // month being drawn + inline: inline, // is datepicker inline or not + dpDiv: (!inline ? this.dpDiv : // presentation div + $('
'))}; + }, + + /* Attach the date picker to an input field. */ + _connectDatepicker: function(target, inst) { + var input = $(target); + inst.trigger = $([]); + if (input.hasClass(this.markerClassName)) + return; + var appendText = this._get(inst, 'appendText'); + var isRTL = this._get(inst, 'isRTL'); + if (appendText) + input[isRTL ? 'before' : 'after']('' + appendText + ''); + var showOn = this._get(inst, 'showOn'); + if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field + input.focus(this._showDatepicker); + if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked + var buttonText = this._get(inst, 'buttonText'); + var buttonImage = this._get(inst, 'buttonImage'); + inst.trigger = $(this._get(inst, 'buttonImageOnly') ? + $('').addClass(this._triggerClass). + attr({ src: buttonImage, alt: buttonText, title: buttonText }) : + $('').addClass(this._triggerClass). + html(buttonImage == '' ? buttonText : $('').attr( + { src:buttonImage, alt:buttonText, title:buttonText }))); + input[isRTL ? 'before' : 'after'](inst.trigger); + inst.trigger.click(function() { + if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target) + $.datepicker._hideDatepicker(); + else + $.datepicker._showDatepicker(target); + return false; + }); + } + input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress). + bind("setData.datepicker", function(event, key, value) { + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key) { + return this._get(inst, key); + }); + $.data(target, PROP_NAME, inst); + }, + + /* Attach an inline date picker to a div. */ + _inlineDatepicker: function(target, inst) { + var divSpan = $(target); + if (divSpan.hasClass(this.markerClassName)) + return; + divSpan.addClass(this.markerClassName).append(inst.dpDiv). + bind("setData.datepicker", function(event, key, value){ + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key){ + return this._get(inst, key); + }); + $.data(target, PROP_NAME, inst); + this._setDate(inst, this._getDefaultDate(inst)); + this._updateDatepicker(inst); + this._updateAlternate(inst); + }, + + /* Pop-up the date picker in a "dialog" box. + @param input element - ignored + @param dateText string - the initial date to display (in the current format) + @param onSelect function - the function(dateText) to call when a date is selected + @param settings object - update the dialog date picker instance's settings (anonymous object) + @param pos int[2] - coordinates for the dialog's position within the screen or + event - with x/y coordinates or + leave empty for default (screen centre) + @return the manager object */ + _dialogDatepicker: function(input, dateText, onSelect, settings, pos) { + var inst = this._dialogInst; // internal instance + if (!inst) { + var id = 'dp' + (++this.uuid); + this._dialogInput = $(''); + this._dialogInput.keydown(this._doKeyDown); + $('body').append(this._dialogInput); + inst = this._dialogInst = this._newInst(this._dialogInput, false); + inst.settings = {}; + $.data(this._dialogInput[0], PROP_NAME, inst); + } + extendRemove(inst.settings, settings || {}); + this._dialogInput.val(dateText); + + this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); + if (!this._pos) { + var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; + var scrollY = document.documentElement.scrollTop || document.body.scrollTop; + this._pos = // should use actual width/height below + [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; + } + + // move input on screen for focus, but hidden behind dialog + this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px'); + inst.settings.onSelect = onSelect; + this._inDialog = true; + this.dpDiv.addClass(this._dialogClass); + this._showDatepicker(this._dialogInput[0]); + if ($.blockUI) + $.blockUI(this.dpDiv); + $.data(this._dialogInput[0], PROP_NAME, inst); + return this; + }, + + /* Detach a datepicker from its control. + @param target element - the target input field or division or span */ + _destroyDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + $.removeData(target, PROP_NAME); + if (nodeName == 'input') { + inst.trigger.remove(); + $target.siblings('.' + this._appendClass).remove().end(). + removeClass(this.markerClassName). + unbind('focus', this._showDatepicker). + unbind('keydown', this._doKeyDown). + unbind('keypress', this._doKeyPress); + } else if (nodeName == 'div' || nodeName == 'span') + $target.removeClass(this.markerClassName).empty(); + }, + + /* Enable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _enableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = false; + inst.trigger.filter("button"). + each(function() { this.disabled = false; }).end(). + filter("img"). + css({opacity: '1.0', cursor: ''}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().removeClass('ui-state-disabled'); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + }, + + /* Disable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _disableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = true; + inst.trigger.filter("button"). + each(function() { this.disabled = true; }).end(). + filter("img"). + css({opacity: '0.5', cursor: 'default'}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().addClass('ui-state-disabled'); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + this._disabledInputs[this._disabledInputs.length] = target; + }, + + /* Is the first field in a jQuery collection disabled as a datepicker? + @param target element - the target input field or division or span + @return boolean - true if disabled, false if enabled */ + _isDisabledDatepicker: function(target) { + if (!target) { + return false; + } + for (var i = 0; i < this._disabledInputs.length; i++) { + if (this._disabledInputs[i] == target) + return true; + } + return false; + }, + + /* Retrieve the instance data for the target control. + @param target element - the target input field or division or span + @return object - the associated instance data + @throws error if a jQuery problem getting data */ + _getInst: function(target) { + try { + return $.data(target, PROP_NAME); + } + catch (err) { + throw 'Missing instance data for this datepicker'; + } + }, + + /* Update the settings for a date picker attached to an input field or division. + @param target element - the target input field or division or span + @param name object - the new settings to update or + string - the name of the setting to change or + @param value any - the new value for the setting (omit if above is an object) */ + _optionDatepicker: function(target, name, value) { + var settings = name || {}; + if (typeof name == 'string') { + settings = {}; + settings[name] = value; + } + var inst = this._getInst(target); + if (inst) { + if (this._curInst == inst) { + this._hideDatepicker(null); + } + extendRemove(inst.settings, settings); + var date = new Date(); + extendRemove(inst, {rangeStart: null, // start of range + endDay: null, endMonth: null, endYear: null, // end of range + selectedDay: date.getDate(), selectedMonth: date.getMonth(), + selectedYear: date.getFullYear(), // starting point + currentDay: date.getDate(), currentMonth: date.getMonth(), + currentYear: date.getFullYear(), // current selection + drawMonth: date.getMonth(), drawYear: date.getFullYear()}); // month being drawn + this._updateDatepicker(inst); + } + }, + + // change method deprecated + _changeDatepicker: function(target, name, value) { + this._optionDatepicker(target, name, value); + }, + + /* Redraw the date picker attached to an input field or division. + @param target element - the target input field or division or span */ + _refreshDatepicker: function(target) { + var inst = this._getInst(target); + if (inst) { + this._updateDatepicker(inst); + } + }, + + /* Set the dates for a jQuery selection. + @param target element - the target input field or division or span + @param date Date - the new date + @param endDate Date - the new end date for a range (optional) */ + _setDateDatepicker: function(target, date, endDate) { + var inst = this._getInst(target); + if (inst) { + this._setDate(inst, date, endDate); + this._updateDatepicker(inst); + this._updateAlternate(inst); + } + }, + + /* Get the date(s) for the first entry in a jQuery selection. + @param target element - the target input field or division or span + @return Date - the current date or + Date[2] - the current dates for a range */ + _getDateDatepicker: function(target) { + var inst = this._getInst(target); + if (inst && !inst.inline) + this._setDateFromField(inst); + return (inst ? this._getDate(inst) : null); + }, + + /* Handle keystrokes. */ + _doKeyDown: function(event) { + var inst = $.datepicker._getInst(event.target); + var handled = true; + var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); + inst._keyEvent = true; + if ($.datepicker._datepickerShowing) + switch (event.keyCode) { + case 9: $.datepicker._hideDatepicker(null, ''); + break; // hide on tab out + case 13: var sel = $('td.' + $.datepicker._dayOverClass + + ', td.' + $.datepicker._currentClass, inst.dpDiv); + if (sel[0]) + $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); + else + $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration')); + return false; // don't submit the form + break; // select the value on enter + case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration')); + break; // hide on escape + case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // previous month/year on page up/+ ctrl + case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // next month/year on page down/+ ctrl + case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); + handled = event.ctrlKey || event.metaKey; + break; // clear on ctrl or command +end + case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); + handled = event.ctrlKey || event.metaKey; + break; // current on ctrl or command +home + case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); + handled = event.ctrlKey || event.metaKey; + // -1 day on ctrl or command +left + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +left on Mac + break; + case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // -1 week on ctrl or command +up + case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); + handled = event.ctrlKey || event.metaKey; + // +1 day on ctrl or command +right + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +right + break; + case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // +1 week on ctrl or command +down + default: handled = false; + } + else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home + $.datepicker._showDatepicker(this); + else { + handled = false; + } + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }, + + /* Filter entered characters - based on date format. */ + _doKeyPress: function(event) { + var inst = $.datepicker._getInst(event.target); + if ($.datepicker._get(inst, 'constrainInput')) { + var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); + var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); + return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); + } + }, + + /* Pop-up the date picker for a given input field. + @param input element - the input field attached to the date picker or + event - if triggered by focus */ + _showDatepicker: function(input) { + input = input.target || input; + if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger + input = $('input', input.parentNode)[0]; + if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here + return; + var inst = $.datepicker._getInst(input); + var beforeShow = $.datepicker._get(inst, 'beforeShow'); + extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {})); + $.datepicker._hideDatepicker(null, ''); + $.datepicker._lastInput = input; + $.datepicker._setDateFromField(inst); + if ($.datepicker._inDialog) // hide cursor + input.value = ''; + if (!$.datepicker._pos) { // position below input + $.datepicker._pos = $.datepicker._findPos(input); + $.datepicker._pos[1] += input.offsetHeight; // add the height + } + var isFixed = false; + $(input).parents().each(function() { + isFixed |= $(this).css('position') == 'fixed'; + return !isFixed; + }); + if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled + $.datepicker._pos[0] -= document.documentElement.scrollLeft; + $.datepicker._pos[1] -= document.documentElement.scrollTop; + } + var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; + $.datepicker._pos = null; + inst.rangeStart = null; + // determine sizing offscreen + inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); + $.datepicker._updateDatepicker(inst); + // fix width for dynamic number of date pickers + // and adjust position before showing + offset = $.datepicker._checkOffset(inst, offset, isFixed); + inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? + 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', + left: offset.left + 'px', top: offset.top + 'px'}); + if (!inst.inline) { + var showAnim = $.datepicker._get(inst, 'showAnim') || 'show'; + var duration = $.datepicker._get(inst, 'duration'); + var postProcess = function() { + $.datepicker._datepickerShowing = true; + if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems + $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4, + height: inst.dpDiv.height() + 4}); + }; + if ($.effects && $.effects[showAnim]) + inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[showAnim](duration, postProcess); + if (duration == '') + postProcess(); + if (inst.input[0].type != 'hidden') + inst.input[0].focus(); + $.datepicker._curInst = inst; + } + }, + + /* Generate the date picker content. */ + _updateDatepicker: function(inst) { + var dims = {width: inst.dpDiv.width() + 4, + height: inst.dpDiv.height() + 4}; + var self = this; + inst.dpDiv.empty().append(this._generateHTML(inst)) + .find('iframe.ui-datepicker-cover'). + css({width: dims.width, height: dims.height}) + .end() + .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a') + .bind('mouseout', function(){ + $(this).removeClass('ui-state-hover'); + if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover'); + if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover'); + }) + .bind('mouseover', function(){ + if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) { + $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + $(this).addClass('ui-state-hover'); + if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover'); + if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover'); + } + }) + .end() + .find('.' + this._dayOverClass + ' a') + .trigger('mouseover') + .end(); + var numMonths = this._getNumberOfMonths(inst); + var cols = numMonths[1]; + var width = 17; + if (cols > 1) { + inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); + } else { + inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); + } + inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + + 'Class']('ui-datepicker-multi'); + inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + + 'Class']('ui-datepicker-rtl'); + if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst) + $(inst.input[0]).focus(); + }, + + /* Check positioning to remain on screen. */ + _checkOffset: function(inst, offset, isFixed) { + var dpWidth = inst.dpDiv.outerWidth(); + var dpHeight = inst.dpDiv.outerHeight(); + var inputWidth = inst.input ? inst.input.outerWidth() : 0; + var inputHeight = inst.input ? inst.input.outerHeight() : 0; + var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft(); + var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop(); + + offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); + offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; + offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; + + // now check if datepicker is showing outside window viewport - move to a better place if so. + offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0; + offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0; + + return offset; + }, + + /* Find an object's position on the screen. */ + _findPos: function(obj) { + while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) { + obj = obj.nextSibling; + } + var position = $(obj).offset(); + return [position.left, position.top]; + }, + + /* Hide the date picker from view. + @param input element - the input field attached to the date picker + @param duration string - the duration over which to close the date picker */ + _hideDatepicker: function(input, duration) { + var inst = this._curInst; + if (!inst || (input && inst != $.data(input, PROP_NAME))) + return; + if (inst.stayOpen) + this._selectDate('#' + inst.id, this._formatDate(inst, + inst.currentDay, inst.currentMonth, inst.currentYear)); + inst.stayOpen = false; + if (this._datepickerShowing) { + duration = (duration != null ? duration : this._get(inst, 'duration')); + var showAnim = this._get(inst, 'showAnim'); + var postProcess = function() { + $.datepicker._tidyDialog(inst); + }; + if (duration != '' && $.effects && $.effects[showAnim]) + inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), + duration, postProcess); + else + inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' : + (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess); + if (duration == '') + this._tidyDialog(inst); + var onClose = this._get(inst, 'onClose'); + if (onClose) + onClose.apply((inst.input ? inst.input[0] : null), + [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback + this._datepickerShowing = false; + this._lastInput = null; + if (this._inDialog) { + this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); + if ($.blockUI) { + $.unblockUI(); + $('body').append(this.dpDiv); + } + } + this._inDialog = false; + } + this._curInst = null; + }, + + /* Tidy up after a dialog display. */ + _tidyDialog: function(inst) { + inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); + }, + + /* Close date picker if clicked elsewhere. */ + _checkExternalClick: function(event) { + if (!$.datepicker._curInst) + return; + var $target = $(event.target); + if (($target.parents('#' + $.datepicker._mainDivId).length == 0) && + !$target.hasClass($.datepicker.markerClassName) && + !$target.hasClass($.datepicker._triggerClass) && + $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI)) + $.datepicker._hideDatepicker(null, ''); + }, + + /* Adjust one of the date sub-fields. */ + _adjustDate: function(id, offset, period) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._isDisabledDatepicker(target[0])) { + return; + } + this._adjustInstDate(inst, offset + + (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning + period); + this._updateDatepicker(inst); + }, + + /* Action for current link. */ + _gotoToday: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._get(inst, 'gotoCurrent') && inst.currentDay) { + inst.selectedDay = inst.currentDay; + inst.drawMonth = inst.selectedMonth = inst.currentMonth; + inst.drawYear = inst.selectedYear = inst.currentYear; + } + else { + var date = new Date(); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + } + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Action for selecting a new month/year. */ + _selectMonthYear: function(id, select, period) { + var target = $(id); + var inst = this._getInst(target[0]); + inst._selectingMonthYear = false; + inst['selected' + (period == 'M' ? 'Month' : 'Year')] = + inst['draw' + (period == 'M' ? 'Month' : 'Year')] = + parseInt(select.options[select.selectedIndex].value,10); + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Restore input focus after not changing month/year. */ + _clickMonthYear: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + if (inst.input && inst._selectingMonthYear && !$.browser.msie) + inst.input[0].focus(); + inst._selectingMonthYear = !inst._selectingMonthYear; + }, + + /* Action for selecting a day. */ + _selectDay: function(id, month, year, td) { + var target = $(id); + if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { + return; + } + var inst = this._getInst(target[0]); + inst.selectedDay = inst.currentDay = $('a', td).html(); + inst.selectedMonth = inst.currentMonth = month; + inst.selectedYear = inst.currentYear = year; + if (inst.stayOpen) { + inst.endDay = inst.endMonth = inst.endYear = null; + } + this._selectDate(id, this._formatDate(inst, + inst.currentDay, inst.currentMonth, inst.currentYear)); + if (inst.stayOpen) { + inst.rangeStart = this._daylightSavingAdjust( + new Date(inst.currentYear, inst.currentMonth, inst.currentDay)); + this._updateDatepicker(inst); + } + }, + + /* Erase the input field and hide the date picker. */ + _clearDate: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + inst.stayOpen = false; + inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null; + this._selectDate(target, ''); + }, + + /* Update the input field with the selected date. */ + _selectDate: function(id, dateStr) { + var target = $(id); + var inst = this._getInst(target[0]); + dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); + if (inst.input) + inst.input.val(dateStr); + this._updateAlternate(inst); + var onSelect = this._get(inst, 'onSelect'); + if (onSelect) + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback + else if (inst.input) + inst.input.trigger('change'); // fire the change event + if (inst.inline) + this._updateDatepicker(inst); + else if (!inst.stayOpen) { + this._hideDatepicker(null, this._get(inst, 'duration')); + this._lastInput = inst.input[0]; + if (typeof(inst.input[0]) != 'object') + inst.input[0].focus(); // restore focus + this._lastInput = null; + } + }, + + /* Update any alternate field to synchronise with the main field. */ + _updateAlternate: function(inst) { + var altField = this._get(inst, 'altField'); + if (altField) { // update alternate field too + var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); + var date = this._getDate(inst); + dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); + $(altField).each(function() { $(this).val(dateStr); }); + } + }, + + /* Set as beforeShowDay function to prevent selection of weekends. + @param date Date - the date to customise + @return [boolean, string] - is this date selectable?, what is its CSS class? */ + noWeekends: function(date) { + var day = date.getDay(); + return [(day > 0 && day < 6), '']; + }, + + /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. + @param date Date - the date to get the week for + @return number - the number of the week within the year that contains this date */ + iso8601Week: function(date) { + var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); + var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan + var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7 + firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday + if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary + checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year + return $.datepicker.iso8601Week(checkDate); + } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year + firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7; + if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary + return 1; + } + } + return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date + }, + + /* Parse a string value into a date object. + See formatDate below for the possible formats. + + @param format string - the expected format of the date + @param value string - the date in the above format + @param settings Object - attributes include: + shortYearCutoff number - the cutoff year for determining the century (optional) + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return Date - the extracted date value or null if value is blank */ + parseDate: function (format, value, settings) { + if (format == null || value == null) + throw 'Invalid arguments'; + value = (typeof value == 'object' ? value.toString() : value + ''); + if (value == '') + return null; + var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + var year = -1; + var month = -1; + var day = -1; + var doy = -1; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Extract a number from the string value + var getNumber = function(match) { + lookAhead(match); + var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2))); + var size = origSize; + var num = 0; + while (size > 0 && iValue < value.length && + value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') { + num = num * 10 + parseInt(value.charAt(iValue++),10); + size--; + } + if (size == origSize) + throw 'Missing number at position ' + iValue; + return num; + }; + // Extract a name from the string value and convert to an index + var getName = function(match, shortNames, longNames) { + var names = (lookAhead(match) ? longNames : shortNames); + var size = 0; + for (var j = 0; j < names.length; j++) + size = Math.max(size, names[j].length); + var name = ''; + var iInit = iValue; + while (size > 0 && iValue < value.length) { + name += value.charAt(iValue++); + for (var i = 0; i < names.length; i++) + if (name == names[i]) + return i + 1; + size--; + } + throw 'Unknown name at position ' + iInit; + }; + // Confirm that a literal character matches the string value + var checkLiteral = function() { + if (value.charAt(iValue) != format.charAt(iFormat)) + throw 'Unexpected literal at position ' + iValue; + iValue++; + }; + var iValue = 0; + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + checkLiteral(); + else + switch (format.charAt(iFormat)) { + case 'd': + day = getNumber('d'); + break; + case 'D': + getName('D', dayNamesShort, dayNames); + break; + case 'o': + doy = getNumber('o'); + break; + case 'm': + month = getNumber('m'); + break; + case 'M': + month = getName('M', monthNamesShort, monthNames); + break; + case 'y': + year = getNumber('y'); + break; + case '@': + var date = new Date(getNumber('@')); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case "'": + if (lookAhead("'")) + checkLiteral(); + else + literal = true; + break; + default: + checkLiteral(); + } + } + if (year == -1) + year = new Date().getFullYear(); + else if (year < 100) + year += new Date().getFullYear() - new Date().getFullYear() % 100 + + (year <= shortYearCutoff ? 0 : -100); + if (doy > -1) { + month = 1; + day = doy; + do { + var dim = this._getDaysInMonth(year, month - 1); + if (day <= dim) + break; + month++; + day -= dim; + } while (true); + } + var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); + if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) + throw 'Invalid date'; // E.g. 31/02/* + return date; + }, + + /* Standard date formats. */ + ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) + COOKIE: 'D, dd M yy', + ISO_8601: 'yy-mm-dd', + RFC_822: 'D, d M y', + RFC_850: 'DD, dd-M-y', + RFC_1036: 'D, d M y', + RFC_1123: 'D, d M yy', + RFC_2822: 'D, d M yy', + RSS: 'D, d M y', // RFC 822 + TIMESTAMP: '@', + W3C: 'yy-mm-dd', // ISO 8601 + + /* Format a date object into a string value. + The format can be combinations of the following: + d - day of month (no leading zero) + dd - day of month (two digit) + o - day of year (no leading zeros) + oo - day of year (three digit) + D - day name short + DD - day name long + m - month of year (no leading zero) + mm - month of year (two digit) + M - month name short + MM - month name long + y - year (two digit) + yy - year (four digit) + @ - Unix timestamp (ms since 01/01/1970) + '...' - literal text + '' - single quote + + @param format string - the desired format of the date + @param date Date - the date value to format + @param settings Object - attributes include: + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return string - the date in the above format */ + formatDate: function (format, date, settings) { + if (!date) + return ''; + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Format a number, with leading zero if necessary + var formatNumber = function(match, value, len) { + var num = '' + value; + if (lookAhead(match)) + while (num.length < len) + num = '0' + num; + return num; + }; + // Format a name, short or long as requested + var formatName = function(match, value, shortNames, longNames) { + return (lookAhead(match) ? longNames[value] : shortNames[value]); + }; + var output = ''; + var literal = false; + if (date) + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + output += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': + output += formatNumber('d', date.getDate(), 2); + break; + case 'D': + output += formatName('D', date.getDay(), dayNamesShort, dayNames); + break; + case 'o': + var doy = date.getDate(); + for (var m = date.getMonth() - 1; m >= 0; m--) + doy += this._getDaysInMonth(date.getFullYear(), m); + output += formatNumber('o', doy, 3); + break; + case 'm': + output += formatNumber('m', date.getMonth() + 1, 2); + break; + case 'M': + output += formatName('M', date.getMonth(), monthNamesShort, monthNames); + break; + case 'y': + output += (lookAhead('y') ? date.getFullYear() : + (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); + break; + case '@': + output += date.getTime(); + break; + case "'": + if (lookAhead("'")) + output += "'"; + else + literal = true; + break; + default: + output += format.charAt(iFormat); + } + } + return output; + }, + + /* Extract all possible characters from the date format. */ + _possibleChars: function (format) { + var chars = ''; + var literal = false; + for (var iFormat = 0; iFormat < format.length; iFormat++) + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + chars += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': case 'm': case 'y': case '@': + chars += '0123456789'; + break; + case 'D': case 'M': + return null; // Accept anything + case "'": + if (lookAhead("'")) + chars += "'"; + else + literal = true; + break; + default: + chars += format.charAt(iFormat); + } + return chars; + }, + + /* Get a setting value, defaulting if necessary. */ + _get: function(inst, name) { + return inst.settings[name] !== undefined ? + inst.settings[name] : this._defaults[name]; + }, + + /* Parse existing date and initialise date picker. */ + _setDateFromField: function(inst) { + var dateFormat = this._get(inst, 'dateFormat'); + var dates = inst.input ? inst.input.val() : null; + inst.endDay = inst.endMonth = inst.endYear = null; + var date = defaultDate = this._getDefaultDate(inst); + var settings = this._getFormatConfig(inst); + try { + date = this.parseDate(dateFormat, dates, settings) || defaultDate; + } catch (event) { + this.log(event); + date = defaultDate; + } + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + inst.currentDay = (dates ? date.getDate() : 0); + inst.currentMonth = (dates ? date.getMonth() : 0); + inst.currentYear = (dates ? date.getFullYear() : 0); + this._adjustInstDate(inst); + }, + + /* Retrieve the default date shown on opening. */ + _getDefaultDate: function(inst) { + var date = this._determineDate(this._get(inst, 'defaultDate'), new Date()); + var minDate = this._getMinMaxDate(inst, 'min', true); + var maxDate = this._getMinMaxDate(inst, 'max'); + date = (minDate && date < minDate ? minDate : date); + date = (maxDate && date > maxDate ? maxDate : date); + return date; + }, + + /* A date may be specified as an exact value or a relative one. */ + _determineDate: function(date, defaultDate) { + var offsetNumeric = function(offset) { + var date = new Date(); + date.setDate(date.getDate() + offset); + return date; + }; + var offsetString = function(offset, getDaysInMonth) { + var date = new Date(); + var year = date.getFullYear(); + var month = date.getMonth(); + var day = date.getDate(); + var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; + var matches = pattern.exec(offset); + while (matches) { + switch (matches[2] || 'd') { + case 'd' : case 'D' : + day += parseInt(matches[1],10); break; + case 'w' : case 'W' : + day += parseInt(matches[1],10) * 7; break; + case 'm' : case 'M' : + month += parseInt(matches[1],10); + day = Math.min(day, getDaysInMonth(year, month)); + break; + case 'y': case 'Y' : + year += parseInt(matches[1],10); + day = Math.min(day, getDaysInMonth(year, month)); + break; + } + matches = pattern.exec(offset); + } + return new Date(year, month, day); + }; + date = (date == null ? defaultDate : + (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) : + (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date))); + date = (date && date.toString() == 'Invalid Date' ? defaultDate : date); + if (date) { + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + } + return this._daylightSavingAdjust(date); + }, + + /* Handle switch to/from daylight saving. + Hours may be non-zero on daylight saving cut-over: + > 12 when midnight changeover, but then cannot generate + midnight datetime, so jump to 1AM, otherwise reset. + @param date (Date) the date to check + @return (Date) the corrected date */ + _daylightSavingAdjust: function(date) { + if (!date) return null; + date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); + return date; + }, + + /* Set the date(s) directly. */ + _setDate: function(inst, date, endDate) { + var clear = !(date); + var origMonth = inst.selectedMonth; + var origYear = inst.selectedYear; + date = this._determineDate(date, new Date()); + inst.selectedDay = inst.currentDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear(); + if (origMonth != inst.selectedMonth || origYear != inst.selectedYear) + this._notifyChange(inst); + this._adjustInstDate(inst); + if (inst.input) { + inst.input.val(clear ? '' : this._formatDate(inst)); + } + }, + + /* Retrieve the date(s) directly. */ + _getDate: function(inst) { + var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : + this._daylightSavingAdjust(new Date( + inst.currentYear, inst.currentMonth, inst.currentDay))); + return startDate; + }, + + /* Generate the HTML for the current state of the date picker. */ + _generateHTML: function(inst) { + var today = new Date(); + today = this._daylightSavingAdjust( + new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time + var isRTL = this._get(inst, 'isRTL'); + var showButtonPanel = this._get(inst, 'showButtonPanel'); + var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); + var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); + var numMonths = this._getNumberOfMonths(inst); + var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); + var stepMonths = this._get(inst, 'stepMonths'); + var stepBigMonths = this._get(inst, 'stepBigMonths'); + var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); + var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : + new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + var minDate = this._getMinMaxDate(inst, 'min', true); + var maxDate = this._getMinMaxDate(inst, 'max'); + var drawMonth = inst.drawMonth - showCurrentAtPos; + var drawYear = inst.drawYear; + if (drawMonth < 0) { + drawMonth += 12; + drawYear--; + } + if (maxDate) { + var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), + maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate())); + maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); + while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { + drawMonth--; + if (drawMonth < 0) { + drawMonth = 11; + drawYear--; + } + } + } + inst.drawMonth = drawMonth; + inst.drawYear = drawYear; + var prevText = this._get(inst, 'prevText'); + prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), + this._getFormatConfig(inst))); + var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? + '' + prevText + '' : + (hideIfNoPrevNext ? '' : '' + prevText + '')); + var nextText = this._get(inst, 'nextText'); + nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), + this._getFormatConfig(inst))); + var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? + '' + nextText + '' : + (hideIfNoPrevNext ? '' : '' + nextText + '')); + var currentText = this._get(inst, 'currentText'); + var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); + currentText = (!navigationAsDateFormat ? currentText : + this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); + var controls = (!inst.inline ? '' : ''); + var buttonPanel = (showButtonPanel) ? '
' + (isRTL ? controls : '') + + (this._isInRange(inst, gotoDate) ? '' : '') + (isRTL ? '' : controls) + '
' : ''; + var firstDay = parseInt(this._get(inst, 'firstDay'),10); + firstDay = (isNaN(firstDay) ? 0 : firstDay); + var dayNames = this._get(inst, 'dayNames'); + var dayNamesShort = this._get(inst, 'dayNamesShort'); + var dayNamesMin = this._get(inst, 'dayNamesMin'); + var monthNames = this._get(inst, 'monthNames'); + var monthNamesShort = this._get(inst, 'monthNamesShort'); + var beforeShowDay = this._get(inst, 'beforeShowDay'); + var showOtherMonths = this._get(inst, 'showOtherMonths'); + var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; + var endDate = inst.endDay ? this._daylightSavingAdjust( + new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate; + var defaultDate = this._getDefaultDate(inst); + var html = ''; + for (var row = 0; row < numMonths[0]; row++) { + var group = ''; + for (var col = 0; col < numMonths[1]; col++) { + var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); + var cornerClass = ' ui-corner-all'; + var calender = ''; + if (isMultiMonth) { + calender += '
'; + } + calender += '
' + + (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + + (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, + selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers + '
' + + ''; + var thead = ''; + for (var dow = 0; dow < 7; dow++) { // days of the week + var day = (dow + firstDay) % 7; + thead += '= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' + + '' + dayNamesMin[day] + ''; + } + calender += thead + ''; + var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); + if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) + inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); + var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; + var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate + var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); + for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows + calender += ''; + var tbody = ''; + for (var dow = 0; dow < 7; dow++) { // create date picker days + var daySettings = (beforeShowDay ? + beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); + var otherMonth = (printDate.getMonth() != drawMonth); + var unselectable = otherMonth || !daySettings[0] || + (minDate && printDate < minDate) || (maxDate && printDate > maxDate); + tbody += ''; // display for this month + printDate.setDate(printDate.getDate() + 1); + printDate = this._daylightSavingAdjust(printDate); + } + calender += tbody + ''; + } + drawMonth++; + if (drawMonth > 11) { + drawMonth = 0; + drawYear++; + } + calender += '
' + // actions + (otherMonth ? (showOtherMonths ? printDate.getDate() : ' ') : // display for other months + (unselectable ? '' + printDate.getDate() + '' : '' + printDate.getDate() + '')) + '
' + (isMultiMonth ? '
' + + ((numMonths[0] > 0 && col == numMonths[1]-1) ? '
' : '') : ''); + group += calender; + } + html += group; + } + html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ? + '' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, + selectedDate, secondary, monthNames, monthNamesShort) { + minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate); + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '
'; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '' + monthNames[drawMonth] + ' '; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += ''; + } + if (!showMonthAfterYear) + html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? ' ' : ''); + // year selection + if (secondary || !changeYear) + html += '' + drawYear + ''; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var year = 0; + var endYear = 0; + if (years.length != 2) { + year = drawYear - 10; + endYear = drawYear + 10; + } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') { + year = drawYear + parseInt(years[0], 10); + endYear = drawYear + parseInt(years[1], 10); + } else { + year = parseInt(years[0], 10); + endYear = parseInt(years[1], 10); + } + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + html += ''; + } + if (showMonthAfterYear) + html += (secondary || changeMonth || changeYear ? ' ' : '') + monthHtml; + html += '
'; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate: function(inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._daylightSavingAdjust(new Date(year, month, day)); + // ensure it is within the bounds set + var minDate = this._getMinMaxDate(inst, 'min', true); + var maxDate = this._getMinMaxDate(inst, 'max'); + date = (minDate && date < minDate ? minDate : date); + date = (maxDate && date > maxDate ? maxDate : date); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Notify change of month/year. */ + _notifyChange: function(inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths: function(inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */ + _getMinMaxDate: function(inst, minMax, checkRange) { + var date = this._determineDate(this._get(inst, minMax + 'Date'), null); + return (!checkRange || !inst.rangeStart ? date : + (!date || inst.rangeStart > date ? inst.rangeStart : date)); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - new Date(year, month, 32).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date( + curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(inst, date) { + // during range selection, use minimum of selected date and range start + var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust( + new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay))); + newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate); + var minDate = newMinDate || this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate)); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig: function(inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff: shortYearCutoff, + dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), + monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate: function(inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } +}); + +/* jQuery extend now ignores nulls! */ +function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; +}; + +/* Determine whether an object is an array. */ +function isArray(a) { + return (a && (($.browser.safari && typeof a == 'object' && a.length) || + (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); +}; + +/* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ +$.fn.datepicker = function(options){ + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find('body').append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function() { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); +}; + +$.datepicker = new Datepicker(); // singleton instance +$.datepicker.initialized = false; +$.datepicker.uuid = new Date().getTime(); +$.datepicker.version = "1.7.1"; + +// Workaround for #4055 +// Add another global to avoid noConflict issues with inline event handlers +window.DP_jQuery = $; + +})(jQuery); diff --git a/admin/template/js/ui.dialog.js b/admin/template/js/ui.dialog.js new file mode 100644 index 000000000..fdd5b26df --- /dev/null +++ b/admin/template/js/ui.dialog.js @@ -0,0 +1,671 @@ +/* + * jQuery UI Dialog 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * ui.core.js + * ui.draggable.js + * ui.resizable.js + */ +(function($) { + +var setDataSwitch = { + dragStart: "start.draggable", + drag: "drag.draggable", + dragStop: "stop.draggable", + maxHeight: "maxHeight.resizable", + minHeight: "minHeight.resizable", + maxWidth: "maxWidth.resizable", + minWidth: "minWidth.resizable", + resizeStart: "start.resizable", + resize: "drag.resizable", + resizeStop: "stop.resizable" + }, + + uiDialogClasses = + 'ui-dialog ' + + 'ui-widget ' + + 'ui-widget-content ' + + 'ui-corner-all '; + +$.widget("ui.dialog", { + + _init: function() { + this.originalTitle = this.element.attr('title'); + + var self = this, + options = this.options, + + title = options.title || this.originalTitle || ' ', + titleId = $.ui.dialog.getTitleId(this.element), + + uiDialog = (this.uiDialog = $('
')) + .appendTo(document.body) + .hide() + .addClass(uiDialogClasses + options.dialogClass) + .css({ + position: 'absolute', + overflow: 'hidden', + zIndex: options.zIndex + }) + // setting tabIndex makes the div focusable + // setting outline to 0 prevents a border on focus in Mozilla + .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { + (options.closeOnEscape && event.keyCode + && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event)); + }) + .attr({ + role: 'dialog', + 'aria-labelledby': titleId + }) + .mousedown(function(event) { + self.moveToTop(false, event); + }), + + uiDialogContent = this.element + .show() + .removeAttr('title') + .addClass( + 'ui-dialog-content ' + + 'ui-widget-content') + .appendTo(uiDialog), + + uiDialogTitlebar = (this.uiDialogTitlebar = $('
')) + .addClass( + 'ui-dialog-titlebar ' + + 'ui-widget-header ' + + 'ui-corner-all ' + + 'ui-helper-clearfix' + ) + .prependTo(uiDialog), + + uiDialogTitlebarClose = $('') + .addClass( + 'ui-dialog-titlebar-close ' + + 'ui-corner-all' + ) + .attr('role', 'button') + .hover( + function() { + uiDialogTitlebarClose.addClass('ui-state-hover'); + }, + function() { + uiDialogTitlebarClose.removeClass('ui-state-hover'); + } + ) + .focus(function() { + uiDialogTitlebarClose.addClass('ui-state-focus'); + }) + .blur(function() { + uiDialogTitlebarClose.removeClass('ui-state-focus'); + }) + .mousedown(function(ev) { + ev.stopPropagation(); + }) + .click(function(event) { + self.close(event); + return false; + }) + .appendTo(uiDialogTitlebar), + + uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('')) + .addClass( + 'ui-icon ' + + 'ui-icon-closethick' + ) + .text(options.closeText) + .appendTo(uiDialogTitlebarClose), + + uiDialogTitle = $('') + .addClass('ui-dialog-title') + .attr('id', titleId) + .html(title) + .prependTo(uiDialogTitlebar); + + uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); + + (options.draggable && $.fn.draggable && this._makeDraggable()); + (options.resizable && $.fn.resizable && this._makeResizable()); + + this._createButtons(options.buttons); + this._isOpen = false; + + (options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe()); + (options.autoOpen && this.open()); + + }, + + destroy: function() { + (this.overlay && this.overlay.destroy()); + this.uiDialog.hide(); + this.element + .unbind('.dialog') + .removeData('dialog') + .removeClass('ui-dialog-content ui-widget-content') + .hide().appendTo('body'); + this.uiDialog.remove(); + + (this.originalTitle && this.element.attr('title', this.originalTitle)); + }, + + close: function(event) { + var self = this; + + if (false === self._trigger('beforeclose', event)) { + return; + } + + (self.overlay && self.overlay.destroy()); + self.uiDialog.unbind('keypress.ui-dialog'); + + (self.options.hide + ? self.uiDialog.hide(self.options.hide, function() { + self._trigger('close', event); + }) + : self.uiDialog.hide() && self._trigger('close', event)); + + $.ui.dialog.overlay.resize(); + + self._isOpen = false; + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + if (self.options.modal) { + var maxZ = 0; + $('.ui-dialog').each(function() { + if (this != self.uiDialog[0]) { + maxZ = Math.max(maxZ, $(this).css('z-index')); + } + }); + $.ui.dialog.maxZ = maxZ; + } + }, + + isOpen: function() { + return this._isOpen; + }, + + // the force parameter allows us to move modal dialogs to their correct + // position on open + moveToTop: function(force, event) { + + if ((this.options.modal && !force) + || (!this.options.stack && !this.options.modal)) { + return this._trigger('focus', event); + } + + if (this.options.zIndex > $.ui.dialog.maxZ) { + $.ui.dialog.maxZ = this.options.zIndex; + } + (this.overlay && this.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = ++$.ui.dialog.maxZ)); + + //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. + // http://ui.jquery.com/bugs/ticket/3193 + var saveScroll = { scrollTop: this.element.attr('scrollTop'), scrollLeft: this.element.attr('scrollLeft') }; + this.uiDialog.css('z-index', ++$.ui.dialog.maxZ); + this.element.attr(saveScroll); + this._trigger('focus', event); + }, + + open: function() { + if (this._isOpen) { return; } + + var options = this.options, + uiDialog = this.uiDialog; + + this.overlay = options.modal ? new $.ui.dialog.overlay(this) : null; + (uiDialog.next().length && uiDialog.appendTo('body')); + this._size(); + this._position(options.position); + uiDialog.show(options.show); + this.moveToTop(true); + + // prevent tabbing out of modal dialogs + (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) { + if (event.keyCode != $.ui.keyCode.TAB) { + return; + } + + var tabbables = $(':tabbable', this), + first = tabbables.filter(':first')[0], + last = tabbables.filter(':last')[0]; + + if (event.target == last && !event.shiftKey) { + setTimeout(function() { + first.focus(); + }, 1); + } else if (event.target == first && event.shiftKey) { + setTimeout(function() { + last.focus(); + }, 1); + } + })); + + // set focus to the first tabbable element in the content area or the first button + // if there are no tabbable elements, set focus on the dialog itself + $([]) + .add(uiDialog.find('.ui-dialog-content :tabbable:first')) + .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first')) + .add(uiDialog) + .filter(':first') + .focus(); + + this._trigger('open'); + this._isOpen = true; + }, + + _createButtons: function(buttons) { + var self = this, + hasButtons = false, + uiDialogButtonPane = $('
') + .addClass( + 'ui-dialog-buttonpane ' + + 'ui-widget-content ' + + 'ui-helper-clearfix' + ); + + // if we already have a button pane, remove it + this.uiDialog.find('.ui-dialog-buttonpane').remove(); + + (typeof buttons == 'object' && buttons !== null && + $.each(buttons, function() { return !(hasButtons = true); })); + if (hasButtons) { + $.each(buttons, function(name, fn) { + $('') + .addClass( + 'ui-state-default ' + + 'ui-corner-all' + ) + .text(name) + .click(function() { fn.apply(self.element[0], arguments); }) + .hover( + function() { + $(this).addClass('ui-state-hover'); + }, + function() { + $(this).removeClass('ui-state-hover'); + } + ) + .focus(function() { + $(this).addClass('ui-state-focus'); + }) + .blur(function() { + $(this).removeClass('ui-state-focus'); + }) + .appendTo(uiDialogButtonPane); + }); + uiDialogButtonPane.appendTo(this.uiDialog); + } + }, + + _makeDraggable: function() { + var self = this, + options = this.options, + heightBeforeDrag; + + this.uiDialog.draggable({ + cancel: '.ui-dialog-content', + handle: '.ui-dialog-titlebar', + containment: 'document', + start: function() { + heightBeforeDrag = options.height; + $(this).height($(this).height()).addClass("ui-dialog-dragging"); + (options.dragStart && options.dragStart.apply(self.element[0], arguments)); + }, + drag: function() { + (options.drag && options.drag.apply(self.element[0], arguments)); + }, + stop: function() { + $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); + (options.dragStop && options.dragStop.apply(self.element[0], arguments)); + $.ui.dialog.overlay.resize(); + } + }); + }, + + _makeResizable: function(handles) { + handles = (handles === undefined ? this.options.resizable : handles); + var self = this, + options = this.options, + resizeHandles = typeof handles == 'string' + ? handles + : 'n,e,s,w,se,sw,ne,nw'; + + this.uiDialog.resizable({ + cancel: '.ui-dialog-content', + alsoResize: this.element, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + minWidth: options.minWidth, + minHeight: options.minHeight, + start: function() { + $(this).addClass("ui-dialog-resizing"); + (options.resizeStart && options.resizeStart.apply(self.element[0], arguments)); + }, + resize: function() { + (options.resize && options.resize.apply(self.element[0], arguments)); + }, + handles: resizeHandles, + stop: function() { + $(this).removeClass("ui-dialog-resizing"); + options.height = $(this).height(); + options.width = $(this).width(); + (options.resizeStop && options.resizeStop.apply(self.element[0], arguments)); + $.ui.dialog.overlay.resize(); + } + }) + .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); + }, + + _position: function(pos) { + var wnd = $(window), doc = $(document), + pTop = doc.scrollTop(), pLeft = doc.scrollLeft(), + minTop = pTop; + + if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) { + pos = [ + pos == 'right' || pos == 'left' ? pos : 'center', + pos == 'top' || pos == 'bottom' ? pos : 'middle' + ]; + } + if (pos.constructor != Array) { + pos = ['center', 'middle']; + } + if (pos[0].constructor == Number) { + pLeft += pos[0]; + } else { + switch (pos[0]) { + case 'left': + pLeft += 0; + break; + case 'right': + pLeft += wnd.width() - this.uiDialog.outerWidth(); + break; + default: + case 'center': + pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2; + } + } + if (pos[1].constructor == Number) { + pTop += pos[1]; + } else { + switch (pos[1]) { + case 'top': + pTop += 0; + break; + case 'bottom': + pTop += wnd.height() - this.uiDialog.outerHeight(); + break; + default: + case 'middle': + pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2; + } + } + + // prevent the dialog from being too high (make sure the titlebar + // is accessible) + pTop = Math.max(pTop, minTop); + this.uiDialog.css({top: pTop, left: pLeft}); + }, + + _setData: function(key, value){ + (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value)); + switch (key) { + case "buttons": + this._createButtons(value); + break; + case "closeText": + this.uiDialogTitlebarCloseText.text(value); + break; + case "dialogClass": + this.uiDialog + .removeClass(this.options.dialogClass) + .addClass(uiDialogClasses + value); + break; + case "draggable": + (value + ? this._makeDraggable() + : this.uiDialog.draggable('destroy')); + break; + case "height": + this.uiDialog.height(value); + break; + case "position": + this._position(value); + break; + case "resizable": + var uiDialog = this.uiDialog, + isResizable = this.uiDialog.is(':data(resizable)'); + + // currently resizable, becoming non-resizable + (isResizable && !value && uiDialog.resizable('destroy')); + + // currently resizable, changing handles + (isResizable && typeof value == 'string' && + uiDialog.resizable('option', 'handles', value)); + + // currently non-resizable, becoming resizable + (isResizable || this._makeResizable(value)); + break; + case "title": + $(".ui-dialog-title", this.uiDialogTitlebar).html(value || ' '); + break; + case "width": + this.uiDialog.width(value); + break; + } + + $.widget.prototype._setData.apply(this, arguments); + }, + + _size: function() { + /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content + * divs will both have width and height set, so we need to reset them + */ + var options = this.options; + + // reset content sizing + this.element.css({ + height: 0, + minHeight: 0, + width: 'auto' + }); + + // reset wrapper sizing + // determine the height of all the non-content elements + var nonContentHeight = this.uiDialog.css({ + height: 'auto', + width: options.width + }) + .height(); + + this.element + .css({ + minHeight: Math.max(options.minHeight - nonContentHeight, 0), + height: options.height == 'auto' + ? 'auto' + : Math.max(options.height - nonContentHeight, 0) + }); + } +}); + +$.extend($.ui.dialog, { + version: "1.7.2", + defaults: { + autoOpen: true, + bgiframe: false, + buttons: {}, + closeOnEscape: true, + closeText: 'close', + dialogClass: '', + draggable: true, + hide: null, + height: 'auto', + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: 'center', + resizable: true, + show: null, + stack: true, + title: '', + width: 300, + zIndex: 1000 + }, + + getter: 'isOpen', + + uuid: 0, + maxZ: 0, + + getTitleId: function($el) { + return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid); + }, + + overlay: function(dialog) { + this.$el = $.ui.dialog.overlay.create(dialog); + } +}); + +$.extend($.ui.dialog.overlay, { + instances: [], + maxZ: 0, + events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), + function(event) { return event + '.dialog-overlay'; }).join(' '), + create: function(dialog) { + if (this.instances.length === 0) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ($.ui.dialog.overlay.instances.length) { + $(document).bind($.ui.dialog.overlay.events, function(event) { + var dialogZ = $(event.target).parents('.ui-dialog').css('zIndex') || 0; + return (dialogZ > $.ui.dialog.overlay.maxZ); + }); + } + }, 1); + + // allow closing by pressing the escape key + $(document).bind('keydown.dialog-overlay', function(event) { + (dialog.options.closeOnEscape && event.keyCode + && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event)); + }); + + // handle window resize + $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); + } + + var $el = $('
').appendTo(document.body) + .addClass('ui-widget-overlay').css({ + width: this.width(), + height: this.height() + }); + + (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe()); + + this.instances.push($el); + return $el; + }, + + destroy: function($el) { + this.instances.splice($.inArray(this.instances, $el), 1); + + if (this.instances.length === 0) { + $([document, window]).unbind('.dialog-overlay'); + } + + $el.remove(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + var maxZ = 0; + $.each(this.instances, function() { + maxZ = Math.max(maxZ, this.css('z-index')); + }); + this.maxZ = maxZ; + }, + + height: function() { + // handle IE 6 + if ($.browser.msie && $.browser.version < 7) { + var scrollHeight = Math.max( + document.documentElement.scrollHeight, + document.body.scrollHeight + ); + var offsetHeight = Math.max( + document.documentElement.offsetHeight, + document.body.offsetHeight + ); + + if (scrollHeight < offsetHeight) { + return $(window).height() + 'px'; + } else { + return scrollHeight + 'px'; + } + // handle "good" browsers + } else { + return $(document).height() + 'px'; + } + }, + + width: function() { + // handle IE 6 + if ($.browser.msie && $.browser.version < 7) { + var scrollWidth = Math.max( + document.documentElement.scrollWidth, + document.body.scrollWidth + ); + var offsetWidth = Math.max( + document.documentElement.offsetWidth, + document.body.offsetWidth + ); + + if (scrollWidth < offsetWidth) { + return $(window).width() + 'px'; + } else { + return scrollWidth + 'px'; + } + // handle "good" browsers + } else { + return $(document).width() + 'px'; + } + }, + + resize: function() { + /* If the dialog is draggable and the user drags it past the + * right edge of the window, the document becomes wider so we + * need to stretch the overlay. If the user then drags the + * dialog back to the left, the document will become narrower, + * so we need to shrink the overlay to the appropriate size. + * This is handled by shrinking the overlay before setting it + * to the full document size. + */ + var $overlays = $([]); + $.each($.ui.dialog.overlay.instances, function() { + $overlays = $overlays.add(this); + }); + + $overlays.css({ + width: 0, + height: 0 + }).css({ + width: $.ui.dialog.overlay.width(), + height: $.ui.dialog.overlay.height() + }); + } +}); + +$.extend($.ui.dialog.overlay.prototype, { + destroy: function() { + $.ui.dialog.overlay.destroy(this.$el); + } +}); + +})(jQuery); diff --git a/admin/template/js/ui.sortable.js b/admin/template/js/ui.sortable.js new file mode 100644 index 000000000..5460850b4 --- /dev/null +++ b/admin/template/js/ui.sortable.js @@ -0,0 +1,1019 @@ +/* + * jQuery UI Sortable 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Sortables + * + * Depends: + * ui.core.js + */ +(function($) { + +$.widget("ui.sortable", $.extend({}, $.ui.mouse, { + _init: function() { + + var o = this.options; + this.containerCache = {}; + this.element.addClass("ui-sortable"); + + //Get the items + this.refresh(); + + //Let's determine if the items are floating + this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false; + + //Let's determine the parent's offset + this.offset = this.element.offset(); + + //Initialize mouse events for interaction + this._mouseInit(); + + }, + + destroy: function() { + this.element + .removeClass("ui-sortable ui-sortable-disabled") + .removeData("sortable") + .unbind(".sortable"); + this._mouseDestroy(); + + for ( var i = this.items.length - 1; i >= 0; i-- ) + this.items[i].item.removeData("sortable-item"); + }, + + _mouseCapture: function(event, overrideHandle) { + + if (this.reverting) { + return false; + } + + if(this.options.disabled || this.options.type == 'static') return false; + + //We have to refresh the items data once first + this._refreshItems(event); + + //Find out if the clicked node (or one of its parents) is a actual item in this.items + var currentItem = null, self = this, nodes = $(event.target).parents().each(function() { + if($.data(this, 'sortable-item') == self) { + currentItem = $(this); + return false; + } + }); + if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target); + + if(!currentItem) return false; + if(this.options.handle && !overrideHandle) { + var validHandle = false; + + $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); + if(!validHandle) return false; + } + + this.currentItem = currentItem; + this._removeCurrentsFromItems(); + return true; + + }, + + _mouseStart: function(event, overrideHandle, noActivation) { + + var o = this.options, self = this; + this.currentContainer = this; + + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture + this.refreshPositions(); + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Get the next scrolling parent + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.currentItem.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + // Only after we got the offset, we can change the helper's position to absolute + // TODO: Still need to figure out a way to make relative sorting possible + this.helper.css("position", "absolute"); + this.cssPosition = this.helper.css("position"); + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + if(o.cursorAt) + this._adjustOffsetFromHelper(o.cursorAt); + + //Cache the former DOM position + this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; + + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way + if(this.helper[0] != this.currentItem[0]) { + this.currentItem.hide(); + } + + //Create the placeholder + this._createPlaceholder(); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + if(o.cursor) { // cursor option + if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); + $('body').css("cursor", o.cursor); + } + + if(o.opacity) { // opacity option + if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); + this.helper.css("opacity", o.opacity); + } + + if(o.zIndex) { // zIndex option + if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); + this.helper.css("zIndex", o.zIndex); + } + + //Prepare scrolling + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') + this.overflowOffset = this.scrollParent.offset(); + + //Call callbacks + this._trigger("start", event, this._uiHash()); + + //Recache the helper size + if(!this._preserveHelperProportions) + this._cacheHelperProportions(); + + + //Post 'activate' events to possible containers + if(!noActivation) { + for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); } + } + + //Prepare possible droppables + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.dragging = true; + + this.helper.addClass("ui-sortable-helper"); + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + + }, + + _mouseDrag: function(event) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if(this.options.scroll) { + var o = this.options, scrolled = false; + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { + + if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + + if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + + } else { + + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + //Set the helper position + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + + //Rearrange + for (var i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); + if (!intersection) continue; + + if(itemElement != this.currentItem[0] //cannot intersect with itself + && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before + && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked + && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) + ) { + + this.direction = intersection == 1 ? "down" : "up"; + + if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { + this._rearrange(event, item); + } else { + break; + } + + this._trigger("change", event, this._uiHash()); + break; + } + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + //Call callbacks + this._trigger('sort', event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function(event, noPropagation) { + + if(!event) return; + + //If we are using droppables, inform the manager about the drop + if ($.ui.ddmanager && !this.options.dropBehaviour) + $.ui.ddmanager.drop(this, event); + + if(this.options.revert) { + var self = this; + var cur = self.placeholder.offset(); + + self.reverting = true; + + $(this.helper).animate({ + left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), + top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) + }, parseInt(this.options.revert, 10) || 500, function() { + self._clear(event); + }); + } else { + this._clear(event, noPropagation); + } + + return false; + + }, + + cancel: function() { + + var self = this; + + if(this.dragging) { + + this._mouseUp(); + + if(this.options.helper == "original") + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + else + this.currentItem.show(); + + //Post deactivating events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + this.containers[i]._trigger("deactivate", null, self._uiHash(this)); + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", null, self._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); + + $.extend(this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + }); + + if(this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } + + return true; + + }, + + serialize: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var str = []; o = o || {}; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); + if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); + }); + + return str.join('&'); + + }, + + toArray: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var ret = []; o = o || {}; + + items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); + return ret; + + }, + + /* Be careful with the following core functions */ + _intersectsWith: function(item) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height; + + var l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height; + + var dyClick = this.offset.click.top, + dxClick = this.offset.click.left; + + var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + + if( this.options.tolerance == "pointer" + || this.options.forcePointerForContainers + || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) + ) { + return isOverElement; + } else { + + return (l < x1 + (this.helperProportions.width / 2) // Right Half + && x2 - (this.helperProportions.width / 2) < r // Left Half + && t < y1 + (this.helperProportions.height / 2) // Bottom Half + && y2 - (this.helperProportions.height / 2) < b ); // Top Half + + } + }, + + _intersectsWithPointer: function(item) { + + var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), + isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), + isOverElement = isOverElementHeight && isOverElementWidth, + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (!isOverElement) + return false; + + return this.floating ? + ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) + : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); + + }, + + _intersectsWithSides: function(item) { + + var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), + isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); + } else { + return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); + } + + }, + + _getDragVerticalDirection: function() { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta != 0 && (delta > 0 ? "down" : "up"); + }, + + _getDragHorizontalDirection: function() { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta != 0 && (delta > 0 ? "right" : "left"); + }, + + refresh: function(event) { + this._refreshItems(event); + this.refreshPositions(); + }, + + _connectWith: function() { + var options = this.options; + return options.connectWith.constructor == String + ? [options.connectWith] + : options.connectWith; + }, + + _getItemsAsjQuery: function(connected) { + + var self = this; + var items = []; + var queries = []; + var connectWith = this._connectWith(); + + if(connectWith && connected) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], 'sortable'); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper"), inst]); + } + }; + }; + } + + queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper"), this]); + + for (var i = queries.length - 1; i >= 0; i--){ + queries[i][0].each(function() { + items.push(this); + }); + }; + + return $(items); + + }, + + _removeCurrentsFromItems: function() { + + var list = this.currentItem.find(":data(sortable-item)"); + + for (var i=0; i < this.items.length; i++) { + + for (var j=0; j < list.length; j++) { + if(list[j] == this.items[i].item[0]) + this.items.splice(i,1); + }; + + }; + + }, + + _refreshItems: function(event) { + + this.items = []; + this.containers = [this]; + var items = this.items; + var self = this; + var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; + var connectWith = this._connectWith(); + + if(connectWith) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], 'sortable'); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); + this.containers.push(inst); + } + }; + }; + } + + for (var i = queries.length - 1; i >= 0; i--) { + var targetData = queries[i][1]; + var _queries = queries[i][0]; + + for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { + var item = $(_queries[j]); + + item.data('sortable-item', targetData); // Data for target checking (mouse manager) + + items.push({ + item: item, + instance: targetData, + width: 0, height: 0, + left: 0, top: 0 + }); + }; + }; + + }, + + refreshPositions: function(fast) { + + //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change + if(this.offsetParent && this.helper) { + this.offset.parent = this._getParentOffset(); + } + + for (var i = this.items.length - 1; i >= 0; i--){ + var item = this.items[i]; + + //We ignore calculating positions of all connected containers when we're not over them + if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) + continue; + + var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; + + if (!fast) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } + + var p = t.offset(); + item.left = p.left; + item.top = p.top; + }; + + if(this.options.custom && this.options.custom.refreshContainers) { + this.options.custom.refreshContainers.call(this); + } else { + for (var i = this.containers.length - 1; i >= 0; i--){ + var p = this.containers[i].element.offset(); + this.containers[i].containerCache.left = p.left; + this.containers[i].containerCache.top = p.top; + this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); + this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); + }; + } + + }, + + _createPlaceholder: function(that) { + + var self = that || this, o = self.options; + + if(!o.placeholder || o.placeholder.constructor == String) { + var className = o.placeholder; + o.placeholder = { + element: function() { + + var el = $(document.createElement(self.currentItem[0].nodeName)) + .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder") + .removeClass("ui-sortable-helper")[0]; + + if(!className) + el.style.visibility = "hidden"; + + return el; + }, + update: function(container, p) { + + // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified + if(className && !o.forcePlaceholderSize) return; + + //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item + if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); }; + if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); }; + } + }; + } + + //Create the placeholder + self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); + + //Append it after the actual current item + self.currentItem.after(self.placeholder); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update(self, self.placeholder); + + }, + + _contactContainers: function(event) { + for (var i = this.containers.length - 1; i >= 0; i--){ + + if(this._intersectsWith(this.containers[i].containerCache)) { + if(!this.containers[i].containerCache.over) { + + if(this.currentContainer != this.containers[i]) { + + //When entering a new container, we will find the item with the least distance and append our item near it + var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[i].floating ? 'left' : 'top']; + for (var j = this.items.length - 1; j >= 0; j--) { + if(!$.ui.contains(this.containers[i].element[0], this.items[j].item[0])) continue; + var cur = this.items[j][this.containers[i].floating ? 'left' : 'top']; + if(Math.abs(cur - base) < dist) { + dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; + } + } + + if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled + continue; + + this.currentContainer = this.containers[i]; + itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[i].element, true); + this._trigger("change", event, this._uiHash()); + this.containers[i]._trigger("change", event, this._uiHash(this)); + + //Update the placeholder + this.options.placeholder.update(this.currentContainer, this.placeholder); + + } + + this.containers[i]._trigger("over", event, this._uiHash(this)); + this.containers[i].containerCache.over = 1; + } + } else { + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", event, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + }; + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); + + if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already + $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); + + if(helper[0] == this.currentItem[0]) + this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; + + if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); + if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left; + if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top; + if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + }, + + _getParentOffset: function() { + + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.currentItem.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), + top: (parseInt(this.currentItem.css("marginTop"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment)) { + var ce = $(o.containment)[0]; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, + co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, + co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top + ]; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + + if(this.containment) { + if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if(o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _rearrange: function(event, i, a, hardRefresh) { + + a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var self = this, counter = this.counter; + + window.setTimeout(function() { + if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove + },0); + + }, + + _clear: function(event, noPropagation) { + + this.reverting = false; + // We delay all events that have to be triggered to after the point where the placeholder has been removed and + // everything else normalized again + var delayedTriggers = [], self = this; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) + if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem); + this._noFinalSort = null; + + if(this.helper[0] == this.currentItem[0]) { + for(var i in this._storedCSS) { + if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; + } + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + } else { + this.currentItem.show(); + } + + if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); + if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed + if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element + if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); + for (var i = this.containers.length - 1; i >= 0; i--){ + if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + } + }; + }; + + //Post events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + if(this.containers[i].containerCache.over) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + this.containers[i].containerCache.over = 0; + } + } + + //Do what was originally in plugins + if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor + if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset cursor + if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index + + this.dragging = false; + if(this.cancelHelperRemoval) { + if(!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + return false; + } + + if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + + if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; + + if(!noPropagation) { + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return true; + + }, + + _trigger: function() { + if ($.widget.prototype._trigger.apply(this, arguments) === false) { + this.cancel(); + } + }, + + _uiHash: function(inst) { + var self = inst || this; + return { + helper: self.helper, + placeholder: self.placeholder || $([]), + position: self.position, + absolutePosition: self.positionAbs, //deprecated + offset: self.positionAbs, + item: self.currentItem, + sender: inst ? inst.element : null + }; + } + +})); + +$.extend($.ui.sortable, { + getter: "serialize toArray", + version: "1.7.2", + eventPrefix: "sort", + defaults: { + appendTo: "parent", + axis: false, + cancel: ":input,option", + connectWith: false, + containment: false, + cursor: 'auto', + cursorAt: false, + delay: 0, + distance: 1, + dropOnEmpty: true, + forcePlaceholderSize: false, + forceHelperSize: false, + grid: false, + handle: false, + helper: "original", + items: '> *', + opacity: false, + placeholder: false, + revert: false, + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + scope: "default", + tolerance: "intersect", + zIndex: 1000 + } +}); + +})(jQuery); diff --git a/admin/template/js/wysiwyg/jquery.wysiwyg.css b/admin/template/js/wysiwyg/jquery.wysiwyg.css new file mode 100644 index 000000000..506d77ea7 --- /dev/null +++ b/admin/template/js/wysiwyg/jquery.wysiwyg.css @@ -0,0 +1,57 @@ + +div.wysiwyg { border: 1px solid #999; padding: 5px; background-color: #FFFFE6; } +div.wysiwyg * { margin: 0; padding: 0; } + +div.wysiwyg ul.panel { border: 1px solid #999; float: left; width: 100%; padding: 4px 0 4px 0; background: #ffffff; } +div.wysiwyg ul.panel li { list-style-type: none; float: left; margin: 0 2px; background: #ffffff;} +div.wysiwyg ul.panel li.separator { height: 16px; margin: 0 4px; border-left: 1px solid #cccccc; } +div.wysiwyg ul.panel li a { opacity: 0.6; display: block; width: 16px; height: 16px; background: url('jquery.wysiwyg.gif') no-repeat -64px -80px; border: 0; cursor: pointer; padding: 1px; } +div.wysiwyg ul.panel li a:hover, div.wysiwyg ul.panel li a.active { opacity: 0.99; } +div.wysiwyg ul.panel li a.active { background-color: #f9f9f9; border: 1px solid #cccccc; border-left-color: #aaaaaa; border-top-color: #aaaaaa; padding: 0; } + +div.wysiwyg ul.panel li a.bold { background-position: 0 -16px; } +div.wysiwyg ul.panel li a.italic { background-position: -16px -16px; } +div.wysiwyg ul.panel li a.strikeThrough { background-position: -32px -16px; } +div.wysiwyg ul.panel li a.underline { background-position: -48px -16px; } + +div.wysiwyg ul.panel li a.justifyLeft { background-position: 0 0; } +div.wysiwyg ul.panel li a.justifyCenter { background-position: -16px 0; } +div.wysiwyg ul.panel li a.justifyRight { background-position: -32px 0; } +div.wysiwyg ul.panel li a.justifyFull { background-position: -48px 0; } + +div.wysiwyg ul.panel li a.indent { background-position: -64px 0; } +div.wysiwyg ul.panel li a.outdent { background-position: -80px 0; } + +div.wysiwyg ul.panel li a.subscript { background-position: -64px -16px; } +div.wysiwyg ul.panel li a.superscript { background-position: -80px -16px; } + +div.wysiwyg ul.panel li a.undo { background-position: 0 -64px; } +div.wysiwyg ul.panel li a.redo { background-position: -16px -64px; } + +div.wysiwyg ul.panel li a.insertOrderedList { background-position: -32px -48px; } +div.wysiwyg ul.panel li a.insertUnorderedList { background-position: -16px -48px; } +div.wysiwyg ul.panel li a.insertHorizontalRule { background-position: 0 -48px; } + +div.wysiwyg ul.panel li a.h1 { background-position: 0 -32px; } +div.wysiwyg ul.panel li a.h2 { background-position: -16px -32px; } +div.wysiwyg ul.panel li a.h3 { background-position: -32px -32px; } +div.wysiwyg ul.panel li a.h4 { background-position: -48px -32px; } +div.wysiwyg ul.panel li a.h5 { background-position: -64px -32px; } +div.wysiwyg ul.panel li a.h6 { background-position: -80px -32px; } + +div.wysiwyg ul.panel li a.cut { background-position: -32px -64px; } +div.wysiwyg ul.panel li a.copy { background-position: -48px -64px; } +div.wysiwyg ul.panel li a.paste { background-position: -64px -64px; } + +div.wysiwyg ul.panel li a.increaseFontSize { background-position: -16px -80px; } +div.wysiwyg ul.panel li a.decreaseFontSize { background-position: -32px -80px; } + +div.wysiwyg ul.panel li a.createLink { background-position: -80px -48px; } +div.wysiwyg ul.panel li a.insertImage { background-position: -80px -80px; } + +div.wysiwyg ul.panel li a.html { background-position: -48px -48px; } +div.wysiwyg ul.panel li a.removeFormat { background-position: -80px -64px; } + +div.wysiwyg ul.panel li a.empty { background-position: -64px -80px; } + +div.wysiwyg iframe { border: 0; margin: 5px 0 0 0; clear: left; } \ No newline at end of file diff --git a/admin/template/js/wysiwyg/jquery.wysiwyg.gif b/admin/template/js/wysiwyg/jquery.wysiwyg.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd64e3667187ddc39aa935d44bfb273b3c82a049 GIT binary patch literal 4478 zcmWmDi9gei2ZH`znWWp(Bkf$;-s@XLUSeY@$ujM0z_5nC~5z<<}8gyQ&?Eon3wSJ z2w-7hF*`dur&L~6_Ep>}E9)4z&cxKJc*pBrDg|55wCA}99d~BFR5u?EFATpw_&Kif zAE{hOrBV~BM${j4uj<4_4MPC|0fMSFrBbQev$vz8V_@`K{mrSLkNe9+5g{c(1DdC@ z$I)?l!!Mh{6#g_pi{?iE)L!Z9pi|;)NA5&NM}K6x&YhRTaVvjKw`e|o%W4aKTI!=q zOx8Y0U^1D~hbM~VH){t<_oY45*VkXSZr#BP;4;ESaZPoB)X_QI_g}gZ~6A5 z($UW^Qm3bA=^GjyFD)eJQPySErGci8 zo1Kf5A5uGf?!VBK-YP1IwAST#7xm`u%TVHQIG+=1_MLbhf9!I{uI6w~!_U%)uoHtCAL ziW01R4&Kd29;jV;H@C949A36_=x%Inr@5W~(LRAn(_>4%4J|GD66wo79AQwyqEFo{ zS}DjZo%mo-k-D~GzmZs(v4I!4?3__VUd^zbDGNIHW9HDSj?F*Z7B)#P1hgN+I3?ws ze=;Q8TvGjcZ`8TBvYktHOZ*>OR`{e%M7_^i)YNk$(T)}-$E_E&n?Of-MbtF%GW3aS zkCKbo5xn#RFKqqh4{%p+x~WdhCpt{11(2KN zh|q8^sE?>ExTS!P{FILze4Cg@UX9V0D{#~SyKVS+n{I`niy_;KX%z^eQ6}~h7Tye! zGEZSnvwDzv;>TPo*lBFX#+aXO5DH^MV=XiE?o{Dih!rZF*;<7W)7n@%2Ir@+;20Ad znD3fqI2$HK2C)s9KUrD+$&H;Z|Sa}5*>pk%SZZU_uO2Os22F*a^yXfXl$RdE@bCL?yAzX=e5_hCr74g zf>QjEeETJ?z<#0~U33LmLH`7=EVz_ol@E8G5343d=n=X0wH5X?)rxuzVni~<1Zm+&TDh@f&g|2A> zM%|A^-7{RHTe0!&$_-~2(_6QQD*O~iI$q&x2}z;pd(I?gB5%ZgR0Kc>v^1TNp{ z{i@XOT~A%8Fpxcl<)MDMN8L75puZDQW-{)O#ajcMx0M}`Fo^ROcbFxRY^}p8?z6P! z&D|29jVkH#C|G11P)W8FlZd*Y$A3JP0GMCjaTsL&^+m>E8K}rgE1{pgrO#nvzLtyh6zi48k`Gu8bzYwN}<`WS{> zNWOQ~?PcuP$+Y=VktOW0IYeQ=H5}{p;#QLwRzAlpxr1n?r|rUMZk7HB>=fylogzbE zv|%M{eeWUtCOxXojjh=cxtgSWoOdP$kP=v3-SeN$D2TQ6bWd*)-E-rR0_~iiLGf~2 zv|P(Y5G^m3g~%&RNx`TkQbER^#Lva*FSQ$28`x%XgbtQrTbEv0j4tJfXfF&)H@UCV zPbonX-#|SZ+SNMH-LY%&gku`mkn}JnYTd?fz5=GnJr>U(4AisiM9!IKifw7}aZ5-} z<(JE`r92{X@oi_~t;{_UpQ|koc3B15d99y8Rj!hwUHH&$OveZ*Hrj*sNZTj*I7;Nv zz*XK2SO=RgRK0EJ?K(Sj!+OQ>n9RAyUngwcf(p@ zzH(p_+Vi&oG!q?N!l0twxj9R`GOKJ8mduL#aUmOuPd*Uwrwzc>KKHQUnG*)-3+_v8 z85Sa)!r=-rLtsxe&u%^4MQsn7a#80{d`xFs<5n>vbe*S=PZ*SA^@43>OI{*XS)_+| z4lTX11m|rTU%1JSMU(e|mSEV`L2wdgvjW#|4z8#Mh0F~0Up)J($M%5L9+?Br58g1o zvI*pHSNUWj-CYed3+eXNe?s4!M>-*ATdRrdWft#cAbE(fvj>TCZJ+HRY@1A(DlS`A zy`tSjOG)^4+t{$t6ke7s-U#tP8#WIT()cI;^?vi#&$Nq(=Q!qek>kY*qw{x^Tk;=_ zB~Mfpuuk4_(8Nk0Q-8FdL(h6cCLfVFbpHx;-|RW8*-_vRo#bxYvJ`nD4H(rK;q20> zNPThKpuh1Gd(ee%$7KYX8&u@k@ovQ|O>s0~^h6Mo=YKL3QkiII+MSPs&Iq z8X~idiDCDU`V5*qV=|6R@~UwZ9SEE{rgvA}av|?xny+s#?H~HOmd0fi_ry-UVZYljO-uSa zk+HOAV9l+|$07FS;3a+&3B%nxKE{m-jA$Fu?~D!|T1{t|TI$@}j5VxjzV^D&zIwnc zr8M(D_fYc|_?F8k55*IQl+Qh=bL8+&2;xKgagjWWD+}lVqU-PjwrGo3L0CUHKbgVp zaq+Sx{+_rnW#i(pHn%S`?B_MjSs8O{m^vf%9)p&|xm`Uvld%hgfnoLSbq0@-7VUgU zK?9#u9ir?-Gg0CVEm*(KlZYqq+klB4{ne>LPxvp&+aK=MbH@)u^$WCrR*Q+P2vrm~ zrgrUdU`W{5os0N}WyU|P65-@<)3PT;mRNHrmT$9 z$}8Ghary*?OHN3~D%=O;16k0;gmIpwlI;DXPwW#rBoPXERQRQ6h(>1{BSqfiEx;Jnfznd~iLm1GB zzr)~XHD&xS%DcalM+g3+vWRch$?M@%f|gtfBW>sSKb}R?yb)tf{S)g#pu}BaMdmkZUPY@DOqSK}APcIkxJVH)6|Wy&E6Zk#wQ;g-RIi5#Ix709I%kJHIEUooTda4XShTJ;yxD@2aD5M5mO$}S2+pU zhdW`3(3e4H5|3EC(;Jsy4>$me=_yM0lzByJ_EG4SskuI#tgo;K&5<{BG>i`fI9XwC zK-g24Tz*tJHS}-az1Mt58+(pskrWPj;^VvvpRt* z@Gyu0;s}6}aiPa;s3(!7_?*%gNu`)hRKBi|^p{6qVj~!aDsIz(k2KGUMx4&lmk@RPfrQ7WH^QZ)aVY~d{6iY4 z8Lw|NN$%xVEY8GYA>?u|NDNgD%F)|7AYGxizpc9WO?A48?7$`7QA>1i&5rNYA{E+J zh2Em2xT?{YBqS*YwF$tmIH*_vvz?}o=Yk_z!Uq+;6d=#25udr$^F!ryZPj*G<#8+M zCA}Usf>7(UdPgOg>k?F9O+7LgY@{PkaS4qoREC0(J44BoqhbKefTG|bfWZ)|#d7Zp za_keB6iuhRRFOQbp$&3WE(e9=fuA6Jj{G1hwz2J6;~lNuO&Qi-f~jIRwl*{dJx8zL z=uN?7i3*M5;q|Ra_5daq!iypOBhL|UoWT8Ou(vtqTdtwo<>x<1D6TLL0bNL!fyj#U z?aq+&()O}0popVsvC77GQ z+1yNMi=1$pd&!nni^?HMVU)dm?+WS#_#2d3Nb%X!;`{I$^K&GQJNL;#G^O hX!c45k+I+m^@2VEr;rh2UR*hpobMjF7=Zvb{U3Ub*!Tbd literal 0 HcmV?d00001 diff --git a/admin/template/js/wysiwyg/jquery.wysiwyg.js b/admin/template/js/wysiwyg/jquery.wysiwyg.js new file mode 100644 index 000000000..db278fc4a --- /dev/null +++ b/admin/template/js/wysiwyg/jquery.wysiwyg.js @@ -0,0 +1,652 @@ +/** + * WYSIWYG - jQuery plugin 0.5 + * + * Copyright (c) 2008-2009 Juan M Martinez + * http://plugins.jquery.com/project/jWYSIWYG + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * $Id: $ + */ +(function( $ ) +{ + $.fn.document = function() + { + var element = this[0]; + + if ( element.nodeName.toLowerCase() == 'iframe' ) + return element.contentWindow.document; + /* + return ( $.browser.msie ) + ? document.frames[element.id].document + : element.contentWindow.document // contentDocument; + */ + else + return $(this); + }; + + $.fn.documentSelection = function() + { + var element = this[0]; + + if ( element.contentWindow.document.selection ) + return element.contentWindow.document.selection.createRange().text; + else + return element.contentWindow.getSelection().toString(); + }; + + $.fn.wysiwyg = function( options ) + { + if ( arguments.length > 0 && arguments[0].constructor == String ) + { + var action = arguments[0].toString(); + var params = []; + + for ( var i = 1; i < arguments.length; i++ ) + params[i - 1] = arguments[i]; + + if ( action in Wysiwyg ) + { + return this.each(function() + { + $.data(this, 'wysiwyg') + .designMode(); + + Wysiwyg[action].apply(this, params); + }); + } + else return this; + } + + var controls = {}; + + /** + * If the user set custom controls, we catch it, and merge with the + * defaults controls later. + */ + if ( options && options.controls ) + { + var controls = options.controls; + delete options.controls; + } + + var options = $.extend({ + html : '<'+'?xml version="1.0" encoding="UTF-8"?'+'>STYLE_SHEETINITIAL_CONTENT', + css : {}, + + debug : false, + + autoSave : true, // http://code.google.com/p/jwysiwyg/issues/detail?id=11 + rmUnwantedBr : true, // http://code.google.com/p/jwysiwyg/issues/detail?id=15 + brIE : true, + + controls : {}, + messages : {} + }, options); + + options.messages = $.extend(true, options.messages, Wysiwyg.MSGS_EN); + options.controls = $.extend(true, options.controls, Wysiwyg.TOOLBAR); + + for ( var control in controls ) + { + if ( control in options.controls ) + $.extend(options.controls[control], controls[control]); + else + options.controls[control] = controls[control]; + } + + // not break the chain + return this.each(function() + { + Wysiwyg(this, options); + }); + }; + + function Wysiwyg( element, options ) + { + return this instanceof Wysiwyg + ? this.init(element, options) + : new Wysiwyg(element, options); + } + + $.extend(Wysiwyg, { + insertImage : function( szURL, attributes ) + { + var self = $.data(this, 'wysiwyg'); + + if ( self.constructor == Wysiwyg && szURL && szURL.length > 0 ) + { + if ( attributes ) + { + self.editorDoc.execCommand('insertImage', false, '#jwysiwyg#'); + var img = self.getElementByAttributeValue('img', 'src', '#jwysiwyg#'); + + if ( img ) + { + img.src = szURL; + + for ( var attribute in attributes ) + { + img.setAttribute(attribute, attributes[attribute]); + } + } + } + else + { + self.editorDoc.execCommand('insertImage', false, szURL); + } + } + }, + + createLink : function( szURL ) + { + var self = $.data(this, 'wysiwyg'); + + if ( self.constructor == Wysiwyg && szURL && szURL.length > 0 ) + { + var selection = $(self.editor).documentSelection(); + + if ( selection.length > 0 ) + { + self.editorDoc.execCommand('unlink', false, []); + self.editorDoc.execCommand('createLink', false, szURL); + } + else if ( self.options.messages.nonSelection ) + alert(self.options.messages.nonSelection); + } + }, + + setContent : function( newContent ) + { + var self = $.data(this, 'wysiwyg'); + self.setContent( newContent ); + self.saveContent(); + }, + + clear : function() + { + var self = $.data(this, 'wysiwyg'); + self.setContent(''); + self.saveContent(); + }, + + MSGS_EN : { + nonSelection : 'select the text you wish to link' + }, + + TOOLBAR : { + bold : { visible : true, tags : ['b', 'strong'], css : { fontWeight : 'bold' } }, + italic : { visible : true, tags : ['i', 'em'], css : { fontStyle : 'italic' } }, + strikeThrough : { visible : false, tags : ['s', 'strike'], css : { textDecoration : 'line-through' } }, + underline : { visible : false, tags : ['u'], css : { textDecoration : 'underline' } }, + + separator00 : { visible : false, separator : true }, + + justifyLeft : { visible : false, css : { textAlign : 'left' } }, + justifyCenter : { visible : false, tags : ['center'], css : { textAlign : 'center' } }, + justifyRight : { visible : false, css : { textAlign : 'right' } }, + justifyFull : { visible : false, css : { textAlign : 'justify' } }, + + separator01 : { visible : false, separator : true }, + + indent : { visible : false }, + outdent : { visible : false }, + + separator02 : { visible : false, separator : true }, + + subscript : { visible : false, tags : ['sub'] }, + superscript : { visible : false, tags : ['sup'] }, + + separator03 : { visible : false, separator : true }, + + undo : { visible : false }, + redo : { visible : false }, + + separator04 : { visible : false, separator : true }, + + insertOrderedList : { visible : false, tags : ['ol'] }, + insertUnorderedList : { visible : false, tags : ['ul'] }, + insertHorizontalRule : { visible : false, tags : ['hr'] }, + + separator05 : { separator : true }, + + createLink : { + visible : true, + exec : function() + { + var selection = $(this.editor).documentSelection(); + + if ( selection.length > 0 ) + { + if ( $.browser.msie ) + this.editorDoc.execCommand('createLink', true, null); + else + { + var szURL = prompt('URL', 'http://'); + + if ( szURL && szURL.length > 0 ) + { + this.editorDoc.execCommand('unlink', false, []); + this.editorDoc.execCommand('createLink', false, szURL); + } + } + } + else if ( this.options.messages.nonSelection ) + alert(this.options.messages.nonSelection); + }, + + tags : ['a'] + }, + + insertImage : { + visible : true, + exec : function() + { + if ( $.browser.msie ) + this.editorDoc.execCommand('insertImage', true, null); + else + { + var szURL = prompt('URL', 'http://'); + + if ( szURL && szURL.length > 0 ) + this.editorDoc.execCommand('insertImage', false, szURL); + } + }, + + tags : ['img'] + }, + + separator06 : { separator : true }, + + h1mozilla : { visible : true && $.browser.mozilla, className : 'h1', command : 'heading', arguments : ['h1'], tags : ['h1'] }, + h2mozilla : { visible : true && $.browser.mozilla, className : 'h2', command : 'heading', arguments : ['h2'], tags : ['h2'] }, + h3mozilla : { visible : true && $.browser.mozilla, className : 'h3', command : 'heading', arguments : ['h3'], tags : ['h3'] }, + + h1 : { visible : true && !( $.browser.mozilla ), className : 'h1', command : 'formatBlock', arguments : ['Heading 1'], tags : ['h1'] }, + h2 : { visible : true && !( $.browser.mozilla ), className : 'h2', command : 'formatBlock', arguments : ['Heading 2'], tags : ['h2'] }, + h3 : { visible : true && !( $.browser.mozilla ), className : 'h3', command : 'formatBlock', arguments : ['Heading 3'], tags : ['h3'] }, + + separator07 : { visible : false, separator : true }, + + cut : { visible : false }, + copy : { visible : false }, + paste : { visible : false }, + + separator08 : { separator : true && !( $.browser.msie ) }, + + increaseFontSize : { visible : true && !( $.browser.msie ), tags : ['big'] }, + decreaseFontSize : { visible : true && !( $.browser.msie ), tags : ['small'] }, + + separator09 : { separator : true }, + + html : { + visible : false, + exec : function() + { + if ( this.viewHTML ) + { + this.setContent( $(this.original).val() ); + $(this.original).hide(); + } + else + { + this.saveContent(); + $(this.original).show(); + } + + this.viewHTML = !( this.viewHTML ); + } + }, + + removeFormat : { + visible : true, + exec : function() + { + this.editorDoc.execCommand('removeFormat', false, []); + this.editorDoc.execCommand('unlink', false, []); + } + } + } + }); + + $.extend(Wysiwyg.prototype, + { + original : null, + options : {}, + + element : null, + editor : null, + + init : function( element, options ) + { + var self = this; + + this.editor = element; + this.options = options || {}; + + $.data(element, 'wysiwyg', this); + + var newX = element.width || element.clientWidth; + var newY = element.height || element.clientHeight; + + if ( element.nodeName.toLowerCase() == 'textarea' ) + { + this.original = element; + + if ( newX == 0 && element.cols ) + newX = ( element.cols * 8 ) + 21; + + if ( newY == 0 && element.rows ) + newY = ( element.rows * 16 ) + 16; + + var editor = this.editor = $('').css({ + minHeight : ( newY - 6 ).toString() + 'px', + width : ( newX - 8 ).toString() + 'px' + }).attr('id', $(element).attr('id') + 'IFrame'); + + if ( $.browser.msie ) + { + this.editor + .css('height', ( newY ).toString() + 'px'); + + /** + var editor = $('').css({ + width : ( newX - 6 ).toString() + 'px', + height : ( newY - 8 ).toString() + 'px' + }).attr('id', $(element).attr('id') + 'IFrame'); + + editor.outerHTML = this.editor.outerHTML; + */ + } + } + + var panel = this.panel = $('
    ').addClass('panel'); + + this.appendControls(); + this.element = $('
    ').css({ + width : ( newX > 0 ) ? ( newX ).toString() + 'px' : '100%' + }).addClass('wysiwyg') + .append(panel) + .append( $('
    ').css({ clear : 'both' }) ) + .append(editor); + + $(element) + // .css('display', 'none') + .hide() + .before(this.element); + + this.viewHTML = false; + + this.initialHeight = newY - 8; + + /** + * @link http://code.google.com/p/jwysiwyg/issues/detail?id=52 + */ + this.initialContent = $(element).val(); + + this.initFrame(); + + if ( this.initialContent.length == 0 ) + this.setContent(''); + + if ( this.options.autoSave ) + $('form').submit(function() { self.saveContent(); }); + + $('form').bind('reset', function() + { + self.setContent( self.initialContent ); + self.saveContent(); + }); + }, + + initFrame : function() + { + var self = this; + var style = ''; + + /** + * @link http://code.google.com/p/jwysiwyg/issues/detail?id=14 + */ + if ( this.options.css && this.options.css.constructor == String ) + style = ''; + + this.editorDoc = $(this.editor).document(); + this.editorDoc_designMode = false; + + try { + this.editorDoc.designMode = 'on'; + this.editorDoc_designMode = true; + } catch ( e ) { + // Will fail on Gecko if the editor is placed in an hidden container element + // The design mode will be set ones the editor is focused + + $(this.editorDoc).focus(function() + { + self.designMode(); + }); + } + + this.editorDoc.open(); + this.editorDoc.write( + this.options.html + .replace(/INITIAL_CONTENT/, this.initialContent) + .replace(/STYLE_SHEET/, style) + ); + this.editorDoc.close(); + this.editorDoc.contentEditable = 'true'; + + if ( $.browser.msie ) + { + /** + * Remove the horrible border it has on IE. + */ + setTimeout(function() { $(self.editorDoc.body).css('border', 'none'); }, 0); + } + + $(this.editorDoc).click(function( event ) + { + self.checkTargets( event.target ? event.target : event.srcElement); + }); + + /** + * @link http://code.google.com/p/jwysiwyg/issues/detail?id=20 + */ + $(this.original).focus(function() + { + $(self.editorDoc.body).focus(); + }); + + if ( this.options.autoSave ) + { + /** + * @link http://code.google.com/p/jwysiwyg/issues/detail?id=11 + */ + $(this.editorDoc).keydown(function() { self.saveContent(); }) + .keyup(function() { self.saveContent(); }) + .mousedown(function() { self.saveContent(); }); + } + + if ( this.options.css ) + { + setTimeout(function() + { + if ( self.options.css.constructor == String ) + { + /** + * $(self.editorDoc) + * .find('head') + * .append( + * $('') + * .attr('href', self.options.css) + * ); + */ + } + else + $(self.editorDoc).find('body').css(self.options.css); + }, 0); + } + + $(this.editorDoc).keydown(function( event ) + { + if ( $.browser.msie && self.options.brIE && event.keyCode == 13 ) + { + var rng = self.getRange(); + rng.pasteHTML('
    '); + rng.collapse(false); + rng.select(); + + return false; + } + }); + }, + + designMode : function() + { + if ( !( this.editorDoc_designMode ) ) + { + try { + this.editorDoc.designMode = 'on'; + this.editorDoc_designMode = true; + } catch ( e ) {} + } + }, + + getSelection : function() + { + return ( window.getSelection ) ? window.getSelection() : document.selection; + }, + + getRange : function() + { + var selection = this.getSelection(); + + if ( !( selection ) ) + return null; + + return ( selection.rangeCount > 0 ) ? selection.getRangeAt(0) : selection.createRange(); + }, + + getContent : function() + { + return $( $(this.editor).document() ).find('body').html(); + }, + + setContent : function( newContent ) + { + $( $(this.editor).document() ).find('body').html(newContent); + }, + + saveContent : function() + { + if ( this.original ) + { + var content = this.getContent(); + + if ( this.options.rmUnwantedBr ) + content = ( content.substr(-4) == '
    ' ) ? content.substr(0, content.length - 4) : content; + + $(this.original).val(content); + } + }, + + appendMenu : function( cmd, args, className, fn ) + { + var self = this; + var args = args || []; + + $('
  • ').append( + $('
    ').addClass(className || cmd) + ).mousedown(function() { + if ( fn ) fn.apply(self); else self.editorDoc.execCommand(cmd, false, args); + if ( self.options.autoSave ) self.saveContent(); + }).appendTo( this.panel ); + }, + + appendMenuSeparator : function() + { + $('
  • ').appendTo( this.panel ); + }, + + appendControls : function() + { + for ( var name in this.options.controls ) + { + var control = this.options.controls[name]; + + if ( control.separator ) + { + if ( control.visible !== false ) + this.appendMenuSeparator(); + } + else if ( control.visible ) + { + this.appendMenu( + control.command || name, control.arguments || [], + control.className || control.command || name || 'empty', control.exec + ); + } + } + }, + + checkTargets : function( element ) + { + for ( var name in this.options.controls ) + { + var control = this.options.controls[name]; + var className = control.className || control.command || name || 'empty'; + + $('.' + className, this.panel).removeClass('active'); + + if ( control.tags ) + { + var elm = element; + + do { + if ( elm.nodeType != 1 ) + break; + + if ( $.inArray(elm.tagName.toLowerCase(), control.tags) != -1 ) + $('.' + className, this.panel).addClass('active'); + } while ( elm = elm.parentNode ); + } + + if ( control.css ) + { + var elm = $(element); + + do { + if ( elm[0].nodeType != 1 ) + break; + + for ( var cssProperty in control.css ) + if ( elm.css(cssProperty).toString().toLowerCase() == control.css[cssProperty] ) + $('.' + className, this.panel).addClass('active'); + } while ( elm = elm.parent() ); + } + } + }, + + getElementByAttributeValue : function( tagName, attributeName, attributeValue ) + { + var elements = this.editorDoc.getElementsByTagName(tagName); + + for ( var i = 0; i < elements.length; i++ ) + { + var value = elements[i].getAttribute(attributeName); + + if ( $.browser.msie ) + { + /** IE add full path, so I check by the last chars. */ + value = value.substr(value.length - attributeValue.length); + } + + if ( value == attributeValue ) + return elements[i]; + } + + return false; + } + }); +})(jQuery); \ No newline at end of file diff --git a/admin/template/page_index.php b/admin/template/page_index.php new file mode 100644 index 000000000..ba46d03cc --- /dev/null +++ b/admin/template/page_index.php @@ -0,0 +1,267 @@ + + + + +World of Warcraft Armory : Administration panel + + + + + + + + + + + + + + + + +// JavaScript Document +$(function () { + %s + + // first correct the timestamps - they are recorded as the daily + // midnights in UTC+0100, but Flot always displays dates in UTC + // so we have to add one hour to hit the midnights in the plot + for (var i = 0; i < d.length; ++i) + d[i][0] += 60 * 60 * 1000; + + // helper for returning the weekends in a period + function weekendAreas(axes) { + var markings = []; + var d = new Date(axes.xaxis.min); + // go to the first Saturday + d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) %% 7)) + d.setUTCSeconds(0); + d.setUTCMinutes(0); + d.setUTCHours(0); + var i = d.getTime(); + do { + // when we don\'t set yaxis the rectangle automatically + // extends to infinity upwards and downwards + markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000 } }); + i += 7 * 24 * 60 * 60 * 1000; + } while (i < axes.xaxis.max); + + return markings; + } + + var options = { + xaxis: { mode: "time" }, + selection: { mode: "xy" }, + lines: { show: true, fill: 0.5 }, + points: { show: true }, + yaxis: { min: 1, max: 1000 }, + grid: { markings: weekendAreas, hoverable: true, clickable: true, labelMargin: 10 }, + colors: ["#639ecb"], //639ecb //e03c42 + shadowSize: 2 + }; + function showTooltip(x, y, contents) { + $(\'
    \' + contents + \'
    \').css( { + position: \'absolute\', + display: \'none\', + top: y - 35, + left: x + 0, + color: \'#333\', + border: \'1px solid #999\', + padding: \'2px\', + \'background-color\': \'#EFEFEF\', + opacity: 0.80 + }).appendTo("body").fadeIn(200); + } + + var plot = $.plot($("#placeholder"), [d], options); + var previousPoint = null; + $("#placeholder").bind("plothover", function (event, pos, item) { + $("#x").text(pos.x.toFixed(2)); + $("#y").text(pos.y.toFixed(2)); + if (item) { + if (previousPoint != item.datapoint) { + previousPoint = item.datapoint; + + $("#tooltip").remove(); + var x = item.datapoint[0].toFixed(0), + y = item.datapoint[1].toFixed(0); + + if(y == 1) { + showTooltip(item.pageX, item.pageY, + y + " visitor"); + } + else { + showTooltip(item.pageX, item.pageY, + y + " visitors"); + } + } + } + else { + $("#tooltip").remove(); + previousPoint = null; + } + }); +}); +', Admin::GetJSFormattedVisitorsValue()); + break; + case 'news': + echo ''; + break; +} +?> + + + + +
    + + +
    + +
    Welcome, | Logout
    +
    + + + + +
    +
    + + + +
    + + + + + + diff --git a/admin/template/page_login.php b/admin/template/page_login.php new file mode 100644 index 000000000..8da99dbfb --- /dev/null +++ b/admin/template/page_login.php @@ -0,0 +1,47 @@ + + + + +World of Warcraft Armory : Login to administration panel + + + + + + + + +
    +
    +

    Login to administration panel

    +
    +

    You just need to hit the button and you're in!

    + Authentication required!

    '; + } + ?> +
    +

    + +

    +

    + +

    + Authentification +
    +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/includes/armory_loader.php b/includes/armory_loader.php index 977357424..96de77e3d 100644 --- a/includes/armory_loader.php +++ b/includes/armory_loader.php @@ -37,6 +37,20 @@ if(!@include(__ARMORYDIRECTORY__ . '/includes/defines.php')) { die('Error: unable to load defines.php!'); } +if(!@include(__ARMORYDIRECTORY__ . '/includes/classes/class.cacher.php')) { + die('Error: unable to load Cacher class!'); +} +/* SQL CACHER: IN DEVELOPMENT! */ +/* +if(isset($_GET['_DROPSQLCACHE_'])) { + $cacher = new Cacher(md5('1'), 'scalar'); + $cacher->DropAllCache(); + $cacher->Free(); + unset($cacher); + header('Location: index.xml'); + exit; +} +*/ if(!@include(__ARMORYDIRECTORY__ . '/includes/classes/class.armory.php')) { die('Error: unable to load Armory class!'); } @@ -48,27 +62,29 @@ Armory::InitializeArmory(); /* Check DbVersion */ -$dbVersion = Armory::$aDB->selectCell("SELECT `version` FROM `ARMORYDBPREFIX_db_version`"); -if($dbVersion != DB_VERSION) { - if(!$dbVersion) { +if(!defined('SKIP_DB')) { + $dbVersion = Armory::$aDB->selectCell("SELECT `version` FROM `ARMORYDBPREFIX_db_version`"); + if($dbVersion != DB_VERSION) { + if(!$dbVersion) { + if(isset(Armory::$armoryconfig['checkVersionType']) && Armory::$armoryconfig['checkVersionType'] == 'log') { + Armory::Log()->writeError('ArmoryChecker: wrong Armory DB name!'); + } + else { + echo 'Fatal error: wrong Armory DB name
    '; + } + } + $errorDBVersion = sprintf('Current version is %s but expected %s.
    + Apply all neccessary updates from \'sql/updates\' folder and refresh this page.', ($dbVersion) ? "'" . $dbVersion . "'" : 'not defined', "'" . DB_VERSION . "'"); if(isset(Armory::$armoryconfig['checkVersionType']) && Armory::$armoryconfig['checkVersionType'] == 'log') { - Armory::Log()->writeError('ArmoryChecker: wrong Armory DB name!'); + Armory::Log()->writeError('ArmoryChecker : DB_VERSION error: %s', (defined('DB_VERSION')) ? $errorDBVersion : 'DB_VERSION constant not defined!'); } else { - echo 'Fatal error: wrong Armory DB name
    '; - } - } - $errorDBVersion = sprintf('Current version is %s but expected %s.
    - Apply all neccessary updates from \'sql/updates\' folder and refresh this page.', ($dbVersion) ? "'" . $dbVersion . "'" : 'not defined', "'" . DB_VERSION . "'"); - if(isset(Armory::$armoryconfig['checkVersionType']) && Armory::$armoryconfig['checkVersionType'] == 'log') { - Armory::Log()->writeError('ArmoryChecker : DB_VERSION error: %s', (defined('DB_VERSION')) ? $errorDBVersion : 'DB_VERSION constant not defined!'); - } - else { - echo 'DB_VERSION error:
    '; - if(!defined('DB_VERSION')) { - die('DB_VERSION constant not defined!'); + echo 'DB_VERSION error:
    '; + if(!defined('DB_VERSION')) { + die('DB_VERSION constant not defined!'); + } + die($errorDBVersion); } - die($errorDBVersion); } } /* Check revision */ @@ -101,7 +117,7 @@ } error_reporting(E_ALL); /* Check maintenance */ -if(Armory::$armoryconfig['maintenance'] == true && !defined('MAINTENANCE_PAGE')) { +if(Armory::$armoryconfig['maintenance'] == true && !defined('MAINTENANCE_PAGE') && !defined('ADMIN_PAGE')) { header('Location: maintenance.xml'); exit; } @@ -112,6 +128,8 @@ $utils = new Utils(); // Check $_GET variable $utils->CheckVariablesForPage(); + // Update visitors count + $utils->UpdateVisitorsCount(); } /** Login **/ if(isset($_GET['login']) && $_GET['login'] == 1) { @@ -221,19 +239,32 @@ } if(defined('load_itemprototype_class')) { if(!@include(__ARMORYDIRECTORY__ . '/includes/classes/class.itemprototype.php')) { - die('Error: unable to load ItemPrototype Class!'); + die('Error: unable to load ItemPrototype class!'); } // Do not create class instance here. It should be created in Characters or Items classes. } if(defined('load_item_class')) { if(!@include(__ARMORYDIRECTORY__ . '/includes/classes/class.item.php')) { - die('Error: unable to load Item Class!'); + die('Error: unable to load Item class!'); } // Do not create class instance here. It should be created in Characters or Items classes. } +if(defined('ADMIN_PAGE')) { + if(!@include(__ARMORYDIRECTORY__ . '/includes/classes/class.template.php')) { + die('Error: unable to load template class!'); + } + if(!@include(__ARMORYDIRECTORY__ . '/includes/classes/class.admin.php')) { + die('Error: unable to load template class!'); + } + // Re-build account data from cookie. + Admin::InitializeAdmin(); + // Load locale + Template::LoadLocale( isset($_SESSION['admin_locale']) ? $_SESSION['admin_locale'] : 'en'); + // Do not create instances of these classes: they are using static methods. +} // Start XML parser if(!@include(__ARMORYDIRECTORY__ . '/includes/classes/class.xmlhandler.php')) { - die('Error: unable to load XML Handler Class!'); + die('Error: unable to load XML Handler class!'); } $xml = new XMLHandler(Armory::GetLocale()); if(!defined('RSS_FEED')) { diff --git a/includes/classes/class.admin.php b/includes/classes/class.admin.php new file mode 100644 index 000000000..3f9dc9927 --- /dev/null +++ b/includes/classes/class.admin.php @@ -0,0 +1,462 @@ +selectRow("SELECT `id`, `username`, `sha_pass_hash` FROM `account` WHERE `username` = '%s' AND `sha_pass_hash` = '%s' LIMIT 1", $username, self::CreateSha()); + if(!$user_data) { + Armory::Log()->writeError('%s : authentication for user %s was failed.', __METHOD__, $username); + return false; + } + $gm_level = 0; + switch(Armory::$realmData[1]['type']) { + default: + case SERVER_MANGOS: + $gm_level = Armory::$rDB->selectCell("SELECT `gmlevel` FROM `account` WHERE `id` = %d LIMIT 1", $user_data['id']); + break; + case SERVER_TRINITY: + $gm_level = Armory::$rDB->selectCell("SELECT `gmlevel` FROM `account_access` WHERE `id` = %d LIMIT 1", $user_data['id']); + break; + } + if($gm_level < 3) { + Armory::Log()->writeError('%s : unable to authorize user %s (ID: %d): only administrators can log in admin panel!', __METHOD__, $username, $user_data['id']); + return false; + } + self::$user_id = $user_data['id']; + self::$user_rights = $gm_level; + return self::CreateSessionData(); + } + + private static function CreateSha() { + if(!self::$user_name || !self::$user_pass) { + return 0; + } + self::$user_hash = sha1(strtoupper(self::$user_name) . ':' . strtoupper(self::$user_pass)); + return self::$user_hash; + } + + private static function CreateSessionData() { + $sess = array( + 'user_id' => self::$user_id, + 'user_name' => self::$user_name, + 'user_hash' => self::$user_hash, + 'user_rights' => self::$user_rights + ); + self::$user_session = $sess; + $session = ''; + foreach($sess as $session_key => $value) { + $session .= $session_key . ':' . $value .';'; + } + setcookie('armory_admin', $session, time() + 60*60*24*30); + $_SESSION['armory_admin_name'] = self::$user_name; + self::$is_logged_in = true; + return true; + } + + public static function PerformLogout() { + self::DestroyAccount(); + self::DestroySession(); + return true; + } + + private static function DestroyAccount() { + self::$user_id = 0; + self::$user_name = null; + self::$user_pass = null; + self::$user_hash = null; + self::$user_rights = 0; + self::$user_session = array(); + self::$is_logged_in = false; + return true; + } + + private static function DestroySession() { + if(!isset($_COOKIE['armory_admin'])) { + return true; + } + setcookie('armory_admin', ''); + unset($_COOKIE['armory_admin'], $_SESSION['armory_admin_name']); + } + + public static function GetRawVisitorsValue() { + return Armory::$aDB->select("SELECT `date`, `count` FROM `ARMORYDBPREFIX_visitors`"); + } + + public static function GetJSFormattedVisitorsValue() { + $visitors = self::GetRawVisitorsValue(); + $js_string = 'var d = [%s];'; + $tmpStr = ''; + if(is_array($visitors)) { + $count = count($visitors); + for($i = 0; $i < $count; ++$i) { + $tmpStr .= sprintf('[%d, %d],', $visitors[$i]['date'], $visitors[$i]['count']); + } + } + return sprintf($js_string, $tmpStr); + } + + public static function GetNotifications() { + /* + types: + + error + warning + info + success + */ + $notifications = array(); + // Check for icons + if(!file_exists(__ARMORYDIRECTORY__ . '/wow-icons/_images/21x21/ability_ambush.png')) { + $notifications[] = array( + 'type' => 'error', + 'message' => 'Icons were not found!' + ); + } + // Check for .htaccess files + $htaccess_files = array( + '/.htaccess', + '/_content/.htaccess', + '/_data/.htaccess', + '/_layout/.htaccess', + '/data/.htaccess' + ); + foreach($htaccess_files as $htaccess) { + if(!file_exists(__ARMORYDIRECTORY__ . $htaccess)) { + $notifications[] = array( + 'type' => 'error', + 'message' => 'Not all .htaccess files were found!' + ); + break; + } + } + return $notifications; + } + + public static function UpdateConfigFile($configs) { + if(!is_array($configs)) { + Armory::Log()->writeError('%s : unable to update configs: $configs must be an array!', __METHOD__); + return false; + } + $config_template = sprintf("writeError('%s : unable to add new realm: $configs must be an array!', __METHOD__); + return false; + } + $realm_config_template = sprintf(" +\$ArmoryConfig['multiRealm'][%d]['id'] = %d; +\$ArmoryConfig['multiRealm'][%d]['name'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['type'] = %s; +\$ArmoryConfig['multiRealm'][%d]['host_characters'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['user_characters'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['pass_characters'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['name_characters'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['charset_characters'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['host_world'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['user_world'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['pass_world'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['name_world'] = '%s'; +\$ArmoryConfig['multiRealm'][%d]['charset_world'] = '%s'; +", + $configs['realmID'], $configs['realmID'], + $configs['realmID'], $configs['realmName'], + $configs['realmID'], $configs['realmType'] == 1 ? 'SERVER_MANGOS' : 'SERVER_TRINITY', + $configs['realmID'], $configs['realmCharsHost'], + $configs['realmID'], $configs['realmCharsUser'], + $configs['realmID'], $configs['realmCharsPassword'], + $configs['realmID'], $configs['realmCharsName'], + $configs['realmID'], $configs['realmCharsCharset'], + $configs['realmID'], $configs['realmWorldHost'], + $configs['realmID'], $configs['realmWorldUser'], + $configs['realmID'], $configs['realmWorldPassword'], + $configs['realmID'], $configs['realmWorldName'], + $configs['realmID'], $configs['realmWorldCharset'] + ); + file_put_contents(__ARMORYDIRECTORY__ . '/includes/classes/configuration.php', $realm_config_template, FILE_APPEND); + return true; + } + + public static function GetAccountsList($offset = 1, $sort_by = 'id', $sort_type = 'ASC', $search = null) { + $limit = 20 * ($offset - 1); + $type = SERVER_MANGOS; + // Detect: trinity or mangos realmd database + Armory::$rDB->SkipNextError(); + $access_table = Armory::$rDB->selectCell("SELECT 1 FROM `account_access`"); + if($access_table) { + $type = SERVER_TRINITY; + } + switch($type) { + case SERVER_MANGOS: + if($search != null) { + $accounts = Armory::$rDB->select("SELECT * FROM `account` WHERE `username` LIKE '%%%s%%' ORDER BY `%s` %s LIMIT %d, 20", $search, $sort_by, $sort_type, $limit); + } + else { + $accounts = Armory::$rDB->select("SELECT * FROM `account` ORDER BY `%s` %s LIMIT %d, 20", $sort_by, $sort_type, $limit); + } + break; + case SERVER_TRINITY: + if($search != null) { + $accounts = Armory::$rDB->select(" + SELECT + `account`.`id`, + `account`.`username`, + `account`.`sha_pass_hash`, + `account`.`email`, + `account`.`last_ip`, + `account`.`last_login`, + `account`.`expansion`, + `account_access`.`gmlevel` + FROM `account` + JOIN `account_access` ON `account_access`.`id` = `account`.`id` + WHERE `account_access`.`RealmID` = -1 + AND `account`.`username` LIKE '%%%s%%' + ORDER BY `account`.`%s` %s + LIMIT %d, 20 + ", $search, $sort_by, $sort_type, $limit); + } + else { + $accounts = Armory::$rDB->select(" + SELECT + `account`.`id`, + `account`.`username`, + `account`.`sha_pass_hash`, + `account`.`email`, + `account`.`last_ip`, + `account`.`last_login`, + `account`.`expansion`, + `account_access`.`gmlevel` + FROM `account` + JOIN `account_access` ON `account_access`.`id` = `account`.`id` + WHERE `account_access`.`RealmID` = -1 + ORDER BY `account`.`%s` %s + LIMIT %d, 20 + ", $sort_by, $sort_type, $limit); + } + break; + } + return $accounts; + } + + public static function GetAccount($id) { + if($id <= 0) { + Armory::Log()->writeError('%s : user id must be > 0 (%d given.)!', __METHOD__, $id); + return false; + } + return Armory::$rDB->selectRow("SELECT * FROM `account` WHERE `id` = %d LIMIT 1", $id); + } + + public static function UpdateAccount($info) { + if(!is_array($info)) { + Armory::Log()->writeError('%s : unable to update user: $info must be an array (%s given)!', __METHOD__, gettype($info)); + return false; + } + if(!isset($info['gmlevel'])) { + // Find + Armory::$rDB->SkipNextError(); + $realms = Armory::$rDB->select("SELECT `RealmID` FROM `account_access` WHERE `id` = %d", $info['id']); + if(is_array($realms)) { + foreach($realms as $realm) { + if(isset($info['gmlevel_' . $realm['RealmID']])) { + Armory::$rDB->query("UPDATE `account_access` SET `gmlevel` = %d WHERE `RealmID` = %d AND `id` = %d", $info['gmlevel_' . $realm['RealmID']], $realm['RealmID'], $info['id']); + } + } + } + Armory::$rDB->query("UPDATE `account` SET `username` = '%s', `sha_pass_hash` = '%s', `v` = '', `s` = '', `email` = '%s', `joindate` = '%s', `last_ip` = '%s', `locked` = %d, `last_login` = '%s', `expansion` = %d WHERE `id` = %d LIMIT 1", + $info['username'], $info['sha_pass_hash'], $info['email'], $info['joindate'], $info['last_ip'], $info['locked'], $info['last_login'], $info['expansion'], $info['id'] + ); + } + else { + Armory::$rDB->query("UPDATE `account` SET `username` = '%s', `sha_pass_hash` = '%s', `gmlevel` = %d, `v` = '', `s` = '', `email` = '%s', `joindate` = '%s', `last_ip` = '%s', `locked` = %d, `last_login` = '%s', `expansion` = %d WHERE `id` = %d LIMIT 1", + $info['username'], $info['sha_pass_hash'], $info['gmlevel'], $info['email'], $info['joindate'], $info['last_ip'], $info['locked'], $info['last_login'], $info['expansion'], $info['id'] + ); + } + return true; + } + + public static function DeleteAccount($id) { + if($id <= 0) { + Armory::Log()->writeError('%s : account id must be > 0 (%d given)!', __METHOD__, $id); + return false; + } + Armory::$rDB->query("DELETE FROM `account` WHERE `id` = %d LIMIT 1", $id); + return true; + } +} +?> \ No newline at end of file diff --git a/includes/classes/class.armory.php b/includes/classes/class.armory.php index 9b7321d0e..741211b6b 100644 --- a/includes/classes/class.armory.php +++ b/includes/classes/class.armory.php @@ -80,37 +80,39 @@ public static function InitializeArmory() { self::$armoryconfig = $ArmoryConfig['settings']; self::$debugHandler = new ArmoryDebug(array('useDebug' => self::$armoryconfig['useDebug'], 'logLevel' => self::$armoryconfig['logLevel'])); self::$realmData = $ArmoryConfig['multiRealm']; - self::$aDB = new ArmoryDatabaseHandler(self::$mysqlconfig['host_armory'], self::$mysqlconfig['user_armory'], self::$mysqlconfig['pass_armory'], self::$mysqlconfig['name_armory'], self::$mysqlconfig['charset_armory'], self::$armoryconfig['db_prefix']); - self::$rDB = new ArmoryDatabaseHandler(self::$mysqlconfig['host_realmd'], self::$mysqlconfig['user_realmd'], self::$mysqlconfig['pass_realmd'], self::$mysqlconfig['name_realmd'], self::$mysqlconfig['charset_realmd']); - if(isset($_GET['r'])) { - if(preg_match('/,/', $_GET['r'])) { - // Achievements/statistics comparison cases - $rData = explode(',', $_GET['r']); - $realmName = urldecode($rData[0]); + if(!defined('SKIP_DB')) { + self::$aDB = new ArmoryDatabaseHandler(self::$mysqlconfig['host_armory'], self::$mysqlconfig['user_armory'], self::$mysqlconfig['pass_armory'], self::$mysqlconfig['name_armory'], self::$mysqlconfig['charset_armory'], self::$armoryconfig['db_prefix']); + self::$rDB = new ArmoryDatabaseHandler(self::$mysqlconfig['host_realmd'], self::$mysqlconfig['user_realmd'], self::$mysqlconfig['pass_realmd'], self::$mysqlconfig['name_realmd'], self::$mysqlconfig['charset_realmd']); + if(isset($_GET['r'])) { + if(preg_match('/,/', $_GET['r'])) { + // Achievements/statistics comparison cases + $rData = explode(',', $_GET['r']); + $realmName = urldecode($rData[0]); + } + else { + $realmName = urldecode($_GET['r']); + } + $realm_id = self::FindRealm($realmName); + if(isset(self::$realmData[$realm_id])) { + self::$connectionData = self::$realmData[$realm_id]; + self::$cDB = new ArmoryDatabaseHandler(self::$connectionData['host_characters'], self::$connectionData['user_characters'], self::$connectionData['pass_characters'], self::$connectionData['name_characters'], self::$connectionData['charset_characters']); + self::$currentRealmInfo = array('name' => self::$connectionData['name'], 'id' => $realm_id, 'type' => self::$connectionData['type'], 'connected' => true); + self::$wDB = new ArmoryDatabaseHandler(self::$connectionData['host_world'], self::$connectionData['user_world'], self::$connectionData['pass_world'], self::$connectionData['name_world'], self::$connectionData['charset_world']); + } } - else { - $realmName = urldecode($_GET['r']); + $realm_info = self::$realmData[1]; + if(self::$cDB == null) { + self::$cDB = new ArmoryDatabaseHandler($realm_info['host_characters'], $realm_info['user_characters'], $realm_info['pass_characters'], $realm_info['name_characters'], $realm_info['charset_characters']); } - $realm_id = self::FindRealm($realmName); - if(isset(self::$realmData[$realm_id])) { - self::$connectionData = self::$realmData[$realm_id]; - self::$cDB = new ArmoryDatabaseHandler(self::$connectionData['host_characters'], self::$connectionData['user_characters'], self::$connectionData['pass_characters'], self::$connectionData['name_characters'], self::$connectionData['charset_characters']); - self::$currentRealmInfo = array('name' => self::$connectionData['name'], 'id' => $realm_id, 'type' => self::$connectionData['type'], 'connected' => true); - self::$wDB = new ArmoryDatabaseHandler(self::$connectionData['host_world'], self::$connectionData['user_world'], self::$connectionData['pass_world'], self::$connectionData['name_world'], self::$connectionData['charset_world']); + if(self::$wDB == null) { + self::$wDB = new ArmoryDatabaseHandler($realm_info['host_world'], $realm_info['user_world'], $realm_info['pass_world'], $realm_info['name_world'], $realm_info['charset_world']); + } + if(!self::$currentRealmInfo) { + self::$currentRealmInfo = array('name' => $realm_info['name'], 'id' => 1, 'type' => $realm_info['type'], 'connected' => true); + } + if(!self::$connectionData) { + self::$connectionData = $realm_info; } - } - $realm_info = self::$realmData[1]; - if(self::$cDB == null) { - self::$cDB = new ArmoryDatabaseHandler($realm_info['host_characters'], $realm_info['user_characters'], $realm_info['pass_characters'], $realm_info['name_characters'], $realm_info['charset_characters']); - } - if(self::$wDB == null) { - self::$wDB = new ArmoryDatabaseHandler($realm_info['host_world'], $realm_info['user_world'], $realm_info['pass_world'], $realm_info['name_world'], $realm_info['charset_world']); - } - if(!self::$currentRealmInfo) { - self::$currentRealmInfo = array('name' => $realm_info['name'], 'id' => 1, 'type' => $realm_info['type'], 'connected' => true); - } - if(!self::$connectionData) { - self::$connectionData = $realm_info; } if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $user_locale = strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2)); diff --git a/includes/classes/class.dbhandler.php b/includes/classes/class.dbhandler.php index 667a7a736..890405a66 100644 --- a/includes/classes/class.dbhandler.php +++ b/includes/classes/class.dbhandler.php @@ -188,7 +188,7 @@ private function _query($safe_sql, $queryType) { } $query_end = microtime(true); $queryTime = round($query_end - $query_start, 4); - //Armory::Log()->writeSql('[%s ms]: %s', $queryTime, $safe_sql); + Armory::Log()->writeSql('[%s ms]: %s', $queryTime, $safe_sql); $this->queryTimeGeneration += $queryTime; return $result; } diff --git a/includes/classes/class.debug.php b/includes/classes/class.debug.php index cbf427ec0..f7042f3c5 100644 --- a/includes/classes/class.debug.php +++ b/includes/classes/class.debug.php @@ -28,7 +28,7 @@ * Log config **/ private $config; - private $file = 'cache/_debug/tmp.dbg'; + private $file = ''; /** * Initializes debugger @@ -38,13 +38,14 @@ public function ArmoryDebug($config, $file = false) { return; } $this->config = $config; + $this->file = __ARMORYDIRECTORY__ . '/cache/_debug/tmp.dbg'; if($file) { $this->file = $file; } } public function writeLog($logtext) { - if($this->config['useDebug'] == false || $this->config['logLevel'] == 1) { + if($this->config['useDebug'] == false || $this->config['logLevel'] < 2) { return; } $args = func_get_args(); @@ -68,7 +69,7 @@ public function writeError($errorText) { } public function writeSql($sqlText) { - if($this->config['useDebug'] == false || $this->config['logLevel'] == 1) { + if($this->config['useDebug'] == false || $this->config['logLevel'] < 3) { return; } $args = func_get_args(); diff --git a/includes/classes/class.template.php b/includes/classes/class.template.php new file mode 100644 index 000000000..e54436e38 --- /dev/null +++ b/includes/classes/class.template.php @@ -0,0 +1,109 @@ +writeError('%s : unable to find localization for string "%s": locale storage is empty!', __METHOD__, $string); + return $string; + } + if(!isset(self::$template_locale[$string])) { + Armory::Log()->writeError('%s : string "%s" was not found in locale storage!', __METHOD__, $string); + return $string; + } + return self::$template_locale[$string]; + } + + public static function SetTemplateTheme($theme) { + self::$template_theme = $theme; + } + + public static function GetTemplateTheme() { + return self::$template_theme != null ? self::$template_theme : 'overall'; + } + + public static function LoadTemplate($template_name, $overall = false) { + if($overall) { + $template = __ARMORYDIRECTORY__ . '/admin/template/overall/overall_' . $template_name . '.php'; + } + else { + $template = __ARMORYDIRECTORY__ . '/admin/template/' . $template_name . '.php'; + } + if(file_exists($template)) { + include($template); + } + else { + Armory::Log()->writeError('%s : unable to find template "%s" (template theme: %s, overall: %d, path: %s)!', __METHOD__, $template_name, self::GetTemplateTheme(), (int) $overall, $template); + } + } + + public static function GetPageIndex() { + return self::$page_index; + } + + public static function SetPageIndex($index) { + self::$page_index = $index; + } + + public static function GetPageData($index) { + return (isset(self::$page_data[$index])) ? self::$page_data[$index] : null; + } + + public static function SetPageData($index, $data) { + self::$page_data[$index] = $data; + } + + public static function AddToPageData($index, $data) { + if(!isset(self::$page_data[$index])) { + return true; + } + self::$page_data[$index] .= $data; + } +} +?> \ No newline at end of file diff --git a/includes/classes/class.utils.php b/includes/classes/class.utils.php index d36410d90..a44cdce89 100644 --- a/includes/classes/class.utils.php +++ b/includes/classes/class.utils.php @@ -1393,21 +1393,52 @@ public function GetFactionId($raceID) { * @category Utils class * @access public * @param bool $feed = false + * @param int $itemId = 0 * @return array **/ - public function GetArmoryNews($feed = false) { - $news = Armory::$aDB->select("SELECT `id`, `date`, `title_en_gb` AS `titleOriginal`, `title_%s` AS `titleLoc`, `text_en_gb` AS `textOriginal`, `text_%s` AS `textLoc` FROM `ARMORYDBPREFIX_news` WHERE `display`=1 ORDER BY `date` DESC", Armory::GetLocale(), Armory::GetLocale()); + public function GetArmoryNews($feed = false, $itemId = 0, $empty = false) { + if(Armory::$armoryconfig['useNews'] == false && !defined('ADMIN_PAGE')) { + return false; + } + if($empty) { + return array( + 'id' => Armory::$aDB->selectCell("SELECT MAX(`id`)+1 FROM `ARMORYDBPREFIX_news`"), + 'date' => time(), + 'title_de_de' => null, + 'title_en_gb' => null, + 'title_es_es' => null, + 'title_fr_fr' => null, + 'title_ru_ru' => null, + 'text_de_de' => null, + 'text_en_gb' => null, + 'text_es_es' => null, + 'text_fr_fr' => null, + 'text_ru_ru' => null, + 'display' => 1 + ); + } + if($itemId > 0) { + $newsitem = Armory::$aDB->selectRow("SELECT * FROM `ARMORYDBPREFIX_news` WHERE `id` = %d", $itemId); + $locales = array('de_de', 'en_gb', 'es_es', 'fr_fr', 'ru_ru'); + foreach($locales as $loc) { + $newsitem['title_' . $loc] = stripcslashes($newsitem['title_' . $loc]); + $newsitem['text_' . $loc] = stripcslashes($newsitem['text_' . $loc]); + } + return $newsitem; + } + $news = Armory::$aDB->select("SELECT `id`, `date`, `title_en_gb` AS `titleOriginal`, `title_%s` AS `titleLoc`, `text_en_gb` AS `textOriginal`, `text_%s` AS `textLoc` FROM `ARMORYDBPREFIX_news`%s ORDER BY `date` DESC", Armory::GetLocale(), Armory::GetLocale(), !defined('ADMIN_PAGE') ? ' WHERE `display`=1' : null); if(!$news) { return false; } $allNews = array(); $i = 0; foreach($news as $new) { - $allNews[$i] = array(); - if($feed == true) { - $allNews[$i]['date'] = date('d m Y', $new['date']); - } - else { + $allNews[$i] = array( + 'id' => $new['id'], + 'date' => date('d m Y', $new['date']) + ); + $allNews[$i]['id'] = $new['id']; + if(!$feed) { $allNews[$i]['posted'] = date('Y-m-d\TH:i:s\Z', $new['date']); } if(!isset($new['titleLoc']) || empty($new['titleLoc'])) { @@ -1431,6 +1462,48 @@ public function GetArmoryNews($feed = false) { return false; } + public function AddNewsItem($newsItem, $update = false) { + if(!is_array($newsItem)) { + Armory::Log()->writeError('%s : $newsItem must be an array (%s given.)!', __METHOD__, gettype($newsItem)); + return 'error_array'; + } + if($update) { + $sql_query = "UPDATE `ARMORYDBPREFIX_news` SET `date` = %d, + `title_de_de` = '%s', `title_en_gb` = '%s', `title_es_es` = '%s', `title_fr_fr` = '%s', `title_ru_ru` = '%s', + `text_de_de` = '%s', `text_en_gb` = '%s', `text_es_es` = '%s', `text_fr_fr` = '%s', `text_ru_ru` = '%s', + `display` = %d + WHERE `id` = %d"; + $id = $newsItem['id']; + } + else { + $sql_query = "INSERT INTO `ARMORYDBPREFIX_news` + (`date`, `title_de_de`, `title_en_gb`, `title_es_es`, `title_fr_fr`, `title_ru_ru`, + `text_de_de`, `text_en_gb`, `text_es_es`, `text_fr_fr`, `text_ru_ru`, `id`) + VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)"; + $id = Armory::$aDB->selectCell("SELECT MAX(`id`)+1 FROM `ARMORYDBPREFIX_news`"); + } + $newsItem['date'] = strtotime($newsItem['date']); + if(!Armory::$aDB->query($sql_query, + $newsItem['date'], + $newsItem['title_de_de'], + $newsItem['title_en_gb'], + $newsItem['title_es_es'], + $newsItem['title_fr_fr'], + $newsItem['title_ru_ru'], + $newsItem['text_de_de'], + $newsItem['text_en_gb'], + $newsItem['text_es_es'], + $newsItem['text_fr_fr'], + $newsItem['text_ru_ru'], + isset($newsItem['display']) ? 1 : 0, + $id + )) { + return 'error_insert'; + } + header('Location: ?action=news&subaction=added'); + exit; + } + /** * Checks for active session & cookie for dual items tooltips * @category Utils class @@ -1867,5 +1940,17 @@ private function IsUserAdmin() { } return false; } + + public function UpdateVisitorsCount() { + if(!isset($_COOKIE['armory_visited'])) { + if(!Armory::$aDB->selectCell("SELECT 1 FROM `ARMORYDBPREFIX_visitors` WHERE `date` = %d", strtotime('TODAY'))) { + Armory::$aDB->query("INSERT INTO `ARMORYDBPREFIX_visitors` SET `date` = %d, `count` = 1", strtotime('TODAY')); + } + else { + Armory::$aDB->query("UPDATE `ARMORYDBPREFIX_visitors` SET `count`= `count` + 1 WHERE `date` = %d", strtotime('TODAY')); + } + setcookie('armory_visited', 1, strtotime('TOMORROW')); + } + } } ?> \ No newline at end of file diff --git a/includes/revision_nr.php b/includes/revision_nr.php index adf70b6f7..efe7467d3 100644 --- a/includes/revision_nr.php +++ b/includes/revision_nr.php @@ -1,5 +1,5 @@ \ No newline at end of file