From da3ce46d14e4965f3e3977caefa3b47caef5453a Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 9 Aug 2011 07:29:08 +0000 Subject: [PATCH 001/472] added Laotian language to setup --- setup/lang/languages | 1 + 1 file changed, 1 insertion(+) diff --git a/setup/lang/languages b/setup/lang/languages index 04d5611c3e..11a4aa980d 100644 --- a/setup/lang/languages +++ b/setup/lang/languages @@ -19,6 +19,7 @@ it Italiano iw Hebrew ja Japanese ko Korean +lo Laotian lt Lithuanian lv Latvian nl Dutch From 91545df1e6980bb1489d74b1d765ebe414e76377 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 9 Aug 2011 10:07:22 +0000 Subject: [PATCH 002/472] * eSync/Addressbook: added mapping of private cellphone to home2phone, other phone to business2phonenumber and changed role to title in mapping of jobtitle (role is no longer mapped, because no outlook equivalent, egw prefix is mapped to ol title!) --- .../inc/class.addressbook_activesync.inc.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/addressbook/inc/class.addressbook_activesync.inc.php b/addressbook/inc/class.addressbook_activesync.inc.php index 92900595f8..2c67e03dda 100644 --- a/addressbook/inc/class.addressbook_activesync.inc.php +++ b/addressbook/inc/class.addressbook_activesync.inc.php @@ -42,7 +42,7 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug 'body' => 'note', //'bodysize' => '', //'bodytruncated' => '', - //'business2phonenumber' => '', + 'business2phonenumber' => 'tel_other', 'businesscity' => 'adr_one_locality', 'businesscountry' => 'adr_one_countryname', 'businesspostalcode' => 'adr_one_postalcode', @@ -52,7 +52,7 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug 'businessphonenumber' => 'tel_work', 'carphonenumber' => 'tel_car', 'categories' => 'cat_id', - //'children' => '', + //'children' => '', // collection of 'child' elements 'companyname' => 'org_name', 'department' => 'org_unit', 'email1address' => 'email', @@ -60,7 +60,7 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug //'email3address' => '', 'fileas' => 'n_fileas', 'firstname' => 'n_given', - //'home2phonenumber' => '', + 'home2phonenumber' => 'tel_cell_private', 'homecity' => 'adr_two_locality', 'homecountry' => 'adr_two_countryname', 'homepostalcode' => 'adr_two_postalcode', @@ -68,7 +68,7 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug 'homestreet' => 'adr_two_street', 'homefaxnumber' => 'tel_fax_home', 'homephonenumber' => 'tel_home', - 'jobtitle' => 'role', + 'jobtitle' => 'title', // unfortunatly outlook only has title & jobtitle, while EGw has 'n_prefix', 'title' & 'role', 'lastname' => 'n_family', 'middlename' => 'n_middle', 'mobilephonenumber' => 'tel_cell', @@ -82,7 +82,7 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug //'radiophonenumber' => '', //'spouse' => '', 'suffix' => 'n_suffix', - 'title' => 'n_prefix', + 'title' => 'n_prefix', 'webpage' => 'url', //'yomicompanyname' => '', //'yomifirstname' => '', @@ -533,6 +533,9 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug $contact[$attr] = $message->$key; } break; + case 'title': // as ol jobtitle mapping changed in egw from role to title, do NOT overwrite title with value of role + if ($id && $message->$key == $contact['role']) break; + // fall throught default: $contact[$attr] = $message->$key; break; From 9de3b4afc90acfe79b1432e3e43099c320fff9da Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 9 Aug 2011 18:19:58 +0000 Subject: [PATCH 003/472] Use similar_text() to try to automatically match import field names to application fields when there's no exact match --- ...portexport_wizard_basic_import_csv.inc.php | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/importexport/inc/class.importexport_wizard_basic_import_csv.inc.php b/importexport/inc/class.importexport_wizard_basic_import_csv.inc.php index d86ffceb04..0a1429960d 100644 --- a/importexport/inc/class.importexport_wizard_basic_import_csv.inc.php +++ b/importexport/inc/class.importexport_wizard_basic_import_csv.inc.php @@ -138,11 +138,13 @@ class importexport_wizard_basic_import_csv # Copy already set, but allow new file to update $content['field_mapping'][$index] = $content['plugin_options']['field_mapping'][$index]; } + $best_match = ''; + $best_match_value = 0; foreach($this->mapping_fields as $key => $field_name) { if(is_array($field_name)) continue; if(strcasecmp($field, $field_name) == 0 || strcasecmp($field,$key) == 0) { $content['field_mapping'][$index] = $key; - continue; + continue 2; } // Check english also if($GLOBALS['egw_info']['user']['preferences']['common']['lang'] != 'en' && !isset($english[$field_name])) { @@ -155,8 +157,22 @@ class importexport_wizard_basic_import_csv } if($english[$field_name] && strcasecmp($field, $english[$field_name]) == 0) { $content['field_mapping'][$index] = $key; - continue; + continue 2; } + + // Check for similar but slightly different + $match = 0; + if(similar_text(strtolower($field), strtolower($field_name), $match) && + $match > 85 && + $match > $best_match_value + ) { + $best_match = $key; + $best_match_value = $match; + } + + } + if($best_match) { + $content['field_mapping'][$index] = $best_match; } } } elseif($content['plugin_options']['csv_fields']) { From e15b7304bc7b755f2836b990e84070f26a0b8e69 Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 9 Aug 2011 19:14:03 +0000 Subject: [PATCH 004/472] Unset empty private, it causes issues trying to find them --- addressbook/inc/class.addressbook_import_contacts_csv.inc.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addressbook/inc/class.addressbook_import_contacts_csv.inc.php b/addressbook/inc/class.addressbook_import_contacts_csv.inc.php index 7752c0195e..d0a576f6b2 100644 --- a/addressbook/inc/class.addressbook_import_contacts_csv.inc.php +++ b/addressbook/inc/class.addressbook_import_contacts_csv.inc.php @@ -202,6 +202,9 @@ class addressbook_import_contacts_csv implements importexport_iface_import_plugi } if(count($more_categories) > 0) $record['cat_id'] = array_merge(is_array($record['cat_id']) ? $record['cat_id'] : explode(',',$record['cat_id']), $more_categories); + // Private set but missing causes hidden entries + if(array_key_exists('private', $record) && (!isset($record['private']) || $record['private'] == '')) unset($record['private']); + if ( $_definition->plugin_options['conditions'] ) { foreach ( $_definition->plugin_options['conditions'] as $condition ) { $contacts = array(); From 1c2486e05856c5e6ab8bd350f9e7c726599bb417 Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 9 Aug 2011 19:39:24 +0000 Subject: [PATCH 005/472] Fix handling of colors in hex format --- etemplate/templates/default/msoffice.xslt | 18 ++++++++++++------ etemplate/templates/default/openoffice.xslt | 13 ++++++++++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/etemplate/templates/default/msoffice.xslt b/etemplate/templates/default/msoffice.xslt index 3abf53856e..a9b8eb1431 100644 --- a/etemplate/templates/default/msoffice.xslt +++ b/etemplate/templates/default/msoffice.xslt @@ -150,12 +150,11 @@ Breakers - + - - + @@ -163,9 +162,16 @@ Breakers - - - + + + + + + + + + + diff --git a/etemplate/templates/default/openoffice.xslt b/etemplate/templates/default/openoffice.xslt index 3dc9097d3d..40ea262748 100644 --- a/etemplate/templates/default/openoffice.xslt +++ b/etemplate/templates/default/openoffice.xslt @@ -167,9 +167,16 @@ - - - + + + + + + + + + + From ff89732b243da4aeb0cc44a38bb90a9e45453f12 Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 9 Aug 2011 20:41:16 +0000 Subject: [PATCH 006/472] As lists & tables aren't supported in OO calc, fake it --- etemplate/templates/default/openoffice.xslt | 24 ++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/etemplate/templates/default/openoffice.xslt b/etemplate/templates/default/openoffice.xslt index 40ea262748..c4b773deed 100644 --- a/etemplate/templates/default/openoffice.xslt +++ b/etemplate/templates/default/openoffice.xslt @@ -216,18 +216,26 @@ - + - + + + + + + + + + @@ -240,13 +248,20 @@ - + + + + + + + + @@ -270,6 +285,9 @@ + + + From 9cd080e2ef715ec7632ea189ef6cdde606b0dada Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 9 Aug 2011 20:58:41 +0000 Subject: [PATCH 007/472] Fix hex color values for background color --- etemplate/templates/default/openoffice.xslt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/etemplate/templates/default/openoffice.xslt b/etemplate/templates/default/openoffice.xslt index c4b773deed..300355f3e7 100644 --- a/etemplate/templates/default/openoffice.xslt +++ b/etemplate/templates/default/openoffice.xslt @@ -182,9 +182,16 @@ - - - + + + + + + + + + + From a30b864ddda2ba3ec96ab072983104c5a79dc4de Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 9 Aug 2011 23:10:50 +0000 Subject: [PATCH 008/472] Add jqplot for graphing --- phpgwapi/js/jquery/jqplot/MIT-LICENSE.txt | 21 + phpgwapi/js/jquery/jqplot/README.txt | 77 + phpgwapi/js/jquery/jqplot/changes.txt | 395 + phpgwapi/js/jquery/jqplot/copyright.txt | 29 + .../jqplot/docs/files/MIT-LICENSE-txt.html | 39 + .../jquery/jqplot/docs/files/changes-txt.html | 39 + .../jquery/jqplot/docs/files/gpl-2-0-txt.html | 39 + .../jqplot/docs/files/images/background.jpg | Bin 0 -> 1101 bytes .../jqplot/docs/files/images/basicline.png | Bin 0 -> 17024 bytes .../jqplot/docs/files/images/basiclogaxis.png | Bin 0 -> 19902 bytes .../docs/files/images/basiclogoptions.png | Bin 0 -> 17207 bytes .../jqplot/docs/files/images/basicoptions.png | Bin 0 -> 19864 bytes .../jqplot/docs/files/images/dualaxis.png | Bin 0 -> 29672 bytes .../jquery/jqplot/docs/files/images/logo.jpg | Bin 0 -> 14632 bytes .../jqplot/docs/files/images/navdocs.png | Bin 0 -> 996 bytes .../jqplot/docs/files/images/navdocsover.png | Bin 0 -> 1006 bytes .../jqplot/docs/files/images/navdownload.png | Bin 0 -> 1236 bytes .../docs/files/images/navdownloadover.png | Bin 0 -> 1265 bytes .../jqplot/docs/files/images/navexamples.png | Bin 0 -> 1308 bytes .../docs/files/images/navexamplesover.png | Bin 0 -> 1332 bytes .../jqplot/docs/files/images/navhome.png | Bin 0 -> 858 bytes .../jqplot/docs/files/images/navhomeover.png | Bin 0 -> 886 bytes .../jquery/jqplot/docs/files/images/new.png | Bin 0 -> 13750 bytes .../jqplot/docs/files/images/sample3.png | Bin 0 -> 44781 bytes .../jqplot/docs/files/images/samplesm.png | Bin 0 -> 20874 bytes .../docs/files/jqPlotCssStyling-txt.html | 39 + .../jqplot/docs/files/jqPlotOptions-txt.html | 292 + .../files/jqplot-axisLabelRenderer-js.html | 47 + .../files/jqplot-axisTickRenderer-js.html | 71 + .../files/jqplot-canvasGridRenderer-js.html | 39 + .../jqplot/docs/files/jqplot-core-js.html | 359 + .../files/jqplot-divTitleRenderer-js.html | 39 + .../docs/files/jqplot-lineRenderer-js.html | 53 + .../files/jqplot-linearAxisRenderer-js.html | 49 + .../docs/files/jqplot-markerRenderer-js.html | 65 + .../docs/files/jqplot-shadowRenderer-js.html | 61 + .../docs/files/jqplot-shapeRenderer-js.html | 63 + .../docs/files/jqplot-themeEngine-js.html | 190 + .../docs/files/optionsTutorial-txt.html | 119 + .../jqplot-BezierCurveRenderer-js.html | 45 + .../files/plugins/jqplot-barRenderer-js.html | 67 + .../plugins/jqplot-blockRenderer-js.html | 53 + .../plugins/jqplot-bubbleRenderer-js.html | 71 + .../jqplot-canvasAxisLabelRenderer-js.html | 63 + .../jqplot-canvasAxisTickRenderer-js.html | 79 + .../plugins/jqplot-canvasOverlay-js.html | 197 + .../jqplot-categoryAxisRenderer-js.html | 46 + .../files/plugins/jqplot-ciParser-js.html | 39 + .../docs/files/plugins/jqplot-cursor-js.html | 93 + .../plugins/jqplot-dateAxisRenderer-js.html | 93 + .../plugins/jqplot-donutRenderer-js.html | 98 + .../files/plugins/jqplot-dragable-js.html | 45 + .../jqplot-enhancedLegendRenderer-js.html | 49 + .../plugins/jqplot-funnelRenderer-js.html | 87 + .../files/plugins/jqplot-highlighter-js.html | 80 + .../plugins/jqplot-logAxisRenderer-js.html | 45 + .../plugins/jqplot-mekkoAxisRenderer-js.html | 49 + .../plugins/jqplot-mekkoRenderer-js.html | 62 + .../plugins/jqplot-meterGaugeRenderer-js.html | 103 + .../files/plugins/jqplot-ohlcRenderer-js.html | 65 + .../files/plugins/jqplot-pieRenderer-js.html | 93 + .../files/plugins/jqplot-pointLabels-js.html | 72 + .../files/plugins/jqplot-trendline-js.html | 67 + .../jquery/jqplot/docs/files/usage-txt.html | 58 + phpgwapi/js/jquery/jqplot/docs/index.html | 1 + .../js/jquery/jqplot/docs/index/Classes.html | 70 + .../js/jquery/jqplot/docs/index/Files.html | 34 + .../jquery/jqplot/docs/index/Functions.html | 66 + .../js/jquery/jqplot/docs/index/General.html | 46 + .../js/jquery/jqplot/docs/index/General2.html | 42 + .../js/jquery/jqplot/docs/index/General3.html | 50 + .../js/jquery/jqplot/docs/index/General4.html | 50 + .../js/jquery/jqplot/docs/index/General5.html | 34 + .../js/jquery/jqplot/docs/index/General6.html | 58 + .../js/jquery/jqplot/docs/index/Hooks.html | 46 + .../jquery/jqplot/docs/index/Properties.html | 50 + .../jquery/jqplot/docs/index/Properties2.html | 50 + .../jquery/jqplot/docs/index/Properties3.html | 50 + .../jquery/jqplot/docs/index/Properties4.html | 34 + .../jquery/jqplot/docs/index/Properties5.html | 58 + .../js/jquery/jqplot/docs/javascript/main.js | 836 ++ .../jqplot/docs/javascript/searchdata.js | 182 + .../jquery/jqplot/docs/search/ClassesA.html | 20 + .../jquery/jqplot/docs/search/ClassesD.html | 20 + .../jquery/jqplot/docs/search/ClassesG.html | 20 + .../jquery/jqplot/docs/search/ClassesH.html | 20 + .../jquery/jqplot/docs/search/ClassesJ.html | 20 + .../jquery/jqplot/docs/search/ClassesL.html | 20 + .../jquery/jqplot/docs/search/ClassesS.html | 20 + .../jqplot/docs/search/ClassesSymbols.html | 20 + .../jquery/jqplot/docs/search/ClassesT.html | 20 + .../jquery/jqplot/docs/search/ClassesV.html | 20 + .../js/jquery/jqplot/docs/search/FilesJ.html | 20 + .../jquery/jqplot/docs/search/FunctionsC.html | 20 + .../jquery/jqplot/docs/search/FunctionsD.html | 20 + .../jquery/jqplot/docs/search/FunctionsG.html | 20 + .../jquery/jqplot/docs/search/FunctionsI.html | 20 + .../jquery/jqplot/docs/search/FunctionsM.html | 20 + .../jquery/jqplot/docs/search/FunctionsN.html | 20 + .../jquery/jqplot/docs/search/FunctionsR.html | 20 + .../jquery/jqplot/docs/search/FunctionsS.html | 20 + .../jquery/jqplot/docs/search/FunctionsZ.html | 20 + .../jquery/jqplot/docs/search/GeneralA.html | 20 + .../jquery/jqplot/docs/search/GeneralB.html | 20 + .../jquery/jqplot/docs/search/GeneralC.html | 20 + .../jquery/jqplot/docs/search/GeneralD.html | 20 + .../jquery/jqplot/docs/search/GeneralE.html | 20 + .../jquery/jqplot/docs/search/GeneralF.html | 20 + .../jquery/jqplot/docs/search/GeneralG.html | 20 + .../jquery/jqplot/docs/search/GeneralH.html | 20 + .../jquery/jqplot/docs/search/GeneralI.html | 20 + .../jquery/jqplot/docs/search/GeneralJ.html | 20 + .../jquery/jqplot/docs/search/GeneralL.html | 20 + .../jquery/jqplot/docs/search/GeneralM.html | 20 + .../jquery/jqplot/docs/search/GeneralN.html | 20 + .../jquery/jqplot/docs/search/GeneralO.html | 20 + .../jquery/jqplot/docs/search/GeneralP.html | 20 + .../jquery/jqplot/docs/search/GeneralR.html | 20 + .../jquery/jqplot/docs/search/GeneralS.html | 20 + .../jqplot/docs/search/GeneralSymbols.html | 20 + .../jquery/jqplot/docs/search/GeneralT.html | 20 + .../jquery/jqplot/docs/search/GeneralU.html | 20 + .../jquery/jqplot/docs/search/GeneralV.html | 20 + .../jquery/jqplot/docs/search/GeneralW.html | 20 + .../jquery/jqplot/docs/search/GeneralX.html | 20 + .../jquery/jqplot/docs/search/GeneralY.html | 20 + .../jquery/jqplot/docs/search/GeneralZ.html | 20 + .../js/jquery/jqplot/docs/search/HooksA.html | 20 + .../js/jquery/jqplot/docs/search/HooksE.html | 20 + .../js/jquery/jqplot/docs/search/HooksJ.html | 20 + .../js/jquery/jqplot/docs/search/HooksP.html | 20 + .../jquery/jqplot/docs/search/NoResults.html | 15 + .../jqplot/docs/search/PropertiesA.html | 20 + .../jqplot/docs/search/PropertiesB.html | 20 + .../jqplot/docs/search/PropertiesC.html | 20 + .../jqplot/docs/search/PropertiesD.html | 20 + .../jqplot/docs/search/PropertiesE.html | 20 + .../jqplot/docs/search/PropertiesF.html | 20 + .../jqplot/docs/search/PropertiesG.html | 20 + .../jqplot/docs/search/PropertiesH.html | 20 + .../jqplot/docs/search/PropertiesI.html | 20 + .../jqplot/docs/search/PropertiesL.html | 20 + .../jqplot/docs/search/PropertiesM.html | 20 + .../jqplot/docs/search/PropertiesN.html | 20 + .../jqplot/docs/search/PropertiesO.html | 20 + .../jqplot/docs/search/PropertiesP.html | 20 + .../jqplot/docs/search/PropertiesR.html | 20 + .../jqplot/docs/search/PropertiesS.html | 20 + .../jqplot/docs/search/PropertiesT.html | 20 + .../jqplot/docs/search/PropertiesU.html | 20 + .../jqplot/docs/search/PropertiesV.html | 20 + .../jqplot/docs/search/PropertiesW.html | 20 + .../jqplot/docs/search/PropertiesX.html | 20 + .../jqplot/docs/search/PropertiesY.html | 20 + .../jqplot/docs/search/PropertiesZ.html | 20 + phpgwapi/js/jquery/jqplot/docs/styles/1.css | 767 ++ phpgwapi/js/jquery/jqplot/docs/styles/2.css | 174 + .../js/jquery/jqplot/docs/styles/main.css | 2 + phpgwapi/js/jquery/jqplot/examples/.htaccess | 13 + phpgwapi/js/jquery/jqplot/examples/OHLC.html | 331 + phpgwapi/js/jquery/jqplot/examples/OHLC2.html | 194 + .../js/jquery/jqplot/examples/ajax-loader.gif | Bin 0 -> 3208 bytes phpgwapi/js/jquery/jqplot/examples/area.html | 108 + .../js/jquery/jqplot/examples/axisLabel.html | 121 + .../examples/axisLabelsRotatedText.html | 141 + .../examples/axisLabelsRotatedText2.html | 174 + .../examples/axisScalingForceTicAt.html | 219 + .../jqplot/examples/barLinePieStack.html | 230 + .../jqplot/examples/barMissingValues.html | 63 + .../js/jquery/jqplot/examples/barTest.html | 307 + .../js/jquery/jqplot/examples/barTest2.html | 103 + .../jquery/jqplot/examples/bezierCurve.html | 96 + .../js/jquery/jqplot/examples/blockPlot.html | 149 + .../jquery/jqplot/examples/breakOnNull.html | 51 + .../jquery/jqplot/examples/bubbleChart2.html | 253 + .../jquery/jqplot/examples/bubblechart.html | 69 + .../examples/candlestickCanvasOverlay.html | 221 + .../jquery/jqplot/examples/canvasOverlay.html | 238 + .../js/jquery/jqplot/examples/catchError.html | 53 + .../examples/categoryHorizontalBar.html | 81 + .../jqplot/examples/categoryVsLinearAxes.html | 73 + .../jquery/jqplot/examples/chartInTable.html | 34 + .../js/jquery/jqplot/examples/ciParser.html | 110 + .../customHighlighterCursorTrendline.html | 69 + .../jqplot/examples/customPieTests.html | 72 + .../js/jquery/jqplot/examples/dataLabels.html | 190 + .../jquery/jqplot/examples/dataRenderer.html | 178 + .../jquery/jqplot/examples/dataTracking.html | 92 + .../js/jquery/jqplot/examples/donutTest.html | 84 + .../js/jquery/jqplot/examples/donutTest.js | 96 + .../js/jquery/jqplot/examples/donutTest2.html | 58 + .../jquery/jqplot/examples/dynamicplot.html | 347 + phpgwapi/js/jquery/jqplot/examples/example.js | 12 + .../js/jquery/jqplot/examples/examples.css | 34 + .../js/jquery/jqplot/examples/fillToZero.html | 127 + .../js/jquery/jqplot/examples/filledLine.html | 77 + .../examples/filledLineCategoryAxis.html | 79 + .../js/jquery/jqplot/examples/funnelTest.html | 77 + .../js/jquery/jqplot/examples/funnelTest.js | 74 + .../jqplot/examples/gridCustomization.html | 55 + .../jquery/jqplot/examples/gridPadding.html | 93 + .../js/jquery/jqplot/examples/hiddenPlot.html | 215 + .../jquery/jqplot/examples/highlighter.html | 94 + .../jquery/jqplot/examples/highlighter2.html | 62 + .../jquery/jqplot/examples/highlighter3.html | 94 + .../jqplot/examples/horizontalLine.html | 50 + .../js/jquery/jqplot/examples/intticks.html | 178 + .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 0 -> 260 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 0 -> 251 bytes .../images/ui-bg_flat_10_000000_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 0 -> 104 bytes .../images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 0 -> 125 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 0 -> 3762 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 0 -> 90 bytes .../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 0 -> 129 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_228ef1_256x240.png | Bin 0 -> 5355 bytes .../images/ui-icons_ef8c08_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes .../ui-lightness/jquery-ui-1.8.6.custom.css | 572 ++ .../js/jquery-ui-1.8.1.custom.min.js | 756 ++ .../js/jquery-ui-1.8.6.custom.min.js | 778 ++ .../js/jquery/jqplot/examples/jsondata.txt | 1 + .../jquery/jqplot/examples/legendLabels.html | 205 + .../jquery/jqplot/examples/legendLabels2.html | 228 + .../js/jquery/jqplot/examples/linepiebar.html | 158 + .../jquery/jqplot/examples/markerStyles.html | 45 + .../js/jquery/jqplot/examples/mekkoChart.html | 224 + .../js/jquery/jqplot/examples/meterGauge.html | 132 + .../jquery/jqplot/examples/meterGauge2.html | 159 + .../jquery/jqplot/examples/minMaxLines.html | 60 + .../jquery/jqplot/examples/missingValues.html | 119 + .../jqplot/examples/multiAxesRotatedText.html | 69 + .../jqplot/examples/multipleBarColors.html | 150 + .../jquery/jqplot/examples/multipleLines.html | 46 + .../jquery/jqplot/examples/multipleYAxes.html | 104 + phpgwapi/js/jquery/jqplot/examples/nav.inc | 35 + .../jquery/jqplot/examples/noDataOptions.html | 78 + .../js/jquery/jqplot/examples/pieTest.html | 103 + .../js/jquery/jqplot/examples/pieTest2.html | 166 + .../js/jquery/jqplot/examples/pieTest2.js | 80 + .../js/jquery/jqplot/examples/pieTest3.html | 95 + .../js/jquery/jqplot/examples/pieTest4.html | 249 + .../jquery/jqplot/examples/pointLabels.html | 92 + .../jquery/jqplot/examples/pointLabels2.html | 47 + .../js/jquery/jqplot/examples/prefix.html | 89 + .../jqplot/examples/resetAxisTicks.html | 104 + .../jquery/jqplot/examples/resizablePlot.html | 148 + .../jqplot/examples/resizablePlot2.html | 146 + .../jqplot/examples/rotatedTickLabels.html | 61 + .../examples/rotatedTickLabelsZoom.html | 68 + .../jqplot/examples/seriesCanvasReorder.html | 92 + .../jquery/jqplot/examples/seriesUpdate.html | 122 + .../jquery/jqplot/examples/shadowTests.html | 132 + .../jquery/jqplot/examples/singlePoint.html | 69 + .../js/jquery/jqplot/examples/sparkLine.html | 47 + .../jquery/jqplot/examples/stackedBar2.html | 108 + .../jquery/jqplot/examples/stackedBar3.html | 77 + .../stackedBarCategoryVsLinearAxes.html | 122 + .../jqplot/examples/stackedCategoryAxis.html | 89 + .../jqplot/examples/stackedFilledLine.html | 76 + .../jquery/jqplot/examples/stackedLine.html | 57 + phpgwapi/js/jquery/jqplot/examples/test2.html | 64 + .../js/jquery/jqplot/examples/theming.html | 481 + .../trendlineDragableCustomization.html | 82 + phpgwapi/js/jquery/jqplot/examples/ui.html | 191 + .../jquery/jqplot/examples/verticalLine.html | 51 + .../js/jquery/jqplot/examples/waterfall.html | 134 + .../js/jquery/jqplot/examples/waterfall2.html | 204 + phpgwapi/js/jquery/jqplot/examples/zoom1.html | 148 + phpgwapi/js/jquery/jqplot/examples/zoom2.html | 71 + phpgwapi/js/jquery/jqplot/examples/zoom3.html | 67 + phpgwapi/js/jquery/jqplot/examples/zoom4.html | 156 + .../jquery/jqplot/examples/zoomOptions.html | 99 + .../js/jquery/jqplot/examples/zoomProxy.html | 106 + phpgwapi/js/jquery/jqplot/excanvas.js | 1434 +++ phpgwapi/js/jquery/jqplot/excanvas.min.js | 30 + phpgwapi/js/jquery/jqplot/gpl-2.0.txt | 280 + .../js/jquery/jqplot/jqPlotCssStyling.txt | 53 + phpgwapi/js/jquery/jqplot/jqPlotOptions.txt | 276 + phpgwapi/js/jquery/jqplot/jquery.jqplot.css | 226 + phpgwapi/js/jquery/jqplot/jquery.jqplot.js | 8716 ++++++++++++++++ .../js/jquery/jqplot/jquery.jqplot.min.css | 1 + .../js/jquery/jqplot/jquery.jqplot.min.js | 30 + phpgwapi/js/jquery/jqplot/jquery.js | 8936 +++++++++++++++++ phpgwapi/js/jquery/jqplot/jquery.min.js | 18 + phpgwapi/js/jquery/jqplot/optionsTutorial.txt | 239 + .../plugins/jqplot.BezierCurveRenderer.js | 312 + .../plugins/jqplot.BezierCurveRenderer.min.js | 30 + .../jqplot/plugins/jqplot.barRenderer.js | 709 ++ .../jqplot/plugins/jqplot.barRenderer.min.js | 30 + .../jqplot/plugins/jqplot.blockRenderer.js | 234 + .../plugins/jqplot.blockRenderer.min.js | 30 + .../jqplot/plugins/jqplot.bubbleRenderer.js | 754 ++ .../plugins/jqplot.bubbleRenderer.min.js | 30 + .../plugins/jqplot.canvasAxisLabelRenderer.js | 207 + .../jqplot.canvasAxisLabelRenderer.min.js | 30 + .../plugins/jqplot.canvasAxisTickRenderer.js | 247 + .../jqplot.canvasAxisTickRenderer.min.js | 30 + .../jqplot/plugins/jqplot.canvasOverlay.js | 705 ++ .../plugins/jqplot.canvasOverlay.min.js | 30 + .../plugins/jqplot.canvasTextRenderer.js | 420 + .../plugins/jqplot.canvasTextRenderer.min.js | 30 + .../plugins/jqplot.categoryAxisRenderer.js | 636 ++ .../jqplot.categoryAxisRenderer.min.js | 30 + .../jquery/jqplot/plugins/jqplot.ciParser.js | 115 + .../jqplot/plugins/jqplot.ciParser.min.js | 30 + .../js/jquery/jqplot/plugins/jqplot.cursor.js | 1051 ++ .../jqplot/plugins/jqplot.cursor.min.js | 30 + .../jqplot/plugins/jqplot.dateAxisRenderer.js | 439 + .../plugins/jqplot.dateAxisRenderer.min.js | 30 + .../jqplot/plugins/jqplot.donutRenderer.js | 910 ++ .../plugins/jqplot.donutRenderer.min.js | 30 + .../jquery/jqplot/plugins/jqplot.dragable.js | 224 + .../jqplot/plugins/jqplot.dragable.min.js | 30 + .../plugins/jqplot.enhancedLegendRenderer.js | 199 + .../jqplot.enhancedLegendRenderer.min.js | 30 + .../jqplot/plugins/jqplot.funnelRenderer.js | 938 ++ .../plugins/jqplot.funnelRenderer.min.js | 30 + .../jqplot/plugins/jqplot.highlighter.js | 421 + .../jqplot/plugins/jqplot.highlighter.min.js | 30 + .../js/jquery/jqplot/plugins/jqplot.json2.js | 475 + .../jquery/jqplot/plugins/jqplot.json2.min.js | 30 + .../jqplot/plugins/jqplot.logAxisRenderer.js | 446 + .../plugins/jqplot.logAxisRenderer.min.js | 30 + .../plugins/jqplot.mekkoAxisRenderer.js | 610 ++ .../plugins/jqplot.mekkoAxisRenderer.min.js | 30 + .../jqplot/plugins/jqplot.mekkoRenderer.js | 436 + .../plugins/jqplot.mekkoRenderer.min.js | 30 + .../plugins/jqplot.meterGaugeRenderer.js | 1033 ++ .../plugins/jqplot.meterGaugeRenderer.min.js | 30 + .../jqplot/plugins/jqplot.ohlcRenderer.js | 372 + .../jqplot/plugins/jqplot.ohlcRenderer.min.js | 30 + .../jqplot/plugins/jqplot.pieRenderer.js | 898 ++ .../jqplot/plugins/jqplot.pieRenderer.min.js | 30 + .../jqplot/plugins/jqplot.pointLabels.js | 353 + .../jqplot/plugins/jqplot.pointLabels.min.js | 30 + .../jquery/jqplot/plugins/jqplot.trendline.js | 220 + .../jqplot/plugins/jqplot.trendline.min.js | 30 + phpgwapi/js/jquery/jqplot/usage.txt | 126 + 342 files changed, 56759 insertions(+) create mode 100644 phpgwapi/js/jquery/jqplot/MIT-LICENSE.txt create mode 100644 phpgwapi/js/jquery/jqplot/README.txt create mode 100644 phpgwapi/js/jquery/jqplot/changes.txt create mode 100644 phpgwapi/js/jquery/jqplot/copyright.txt create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/MIT-LICENSE-txt.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/changes-txt.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/gpl-2-0-txt.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/background.jpg create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/basicline.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/basiclogaxis.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/basiclogoptions.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/basicoptions.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/dualaxis.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/logo.jpg create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/navdocs.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/navdocsover.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/navdownload.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/navdownloadover.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/navexamples.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/navexamplesover.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/navhome.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/navhomeover.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/new.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/sample3.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/images/samplesm.png create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqPlotCssStyling-txt.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqPlotOptions-txt.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-axisLabelRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-axisTickRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-canvasGridRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-core-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-divTitleRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-lineRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-linearAxisRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-markerRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-shadowRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-shapeRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/jqplot-themeEngine-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/optionsTutorial-txt.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-BezierCurveRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-barRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-blockRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-bubbleRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasAxisLabelRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasAxisTickRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasOverlay-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-categoryAxisRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-ciParser-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-cursor-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-dateAxisRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-donutRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-dragable-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-enhancedLegendRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-funnelRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-highlighter-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-logAxisRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-mekkoAxisRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-mekkoRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-meterGaugeRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-ohlcRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-pieRenderer-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-pointLabels-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-trendline-js.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/files/usage-txt.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Classes.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Files.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Functions.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/General.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/General2.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/General3.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/General4.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/General5.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/General6.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Hooks.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Properties.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Properties2.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Properties3.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Properties4.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/index/Properties5.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/javascript/main.js create mode 100644 phpgwapi/js/jquery/jqplot/docs/javascript/searchdata.js create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesA.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesD.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesG.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesH.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesJ.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesL.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesS.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesSymbols.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesT.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/ClassesV.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FilesJ.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsC.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsD.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsG.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsI.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsM.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsN.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsR.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsS.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/FunctionsZ.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralA.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralB.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralC.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralD.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralE.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralF.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralG.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralH.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralI.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralJ.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralL.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralM.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralN.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralO.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralP.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralR.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralS.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralSymbols.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralT.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralU.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralV.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralW.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralX.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralY.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/GeneralZ.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/HooksA.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/HooksE.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/HooksJ.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/HooksP.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/NoResults.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesA.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesB.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesC.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesD.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesE.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesF.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesG.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesH.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesI.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesL.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesM.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesN.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesO.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesP.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesR.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesS.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesT.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesU.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesV.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesW.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesX.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesY.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/search/PropertiesZ.html create mode 100644 phpgwapi/js/jquery/jqplot/docs/styles/1.css create mode 100644 phpgwapi/js/jquery/jqplot/docs/styles/2.css create mode 100644 phpgwapi/js/jquery/jqplot/docs/styles/main.css create mode 100644 phpgwapi/js/jquery/jqplot/examples/.htaccess create mode 100644 phpgwapi/js/jquery/jqplot/examples/OHLC.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/OHLC2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/ajax-loader.gif create mode 100644 phpgwapi/js/jquery/jqplot/examples/area.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/axisLabel.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/axisLabelsRotatedText.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/axisLabelsRotatedText2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/axisScalingForceTicAt.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/barLinePieStack.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/barMissingValues.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/barTest.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/barTest2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/bezierCurve.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/blockPlot.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/breakOnNull.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/bubbleChart2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/bubblechart.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/candlestickCanvasOverlay.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/canvasOverlay.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/catchError.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/categoryHorizontalBar.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/categoryVsLinearAxes.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/chartInTable.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/ciParser.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/customHighlighterCursorTrendline.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/customPieTests.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/dataLabels.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/dataRenderer.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/dataTracking.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/donutTest.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/donutTest.js create mode 100644 phpgwapi/js/jquery/jqplot/examples/donutTest2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/dynamicplot.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/example.js create mode 100644 phpgwapi/js/jquery/jqplot/examples/examples.css create mode 100644 phpgwapi/js/jquery/jqplot/examples/fillToZero.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/filledLine.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/filledLineCategoryAxis.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/funnelTest.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/funnelTest.js create mode 100644 phpgwapi/js/jquery/jqplot/examples/gridCustomization.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/gridPadding.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/hiddenPlot.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/highlighter.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/highlighter2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/highlighter3.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/horizontalLine.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/intticks.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_222222_256x240.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_228ef1_256x240.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_ef8c08_256x240.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_ffd27a_256x240.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_ffffff_256x240.png create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/jquery-ui-1.8.6.custom.css create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/js/jquery-ui-1.8.1.custom.min.js create mode 100644 phpgwapi/js/jquery/jqplot/examples/jquery-ui/js/jquery-ui-1.8.6.custom.min.js create mode 100644 phpgwapi/js/jquery/jqplot/examples/jsondata.txt create mode 100644 phpgwapi/js/jquery/jqplot/examples/legendLabels.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/legendLabels2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/linepiebar.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/markerStyles.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/mekkoChart.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/meterGauge.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/meterGauge2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/minMaxLines.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/missingValues.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/multiAxesRotatedText.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/multipleBarColors.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/multipleLines.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/multipleYAxes.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/nav.inc create mode 100644 phpgwapi/js/jquery/jqplot/examples/noDataOptions.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/pieTest.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/pieTest2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/pieTest2.js create mode 100644 phpgwapi/js/jquery/jqplot/examples/pieTest3.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/pieTest4.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/pointLabels.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/pointLabels2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/prefix.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/resetAxisTicks.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/resizablePlot.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/resizablePlot2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/rotatedTickLabels.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/rotatedTickLabelsZoom.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/seriesCanvasReorder.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/seriesUpdate.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/shadowTests.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/singlePoint.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/sparkLine.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/stackedBar2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/stackedBar3.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/stackedBarCategoryVsLinearAxes.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/stackedCategoryAxis.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/stackedFilledLine.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/stackedLine.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/test2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/theming.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/trendlineDragableCustomization.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/ui.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/verticalLine.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/waterfall.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/waterfall2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/zoom1.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/zoom2.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/zoom3.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/zoom4.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/zoomOptions.html create mode 100644 phpgwapi/js/jquery/jqplot/examples/zoomProxy.html create mode 100644 phpgwapi/js/jquery/jqplot/excanvas.js create mode 100644 phpgwapi/js/jquery/jqplot/excanvas.min.js create mode 100644 phpgwapi/js/jquery/jqplot/gpl-2.0.txt create mode 100644 phpgwapi/js/jquery/jqplot/jqPlotCssStyling.txt create mode 100644 phpgwapi/js/jquery/jqplot/jqPlotOptions.txt create mode 100644 phpgwapi/js/jquery/jqplot/jquery.jqplot.css create mode 100644 phpgwapi/js/jquery/jqplot/jquery.jqplot.js create mode 100644 phpgwapi/js/jquery/jqplot/jquery.jqplot.min.css create mode 100644 phpgwapi/js/jquery/jqplot/jquery.jqplot.min.js create mode 100644 phpgwapi/js/jquery/jqplot/jquery.js create mode 100644 phpgwapi/js/jquery/jqplot/jquery.min.js create mode 100644 phpgwapi/js/jquery/jqplot/optionsTutorial.txt create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.BezierCurveRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.BezierCurveRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.barRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.barRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.blockRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.blockRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.bubbleRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.bubbleRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisLabelRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisLabelRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisTickRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasOverlay.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasOverlay.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasTextRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasTextRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.categoryAxisRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.categoryAxisRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.ciParser.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.ciParser.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.cursor.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.cursor.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.dateAxisRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.dateAxisRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.donutRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.donutRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.dragable.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.dragable.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.enhancedLegendRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.enhancedLegendRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.funnelRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.funnelRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.highlighter.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.highlighter.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.json2.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.json2.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.logAxisRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.logAxisRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoAxisRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoAxisRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.meterGaugeRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.meterGaugeRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.ohlcRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.ohlcRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.pieRenderer.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.pieRenderer.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.pointLabels.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.pointLabels.min.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.trendline.js create mode 100644 phpgwapi/js/jquery/jqplot/plugins/jqplot.trendline.min.js create mode 100644 phpgwapi/js/jquery/jqplot/usage.txt diff --git a/phpgwapi/js/jquery/jqplot/MIT-LICENSE.txt b/phpgwapi/js/jquery/jqplot/MIT-LICENSE.txt new file mode 100644 index 0000000000..da4732ec39 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/MIT-LICENSE.txt @@ -0,0 +1,21 @@ +Title: MIT License + +Copyright (c) 2009-2011 Chris Leonello + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/README.txt b/phpgwapi/js/jquery/jqplot/README.txt new file mode 100644 index 0000000000..2b2b09ad04 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/README.txt @@ -0,0 +1,77 @@ +Title: jqPlot Readme + +Pure JavaScript plotting plugin for jQuery. + +To learn how to use jqPlot, start with the Basic Unsage Instructions below. Then read the +usage.txt and jqPlotOptions.txt files included with the distribution. + +The jqPlot home page is at . + +Downloads can be found at . + +The mailing list is at . + +Examples and unit tests are at . + +Documentation is at . + +The project page and source code are at . + +Bugs, issues, feature requests: . + +Basic Usage Instructions: + +jqPlot requires jQuery (1.4+ required for certain features). jQuery 1.4.4 is included in +the distribution. To use jqPlot include jQuery, the jqPlot jQuery plugin, the jqPlot css file and +optionally the excanvas script to support IE version prior to IE 9 in your web page: + +> +> +> +> + +For usage instructions, see in usage.txt. For available options, see + in jqPlotOptions.txt. + +Building from source: + +If you've cloned the repository, you can build a distribution from source. +You need to have ant installed. You can simply +type "ant" from the jqplot directory to build the default "all" target. +There are 6 pertinent targets: clean, dist, min, docs, compress and all. Use: + +> ant -p + +to get a description of the various build targets. + +Legal Notices: + +Copyright (c) 2009-2010 Chris Leonello +jqPlot is currently available for use in all personal or commercial projects +under both the MIT and GPL version 2.0 licenses. This means that you can +choose the license that best suits your project and use it accordingly. + +Although not required, the author would appreciate an email letting him +know of any substantial use of jqPlot. You can reach the author at: +chris at jqplot or see http://www.jqplot.com/info.php . + +If you are feeling kind and generous, consider supporting the project by +making a donation at: http://www.jqplot.com/donate.php . + +jqPlot includes date instance methods and printf/sprintf functions by other authors: + +Date instance methods: + + author Ken Snyder (ken d snyder at gmail dot com) + date 2008-09-10 + version 2.0.2 (http://kendsnyder.com/sandbox/date/) + license Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/) + +JavaScript printf/sprintf functions. + + version 2007.04.27 + author Ash Searle + http://hexmen.com/blog/2007/03/printf-sprintf/ + http://hexmen.com/js/sprintf.js + The author (Ash Searle) has placed this code in the public domain: + "This code is unrestricted: you are free to use it however you like." diff --git a/phpgwapi/js/jquery/jqplot/changes.txt b/phpgwapi/js/jquery/jqplot/changes.txt new file mode 100644 index 0000000000..79c1567759 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/changes.txt @@ -0,0 +1,395 @@ +Title: Change Log + +1.0.0b2: +* Major improvements in memory usage: +** Merged in changes from Timo Besenruether to reuse canvas elements and improve + memory performance. +** Fixed all identifiable DOM leaks. +** Mergged in changes from cguillot for memory improvements in IE < 9. +* Added vertical and dashed vertical line support for canvas overlay. +* Fixed bug where initially hidden plots would not display. +* Fixed bug with point labels and null data points. +* Updated to jQuery 1.6.1. +* Improved pie slice margin calculation and fixed slice margin and pie positioning + with small slices. +* Improved bar renderer so bars always start at 0 if: +** The axis is a linear axis (not log/date). +** There are no other line types besides bars attached to the axis. +** The data on the axis is all >= 0. +** The user has not specified a pad, padMin or forceTickAt0 = true option. +* Modified tick prefix behavious so prefix no added to all ticks, even if format + string is specified. +* Fix to ensure original tick formats are applied when zooming and resetting + zoom. +* Updated auto tick format string so format adjusted when zooming. +* Modified auto tick computation to put less ticks on small plots and more + ticks on large plots. +* Update bubble render to support gradients in IE 9. + +1.0.0b1: +* Much improved tick generation algorithm to get precise rounded + tick values (Thanks Scott Prahl!). +* Auto compute tick format string if none is provided. +* Much better "slicing" of pie charts when using "sliceMargin" option to set + a gap between the slices. +* Expanded canvasOverlay plugin to create arbitrary dashed and solid + horizontal and vertical lines on top of plot. +* Added defaultColors and defaultNegativeColors options to $.jqplot.config. +* Fixed issue #318, highlighter & bar renderer incompatability. +* Improve highlighter tooltip positioning with negative bars. +* Fixed #305, mispelling of jqlotDragStart and jqlotDragStop. MUST NOW BIND + TO jqplotDragStart and jqplotDragStop. +* Fixed #290, some variables left in global scope. +* Fixed #289, OHLC line widths hard coded at 1.5. Now set by lineWidth option. +* Fixed #296 for determining databounds on log axes. +* Updated to jQuery 1.5.1 +* Fixed waterfall plot to ensure first and last bars always fill to zero. +* Added lineJoin and lineCap option to series lines. +* Bar widths now based on width of grid, not plot target for better scaling. +* Added looseZoom option to cursor so zooming can produce well rounded ticks. +* Added forceTickAt0 and forceTickAt100 options to ensure there will always + be a tick at 0 or 100 in the plot. +* Fixed bug where cursor legend didn't honor series showLabel option. + + +1.0.0a: + +* Series can now be moved forward or backward in stack to e.g. bring a line + forward when mousing over a point. +* Can now move outside of grid area while zooming. Can have zoom + constrained to grid area or allow zooming outside. +* Fixed issue #142 with tooltip drawn on top of event canvas, hiding + mouse events. +* Fixed #147 where pie slices with 0 value not rendering properly in IE. +* Fixed #130 where stack data not sorted properly. +* Fixed bug with null values not handled properly in category axes. +* Fixed #156 where pie charts not rendering on QTWebKit. +* Now using feature detection for canvas and canvas text capability + rather than browser version. +* Added enahncedLegendRenderer plugin to allow multi row/column legends + and clickable labels to show/hide series. +* Added fillToValue option to allow filled line plot to fill to an + arbitrary value. +* Added block plot plugin. +* Added funnel type charts. +* Added meter gauge type charts. +* Added plot theming support. +* $.jqplot.config.enablePlugins now false by default. +* Implemented highlighting on bar, pie, donut, funnel, etc. charts. +* Fix to pointlabels plugin to align labels properly on multi series plots. +* Added custom error handling to display error message in plot area. +* Fixed issue where would call to draw grid border of 0 width would + result in a default border being drawn. +* Added options to place legend outside of grid and shrink grid so everything + stays within plot div. +* Fixed bug in color generator so now calls to get() continually cycle + through colors just like next(). +* Added defaultAxisStart option. +* Added gradient fills to bubbles. +* Added bubble charts. +* Added showLabels option to bubble charts. +* Pass bubble radius to event callback in bubble charts. +* Fixed #207, typo in docs. +* Fixed #206 where "value" pie slice data labels were displaying wrong + value. +* Fixed #147 with 0 value slices in IE6. +* Fixed issue #241, disabled varyBarColor option in stacked charts. +* Added dataRenderer option to allow custom processors for JSON, AJAX + and anywhere else you might want to get data. +* Fixed null value handling so plot now properly skip or join over nulls. +* Fixed showTicks and showTickMarks option conflicts. +* Fixed issue #185 where pointLabels plugin incompatibility could crash + pie, donut and other plots. +* Fixed #23 and #143 to obey gridPadding option. +* Fixed #233 with highlighter tooltip separator. +* Fixed #224 where type checking failing on GWT. +* Fixed #272 with pie highlighting not working on replot. +* Memory performance improvements. +* Changes to build script so everything should build when pulled from repo. +* Fixed issue #275, IE 6/7 don't support array indexing of strings. +* Added event listener hooks for mouseUp, mouseDown, etc. to all line plots. +* Fixed bug with highlighter not working when null in data. +* Updated to jQuery 1.4.4 +* Fixed bug where donut plots showed value of radians of slice instead + of actual data. +* Reverted to excanvas r3 so IE8 no longer has to emulate IE7. +* Added tooltipContentEditor option to highlighter, allowing callback + to manipulate tooltip content at run time (thanks Tim Bunce!). +* Fixed bug where axes scale not resetting. +* Fixed bug with date axes where data bounds not properly set. +* Fixed issue where tick marks disappear if grid lines turned off. +* Updated replot method to allow passing in axes options for more control. +* Added experimental support for "broken" axes. +* Fixed bug with pies where pies with 0 valued slices did not draw correctly. +* Added canvasOverlay plugin to allow drawing of arbitrary shapes on a canvas + over the plot. +* Added option to display arbitrary text/html (message, animated gif, etc.) if + plot is constructed without data. Allow a "data loading" indicator to be shown. +* Added resetAxisValues method to manually update axis ticks without + redrawing the plot. +* Fix to labels on negative bars so label postiion of 'n' will be below a negative bar, + just as it is above a positive bar (thanks guigod!). +* Added thousands separator character (') to sprintf formatting (thanks yuichi1004!). +* Re-factored date parsing/formatting to use new jsDate module which does not + extend the Date prototype. + + +0.9.7: + +* Added Mekko chart plot type with enhanced legend and axes support. +* Implemented vertical waterfall charts. Can create waterfall plot as + option to bar chart. See examples folder of distribution. +* Enhanced plot labels for waterfall style. +* Enhanced bar plots so you can now color each bar of a series + independently with the "varyBarColor" option. +* Re-factored series drawing so that each series and series shadow drawn + on it's own canvas. Allows series to be redrawn independently of each other. +* Added additional default series colors. +* Added useNegativeColors option to turn off negative color array and use + only seriesColors array to define all bar/filled line colors. +* Fix css for cursor legend. +* Modified shape renderer so rectangles can be stroked and filled. +* Re-factored date methods out of dateAxisRenderer so that date formatter + and methods can be accesses outside of dateAxisRenderer plugin. +* Fixed #132, now trigger series change event on plot target instead of drag canvas. +* Fixes issue #116 where some source files had mix of tabs and spaces + for indentation. Should have been all spaces. +* Fixed issue #126, some links broken in docs section of web site. +* Fixed issue #90, trendline plugin incompatibility with pie renderer. +* Updated samples in examples folder of distribution to include navigation + links if web server is set up to process .html files with php. + + +0.9.6: + +* New, easier to use, replot() method for placing plots in tabs, accordions, + resizable containers or for changing plot parameters programmatically. +* Updated legend renderer for pie charts to draw swatches which will + print correctly. +* Fixed issue #118 with patch from taum so autoscale option will + honor tickInterval and numberTicks options +* Fix to plot diameter calculation for initially hidden plots. +* Added examples for making plots in jQuery UI tabs and accordions. +* Fixed issue #120 where pie chart with single slice not displaying + correctly in IE and Chrome + + +0.9.5.2: + +* Fixed #102 where double clicking on plot that has zoom enabled, but + has not been zoomed resulted in error. +* Fixed bug where candlestick coloring options not working. +* Added option to turn individual series labels off in the legend. + + +0.9.5.1: + +* Fixed bug where tooltip not working with OHLC and candlestick charts. +* Added additional marker styles: plus, X and dash. + + +0.9.5: + +* Implemented "zoomProxy". zoomProxy allows zooming one plot from another + such as an overview plot. +* Zooming can now be constrained to just x or y axis. +* Enhanced cursor plugin with vertical "dataTracking" line. This is a line + at the cursor location with a readout of data points at the line location + which are displayed in the chart legend. +* Changed cursor tooltip format string. Now one format string is used for + entire tooltip. +* Added mechanisms to specify plot size when plot target is hidden or plot + height/width otherwise cannot be determined from markup. +* Added $.jqplot.config object to specify jqplot wide configuration options. + These include enablePlugins to globally set the default plugin state on/off + and defaultHeight/defaultWidth to specify default plot height/width. +* Added fillToZero option which forces filled charts to fill to zero as opposed + to axis minimum. Thus negative filled bar/line values will fill upwards to + zero axis value. +* Added option to disable stacking on individual lines. +* Changed targetId property of the plot object so it now includes a "#" before + the id string. +* Improved tick and body sizing of Open Hi Low Close and candlestick charts. +* Removed lots of web site related files from the repository. This means that, + if working from the sources, user's won't be able to build the jqplot web + site and the docs/tests that are hosted on that site. The minified and + compressed distribution packages will build fine. +* Lots of examples were added to a separate examples directory to better show + functionality of jqPlot for local testing with the distribution. +* Many various bug fixes and other minor enhancements. + + +0.9.4: + +* Implemented axis labels. Labels can be rendered in div tags or as canvas + elements supporting rotated text. +* Improved rotated axis label positioning so labels will start or end at a + tick position. +* Fixed bug where an empty data series would hang plot rendering. +* completed issue #66 for misc. improvements to documentation. +* Fixed issue #64 where the same ID's were assigned to cursor and highlighter + elements. +* Added option to legend to encode special HTML characters. +* Fixed undesirable behavior where point labels for points off the plot + were being rendered. +* Added edgeTolerance option to point label renderer to control rendering of + labels near plot edges. + + +0.9.3: + +* Preliminary support for axis labels. Currently rendered into DIV tags, + so no rotated label support. This feature is currently experimental. +* Fixed bug #52, needed space in tick div tag between style and class declarations + or plot failed in certain application doctypes. +* Fixed issue #54, miter style line join for chart lines causing spikes at steep + changes in slope. Changed miter style to round. +* Added examples for new autoscaling algorithm. +* Fixed bug #57, category axis labels disappear on redraw() +* Improved algorithm which controlled maximum number of labels that would display + on a category axis. +* Fixed bug #45 where null values causing errors in plotData and gridData. +* Fixed issue #60 where seriesColors option was not working. + + +0.9.2: + +* Fixed bug #45 where a plot could crash if series had different numbers of points. +* Fixed issue #50, added option to turn off sorting of series data. +* Fixed issue #31, implemented a better axis autoscaling algorithm and added an autoscale option. + +0.9.1: + +* Fixed bug #40, when axis pad, padMax, padMin set to 0, graph would fail to render. +* Fixed bug #41 where pie and bar charts not rendered correctly on redraw(). +* Fixed bug #11, filled stacked line plots not rendering correctly in IE. +* Fixed bug #42 where stacked charts not rendering with string date axis ticks. +* Fixed bug in redraw() method where axes ticks were not reset. +* Fixed "jqplotPreRedrawEvent" that should have been named "jqplotPostRedraw" event. + +0.9.0: + +* Added Open Hi Low Close charts, Candlestick charts and Hi Low Close charts. +* Added support for arbitrary labels on the data points. +* Enhanced highlighter plugin to allow custom formatting control of entire tooltip. +* Enhanced highlighter to support multiple y values in a data point. +* Fixed bug #38 where series with a single point with a negative value would fail. +* Improvements to examples to show what plugins to include. +* Expanded documentation for some of the plugins. + +0.8.5: + +* Added zooming ability with double click or single click options to reset zoom. +* Modified default tick spacing algorithm for date axes to give more space to ticks. +* Fixed bug #2 where tickInterval wasn't working properly. +* Added neighborThreshold option to control how close mouse must be to + point to trigger neighbor detection. +* Added double click event handler on plot. + +0.8.0: + +* Support for up to 9 y axes. +* Added option to control padding at max/min bounds of axes separately. +* Closed issue #21, added options to control grid line color and width. +* Closed issue #20, added options to filled line charts to stoke above + fill and customize fill color and transparency. +* Improved structure of on line documentation to make usage and options + docs default. +* Added much documentation on options and css styling. + +0.7.1: + +* Bug fix release +* Fixed bug #6, missing semi-colons messing up some javascript compressors. +* Fixed bug #13 where 2D ticks array of [values, labels] would fail to + renderer with DateAxisRenderer. +* Fixes bug #16 where pie renderer overwriting options for all plot types + and crashing non pie plots. +* Fixes bug #17 constrainTo dragable option mispelled as "contstrainTo". + Fixed dragable color issue when used with trend lines. + +0.7.0: + +* Pie chart support +* Enabled tooltipLocation option in highlighter. +* Highlighter Tooltip will account for mark size and highlight size when + positioning itself. +* Added ability to show just x, y or both axes in highlighter tooltip. +* Added customization of separator between axes values in highlighter tooltip. +* Modified how shadows are drawn for lines, bars and markers. Now drawn first, + so they are always behind the object. +* Adjustments to shadow parameters on lines to account for new shadow positioning. +* Added a ColorGenerator class to robustly return next available color + for a plot with wrap around to first color at end. +* Udates to docs about css file. +* Fixed bug with String x values in series and IE error on sorting (Category Axis). +* Added cursor changes in dragable plugin when cursor near dragable point. + +0.6.6b: + +* Added excanvas.js and excanvas.min.js to compressed distributions. +* Added example/test html pages I had locally into repository and to + compressed distributions. + +0.6.6a: + +* Removed absolute positioning from dom element and put back into css file. +* Duplicate of 0.6.6 with a suffix to unambiguously differentiate between + previously posted 0.6.6 release. + +0.6.6: + +* Fixed bug #5, trend line plugin failing when no trend line options specified. +* Added absolute position css spec to axis tick dom element. +* Enhancement to category axes, more intuitive handling of series with + missing data values. + +0.6.5: + +* Fixed bug #4, series of unequal data length not rendering correctly. + This is a bugfix release only. + +0.6.4: + +* Fixed bug (issue #1 in tracker) where flat line data series (all x and/or y + values are euqal) or single value data series would crash. + +0.6.3: + +* Support for stacked line (a.k.a. area) and stacked bar (horizontal and + vertical) charts. +* Refactored barRenderer to use default shape and shadow renderers. +* Added info (contacts & support information) page to web site. + +0.6.2: + +* This is a minor upgrade to docs and build only. No functionality has changed. +* Ant build script generates entire site, examples, tests and distribution. +* Improvements to documentation. + +0.6.1: + +* New sprintf implementation from Ash Searle that implements %g. +* Fix to sprintf e/f formats. +* Created new format specifier, %p and %P to preserve significance. +* Modified p/P format to better display larger numbers. +* Fixed and simplified significant digits calculation for sprintf. +* Added option to have cursor tooltip follow the mouse or not. +* Added options to change size of highlight. +* Updates to handle dates like '6-May-09'. +* Mods to improve look of web site. +* Updates to documentation. +* Added license and copyright statement to source files. + +0.6.0: + +* Added rotated text support. Uses native canvas text functionality in + browsers that support it or draws text on canvas with Hershey font +* metrics for non-supporting browsers. +* Removed lots of lint in js code. +* Moved tick css from js code into css file. +* Fix to tick positioning css. y axis ticks were positioned to wrong side of axis div. +* Re-factored axis tick renderer instantiation into the axes renderers themselves. + + +For changes prior to 0.6.0 release, please see change log at http://bitbucket.org/cleonello/jqplot/changesets/ \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/copyright.txt b/phpgwapi/js/jquery/jqplot/copyright.txt new file mode 100644 index 0000000000..1329729f6f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/copyright.txt @@ -0,0 +1,29 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: @VERSION + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ diff --git a/phpgwapi/js/jquery/jqplot/docs/files/MIT-LICENSE-txt.html b/phpgwapi/js/jquery/jqplot/docs/files/MIT-LICENSE-txt.html new file mode 100644 index 0000000000..34d120c3a1 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/MIT-LICENSE-txt.html @@ -0,0 +1,39 @@ + + +MIT License + + + + + + + + + +

Copyright © 2009-2011 Chris Leonello

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/changes-txt.html b/phpgwapi/js/jquery/jqplot/docs/files/changes-txt.html new file mode 100644 index 0000000000..76a6835845 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/changes-txt.html @@ -0,0 +1,39 @@ + + +Change Log + + + + + + + + + +

1.0.0b2

  • Major improvements in memory usage: ** Merged in changes from Timo Besenruether to reuse canvas elements and improve memory performance.  ** Fixed all identifiable DOM leaks.  ** Mergged in changes from cguillot for memory improvements in IE < 9.
  • Added vertical and dashed vertical line support for canvas overlay.
  • Fixed bug where initially hidden plots would not display.
  • Fixed bug with point labels and null data points.
  • Updated to jQuery 1.6.1.
  • Improved pie slice margin calculation and fixed slice margin and pie positioning with small slices.
  • Improved bar renderer so bars always start at 0 if: ** The axis is a linear axis (not log/date).  ** There are no other line types besides bars attached to the axis.  ** The data on the axis is all >= 0.  ** The user has not specified a pad, padMin or forceTickAt0 = true option.
  • Modified tick prefix behavious so prefix no added to all ticks, even if format string is specified.
  • Fix to ensure original tick formats are applied when zooming and resetting zoom.
  • Updated auto tick format string so format adjusted when zooming.
  • Modified auto tick computation to put less ticks on small plots and more ticks on large plots.
  • Update bubble render to support gradients in IE 9.

1.0.0b1

  • Much improved tick generation algorithm to get precise rounded tick values (Thanks Scott Prahl!).
  • Auto compute tick format string if none is provided.
  • Much better “slicing” of pie charts when using “sliceMargin” option to set a gap between the slices.
  • Expanded canvasOverlay plugin to create arbitrary dashed and solid horizontal and vertical lines on top of plot.
  • Added defaultColors and defaultNegativeColors options to $.jqplot.config.
  • Fixed issue #318, highlighter & bar renderer incompatability.
  • Improve highlighter tooltip positioning with negative bars.
  • Fixed #305, mispelling of jqlotDragStart and jqlotDragStop.  MUST NOW BIND TO jqplotDragStart and jqplotDragStop.
  • Fixed #290, some variables left in global scope.
  • Fixed #289, OHLC line widths hard coded at 1.5.  Now set by lineWidth option.
  • Fixed #296 for determining databounds on log axes.
  • Updated to jQuery 1.5.1
  • Fixed waterfall plot to ensure first and last bars always fill to zero.
  • Added lineJoin and lineCap option to series lines.
  • Bar widths now based on width of grid, not plot target for better scaling.
  • Added looseZoom option to cursor so zooming can produce well rounded ticks.
  • Added forceTickAt0 and forceTickAt100 options to ensure there will always be a tick at 0 or 100 in the plot.
  • Fixed bug where cursor legend didn’t honor series showLabel option.

1.0.0a

  • Series can now be moved forward or backward in stack to e.g. bring a line forward when mousing over a point.
  • Can now move outside of grid area while zooming.  Can have zoom constrained to grid area or allow zooming outside.
  • Fixed issue #142 with tooltip drawn on top of event canvas, hiding mouse events.
  • Fixed #147 where pie slices with 0 value not rendering properly in IE.
  • Fixed #130 where stack data not sorted properly.
  • Fixed bug with null values not handled properly in category axes.
  • Fixed #156 where pie charts not rendering on QTWebKit.
  • Now using feature detection for canvas and canvas text capability rather than browser version.
  • Added enahncedLegendRenderer plugin to allow multi row/column legends and clickable labels to show/hide series.
  • Added fillToValue option to allow filled line plot to fill to an arbitrary value.
  • Added block plot plugin.
  • Added funnel type charts.
  • Added meter gauge type charts.
  • Added plot theming support.
  • $.jqplot.config.enablePlugins now false by default.
  • Implemented highlighting on bar, pie, donut, funnel, etc. charts.
  • Fix to pointlabels plugin to align labels properly on multi series plots.
  • Added custom error handling to display error message in plot area.
  • Fixed issue where would call to draw grid border of 0 width would result in a default border being drawn.
  • Added options to place legend outside of grid and shrink grid so everything stays within plot div.
  • Fixed bug in color generator so now calls to get() continually cycle through colors just like next().
  • Added defaultAxisStart option.
  • Added gradient fills to bubbles.
  • Added bubble charts.
  • Added showLabels option to bubble charts.
  • Pass bubble radius to event callback in bubble charts.
  • Fixed #207, typo in docs.
  • Fixed #206 where “value” pie slice data labels were displaying wrong value.
  • Fixed #147 with 0 value slices in IE6.
  • Fixed issue #241, disabled varyBarColor option in stacked charts.
  • Added dataRenderer option to allow custom processors for JSON, AJAX and anywhere else you might want to get data.
  • Fixed null value handling so plot now properly skip or join over nulls.
  • Fixed showTicks and showTickMarks option conflicts.
  • Fixed issue #185 where pointLabels plugin incompatibility could crash pie, donut and other plots.
  • Fixed #23 and #143 to obey gridPadding option.
  • Fixed #233 with highlighter tooltip separator.
  • Fixed #224 where type checking failing on GWT.
  • Fixed #272 with pie highlighting not working on replot.
  • Memory performance improvements.
  • Changes to build script so everything should build when pulled from repo.
  • Fixed issue #275, IE 6/7 don’t support array indexing of strings.
  • Added event listener hooks for mouseUp, mouseDown, etc. to all line plots.
  • Fixed bug with highlighter not working when null in data.
  • Updated to jQuery 1.4.4
  • Fixed bug where donut plots showed value of radians of slice instead of actual data.
  • Reverted to excanvas r3 so IE8 no longer has to emulate IE7.
  • Added tooltipContentEditor option to highlighter, allowing callback to manipulate tooltip content at run time (thanks Tim Bunce!).
  • Fixed bug where axes scale not resetting.
  • Fixed bug with date axes where data bounds not properly set.
  • Fixed issue where tick marks disappear if grid lines turned off.
  • Updated replot method to allow passing in axes options for more control.
  • Added experimental support for “broken” axes.
  • Fixed bug with pies where pies with 0 valued slices did not draw correctly.
  • Added canvasOverlay plugin to allow drawing of arbitrary shapes on a canvas over the plot.
  • Added option to display arbitrary text/html (message, animated gif, etc.) if plot is constructed without data.  Allow a “data loading” indicator to be shown.
  • Added resetAxisValues method to manually update axis ticks without redrawing the plot.
  • Fix to labels on negative bars so label postiion of ‘n’ will be below a negative bar, just as it is above a positive bar (thanks guigod!).
  • Added thousands separator character (‘) to sprintf formatting (thanks yuichi1004!).
  • Re-factored date parsing/formatting to use new jsDate module which does not extend the Date prototype.

0.9.7

  • Added Mekko chart plot type with enhanced legend and axes support.
  • Implemented vertical waterfall charts.  Can create waterfall plot as option to bar chart.  See examples folder of distribution.
  • Enhanced plot labels for waterfall style.
  • Enhanced bar plots so you can now color each bar of a series independently with the “varyBarColor” option.
  • Re-factored series drawing so that each series and series shadow drawn on it’s own canvas.  Allows series to be redrawn independently of each other.
  • Added additional default series colors.
  • Added useNegativeColors option to turn off negative color array and use only seriesColors array to define all bar/filled line colors.
  • Fix css for cursor legend.
  • Modified shape renderer so rectangles can be stroked and filled.
  • Re-factored date methods out of dateAxisRenderer so that date formatter and methods can be accesses outside of dateAxisRenderer plugin.
  • Fixed #132, now trigger series change event on plot target instead of drag canvas.
  • Fixes issue #116 where some source files had mix of tabs and spaces for indentation.  Should have been all spaces.
  • Fixed issue #126, some links broken in docs section of web site.
  • Fixed issue #90, trendline plugin incompatibility with pie renderer.
  • Updated samples in examples folder of distribution to include navigation links if web server is set up to process .html files with php.

0.9.6

  • New, easier to use, replot() method for placing plots in tabs, accordions, resizable containers or for changing plot parameters programmatically.
  • Updated legend renderer for pie charts to draw swatches which will print correctly.
  • Fixed issue #118 with patch from taum so autoscale option will honor tickInterval and numberTicks options
  • Fix to plot diameter calculation for initially hidden plots.
  • Added examples for making plots in jQuery UI tabs and accordions.
  • Fixed issue #120 where pie chart with single slice not displaying correctly in IE and Chrome

0.9.5.2

  • Fixed #102 where double clicking on plot that has zoom enabled, but has not been zoomed resulted in error.
  • Fixed bug where candlestick coloring options not working.
  • Added option to turn individual series labels off in the legend.

0.9.5.1

  • Fixed bug where tooltip not working with OHLC and candlestick charts.
  • Added additional marker styles: plus, X and dash.

0.9.5

  • Implemented “zoomProxy”.  zoomProxy allows zooming one plot from another such as an overview plot.
  • Zooming can now be constrained to just x or y axis.
  • Enhanced cursor plugin with vertical “dataTracking” line.  This is a line at the cursor location with a readout of data points at the line location which are displayed in the chart legend.
  • Changed cursor tooltip format string.  Now one format string is used for entire tooltip.
  • Added mechanisms to specify plot size when plot target is hidden or plot height/width otherwise cannot be determined from markup.
  • Added $.jqplot.config object to specify jqplot wide configuration options.  These include enablePlugins to globally set the default plugin state on/off and defaultHeight/defaultWidth to specify default plot height/width.
  • Added fillToZero option which forces filled charts to fill to zero as opposed to axis minimum.  Thus negative filled bar/line values will fill upwards to zero axis value.
  • Added option to disable stacking on individual lines.
  • Changed targetId property of the plot object so it now includes a “#” before the id string.
  • Improved tick and body sizing of Open Hi Low Close and candlestick charts.
  • Removed lots of web site related files from the repository.  This means that, if working from the sources, user’s won’t be able to build the jqplot web site and the docs/tests that are hosted on that site.  The minified and compressed distribution packages will build fine.
  • Lots of examples were added to a separate examples directory to better show functionality of jqPlot for local testing with the distribution.
  • Many various bug fixes and other minor enhancements.

0.9.4

  • Implemented axis labels.  Labels can be rendered in div tags or as canvas elements supporting rotated text.
  • Improved rotated axis label positioning so labels will start or end at a tick position.
  • Fixed bug where an empty data series would hang plot rendering.
  • completed issue #66 for misc. improvements to documentation.
  • Fixed issue #64 where the same ID’s were assigned to cursor and highlighter elements.
  • Added option to legend to encode special HTML characters.
  • Fixed undesirable behavior where point labels for points off the plot were being rendered.
  • Added edgeTolerance option to point label renderer to control rendering of labels near plot edges.

0.9.3

  • Preliminary support for axis labels.  Currently rendered into DIV tags, so no rotated label support.  This feature is currently experimental.
  • Fixed bug #52, needed space in tick div tag between style and class declarations or plot failed in certain application doctypes.
  • Fixed issue #54, miter style line join for chart lines causing spikes at steep changes in slope.  Changed miter style to round.
  • Added examples for new autoscaling algorithm.
  • Fixed bug #57, category axis labels disappear on redraw()
  • Improved algorithm which controlled maximum number of labels that would display on a category axis.
  • Fixed bug #45 where null values causing errors in plotData and gridData.
  • Fixed issue #60 where seriesColors option was not working.

0.9.2

  • Fixed bug #45 where a plot could crash if series had different numbers of points.
  • Fixed issue #50, added option to turn off sorting of series data.
  • Fixed issue #31, implemented a better axis autoscaling algorithm and added an autoscale option.

0.9.1

  • Fixed bug #40, when axis pad, padMax, padMin set to 0, graph would fail to render.
  • Fixed bug #41 where pie and bar charts not rendered correctly on redraw().
  • Fixed bug #11, filled stacked line plots not rendering correctly in IE.
  • Fixed bug #42 where stacked charts not rendering with string date axis ticks.
  • Fixed bug in redraw() method where axes ticks were not reset.
  • Fixed “jqplotPreRedrawEvent” that should have been named “jqplotPostRedraw” event.

0.9.0

  • Added Open Hi Low Close charts, Candlestick charts and Hi Low Close charts.
  • Added support for arbitrary labels on the data points.
  • Enhanced highlighter plugin to allow custom formatting control of entire tooltip.
  • Enhanced highlighter to support multiple y values in a data point.
  • Fixed bug #38 where series with a single point with a negative value would fail.
  • Improvements to examples to show what plugins to include.
  • Expanded documentation for some of the plugins.

0.8.5

  • Added zooming ability with double click or single click options to reset zoom.
  • Modified default tick spacing algorithm for date axes to give more space to ticks.
  • Fixed bug #2 where tickInterval wasn’t working properly.
  • Added neighborThreshold option to control how close mouse must be to point to trigger neighbor detection.
  • Added double click event handler on plot.

0.8.0

  • Support for up to 9 y axes.
  • Added option to control padding at max/min bounds of axes separately.
  • Closed issue #21, added options to control grid line color and width.
  • Closed issue #20, added options to filled line charts to stoke above fill and customize fill color and transparency.
  • Improved structure of on line documentation to make usage and options docs default.
  • Added much documentation on options and css styling.

0.7.1

  • Bug fix release
  • Fixed bug #6, missing semi-colons messing up some javascript compressors.
  • Fixed bug #13 where 2D ticks array of [values, labels] would fail to renderer with DateAxisRenderer.
  • Fixes bug #16 where pie renderer overwriting options for all plot types and crashing non pie plots.
  • Fixes bug #17 constrainTo dragable option mispelled as “contstrainTo”.  Fixed dragable color issue when used with trend lines.

0.7.0

  • Pie chart support
  • Enabled tooltipLocation option in highlighter.
  • Highlighter Tooltip will account for mark size and highlight size when positioning itself.
  • Added ability to show just x, y or both axes in highlighter tooltip.
  • Added customization of separator between axes values in highlighter tooltip.
  • Modified how shadows are drawn for lines, bars and markers.  Now drawn first, so they are always behind the object.
  • Adjustments to shadow parameters on lines to account for new shadow positioning.
  • Added a ColorGenerator class to robustly return next available color for a plot with wrap around to first color at end.
  • Udates to docs about css file.
  • Fixed bug with String x values in series and IE error on sorting (Category Axis).
  • Added cursor changes in dragable plugin when cursor near dragable point.

0.6.6b

  • Added excanvas.js and excanvas.min.js to compressed distributions.
  • Added example/test html pages I had locally into repository and to compressed distributions.

0.6.6a

  • Removed absolute positioning from dom element and put back into css file.
  • Duplicate of 0.6.6 with a suffix to unambiguously differentiate between previously posted 0.6.6 release.

0.6.6

  • Fixed bug #5, trend line plugin failing when no trend line options specified.
  • Added absolute position css spec to axis tick dom element.
  • Enhancement to category axes, more intuitive handling of series with missing data values.

0.6.5

  • Fixed bug #4, series of unequal data length not rendering correctly.  This is a bugfix release only.

0.6.4

  • Fixed bug (issue #1 in tracker) where flat line data series (all x and/or y values are euqal) or single value data series would crash.

0.6.3

  • Support for stacked line (a.k.a. area) and stacked bar (horizontal and vertical) charts.
  • Refactored barRenderer to use default shape and shadow renderers.
  • Added info (contacts & support information) page to web site.

0.6.2

  • This is a minor upgrade to docs and build only.  No functionality has changed.
  • Ant build script generates entire site, examples, tests and distribution.
  • Improvements to documentation.

0.6.1

  • New sprintf implementation from Ash Searle that implements %g.
  • Fix to sprintf e/f formats.
  • Created new format specifier, %p and %P to preserve significance.
  • Modified p/P format to better display larger numbers.
  • Fixed and simplified significant digits calculation for sprintf.
  • Added option to have cursor tooltip follow the mouse or not.
  • Added options to change size of highlight.
  • Updates to handle dates like ‘6-May-09’.
  • Mods to improve look of web site.
  • Updates to documentation.
  • Added license and copyright statement to source files.

0.6.0

  • Added rotated text support.  Uses native canvas text functionality in browsers that support it or draws text on canvas with Hershey font
  • metrics for non-supporting browsers.
  • Removed lots of lint in js code.
  • Moved tick css from js code into css file.
  • Fix to tick positioning css.  y axis ticks were positioned to wrong side of axis div.
  • Re-factored axis tick renderer instantiation into the axes renderers themselves.

For changes prior to 0.6.0 release, please see change log at http://bitbucket.org/cleonello/jqplot/changesets/

+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/gpl-2-0-txt.html b/phpgwapi/js/jquery/jqplot/docs/files/gpl-2-0-txt.html new file mode 100644 index 0000000000..0dc5f9b6cd --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/gpl-2-0-txt.html @@ -0,0 +1,39 @@ + + +GPL Version 2 + + + + + + + + + +

GNU GENERAL PUBLIC LICENSE Version 2, June 1991

Copyright © 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it.  By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.  This General Public License applies to most of the Free Software Foundation’s software and to any other program whose authors commit to using it.  (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.)  You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price.  Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights.  These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have.  You must make sure that they, too, receive or can get the source code.  And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author’s protection and ours, we want to make certain that everyone understands that there is no warranty for this free software.  If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors’ reputations.

Finally, any free program is threatened constantly by software patents.  We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary.  To prevent this, we have made it clear that any patent must be licensed for everyone’s free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0.  This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License.  The “Program”, below, refers to any such program or work, and a “work based on the Program” means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language.  (Hereinafter, translation is included without limitation in the term “modification”.)  Each licensee is addressed as “you”.

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope.  The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program).  Whether that is true depends on what the Program does.

1.  You may copy and distribute verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2.  You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.

b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.

c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License.  (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works.  But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3.  You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer to distribute corresponding source code.  (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for making modifications to it.  For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable.  However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

4.  You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License.  Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License.  However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

5.  You are not required to accept this License, since you have not signed it.  However, nothing else grants you permission to modify or distribute the Program or its derivative works.  These actions are prohibited by law if you do not accept this License.  Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

6.  Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions.  You may not impose any further restrictions on the recipients’ exercise of the rights granted herein.  You are not responsible for enforcing compliance by third parties to this License.

7.  If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License.  If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all.  For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices.  Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

8.  If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded.  In such case, this License incorporates the limitation as if written in the body of this License.

9.  The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time.  Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Program specifies a version number of this License which applies to it and “any later version”, you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation.  If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

10.  If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission.  For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this.  Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

11.  BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12.  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/background.jpg b/phpgwapi/js/jquery/jqplot/docs/files/images/background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c15505294720a0e1d83a5c039e05298d080e8a54 GIT binary patch literal 1101 zcmex=%kxU@K!VDr=Sy-4^*jU-vz?hwr zgN>b&osEryn}d@J1b{3aZY~}W2V@9DD-$a-Gbv!^|O!0je; zaq`9Wk6&J#G%H|hY_`JIz233ax_R@YC$CNjvr;*EeCylenMUVtu&zB*xN?$W<>6c0 zHNRNbUU$0lC%nhvtw2hjW9H$x-7!wzzP?GFFUq?1r|zdMB?WipMl^yL?H^S>H>IW~3b+w*PF{l*G= z_nYV(d9`=H{9~gd6|8TMl)XD$_%ZITrXkN(>EGA5Rm_W696sw=Oh3C literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/basicline.png b/phpgwapi/js/jquery/jqplot/docs/files/images/basicline.png new file mode 100644 index 0000000000000000000000000000000000000000..1cc6bc69136dcce4bea1206afac445ae996c0e8c GIT binary patch literal 17024 zcmcJ$bx>Sg^DYX*;2NCZ?(XguJV(fZXXSBmW8o z1z@p}lvI_Mlq6Gib+WXvw}683hA#g)VuvM;-}hZ95h;aEcT<`?3LE_g(+}06)H<7A z><%aceNM?ECp(h0nI4{)O4n;TtuaOj6d^g-;!;->d*VP*F}mZn2Xt(y#G3ZnAu7WV zyj2U&z{exb)1y{F7^zf`IR_c2zi3vyl2g%Gv?|mQS{S`r&7Q`Mj@~C4d2A{v(C2Q5 zG2Yh>idzD_FK3o9{?ABoMXpzPtdE&cqR6%ReEKJ zVsWVkPwPEdV3@c2-h^eg^%nYsG+0eQnRtBa&x_7!yZt$|WZ4E<*O+ezlBDz`!@ zyo*zKhYK$ICdZ~a7vWkJyS(M;E4O?jt$e)VFK}bFNoo>!Xedl#k??59OiNx{;3xd! z-qgsUAJ3;L6^-E+Ue1Rccw^})ix%;^*|f!b(>eoEv+Ot2SoE60QKE_}Wq*`fXzd^X zLUfkXaf5LNV?lvY~C}FKKb+53o#Hg{{+c zQqc%h-xBdIYUWejJjaG!)7_G~+qVOZM(2edCq}aP-7ItNN9Rf1Muj*Fu%y4N!6TAE zQzd=|UhQksmtkRw0px-)#X#MUP>5upI_h9RYJ*ZNjwC=13Ks1YnkpDLnF58Rzre$+ zg#vjIo39l<5eidI4?yQ^vskCi4r!pec18l}h0Fml7hL2pW!ejA0O`>0|4D}+e88U? zrUc`+R{#sN#wg_>Ehe`QsPzUPr{km3v z)F8_jsy-|H`sG!BC8LXIf}|x>>*;$c{m$kbJ=W`Z}*)xL`_DIq?MGMQRz4r&$^t5R_?W`7v5R9;}Ol?)-42L1N~~Ua|qX<3cA*)sqGwd4O0aj^3~M)TEPH^C+C}Yzc0<|XnoLK zDC~}^%$kh3FXH;_`_4GY1^rmoxQwnTlztNaUv`WTdJ0mt*lg-sU`T`MBSaa13tD}$a7UzAORAW}0+ zhZ?&aN@e9uR}{#0G$%4eAX;s$^i}zEo?nS0k+SlDdT6VVTBgI3s@E2u7O!!^gtqt9 zCo~L9*zh7^KeZ^R*B=sT8QI#~l6Z5r-i?RG76ybYHHrf2ppQ+_%d2t5c4TlcMnJSM z${OT0r{zRB%fG6RGM0Yyx#SliB0b;b!cP3I@tX16?5FUN`;*7_RcQ|K9w%@t6tVwu;~&mc)Fn5A)FQ)iNL>~o0{6Z zeawTmYFv~Rqx`s*;rZ&Qf~RwFN6i1x63db`ZI^Zj3K7_bVd7y z>}R-w)!^J2>YrQEmWSBJKY>L%6?(7zG_H#=nnoFD1DUJKi_-c=?d^0w`QjiDheAXN zg>v86nkIrb%jtdzL)7m+IZlGn>)tuA&G_oE!YOJnD+srcDVY53LQ9E6Gdvk(3Tbt@ z26jc#iIlSFn>sNU`V(aL1p_}ylPRu!NUbQ>SxBHxsj27YCf~JJ_>Lx@X>>l^_bWmA~imnWdh{-|DXFk4nMU*j(d(EXjY|!9yJ(y9K~qs-D{mR9#GGWrgOHndshdK zXdMc5DtdT-M_>FXMMj5|UrHl7uvyg#-Lz=KWMvDTPN-V0M^8}sbvT5v| zAO{fvlncHLd3pMNAq0w^6XMul#@_gh3(ImM$1X{g_yYVp+lcQJo3QTJDjtCY$fBG3 zUE&BoaNpIVQ1Vl1(>am+`Bb`$95YG~dekih6=6K!k{xe4J|!P(@#P-+2pj7bQ#OSh zX{o3<;(p-6cjs?B;C`0k~zS?oSY8Nx+b^P>2fmn}5n5t|iNSD)Ro}Op z6&U4-E`G*TO}h$whj!*hSxdO;i1z;-dS|(3oQkK zJ9*ughAnFiNpJQtob4W1p&;v<(1IT`{$57vXki@HUejdunntu|BF&((<%54b8A@Cx1|J}>ja0IUziaiE zzadKGxf7#R_R#tOmk0h)YcS40mHQDuv1>8fhIl|@sXUc=VeAcU*!;tMnCm?Ol0Fw! zoH#%(*9dU*+kojXk~&Fh7nRIm+%J?wzvG8`005R{hBs~p?^{!AZ&)}04+~ia0zQmT zsHrCo??~r-&E!_ewRbo`78!vVDabU7>BljsavcFlUj1qVf?EP-XkTcVOQ!^-prZjL zx!^Y`z`QdabxduOluBJ_lT5bF1=G{9y=~48AaJz1?g_S4GHjR;bw|jXFFe8a|7d}I zim{P}JV`TVxW`*>tDO7a0kr^Y#9ddukz0qy>ZMLm&25s{iFD3LNGK57fsrXzwJAL7 z_t`hH$uXr(68!tq$O`!fZq+qxZ2UJj%mXcO&qd}OqB-2Gd(z&iZhKV75GxH**9pz# zmlLx9dY=+BY?6Y4$@nY}=W8!=+s{hVJ6>zaNm7AF7HeA?FJ}FyZ zt-8jw;B3u@~|P zL|WTi*hoF*fu*53C8^jv5fQ{2JGPnA{2BgMOlG>)9YV%5$p?N8XU8|Bhketgb#U+& zaTi=j$f(cP>41XDRW4(%SDN=`*{&UR>t3k=ZrkpJKZ0yLt}9YjxW?5i-dGgw2I69! z$8+I;v{rtS9kRN6#q0P#Z(IFZ~ujXn8 zbA0cTOsf9X`9Hh;UExSe$!A@90p%#e7n(R@|0_^gRh?zvd-DK zy(&k;c>$b687wF6D#tk~tHWw5jjBd%4ci7lZuVRU8D>9(356Sy*$78mqaY*ZUPBv#Q_J@Vr`P6 zll78(-QEVx-jQ@o@BvcSB)*UM^yOK;CZ%Mr6|$$^4?i4Kh|0tDaWw*3fFvpe#W-lq zHdgVQp~rtbMXvuUBj9Oh1iG0Z0?$H$iNOMhz{S_Ths7UWayLpgo5cCKpQ)WwYD(;K zP83Y^S{r0sANFF&dbBva97a4GdF`tCnJ$JJpJJ?d45bUjEfm(T?d&S7+6=uz!llJn z^&`k3=$V!cwpm#@BsTs2g=d8vX-6ASl0`&k?84X8Dv7er!ig(D6iW(er=b*lnPo1J zF!AGhT2SiJE>fzN!2a^ko(;+_62CCp0%8qg z31QHdjOm3*#xdGzpY8A=Eu51p7^Xo|ewXw#E7#IM9wiR-oGc=c? zBCn{)|F}#LyLhnh9Aw{lEz|kj6zBbqCs(v&K9Q{qK9Sh_913D(H`OuX0Ya~j2~KJa`9u-BlL(EaFCJ$Q6%iY9!4w!%Q(X*;)HMrGyBqw z%;AEz?Jy3Ix^f&_F9~P^hKbQmUGTWChLxq;oI+M9@b4~dtw2vLAt(cAak7sC1=7PI^(=ZrpxmxOqVf9S|$idb%d=%FAfLJV=&48)OI z>o3gm6q?dGle4i!0Vk88P*|(P$;tjMnbON;w*FSknB^|hrE@mnJA*Nf#gWF9VWO0YHQfEm31R-#c;&!!*B;J8 z@*k&JM*-$Kg|Ly_H0p)D1#(w(mU3G@Z41>kILffyFTp&B&L_U}f?-WN`1=(cW^Znv z{Xa_4eFsrWo?Rp`%DO}O<|v#*Uw6hC;hQ*!5J06E0<4n>_KmE2!O8OLEwe*OvESa7A%IwJtmX-1XrxBc&sdt$My1NdK&VqY#o(cP@9Nto*=Ko+8oXA_IcNakK#4R! z2t8hDcUdD&;wOG^JOhTY@qnyj5$F|ifw_3NslN+4mcf?YveW-;$Xo)z(R^xAy(Cz0OZR|~B7n;*pbJGB zq=2tGjE_ha8w_sXEPs5QMax?uXKT%!+pHw?n)xux9JNgb>UkGjFPUa|n)n+6e}CEv zKGf~F_mz2l66#;XPyqQDP!PF;-DJ+te&e@EN)Y6M!zaOPnByc6kQNfQO1ke6W6t=} zIjhOB0T8WYpxm?!1$)RB`W_a@CypZkcq2fw#9&JVU`qn~2^_?0*|8W1m@A$zaf;dH zfl;C0Rmh?1v5Yf~B0AN1a`9>zjE$k&Bq`pbz_I`kNGPC3Ffjh|6kii#@NJ}7unA5G zQZ;X@{%h{W;UIDfYwqCRkz3|HpvXs^`f33|OpTlwzZ_WwMCtuH2gF^OwELVfdyl-{ zFjgGB^%x^o5rC3=njWM$B>-r)jcF4O!mOL$&7tj|lE|fj&zbxm7;!csu{%CBv~~s& zi8B90^a?plVjR8mNh*(h*=2+w4zXm0r<4AxM1VB~^^*Tt_|I2u#P2_6^i=W&>GdHo z&W04(-)Hho5&1c^fp)b(p72H|fovA#`4SbLe<MMpvS}_YF1#t9v z5-Sr>y9@QxxH5Z!z3}9owy{2rm71y;9Pn^r*VAl#-?bl3jf1YCnOG2+>Ekg&P%aM0 zpaIu9*dMMwv`P|lOQiYqlDo6+N7I6UMXAtU`;Gjb z;6frJqRd`G#4h$5OJ5OwI3%NlflxIfXnc&p;5<3XG1(pr0Ry3a7?{AGXD`i#+@`=R zsuwz%Z*Qab0E?5k1b?njLBfYorGFo7_%iY;JLM$4oFv+`u9Z3frWU6{dj!Y0d;)G7(455-r zF9S!k@t!Tq>$xgFVDvFvKInN<#*v9jru-v-@IC}mFz_IR9c>18XI48gwsjt~j_N!|*NMud;w zt2!zpl#jNZq;0e0aro=!Y=<`dZp=_6^>EHe%b}ji@#9ENMacbB{uQ$p8iYtEf{lS8 z1|E>O73gh%c8yl8y?53%KI2ezGQjttK%(4)`Vs3IY9Y0!duLPk_|OhSK|O-L+*xFY!-Q5{i@@=m`!>5 zc;EUk+T%c-Ase{82$YFnI)tiSPY&@MB>ffCkE`(&FFY|%eLY1kzVN&>+9uRr#0C+f zgod~}l-nekiXP$&PcaJE9f^~ZHJLhL3;vT|+Yk?SSnTEyhJ?1es7;>z-<8$G5R;+x%ci-83Aqud#akPzHybzIP#&H-Y} z|B0o^z5yX%qag$G7myt@QQk-926ZLs0%0BH(%9Z%%Hcrg*qG?9qJr0KW|>0YwMjHG9EDyAufwz95CrautQ+DZ)76Tgosj3 zChV$wz1U`W9@wT8dgAGd8sq2ze#-4VB!b-~>ivxena|7`WIkQt(O<+a-ttIa+9cga z56$N=?vxGBZPYN4^mVx?wJ44eR8JFm1_XQ5@^}}vch#44ESrww0KEF9X(WhLp-=&j zeTWc%vg6I65wN>t{p2=v_l9KkL?IEgfcJ|NU=eAvL|i%7E>fE{sl{oJm;l zsbruqjI->Q^4nq3v|N0Yix4q)-z1w_WXm+44@RBTh5hbh*sv_idiaMW?*R5gj$`Sf zS9g4(l;D1wL@d}ZdxB{5s1`d#5Z~ zGN0&BV~%fa$)C^_a?0*_056B5Hx6bLCn&g%4D&8LcsQEehp>sKaq;-}QF4QgPXm%t zl%x*dPZX0tjOyukF(spuO3t4mlvca)7J7H?&4>NgATP`&QLGCQ-=TNh1*^-~sZQ0P zPs&?l+Xvq>YPvmavG5t7x>mOup$&74h2Tzt=}(L5OA#TGEzu^GeVsqnEyV18POL+@ zNq6v1hLg+@qFP~LQm3=KPysb7HcN!g_BjVQzn$J8jvCs~1cbQ!{J!{LKBOgt+;wU> zNb|I@mo0vssm;xRI78m{K@6f(yXW!T+w}6^4NHt19LEF%1Uz~)6-iti8xVnSMtmX% z@j(QBPwahj0TZ%Mp=W8Sl_Jdf^=2-llPrz_d&*2wZTJ!91i(!!b%R4=l*c^ z4WVMSTXIdA0Ckp~yKIE;Bey{Sya*WdM6nHovv!)>$kpqcI^So1uz-5%E6!Kgp7@`7 zT3Waj5y=P_bk5PaF+LO^IY3s+O2CmHiArk1I{zP~2N!ox;;^DKblyQkH^P_J4fi+z z9&KV8D(2pIvD{5nm1lv3vE9o{{~Ob!0LE53^=VXL??+nR1x`q&nL28Y5(I*5@K#~c z*T0*{T@p?bFQ4SJV1-gbPFehohp}fIjC~7)VgbA#g1z}M@uQ$F$5MTjUluk~X&4ln zREE=#nu|*bD=v62TD-F$u>-vHFbrZ3#hT!AR%7)n>IoTiY`ZtCQx1aDlChllLFc^c zvMGD48xfLz7Rc074hmsB8VPk~Wrw$Oeq@Xv#XVmFWbl#q!8#*7Iyp%a3YLXGt2&uo zN-U%F494luPh+{qzq{vgI~s`%71`IB?-y5kBLGRC!^TW!UnN*sgYQMy>5ofRX>LTH z3`kv)F&EWF0*Z#ADM9$;SO66ZM|;Zr`EGkq3f9>()aKIWqsp-c46L%CLwL&1OsMSA zvraQZl}s+Rye!DH+>0o)N)x+0B|!@0{!9V^2w^H3X(gnM*t86#c^+zO)8k0ip%6wY z@WP^`akeQ1Th9&2&MoKyk0*8=dHo*<&G(2K@BugAa%Xi zT;ca*7~Eg8i_Ngkhzv` zJ6rkH*CQ+x*a9TRmoL}Na%OM$41=1Zt-?NJ^M4BD(7cIN^MLJ3bD?uKE93Q>X{H!x<%GdPvXQf1OB3 zl=Ds_1Q|+8e{?B{gOGPYvT|fG5ZD^4Jo_djC~IK2c9goU01jvbTR`BvW@%`3H6T(} z%zGFmHFD?%3$L+1qM&Fbkq)w*RcZmtbtzaJ9`zuaJn*$F9E6LWzg|j@4Os0(I?lP;|3b6`EPtR#D^;ax2@US+g!j^r`=}6Ck@f=o zyxeBu@p$|z)nK71(89yah~SdsVWNgZc6B1W<0N8k&gpN?r~A9^%UG5kQv^iouaH%) z6F6NO6%ylQMVS6ogQjJ$u3gFK&ebYONfg)))~d@yK!s<^Csy)fRC>UN`T$VakDN*{Y50>t{zL_9}LWKDrf<<^}Abt;_JH8 z;>^GCi#Ho3)>1cN?5dJvxJ$W?_RRo0}l1jrKs?)oQu4g3OKbZ=XdD4 zxZ(TSe>#_C*O#gnUVr`^sVsfk`Lw%>Us!h+{uabqE&7V+Zy$?DdTFpJPb75AnKv-n zect?xq-&>Q>vX5V?DQPrQD3Am%akdY9!`=qAyHPLm&)|2rZmFZ-jScoR@ruGBSozz zQWVe@LJ*t6^3z&K`*Ev*@*UzC2BLKc)T!{)bAr>gd(L@qvyRo5bIlYKcoZ5iWG8P+ zdrV1D$`BGPgqnE?DgD7h8f|Ux+5C+w;pq?%IQw(^5)XHB=z`Y3o*Gs5aCyA|MdpD> z?|hsWcNZgR*~4@y59_4GvJXE3f%P78T)qBo>wiy$(yr=q1~muYqi)`UrNVdChIw|} zELU}GDkR{nm%tUR1C5@^qNpPTLKzPcNJQyuew{+1?C^4Ad*O=ZpY1opFJ)@KB@VGh zW3uiY%x{&H8X7W80y%Ej_|L@5++);y=5$ zoNQ_)@;R3~8z|%43=V7q8kOilgNPl1U!5Gh@4H1N6Fc9iwdZv{OB0!Kn6@R0zJR)N zCoj=z(9r?wis4@Q;@#n9N60q~N@ zW#RFRqd-<^IT6A$b~j*g@m}Ivc}GX_h?~>akC+M*U6CnV8cse3WKud-Lhh^jL}pN! zcN0M9SJBrow+r42DcI+*N@N1{+&PE|u+Be@ur?P3Skde0sZ(00RsSpwx%TBRn6ccS zsn{43ZFM1W+81QfYr4SW^=o6Q=C?0(l-&9}@KNDyuauRX7p+7i^`f5@$GYT8*b-8| zE4rn0UYG71M11Eohwbqd>pc^XtW?Yy(HR0_X=E^+^NNabewW^xS&mO4Q;48)Mr0tY zl?DvZl3fIj$sV>jKu+%@F4k!~q_CT|IR9XNl@-GdH~zEA??wE?ZLZ8^F?Qwu)D0Q* zLE#GPv^yGUz%EWBISi1Bbf9hd5dqxFICg$|-*S*142Fdj2d;XY*@mA(nT;9 z&epFpy#gTI#pJB@w{d$aD4_T1J`^puo4(snl{Y<3jc;{o3Wmk0$w+ZwmEmuw!Xpid z8xD5JGU(>n{t```tTPu3_jZnr5K6K$nmKHF37)D-zQP}8ft2nXHxTQR$cSy}q-nml zUhK{h?T7nqtjdLtKuYg;h52>!qc_L4Pje1q;AAGG0u5n1#h=`#cJ_}tvm=7 zjsRZ~0T@O`3zTnIUY|Tvks%vTcXhb`-o2ebQB`{4F;BzGhYB1GhFrMZXXQ>}8JE9-`4HPJ;#K~OW?-V=R# z3LX_Y0*_n;^Jw|AzwDC01Cjjvwau*UOUEZ5#G9%)($bu*7fadG#4TRa3k4~Vf`}WF z3qH{Jztmt=24GqEw$M`sbb%)r%b2E zu%Z#Szk=i=Z~TLQ|K#jyCii%Y>VSfgt9C6LBuIc{X34gJOiu)-18w$;?NC$8yi^Qu z;V4O(6+@XtW351Uq%FmRdNsALEl#<1f9Vx`7JrOGz0r?BZLa8B?&@Q|`IL^W`_b&v z!ffundRTtS>M^SMZHYefA0;$F6EE-m%{?Ry2xA+E5+QkMUUQ8!HfUfN_+D&r(S0xX z5lHu*aLvS+3!lor58GgrDf<{Hbbw}vfEW{%KmaTcajx-P!D1MJqn-s&!#>L0!LnPp-bb?3y^ROhBwn|{_{z$$BweA(#(>#lc>LXvK| z&&y)L-so9?4X6C&zPqnCk`Y2SnmKk^FjFbwGjNy6KVBLCvGg@~m z1}ck_@7Bfn+IZb2c^@P#V$6fnYOyJYi$Wabvt2dIfp>($?bE7H6AXy-l6XQyuqSk%wN4!gz}z7O+cOBbgZF!e8Kdk{(%5^gM^R?Dbr#kL z-BFiBRF^kasm!=#v74$FE-1@+cPp$$+Xj7jro{tb)BdPE3S@yKzYi`LRZN4ubFLLYw1P_;ib?&Lg%yV%CFpthw% zHL4C%ED44Ts?b@yCGN(q%F>!NI*_VaE`ThE{ z?xO&Hhp|Wkn_(*piu9Xo~4B(NPR>nr2Fq7nV`s8 zh7X|Q;?l%>3w}Xlg-zFXOO|oO7M1f51i_BbEKs7ni3Iw#+=N8jeLlZRu#5U~qB>;0|*#JMhf?iiop6F$mA!l-XoSQMr~b+S96$mnT4!?FglZCSTW zV}9Et1ez=)L{p_#Zw z^${T9ZsTHGTD5R+aHuY0P81g$ol@n~rbXG(P^e%xNvRSW=D7DRT%IC;(6Z?lIZoi* zPU-BX1 z;>}_gxQZZj9DEl$P1ozvEgW?Qf3XK z$t8_(oavlv%N_apxfYY;I9yR-=%qORLy?2LX-hT_9ISki;UssY?@m<|#g-nTPGhCzC z=d4FwkG}RXvbHg4{3a`#yZuQ>hwZ;rJID)s_(i^FEI&YfvP6{d2WG61EQBpbY@3;~ zphJO8#1JTOvnp^^=DO2LK*_#ZW44*#Npf0TqW@j5_GPrIQ}grkbLeYXeNd6*_7Oe- z+WVP@+v`jbzqJAC&*JJdWa96Uh@K9bDhkAJ;iZgG2~yMkj7$)4Vg)-=>3oFV45<1N z)9~tkN@pS+8`{~_Qcx<1J`E$&54HHaHY}#csb*dbCny*_0 zwHpz_*QdMywtbjLW{2g?zHJGyz^yQA1jbd$v-MzwEM?j_+WyS$P?67MU%#w%+sP=c z9T~kk?Ybyz$3)T+WUf3?FC<+KN56 zTA!DSMY-5|be(59f;LyJa4#yI?$jQ?Z8HZ2wt>>GwqbV+WQ9MiP|#W)dOnTqd|I_a zpwGT6@_RkD)H__Y3%u^C#_c;`Xu0gH{DiHW{NOA4xB28Zr#f;!yH>PP05WrgX^y{?}pz#@_ z{r>n*;8WxVzfqvOpDLxmE+&@ zuS%5-%uSCV8y%|#N8fXHm08L8Ac5J9rpHAiC!c`E2~Y85vg+fDBEq0;>*e#U>W)Gb zA6-PEvAQl6H$&0Y%}sm;=eDj+pzncaP~+7Fy%v_YjJJ&yQnN;`md21j#RPo}C9JOn zGB#4OJc&jU|jgzk^1U*nD$P*Lz*(($W zWRqP7E96_0x~g}y)+_@99W=bWR{DV=LaKuYG;NH8eM2>8Oy>xQs(=bcJkda>(b}=L z_WS)?qq4if1wSj^_Lj)R{P4zP9mL-+myIX)*O@`D)3Vy8*|*@DF{Ll1I3uni9fT78 zQ-_s2I+ZUMM?+a*ibiZ!t0|Hte+hq-rkC|9d|F|pM!T=!TO-0!Gy`)eQMdmmMPKEe&T_={go$T;Q8b{;|Ghl5H<} zWnp4uXJ8Uq0&HOEEc#;#mMYZu zp3q&(;6>t7prNudTC1SC3=|pGNF#=p7%VV`0k^!o>AGJb({{!CMWuGAFJJ*lW=80D z@fcT0x2-d$`2)@%7CI>za4W&t9vxv;mbFp`Ri(7Yw!WE#_><>j+og!F?d5|k58jx; z<#7c1f!``qOd=oP+Pzw6q4gNbE5h;yM9{$zn!fSD)kwa23!mj?!08 z19$(3coo=Jb#jmw+^urdDy-v(D5CTaYYd&q0ab*i`Jjh}i(WsT^}(H4WT|dZy|zB2 z9|YAKlqQ|RN(@)mK?|4_yw%F znUMP<49d-ryA=E-H6`hNuH8;Eceh8mhrVO+GD#lC!~x8_0ns4+SiPr#yPEjb zd>Z>lEtu<84vxXf<^Z?u^U%1{)`=r7%dOBk*r!G7T2ND7bNrPS`0#;z{BmGr^>zNY zv!l(fsG$S7dCCmmddv^=vGx(c4;{Xjg(>Ml%18=y!`N3fpBkEBRAGa&MuEq{0$7vySu$g zw0q+objGlM$g^KAos!>jQ9~QT(CMkf_5;D3F*+<#1KV0BFi-?uWiAA2BR0oEGN0!L zv-f717%lSL?W9a6ZQoKSc4UJ0OQ-71{iCg;McW#U>0!K{ZW}$-+;FcQFLO!)YPbUF z%Q>D7sU!-UU_u|xONl@8@GSE0Er}}k^IKbA)^?2aI@M;xEM+IAoa@rG$9uODw0G>e zwQ*z425?hU>v?02jpB`R;RiIlJos=gMDljtOx8!3Rp33#WPAdqhCmX<0&xPSbQ7CM zHwSk|#CUmL5R7&%HWq8!!WZG{lE_i&5J~M%TE4$5B)zJ_Rut2GHW1>@`7bHqG9v)+ zOk&gEKY$$h&`vUIqP_P*FcMo)?CarjWZ^)W)?_&(2QB%DeR^jO{drC;>f8wwNCjDv zO75yOWs(z8O4L7Jez1bvPda;3v3DYXNs46Rr_1jN{n`e<>SrfoM*>nYkF@D9@x#PI zc(Oy7>oJor$*$!mZ2YB^-gz_OLQcDTuplvnkQoy+v8R=Er*U9WK_2y7+W%B!2DL92dO4R1VQ^b+y7}V|1~$mkQrF*^yELqZrK;}XRfR? ztJ-R)*-Mww*L9_>V{zqU^WOQXXmf6z-R=(Wo`}#Lqz)ZYyAuT#1AMxD`nssw*Zn@b zt!1MsURGD`e1lb)l_5*yGzB0b!WSSCF@IvL95`Sx@BTFg;W_pTegR~3F#sYZ+c@RH z)*$ILUz}jOTb(@1is=}2Vf$|a+;gfpQjOE;l3jV}z$k}?d#};?dYic*k){N;;jEvF z5lvOR_KEHLsbk?=1vhIT82D*N)24t04*YUdr#3!P8(7x8CE4r`^jU(HYkN5vr*+A?@87RU>-QGrdgqb8T%F7CdGgESNebxY z2H`ytFRgb+ejCbtkJ1h1Wm+nhGKGA?1x>}~8;^{~S8Vav;J_xO%63YQ(PZ6jF{CA| zad)sPa-Ktp>g;K%)&%xRcs|YP`{7ll!{1o-QgmGvFTEVEqJpls*u*<@ap6jRX){%P zyx8b8Stwsc+_`sHV4m3|W?-;YhGV%Q!{`c=1jiuR72MZkebM%AoxG}(!b-zan+T-ljR?V-92p64gWUPN3g+^kZ+-BQ%O>Y}YrNWXrs`0i} zI#Lg)4%H}OP57z6;l2m@MK)jGKOtJLP$HY#;A* z+UMqYm97}q#HISJbxmXi%1?wgB6nRGBYxJ7ux=y<9-jshpTi<;!EBS&vW7o@%zMNc znlM+izJl)6W|KO9a>h+=q+{=-lsR?;T-Ve@*-)(nbm+Dm(;1Z4xr@&GH$$zZ6kz{Gp&#=Hu?;GW1ds_&Ayv zM29HX-$=6LRg>@9o577fHsnI{HrGfM!iLRS0CJ($@IBT1&XKj;h0Y{bHMC@@%EV zB>#NBrSjcj$Tl*>9B2rsYKng*as2%B1#KUX?*iXZ!LMc|2dlbbVT@iB>x+v(9|KofO=ZQG*8XhZW(MdA7^XZWqnvGw|sf zIHJ1ToT9p`QO%BU5`1VY8cqCG>sR#DP!y&zdA5#lw+bruNW(cWhnWMv#8GUuZTV$c zeq;ud8e9NBZ#J)+uu2B9aAfQ$jfBU*tbG*ZGU3_&KHG7$U!&Y1 zwBh1gbx;VlZ?L&F<9^&-R?|W8B~oi|Jj5pdq)$_+Y}7VXD zATxh4m)zdq>q7_K-!5?mopiyU7>V^)W0{;%PJ42CuRhFpe$>71uD9bA(Y0|{x?XB` z7EiG)%E%b>bjYF}+I%Qb$N>|?6NI^Y^aEy>kwm*pKmBDR#S1nvKP{NK-z3F6 zoRQR4VyR)?^gUWWzhsW9-*_oHlft_vs1x{tM|J1jbp(5f%ha^+&0%OXB){zQQPqrv z{qIz)i<7)DY{skx4bRQ8-&I!c*mZxP$}leB_xuUF5sX@Jgxj-dV#x-+4(fbxOgp7e zig!Sg*A4GHIUesBKtZ=nTj1+<_V5pKAHd>MIR91@X76)TwDY+bFR(padv_!l7PS1| z>bG)3{Xk}u8~YW5RbSgxryF;i;qSP`K?AL~s|krLcs*rY=`w^q8ICIl(uN_yy@`YF_WEi%49QXlkcF zclee3s1N+JV}SB|dqLr`LaEb8GH@S7;^pZgN6YK*h4)5cQ-!{v^xiVqtIy!klgP%_ z;qUFAY=gp5jFor4ZY-O|bE{7$tFHS83Wzt+`GePgqf>< zeiiUzO;QDdgTDCeomq4i$TK5`IY)& z4xcVEEKBKwCt{q)j~h#}hQ;aavaG2Du7*E<`?gaIQ-7IJODL+LUh^fb!T(`j;fqUYvFtc&>PGjg zNM`)o9OU3&1nk#_BBZwX!1<|-S8~hXr{kzvM;?M(WH{C{{K{0bk@g4@jvX7+%B{K-ozOI1i1 Ghx{*hLh2m= literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/basiclogaxis.png b/phpgwapi/js/jquery/jqplot/docs/files/images/basiclogaxis.png new file mode 100644 index 0000000000000000000000000000000000000000..7c169633ac6e387f51c1f88400439b490b45cb23 GIT binary patch literal 19902 zcmYg&byQSQ7cUG$OGpTUlyrl{(2aBm2uLH+-Q6XPbeD8XGt?j{-QC?S9q;;m-+Sw^ z*6;`Ga?d^I?6dbT_MI?gMJWt4A~ZNSI1CwS2^Bav_#EKFg8~Bn5@%RV4hIKfF&7tC zmJt^xS9Y*9F}E^?gL8wgh#$7Z6(#J=R)|GQqSM-xr1*}9Rl-!FT##I6UdC?y>QAq2 z!tlwCcx}3~3y#9ywJ)vV`Y7)MvhYMDuHNs7f`vusj@$0B@FZeu+G_`?^a2Q0ja_^m zjyO(_TKN$qlAUL*Kf=vnn)ZlKhT+mGQHQ8w_ozc%3>t0RPSkSQl#<}j9Z|#G{#wg# z@j;%?IxA`$X;&D3k!5dY79k+X@b;RCiO9sUsi5;RH{sOK+~TUYfV53$hKjzF$g*&u5>;JKqu zFhsJt-F~oa@ynfs@m)Tx-gx^yy&i4@wYHhneW5*z)4l^g9`foqrjWP^(VJt3I-}|^ zobh11`D4E^)Gy$XrhG2Ue&u%l^hGM!PQUg~X*+;f3KlvlE#M z!`;uR80CipXW81gvZ&_rZ>rgUWc12SFXGCqD(UW8eI%F|`i*$E7AFY~ z7wq>9kH3Do2v)D$g;b=j-0%#y@<2qNkwz`zK8X=vzG4yyMaD#DT5{cjJrW-GB!>=` zJe?+0HU?j~+8ur%7)?!DG>+2Bq%GW=`tnC&hW(lvm;SThcVT&@@;-$YT1y~+Q0=6@ zIKsi9Z+xNPvfq8`{={naMA9)_d5>{4-`^qI8<_YZK^f1h}7Q# z6!27jU^5V%-7N_@Je5H$Sb5E=!HnGqxF`p<4)FuW`VHfV_}9+o^+f)=78JS)ha&>w zmV-kaF^PD?5dw~dLwo0g09-%E1dqp)&a5>=2wVW%5aYi$Y~oJmupCJ#&#m-V!C)Z9 zU%vz2qE+ykiZ86F=-SsWTZ&4++4gIAkQEaT2rb_PI@~`g6?MP*`vF6_@Zv1ct`k6|*9HE5Jj>bx!PoHg1<`^lc zo`V}z#SlXrR(zFKyb2_kXrd+|ujuXC;O@>@TjOyS$W%PJleX&o&$@|F4R8~q3U;=} zE%AL}qPOs*A&gX3LqVeH#Q|7)_g!V?eJpYqLZs6Qm9;xuyN1eaa1V6R4C-EgXiyC> zqT6~7-oE@!M`9#D;&PW5Y?|O#{zM5PSiUEwXdScmm1_|{2R%s@w@0PGiuKqW9e&oJ z>VH55mMY$WOEw>YD~DC~i?hqM`CI#}n>EVUD{YA>2deW$mc}FTZv^77b=)84dbn}0 zk2JK^87M|bhQrt962t5fh<((=JAWNCW1}upSy}(nPWNAR#N6-N26N$`2PNAuM%DwnCcE7KI`QpBles{t zV(Ehi$z;yVSorU|@J->R)0NNcGOB2ln5T`4(BxQV8Bxq#UDEMe4%Um|baC&^BA-~N zbF$xg(>@FYNX0)LTnh6$q&2lLeqVc*QvC{YnpRi;9Q*K;dT4-6VPkkxrAbQpK}W<0 zf-0U84TqMoKc~oJVk%zHwF}wWO~#J%{n1))P4c*Bym3VG;6Tp)=>iAyldj;8bgabu z$LFaYWCq8MFn8lcnnDD9U5yJ5t&oqVDX!fc1HVskAswwO0b`w)m(+K6sZX6@nmQ`u zkJp1TL!)hcr-3A?+fOl;-P^%m*p=FA_E-FV1gHv|;(ySM_?sBao9Oh;5eFAMoOpK^ zoQ5K3${KTtFA|OUY+j^@B&}fV?xT6ZI7%&ogDa>O7^ljm|A!U65K50@Z!GgP(>Mz@ z|G-@Kyw>5GaCj9S-n0EhzqkEjHVVG0E}qtcJ_G`SKMLdkN#II;%6>Sx&K&ynRG*1# zIi2Rj^Q=^0z1C&!eNyD^9HiFK5w8yMnG1Q5M+v~CE!6A8^1KMvn9y@Kbj~Lukyoj? zto?8w#OVbM`~>OPBG9{A)NiQ7ybNmLYWA!xGq#%`&NwrQSJjtUgmQnxZKWwIP6{Ye zbLReOla<#!tlePaZHSBO{ioe^kh9IA3yGj|0V)Ijg^km|=X^NB%xX1H^q&0D9Lq{J zdU|Px*Zdi!ki}2!E^kgDz0qpEl_GM4xnxK{Z5Vs3mE*)0iB`&k|1XL#8@KZzqc)^! zdMkCy>x;y0YJc?U*QsF+pRSz>?M53d5}DN`ymn7NQCa=D|Ez+@5!kmKhBkq zVU2w~cpHDeljQt5FDGX##k8RfUyd<9zxv%&!wunko^wns>^vFE`=!_%@=wLzE6MGH z;Mvb_z}LYAFKA-=_lw%6R`Z0o6gZOIf;Y)(e2DL@3-I0YLjAW==92)ee^bZMxwXDuOsBVhEh;L?Zkgro$x+cC_d9Oo`L|Zs6k;^F~#e;oyIUzy`c))IK6rgt*VMGiMp?n?@9FzQ?pqp z5>zBlGK8h1)|xpBh5hXI!>gAN61QA3)kU0;;KA)|gn!H!op;|osfHe`oj;9iqba!J zQ4BER-0vJiKkiBV97T$x*aH`3i|Fl%=N>>}+6ymv*09}*WotMbE*K8By`hQ+RZB@9 zQ9a`c&#pCDk*I;OD8{Z!P+MD5=+-;lauIM^o2$G$jYnR3qtc(Mn<<{ce4UZ5rvA41 z`F;_DLyV?IG=#nC7_%#;dg~^#iX&9R&h1)Mcqn^yirS?Vv)$~+;D;uP5X+hYj?(rS z^V2UFnlqlv$HqL=#|5&``9nWuphR&r@WR#)2R_SO=*EF*ETG9A3|4X%;DhFbO zpkSEJ1gj$@nB>Js!7%}~lCiP0as`=-n)=?IMvUMQJ}SG3SM2LuO5g?0r1IYL*wset zwy$%;O%hL8J~czgTf}M4vQw3Z&0{l*0M844W@Xli8I%$ih3Tk+15fXujvq>ef^E{$ zpP&rAuhA%ktnuxF2s4_Y$L4LxC9S$d&YKZgk55&n1);75QhGnj$`CNEoh@OyoBG9g zL~f6BbuaEZ!lMF)z7?al^hS{%$=A$+c-YWzU$gOqm&%lJvr?)qt-1`l3H~(9!GNMo z*fsdQMy93^f>+%qI4sk?U)9KFH6hZGC-8kic;fIMeWl>5R5)Q)x<5xC zUG7_G17>!l2ppmfSmce@lFOlqI6715k>J6>0nwhGZJrI?T&j%gE5yo`wC5QbD1x3| z%~PN%RQNW8zb$-L+5XY@#@xjD`$;H;-0B(Oy|>EU_%lwSmWJyA%wJZEkrFpKGGC>A zaAS`>AZ;o0LFq51xeD_JCD{=HR+)xVfHyK_-sb}RH0%VmLQAg8I9Y~*WBZUVE?2p4 zcAo^LevUy)6{sW;@%b1k+&`aY=fWMdaX%Kg&V3kek{+%+ekd!5tXKP668LcGu{hR+ z+*g!D?WdqNcmc`aQyu=HVbXqIB)<%~{gu8t&$A7?MyP{3GxBXj^4JS_ZrXn=drN(B z;q7?|%9h)+E=eMr`{4ohsG>^ygyOb%`G1j4g)iRX&j|gPD8jg~jJ9Eo}GE_LQKFNm$@{^@bfErg4QJ1KlcjHV)t6jTHa2u%A^lSSNMW6(VW*(p&-o3}_zCHuUOme8uS z{P-U7V!YTkgaa=oHrv)}EY7ryk}%70@P;t{v9ZGj>^?~fYHx^%WW<{|<-;8&QG{{W zzEJaqq)v^e`(@KzYYYa~8?JxrUkkeJv-XHf)$WUggIHKt2BCM6FBF zlu{R`3n_TOy~+1Cm0n1h;uTnji;*;{4dd|IqLlnNxG`49p6f2Q?ni_p#im@$D|Wha zeJfq^_K;U|O)ze{R~CJf9TVOvk0_MV^XuEW-5%1GF&rubc#vjbEu2$4&3<00(RwGD z@&mhhI3X{N0W$y`jI76V3;}p8p8&`GiB=Z7ixQp+rUlf|a%LjVSE%IvVE{f)rxSe@ z13+<00JZ;WFdJh7P(6(-aK`h%>;eEBFQ;b9hkZh5TaRQ#u=sB5r#8JHXU56W*+ z7#NUdsAV*Io6^+6cpd)k6wONP$(Q6^xU|pI9dI3=wAQ<~+;CNR&BIPyCITWek!8(T zv3=Ny8?3@7nYiD@gb^YEjDm_y2!v!|mmID%AX(O!UrsdYX*PA69lzaz~uLMb?UIug(W5*BC*5H|rXLxodlpt<@5U7M1 zkMEK}cQ^}%xkWV{xr;Y8=H}+B^v{yOytPp4_y-Q}jz2{I{*{jMnMDN*0eWP zRT$({}kN40*rOT1K6nNT$J%aG?0v)z#HoNhx0Y!B_b9@a;<4vM`O+{mP9n ze3YfF?dicm08vJI`eI5RCtE+5d}2V*47^fV%3URGBgi9TJ-6nFk@WKRua{db~-Ks}8tbcwR~1u6sh zXRQ1ChF0Yz9gd}sPF7QbWA-L^Ww|(g-9JAxncs|=6Jqn&>m`|BQQG%b>N<(|JT9K* zU-5l7j>>c)SR|w6C`Frf;B8A(B^D^aD!p#W{PK1DVE84~z(5;&hvbm}I4y_NV{_vR z6)I(bbX0fH`>jZC;#FvN_A1Xuq)3!*KUmm|wVXag0tcXw`}=&O;KP+E_gTo!@iIC} zmBxb`yv+W-3?J(zJ#bpMC1E{bs}(2v>duEH#NQ_7|9r_+77HHKOl&&$=U769v^SCC zg+jJS-)~0aBD@FYst8KZg6DwbM97Z{5STuz-N@LfF4j$Xc3LF^C)h-e7*`C4MOoDT z&r^M-9SkKURMF)2_mh)2Cd>|wukCowO8?AQOoq-h9E1UB;Qh+5J z?b82^t$}UP`{1YJ2?0+FCntAH zh=V$Z?|+hYQdO!*S}~;Y$8b)~ezgwq9R8EC0s_V5 z1Q~H;L(&h49G;P!T-B){o7dyy+E_CAcgf=Uc{A3?b;gbuSzT-=2%)&C(@Dof4W4sk ze7qkaWz#4K1QD_!L_?i>?XPY9cWhss);vfNVq0nO^a!?XN8Tf<6Bk_vgWxGm&sZIQ zlX3z)haSBSj9UEzw!eVRX0R|nkCkEYfywjhR(YRoN_j2BKQJcN zPZ!ruv5}SKk#To|K2ayPFkukk=hq@;gZo*L<(w~QyG+PIpuP)`*k!DrF-o0k&5fe3 zeeMZgImdPhFR>U|2F2CvE0VEk$eGT!^VbvOcB1~o7}Q?KsB;AV#1*b9cl!oE>+q4} zy)y-8q^M9b_utS@?jr%I1S01gfrhA&l10>@xP$(HE5O-~0wdI3R#`Xt2FCxBWD1K?ENjFm#4q7;nq6~`hFt1&q z`-#+O8Kl^)5+D~@kqK(=8>gM^dm>|kZLtj19a=?P`L7@4*7ePjv?Pnt_11G?`|zD| zR0c8NZiRZ!aID5UIRj}!hS7(xX4De_kAQTS!gPEtIp;yF|2?cH)mc|PN8PS{cz|MK zzf3JzT61^sDd;qrj18%D5wY-%=*Lc7?&1i^H69wKKz;L zg`V3~3YQfXuPKb9n=sZ7AN#iXWB{33D!&HP!@VT%Y?YGi4NvEH&?_1gP6YHyb-qb! zw<|ikuFK9MY1jd(AMyE-oG@u~Y*nl{`e%H8uBECj@qSk$6R2nr@eum2dwI+s@OVuW zur+Hc16(jP;o^$pi*aKqY??#wy54lAb|bNhLs4Es-5Djw^{XfTt^ zT6EocW}djK7O_ELI)O&)2j3nlq2>KT^VEQ*d4r;KQX4!TL2|b+uvHK&RhvMVFP{4F zD5#m-F=%pjqOv!Y8E>zdeC^i+4gc~L8W09pD0=VV%V^;$dppX9Ml0`s*mFILh)g|A zA~z9*u0TAMA#~DsJY_Fw>W-kL09*@zFZnyuO?LUh*Sn6-Et)Nx*KDn>Z=c1mBtc_tfMd|q=Iz#xafTuwC-&4#; ztabmL@HSpmPIwoB_vUuU!^|WS7VP5EU9JM>Ut2ho(yNZgGileO`NNMMm2SFp)JG`G zw<5uXt5Ufl&0Q%$A4QtDwu6jQ&U)x@yy;6GEQ*)}NdlBaF}5(>P;`rK-=(1GM{T!O z5F{)hx%pR`e{whr*s5^w|F%jUw`s`@_xc7wV{>euJ5zZ7ym`=iV!G+q0H7ypQn8a# z890De!y<%V?)cGKNk0wr#EavY_L{lC^7xn6{E$ljFjqGK8g+R^_n2M_72LzaQyb^Q z)G%5K`bP257h*5{?kxjlPHkr{n{u&_{v2;)B9T!EqhQO|g%kYA)E6#F?VeXt*wK{8 zZwx*|RznmauD_K~mChXh)>s3ZAQlEPWr`!j!ePVoFOQ(DVL(@7NYp9;nYO+-4f%%? z7390Z&~R>r-qb7&zculjYbvwf%<1mA?%nu)P7ePQo351CH~#``&m2cVLTwnkrbfTd)PSt1AInrKL5vgFH(SglzhmmfAGVe*Ho{v^(T> z*pFRRQ!IuELUaESpNC7b1O-z!rUdTHm`Yj4QRwH@;m8OJp(YAGQu*uU#cBGgR_df1 zx;9-wlLsU;L>pyqqnQcHO7_=m^cEAfSBcS?Y~mlReLS^;;B2I0jvk$^PqQX7 z4vSPY9N3sCv)c~|TK;ZFi3&UsoDl)QOAxeX@pu;8x|tk7sIiI4@rE^>k8CO8!9xiX z?UfqC=QE*KOm@xhiXnc#4Ua{!*1jhrfk#-qoNJVlas4Uwld5jEr9sIfIM`prd!COy z2e*B4L-N#S@%^B|70Vd{8qa^CBT0O*6n%H}#9224f%Wx3mEI;fP4xQoMFYb})NOeQ z<1%R!@4o9orLeF!GKnEkwq6TkSj8+O4>#Z5iw_u18!w(b@2AQv>8h0UMHLwy_WrZR z4a0`f-Q5O!yyHDitKJpHI<1Xt-l5BAVU{m@Tb-hJm2lB1`#%n0K<%F?8TI-S13CA?`mv?2HyMsxfvIu*1U0nije!z zzlg1>E_WQvAn~3%8*XegdA@ci_@wx_ug?4rqVM6-6|*dAxX7~<=|)N24#}cvfgT=2 zm!s^tFlk-de*_3sq3U4K+o>J@$?%A~{jH*4N+bnmfk=rGg5~aAzr^8CXw#S;zYalO zVrFJ0u~U#Xzmsg^w`#9rvGmV(erpv!Q|dW|sIWWIs2ix*XcKHf!OEk#ukTn(dcSP& zBrvr$)BraKJ&V>x4#DC1J8$$Qs9Ok|FU=yw-~^{5BY@!x+7tIQHKl~cVMrY_AD`Ak zefGhUp@u{h# zTSP!vw6@&vCGEl+C^OeT}hx7}#(co2PF~ z8(iu-V}EmIjcz(>pzMFXY|FH1>c|cYpF2~jfac-iY&1Wv_!+8H@SpowSR6D?XPzk< zT;aSQ9qli(C}z3k(cehMj=tx9#pm_S77UxdjSleTY^)C;%a;_&E83xTM_m$~T3TK< zsKYz3ncFwXQ~GUyq3Ck`jruipC~Byj8hvOX-4FBoZE)V_lCarH4%aqW6#csEZLYLW zbL(Q898?AbV5DZE7~M5~;@*$r(@pN-t2r>#87nz`4jym4z4U!s3tMENI%C(?v_2!6 zz_Yv=Yj@j3`N|D6@XrIk$=*O(X_z`H=YW6OKNtS$EmSX2b+)~7)o5(^1*qW z7_VuZW}(QY?bOkY&gQ3N=;^$G|D|hHyYKxV_m`HeGJ9pn4$P$FZM#1zYR226E~;3+ z>DO>EANyDceC(f*5hZQ&tF2_`!eM4+Nn#ZMM)p{;yRV!dz(X9dDrTo>As;Kq7vf8I zZn)0Nlk5C+Bft`#eMlm$gkUeKvH9i}PI-+9jwHVBGsrbRs`~h`BFSUV>2j;dMzeY% z^fcEzb^a#(!e*Gg%hz0>xpF$^N^TeM`xkX1?)yZU8`nG5ME= z^w0ixB@w(G*R$kyM|-;)&P-A%T@M2M_>EG;m`S;np(Q1l4=+=H zmAQ5P6LO}FB17ok+_1I3-)(+;Eh0vjB}9xy4ECeZWcDYrf8)HHY4ix5@9Ii12=+&3!6evFKZAsxqe64<$OF?y%d9mplfL+)AO8>OHY64{d zkf}$G;J>6slMHx9pR>oCW{vQ-8k_5nUt&U*uvlX1IF{Fz?j4LH-u#5ke=Yf%B`=es zu+n~WMey0x)=wYX2Lf@|6YD$1jODHMO1-g8&yod2uO4dn5s(O~%bBOM zdlM8RqYdw08ba);^bd}Y?Z1I#KMppZLxJq{7h^Y|x*6}&+MEubS$Z()mL5Hy=D8qs zk%9X@PDe8%0>NaI3Mtn0O(4PuvlSVQFb)84f1s>8wor+b;AJNm6D$j0@f+|mc#>kY zvwAtO(WSY-zp>)7O*SZJnxwN+S2r-Le2c>ARCmN8kFZKgzKGaE@Pjpc3b_j&53WcL zT}7-&vdZ)NeEGxz!CWj*! zrBge;;`qYk|3&k}DF|^y79De#o5-J|k;TV}MsB9Wo{J@;-DSiZWV&bl)0H(CL9u#r z*sOe*^fg+>{12mma*F@J@JEW4(%5s4tN*}o0<$*K&VRQwQuq=ziH+A}AJAnmqnHyI z*J-wY2Q3@h-zj%lVq>)rdB98A?{yOl*e+;-8(fGWJd*OS^%v`Aij>chp=q8_`>D)W z_bQ{*BhpJ6WvclpRyIM^u(ewtIh)hkOhDD2DgIX3kw0DQ$V2lqe z{-cZzFVsQ^jFnSp_+~ndr7g8z2JCnEu;VyA=W$-#$M%uXtM_^eK=1$*XYq>Y3jvv) zzZXG}m(IzIV?RK;6gKE=)heM86pYP^yVm68w}|_`?-bZe?*s+*05>TpIM1a{8Jfa` z!-njiUg6A;h~|XB-5x;n?x&6XZ`}cw)N&w(0y*?@mA@aDL|?FZ5@`l<@H@zlMS^o? zG2R%IB<9#Nw0$FK&M}W(!vi1Kc*LAdn4kc7(j***wGgbvxhgqoh zgr$z-0C?R|>D_s3$Ti^|5{H5}qG=u6YfL-;-WAf{-Ke#~S2a~$z=+upd z5*bhOU=xwP0Pj}k+X%TT{c`gbIUdaC-!iXNB}qZ99=RoD=q$Z8$F=}FZy20CaX_}j zf7VO#KKO{ZY2jsk=KY#TV>68X#@VSqM-=TdH=*X518>^)73e6i_E-u0pMPq1n5Bz{ zfyxgG7ugPnGtaV9I=+U(h!4!y2*6uItE>7Yyo9NNP~rw9>*oicd*$wZL-H%V;*RT; zebz<3e70QILfFl(SU1GWai-W6C|?(!n)wv%DO+Fa{;NyS!XRq-4Nq8_dxa9@%Htc= z#0(JzT1I`+y9Mvc6Is5t4t-=d!L)5|W0JNGvPkN+XP;a1D_jx(LsNg#88NsJ(T++! z_xum~^r4E79`DIFy~q+DDtqmHg)QkNF6RI;LpqWYK8^x=_SrYB8L%0Dc;I#BfBZmY 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 literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/basicoptions.png b/phpgwapi/js/jquery/jqplot/docs/files/images/basicoptions.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea441c89adac7b20bc38d2a16c7d042791b722c GIT binary patch literal 19864 zcmbrlWmKHO(k%?b;O-jSf;)q2aCdhJ4#C|*aDoJPclY2P9D=*MyThHF_q_Lh|Gyuz z*0YB0hwiSf+PikugexgXA|ntWKtMnsOG}BXKtMp|fo5Zw?k#w&oBJ9*~s@<2INgc!SyUu?R`DIy+y;!mv8&HW9vHWM=1@0a5v1|{9aDk zFHYO}pv0417wjY;7Evq*#Ad=VX%wk`XrK*f{B|>Hw)Z$!%Vkkag1mBukMOv&liTIx ze!uLgtZ$}Sr>`Z+-pMS6f|2GK{3b7Ifvqxy z%ukf4Jmgizk!lw;h)+U3N}pQeQ~ef1Ty#II+$ek4On=f5K3DCZdg~R&5t0s(_60}$ z=;%(;b&6wA0cb;L>Mo^;ao@9B`AuzvF#ijie9M3{zCdnkL)}Q&MwM-nj$_c%=U>J! zwvT%+Hf;g93*EdoZyOK3{%`2x9f0DhsSQEXmYWEXop!;LWvlnlctoXp6#Jw_ud$R0w zWPE0#eI24vb--Pjy8ZwfZwGOUyu(ad$198Cq98E{hr*&DGOW7qcE94C4J3z-mcCsi zRW*lPyE~q+;ZCL|t(ZsaWYQEJ&T0>f&$HfBVSZK@2osW1tQeASqp<;BAb3Y9ZD$Aw zM9hC5NQkryJO~I<2x)NO$;f(TKtak%qSo$%ma%-1ol4tV4Q;3G7Ytp~#{M~4dPE_Gq}&_@D((2Ry0AKc2jmQH@dW^5 z1DG*|qi^>94z!a&QU(x&UO<4ycghJLj;7vBv>!Dh>*NoV8Zn3y5m)~5w#@ob`@68{ z)mri}sQ>E~3wpS^?(=&m^VrOVzqS5fqd2PoFWE3QIypMLOHT?#`|cIisWv#!+pqRf zACd-*>@EuWYyw)-_(X^H)`^ubD8N5>c?dhl3ANXE3-=A^b>C*HTx4K@tw1lZ@j`i?oC)`+|N^X3(o!!+-xj$$~)k2-<<yaxE9K}^gUF;ER4T;&s(^f z;wnnqt+&(IGSrHUoP{)z5zO3aa7Sp+lL~&P(_g0bFukmz-m8^QQiwjqyPNm8&r5LO zyzWimlP9Ex-M(K`$VTiVRCU&|eAL&^8KIH&Ts;Wg8pT^|0th;!J%+@=*CqXHZ8)pS&Wi9QV3-juy%$@s>E7f~R zcluS8bo9I#xBX2~d((Yu_OJVn=qqE3TFNd3L4Je!rJw)qM+60t?*~TkpjIi#kV(QC zE)EYvlvdKxhZ(k=Jz+_iRD=$E=8?Tg3^Fkqk&jbT$KtkMYNY-#+|apy_Tg0-H6yB{ zuI~02yldCBjwT=;;#rZj{k9_kv9dFWy!R+r!unD9iEqhtNR|(EUORONQBBdJGP&Ez z^!;Us5U%v8PeEss^6KP+oeD+)pmiaN@zGyor@g{eX@DoaF|W~n!(4a^Ki&C3K<^l5 z!)^C6POqymL{Hkl<*#TEO|0N$PZPh}n7UHeR6xbryg)3dZuz}@FpXbh6Dw^tI=$I; z=~s_nr^kkFp&a5$Z1X6|N_=i$F&ah}uk&cqcsiFuDm_)a6{=Z*< zPkLgp#q(zH?#jhp`pfx-jTS(TC|M{YfkFV;M?6nqVzth0bdZC3a`z8x@gYCvTdghl z|Isfvtk#*!4jzZNIO>z zcfB6js5d+zay#htxPFe$9@Ziztc-}!zZtuara#(XQ1_|$3&*6Q%=$(&ylmGc6CRDC zI#}W9XG3?BE*S4VQAH-5+O-^8N2`NfPq#xO9o5g_+Iz9~I0@B|MHkOzxRH@n5*{8d z?`82qINTuBgq;|;c~2C)s?ckKGiLrbP0+z!E{a-1tW6r=>GF4^@Oa((sO#^d;ro6x zH@Ab7%P*0N<6m|3=royp+R~e)V*=_`@1L-aqw?=c9d% zmsD&!+||{(ad?=R2@U(H`h-@>_Vje;PobeP(XjsTNNQx;)r|?mY_7-qcZlHw09Ro| z@wt5r874AM8dMD7Ym-$n{7Gb;>Fqr$~4 zuPhYg=AKe)Wk)X~$`z(@_}y=<-*mvIIwZ3f-(8|Ac4@S&!#yTzf}z1foyd1ke2_Yz zeDc%c-g(o?bXHN6{Rhw%kJ7@p_I(PZ`mwk$^e%IKn?9xhW zgbnMhUI`~{5#>-KpYrtGk9g=BJk_=~P{i@M?EbZb^lS>FI-Wc;F^a;R2^ z;aS(lL=iPy{;_U1U)@W{Aj)7MJAqd|>W%vrrncf51vf#fD0S@UmZzJfV+u{!_tl6- zF|(a3TZv7|G#bC_{5_Y@>hmethMDDy8b19u(V>sXf&T6UO3Sy02cjE>q=zTJooqHi zr&YMepDPKMB0I81-G1uS;lFphoy(u;oV*R!%g?eoG{qYZ5VU<+FfoWfeUY@SusVu# z5b#f{^sHrk_r)ceEZAaCX=>dcRH)UWyKrBGp1Gn9y)c3z(m9K@rY%Yc{~)G!bX=an z71@vuQ~I-L#o0}>ue3HJY)!5Q2sHP?h*%-<$!3EPZP9Tf&)y&A^SDx~r< zPPmMd;<4n+!NKwMNWw9tM!SVQ*`89RdOiL|0%na^5&Od9h4O*By7B^D!0xGbrQN!WD&dfi8mT=UY=-1_0aWo zL(T%TY505MiWrTgU+nI9u3lAhwv>?yk}DKJ)9$y%mAvo86j4&nA?Xd7bPNY@oS1W4 zrYr#{(?8w`aQsPTcJGD}X~@?e1r=gjwg72Q?J+m2!fl`eiJS*&~<7-WFAe?W@h2`$ zCj!Ml#C?ZG!%urUQ%q2Pi)GDc{MD6QKc7jlD@kEh`fvV8PpQD)avV1PT|CfqRTWvR zafR%bv{I(JOPv*lSxTd>jhiC1l3TURsvPCJ$4}PZ3X+s0@7o=D>_+$1p*XZr;91bK z2BoVGwl0UX?T>8!E?O=ykMSx=5JVchd{H*cl3o(n@Djk$Zx!@=6%Z4OaW~&#nHjb> z4CBbjy(DFi(Wvzs_0pL9C9P<|lD|mzZKHD68fy*=8;IPUb-p}&fdR3Lx0UG&G&7AN zWpUUb*T2gfuU=5J8E>&Nr)TD(tr;=&!2D12N$rBddjWis- zXVGkubYfigy{SLxa4;D_LMI3NQRCa=~@%;)SNgoDr*?5>f7w?5YZ~LG%y{77z=N>bOZH)@?n3Py*ZBZQB#ItKJ zTEa5I=r9!Zfkg)&mOHvbmm&G#CIR^OU57C?^iFLoRMxJ&Dj3?hPg}siYRh>r0n9Xq z5{ibh=epiTclL82rMho`Q$KHf@T2mf1IM}}(WHe)z7l2s{3!}BkOWhP_NqTqMw9_S z2@!~sviyJ$`J@2^+z48D*kHn5O%XtF;QHkU3Ttk-c>${C)K zt1-C4XK3wpO68Tmk#xPrd||9np;TbE{#&MR478iFtmMOD!(5LlWpVN=K{kg3E!~_~6&Up`uY6#P{E8K4p8dZkgXTnUU>L#@f zeErh1Ej?UON{rN~Hs-&yQb;9EzgJJ8#$@UV zN>cVavh)!N<<>#J-5>0kZQAtn%L5t;z%tKQnx1LCsOa#L2KMKPnSz7;7sCTr@E1a~;U8pDqel@*;$!mnCw zINvYGzH}uvrmRJIac$amdIU-(mAvS?_b9YOgN-^Y1%Y$bxMa(liNc{kiUx#XE9dz6 z<9ov3k<3P6v-tFPcZ1K&+_A!QLFz}5i!?grOgQSRZ;z(zCJhANJT}@wEd;zBwsc>@ z%=SbR0}e;rUrkUw&35K5sLODf$)KOSe==)v>%I&HHT{``r*+Ezj1?6Lj1?w+IFAHfrsfZ-e-c9S!zWYsuCG7picf4?*IUR}5`fnNhrJ_tE515Z%Z^yo7cukp zx+LOHlFGLhN@p%Y6>2wH7S^r`_V4DR}==%=1wa( z6p(DWf))TQV8WEYKXgq*M;`oh1W0!@MidGTUY2r_E&2=RyP;?8OOrgc`E1RX}Q!2>c~0U5cOD6K8J%30VWrT0=9S>Z7`_OKnGfo zLNZf0c3!2;nKj{!<3zlhL8Dyf6#rH*d@U+3kED4LiQbVG$-$TE9)&xUhbdpO;0%Uc zsIN~HfYO)nm6b)Tu(LwF+Jv{xfZa0vE7ctd{~bDHD)Lqb7LBb{+@jt!ef*7E)|gX6w4FpBMuY#CG>B!(?l|n$?pSt>kMy@DVI|;H z?!|_KYc^oaN@ZrTIqGykvx}oqE?{6_PDgr|Ms5v@1 z`ewg$p@>Q;)?3S!X!N8ASge5p%Gm2$e|7i~=k#+-pN*akrl}5AAIdctbCC>9P{3$L zSUQh{8x0#t3?O9$0&Mp8l%OlS3;R6EEw1rUiW3tMj9_j=+wd_HK)1qd@qmr@N~1KV z=KiF>_*G9u%{CT<_KcT<91{wFrBvQ|{NT+EkqU4J3buM7SeN=)teEWSPjx^5U|}yR z%#cK*cPv|T)TIKtfaiz0vd45HJLfU8f2dTZKp-FhQixIF{|yi<<%M>}JB&D<)sol{ zZ+G2>Ah#y+-=J(jg1?M~kW+oDD?-WuMVmbT%2C4m3}73|Hc+!PDRG*RV*&od19%_5 zvx>kxTbvWNIUh6--r1-n4N6@g0ryw!ZD_D-5W#i#b`4c$hUk>3RHT%qjHsy%o@w4}^pxYP-gsRcRZa_bwg`d>JH$>fbR$vnKi&0WyjL z_$j8WzY3{(Lvk>YnP`NGk8lizd(;83l9SEA z(+Io4p)GM*S5f&&gK>!j8NB3?_Zv%R+hXLGa-AdCV2}KsqmY=^8Bl1i5#XRH1fa2& zx%<^)(L^apCCZri>0yN#rmHJw@T$#cikEUz8Bk-@XQ`>EE4P0Mu~ac-Re=dBbD*3r zkqok4J@hcPrDQ3E%P1{xnVE)3Xg*I*g3ClQVD%i$4N%%43fR;Ho9r2Gmpz>eh@q_4 zlIFU-S$|Q-osm1}DfT%xTB;ipNY}_YC(mvC=TDv06$ZMT{9T$;m!3|ElOBNwn8bji zy4!V9x6HYQwb2x_hvVgv`;zR0(oTCp&XgSGrU3x?lf3y|GI)AksdMm`nj4&sC=3T~ zJG>xd>s2(zOAL&ZcHrT#t_3|3ek=Di(_rw83=PT%DyRK*XMc(_B?}&8X6;S+$=(zO zH?xa`R!$H;4$Xbiur5lfXtXm#kRh0qk!I^N7RgC?b!=E6wl9YV*NI2>;SzxD=LeM2 zxWQeR5RuhWQ+njk2A%YKPVZLwrHVv5cL)BP`gm~1mYIvGvz;VK70^)2=WylUvC)Ho z^48Mx#|VUx5(WI-)+W@UgT&~BU_7Y5D0r!!ld(SNw<=v-tt{ zy?AgBtD4#1VB5p_@WFbCL5JrFfxKZ@?YE(urN)j8O?xj>{fhPn!uKzLf37NX!aUc! z1{vL^*b%noiO4bGoe6>v2pBwS+=)r`5r=iYA<+TDbRd|H(>~Ii1^i z{kd@q7z7BJlf1{~l&I3_K?m(KeTplvTjfxcV8FuWmmk?6|1t{Zmz!uH4QMe526FPK zpJB!VAP1s{(cviwf?~egZQ_{`Gii~;)Ns5aX&GazF&%eX5;7bA+b}&QtvHN6y;*~0 zS#niw27*P|d|sV#)qUzRrR|nKS48laiNda< z<2#K9=!&u3yJU{PmKu5{ZFTw0i9t@AJ)Uitu;vF9PJquX`Vu;YEuppNqZHAUt}|>g z8dg7vOGu?trz{RUq_9wn%_%Eo;;lzN4h94y6*a20hBSO$$di8ky7e`lkQrg({eJmW z?yikU*)eL=;3jJL4tdp-&Nn%)E-I_nKzqG^w_+!s$(AZdH>XfSW$)2aKZu-Ca<@7Z z3NP(P+N3z?vS)}THg`7-4Yf+DR9K-hy*08lLsd{#p>i;LRO4}F@)BLK&S-#ViMsU! z-%f5|#@Kz!6g<5Q@B0DU*YkcT-`nd7+`HPJ%ks-e`N|v$k)F_>wP)9DFM^@E_+Zwv2j4`u^!km4zG(spnJ>y5eH)Wpbq9$T#!ygg+p-^6p#6&WB{d zuk+vxyk1dntZWtm-{O6-H#N#2>Br8UevxS~o4b1nAEXGZ#W3QwLvwp!R+_j^1qVHF z-2P9{qs9&V-L!&huh|zHH=ud|1MP7#p(~b*Z@oI@b4iDBX%3JyhUpysYuB_+h>xhQ zHvjXc7Ab%5Nh{FAEw)<+X@2>Q4TL zeGS95O*$2_MT6|b85dD6dpLyFM9DB&6oJE{0d;taYRRIqt5KVOtghj}sNrLJog{{y zH^>9gQ!Qnrf<{}xbjIP*Q-nOMd>f1IRtn0-e;8#Hodq!=^GgB}f&wa6V6fFAhl!Zt z$5GNJn)-W+6)lK4CukzE*+YOo$d!C<@|yCIsU6mE6CpB@1W)@Rp=Voi4WQe90Da;i z1UyG=;VJVT!&0Y^hGGb=hBHKqz$K|hGgd<>BO?Ge^0LkNKgftL0XacP5eb;}uYflQ zDwm`EZ_vLK0TiBTR#4Y>FL$u0?3C~LwGR9s7%B`rkm??S=WyXrcVDkdt3af&7r)5aeZ%-z?o$DO)X8S)36tTuW6oj$MW!El;G z4wb!q3GZq%mmOZ-A{dYZf|Fwd6wx1Fm$gUCzLQam7Bd?CR`uNo555M!xHK7$Js1c> zVN{nU)a8Xj?eO`vV8$HXRyIRXVf`C8(LaCyc9BDFP%62+ow$j?%B`o-CD^04=yQEu7*V|u*0EF#0;FpI`abhmTzj%`wjD1}O# zf&+StC^zYWWxDnTovMfg?$y=?v9z&PQ3;QiyNsdV#Qp~n1FF$MgSOc+WAg*5hfZCN za>QUn#o(M+F!(x#im{2&lJCH$s|(5Kg!n5hR`|1;TF=j$vtixU(>|X6@(!N}hz^{h z0RZ+KRT*e7IR6clJ+kEphE2j4Gy_S1fvm6tTX)(%%elK-m<&GF$UWEN`ac&y{a+U_ z0YJ}D>HmTpd}C6bPUouG@#_EyF{Q>39AI#@!^2-@1q@icAq~EzF{+A_)r%HSyQ*oS z&PakUNgl`l+6osFr0?DNWn*HjTQS4-|9eB+;e5W`akvzZ0OJ=O@65C=+-u^+q6wpr zeo#O%Q#-!j&n+jxIBtXey6*=vi-}qMShqV9`z*+k8ZQXgo&{0yfXL`1n!W+pv;F$R z^bJ%!nJ9}d9PJEGxc(jJA(vCtarJs;!(wLUw7Z%E0ncYNk#JbfLD5i1kgN&zqvNcOLYSB&D z!eb6|7*E^E68U&(a}BQO&9+=oM@)(Vh{+xA_rKUl5~`^sOH$P&H0Q{=#`8HTVU;)$ zdy%keQ?jfB1&uR6@bF=gDe#O=r>yJY9ve4cYF9lrWkR_rw|SjOxRB=13!I~x*`|cd zaj1#^OS#<8gC8aU{O@6aO$cV4au$J&-f`DVUb7dJD-FhB|7-<7F%Si;i)^|{svcF! zln;9~t59G<*LEN$fa#=ID%cnPMY8S}I2J}Hjq;_8f(Uc|mSMs3WZm!ojl%6eg+rAM z)owT&`o|G7(TPipGFzno4T$)^1G=wlEI%ipCq?MuaFS$#4zAOsqU#B^92GFc!0ZT* z89-hBbW?6=EH_pq+V#J^02y?&3_4ZfG!yt0Q#@ht)Bl&}Emu2>-Fou9pGYwd7^qgP z-ah}<^5(xU$bB@LUk5z%vw4orBeN#hNJ_%ufzt;$tiS~BPAhJg?%hf=SMpiKB{B-o zd2*yTMD&c!=)=XLs>GLN*HNDSihL=b<)n+TdL=CQtU+J$3|&G5kRYjN-y00oC0wMg35TC2+bL+t9z;K}y0 z+Id4+aOH5y>Vu_2E~qHzIYxs92Q^9-4S*rHUgw+} zEQh_e8vhA6*~-N{2$);?nNV~w5+_scr|p=_UFHnuTzD+y#^sy$Kit;A?9t|*EQkL` zP=^$eYIo#QM9FhmM@EYWICBXo2ZCeIf1?<{H5f|bPfRJ1s3;tTm`pKB zXJUi4BknfmZ|hQ#G>ww)%5&8=fz}ndSoN0Q1oj~&b}q5NJiZpQ#H!U*+8c`FoOrIi z8zN;!^VpA=5{#I}J{Uoj7T>!)J6Dl|l)T7Da#z!cZHD0|qMN>CZqK$d^M6gFn zKojFDaB%16evhbJwe-55FCk!#E>qays%HMTY7J3pa*^mN?{>V)zrz2!-_Jf~Ft=)v z+7x#!?UCwf*?2KIlqaNqx-ab$B@*BH(eV>4utjlW@i6E;7&Vh3YO@sYpCXwH*0|=u z(o1d17K^6>8z-lXP6pVDxv4K@mVZsblWda`gY8!M5>OwG+7pAiU`~14E+_16kq}BYw$;u}K5@n`*-Lh)Xx2XiyXzJ2Wb)CPisS0uCXc3{2L) zvL7nw3psG=nDklv2n*JxvHxDLDqzKp`WGz9h>+#L|C5KZ_361%;3W^fl|a;TVec+I{3V7aX_pSN@N28sT6@B9)uHAM|GIibV4Ea%Dk z7u+l?X#bYL|G!I^M5}RK0o!0KiAA}F+LjmOR6%lpZ`01AJ_}-I;Nb9NLkGc*zPUAs ze!1&3pg|dWiz$0m-jN7Fq@aLw$21C!l9Cek5l1=!Q^dCD%l%t00JPptxf#+p7M9*y ztA3JG(#OE2$sKz8o6zhy^FtY%&w91Q(b$Y~Qv)zm)(Hs2)M~^1e32LW#ulo}c=_HB zenA%!E3BXlIQTmsjmzdZg^%#CIiZ1hR%M3rj^54>cd|fu8exZJqaWaPgBh?WArbhG z(Jdz@5N%1s>tI#18x3gGaxqO$Gr3-2JAHy=0d+*3rsN8&w}N_f0-d|VxdiKjkLW*) zz#a3DO|^^3=R?A|Bb9B1VcuSsTWjig!x$6IaocFMx()d{{1#kf!W;-oy@UsRxF3xY z%HI_+<+qN0JuaZt$DOO{@+{x_6T&q7O>OCJCzp7P;9jF?jJ`)Hqdd5VLp~#wvN^Mm2s&=$jwJ{_33oTQ zZ%|i0-@zsO|6CXFrXirjyPcfTKvJAiSU?3mO-EM z_WRPPR7HCi?|v!m=+S~Z(QtFN7^RF>;q>gPMg=`<8td0YQ+Kf0iL({GLCJy@m{fKD@pSC4kbZ33G_U4#*fmh}hswng z;Nh5K4?6Lqb*nM}lk!BO^-!RM^rnPvUsYZgr+b4a;i}%#?T{r6EUZi}GRm`DE+mS( z6&}?@oP=aF;pfj$p};}Woc7$~%9++@CV?n)>4=PEUT66FQ}dtQTfL5^#(cLO;B4`x zr(DX22+qgp?6mW5KJ~~~&NR&dhK^+Ih2%3)@S%X03)>$o1mLuH}8M5SJ_pn`V@gJvKBV8Ue49>2(Vt7&QK zHDiHxgMD>;r-&2DooenzAbRa#QcGTnd6k%LiL38Tkut&px(rTmcRjygpCLOZf7Zim zH-4vUO}Sh9ii`4FNqJL3#2HChd1nv;)!_>u7_DSsEs&KQxzarc(N)87w`;;z3BkDm z0F{e~jZ#vM@{I)Mrx4hGt}G)IGj@SYYpp268CCUA^Yn&jTsC(VFT%6Jn>i5(0!WJ? z$NLLVoD<{StUM$%mvhnALRoKNd9-LPi8HwCLcWku=z&)Eo1HzRpbX86_if2&XCY^~ zX-jw?m)gtV2*9D}8JA9%_d>*DP3mUP(omQYZkZ$kI2)!|WK}k#Fsjx5P)mE5Osh6d z>sX}I%8uogC+LYn$+i3%2pcMZltuS#7Ni(ARo)Ze$p zU{7WCM%AxSOD}5Ob9?d7PeonPPdqlj+3C9Ym1jb*u-{y1m+#wWf$?=SZOnSx+-oMs z4WlSHHC3lHfog-mIO~k*uUHWS0E49%uvD*z7LYjd@jOnGt&Yu3pZKyylZgs|{R<<2 zB*%zdyyTsy2BSD5y%Uwlmo-^+)?vI?#7&HibFrAZGWeb0f2!Hr>*WIenfBVa^zLC` zwKl*3jYUVUi}^jL;T)qwrM1hgRs8gt)CuzV0c=n04q4Ikcjs+ZMWs(nKTldyk=(`KMmC$0gjnXmVM@x!#&_680=BrRYx;8Fa|(c|ef`uWl2e zi^T?TV}O+PuUGP*K4oTFK;4BsudCN5i8lVy7N^u=O5VXk&q^*$AfZtztl=%n5YQJb z8=-S`K@DQ!eu0Ri6l#-T7xshcG!F<{&54i4IM)O*e{MTO>piGmH)q^-J<|_L9O<%d zb*yTP&$Q^0;}vR=_lf>J!0R-XJfcuPl-$GFe%?ANz4IK89brV))n*}zYxTd?=sROy zO<4YuHuLV$)$V~v+?B36uVxS941w=#9SX6~bC z<9887W-Ux?BFNEDVO%=zO%8A7&(g)MdKwYOC3Jr#=mL<$sVn_?seT_%wMDzwm)%>i ze?tFHLE5tD7OkMzn=tH#(S?>+s@n#B_5AC)>$R|NInHk-OW+qjAskJ*hvhm-1p*o+ zYP)f1HqnnbC35q9&ObBF2L*ilO3!EGZJIhu;iwbMpuxclaP<{V&#G+v{n*Gm6b0v6 z9xhUw{iIV^I;R8ipGzr9-)r$YdS__Sxn_)Q{$dYJ)u(73IKsyZ06u=%bXf~=j}+p- zJ4_rQNpX9KIBZ+8x(A=$spy`jRrFX|Ag8_Ag9!uWrYi87?jzNE3sez5Ygbn=+3D{m zj@07NqSD%&%xay{oJ_hbgaWMKI>{at6jau?K4uHAc>lm@rqd}hD_-iOsZtX}2@`mL zn*~kQ4*hx(={71dLg{;YE@v4R>{q-FhA!QTN0V6gN}?NLQuD+56{!I(h{K^c+#mzS z_0Oh4bXHa&W=_?&r|zzP0wV!ufY6y!-<)5{J3cvRtcXk)E$cd6C%YSIu9Z_T+{~2E zS3JWidZnvhl3qKIIb*uagOlWG1M8kgyM%7K^!4>g9c9&>P|Gg{5=UsTT8fFmLel5! zlqwo{AGf^}t;yM09QSc}MZA#1}F6-6rxdX5_Kf34ke~-Fb%X8hh zJpF<$Yx~CRljXn1am(_k``aJyK`Kgbpo#*JJrxqswscdpIyi&|#+|J&#Vs00yir75 z%fvauz)W*njTEah8uW06ehaR&;P9_+uae}2x%aH(EGxuqN>AD`rnLy1_6)a|2A!CX zsz>M+7tjdHl?OY-HGNx;Go09!8x{kH}s8yu+I32eONFN6LSo-;&ZOwj=$$UOdB`3!+gX{ zk9KkAb4(@9`##=a>j;l(NCO6`6DofA>jkUXY>HK(^^?r1WhK|r&6a8 z%$tRHb~QcDm!bJk%pDIOFo_WohoJ!90X+eH&?`IJ;ml~@Upj=SWT<%tn2Q><6H4jw zRA8B~&WzhNbT63!oP7FEJ&jqXuRoI-Y!->=5^}T%JaqrQK1!w|ta5#Er4R1i7Z>l- zGQ1CHMNU9i+Z|)DUfpGIzZh+tHled=QSqtYPJgDScFt~)hK_Gxk=N^&)4D=_M$aJ( zJd#EW8obMb<&SkS6ur?qlmgSHSfR^J;WZ-}sAs432jZx86ENjx@8esQg5ZL9g(*1G zFkc#%m8c&+Z-jmh$LO^j2pP{PRdOnfp5wev;G?G}Cnu+*?6>6-Q>2$76yG#(HT}Wz z*&W=T@67Ea=RgS*UY^+K)bTkn0jEm8mf-B{a8jboYo%WS+kF-Tp{15|c`0SIl@^=H zwRwYnDAWdMBr$OXF-|_=U~@7j7A+h=o1Kc9-W4xzyI%_)vk@HH12HSa?6F-DjUy{s z9Pi{>BPcAVR_EQ3sO{Dfp}D-XNOx$?hx6GM1qf^N2cyfBSgyaLLEyKQR0j5tP&L!> zl`^$8K)WDr_s%*Qvzv&jnZ$MYRu0*i>aO}IF1Li?GV64|@iHB_r|A@ne~%f>AH0r@ z|LZXL?d8wKmuNyB`Y4`>f2|fWXRe220^ap?eL2nA3>6Fe4mat9Wig1^tg`6Xv_T=F zhkd!C5o^#pdU%~Lpjprcqi*LuQUUV46-@Qn>3HOserD8y1hWri&65?@%ucUmT4T|d z+FDw>RRB@`0z3LU=>orCcK+a1tBcPF*Wpx!byaW=$pANV)3K|Y)lGdIPlVMKdc8%c zxb#5a6ro8=J`R%`<+SACdY2cIuP@|@cZ(C;Y5UCf zue(~d9QU7PpGwV(R-f$>n~T_SY&Ct7w?A~#J{X3_uGAI^5WuYP5dusNN7s? z@8u3BFZ}O12(RJ_dcUGNKY;s|+QPkEy_)&bHkgOm3252P!EI0t!4@Y~HW$k-o38$; ze>Ntwu?1tBj#TzuOWBRDe#Ulht|NRF5L-7OgSP5JHsQZ!6YuYjW4APTO#Hkv>@N?< z4IbDa?DW}c_SdBG_a8;rOMUAa^?X{h^Y$}4oWl7e*mNCElMFAmQ?$wx_mPa)e23Ob zcj15U<3n>7et==deSh(^8KSUMG=)k}u&4O?Iutz=gIMSbfQ>73FTC*6ts3`k-FE)D zo2Y=rIbnL(!MdgDdJs*$NZf;zP8l$`w2(D>a+_2%pTnZv;B)-?C$)BqwdNDjAN+EA zTDx{Sn}Ju(6+f)|bMK-1&i8RxX`$8keDlU)1h{a6J0*q&5W~lPAM}NfThs4Iyl}HU z=acjFAv_Xahd+ifeW{J-i$kvQZCzcq3UFlMrNbdF6LWYM#jcFPc?$mTG%-Bbqgw=H zgU(3qJMOa}?%w;df*hvh0*AJIhr*8yXd1idOh$0ih|5q(xZCzAV93HI##U#ff~r1m z)~&j-nN6n6{;=_?>@q(=!$Hxj<#sA7L-FH!t8OvOnlUB$=9@-!9ND*UVad4umXdX} z#e>i(yDA)0*st@2KkE#F%IE_3bg}BmO-Np*M`Wwd)~+Huj?c_oK0-M9Y&J zKWjKnH8j{rjN;$=^|qimjvS67ZzfE$O>u%Op;3Cj_`Q>vw2Cqy$A(p<9d88%2bvfQ z%ZXzlts=w6^$Egnj^sA*kZw;d#FW##-%I}~!%my828-vr2H}o6diwLz^V^*Eyafb@l71ix~>|SggIcJ$Bc3 zmz=?5@%lpc6J}u;v6KkET?;*&7cOm?uAQ}hRw-FxxioJ*%@N|owUGjuDU&Z z!5=AT&odGgYu}t4!=#9b8Bo!su>;A-ATRNW2q=R~FB~7AUf!O*`I(>03AUxyJCx$e zrI#Tfs|S$4a;k=wKPGAddF?mKXn75k#R(f(&RQi+gMemhMI65OTSD*Kro1di8#rPP zkiYU$-{+mfa`dAOQeQd~hLPh078iE<9ZZ(#+ZV?;P@>Hd_Q!8dD`TD;j62jhI`s^hh2)}zc z6T)qKk8)K-slK(siOUn<5MeMN>{{dB!q*sj7mksLE(*8(uB9=WOd86rYVkSx(PVJA zAfT>L&4RK*AbfM9kIq07qB4PMO^iY0i0Mh=TN0~Gbg+3uy1mI+y7YC=K9Fua;9Ol{KUwp&x^*| zlqM~!rC5&t2mcmvYEJGD0qz#}3vgJhum?f9Mih&PJShbFM?f(QfyLB!(s?f+JGsPMg{|rp(s4VAI{0 z1!*Oo_KgIME)#Ap&=y97?o;}DpR;|H`-Y!j!yWX9S4r*In3IeA18zDSCqIyM09b1sxUed*|5XL z(9`xbi8fq4r0OMG+71n_@1^had(X%6^!}jl4s7B}y~`F2 z#HrqD@Eql3^;IXoYbD#g)S_@0g2VF|Som=SQ_Gd&DE&6SPJiSJFzqM2%Vz(*lhNg7 zCkS50`$g|)izFr+%0NoX#zC$|hX{#{85}I(4*eZ^R9h$#`}3n2)!@4I;EzQrBn7Mp zi^Yb4#?$&iq(^wgAEw>1cws;f(e4Efl-t8eb4htDwYRZNl4(8%9jk-G$iFkSb@;N| zxGA=o`?WJJW#) zL^J6c$?7hyPeR7~L;XEls=FEfF>P?JVYb=z$Ox4NarV8Wv-WXQ;_UskIP&BZ3{-k1hEi=cy!j@+g|AEZo{0vB4f?U;<^iJayPt;lDlu0ch5P{u<_X8UO z->wdqvSG%ZtI1v0mJ~IH3HvG`00Uk)3y6`62ZW<00l&~9kY(CXq~>+Ao~Gbk!*unO zheh+Vk}$Kf4K4x53A89fbrKRt)uDMt<5%7nU(GqEepKabu0Vxoh+Yq3Gm+8KDp4sl zBQcqT%aX$YU^duc+m3LGDDGRff=@1lt#3qlKO?=F+}K+Ga`rR23|2*U)#`%<58DeMyZ=Q1(6Z_vH-7_C?EbZ^8A2%s+{3qngGrdmYjOa1`_=<$;DquHM~iIqs)d=(sp%W9 z8bmHPTGic1^jiT2HXj%Y*1C{d#&+5}?=M~M-HD1#wF^xn-VcbvQKpK$l5z4qFl-u0~g zuJt~@XVbA9p8pH*#ffU0muI|*nYyt{T|qB15g3{2LonOTh*9$DV(3wy+|`Jw4q=S$ z%@`rsXm$Efnw!b0b*@;37)RNY_5Dt8Ym6eiKEpWaG1`x>x9G2V8T6B{Y1d;qPkOLk z8z{}_8GEEkbdwOh;RkcQc4SRurEE#9_K={4D8oqjRKu|m{t6BH6Z`2dz-X0Kj5%7V zT{sOqZZ9)N4U~OgWq+8(`;N2l0!~`Rl9r0=w7_<*DAB_rvu+CIdLT8SNgWGfVFr&{ z8I{-#z2{Sx&OmEmH}{p^m;TlsRW_0r`eV)%JD>iPIzn*OfC+yDn#_h?=_aj`YSh%# z6COyEFz5>kamKJH5I~%oY|NXO&^Q6*)%p0`+al9VS0(4GHZcL5tZjPW=-{C3;<6RPR znR`Suc!y!X#(t$F)15K1DjSo>AfL|)Exf3&*~`8XHJ?a9TU6b5CjwZ6-neLilBHz$0>&SOOyI`-ERfM-M^qriK6r~aw1Yivh)ZW0#YI_>v^ z<(3(@0L8LXzXagrswTPy3d+S@((f&t9HsS#Gu`}K6f|g1$US-yfSi#nYJJ>pp*zyA z<#w4v#Sm_|mD25%+N=E4y9Do+Q`CTbp4QKiWK=>oLytNOY9p{ktL*8;RN*1u|RBU%Ny&ki`?3e$kCC<#xn9w~NP0 z004O(KO*;6NxPo)y;*V17QPf59+#?(%8+dGA5k6Y(5vmdv-mT~#5^Cp-`;5c-&gfTHxeR;x> z-IvGc(7K4__(SHU9$&yzYO>YOa~eVdXvXK@Ck&OlCfU|8nHVgap#U&|Jlj3}$`~xN zzxO5ZO}U-IWi`pfjX+JDtm{N&yvtr7n<{>TtW$$+#%)#v=~jE@^?1CBt*Ma1U!0eV zjEwXns&IVdea(gHV?yZQ|BLrZf;v{Jd-rzQqQobfoL>$$8fPHz^&7){0M9{+3@}yf zdFq8p(1+m{09~Pz-J)7yQgjWp`-X1zR?m2HQsTv3xl3eiaO4JK?{f6_jzHX7hn(}; zc)o!jKW^p&neIJnomsF}YrA`kYcA%(PLt-WVXLA5BhZCi$wc%)eyinGtdRM5RvwIBN?m7qb-#?2oVVFT z&IfSM4HH}A-wJG#uj7OGqvYc)FkO3k3q9yYfZf*_S$16bOP#GR<;|CNO~g}hugIK= z*d{wR=XbLxhow9W=9opzG9OA!S%6?hsY0^qiAml=K4`yf$dCi5A`XStSDvI4!4;BH z;y=O95-sAom&p^ODtt;gPzFnyDIK!!e!s4ED=Uq^zv7|i9kd=OVtt_RU_pZ#C~kAw z&Oh(bhcWZ*I@4Qt35KJ2?o_ZviXpdL1#9XZO9W~8+989!sxNEB<}i<$x`H~vn(Dh% zrX%wN)THZm{PXJB*Kq+{<-Jr}IM3}LtBd7qI6^6P4K_wSgUYy>I-ky6(QBq#@!M12 zgdF@1%eO|&*Ow=_Zkb&Q=yw&~-2Uw};7*)AT>@>FW%)b%vOA!oRn^Pe)GvV5aBhVVeeWgbR#42)gxi&E;X!3bN-WQU4o+bF?5(@Ile{YLsCiBfZq*RZ=n zeV4!~0p-x`H)h?{{6;rS>61Q zIP$Lh0Umuclrbd>N4o6Jk%^o;izaS^^#^?5lO=aO$;+dlLT9%FVZ0xI!BUea)(&Sn z*yMeHjPgS(HnVKZ7th~{8R7_<4EBZ(f1WWPC=hU$?pV#73>gYIStDe8J#jYk+ep9i z_S6M$GALoo`D3XwmU+NpJy6LaCA|*b@r;x8N^_v-!nNQalSgy0V5Jc#J;H>m0SWWB z_6{ITm1ClUW4G6x21cPD3fb7h>?DRKSAQVCq-1D`Mc!4B7$pjg%W-(UG@q#pC6a1b z5F6@piC{HlccJVED9ID5Wuk^KaGWSL++ULy_=z~Pb48qzDHZ|SGGlGxs3Df&)=pNe zFfNOE12wfm+LZV~KF@1vS~h@adCld|gybDcQFBof>B(Ky%TA#wsl`}Bt53@fIR#u0 zk3zflKc=A!CwvG|sjRxQ<{;|2jQjPvqYa+@QAa6@X5H**Sd!fOLvLjJVQ1zizh@!m zMI!Lr0Z8<+WG$ZpU962Z->;TBDB0ofN&1utt1(awzy0YqT?7c)xZuJ<8=Ofkz91&V~Qj@*E$Y(@9>_C9uNWXc;= zF0>CCQiC~7K`p0u0scWINy7AnF9Cp@K-1h|*Er2TFGPYL%SdSi^V>5P)wkgX)nH~b z;KbTw7oJ+aoqeZ8;7HgsM8r$vKr}m`tBaYzS}P^L_KEn~Zp#ehn?q*luxbMd6fT%= zFww{$`Q0nJPRd90&OgcZzb02-jK|L5j=&*e*? z2;A}FmQrH#{lo#mbRdu%n+QBzw{L<8QA^Qu&uN`+mI)wH+1aMoem zgX})(^q#fLaXQfV~BX0iNE3VPQVM#jkwD(`^ xg7W$JUlD1FscxxC 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 WF>N{^fi7VDA}y{URxM%_^nU;^0A3UT literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/logo.jpg b/phpgwapi/js/jquery/jqplot/docs/files/images/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a12fffcd5e43de9e69d5b2e42842837972123577 GIT binary patch literal 14632 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 literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/navdocs.png b/phpgwapi/js/jquery/jqplot/docs/files/images/navdocs.png new file mode 100644 index 0000000000000000000000000000000000000000..318ab04ebf00b044ce63572fada1b32f4eb2f58f GIT binary patch literal 996 zcmVPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RU1_1*t5+BUqd;kCdB6LMqbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;8|jZXjVGO<`k)sCPpE00T%#L_t(o!|m2vh*nh; z2k_tIl!js1OK2rT=mcpmcA@AZQLT!eiXt*HgGlnFY-)n&Ay$K=-9(qqnp9cnE}I>?+=G{&VR4H&RTozwf3fsHri;TjiJ#o z(g~%MgM+Aj*oGxo6cGnUYV-fX3CF<3NtldHlaZf#= z%G?Fmg;Q}S9zj2*M#Q(rJ1{bHxs?`UlqLgj<7dn&rA%uvcV|TW7!m6tq6hD$y;;XQ zr~!0V?{DEr+@#6eOZnZ4>xW_M9o&v9YqFFwDHkp@nJsuQB6bYYyCn6d<9ED*`2#gv zN*Rym)4y@pjD-=gtd&EDYAz!7WB7=d%GE;#mv}h?nw~4YJo(;I%23Vcuau`%TsJ0R zD=xiGFKISDqFZ%)9m~vJw;4<{#npO^V4*KrPN3Qfg`F?UPME_BO zJ2*(nj6ruqtjR2OVfL`(O8@RJ)mh`V{(zc#$3#eh&{s%?mkWT zTb~a6ko?0Dv44onjZ3+!;?7O^WyO7wa!SRWm2&d{5fRS}vj4QE=I+gBE0&Z}o{NZm zM{?-URx72P=hH+Q*m1~HFP1iCwEcGO_koZT%0cK$i@Cpa~$<(`oP6F53_U5 z&3I4Kpk_M)I@3^xCR+zm&csB#9uaF>1T&$OGDcGe*I|yP-rlHmKFHt}l~R7q@!lL; zS?PV8!ObtF{DP}A4dlPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RU1_1*#Hlfs<^Z)<=B6LMqbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;8|jZXjVGO<`k)sCPpE00UA;NK{tzR1|^HW)Mlfl(V%#5X5E|b)q1sFtt0;zC}R= zDG@#tfstYss97x*(ZzDYalQ2LJ8Q$A{kOZYu`mBG3}@#2&N*`~zjJ;+I_RK-4mubc zT@zKP%Is(h>mc@EE!N~keRQHW|1TUj2{ul^e5}ILQyowfT~L)-7q(#m7UEK@!-l-5 z?`|qIDt7_);bh!_hj0Yv=SBVXR0l>>F1FG$m?l-=P5gx3s>~L)(cPOD_4j#EZ_SIk zA8&`f-l-011k)SuZ{TsR@o%&N@hMdB7qmHiM8|@;nc0zSe04ckn6_BxC|L)<1zF#?7xgVacUH00oGMzcJ-LS1zw1NdLq*sg1@>d zv$2NHpFvM)@cJ+hyKyJMxE{l}rkz96TfT?m z5t**y{lrMbk^czpXbTk;gTB0|H%FEFFo@f*GS(LbeIzgH?bu$GS%xj~-^0@Inh{C* z63ekXFX{v14enlP`fUpbz6<_?c~Ku4qjEEY?rZSQ3Ho`1_gT>H2Jg(EJ4YCKQ9spU z|4FIm?ulnN)>dU!=0$yQG>49DwW`dH_wQEe3j;H;DKF}Gjg66B`=-Gg9*15N)7mZM zMg5#qwb$`G&cYLTshv)Mn*+Y`xI zfT2kC`_ggLFU^6AaW0mI&dqp78c<7(g6UzXORCo4pi3|ZujEC&rA;uit1_D*^}%&m zCiUBE4Vm{MxHVOo{Sxb|V{Nb@_fZ5lP?g!wxJnuze}vuBu~E8o%)zUe8@hG7Y){7B zvWZo3ppVF&CJlwTEpp$YCok&#A$K;uk|t&okLE=^5HcHZ*C_ui^P=t>g+D2G%LCYo z`|xmcAusA*r9K(NU)V3*WEPDC7IM3!ZT*FG5#KAFb1NI>mPvQlAsoUF7-;=x2OV_K cK?f7XKL>mBqVIr&G5`Po07*qoM6N<$f?Ma)NB{r; literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/navdownload.png b/phpgwapi/js/jquery/jqplot/docs/files/images/navdownload.png new file mode 100644 index 0000000000000000000000000000000000000000..41723e77d18ea25299c4d8cebce3fea7c5adff63 GIT binary patch literal 1236 zcmV;_1S|WAP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RU1_1*M1rUI6SO5S3B6LMqbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;8|jZXjVGO<`k)sCPpE00cNmL_t(&-tCxsh*eb- z#(y)8qCI?|1{Mf5=u|dEY7fK0Khn=2ijpFlN(rryq{Qg~7DEt8&h)^F0*UEeI7FoW z(Sp)SEozd19G}JHNTT3KSyQCe-2T|>bT_wq=bnpGV{ksWeCMpa_TFoK`*|*8$dDmJ zh71`p3?!;5tzc%k0@HDz8(0IhNXk{(=0GEgalE9S!S1hm0QwjPOa@i~PyO2o{U1>S zU}jZ7Cr}5}12chFfL2L&m8g3Wa1+LNV?4(XL)I`s30#5+f5oYoW{@x7COVQTbz^%a5vC+&X z5(ZE}A7H>TNe8@q8!!zxPtqPUyB_!e*ePkM`@9C+3ETm^0UQCY1X_VhfGt3Sq{F3x zD;G!Pw}`MRCjq|!9|KDy9g2LG0!@UKys(@wfA7hXj=8V^Ex^m(iOg(H3Xyj^PmY2a z18fH717`puft!JiW_G%}edc_H^9<)YGds$}%5xBqy zuOg98_z%K}|LV^pD1Q^l6)=RE1JEdGtE4TSaGcO)uanH=>4brXu#F_M_|t;^R!Hgu zp7-~0{lu0g4kRrGCIBmZ5W2l+RMgg`&P{&6KUS&8_jrSyKpSwc+aHwlN13)pIvVUI=wJ!WL!j@1>VKYLU%sDEXz+2rPEtHc47nt|9V!@t(+bB1Jt2TSg7}LH!8$j{axzG3UM%?Wc;v z%pL{a0nP`W1#T$fmaNpOg7=b$N526$hj5^50`B(&mZuczTIa2it;=~vWJ{LY?#Pzx z%L|>i0qww4_wSapFJ&CXkT#C{l3XM`PFP`uIOsgdxvpI2@yAFb@TYSFa5nI&q>d7G zCz#oAU^pygg}7pld~4tsgCm$elUc{K0~VKuY^w*f=>=Pa%iY2!!^?VHSO zJ+Lwk+?w85yJJSjW9!d315b@CG{4xlg#F?ojV9C>!d}lAdW?Zt@60%G>`lN yd6~EMIdC`7L)eDqyU-ajWXO;qLxv3h5&i<_Ibnja1JdOH0000Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RU1_1*$DF^Yw!Tvup^e`z3C9U-lRC*v zo=q5N2-`?9i$5#qZ;dv-3wTc6Ckzl_sCQP?0p|kmi14!rTS76B4+{TO zB9|CtfE6O#7H#~dat)E+i}y#iQz_~} z*fMI!59%kt_Y6Ffy>Neu_EW{-ta=o98<-9}1Ke1|Em^5m1@9#hkA5R?KH)&w0^BbN zn3O_YC%hxFbqmjlY{_!l7uk}1d71D|paYmG{yp0GgDK-EhO}|qm*k?2f1I$w3UNeu zif~=I&f|}fCg4xuM&LZ)6>WTHiMo@VRU?6sz(T?-%mJ@OJ|BuutWKVLSL9T2NIwfj z+_i)QxQ}oN7)RKr*AouQ24D~Hv)IR%>U=Q%yZ9a0MY!5L5*KLWj}xvx?SvWHNBAkHs+pqH=>Ef%3OWXO;qLxv0) b{v-Sa+D>Gw2rhzl00000NkvXXu0mjfPwqB$ literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/navexamples.png b/phpgwapi/js/jquery/jqplot/docs/files/images/navexamples.png new file mode 100644 index 0000000000000000000000000000000000000000..89d1fb4e2ff9113a1eb475fa6f9b2be803c63d71 GIT binary patch literal 1308 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 literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/navhomeover.png b/phpgwapi/js/jquery/jqplot/docs/files/images/navhomeover.png new file mode 100644 index 0000000000000000000000000000000000000000..63bbf7a3117740c50543c04bab97758e3fd36428 GIT binary patch literal 886 zcmV-+1Bv{JP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RU1_1*zFO%hyvH$=8B6LMqbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;8|jZXjVGO<`k)sCPpE00P=cL_t(o!|m2zsAf|b z$MMfQ^J-&Fq)f`xP-=8!#^g_8C>I)%+$hB)C35HAI#T3{8;(5}$iHH0qSWL@b3qfM zj55lfFqm`UZzF0%&DmH6$HiXnoMk(2(|PBN;Ke2471^k!vp{c7LKEat-i;M6awuG2&UTTqx#WDyn&0;f_ z;}N`w?{QO8S8JDA5YxUQW)?r- zay*Omcnde;96W~A*p6F5Ob3dw8?w#`?8V(7rq_q*>2<{2pA&p93;YJhV`GSEMLh%ag_ca?+z?Y!%r}DurxbC!bF#-4zRe+~SQK&(Ruu1l!}<`@ z-uaU4E>KV57o3-q-ID!NOLm;eqVC5O3ft zJd=IpKkS}7?&TcwcrHvF_GP;X9L(21K$Gu}v+$Ms+CkDGrnf^(yK({Gx_RR74KaPJ zZKnbEg_u6W^ZEJY;@!qb~Y1?65`km+7aH4i)-iEIRRSYrx(TN?l&ki^v+jk4! z?rhi0qh;`0P2ro)cF?EGi+87GyQ4GD=}ler=g~X&wVJv*#@yd)61U<6>Z zz=PP=)YUt~2J|^}s5rau?=iO$kIEEo(Dv@G!auFuJCBqpT#sw=HQ>o%1CH9+IK=d$ zcFWnOU0`PL5-tld%`C$FpW-UKkKeW1-|Zo$tw$@TF=NJz8M7Gt4at$yD`MIj6#xJL M07*qoM6N<$f*-1`IsgCw literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/new.png b/phpgwapi/js/jquery/jqplot/docs/files/images/new.png new file mode 100644 index 0000000000000000000000000000000000000000..3eaba9c8c9348d6338104594c1ce868ec55927af GIT binary patch literal 13750 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 D%-5D` literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/images/sample3.png b/phpgwapi/js/jquery/jqplot/docs/files/images/sample3.png new file mode 100644 index 0000000000000000000000000000000000000000..31e644dee30bac2d44714045568a69dffb864757 GIT binary patch literal 44781 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ⅈc%nA3!N6+cGq^I^Z4*))9-AYPPl$g}JkH77g9-<)lJ zkiYsJDtQgH<>FNHqcF**6CpehP_=jJDX&t8X@o38}x{d8^i0eRsXHa1Ns=I+-riV;$RCb*7Bv z)}V!0V8GErGP@9eEhTzz@ay$RSgcE2=Kdo!nabQiwIs{jYn9Z=^!0GD$@_a7OM6_0 zv_jS6FaB@dPL?rR|GT&(*6qH#_K9fZV*Iv2GbIQuS~c*5h?SX@db5$DNh2=6X*XRy zhOKE)ls6^Xc^9HB5+c+QyUPvvk>hpT!zRCw*>1$;59}t8p|`d8`)6HFKl6C-TyT z=4z$8nQH<)?W_w0icggckub49A1VL!hdY|iD1VfqrT8Yi`X2fe))K4wHQcTAf+=>$ z8e|_L?mx`0K#(@J39+BAIOno|oisU^xp%)W8Z6XJaTaq*A}D1$;9}a#hs`VM$3mxf zy`k8JvBp#SojfR>ocvIz;0#yW8vLh-NrHHr#jba9Ii^XP-2sEGX_sf()0b#Jh3X_a z#j=O&yl|l<`8k9_2iq#{f>tZM(sze%ZwIN#n2k#AQE`C{zDfDnomGv4HQmT;qUeF9 z4&$9$uL^w$=e>UojK?K0Hph%3F#GQgJ}#+_r-XBQ9BlC%Py}(SGX@F-p}I zCc`k|c%T~$W4A$Y_)7$=f0@2?I*O*;5hQMD908kdI}fa?ts2&cpzUg7iB7luwLQ_$ zV_Ax@`CWS#_c8W%-1 z#f`7)Gz~Xq%(B39@9{Um6*xoGG(Ytbd~VZkX~T|twYPMWYA_^cWwzx|NdqT}wf#>? zN%d#ENZZq{MGg+cNMrYa>VigRV-uf=i^=kh|59nijP_v)%hmsro zPp5oZ6cDvR45I_@M2<7cZTW*<8Vn~5+uMfLcdNMR8= z!fX1Zzh4^1^gVZ)o=6xAKpzO2pK}rSewqJ^v`rqXv-l~bq!D9GNUsx7jdm|yD4s5I zl5LT$i4zo7f4b$Mef5ak4n-LaPUU2dc@~pMp8L{s>}6EpBjZjeD$iO5I@43)Q=PgE z9vz4?qQDU9G4|wgoBSDYQFGjCpSKcK;-uxPIiH8JBmPChhkbPx#h26uz#s?uyY5#?CQT>EZuG36OXS2#=HnLVAci5bMpHYvKoiQ*nll z+A7)Vy$+lTCK5n0x#O`?SsKu#7C>!L1VpQE059tRgyFYS*Yz#w051e^?Wk?k6#`B- ztyDU|t9-J}l}_J?2K;si|K+p5_b>2ak567*E6;a!fc*v-iwuU>jrEFk9A5kjfgPYY literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqPlotCssStyling-txt.html b/phpgwapi/js/jquery/jqplot/docs/files/jqPlotCssStyling-txt.html new file mode 100644 index 0000000000..dbed258640 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqPlotCssStyling-txt.html @@ -0,0 +1,39 @@ + + +jqPlot CSS Customization + + + + + + + + + +

    Much of the styling of jqPlot is done by css.  The jqPlot css file is, unremarkably, jquery.jqplot.css and resides in the same directory as jqPlot itself.

    There exist some styling related javascript properties on the plot objects themselves (like fontStyle, fontSize, etc.).  These can be set with the options object at plot creation.  Generally, setting these options is NOT the preferred way to customize the look of the plot.  Use the css file instead.  These options are deprecated and may disappear.  The exceptions are certain background and color options which control attributes of something renderered on a canvas.  This would be line color, grid background, etc.  These must be set by the options object.  For a list of available options, see jqPlot Options.

    Objects in the plot that can be customized by css are given a css class like “.jqplot-*”.  For example, the plot title will have a “.jqplot-title” class, the axes “.jqplot-axis”, etc.

    Currently assigned classes in jqPlot are as follows:

    .jqplot-targetStyles for the plot target div.  These will be cascaded down to all plot elements according to css rules.
    .jqplot-axisStyles for all axes
    .jqplot-xaxisStyles applied to the primary x axis only.
    .jqplot-yaxisStyles applied to the primary y axis only.
    .jqplot-x2axis, .jqplot-x3axis, ...Styles applied to the 2nd, 3rd, etc. x axis only.
    .jqplot-y2axis, .jqplot-y3axis, ...Styles applied to the 2nd, 3rd, etc.y axis only.
    .jqplot-axis-tickStyles applied to all axis ticks
    .jqplot-xaxis-tickStyles applied to primary x axis ticks only.
    .jqplot-x2axis-tickStyles applied to secondary x axis ticks only.
    .jqplot-yaxis-tickStyles applied to primary y axis ticks only.
    .jqplot-y2axis-tickStyles applied to secondary y axis ticks only.
    table.jqplot-table-legendStyles applied to the legend box table.
    .jqplot-titleStyles applied to the title.
    .jqplot-cursor-tooltipStyles applied to the cursor tooltip
    .jqplot-highlighter-tooltipStyles applied to the highlighter tooltip.
    div.jqplot-table-legend-swatchthe div element used for the colored swatch on the legend.

    Note that axes will be assigned 2 classes like: class=”.jqplot-axis .jqplot-xaxis”.

    + +
    + + + + + + + + + + +
    This document is out of date.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqPlotOptions-txt.html b/phpgwapi/js/jquery/jqplot/docs/files/jqPlotOptions-txt.html new file mode 100644 index 0000000000..c94773ca84 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqPlotOptions-txt.html @@ -0,0 +1,292 @@ + + +jqPlot Options + + + + + + + + + +

    This document is out of date.  While the options described here should still be relavent and valid, it has not been updated for many new options.  Sorry for this inconvenience.

    This document describes the options available to jqPlot.  These are set with the third argument to the $.jqplot(‘target’, data, options) function.  Options are using the following convention:

    property: default, // notes

    This document is not complete!  Not all options are shown!  Also, Options marked with * in the notes are post 0.7.1 additions.  They will be available in the next release.  Further information about the options can be found in the online API documentation.  For details on how the options relate to the API documentation, see the Options Tutorial in the optionsTutorial.txt file.

    options =
    +{
    +    seriesColors: [ "#4bb2c5", "#c5b47f", "#EAA228", "#579575", "#839557", "#958c12",
    +        "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc"],  // colors that will
    +         // be assigned to the series.  If there are more series than colors, colors
    +         // will wrap around and start at the beginning again.
    +
    +    stackSeries: false, // if true, will create a stack plot.
    +                        // Currently supported by line and bar graphs.
    +
    +    title: '',      // Title for the plot.  Can also be specified as an object like:
    +
    +    title: {
    +        text: '',   // title for the plot,
    +        show: true,
    +    },
    +
    +    axesDefaults: {
    +        show: false,    // wether or not to renderer the axis.  Determined automatically.
    +        min: null,      // minimum numerical value of the axis.  Determined automatically.
    +        max: null,      // maximum numverical value of the axis.  Determined automatically.
    +        pad: 1.2,       // a factor multiplied by the data range on the axis to give the
    +                        // axis range so that data points don't fall on the edges of the axis.
    +        ticks: [],      // a 1D [val1, val2, ...], or 2D [[val, label], [val, label], ...]
    +                        // array of ticks to use.  Computed automatically.
    +        numberTicks: undefined,
    +        renderer: $.jqplot.LinearAxisRenderer,  // renderer to use to draw the axis,
    +        rendererOptions: {},    // options to pass to the renderer.  LinearAxisRenderer
    +                                // has no options,
    +        tickOptions: {
    +            mark: 'outside',    // Where to put the tick mark on the axis
    +                                // 'outside', 'inside' or 'cross',
    +            showMark: true,
    +            showGridline: true, // wether to draw a gridline (across the whole grid) at this tick,
    +            markSize: 4,        // length the tick will extend beyond the grid in pixels.  For
    +                                // 'cross', length will be added above and below the grid boundary,
    +            show: true,         // wether to show the tick (mark and label),
    +            showLabel: true,    // wether to show the text label at the tick,
    +            formatString: '',   // format string to use with the axis tick formatter
    +        }
    +        showTicks: true,        // wether or not to show the tick labels,
    +        showTickMarks: true,    // wether or not to show the tick marks
    +    },
    +
    +    axes: {
    +        xaxis: {
    +            // same options as axesDefaults
    +        },
    +        yaxis: {
    +            // same options as axesDefaults
    +        },
    +        x2axis: {
    +            // same options as axesDefaults
    +        },
    +        y2axis: {
    +            // same options as axesDefaults
    +        }
    +    },
    +
    +    seriesDefaults: {
    +        show: true,     // wether to render the series.
    +        xaxis: 'xaxis', // either 'xaxis' or 'x2axis'.
    +        yaxis: 'yaxis', // either 'yaxis' or 'y2axis'.
    +        label: '',      // label to use in the legend for this line.
    +        color: '',      // CSS color spec to use for the line.  Determined automatically.
    +        lineWidth: 2.5, // Width of the line in pixels.
    +        shadow: true,   // show shadow or not.
    +        shadowAngle: 45,    // angle (degrees) of the shadow, clockwise from x axis.
    +        shadowOffset: 1.25, // offset from the line of the shadow.
    +        shadowDepth: 3,     // Number of strokes to make when drawing shadow.  Each
    +                            // stroke offset by shadowOffset from the last.
    +        shadowAlpha: 0.1,   // Opacity of the shadow.
    +        showLine: true,     // whether to render the line segments or not.
    +        showMarker: true,   // render the data point markers or not.
    +        fill: false,        // fill under the line,
    +        fillAndStroke: false,       // *stroke a line at top of fill area.
    +        fillColor: undefined,       // *custom fill color for filled lines (default is line color).
    +        fillAlpha: undefined,       // *custom alpha to apply to fillColor.
    +        renderer: $.jqplot.LineRenderer],    // renderer used to draw the series.
    +        rendererOptions: {}, // options passed to the renderer.  LineRenderer has no options.
    +        markerRenderer: $.jqplot.MarkerRenderer,    // renderer to use to draw the data
    +                                                    // point markers.
    +        markerOptions: {
    +            show: true,             // wether to show data point markers.
    +            style: 'filledCircle',  // circle, diamond, square, filledCircle.
    +                                    // filledDiamond or filledSquare.
    +            lineWidth: 2,       // width of the stroke drawing the marker.
    +            size: 9,            // size (diameter, edge length, etc.) of the marker.
    +            color: '#666666'    // color of marker, set to color of line by default.
    +            shadow: true,       // wether to draw shadow on marker or not.
    +            shadowAngle: 45,    // angle of the shadow.  Clockwise from x axis.
    +            shadowOffset: 1,    // offset from the line of the shadow,
    +            shadowDepth: 3,     // Number of strokes to make when drawing shadow.  Each stroke
    +                                // offset by shadowOffset from the last.
    +            shadowAlpha: 0.07   // Opacity of the shadow
    +        }
    +    },
    +
    +    series:[
    +        {Each series has same options as seriesDefaults},
    +        {You can override each series individually here}
    +    ],
    +
    +    legend: {
    +        show: false,
    +        location: 'ne',     // compass direction, nw, n, ne, e, se, s, sw, w.
    +        xoffset: 12,        // pixel offset of the legend box from the x (or x2) axis.
    +        yoffset: 12,        // pixel offset of the legend box from the y (or y2) axis.
    +    },
    +
    +    grid: {
    +        drawGridLines: true,        // wether to draw lines across the grid or not.
    +        gridLineColor: '#cccccc'    // *Color of the grid lines.
    +        background: '#fffdf6',      // CSS color spec for background color of grid.
    +        borderColor: '#999999',     // CSS color spec for border around grid.
    +        borderWidth: 2.0,           // pixel width of border around grid.
    +        shadow: true,               // draw a shadow for grid.
    +        shadowAngle: 45,            // angle of the shadow.  Clockwise from x axis.
    +        shadowOffset: 1.5,          // offset from the line of the shadow.
    +        shadowWidth: 3,             // width of the stroke for the shadow.
    +        shadowDepth: 3,             // Number of strokes to make when drawing shadow.
    +                                    // Each stroke offset by shadowOffset from the last.
    +        shadowAlpha: 0.07           // Opacity of the shadow
    +        renderer: $.jqplot.CanvasGridRenderer,  // renderer to use to draw the grid.
    +        rendererOptions: {}         // options to pass to the renderer.  Note, the default
    +                                    // CanvasGridRenderer takes no additional options.
    +    },
    +
    +    // Plugin and renderer options.
    +
    +    // BarRenderer.
    +    // With BarRenderer, you can specify additional options in the rendererOptions object
    +    // on the series or on the seriesDefaults object.  Note, some options are respecified
    +    // (like shadowDepth) to override lineRenderer defaults from which BarRenderer inherits.
    +
    +    seriesDefaults: {
    +        rendererOptions: {
    +            barPadding: 8,      // number of pixels between adjacent bars in the same
    +                                // group (same category or bin).
    +            barMargin: 10,      // number of pixels between adjacent groups of bars.
    +            barDirection: 'vertical', // vertical or horizontal.
    +            barWidth: null,     // width of the bars.  null to calculate automatically.
    +            shadowOffset: 2,    // offset from the bar edge to stroke the shadow.
    +            shadowDepth: 5,     // nuber of strokes to make for the shadow.
    +            shadowAlpha: 0.8,   // transparency of the shadow.
    +        }
    +    },
    +
    +    // Cursor
    +    // Options are passed to the cursor plugin through the "cursor" object at the top
    +    // level of the options object.
    +
    +    cursor: {
    +        style: 'crosshair',     // A CSS spec for the cursor type to change the
    +                                // cursor to when over plot.
    +        show: true,
    +        showTooltip: true,      // show a tooltip showing cursor position.
    +        followMouse: false,     // wether tooltip should follow the mouse or be stationary.
    +        tooltipLocation: 'se',  // location of the tooltip either relative to the mouse
    +                                // (followMouse=true) or relative to the plot.  One of
    +                                // the compass directions, n, ne, e, se, etc.
    +        tooltipOffset: 6,       // pixel offset of the tooltip from the mouse or the axes.
    +        showTooltipGridPosition: false,     // show the grid pixel coordinates of the mouse
    +                                            // in the tooltip.
    +        showTooltipUnitPosition: true,      // show the coordinates in data units of the mouse
    +                                            // in the tooltip.
    +        tooltipFormatString: '%.4P',    // sprintf style format string for tooltip values.
    +        useAxesFormatters: true,        // wether to use the same formatter and formatStrings
    +                                        // as used by the axes, or to use the formatString
    +                                        // specified on the cursor with sprintf.
    +        tooltipAxesGroups: [],  // show only specified axes groups in tooltip.  Would specify like:
    +                                // [['xaxis', 'yaxis'], ['xaxis', 'y2axis']].  By default, all axes
    +                                // combinations with for the series in the plot are shown.
    +
    +    },
    +
    +    // Dragable
    +    // Dragable options are specified with the "dragable" object at the top level
    +    // of the options object.
    +
    +    dragable: {
    +        color: undefined,       // custom color to use for the dragged point and dragged line
    +                                // section. default will use a transparent variant of the line color.
    +        constrainTo: 'none',    // Constrain dragging motion to an axis: 'x', 'y', or 'none'.
    +    },
    +
    +    // Highlighter
    +    // Highlighter options are specified with the "highlighter" object at the top level
    +    // of the options object.
    +
    +    highlighter: {
    +        lineWidthAdjust: 2.5,   // pixels to add to the size line stroking the data point marker
    +                                // when showing highlight.  Only affects non filled data point markers.
    +        sizeAdjust: 5,          // pixels to add to the size of filled markers when drawing highlight.
    +        showTooltip: true,      // show a tooltip with data point values.
    +        tooltipLocation: 'nw',  // location of tooltip: n, ne, e, se, s, sw, w, nw.
    +        fadeTooltip: true,      // use fade effect to show/hide tooltip.
    +        tooltipFadeSpeed: "fast"// slow, def, fast, or a number of milliseconds.
    +        tooltipOffset: 2,       // pixel offset of tooltip from the highlight.
    +        tooltipAxes: 'both',    // which axis values to display in the tooltip, x, y or both.
    +        tooltipSeparator: ', '  // separator between values in the tooltip.
    +        useAxesFormatters: true // use the same format string and formatters as used in the axes to
    +                                // display values in the tooltip.
    +        tooltipFormatString: '%.5P' // sprintf format string for the tooltip.  only used if
    +                                    // useAxesFormatters is false.  Will use sprintf formatter with
    +                                    // this string, not the axes formatters.
    +    },
    +
    +    // LogAxisRenderer
    +    // LogAxisRenderer add 2 options to the axes object.  These options are specified directly on
    +    // the axes or axesDefaults object.
    +
    +    axesDefaults: {
    +        base: 10,                   // the logarithmic base.
    +        tickDistribution: 'even',   // 'even' or 'power'.  'even' will produce with even visiual (pixel)
    +                                    // spacing on the axis.  'power' will produce ticks spaced by
    +                                    // increasing powers of the log base.
    +    },
    +
    +    // PieRenderer
    +    // PieRenderer accepts options from the rendererOptions object of the series or seriesDefaults object.
    +
    +    seriesDefaults: {
    +        rendererOptions: {
    +            diameter: undefined, // diameter of pie, auto computed by default.
    +            padding: 20,        // padding between pie and neighboring legend or plot margin.
    +            sliceMargin: 0,     // gap between slices.
    +            fill: true,         // render solid (filled) slices.
    +            shadowOffset: 2,    // offset of the shadow from the chart.
    +            shadowDepth: 5,     // Number of strokes to make when drawing shadow.  Each stroke
    +                                // offset by shadowOffset from the last.
    +            shadowAlpha: 0.07   // Opacity of the shadow
    +        }
    +    },
    +
    +    // Trendline
    +    // Trendline takes options on the trendline object of the series or seriesDefaults object.
    +
    +    seriesDefaults: {
    +        trendline: {
    +            show: true,         // show the trend line
    +            color: '#666666',   // CSS color spec for the trend line.
    +            label: '',          // label for the trend line.
    +            type: 'linear',     // 'linear', 'exponential' or 'exp'
    +            shadow: true,       // show the trend line shadow.
    +            lineWidth: 1.5,     // width of the trend line.
    +            shadowAngle: 45,    // angle of the shadow.  Clockwise from x axis.
    +            shadowOffset: 1.5,  // offset from the line of the shadow.
    +            shadowDepth: 3,     // Number of strokes to make when drawing shadow.
    +                                // Each stroke offset by shadowOffset from the last.
    +            shadowAlpha: 0.07   // Opacity of the shadow
    +        }
    +    }
    +}
    + +
    + + + + + + + + + + +
    This document will help you understand how jqPlot’s options relate to the API documentation and the jqPlot object itself.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-axisLabelRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-axisLabelRenderer-js.html new file mode 100644 index 0000000000..eb1fc451d8 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-axisLabelRenderer-js.html @@ -0,0 +1,47 @@ + + +$.jqplot.AxisLabelRenderer + + + + + + + + + +

    Renderer to place labels on the axes.

    Summary
    $.jqplot.AxisLabelRendererRenderer to place labels on the axes.
    Properties
    showwether or not to show the tick (mark and label).
    labelThe text or html for the label.
    escapeHTMLtrue to escape HTML entities in the label.
    + +

    Properties

    + +

    show

    this.show = true

    wether or not to show the tick (mark and label).

    + +

    label

    this.label = ''

    The text or html for the label.

    + +

    escapeHTML

    this.escapeHTML = false

    true to escape HTML entities in the label.

    + +
    + + + + + + + + + + +
    this.show = true
    wether or not to show the tick (mark and label).
    this.label = ''
    The text or html for the label.
    this.escapeHTML = false
    true to escape HTML entities in the label.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-axisTickRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-axisTickRenderer-js.html new file mode 100644 index 0000000000..0a76e7352a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-axisTickRenderer-js.html @@ -0,0 +1,71 @@ + + +$.jqplot.AxisTickRenderer + + + + + + + + + +

    A “tick” object showing the value of a tick/gridline on the plot.

    Summary
    $.jqplot.AxisTickRendererA “tick” object showing the value of a tick/gridline on the plot.
    Properties
    marktick mark on the axis.
    showMarkwether or not to show the mark on the axis.
    showGridlinewether or not to draw the gridline on the grid at this tick.
    isMinorTickif this is a minor tick.
    sizeLength of the tick beyond the grid in pixels.
    markSizeLength of the tick marks in pixels.
    showwether or not to show the tick (mark and label).
    showLabelwether or not to show the label.
    formatterA class of a formatter for the tick text.
    prefixString to prepend to the tick label.
    formatStringstring passed to the formatter.
    fontFamilycss spec for the font-family css attribute.
    fontSizecss spec for the font-size css attribute.
    textColorcss spec for the color attribute.
    escapeHTMLtrue to escape HTML entities in the label.
    + +

    Properties

    + +

    mark

    this.mark = 'outside'

    tick mark on the axis.  One of ‘inside’, ‘outside’, ‘cross’, ‘’ or null.

    + +

    showMark

    this.showMark = true

    wether or not to show the mark on the axis.

    + +

    showGridline

    this.showGridline = true

    wether or not to draw the gridline on the grid at this tick.

    + +

    isMinorTick

    this.isMinorTick = false

    if this is a minor tick.

    + +

    size

    this.size = 4

    Length of the tick beyond the grid in pixels.  DEPRECATED: This has been superceeded by markSize

    + +

    markSize

    this.markSize = 6

    Length of the tick marks in pixels.  For ‘cross’ style, length will be stoked above and below axis, so total length will be twice this.

    + +

    show

    this.show = true

    wether or not to show the tick (mark and label).  Setting this to false requires more testing.  It is recommended to set showLabel and showMark to false instead.

    + +

    showLabel

    this.showLabel = true

    wether or not to show the label.

    + +

    formatter

    this.formatter = $.jqplot.DefaultTickFormatter

    A class of a formatter for the tick text.  sprintf by default.

    + +

    prefix

    this.prefix = ''

    String to prepend to the tick label.  Prefix is prepended to the formatted tick label.

    + +

    formatString

    this.formatString = ''

    string passed to the formatter.

    + +

    fontFamily

    this.fontFamily

    css spec for the font-family css attribute.

    + +

    fontSize

    this.fontSize

    css spec for the font-size css attribute.

    + +

    textColor

    this.textColor

    css spec for the color attribute.

    + +

    escapeHTML

    this.escapeHTML = false

    true to escape HTML entities in the label.

    + +
    + + + + + + + + + + +
    this.mark = 'outside'
    tick mark on the axis.
    this.showMark = true
    wether or not to show the mark on the axis.
    this.showGridline = true
    wether or not to draw the gridline on the grid at this tick.
    this.isMinorTick = false
    if this is a minor tick.
    this.size = 4
    Length of the tick beyond the grid in pixels.
    this.markSize = 6
    Length of the tick marks in pixels.
    this.show = true
    wether or not to show the tick (mark and label).
    this.showLabel = true
    wether or not to show the label.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    this.prefix = ''
    String to prepend to the tick label.
    this.formatString = ''
    string passed to the formatter.
    this.fontFamily
    css spec for the font-family css attribute.
    this.fontSize
    css spec for the font-size css attribute.
    this.textColor
    css spec for the color attribute.
    this.escapeHTML = false
    true to escape HTML entities in the label.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-canvasGridRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-canvasGridRenderer-js.html new file mode 100644 index 0000000000..ae8df831b8 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-canvasGridRenderer-js.html @@ -0,0 +1,39 @@ + + +$.jqplot.CanvasGridRenderer + + + + + + + + + +

    The default jqPlot grid renderer, creating a grid on a canvas element.  The renderer has no additional options beyond the Grid class.

    + +
    + + + + + + + + + + +
    Object representing the grid on which the plot is drawn.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-core-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-core-js.html new file mode 100644 index 0000000000..ff3cdd3850 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-core-js.html @@ -0,0 +1,359 @@ + + +jqPlot Charts + + + + + + + + + +

    Pure JavaScript plotting plugin for jQuery.

    Summary
    jqPlot ChartsPure JavaScript plotting plugin for jQuery.
    Version1.0.0b2_r792
    Copyright & LicenseCopyright © 2009-2011 Chris Leonello jqPlot is currently available for use in all personal or commercial projects under both the MIT and GPL version 2.0 licenses.
    IntroductionjqPlot requires jQuery (1.4+ required for certain features).
    UsageSee jqPlot Usage
    Available OptionsSee jqPlot Options for a list of options available thorugh the options object (not complete yet!)
    Options UsageSee Options Tutorial
    ChangesSee Change Log
    $.jqplotjQuery function called by the user to create a plot.
    Hooks
    jqPlot Pugin Hooks
    AxisAn individual axis object.
    PropertiesAxes options are specified within an axes object at the top level of the plot options like so:
    showWether to display the axis on the graph.
    tickRendererA class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    tickOptionsOptions that will be passed to the tickRenderer, see $.jqplot.AxisTickRenderer options.
    labelRendererA class of a rendering engine for creating an axis label.
    labelOptionsOptions passed to the label renderer.
    labelLabel for the axis
    showLabeltrue to show the axis label.
    minminimum value of the axis (in data units, not pixels).
    maxmaximum value of the axis (in data units, not pixels).
    autoscaleAutoscale the axis min and max values to provide sensible tick spacing.
    padPadding to extend the range above and below the data bounds.
    padMaxPadding to extend the range above data bounds.
    padMinPadding to extend the range below data bounds.
    ticks1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis.
    numberTicksDesired number of ticks.
    tickIntervalnumber of units between ticks.
    rendererA class of a rendering engine that handles tick generation, scaling input data to pixel grid units and drawing the axis element.
    rendererOptionsrenderer specific options.
    showTicksWether to show the ticks (both marks and labels) or not.
    showTickMarksWether to show the tick marks (line crossing grid) or not.
    showMinorTicksWether or not to show minor ticks.
    useSeriesColorUse the color of the first series associated with this axis for the tick marks and line bordering this axis.
    borderWidthwidth of line stroked at the border of the axis.
    borderColorcolor of the border adjacent to the axis.
    syncTickstrue to try and synchronize tick spacing across multiple axes so that ticks and grid lines line up.
    tickSpacingApproximate pixel spacing between ticks on graph.
    LegendLegend object.
    Properties
    showWether to display the legend on the graph.
    locationPlacement of the legend.
    labelsArray of labels to use.
    showLabelstrue to show the label text on the legend.
    showSwatchtrue to show the color swatches on the legend.
    placement“insideGrid” places legend inside the grid area of the plot.
    xoffsetDEPRECATED.
    yoffsetDEPRECATED.
    bordercss spec for the border around the legend box.
    backgroundcss spec for the background of the legend box.
    textColorcss color spec for the legend text.
    fontFamilycss font-family spec for the legend text.
    fontSizecss font-size spec for the legend text.
    rowSpacingcss padding-top spec for the rows in the legend.
    rendererOptionsrenderer specific options passed to the renderer.
    predrawWether to draw the legend before the series or not.
    marginTopCSS margin for the legend DOM element.
    marginRightCSS margin for the legend DOM element.
    marginBottomCSS margin for the legend DOM element.
    marginLeftCSS margin for the legend DOM element.
    TitlePlot Title object.
    Properties
    texttext of the title;
    showwether or not to show the title
    fontFamilycss font-family spec for the text.
    fontSizecss font-size spec for the text.
    textAligncss text-align spec for the text.
    textColorcss color spec for the text.
    rendererA class for creating a DOM element for the title, see $.jqplot.DivTitleRenderer.
    rendererOptionsrenderer specific options passed to the renderer.
    SeriesAn individual data series object.
    PropertiesProperties will be assigned from a series array at the top level of the options.
    showwether or not to draw the series.
    xaxiswhich x axis to use with this series, either ‘xaxis’ or ‘x2axis’.
    yaxiswhich y axis to use with this series, either ‘yaxis’ or ‘y2axis’.
    rendererA class of a renderer which will draw the series, see $.jqplot.LineRenderer.
    rendererOptionsOptions to pass on to the renderer.
    labelLine label to use in the legend.
    showLabeltrue to show label for this series in the legend.
    colorcss color spec for the series
    lineWidthwidth of the line in pixels.
    lineJoinCanvas lineJoin style between segments of series.
    lineCapCanvas lineCap style at ends of line.
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    breakOnNullWether line segments should be be broken at null value.
    markerRendererA class of a renderer which will draw marker (e.g.
    markerOptionsrenderer specific options to pass to the markerRenderer, see $.jqplot.MarkerRenderer.
    showLinewether to actually draw the line or not.
    showMarkerwether or not to show the markers at the data points.
    index0 based index of this series in the plot series array.
    filltrue or false, wether to fill under lines or in bars.
    fillColorCSS color spec to use for fill under line.
    fillAlphaAlpha transparency to apply to the fill under the line.
    fillAndStrokeIf true will stroke the line (with color this.color) as well as fill under it.
    disableStacktrue to not stack this series with other series in the plot.
    neighborThresholdhow close or far (in pixels) the cursor must be from a point marker to detect the point.
    fillToZerotrue will force bar and filled series to fill toward zero on the fill Axis.
    fillToValuefill a filled series to this value on the fill axis.
    fillAxisEither ‘x’ or ‘y’.
    useNegativeColorstrue to color negative values differently in filled and bar charts.
    GridObject representing the grid on which the plot is drawn.
    Properties
    drawGridlineswether to draw the gridlines on the plot.
    gridLineColorcolor of the grid lines.
    gridLineWidthwidth of the grid lines.
    backgroundcss spec for the background color.
    borderColorcss spec for the color of the grid border.
    borderWidthwidth of the border in pixels.
    drawBorderTrue to draw border around grid.
    shadowwether to show a shadow behind the grid.
    shadowAngleshadow angle in degrees
    shadowOffsetOffset of each shadow stroke from the border in pixels
    shadowWidthwidth of the stoke for the shadow
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowColoran optional css color spec for the shadow in ‘rgba(n, n, n, n)’ form
    shadowAlphaAlpha channel transparency of shadow.
    rendererInstance of a renderer which will actually render the grid, see $.jqplot.CanvasGridRenderer.
    rendererOptionsOptions to pass on to the renderer, see $.jqplot.CanvasGridRenderer.
    jqPlotPlot object returned by call to $.jqplot.
    PropertiesThese properties are specified at the top of the options object like so:
    datauser’s data.
    axesDefaultsdefault options that will be applied to all axes.
    seriesDefaultsdefault options that will be applied to all series.
    seriesArray of series object options.
    axesup to 4 axes are supported, each with it’s own options, See Axis for axis specific options.
    gridSee Grid for grid specific options.
    legendsee <$.jqplot.TableLegendRenderer>
    seriesColorsAnn array of CSS color specifications that will be applied, in order, to the series in the plot.
    sortDatafalse to not sort the data passed in by the user.
    fontSizecss spec for the font-size attribute.
    titleTitle object.
    stackSeriestrue or false, creates a stack or “mountain” plot.
    defaultAxisStart1-D data series are internally converted into 2-D [x,y] data point arrays by jqPlot.
    methods
    initsets the plot target, checks data and applies user options to plot.
    resetAxesScaleReset the specified axes min, max, numberTicks and tickInterval properties to null or reset these properties on all axes if no list of axes is provided.
    reInitializereinitialize plot for replotting.
    destroyReleases all resources occupied by the plot
    replotDoes a reinitialization of the plot followed by a redraw.
    redrawEmpties the plot target div and redraws the plot.
    drawDraws all elements of the plot into the container.
    drawSeriesRedraws all or just one series on the plot.
    moveSeriesToFrontThis method requires jQuery 1.4+ Moves the specified series canvas in front of all other series canvases.
    moveSeriesToBackThis method requires jQuery 1.4+ Moves the specified series canvas behind all other series canvases.
    restorePreviousSeriesOrderThis method requires jQuery 1.4+ Restore the series canvas order to its previous state.
    restoreOriginalSeriesOrderThis method requires jQuery 1.4+ Restore the series canvas order to its original order when the plot was created.
    + +

    Version

    1.0.0b2_r792

    + +

    Copyright & License

    Copyright © 2009-2011 Chris Leonello jqPlot is currently available for use in all personal or commercial projects under both the MIT and GPL version 2.0 licenses.  This means that you can choose the license that best suits your project and use it accordingly.

    See GPL Version 2 and MIT License contained within this distribution for further information.

    The author would appreciate an email letting him know of any substantial use of jqPlot.  You can reach the author at: chris at jqplot dot com or see http://www.jqplot.com/info.php.  This is, of course, not required.

    If you are feeling kind and generous, consider supporting the project by making a donation at: http://www.jqplot.com/donate.php.

    sprintf functions contained in jqplot.sprintf.js by Ash Searle

    version 2007.04.27 author Ash Searle http://hexmen.com/blog/2007/03/printf-sprintf/ http://hexmen.com/js/sprintf.js The author (Ash Searle) has placed this code in the public domain: “This code is unrestricted: you are free to use it however you like.”

    + +

    Introduction

    jqPlot requires jQuery (1.4+ required for certain features). jQuery 1.4.2 is included in the distribution.  To use jqPlot include jQuery, the jqPlot jQuery plugin, the jqPlot css file and optionally the excanvas script for IE support in your web page:

    <!--[if lt IE 9]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->
    +<script language="javascript" type="text/javascript" src="jquery-1.4.4.min.js"></script>
    +<script language="javascript" type="text/javascript" src="jquery.jqplot.min.js"></script>
    +<link rel="stylesheet" type="text/css" href="jquery.jqplot.css" />

    jqPlot can be customized by overriding the defaults of any of the objects which make up the plot.  The general usage of jqplot is:

    chart = $.jqplot('targetElemId', [dataArray,...], {optionsObject});

    The options available to jqplot are detailed in jqPlot Options in the jqPlotOptions.txt file.

    An actual call to $.jqplot() may look like the examples below:

    chart = $.jqplot('chartdiv',  [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]]);

    or

    dataArray = [34,12,43,55,77];
    +chart = $.jqplot('targetElemId', [dataArray, ...], {title:'My Plot', axes:{yaxis:{min:20, max:100}}});

    For more inforrmation, see jqPlot Usage.

    + +

    Usage

    + +

    Available Options

    See jqPlot Options for a list of options available thorugh the options object (not complete yet!)

    + +

    Options Usage

    + +

    Changes

    + +

    $.jqplot

    jQuery function called by the user to create a plot.

    Parameters

    targetID of target element to render the plot into.
    dataan array of data series.
    optionsuser defined options object.  See the individual classes for available options.

    Properties

    configobject to hold configuration information for jqPlot plot object.

    attributes

    enablePluginsFalse to disable plugins by default.  Plugins must then be explicitly enabled in the individual plot options.  Default: false.  This property sets the “show” property of certain plugins to true or false.  Only plugins that can be immediately active upon loading are affected.  This includes non-renderer plugins like cursor, dragable, highlighter, and trendline.
    defaultHeightDefault height for plots where no css height specification exists.  This is a jqplot wide default.
    defaultWidthDefault height for plots where no css height specification exists.  This is a jqplot wide default.
    + +

    Hooks

    + +

    jqPlot Pugin Hooks

    $.jqplot.preInitHookscalled before initialization.
    $.jqplot.postInitHookscalled after initialization.
    $.jqplot.preParseOptionsHookscalled before user options are parsed.
    $.jqplot.postParseOptionsHookscalled after user options are parsed.
    $.jqplot.preDrawHookscalled before plot draw.
    $.jqplot.postDrawHookscalled after plot draw.
    $.jqplot.preDrawSeriesHookscalled before each series is drawn.
    $.jqplot.postDrawSeriesHookscalled after each series is drawn.
    $.jqplot.preDrawLegendHookscalled before the legend is drawn.
    $.jqplot.addLegendRowHookscalled at the end of legend draw, so plugins can add rows to the legend table.
    $.jqplot.preSeriesInitHookscalled before series is initialized.
    $.jqplot.postSeriesInitHookscalled after series is initialized.
    $.jqplot.preParseSeriesOptionsHookscalled before series related options are parsed.
    $.jqplot.postParseSeriesOptionsHookscalled after series related options are parsed.
    $.jqplot.eventListenerHookscalled at the end of plot drawing, binds listeners to the event canvas which lays on top of the grid area.
    $.jqplot.preDrawSeriesShadowHookscalled before series shadows are drawn.
    $.jqplot.postDrawSeriesShadowHookscalled after series shadows are drawn.
    + +

    Axis

    An individual axis object.  Cannot be instantiated directly, but created by the Plot oject.  Axis properties can be set or overriden by the options passed in from the user.

    Summary
    PropertiesAxes options are specified within an axes object at the top level of the plot options like so:
    showWether to display the axis on the graph.
    tickRendererA class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    tickOptionsOptions that will be passed to the tickRenderer, see $.jqplot.AxisTickRenderer options.
    labelRendererA class of a rendering engine for creating an axis label.
    labelOptionsOptions passed to the label renderer.
    labelLabel for the axis
    showLabeltrue to show the axis label.
    minminimum value of the axis (in data units, not pixels).
    maxmaximum value of the axis (in data units, not pixels).
    autoscaleAutoscale the axis min and max values to provide sensible tick spacing.
    padPadding to extend the range above and below the data bounds.
    padMaxPadding to extend the range above data bounds.
    padMinPadding to extend the range below data bounds.
    ticks1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis.
    numberTicksDesired number of ticks.
    tickIntervalnumber of units between ticks.
    rendererA class of a rendering engine that handles tick generation, scaling input data to pixel grid units and drawing the axis element.
    rendererOptionsrenderer specific options.
    showTicksWether to show the ticks (both marks and labels) or not.
    showTickMarksWether to show the tick marks (line crossing grid) or not.
    showMinorTicksWether or not to show minor ticks.
    useSeriesColorUse the color of the first series associated with this axis for the tick marks and line bordering this axis.
    borderWidthwidth of line stroked at the border of the axis.
    borderColorcolor of the border adjacent to the axis.
    syncTickstrue to try and synchronize tick spacing across multiple axes so that ticks and grid lines line up.
    tickSpacingApproximate pixel spacing between ticks on graph.
    + +

    Properties

    Axes options are specified within an axes object at the top level of the plot options like so:

    {
    +   axes: {
    +       xaxis: {min: 5},
    +       yaxis: {min: 2, max: 8, numberTicks:4},
    +       x2axis: {pad: 1.5},
    +       y2axis: {ticks:[22, 44, 66, 88]}
    +       }
    +}

    There are 2 x axes, ‘xaxis’ and ‘x2axis’, and 9 yaxes, ‘yaxis’, ‘y2axis’.  ‘y3axis’, ...  Any or all of which may be specified.

    + +

    show

    this.show = false

    Wether to display the axis on the graph.

    + +

    tickRenderer

    this.tickRenderer = $.jqplot.AxisTickRenderer

    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.

    + +

    tickOptions

    this.tickOptions = {}

    Options that will be passed to the tickRenderer, see $.jqplot.AxisTickRenderer options.

    + +

    labelRenderer

    this.labelRenderer = $.jqplot.AxisLabelRenderer

    A class of a rendering engine for creating an axis label.

    + +

    labelOptions

    this.labelOptions = {}

    Options passed to the label renderer.

    + +

    label

    this.label = null

    Label for the axis

    + +

    showLabel

    this.showLabel = true

    true to show the axis label.

    + +

    min

    this.min=null

    minimum value of the axis (in data units, not pixels).

    + +

    max

    this.max=null

    maximum value of the axis (in data units, not pixels).

    + +

    autoscale

    this.autoscale = false

    Autoscale the axis min and max values to provide sensible tick spacing.  If axis min or max are set, autoscale will be turned off.  The numberTicks, tickInterval and pad options do work with autoscale, although tickInterval has not been tested yet. padMin and padMax do nothing when autoscale is on.

    + +

    pad

    this.pad = 1.2

    Padding to extend the range above and below the data bounds.  The data range is multiplied by this factor to determine minimum and maximum axis bounds.  A value of 0 will be interpreted to mean no padding, and pad will be set to 1.0.

    + +

    padMax

    this.padMax = null

    Padding to extend the range above data bounds.  The top of the data range is multiplied by this factor to determine maximum axis bounds.  A value of 0 will be interpreted to mean no padding, and padMax will be set to 1.0.

    + +

    padMin

    this.padMin = null

    Padding to extend the range below data bounds.  The bottom of the data range is multiplied by this factor to determine minimum axis bounds.  A value of 0 will be interpreted to mean no padding, and padMin will be set to 1.0.

    + +

    ticks

    this.ticks = []

    1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis.  If no label is specified, the value is formatted into an appropriate label.

    + +

    numberTicks

    this.numberTicks

    Desired number of ticks.  Default is to compute automatically.

    + +

    tickInterval

    this.tickInterval

    number of units between ticks.  Mutually exclusive with numberTicks.

    + +

    renderer

    this.renderer = $.jqplot.LinearAxisRenderer

    A class of a rendering engine that handles tick generation, scaling input data to pixel grid units and drawing the axis element.

    + +

    rendererOptions

    this.rendererOptions = {}

    renderer specific options.  See $.jqplot.LinearAxisRenderer for options.

    + +

    showTicks

    this.showTicks = true

    Wether to show the ticks (both marks and labels) or not.  Will not override showMark and showLabel options if specified on the ticks themselves.

    + +

    showTickMarks

    this.showTickMarks = true

    Wether to show the tick marks (line crossing grid) or not.  Overridden by showTicks and showMark option of tick itself.

    + +

    showMinorTicks

    this.showMinorTicks = true

    Wether or not to show minor ticks.  This is renderer dependent.  The default $.jqplot.LinearAxisRenderer does not have minor ticks.

    + +

    useSeriesColor

    this.useSeriesColor = false

    Use the color of the first series associated with this axis for the tick marks and line bordering this axis.

    + +

    borderWidth

    this.borderWidth = null

    width of line stroked at the border of the axis.  Defaults to the width of the grid boarder.

    + +

    borderColor

    this.borderColor = null

    color of the border adjacent to the axis.  Defaults to grid border color.

    + +

    syncTicks

    this.syncTicks = null

    true to try and synchronize tick spacing across multiple axes so that ticks and grid lines line up.  This has an impact on autoscaling algorithm, however.  In general, autoscaling an individual axis will work better if it does not have to sync ticks.

    + +

    tickSpacing

    this.tickSpacing = 75

    Approximate pixel spacing between ticks on graph.  Used during autoscaling.  This number will be an upper bound, actual spacing will be less.

    + +

    Legend

    Legend object.  Cannot be instantiated directly, but created by the Plot oject.  Legend properties can be set or overriden by the options passed in from the user.

    Summary
    Properties
    showWether to display the legend on the graph.
    locationPlacement of the legend.
    labelsArray of labels to use.
    showLabelstrue to show the label text on the legend.
    showSwatchtrue to show the color swatches on the legend.
    placement“insideGrid” places legend inside the grid area of the plot.
    xoffsetDEPRECATED.
    yoffsetDEPRECATED.
    bordercss spec for the border around the legend box.
    backgroundcss spec for the background of the legend box.
    textColorcss color spec for the legend text.
    fontFamilycss font-family spec for the legend text.
    fontSizecss font-size spec for the legend text.
    rowSpacingcss padding-top spec for the rows in the legend.
    rendererOptionsrenderer specific options passed to the renderer.
    predrawWether to draw the legend before the series or not.
    marginTopCSS margin for the legend DOM element.
    marginRightCSS margin for the legend DOM element.
    marginBottomCSS margin for the legend DOM element.
    marginLeftCSS margin for the legend DOM element.
    + +

    Properties

    + +

    show

    this.show = false

    Wether to display the legend on the graph.

    + +

    location

    this.location = 'ne'

    Placement of the legend.  one of the compass directions: nw, n, ne, e, se, s, sw, w

    + +

    labels

    this.labels = []

    Array of labels to use.  By default the renderer will look for labels on the series.  Labels specified in this array will override labels specified on the series.

    + +

    showLabels

    this.showLabels = true

    true to show the label text on the legend.

    + +

    showSwatch

    this.showSwatches = true

    true to show the color swatches on the legend.

    + +

    placement

    this.placement = "insideGrid"

    ”insideGrid” places legend inside the grid area of the plot.  “outsideGrid” places the legend outside the grid but inside the plot container, shrinking the grid to accomodate the legend.  “inside” synonym for “insideGrid”, “outside” places the legend ouside the grid area, but does not shrink the grid which can cause the legend to overflow the plot container.

    + +

    xoffset

    this.xoffset = 0

    DEPRECATED.  Set the margins on the legend using the marginTop, marginLeft, etc. properties or via CSS margin styling of the .jqplot-table-legend class.

    + +

    yoffset

    this.yoffset = 0

    DEPRECATED.  Set the margins on the legend using the marginTop, marginLeft, etc. properties or via CSS margin styling of the .jqplot-table-legend class.

    + +

    border

    this.border

    css spec for the border around the legend box.

    + +

    background

    this.background

    css spec for the background of the legend box.

    + +

    textColor

    this.textColor

    css color spec for the legend text.

    + +

    fontFamily

    this.fontFamily

    css font-family spec for the legend text.

    + +

    fontSize

    this.fontSize

    css font-size spec for the legend text.

    + +

    rowSpacing

    this.rowSpacing = '0.5em'

    css padding-top spec for the rows in the legend.

    + +

    rendererOptions

    this.rendererOptions = {}

    renderer specific options passed to the renderer.

    + +

    predraw

    Wether to draw the legend before the series or not.  Used with series specific legend renderers for pie, donut, mekko charts, etc.

    + +

    marginTop

    this.marginTop = null

    CSS margin for the legend DOM element.  This will set an element CSS style for the margin which will override any style sheet setting.  The default will be taken from the stylesheet.

    + +

    marginRight

    this.marginRight = null

    CSS margin for the legend DOM element.  This will set an element CSS style for the margin which will override any style sheet setting.  The default will be taken from the stylesheet.

    + +

    marginBottom

    this.marginBottom = null

    CSS margin for the legend DOM element.  This will set an element CSS style for the margin which will override any style sheet setting.  The default will be taken from the stylesheet.

    + +

    marginLeft

    this.marginLeft = null

    CSS margin for the legend DOM element.  This will set an element CSS style for the margin which will override any style sheet setting.  The default will be taken from the stylesheet.

    + +

    Title

    Plot Title object.  Cannot be instantiated directly, but created by the Plot oject.  Title properties can be set or overriden by the options passed in from the user.

    Parameters

    texttext of the title.
    Summary
    Properties
    texttext of the title;
    showwether or not to show the title
    fontFamilycss font-family spec for the text.
    fontSizecss font-size spec for the text.
    textAligncss text-align spec for the text.
    textColorcss color spec for the text.
    rendererA class for creating a DOM element for the title, see $.jqplot.DivTitleRenderer.
    rendererOptionsrenderer specific options passed to the renderer.
    + +

    Properties

    + +

    text

    this.text = text

    text of the title;

    + +

    show

    this.show = true

    wether or not to show the title

    + +

    fontFamily

    this.fontFamily

    css font-family spec for the text.

    + +

    fontSize

    this.fontSize

    css font-size spec for the text.

    + +

    textAlign

    this.textAlign

    css text-align spec for the text.

    + +

    textColor

    this.textColor

    css color spec for the text.

    + +

    renderer

    this.renderer = $.jqplot.DivTitleRenderer

    A class for creating a DOM element for the title, see $.jqplot.DivTitleRenderer.

    + +

    rendererOptions

    this.rendererOptions = {}

    renderer specific options passed to the renderer.

    + +

    Series

    An individual data series object.  Cannot be instantiated directly, but created by the Plot oject.  Series properties can be set or overriden by the options passed in from the user.

    Summary
    PropertiesProperties will be assigned from a series array at the top level of the options.
    showwether or not to draw the series.
    xaxiswhich x axis to use with this series, either ‘xaxis’ or ‘x2axis’.
    yaxiswhich y axis to use with this series, either ‘yaxis’ or ‘y2axis’.
    rendererA class of a renderer which will draw the series, see $.jqplot.LineRenderer.
    rendererOptionsOptions to pass on to the renderer.
    labelLine label to use in the legend.
    showLabeltrue to show label for this series in the legend.
    colorcss color spec for the series
    lineWidthwidth of the line in pixels.
    lineJoinCanvas lineJoin style between segments of series.
    lineCapCanvas lineCap style at ends of line.
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    breakOnNullWether line segments should be be broken at null value.
    markerRendererA class of a renderer which will draw marker (e.g.
    markerOptionsrenderer specific options to pass to the markerRenderer, see $.jqplot.MarkerRenderer.
    showLinewether to actually draw the line or not.
    showMarkerwether or not to show the markers at the data points.
    index0 based index of this series in the plot series array.
    filltrue or false, wether to fill under lines or in bars.
    fillColorCSS color spec to use for fill under line.
    fillAlphaAlpha transparency to apply to the fill under the line.
    fillAndStrokeIf true will stroke the line (with color this.color) as well as fill under it.
    disableStacktrue to not stack this series with other series in the plot.
    neighborThresholdhow close or far (in pixels) the cursor must be from a point marker to detect the point.
    fillToZerotrue will force bar and filled series to fill toward zero on the fill Axis.
    fillToValuefill a filled series to this value on the fill axis.
    fillAxisEither ‘x’ or ‘y’.
    useNegativeColorstrue to color negative values differently in filled and bar charts.
    + +

    Properties

    Properties will be assigned from a series array at the top level of the options.  If you had two series and wanted to change the color and line width of the first and set the second to use the secondary y axis with no shadow and supply custom labels for each:

    {
    +   series:[
    +       {color: '#ff4466', lineWidth: 5, label:'good line'},
    +       {yaxis: 'y2axis', shadow: false, label:'bad line'}
    +   ]
    +}
    + +

    show

    this.show = true

    wether or not to draw the series.

    + +

    xaxis

    this.xaxis = 'xaxis'

    which x axis to use with this series, either ‘xaxis’ or ‘x2axis’.

    + +

    yaxis

    this.yaxis = 'yaxis'

    which y axis to use with this series, either ‘yaxis’ or ‘y2axis’.

    + +

    renderer

    this.renderer = $.jqplot.LineRenderer

    A class of a renderer which will draw the series, see $.jqplot.LineRenderer.

    + +

    rendererOptions

    this.rendererOptions = {}

    Options to pass on to the renderer.

    + +

    label

    this.label = ''

    Line label to use in the legend.

    + +

    showLabel

    this.showLabel = true

    true to show label for this series in the legend.

    + +

    color

    this.color

    css color spec for the series

    + +

    lineWidth

    this.lineWidth = 2.5

    width of the line in pixels.  May have different meanings depending on renderer.

    + +

    lineJoin

    this.lineJoin = 'round'

    Canvas lineJoin style between segments of series.

    + +

    lineCap

    this.lineCap = 'round'

    Canvas lineCap style at ends of line.

    + +

    shadow

    this.shadow = true

    wether or not to draw a shadow on the line

    + +

    shadowAngle

    this.shadowAngle = 45

    Shadow angle in degrees

    + +

    shadowOffset

    this.shadowOffset = 1.25

    Shadow offset from line in pixels

    + +

    shadowDepth

    this.shadowDepth = 3

    Number of times shadow is stroked, each stroke offset shadowOffset from the last.

    + +

    shadowAlpha

    this.shadowAlpha = '0.1'

    Alpha channel transparency of shadow.  0 = transparent.

    + +

    breakOnNull

    this.breakOnNull = false

    Wether line segments should be be broken at null value.  False will join point on either side of line.

    + +

    markerRenderer

    this.markerRenderer = $.jqplot.MarkerRenderer

    A class of a renderer which will draw marker (e.g. circle, square, ...) at the data points, see $.jqplot.MarkerRenderer.

    + +

    markerOptions

    this.markerOptions = {}

    renderer specific options to pass to the markerRenderer, see $.jqplot.MarkerRenderer.

    + +

    showLine

    this.showLine = true

    wether to actually draw the line or not.  Series will still be renderered, even if no line is drawn.

    + +

    showMarker

    this.showMarker = true

    wether or not to show the markers at the data points.

    + +

    index

    this.index

    0 based index of this series in the plot series array.

    + +

    fill

    this.fill = false

    true or false, wether to fill under lines or in bars.  May not be implemented in all renderers.

    + +

    fillColor

    this.fillColor

    CSS color spec to use for fill under line.  Defaults to line color.

    + +

    fillAlpha

    this.fillAlpha

    Alpha transparency to apply to the fill under the line.  Use this to adjust alpha separate from fill color.

    + +

    fillAndStroke

    this.fillAndStroke = false

    If true will stroke the line (with color this.color) as well as fill under it.  Applies only when fill is true.

    + +

    disableStack

    this.disableStack = false

    true to not stack this series with other series in the plot.  To render properly, non-stacked series must come after any stacked series in the plot’s data series array.  So, the plot’s data series array would look like:

    [stackedSeries1, stackedSeries2, ..., nonStackedSeries1, nonStackedSeries2, ...]

    disableStack will put a gap in the stacking order of series, and subsequent stacked series will not fill down through the non-stacked series and will most likely not stack properly on top of the non-stacked series.

    + +

    neighborThreshold

    this.neighborThreshold = 4

    how close or far (in pixels) the cursor must be from a point marker to detect the point.

    + +

    fillToZero

    this.fillToZero = false

    true will force bar and filled series to fill toward zero on the fill Axis.

    + +

    fillToValue

    this.fillToValue = 0

    fill a filled series to this value on the fill axis.  Works in conjunction with fillToZero, so that must be true.

    + +

    fillAxis

    this.fillAxis = 'y'

    Either ‘x’ or ‘y’.  Which axis to fill the line toward if fillToZero is true.  ‘y’ means fill up/down to 0 on the y axis for this series.

    + +

    useNegativeColors

    this.useNegativeColors = true

    true to color negative values differently in filled and bar charts.

    + +

    Grid

    Object representing the grid on which the plot is drawn.  The grid in this context is the area bounded by the axes, the area which will contain the series.  Note, the series are drawn on their own canvas.  The Grid object cannot be instantiated directly, but is created by the Plot oject.  Grid properties can be set or overriden by the options passed in from the user.

    Summary
    Properties
    drawGridlineswether to draw the gridlines on the plot.
    gridLineColorcolor of the grid lines.
    gridLineWidthwidth of the grid lines.
    backgroundcss spec for the background color.
    borderColorcss spec for the color of the grid border.
    borderWidthwidth of the border in pixels.
    drawBorderTrue to draw border around grid.
    shadowwether to show a shadow behind the grid.
    shadowAngleshadow angle in degrees
    shadowOffsetOffset of each shadow stroke from the border in pixels
    shadowWidthwidth of the stoke for the shadow
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowColoran optional css color spec for the shadow in ‘rgba(n, n, n, n)’ form
    shadowAlphaAlpha channel transparency of shadow.
    rendererInstance of a renderer which will actually render the grid, see $.jqplot.CanvasGridRenderer.
    rendererOptionsOptions to pass on to the renderer, see $.jqplot.CanvasGridRenderer.
    + +

    Properties

    + +

    drawGridlines

    this.drawGridlines = true

    wether to draw the gridlines on the plot.

    + +

    gridLineColor

    this.gridLineColor = '#cccccc'

    color of the grid lines.

    + +

    gridLineWidth

    this.gridLineWidth = 1.0

    width of the grid lines.

    + +

    background

    this.background = '#fffdf6'

    css spec for the background color.

    + +

    borderColor

    this.borderColor = '#999999'

    css spec for the color of the grid border.

    + +

    borderWidth

    this.borderWidth = 2.0

    width of the border in pixels.

    + +

    drawBorder

    this.drawBorder = true

    True to draw border around grid.

    + +

    shadow

    this.shadow = true

    wether to show a shadow behind the grid.

    + +

    shadowAngle

    this.shadowAngle = 45

    shadow angle in degrees

    + +

    shadowOffset

    this.shadowOffset = 1.5

    Offset of each shadow stroke from the border in pixels

    + +

    shadowWidth

    this.shadowWidth = 3

    width of the stoke for the shadow

    + +

    shadowDepth

    this.shadowDepth = 3

    Number of times shadow is stroked, each stroke offset shadowOffset from the last.

    + +

    shadowColor

    this.shadowColor = null

    an optional css color spec for the shadow in ‘rgba(n, n, n, n)’ form

    + +

    shadowAlpha

    this.shadowAlpha = '0.07'

    Alpha channel transparency of shadow.  0 = transparent.

    + +

    renderer

    this.renderer = $.jqplot.CanvasGridRenderer

    Instance of a renderer which will actually render the grid, see $.jqplot.CanvasGridRenderer.

    + +

    rendererOptions

    this.rendererOptions = {}

    Options to pass on to the renderer, see $.jqplot.CanvasGridRenderer.

    + +

    jqPlot

    Plot object returned by call to $.jqplot.  Handles parsing user options, creating sub objects (Axes, legend, title, series) and rendering the plot.

    Summary
    PropertiesThese properties are specified at the top of the options object like so:
    datauser’s data.
    axesDefaultsdefault options that will be applied to all axes.
    seriesDefaultsdefault options that will be applied to all series.
    seriesArray of series object options.
    axesup to 4 axes are supported, each with it’s own options, See Axis for axis specific options.
    gridSee Grid for grid specific options.
    legendsee <$.jqplot.TableLegendRenderer>
    seriesColorsAnn array of CSS color specifications that will be applied, in order, to the series in the plot.
    sortDatafalse to not sort the data passed in by the user.
    fontSizecss spec for the font-size attribute.
    titleTitle object.
    stackSeriestrue or false, creates a stack or “mountain” plot.
    defaultAxisStart1-D data series are internally converted into 2-D [x,y] data point arrays by jqPlot.
    methods
    initsets the plot target, checks data and applies user options to plot.
    resetAxesScaleReset the specified axes min, max, numberTicks and tickInterval properties to null or reset these properties on all axes if no list of axes is provided.
    reInitializereinitialize plot for replotting.
    destroyReleases all resources occupied by the plot
    replotDoes a reinitialization of the plot followed by a redraw.
    redrawEmpties the plot target div and redraws the plot.
    drawDraws all elements of the plot into the container.
    drawSeriesRedraws all or just one series on the plot.
    moveSeriesToFrontThis method requires jQuery 1.4+ Moves the specified series canvas in front of all other series canvases.
    moveSeriesToBackThis method requires jQuery 1.4+ Moves the specified series canvas behind all other series canvases.
    restorePreviousSeriesOrderThis method requires jQuery 1.4+ Restore the series canvas order to its previous state.
    restoreOriginalSeriesOrderThis method requires jQuery 1.4+ Restore the series canvas order to its original order when the plot was created.
    + +

    Properties

    These properties are specified at the top of the options object like so:

    {
    +    axesDefaults:{min:0},
    +    series:[{color:'#6633dd'}],
    +    title: 'A Plot'
    +}
    + +

    data

    this.data = []

    user’s data.  Data should NOT be specified in the options object, but be passed in as the second argument to the $.jqplot() function.  The data property is described here soley for reference.  The data should be in the form of an array of 2D or 1D arrays like

    [ [[x1, y1], [x2, y2],...], [y1, y2, ...] ].
    + +

    axesDefaults

    default options that will be applied to all axes. see Axis for axes options.

    + +

    seriesDefaults

    seriesDefaults: {}, series:[] }

    default options that will be applied to all series. see Series for series options.

    + +

    series

    this.series = []

    Array of series object options. see Series for series specific options.

    + +

    axes

    this.axes = {xaxis: new Axis('xaxis'), yaxis: new Axis('yaxis'), x2axis: new Axis('x2axis'), y2axis: new Axis('y2axis'), y3axis: new Axis('y3axis'), y4axis: new Axis('y4axis'), y5axis: new Axis('y5axis'), y6axis: new Axis('y6axis'), y7axis: new Axis('y7axis'), y8axis: new Axis('y8axis'), y9axis: new Axis('y9axis')}

    up to 4 axes are supported, each with it’s own options, See Axis for axis specific options.

    + +

    grid

    this.grid = new Grid()

    See Grid for grid specific options.

    + +

    legend

    this.legend = new Legend()

    see <$.jqplot.TableLegendRenderer>

    + +

    seriesColors

    this.seriesColors = $.jqplot.config.defaultColors

    Ann array of CSS color specifications that will be applied, in order, to the series in the plot.  Colors will wrap around so, if their are more series than colors, colors will be reused starting at the beginning.  For pie charts, this specifies the colors of the slices.

    + +

    sortData

    this.sortData = true

    false to not sort the data passed in by the user.  Many bar, stakced and other graphs as well as many plugins depend on having sorted data.

    + +

    fontSize

    this.fontSize

    css spec for the font-size attribute.  Default for the entire plot.

    + +

    title

    this.title = new Title()

    Title object.  See Title for specific options.  As a shortcut, you can specify the title option as just a string like: title: ‘My Plot’ and this will create a new title object with the specified text.

    + +

    stackSeries

    this.stackSeries = false

    true or false, creates a stack or “mountain” plot.  Not all series renderers may implement this option.

    + +

    defaultAxisStart

    this.defaultAxisStart = 1

    1-D data series are internally converted into 2-D [x,y] data point arrays by jqPlot.  This is the default starting value for the missing x or y value.  The added data will be a monotonically increasing series (e.g.  [1, 2, 3, ...]) starting at this value.

    + +

    methods

    + +

    init

    this.init = function(target,
    data,
    options)

    sets the plot target, checks data and applies user options to plot.

    + +

    resetAxesScale

    this.resetAxesScale = function(axes,
    options)

    Reset the specified axes min, max, numberTicks and tickInterval properties to null or reset these properties on all axes if no list of axes is provided.

    Parameters

    axesBoolean to reset or not reset all axes or an array or object of axis names to reset.
    + +

    reInitialize

    this.reInitialize = function ()

    reinitialize plot for replotting. not called directly.

    + +

    destroy

    this.destroy = function()

    Releases all resources occupied by the plot

    + +

    replot

    this.replot = function(options)

    Does a reinitialization of the plot followed by a redraw.  Method could be used to interactively change plot characteristics and then replot.

    Parameters

    optionsOptions used for replotting.

    Properties

    clearfalse to not clear (empty) the plot container before replotting (default: true).
    resetAxestrue to reset all axes min, max, numberTicks and tickInterval setting so axes will rescale themselves. optionally pass in list of axes to reset (e.g.  [‘xaxis’, ‘y2axis’]) (default: false).
    + +

    redraw

    this.redraw = function(clear)

    Empties the plot target div and redraws the plot.  This enables plot data and properties to be changed and then to comletely clear the plot and redraw. redraw will not reinitialize any plot elements.  That is, axes will not be autoscaled and defaults will not be reapplied to any plot elements.  redraw is used primarily with zooming.

    Parameters

    clearfalse to not clear (empty) the plot container before redrawing (default: true).
    + +

    draw

    this.draw = function()

    Draws all elements of the plot into the container.  Does not clear the container before drawing.

    + +

    drawSeries

    this.drawSeries = function(options,
    idx)

    Redraws all or just one series on the plot.  No axis scaling is performed and no other elements on the plot are redrawn. options is an options object to pass on to the series renderers.  It can be an empty object {}.  idx is the series index to redraw if only one series is to be redrawn.

    + +

    moveSeriesToFront

    this.moveSeriesToFront = function (idx)

    This method requires jQuery 1.4+ Moves the specified series canvas in front of all other series canvases.  This effectively “draws” the specified series on top of all other series, although it is performed through DOM manipulation, no redrawing is performed.

    Parameters

    idx0 based index of the series to move.  This will be the index of the series as it was first passed into the jqplot function.
    + +

    moveSeriesToBack

    this.moveSeriesToBack = function (idx)

    This method requires jQuery 1.4+ Moves the specified series canvas behind all other series canvases.

    Parameters

    idx0 based index of the series to move.  This will be the index of the series as it was first passed into the jqplot function.
    + +

    restorePreviousSeriesOrder

    this.restorePreviousSeriesOrder = function ()

    This method requires jQuery 1.4+ Restore the series canvas order to its previous state.  Useful to put a series back where it belongs after moving it to the front.

    + +

    restoreOriginalSeriesOrder

    this.restoreOriginalSeriesOrder = function ()

    This method requires jQuery 1.4+ Restore the series canvas order to its original order when the plot was created.

    + +
    + + + + + + + + + + +
    This document is out of date.
    This document will help you understand how jqPlot’s options relate to the API documentation and the jqPlot object itself.
    this.show = false
    Wether to display the axis on the graph.
    this.tickRenderer = $.jqplot.AxisTickRenderer
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    A “tick” object showing the value of a tick/gridline on the plot.
    this.tickOptions = {}
    Options that will be passed to the tickRenderer, see $.jqplot.AxisTickRenderer options.
    this.labelRenderer = $.jqplot.AxisLabelRenderer
    A class of a rendering engine for creating an axis label.
    this.labelOptions = {}
    Options passed to the label renderer.
    this.label = null
    Label for the axis
    this.showLabel = true
    true to show the axis label.
    this.min=null
    minimum value of the axis (in data units, not pixels).
    this.max=null
    maximum value of the axis (in data units, not pixels).
    this.autoscale = false
    Autoscale the axis min and max values to provide sensible tick spacing.
    this.pad = 1.2
    Padding to extend the range above and below the data bounds.
    this.padMax = null
    Padding to extend the range above data bounds.
    this.padMin = null
    Padding to extend the range below data bounds.
    this.ticks = []
    1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis.
    this.numberTicks
    Desired number of ticks.
    this.tickInterval
    number of units between ticks.
    this.renderer = $.jqplot.LinearAxisRenderer
    A class of a rendering engine that handles tick generation, scaling input data to pixel grid units and drawing the axis element.
    this.rendererOptions = {}
    renderer specific options.
    this.showTicks = true
    Wether to show the ticks (both marks and labels) or not.
    this.showTickMarks = true
    Wether to show the tick marks (line crossing grid) or not.
    this.showMinorTicks = true
    Wether or not to show minor ticks.
    this.useSeriesColor = false
    Use the color of the first series associated with this axis for the tick marks and line bordering this axis.
    this.borderWidth = null
    width of line stroked at the border of the axis.
    this.borderColor = null
    color of the border adjacent to the axis.
    this.syncTicks = null
    true to try and synchronize tick spacing across multiple axes so that ticks and grid lines line up.
    this.tickSpacing = 75
    Approximate pixel spacing between ticks on graph.
    this.show = false
    Wether to display the legend on the graph.
    this.location = 'ne'
    Placement of the legend.
    this.labels = []
    Array of labels to use.
    this.showLabels = true
    true to show the label text on the legend.
    this.showSwatches = true
    true to show the color swatches on the legend.
    this.placement = "insideGrid"
    “insideGrid” places legend inside the grid area of the plot.
    this.xoffset = 0
    DEPRECATED.
    this.yoffset = 0
    DEPRECATED.
    this.border
    css spec for the border around the legend box.
    this.background
    css spec for the background of the legend box.
    this.textColor
    css color spec for the legend text.
    this.fontFamily
    css font-family spec for the legend text.
    this.fontSize
    css font-size spec for the legend text.
    this.rowSpacing = '0.5em'
    css padding-top spec for the rows in the legend.
    this.rendererOptions = {}
    renderer specific options passed to the renderer.
    this.marginTop = null
    CSS margin for the legend DOM element.
    this.marginRight = null
    CSS margin for the legend DOM element.
    this.marginBottom = null
    CSS margin for the legend DOM element.
    this.marginLeft = null
    CSS margin for the legend DOM element.
    this.text = text
    text of the title;
    this.show = true
    wether or not to show the title
    this.fontFamily
    css font-family spec for the text.
    this.fontSize
    css font-size spec for the text.
    this.textAlign
    css text-align spec for the text.
    this.textColor
    css color spec for the text.
    this.renderer = $.jqplot.DivTitleRenderer
    A class for creating a DOM element for the title, see $.jqplot.DivTitleRenderer.
    The default title renderer for jqPlot.
    this.rendererOptions = {}
    renderer specific options passed to the renderer.
    this.show = true
    wether or not to draw the series.
    this.xaxis = 'xaxis'
    which x axis to use with this series, either ‘xaxis’ or ‘x2axis’.
    this.yaxis = 'yaxis'
    which y axis to use with this series, either ‘yaxis’ or ‘y2axis’.
    this.renderer = $.jqplot.LineRenderer
    A class of a renderer which will draw the series, see $.jqplot.LineRenderer.
    The default line renderer for jqPlot, this class has no options beyond the Series class.
    this.rendererOptions = {}
    Options to pass on to the renderer.
    this.label = ''
    Line label to use in the legend.
    this.showLabel = true
    true to show label for this series in the legend.
    this.color
    css color spec for the series
    this.lineWidth = 2.5
    width of the line in pixels.
    this.lineJoin = 'round'
    Canvas lineJoin style between segments of series.
    this.lineCap = 'round'
    Canvas lineCap style at ends of line.
    this.shadow = true
    wether or not to draw a shadow on the line
    this.shadowAngle = 45
    Shadow angle in degrees
    this.shadowOffset = 1.25
    Shadow offset from line in pixels
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowAlpha = '0.1'
    Alpha channel transparency of shadow.
    this.breakOnNull = false
    Wether line segments should be be broken at null value.
    this.markerRenderer = $.jqplot.MarkerRenderer
    A class of a renderer which will draw marker (e.g.
    this.markerOptions = {}
    renderer specific options to pass to the markerRenderer, see $.jqplot.MarkerRenderer.
    The default jqPlot marker renderer, rendering the points on the line.
    this.showLine = true
    wether to actually draw the line or not.
    this.showMarker = true
    wether or not to show the markers at the data points.
    this.index
    0 based index of this series in the plot series array.
    this.fill = false
    true or false, wether to fill under lines or in bars.
    this.fillColor
    CSS color spec to use for fill under line.
    this.fillAlpha
    Alpha transparency to apply to the fill under the line.
    this.fillAndStroke = false
    If true will stroke the line (with color this.color) as well as fill under it.
    this.disableStack = false
    true to not stack this series with other series in the plot.
    this.neighborThreshold = 4
    how close or far (in pixels) the cursor must be from a point marker to detect the point.
    this.fillToZero = false
    true will force bar and filled series to fill toward zero on the fill Axis.
    this.fillToValue = 0
    fill a filled series to this value on the fill axis.
    this.fillAxis = 'y'
    Either ‘x’ or ‘y’.
    this.useNegativeColors = true
    true to color negative values differently in filled and bar charts.
    this.drawGridlines = true
    wether to draw the gridlines on the plot.
    this.gridLineColor = '#cccccc'
    color of the grid lines.
    this.gridLineWidth = 1.0
    width of the grid lines.
    this.background = '#fffdf6'
    css spec for the background color.
    this.borderColor = '#999999'
    css spec for the color of the grid border.
    this.borderWidth = 2.0
    width of the border in pixels.
    this.drawBorder = true
    True to draw border around grid.
    this.shadow = true
    wether to show a shadow behind the grid.
    this.shadowAngle = 45
    shadow angle in degrees
    this.shadowOffset = 1.5
    Offset of each shadow stroke from the border in pixels
    this.shadowWidth = 3
    width of the stoke for the shadow
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowColor = null
    an optional css color spec for the shadow in ‘rgba(n, n, n, n)’ form
    this.shadowAlpha = '0.07'
    Alpha channel transparency of shadow.
    this.renderer = $.jqplot.CanvasGridRenderer
    Instance of a renderer which will actually render the grid, see $.jqplot.CanvasGridRenderer.
    The default jqPlot grid renderer, creating a grid on a canvas element.
    this.rendererOptions = {}
    Options to pass on to the renderer, see $.jqplot.CanvasGridRenderer.
    this.data = []
    user’s data.
    seriesDefaults: {}, series:[] }
    default options that will be applied to all series.
    this.series = []
    Array of series object options.
    this.axes = {xaxis: new Axis('xaxis'), yaxis: new Axis('yaxis'), x2axis: new Axis('x2axis'), y2axis: new Axis('y2axis'), y3axis: new Axis('y3axis'), y4axis: new Axis('y4axis'), y5axis: new Axis('y5axis'), y6axis: new Axis('y6axis'), y7axis: new Axis('y7axis'), y8axis: new Axis('y8axis'), y9axis: new Axis('y9axis')}
    up to 4 axes are supported, each with it’s own options, See Axis for axis specific options.
    An individual axis object.
    this.grid = new Grid()
    See Grid for grid specific options.
    Object representing the grid on which the plot is drawn.
    this.legend = new Legend()
    see $.jqplot.TableLegendRenderer
    this.seriesColors = $.jqplot.config.defaultColors
    Ann array of CSS color specifications that will be applied, in order, to the series in the plot.
    this.sortData = true
    false to not sort the data passed in by the user.
    this.fontSize
    css spec for the font-size attribute.
    this.title = new Title()
    Title object.
    this.stackSeries = false
    true or false, creates a stack or “mountain” plot.
    this.defaultAxisStart = 1
    1-D data series are internally converted into 2-D [x,y] data point arrays by jqPlot.
    this.init = function(target,
    data,
    options)
    sets the plot target, checks data and applies user options to plot.
    this.resetAxesScale = function(axes,
    options)
    Reset the specified axes min, max, numberTicks and tickInterval properties to null or reset these properties on all axes if no list of axes is provided.
    this.reInitialize = function ()
    reinitialize plot for replotting.
    this.destroy = function()
    Releases all resources occupied by the plot
    this.replot = function(options)
    Does a reinitialization of the plot followed by a redraw.
    this.redraw = function(clear)
    Empties the plot target div and redraws the plot.
    this.draw = function()
    Draws all elements of the plot into the container.
    this.drawSeries = function(options,
    idx)
    Redraws all or just one series on the plot.
    this.moveSeriesToFront = function (idx)
    This method requires jQuery 1.4+ Moves the specified series canvas in front of all other series canvases.
    this.moveSeriesToBack = function (idx)
    This method requires jQuery 1.4+ Moves the specified series canvas behind all other series canvases.
    this.restorePreviousSeriesOrder = function ()
    This method requires jQuery 1.4+ Restore the series canvas order to its previous state.
    this.restoreOriginalSeriesOrder = function ()
    This method requires jQuery 1.4+ Restore the series canvas order to its original order when the plot was created.
    GNU GENERAL PUBLIC LICENSE Version 2, June 1991
    Copyright © 2009-2011 Chris Leonello
    The default jqPlot axis renderer, creating a numeric axis.
    An individual data series object.
    Plot Title object.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-divTitleRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-divTitleRenderer-js.html new file mode 100644 index 0000000000..07a41bb223 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-divTitleRenderer-js.html @@ -0,0 +1,39 @@ + + +$.jqplot.DivTitleRenderer + + + + + + + + + +

    The default title renderer for jqPlot.  This class has no options beyond the Title class.

    + +
    + + + + + + + + + + +
    Plot Title object.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-lineRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-lineRenderer-js.html new file mode 100644 index 0000000000..edf05373a6 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-lineRenderer-js.html @@ -0,0 +1,53 @@ + + +$.jqplot.LineRenderer + + + + + + + + + +

    The default line renderer for jqPlot, this class has no options beyond the Series class.  Draws series as a line.

    Summary
    $.jqplot.LineRendererThe default line renderer for jqPlot, this class has no options beyond the Series class.
    Properties
    highlightMouseOverTrue to highlight area on a filled plot when moused over.
    highlightMouseDownTrue to highlight when a mouse button is pressed over an area on a filled plot.
    highlightColorcolor to use when highlighting an area on a filled plot.
    Functions
    setGridDataconverts the user data values to grid coordinates and stores them in the gridData array.
    makeGridDataconverts any arbitrary data values to grid coordinates and returns them.
    + +

    Properties

    + +

    highlightMouseOver

    this.highlightMouseOver = true

    True to highlight area on a filled plot when moused over.  This must be false to enable highlightMouseDown to highlight when clicking on an area on a filled plot.

    + +

    highlightMouseDown

    this.highlightMouseDown = false

    True to highlight when a mouse button is pressed over an area on a filled plot.  This will be disabled if highlightMouseOver is true.

    + +

    highlightColor

    this.highlightColor = null

    color to use when highlighting an area on a filled plot.

    + +

    Functions

    + +

    setGridData

    $.jqplot.LineRenderer.prototype.setGridData = function(plot)

    converts the user data values to grid coordinates and stores them in the gridData array.  Called with scope of a series.

    + +

    makeGridData

    $.jqplot.LineRenderer.prototype.makeGridData = function(data,
    plot)

    converts any arbitrary data values to grid coordinates and returns them.  This method exists so that plugins can use a series’ linerenderer to generate grid data points without overwriting the grid data associated with that series.  Called with scope of a series.

    + +
    + + + + + + + + + + +
    An individual data series object.
    this.highlightMouseOver = true
    True to highlight area on a filled plot when moused over.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over an area on a filled plot.
    this.highlightColor = null
    color to use when highlighting an area on a filled plot.
    $.jqplot.LineRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    $.jqplot.LineRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-linearAxisRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-linearAxisRenderer-js.html new file mode 100644 index 0000000000..51d6919ba0 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-linearAxisRenderer-js.html @@ -0,0 +1,49 @@ + + +$.jqplot.LinearAxisRenderer + + + + + + + + + +

    The default jqPlot axis renderer, creating a numeric axis.  The renderer has no additional options beyond the Axis object.

    Summary
    $.jqplot.LinearAxisRendererThe default jqPlot axis renderer, creating a numeric axis.
    Properties
    breakPointsEXPERIMENTAL!! 
    breakTickLabelLabel to use at the axis break if breakPoints are specified.
    forceTickAt0This will ensure that there is always a tick mark at 0.
    forceTickAt100This will ensure that there is always a tick mark at 100.
    + +

    Properties

    + +

    breakPoints

    this.breakPoints = null

    EXPERIMENTAL!!  Use at your own risk!  Works only with linear axes and the default tick renderer.  Array of [start, stop] points to create a broken axis.  Broken axes have a “jump” in them, which is an immediate transition from a smaller value to a larger value.  Currently, axis ticks MUST be manually assigned if using breakPoints by using the axis ticks array option.

    + +

    breakTickLabel

    this.breakTickLabel = "&asymp

    Label to use at the axis break if breakPoints are specified.

    + +

    forceTickAt0

    this.forceTickAt0 = false

    This will ensure that there is always a tick mark at 0.  If data range is strictly positive or negative, this will force 0 to be inside the axis bounds unless the appropriate axis pad (pad, padMin or padMax) is set to 0, then this will force an axis min or max value at 0.  This has know effect when any of the following options are set: autoscale, min, max, numberTicks or tickInterval.

    + +

    forceTickAt100

    this.forceTickAt100 = false

    This will ensure that there is always a tick mark at 100.  If data range is strictly above or below 100, this will force 100 to be inside the axis bounds unless the appropriate axis pad (pad, padMin or padMax) is set to 0, then this will force an axis min or max value at 100.  This has know effect when any of the following options are set: autoscale, min, max, numberTicks or tickInterval.

    + +
    + + + + + + + + + + +
    this.breakPoints = null
    EXPERIMENTAL!! 
    this.breakTickLabel = "&asymp
    Label to use at the axis break if breakPoints are specified.
    this.forceTickAt0 = false
    This will ensure that there is always a tick mark at 0.
    this.forceTickAt100 = false
    This will ensure that there is always a tick mark at 100.
    An individual axis object.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-markerRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-markerRenderer-js.html new file mode 100644 index 0000000000..bee3ebde25 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-markerRenderer-js.html @@ -0,0 +1,65 @@ + + +$.jqplot.MarkerRenderer + + + + + + + + + +

    The default jqPlot marker renderer, rendering the points on the line.

    Summary
    $.jqplot.MarkerRendererThe default jqPlot marker renderer, rendering the points on the line.
    Properties
    showwether or not to show the marker.
    styleOne of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare
    lineWidthsize of the line for non-filled markers.
    sizeSize of the marker (diameter or circle, length of edge of square, etc.)
    colorcolor of marker.
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    shadowRendererRenderer that will draws the shadows on the marker.
    shapeRendererRenderer that will draw the marker.
    + +

    Properties

    + +

    show

    this.show = true

    wether or not to show the marker.

    + +

    style

    this.style = 'filledCircle'

    One of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare

    + +

    lineWidth

    this.lineWidth = 2

    size of the line for non-filled markers.

    + +

    size

    this.size = 9.0

    Size of the marker (diameter or circle, length of edge of square, etc.)

    + +

    color

    this.color = '#666666'

    color of marker.  Will be set to color of series by default on init.

    + +

    shadow

    this.shadow = true

    wether or not to draw a shadow on the line

    + +

    shadowAngle

    this.shadowAngle = 45

    Shadow angle in degrees

    + +

    shadowOffset

    this.shadowOffset = 1

    Shadow offset from line in pixels

    + +

    shadowDepth

    this.shadowDepth = 3

    Number of times shadow is stroked, each stroke offset shadowOffset from the last.

    + +

    shadowAlpha

    this.shadowAlpha = '0.07'

    Alpha channel transparency of shadow.  0 = transparent.

    + +

    shadowRenderer

    this.shadowRenderer = new $.jqplot.ShadowRenderer()

    Renderer that will draws the shadows on the marker.

    + +

    shapeRenderer

    this.shapeRenderer = new $.jqplot.ShapeRenderer()

    Renderer that will draw the marker.

    + +
    + + + + + + + + + + +
    this.show = true
    wether or not to show the marker.
    this.style = 'filledCircle'
    One of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare
    this.lineWidth = 2
    size of the line for non-filled markers.
    this.size = 9.0
    Size of the marker (diameter or circle, length of edge of square, etc.)
    this.color = '#666666'
    color of marker.
    this.shadow = true
    wether or not to draw a shadow on the line
    this.shadowAngle = 45
    Shadow angle in degrees
    this.shadowOffset = 1
    Shadow offset from line in pixels
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowAlpha = '0.07'
    Alpha channel transparency of shadow.
    this.shadowRenderer = new $.jqplot.ShadowRenderer()
    Renderer that will draws the shadows on the marker.
    this.shapeRenderer = new $.jqplot.ShapeRenderer()
    Renderer that will draw the marker.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-shadowRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-shadowRenderer-js.html new file mode 100644 index 0000000000..7d2bac82d5 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-shadowRenderer-js.html @@ -0,0 +1,61 @@ + + +$.jqplot.shadowRenderer + + + + + + + + + +

    The default jqPlot shadow renderer, rendering shadows behind shapes.

    Summary
    $.jqplot.shadowRendererThe default jqPlot shadow renderer, rendering shadows behind shapes.
    Properties
    angleAngle of the shadow in degrees.
    offsetPixel offset at the given shadow angle of each shadow stroke from the last stroke.
    alphaalpha transparency of shadow stroke.
    lineWidthwidth of the shadow line stroke.
    lineJoinHow line segments of the shadow are joined.
    lineCaphow ends of the shadow line are rendered.
    fillwhether to fill the shape.
    depthhow many times the shadow is stroked.
    isarcwether the shadow is an arc or not.
    drawdraws an transparent black (i.e.
    + +

    Properties

    + +

    angle

    this.angle = 45

    Angle of the shadow in degrees.  Measured counter-clockwise from the x axis.

    + +

    offset

    this.offset = 1

    Pixel offset at the given shadow angle of each shadow stroke from the last stroke.

    + +

    alpha

    this.alpha = 0.07

    alpha transparency of shadow stroke.

    + +

    lineWidth

    this.lineWidth = 1.5

    width of the shadow line stroke.

    + +

    lineJoin

    this.lineJoin = 'miter'

    How line segments of the shadow are joined.

    + +

    lineCap

    this.lineCap = 'round'

    how ends of the shadow line are rendered.

    + +

    fill

    this.fill = false

    whether to fill the shape.

    + +

    depth

    this.depth = 3

    how many times the shadow is stroked.  Each stroke will be offset by offset at angle degrees.

    + +

    isarc

    this.isarc = false

    wether the shadow is an arc or not.

    + +

    draw

    $.jqplot.ShadowRenderer.prototype.draw = function(ctx,
    points,
    options)

    draws an transparent black (i.e. gray) shadow.

    ctxcanvas drawing context
    pointsarray of points or [x, y, radius, start angle (rad), end angle (rad)]
    + +
    + + + + + + + + + + +
    this.angle = 45
    Angle of the shadow in degrees.
    this.offset = 1
    Pixel offset at the given shadow angle of each shadow stroke from the last stroke.
    this.alpha = 0.07
    alpha transparency of shadow stroke.
    this.lineWidth = 1.5
    width of the shadow line stroke.
    this.lineJoin = 'miter'
    How line segments of the shadow are joined.
    this.lineCap = 'round'
    how ends of the shadow line are rendered.
    this.fill = false
    whether to fill the shape.
    this.depth = 3
    how many times the shadow is stroked.
    this.isarc = false
    wether the shadow is an arc or not.
    $.jqplot.ShadowRenderer.prototype.draw = function(ctx,
    points,
    options)
    draws an transparent black (i.e.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-shapeRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-shapeRenderer-js.html new file mode 100644 index 0000000000..f9441ea064 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-shapeRenderer-js.html @@ -0,0 +1,63 @@ + + +$.jqplot.shapeRenderer + + + + + + + + + +

    The default jqPlot shape renderer.  Given a set of points will plot them and either stroke a line (fill = false) or fill them (fill = true).  If a filled shape is desired, closePath = true must also be set to close the shape.

    Summary
    $.jqplot.shapeRendererThe default jqPlot shape renderer.
    Properties
    lineJoinHow line segments of the shadow are joined.
    lineCaphow ends of the shadow line are rendered.
    fillwhether to fill the shape.
    isarcwether the shadow is an arc or not.
    fillRecttrue to draw shape as a filled rectangle.
    strokeRecttrue to draw shape as a stroked rectangle.
    clearRecttrue to cear a rectangle.
    strokeStylecss color spec for the stoke style
    fillStylecss color spec for the fill style.
    Functions
    drawdraws the shape.
    + +

    Properties

    + +

    lineJoin

    this.lineJoin = 'miter'

    How line segments of the shadow are joined.

    + +

    lineCap

    this.lineCap = 'round'

    how ends of the shadow line are rendered.

    + +

    fill

    this.fill = false

    whether to fill the shape.

    + +

    isarc

    this.isarc = false

    wether the shadow is an arc or not.

    + +

    fillRect

    this.fillRect = false

    true to draw shape as a filled rectangle.

    + +

    strokeRect

    this.strokeRect = false

    true to draw shape as a stroked rectangle.

    + +

    clearRect

    this.clearRect = false

    true to cear a rectangle.

    + +

    strokeStyle

    this.strokeStyle = '#999999'

    css color spec for the stoke style

    + +

    fillStyle

    this.fillStyle = '#999999'

    css color spec for the fill style.

    + +

    Functions

    + +

    draw

    $.jqplot.ShapeRenderer.prototype.draw = function(ctx,
    points,
    options)

    draws the shape.

    ctxcanvas drawing context
    pointsarray of points for shapes or [x, y, width, height] for rectangles or [x, y, radius, start angle (rad), end angle (rad)] for circles and arcs.
    + +
    + + + + + + + + + + +
    this.lineJoin = 'miter'
    How line segments of the shadow are joined.
    this.lineCap = 'round'
    how ends of the shadow line are rendered.
    this.fill = false
    whether to fill the shape.
    this.isarc = false
    wether the shadow is an arc or not.
    this.fillRect = false
    true to draw shape as a filled rectangle.
    this.strokeRect = false
    true to draw shape as a stroked rectangle.
    this.clearRect = false
    true to cear a rectangle.
    this.strokeStyle = '#999999'
    css color spec for the stoke style
    this.fillStyle = '#999999'
    css color spec for the fill style.
    $.jqplot.ShapeRenderer.prototype.draw = function(ctx,
    points,
    options)
    draws the shape.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/jqplot-themeEngine-js.html b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-themeEngine-js.html new file mode 100644 index 0000000000..189b777978 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/jqplot-themeEngine-js.html @@ -0,0 +1,190 @@ + + +$.jqplot.ThemeEngine + + + + + + + + + +

    Theme Engine provides a programatic way to change some of the more common jqplot styling options such as fonts, colors and grid options.  A theme engine instance is created with each plot.  The theme engine manages a collection of themes which can be modified, added to, or applied to the plot.

    The themeEngine class is not instantiated directly.  When a plot is initialized, the current plot options are scanned an a default theme named “Default” is created.  This theme is used as the basis for other themes added to the theme engine and is always available.

    A theme is a simple javascript object with styling parameters for various entities of the plot.  A theme has the form:

    {
    +    _name:f "Default",
    +    target: {
    +        backgroundColor: "transparent"
    +    },
    +    legend: {
    +        textColor: null,
    +        fontFamily: null,
    +        fontSize: null,
    +        border: null,
    +        background: null
    +    },
    +    title: {
    +        textColor: "rgb(102, 102, 102)",
    +        fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif",
    +        fontSize: "19.2px",
    +        textAlign: "center"
    +    },
    +    seriesStyles: {},
    +    series: [{
    +        color: "#4bb2c5",
    +        lineWidth: 2.5,
    +        shadow: true,
    +        fillColor: "#4bb2c5",
    +        showMarker: true,
    +        markerOptions: {
    +            color: "#4bb2c5",
    +            show: true,
    +            style: 'filledCircle',
    +            lineWidth: 1.5,
    +            size: 4,
    +            shadow: true
    +        }
    +    }],
    +    grid: {
    +        drawGridlines: true,
    +        gridLineColor: "#cccccc",
    +        gridLineWidth: 1,
    +        backgroundColor: "#fffdf6",
    +        borderColor: "#999999",
    +        borderWidth: 2,
    +        shadow: true
    +    },
    +    axesStyles: {
    +        label: {},
    +        ticks: {}
    +    },
    +    axes: {
    +        xaxis: {
    +            borderColor: "#999999",
    +            borderWidth: 2,
    +            ticks: {
    +                show: true,
    +                showGridline: true,
    +                showLabel: true,
    +                showMark: true,
    +                size: 4,
    +                textColor: "",
    +                whiteSpace: "nowrap",
    +                fontSize: "12px",
    +                fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif"
    +            },
    +            label: {
    +                textColor: "rgb(102, 102, 102)",
    +                whiteSpace: "normal",
    +                fontSize: "14.6667px",
    +                fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif",
    +                fontWeight: "400"
    +            }
    +        },
    +        yaxis: {
    +            borderColor: "#999999",
    +            borderWidth: 2,
    +            ticks: {
    +                show: true,
    +                showGridline: true,
    +                showLabel: true,
    +                showMark: true,
    +                size: 4,
    +                textColor: "",
    +                whiteSpace: "nowrap",
    +                fontSize: "12px",
    +                fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif"
    +            },
    +            label: {
    +                textColor: null,
    +                whiteSpace: null,
    +                fontSize: null,
    +                fontFamily: null,
    +                fontWeight: null
    +            }
    +        },
    +        x2axis: {...
    +        },
    +        ...
    +        y9axis: {...
    +        }
    +    }
    +}

    ”seriesStyles” is a style object that will be applied to all series in the plot.  It will forcibly override any styles applied on the individual series.  “axesStyles” is a style object that will be applied to all axes in the plot.  It will also forcibly override any styles on the individual axes.

    The example shown above has series options for a line series.  Options for other series types are shown below:

    Bar Series

    {
    +    color: "#4bb2c5",
    +    seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"],
    +    lineWidth: 2.5,
    +    shadow: true,
    +    barPadding: 2,
    +    barMargin: 10,
    +    barWidth: 15.09375,
    +    highlightColors: ["rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)"]
    +}

    Pie Series

    {
    +    seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"],
    +    padding: 20,
    +    sliceMargin: 0,
    +    fill: true,
    +    shadow: true,
    +    startAngle: 0,
    +    lineWidth: 2.5,
    +    highlightColors: ["rgb(129,201,214)", "rgb(240,189,104)", "rgb(214,202,165)", "rgb(137,180,158)", "rgb(168,180,137)", "rgb(180,174,89)", "rgb(180,113,161)", "rgb(129,141,236)", "rgb(227,205,120)", "rgb(255,138,76)", "rgb(76,169,219)", "rgb(215,126,190)", "rgb(220,232,135)", "rgb(200,167,96)", "rgb(103,202,235)", "rgb(208,154,215)"]
    +}

    Funnel Series

    {
    +    color: "#4bb2c5",
    +    lineWidth: 2,
    +    shadow: true,
    +    padding: {
    +        top: 20,
    +        right: 20,
    +        bottom: 20,
    +        left: 20
    +    },
    +    sectionMargin: 6,
    +    seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"],
    +    highlightColors: ["rgb(147,208,220)", "rgb(242,199,126)", "rgb(220,210,178)", "rgb(154,191,172)", "rgb(180,191,154)", "rgb(191,186,112)", "rgb(191,133,174)", "rgb(147,157,238)", "rgb(231,212,139)", "rgb(255,154,102)", "rgb(102,181,224)", "rgb(221,144,199)", "rgb(225,235,152)", "rgb(200,167,96)", "rgb(124,210,238)", "rgb(215,169,221)"]
    +}
    Summary
    $.jqplot.ThemeEngineTheme Engine provides a programatic way to change some of the more common jqplot styling options such as fonts, colors and grid options.
    Properties
    themeshash of themes managed by the theme engine.
    activeThemePointer to currently active theme
    methods
    getGet and return the named theme or the active theme if no name given.
    getThemeNamesReturn the list of theme names in this manager in alpha-numerical order.
    getThemesReturn a list of themes in alpha-numerical order by name.
    removeRemove the given theme from the themeEngine.
    newThemeCreate a new theme based on the default theme, adding it the themeEngine.
    renameRename a theme.
    copyCreate a copy of an existing theme in the themeEngine, adding it the themeEngine.
    + +

    Properties

    + +

    themes

    this.themes = {}

    hash of themes managed by the theme engine.  Indexed by theme name.

    + +

    activeTheme

    this.activeTheme=null

    Pointer to currently active theme

    + +

    methods

    + +

    get

    $.jqplot.ThemeEngine.prototype.get = function(name)

    Get and return the named theme or the active theme if no name given.

    parameter

    namename of theme to get.

    returns

    Theme instance of given name.

    + +

    getThemeNames

    $.jqplot.ThemeEngine.prototype.getThemeNames = function()

    Return the list of theme names in this manager in alpha-numerical order.

    parameter

    None

    returns

    A the list of theme names in this manager in alpha-numerical order.

    + +

    getThemes

    $.jqplot.ThemeEngine.prototype.getThemes = function()

    Return a list of themes in alpha-numerical order by name.

    parameter

    None

    returns

    A list of themes in alpha-numerical order by name.

    + +

    remove

    $.jqplot.ThemeEngine.prototype.remove = function(name)

    Remove the given theme from the themeEngine.

    parameters

    namename of the theme to remove.

    returns

    true on success, false on failure.

    + +

    newTheme

    $.jqplot.ThemeEngine.prototype.newTheme = function(name,
    obj)

    Create a new theme based on the default theme, adding it the themeEngine.

    parameters

    namename of the new theme.
    objoptional object of styles to be applied to this new theme.

    returns

    new Theme object.

    + +

    rename

    $.jqplot.ThemeEngine.prototype.rename = function (oldName,
    newName)

    Rename a theme.

    parameters

    oldNamecurrent name of the theme.
    newNamedesired name of the theme.

    returns

    new Theme object.

    + +

    copy

    $.jqplot.ThemeEngine.prototype.copy = function (sourceName,
    targetName,
    obj)

    Create a copy of an existing theme in the themeEngine, adding it the themeEngine.

    parameters

    sourceNamename of the existing theme.
    targetNamename of the copy.
    objoptional object of style parameter to apply to the new theme.

    returns

    new Theme object.

    + +
    + + + + + + + + + + +
    this.themes = {}
    hash of themes managed by the theme engine.
    this.activeTheme=null
    Pointer to currently active theme
    $.jqplot.ThemeEngine.prototype.get = function(name)
    Get and return the named theme or the active theme if no name given.
    $.jqplot.ThemeEngine.prototype.getThemeNames = function()
    Return the list of theme names in this manager in alpha-numerical order.
    $.jqplot.ThemeEngine.prototype.getThemes = function()
    Return a list of themes in alpha-numerical order by name.
    $.jqplot.ThemeEngine.prototype.remove = function(name)
    Remove the given theme from the themeEngine.
    $.jqplot.ThemeEngine.prototype.newTheme = function(name,
    obj)
    Create a new theme based on the default theme, adding it the themeEngine.
    $.jqplot.ThemeEngine.prototype.rename = function (oldName,
    newName)
    Rename a theme.
    $.jqplot.ThemeEngine.prototype.copy = function (sourceName,
    targetName,
    obj)
    Create a copy of an existing theme in the themeEngine, adding it the themeEngine.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/optionsTutorial-txt.html b/phpgwapi/js/jquery/jqplot/docs/files/optionsTutorial-txt.html new file mode 100644 index 0000000000..dba0033f25 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/optionsTutorial-txt.html @@ -0,0 +1,119 @@ + + +Options Tutorial + + + + + + + + + +

    This document will help you understand how jqPlot’s options relate to the API documentation and the jqPlot object itself.  For a listing of options available to jqPlot, see jqPlot Options in the jqPlotOptions.txt file.

    The key to effectively using jqPlot is understanding jqPlot’s options.  The online documentation is API documentation.  While it explains what attributes and methods various objects posses, it doesn’t explain how to use or set those attributes through options.  This tutorial will help explain that.

    Lets assume you are creating a plot like this:

    chart = $.jqplot('chart', dataSeries, optionsObj);

    First, note that you shouldn’t try to directly set attributes on the “chart” object (like chart.grid.shadow) after your call to $.jqplot().  At best this won’t do anything **(see below).  You should pass options in via the “optionsObj”.

    the optionsObj really represents the plot object (jqPlot object, not to be confused with the $.jqplot function which will create a jqPlot object).  Attributes you specify on that object will be merged with attributes in the jqPlot object.  The axes, legend, series, etc. are attributes on the jqPlot object.  The jqPlot/optionsObj object looks something like (only some attributes shown):

    jqPlot-|
    +       |-seriesColors
    +       |-textColor
    +       |-fontFamily
    +       |-fontSize
    +       |-stackSeries
    +       |-series(Array)-|
    +       |               |-Series1-|
    +       |               |         |-lineWidth
    +       |               |         |-shadow
    +       |               |         |-showLine
    +       |               |         |-showMarker
    +       |               |         |-color
    +       |               |-Series2...
    +       |               |-...
    +       |               |-SeriesN
    +       |
    +       |-grid(Object)-|
    +       |              |-drawGridLines
    +       |              |-background
    +       |              |-borderColor
    +       |              |-borderWidth
    +       |              |-shadow
    +       |
    +       |-title(Object)-|
    +       |               |-text
    +       |               |-show
    +       |               |-fontFamily
    +       |               |-fontSize
    +       |               |-textAlign
    +       |               |-textColor
    +       |
    +       |-axes(Object)-|
    +       |              |-xais-|
    +       |              |      |-min
    +       |              |      |-max
    +       |              |      |-numberTicks
    +       |              |      |-showTicks
    +       |              |      |-showTickMarks
    +       |              |      |-pad
    +       |
    +       | ... and so on

    The optionsObj should follow the same construction as if it were a jqPlot object (with some exceptions/shortcuts I’ll mention in a moment).  So generally, when you see something like “this.drawGridLines” in the grid properties in the docs, just replace “this” with “grid” in your options object.  So it becomes optionsObj.grid.drawGridLines.  Do likewise with the other objects in the plot, replacing “this”, with the respective attribute on the plot like “legend” or “title”.  Series and Axes are handled a little different, because series is an array and axes has 4 distinct children “xaxis”, “yaxis”, “x2axis” and “y2axis”.

    So, to remove the shadow from the grid and change the grid border size you would do:

    optionObj = {grid:{shadow:false, borderWidth:9.0}};

    To do the same as above but also make all the text in the plot red you would do:

    optionObj = {
    +   textColor:"#ff0000",
    +   grid:{shadow:false, borderWidth:9.0}
    +}

    Here is a more deeply nested example.  Say you want to specify a min and max on your y axis and use a specific color for your second series.  That would look like:

    optionsObj = {
    +   axes:{yaxis:{min:5, max:230}},
    +   series:[{},{color:"#33ff66"}]
    +}

    Note that series options are an array in order of the series data you sent in to your plot.  To get to the second series, you have to put an object (even if empty) in place of the first series.

    There is a handy shortcut to assign options to all axes or all series at one go.  Use axesDefaults and seriesDefaults.  So, if you wanted both x and y axes to start at 0 and you wanted all series to not show markers, you could do:

    optionsObj = {axesDefaults:{min:0}, seriesDefaults:{showMarker:false}}

    Another shortcut is for the plot title.  Normally, you would assign options to the title as an object.  If you specify a title option as a string, it will assign that to the title.text property automatically.  So these two are equivalent:

    optionsObj = {title:{text:"My Plot"}}

    and

    optionsObj = {title:"My Plot"}

    Where things need more explaination is with renderers, plugins and their options.  Briefly, what’s renderer, what’s a plugin.

    A renderer is an object that is used to draw something and gets attached to an existing object in the plot in order to draw it.  A plugin does more than just provide drawing functionality to an object.  It will do more like calculate a trend line, change the cursor, provide event driven functionality, etc.  I consider renderers plugins, but plugins don’t have to be renderers.

    So, how do you use renderers, plugins, and specify their options?  Some common renderes are for bar charts and category axes.  If you want to render your series as a bar chart with each set of bars showing up in a category on the x axis, you do:

    optionsObj = {
    +   seriesDefaults:{renderer:$.jqplot.BarRenderer},
    +   axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}}
    +}

    This replaces the default renderer used for all series in the plot with a bar renderer and the x axis default renderer (but not any other axis) with a category renderer.

    Now, how would I assign options to those renderers?  The renderer’s attributes may not be present in the pre-existing jqPlot object, they may be specific to the renderer.  This is done through the “rendererOptions” option on the appropriate object.  So, if I wanted my bars to be 25 pixels wide, I would do:

    optionsObj = {
    +   seriesDefaults:{
    +       renderer:$.jqplot.BarRenderer},
    +       rendererOptions:{
    +           barWidth:25
    +       },
    +   axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}}
    +}

    Again, this is using the “seriesDefaults” option, which will apply options to all series in the plot.  You could do the same on any particular series in the plot through the “series” options array.

    Plugins are free to add their own options.  For example, the highlighter plugin has it’s own set of options that are unique to it.  As a result, it responds to options placed in the “highlighter” attribute of your options object.  So, if I wanted to change the highlighter tooltip to fade in and out slowly and be positioned directly above the point I’m highlighting:

    optionsObj = {
    +    highlighter:{tooltipFadeSpeed:'slow', tooltipLocation:'n'}
    +}

    Other plugins, like dragable and trendlines, add their options in with the series.  This is because both of those plugins can have different options for different series in the plot.  So, if you wanted to specify the color of the dragable and constrain it to drag only on the x axis as well as specify the color of the trend line you could do:

    series:[{
    +    dragable: {
    +        color: '#ff3366',
    +        constrainTo: 'x'
    +    },
    +    trendline: {
    +        color: '#cccccc'
    +    }
    +}]

    This would apply those options to the first series only.  If you had 2 series and wanted to turn off dragging and trend lines on the second series, you could do:

    series:[{
    +    dragable: {
    +        color: '#ff3366',
    +        constrainTo: 'x'
    +    },
    +    trendline: {
    +        color: '#cccccc'
    +    }
    +}, {
    +   isDragable: false,
    +   trendline:{
    +       show: false
    +   }
    +}]

    Note, series dragability is turned off with the “isDragable” option directly on the series itself, not with a suboption of “dragable”.  This may be improved in the future.

    I hope this is helpful.  A few key points to remember:

    • When you see “this” in the api docs, you generally replace it with the name of the object (in lowercase) you are looking at in your options object.
    • seriesDefaults and axesDefaults are convenient shortcuts.
    • to assign options to a renderer, generally use the “rendererOptions”
    • plugins may add their own options attribute, like “highlighter” or “cursor”.

    ** Note: you can set attributes after the plot is created (like plot.grid.shadow = false), but you’ll have to issue the appropriate calls to possibly reinitialize and redraw the plot.  jqPlot can definitely handle this to change the plot after creation (this is how the dragable plugin updates the plot data and the trend line plugin recomputes itself when data changes).  This hasn’t been documented yet, however.

    + +
    + + + + + + + + + + +
    This document is out of date.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-BezierCurveRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-BezierCurveRenderer-js.html new file mode 100644 index 0000000000..937a54068f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-BezierCurveRenderer-js.html @@ -0,0 +1,45 @@ + + +$.jqplot.BezierCurveRenderer.js + + + + + + + + + +

    Renderer which draws lines as stacked bezier curves.  Data for the line will not be specified as an array of [x, y] data point values, but as a an array of [start piont, bezier curve] So, the line is specified as: [[xstart, ystart], [cp1x, cp1y, cp2x, cp2y, xend, yend]].

    Summary
    $.jqplot.BezierCurveRenderer.jsRenderer which draws lines as stacked bezier curves.
    Functions
    setGridDataconverts the user data values to grid coordinates and stores them in the gridData array.
    makeGridDataconverts any arbitrary data values to grid coordinates and returns them.
    + +

    Functions

    + +

    setGridData

    $.jqplot.BezierCurveRenderer.prototype.setGridData = function(plot)

    converts the user data values to grid coordinates and stores them in the gridData array.  Called with scope of a series.

    + +

    makeGridData

    $.jqplot.BezierCurveRenderer.prototype.makeGridData = function(data,
    plot)

    converts any arbitrary data values to grid coordinates and returns them.  This method exists so that plugins can use a series’ linerenderer to generate grid data points without overwriting the grid data associated with that series.  Called with scope of a series.

    + +
    + + + + + + + + + + +
    $.jqplot.BezierCurveRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    $.jqplot.BezierCurveRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-barRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-barRenderer-js.html new file mode 100644 index 0000000000..13f02114f1 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-barRenderer-js.html @@ -0,0 +1,67 @@ + + +$.jqplot.BarRenderer + + + + + + + + + +

    A plugin renderer for jqPlot to draw a bar plot.  Draws series as a line.

    Summary
    $.jqplot.BarRendererA plugin renderer for jqPlot to draw a bar plot.
    Properties
    barPaddingNumber of pixels between adjacent bars at the same axis value.
    barMarginNumber of pixels between groups of bars at adjacent axis values.
    barDirection‘vertical’ = up and down bars, ‘horizontal’ = side to side bars
    barWidthWidth of the bar in pixels (auto by devaul).
    shadowOffsetoffset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    shadowDepthnumber of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    shadowAlphatransparency of the shadow (0 = transparent, 1 = opaque)
    waterfalltrue to enable waterfall plot.
    groupsgroup bars into this many groups
    varyBarColortrue to color each bar of a series separately rather than have every bar of a given series the same color.
    highlightMouseOverTrue to highlight slice when moused over.
    highlightMouseDownTrue to highlight when a mouse button is pressed over a slice.
    highlightColorsan array of colors to use when highlighting a bar.
    + +

    Properties

    + +

    barPadding

    this.barPadding = 8

    Number of pixels between adjacent bars at the same axis value.

    + +

    barMargin

    this.barMargin = 10

    Number of pixels between groups of bars at adjacent axis values.

    + +

    barDirection

    this.barDirection = 'vertical'

    ’vertical’ = up and down bars, ‘horizontal’ = side to side bars

    + +

    barWidth

    this.barWidth = null

    Width of the bar in pixels (auto by devaul).  null = calculated automatically.

    + +

    shadowOffset

    this.shadowOffset = 2

    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.

    + +

    shadowDepth

    this.shadowDepth = 5

    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.

    + +

    shadowAlpha

    this.shadowAlpha = 0.08

    transparency of the shadow (0 = transparent, 1 = opaque)

    + +

    waterfall

    this.waterfall = false

    true to enable waterfall plot.

    + +

    groups

    this.groups = 1

    group bars into this many groups

    + +

    varyBarColor

    this.varyBarColor = false

    true to color each bar of a series separately rather than have every bar of a given series the same color.  If used for non-stacked multiple series bar plots, user should specify a separate ‘seriesColors’ array for each series.  Otherwise, each series will set their bars to the same color array.  This option has no Effect for stacked bar charts and is disabled.

    + +

    highlightMouseOver

    this.highlightMouseOver = true

    True to highlight slice when moused over.  This must be false to enable highlightMouseDown to highlight when clicking on a slice.

    + +

    highlightMouseDown

    this.highlightMouseDown = false

    True to highlight when a mouse button is pressed over a slice.  This will be disabled if highlightMouseOver is true.

    + +

    highlightColors

    this.highlightColors = []

    an array of colors to use when highlighting a bar.

    + +
    + + + + + + + + + + +
    this.barPadding = 8
    Number of pixels between adjacent bars at the same axis value.
    this.barMargin = 10
    Number of pixels between groups of bars at adjacent axis values.
    this.barDirection = 'vertical'
    ‘vertical’ = up and down bars, ‘horizontal’ = side to side bars
    this.barWidth = null
    Width of the bar in pixels (auto by devaul).
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowAlpha = 0.08
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.waterfall = false
    true to enable waterfall plot.
    this.groups = 1
    group bars into this many groups
    this.varyBarColor = false
    true to color each bar of a series separately rather than have every bar of a given series the same color.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightColors = []
    an array of colors to use when highlighting a bar.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-blockRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-blockRenderer-js.html new file mode 100644 index 0000000000..e3a0c97aca --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-blockRenderer-js.html @@ -0,0 +1,53 @@ + + +$.jqplot.BlockRenderer + + + + + + + + + +

    Plugin renderer to draw a x-y block chart.  A Block chart has data points displayed as colored squares with a text label inside.  Data must be supplied in the form:

    [[x1, y1, "label 1", {css}], [x2, y2, "label 2", {css}], ...]

    The label and css object are optional.  If the label is ommitted, the box will collapse unless a css height and/or width is specified.

    The css object is an object specifying css properties such as:

    {background:'#4f98a5', border:'3px solid gray', padding:'1px'}

    Note that css properties specified with the data point override defaults specified with the series.

    Summary
    $.jqplot.BlockRendererPlugin renderer to draw a x-y block chart.
    Properties
    cssdefault css styles that will be applied to all data blocks.
    escapeHtmltrue to escape html in the box label.
    insertBreakstrue to turn spaces in data block label into html breaks <br />.
    varyBlockColorstrue to vary the color of each block in this series according to the seriesColors array.
    Methods
    moveBlockMoves an individual block.
    + +

    Properties

    + +

    css

    this.css = {padding:'2px', border:'1px solid #999', textAlign:'center'}

    default css styles that will be applied to all data blocks. these values will be overridden by css styles supplied with the individulal data points.

    + +

    escapeHtml

    this.escapeHtml = false

    true to escape html in the box label.

    + +

    insertBreaks

    this.insertBreaks = true

    true to turn spaces in data block label into html breaks <br />.

    + +

    varyBlockColors

    this.varyBlockColors = false

    true to vary the color of each block in this series according to the seriesColors array.  False to set each block to the color specified on this series.  This has no effect if a css background color option is specified in the renderer css options.

    + +

    Methods

    + +

    moveBlock

    this.moveBlock = function (idx,
    x,
    y,
    duration)

    Moves an individual block.  More efficient than redrawing the whole series by calling plot.drawSeries().  Properties: idx - the 0 based index of the block or point in this series. x - the x coordinate in data units (value on x axis) to move the block to. y - the y coordinate in data units (value on the y axis) to move the block to. duration - optional parameter to create an animated movement.  Can be a number (higher is slower animation) or ‘fast’, ‘normal’ or ‘slow’.  If not provided, the element is moved without any animation.

    + +
    + + + + + + + + + + +
    this.css = {padding:'2px', border:'1px solid #999', textAlign:'center'}
    default css styles that will be applied to all data blocks.
    this.escapeHtml = false
    true to escape html in the box label.
    this.insertBreaks = true
    true to turn spaces in data block label into html breaks br /.
    this.varyBlockColors = false
    true to vary the color of each block in this series according to the seriesColors array.
    this.moveBlock = function (idx,
    x,
    y,
    duration)
    Moves an individual block.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-bubbleRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-bubbleRenderer-js.html new file mode 100644 index 0000000000..d2e71cd9a1 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-bubbleRenderer-js.html @@ -0,0 +1,71 @@ + + +$.jqplot.BubbleRenderer + + + + + + + + + +

    Plugin renderer to draw a bubble chart.  A Bubble chart has data points displayed as colored circles with an optional text label inside.  To use the bubble renderer, you must include the bubble renderer like:

    <script language="javascript" type="text/javascript" src="../src/plugins/jqplot.bubbleRenderer.js"></script>

    Data must be supplied in the form:

    [[x1, y1, r1, <label or {label:'text', color:color}>], ...]

    where the label or options object is optional.

    Note that all bubble colors will be the same unless the “varyBubbleColors” option is set to true.  Colors can be specified in the data array or in the seriesColors array option on the series.  If no colors are defined, the default jqPlot series of 16 colors are used.  Colors are automatically cycled around again if there are more bubbles than colors.

    Bubbles are autoscaled by default to fit within the chart area while maintaining relative sizes.  If the “autoscaleBubbles” option is set to false, the r(adius) values in the data array a treated as literal pixel values for the radii of the bubbles.

    Properties are passed into the bubble renderer in the rendererOptions object of the series options like:

    seriesDefaults: {
    +    renderer: $.jqplot.BubbleRenderer,
    +    rendererOptions: {
    +        bubbleAlpha: 0.7,
    +        varyBubbleColors: false
    +    }
    +}
    Summary
    $.jqplot.BubbleRendererPlugin renderer to draw a bubble chart.
    Properties
    varyBubbleColorsTrue to vary the color of each bubble in this series according to the seriesColors array.
    autoscaleBubblesTrue to scale the bubble radius based on plot size.
    autoscaleMultiplierMultiplier the bubble size if autoscaleBubbles is true.
    autoscalePointsFactorFactor which decreases bubble size based on how many bubbles on on the chart.
    escapeHtmlTrue to escape html in bubble label text.
    highlightMouseOverTrue to highlight bubbles when moused over.
    highlightMouseDownTrue to highlight when a mouse button is pressed over a bubble.
    highlightColorsAn array of colors to use when highlighting a slice.
    bubbleAlphaAlpha transparency to apply to all bubbles in this series.
    highlightAlphaAlpha transparency to apply when highlighting bubble.
    bubbleGradientsTrue to color the bubbles with gradient fills instead of flat colors.
    showLabelsTrue to show labels on bubbles (if any), false to not show.
    + +

    Properties

    + +

    varyBubbleColors

    this.varyBubbleColors = true

    True to vary the color of each bubble in this series according to the seriesColors array.  False to set each bubble to the color specified on this series.  This has no effect if a css background color option is specified in the renderer css options.

    + +

    autoscaleBubbles

    this.autoscaleBubbles = true

    True to scale the bubble radius based on plot size.  False will use the radius value as provided as a raw pixel value for bubble radius.

    + +

    autoscaleMultiplier

    this.autoscaleMultiplier = 1.0

    Multiplier the bubble size if autoscaleBubbles is true.

    + +

    autoscalePointsFactor

    this.autoscalePointsFactor = -0.07

    Factor which decreases bubble size based on how many bubbles on on the chart.  0 means no adjustment for number of bubbles.  Negative values will decrease size of bubbles as more bubbles are added.  Values between 0 and -0.2 should work well.

    + +

    escapeHtml

    this.escapeHtml = true

    True to escape html in bubble label text.

    + +

    highlightMouseOver

    this.highlightMouseOver = true

    True to highlight bubbles when moused over.  This must be false to enable highlightMouseDown to highlight when clicking on a slice.

    + +

    highlightMouseDown

    this.highlightMouseDown = false

    True to highlight when a mouse button is pressed over a bubble.  This will be disabled if highlightMouseOver is true.

    + +

    highlightColors

    this.highlightColors = []

    An array of colors to use when highlighting a slice.  Calculated automatically if not supplied.

    + +

    bubbleAlpha

    this.bubbleAlpha = 1.0

    Alpha transparency to apply to all bubbles in this series.

    + +

    highlightAlpha

    this.highlightAlpha = null

    Alpha transparency to apply when highlighting bubble.  Set to value of bubbleAlpha by default.

    + +

    bubbleGradients

    this.bubbleGradients = false

    True to color the bubbles with gradient fills instead of flat colors.  NOT AVAILABLE IN IE due to lack of excanvas support for radial gradient fills. will be ignored in IE.

    + +

    showLabels

    this.showLabels = true

    True to show labels on bubbles (if any), false to not show.

    + +
    + + + + + + + + + + +
    this.varyBubbleColors = true
    True to vary the color of each bubble in this series according to the seriesColors array.
    this.autoscaleBubbles = true
    True to scale the bubble radius based on plot size.
    this.autoscaleMultiplier = 1.0
    Multiplier the bubble size if autoscaleBubbles is true.
    this.autoscalePointsFactor = -0.07
    Factor which decreases bubble size based on how many bubbles on on the chart.
    this.escapeHtml = true
    True to escape html in bubble label text.
    this.highlightMouseOver = true
    True to highlight bubbles when moused over.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a bubble.
    this.highlightColors = []
    An array of colors to use when highlighting a slice.
    this.bubbleAlpha = 1.0
    Alpha transparency to apply to all bubbles in this series.
    this.highlightAlpha = null
    Alpha transparency to apply when highlighting bubble.
    this.bubbleGradients = false
    True to color the bubbles with gradient fills instead of flat colors.
    this.showLabels = true
    True to show labels on bubbles (if any), false to not show.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasAxisLabelRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasAxisLabelRenderer-js.html new file mode 100644 index 0000000000..c1c5d0c085 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasAxisLabelRenderer-js.html @@ -0,0 +1,63 @@ + + +$.jqplot.CanvasAxisLabelRenderer + + + + + + + + + +

    Renderer to draw axis labels with a canvas element to support advanced featrues such as rotated text.  This renderer uses a separate rendering engine to draw the text on the canvas.  Two modes of rendering the text are available.  If the browser has native font support for canvas fonts (currently Mozila 3.5 and Safari 4), you can enable text rendering with the canvas fillText method.  You do so by setting the “enableFontSupport” option to true.

    Browsers lacking native font support will have the text drawn on the canvas using the Hershey font metrics.  Even if the “enableFontSupport” option is true non-supporting browsers will still render with the Hershey font.

    Summary
    $.jqplot.CanvasAxisLabelRendererRenderer to draw axis labels with a canvas element to support advanced featrues such as rotated text.
    Properties
    angleangle of text, measured clockwise from x axis.
    showwether or not to show the tick (mark and label).
    showLabelwether or not to show the label.
    labellabel for the axis.
    fontFamilyCSS spec for the font-family css attribute.
    fontSizeCSS spec for font size.
    fontWeight
    fontStretchMultiplier to condense or expand font width.
    textColorcss spec for the color attribute.
    enableFontSupporttrue to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
    pt2pxPoint to pixel scaling factor, used for computing height of bounding box around a label.
    + +

    Properties

    + +

    angle

    this.angle = 0

    angle of text, measured clockwise from x axis.

    + +

    show

    this.show = true

    wether or not to show the tick (mark and label).

    + +

    showLabel

    this.showLabel = true

    wether or not to show the label.

    + +

    label

    this.label = ''

    label for the axis.

    + +

    fontFamily

    this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'

    CSS spec for the font-family css attribute.  Applies only to browsers supporting native font rendering in the canvas tag.  Currently Mozilla 3.5 and Safari 4.

    + +

    fontSize

    this.fontSize = '11pt'

    CSS spec for font size.

    + +

    fontWeight

    this.fontWeight = 'normal'
    CSS spec for fontWeight: normal, bold, bolder, lighter or a number 100900
    + +

    fontStretch

    this.fontStretch = 1.0

    Multiplier to condense or expand font width.  Applies only to browsers which don’t support canvas native font rendering.

    + +

    textColor

    this.textColor = '#666666'

    css spec for the color attribute.

    + +

    enableFontSupport

    this.enableFontSupport = true

    true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.  If true, label will be drawn with canvas tag native support for fonts.  If false, label will be drawn with Hershey font metrics.

    + +

    pt2px

    this.pt2px = null

    Point to pixel scaling factor, used for computing height of bounding box around a label.  The labels text renderer has a default setting of 1.4, which should be suitable for most fonts.  Leave as null to use default.  If tops of letters appear clipped, increase this.  If bounding box seems too big, decrease.  This is an issue only with the native font renderering capabilities of Mozilla 3.5 and Safari 4 since they do not provide a method to determine the font height.

    + +
    + + + + + + + + + + +
    this.angle = 0
    angle of text, measured clockwise from x axis.
    this.show = true
    wether or not to show the tick (mark and label).
    this.showLabel = true
    wether or not to show the label.
    this.label = ''
    label for the axis.
    this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'
    CSS spec for the font-family css attribute.
    this.fontSize = '11pt'
    CSS spec for font size.
    this.fontWeight = 'normal'
    this.fontStretch = 1.0
    Multiplier to condense or expand font width.
    this.textColor = '#666666'
    css spec for the color attribute.
    this.enableFontSupport = true
    true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
    this.pt2px = null
    Point to pixel scaling factor, used for computing height of bounding box around a label.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasAxisTickRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasAxisTickRenderer-js.html new file mode 100644 index 0000000000..ee32c92d52 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasAxisTickRenderer-js.html @@ -0,0 +1,79 @@ + + +$.jqplot.CanvasAxisTickRenderer + + + + + + + + + +

    Renderer to draw axis ticks with a canvas element to support advanced featrues such as rotated text.  This renderer uses a separate rendering engine to draw the text on the canvas.  Two modes of rendering the text are available.  If the browser has native font support for canvas fonts (currently Mozila 3.5 and Safari 4), you can enable text rendering with the canvas fillText method.  You do so by setting the “enableFontSupport” option to true.

    Browsers lacking native font support will have the text drawn on the canvas using the Hershey font metrics.  Even if the “enableFontSupport” option is true non-supporting browsers will still render with the Hershey font.

    Summary
    $.jqplot.CanvasAxisTickRendererRenderer to draw axis ticks with a canvas element to support advanced featrues such as rotated text.
    Properties
    marktick mark on the axis.
    showMarkwether or not to show the mark on the axis.
    showGridlinewether or not to draw the gridline on the grid at this tick.
    isMinorTickif this is a minor tick.
    angleangle of text, measured clockwise from x axis.
    markSizeLength of the tick marks in pixels.
    showwether or not to show the tick (mark and label).
    showLabelwether or not to show the label.
    labelPosition‘auto’, ‘start’, ‘middle’ or ‘end’.
    formatterA class of a formatter for the tick text.
    formatStringstring passed to the formatter.
    prefixString to prepend to the tick label.
    fontFamilycss spec for the font-family css attribute.
    fontSizeCSS spec for font size.
    fontWeightCSS spec for fontWeight
    fontStretchMultiplier to condense or expand font width.
    textColorcss spec for the color attribute.
    enableFontSupporttrue to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
    pt2pxPoint to pixel scaling factor, used for computing height of bounding box around a label.
    + +

    Properties

    + +

    mark

    this.mark = 'outside'

    tick mark on the axis.  One of ‘inside’, ‘outside’, ‘cross’, ‘’ or null.

    + +

    showMark

    this.showMark = true

    wether or not to show the mark on the axis.

    + +

    showGridline

    this.showGridline = true

    wether or not to draw the gridline on the grid at this tick.

    + +

    isMinorTick

    this.isMinorTick = false

    if this is a minor tick.

    + +

    angle

    this.angle = 0

    angle of text, measured clockwise from x axis.

    + +

    markSize

    this.markSize = 4

    Length of the tick marks in pixels.  For ‘cross’ style, length will be stoked above and below axis, so total length will be twice this.

    + +

    show

    this.show = true

    wether or not to show the tick (mark and label).

    + +

    showLabel

    this.showLabel = true

    wether or not to show the label.

    + +

    labelPosition

    this.labelPosition = 'auto'

    ’auto’, ‘start’, ‘middle’ or ‘end’.  Whether tick label should be positioned so the start, middle, or end of the tick mark.

    + +

    formatter

    this.formatter = $.jqplot.DefaultTickFormatter

    A class of a formatter for the tick text.  The default $.jqplot.DefaultTickFormatter uses sprintf.

    + +

    formatString

    this.formatString = ''

    string passed to the formatter.

    + +

    prefix

    this.prefix = ''

    String to prepend to the tick label.  Prefix is prepended to the formatted tick label.

    + +

    fontFamily

    this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'

    css spec for the font-family css attribute.

    + +

    fontSize

    this.fontSize = '10pt'

    CSS spec for font size.

    + +

    fontWeight

    this.fontWeight = 'normal'

    CSS spec for fontWeight

    + +

    fontStretch

    this.fontStretch = 1.0

    Multiplier to condense or expand font width.  Applies only to browsers which don’t support canvas native font rendering.

    + +

    textColor

    this.textColor = '#666666'

    css spec for the color attribute.

    + +

    enableFontSupport

    this.enableFontSupport = true

    true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.  If true, tick label will be drawn with canvas tag native support for fonts.  If false, tick label will be drawn with Hershey font metrics.

    + +

    pt2px

    this.pt2px = null

    Point to pixel scaling factor, used for computing height of bounding box around a label.  The labels text renderer has a default setting of 1.4, which should be suitable for most fonts.  Leave as null to use default.  If tops of letters appear clipped, increase this.  If bounding box seems too big, decrease.  This is an issue only with the native font renderering capabilities of Mozilla 3.5 and Safari 4 since they do not provide a method to determine the font height.

    + +
    + + + + + + + + + + +
    this.mark = 'outside'
    tick mark on the axis.
    this.showMark = true
    wether or not to show the mark on the axis.
    this.showGridline = true
    wether or not to draw the gridline on the grid at this tick.
    this.isMinorTick = false
    if this is a minor tick.
    this.angle = 0
    angle of text, measured clockwise from x axis.
    this.markSize = 4
    Length of the tick marks in pixels.
    this.show = true
    wether or not to show the tick (mark and label).
    this.showLabel = true
    wether or not to show the label.
    this.labelPosition = 'auto'
    ‘auto’, ‘start’, ‘middle’ or ‘end’.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    this.formatString = ''
    string passed to the formatter.
    this.prefix = ''
    String to prepend to the tick label.
    this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'
    css spec for the font-family css attribute.
    this.fontSize = '10pt'
    CSS spec for font size.
    this.fontWeight = 'normal'
    CSS spec for fontWeight
    this.fontStretch = 1.0
    Multiplier to condense or expand font width.
    this.textColor = '#666666'
    css spec for the color attribute.
    this.enableFontSupport = true
    true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
    this.pt2px = null
    Point to pixel scaling factor, used for computing height of bounding box around a label.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasOverlay-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasOverlay-js.html new file mode 100644 index 0000000000..9ee5093656 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-canvasOverlay-js.html @@ -0,0 +1,197 @@ + + +$.jqplot.CanvasOverlay + + + + + + + + + +
    Summary
    $.jqplot.CanvasOverlay
    Properties
    objects
    LineA straight line.
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    start[x, y] coordinates for the start of the line.
    stop[x, y] coordinates for the end of the line.
    HorizontalLineA straight horizontal line.
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    yy value to position the line
    xminx value for the start of the line, null to scale to axis min.
    xmaxx value for the end of the line, null to scale to axis max.
    DashedHorizontalLineA straight dashed horizontal line.
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    dashPatternArray of line, space settings in pixels.
    VerticalLineA straight vertical line.
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    DashedVerticalLineA straight dashed vertical line.
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    dashPatternArray of line, space settings in pixels.
    + +

    Properties

    + +

    objects

    this.objects = []
    + +

    Line

    A straight line.

    Summary
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    start[x, y] coordinates for the start of the line.
    stop[x, y] coordinates for the end of the line.
    + +

    Properties

    + +

    name

    Optional name for this overlay object.  Can be later used to retrieve the object by name.

    + +

    show

    true to show (draw), false to not draw.

    + +

    lineWidth

    Width of the line.

    + +

    lineCap

    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]

    + +

    color

    color of the line

    + +

    shadow

    wether or not to draw a shadow on the line

    + +

    shadowAngle

    Shadow angle in degrees

    + +

    shadowOffset

    Shadow offset from line in pixels

    + +

    shadowDepth

    Number of times shadow is stroked, each stroke offset shadowOffset from the last.

    + +

    shadowAlpha

    Alpha channel transparency of shadow.  0 = transparent.

    + +

    xaxis

    X axis to use for positioning/scaling the line.

    + +

    yaxis

    Y axis to use for positioning/scaling the line.

    + +

    start

    [x, y] coordinates for the start of the line.

    + +

    stop

    stop: [] }

    [x, y] coordinates for the end of the line.

    + +

    HorizontalLine

    A straight horizontal line.

    Summary
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    yy value to position the line
    xminx value for the start of the line, null to scale to axis min.
    xmaxx value for the end of the line, null to scale to axis max.
    + +

    Properties

    + +

    name

    Optional name for this overlay object.  Can be later used to retrieve the object by name.

    + +

    show

    true to show (draw), false to not draw.

    + +

    lineWidth

    Width of the line.

    + +

    lineCap

    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]

    + +

    color

    color of the line

    + +

    shadow

    wether or not to draw a shadow on the line

    + +

    shadowAngle

    Shadow angle in degrees

    + +

    shadowOffset

    Shadow offset from line in pixels

    + +

    shadowDepth

    Number of times shadow is stroked, each stroke offset shadowOffset from the last.

    + +

    shadowAlpha

    Alpha channel transparency of shadow.  0 = transparent.

    + +

    xaxis

    X axis to use for positioning/scaling the line.

    + +

    yaxis

    Y axis to use for positioning/scaling the line.

    + +

    y

    y value to position the line

    + +

    xmin

    x value for the start of the line, null to scale to axis min.

    + +

    xmax

    x value for the end of the line, null to scale to axis max.

    + +

    DashedHorizontalLine

    A straight dashed horizontal line.

    Summary
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    dashPatternArray of line, space settings in pixels.
    + +

    Properties

    + +

    name

    Optional name for this overlay object.  Can be later used to retrieve the object by name.

    + +

    show

    true to show (draw), false to not draw.

    + +

    lineWidth

    Width of the line.

    + +

    lineCap

    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]

    + +

    color

    color of the line

    + +

    shadow

    wether or not to draw a shadow on the line

    + +

    shadowAngle

    Shadow angle in degrees

    + +

    shadowOffset

    Shadow offset from line in pixels

    + +

    shadowDepth

    Number of times shadow is stroked, each stroke offset shadowOffset from the last.

    + +

    shadowAlpha

    Alpha channel transparency of shadow.  0 = transparent.

    + +

    xaxis

    X axis to use for positioning/scaling the line.

    + +

    yaxis

    Y axis to use for positioning/scaling the line.

    + +

    dashPattern

    dashPattern: [8,8] }

    Array of line, space settings in pixels.  Default is 8 pixel of line, 8 pixel of space.  Note, limit to a 2 element array b/c of bug with higher order arrays.

    + +

    VerticalLine

    A straight vertical line.

    Summary
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    + +

    Properties

    + +

    name

    Optional name for this overlay object.  Can be later used to retrieve the object by name.

    + +

    show

    true to show (draw), false to not draw.

    + +

    lineWidth

    Width of the line.

    + +

    lineCap

    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]

    + +

    color

    color of the line

    + +

    shadow

    wether or not to draw a shadow on the line

    + +

    shadowAngle

    Shadow angle in degrees

    + +

    shadowOffset

    Shadow offset from line in pixels

    + +

    shadowDepth

    Number of times shadow is stroked, each stroke offset shadowOffset from the last.

    + +

    shadowAlpha

    Alpha channel transparency of shadow.  0 = transparent.

    + +

    xaxis

    X axis to use for positioning/scaling the line.

    + +

    yaxis

    yaxis: 'yaxis', x: null, ymin: null, ymax: null, yOffset: '6px', // number or string. Number interpreted as units, string as pixels. yminOffset: null, ymaxOffset: null }

    Y axis to use for positioning/scaling the line.

    + +

    DashedVerticalLine

    A straight dashed vertical line.

    Summary
    Properties
    nameOptional name for this overlay object.
    showtrue to show (draw), false to not draw.
    lineWidthWidth of the line.
    lineCapType of ending placed on the line [‘round’, ‘butt’, ‘square’]
    colorcolor of the line
    shadowwether or not to draw a shadow on the line
    shadowAngleShadow angle in degrees
    shadowOffsetShadow offset from line in pixels
    shadowDepthNumber of times shadow is stroked, each stroke offset shadowOffset from the last.
    shadowAlphaAlpha channel transparency of shadow.
    xaxisX axis to use for positioning/scaling the line.
    yaxisY axis to use for positioning/scaling the line.
    dashPatternArray of line, space settings in pixels.
    + +

    Properties

    + +

    name

    Optional name for this overlay object.  Can be later used to retrieve the object by name.

    + +

    show

    true to show (draw), false to not draw.

    + +

    lineWidth

    Width of the line.

    + +

    lineCap

    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]

    + +

    color

    color of the line

    + +

    shadow

    wether or not to draw a shadow on the line

    + +

    shadowAngle

    Shadow angle in degrees

    + +

    shadowOffset

    Shadow offset from line in pixels

    + +

    shadowDepth

    Number of times shadow is stroked, each stroke offset shadowOffset from the last.

    + +

    shadowAlpha

    Alpha channel transparency of shadow.  0 = transparent.

    + +

    xaxis

    X axis to use for positioning/scaling the line.

    + +

    yaxis

    Y axis to use for positioning/scaling the line.

    + +

    dashPattern

    dashPattern: [8,8] }

    Array of line, space settings in pixels.  Default is 8 pixel of line, 8 pixel of space.  Note, limit to a 2 element array b/c of bug with higher order arrays.

    + +
    + + + + + + + + + + +
    this.objects = []
    stop: [] }
    [x, y] coordinates for the end of the line.
    dashPattern: [8,8] }
    Array of line, space settings in pixels.
    yaxis: 'yaxis', x: null, ymin: null, ymax: null, yOffset: '6px', // number or string. Number interpreted as units, string as pixels. yminOffset: null, ymaxOffset: null }
    Y axis to use for positioning/scaling the line.
    dashPattern: [8,8] }
    Array of line, space settings in pixels.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-categoryAxisRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-categoryAxisRenderer-js.html new file mode 100644 index 0000000000..83aa917416 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-categoryAxisRenderer-js.html @@ -0,0 +1,46 @@ + + +$.jqplot.CategoryAxisRenderer + + + + + + + + + +

    A plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series.

    To use this renderer, include the plugin in your source

    <script type="text/javascript" language="javascript" src="plugins/jqplot.categoryAxisRenderer.js"></script>

    and supply the appropriate options to your plot

    {axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}}}
    Summary
    $.jqplot.CategoryAxisRendererA plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series.
    Properties
    sortMergedLabelsTrue to sort tick labels when labels are created by merging x axis values from multiple series.
    tickRendererA class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    + +

    Properties

    + +

    sortMergedLabels

    this.sortMergedLabels = false

    True to sort tick labels when labels are created by merging x axis values from multiple series.  That is, say you have two series like:

    line1 = [[2006, 4],            [2008, 9], [2009, 16]];
    +line2 = [[2006, 3], [2007, 7], [2008, 6]];

    If no label array is specified, tick labels will be collected from the x values of the series.  With sortMergedLabels set to true, tick labels will be:

    [2006, 2007, 2008, 2009]

    With sortMergedLabels set to false, tick labels will be:

    [2006, 2008, 2009, 2007]

    Note, this property is specified on the renderOptions for the axes when creating a plot:

    axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer, rendererOptions:{sortMergedLabels:true}}}
    + +

    tickRenderer

    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer. this.tickRenderer = $.jqplot.AxisTickRenderer; this.labelRenderer = $.jqplot.AxisLabelRenderer;

    + +
    + + + + + + + + + + +
    this.sortMergedLabels = false
    True to sort tick labels when labels are created by merging x axis values from multiple series.
    A “tick” object showing the value of a tick/gridline on the plot.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-ciParser-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-ciParser-js.html new file mode 100644 index 0000000000..fa1ffb1110 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-ciParser-js.html @@ -0,0 +1,39 @@ + + +$.jqplot.ciParser + + + + + + + + + +

    Data Renderer function which converts a custom JSON data object into jqPlot data format.  Set this as a callable on the jqplot dataRenderer plot option:

    plot = $.jqplot('mychart', [data], { dataRenderer: $.jqplot.ciParser, ... });

    Where data is an object in JSON format or a JSON encoded string conforming to the City Index API spec.

    Note that calling the renderer function is handled internally by jqPlot.  The user does not have to call the function.  The parameters described below will automatically be passed to the ciParser function.

    Parameters

    dataJSON encoded string or object.
    plotreference to jqPlot Plot object.

    Returns

    data array in jqPlot format.

    + +
    + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-cursor-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-cursor-js.html new file mode 100644 index 0000000000..ba543f94a7 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-cursor-js.html @@ -0,0 +1,93 @@ + + +$.jqplot.Cursor + + + + + + + + + +

    Plugin class representing the cursor as displayed on the plot.

    Summary
    $.jqplot.CursorPlugin class representing the cursor as displayed on the plot.
    Properties
    styleCSS spec for cursor style
    showwether to show the cursor or not.
    showTooltipshow a cursor position tooltip.
    followMouseTooltip follows the mouse, it is not at a fixed location.
    tooltipLocationWhere to position tooltip.
    tooltipOffsetPixel offset of tooltip from the grid boudaries or cursor center.
    showTooltipGridPositionshow the grid pixel coordinates of the mouse.
    showTooltipUnitPositionshow the unit (data) coordinates of the mouse.
    showTooltipDataPositionUsed with showVerticalLine to show intersecting data points in the tooltip.
    tooltipFormatStringsprintf format string for the tooltip.
    useAxesFormattersUse the x and y axes formatters to format the text in the tooltip.
    tooltipAxisGroupsShow position for the specified axes.
    zoomEnable plot zooming.
    looseZoomWill expand zoom range to provide more rounded tick values.
    clickResetWill reset plot zoom if single click on plot without drag.
    dblClickResetWill reset plot zoom if double click on plot without drag.
    showVerticalLinedraw a vertical line across the plot which follows the cursor.
    showHorizontalLinedraw a horizontal line across the plot which follows the cursor.
    constrainZoomTo‘none’, ‘x’ or ‘y’
    intersectionThresholdpixel distance from data point or marker to consider cursor lines intersecting with point.
    showCursorLegendReplace the plot legend with an enhanced legend displaying intersection information.
    cursorLegendFormatStringFormat string used in the cursor legend.
    constrainOutsideZoomTrue to limit actual zoom area to edges of grid, even when zooming outside of plot area.
    showTooltipOutsideZoomTrue will keep updating the tooltip when zooming of the grid.
    methods
    $.jqplot.Cursor.zoomProxylinks targetPlot to controllerPlot so that plot zooming of targetPlot will be controlled by zooming on the controllerPlot.
    + +

    Properties

    + +

    style

    this.style = 'crosshair'

    CSS spec for cursor style

    + +

    show

    this.show = $.jqplot.config.enablePlugins

    wether to show the cursor or not.

    + +

    showTooltip

    this.showTooltip = true

    show a cursor position tooltip.  Location of the tooltip will be controlled by followMouse and tooltipLocation.

    + +

    followMouse

    this.followMouse = false

    Tooltip follows the mouse, it is not at a fixed location.  Tooltip will show on the grid at the location given by tooltipLocation, offset from the grid edge by tooltipOffset.

    + +

    tooltipLocation

    this.tooltipLocation = 'se'

    Where to position tooltip.  If followMouse is true, this is relative to the cursor, otherwise, it is relative to the grid.  One of ‘n’, ‘ne’, ‘e’, ‘se’, ‘s’, ‘sw’, ‘w’, ‘nw’

    + +

    tooltipOffset

    this.tooltipOffset = 6

    Pixel offset of tooltip from the grid boudaries or cursor center.

    + +

    showTooltipGridPosition

    this.showTooltipGridPosition = false

    show the grid pixel coordinates of the mouse.

    + +

    showTooltipUnitPosition

    this.showTooltipUnitPosition = true

    show the unit (data) coordinates of the mouse.

    + +

    showTooltipDataPosition

    this.showTooltipDataPosition = false

    Used with showVerticalLine to show intersecting data points in the tooltip.

    + +

    tooltipFormatString

    this.tooltipFormatString = '%.4P, %.4P'

    sprintf format string for the tooltip.  Uses Ash Searle’s javascript sprintf implementation found here: http://hexmen.com/blog/2007/03/printf-sprintf/ See http://perldoc.perl.org/functions/sprintf.html for reference Note, if showTooltipDataPosition is true, the default tooltipFormatString will be set to the cursorLegendFormatString, not the default given here.

    + +

    useAxesFormatters

    this.useAxesFormatters = true

    Use the x and y axes formatters to format the text in the tooltip.

    + +

    tooltipAxisGroups

    this.tooltipAxisGroups = []

    Show position for the specified axes.  This is an array like [[‘xaxis’, ‘yaxis’], [‘xaxis’, ‘y2axis’]] Default is to compute automatically for all visible axes.

    + +

    zoom

    this.zoom = false

    Enable plot zooming.

    + +

    looseZoom

    this.looseZoom = false

    Will expand zoom range to provide more rounded tick values.  Works only with linear axes and date axes.

    + +

    clickReset

    this.clickReset = false

    Will reset plot zoom if single click on plot without drag.

    + +

    dblClickReset

    this.dblClickReset = true

    Will reset plot zoom if double click on plot without drag.

    + +

    showVerticalLine

    this.showVerticalLine = false

    draw a vertical line across the plot which follows the cursor.  When the line is near a data point, a special legend and/or tooltip can be updated with the data values.

    + +

    showHorizontalLine

    this.showHorizontalLine = false

    draw a horizontal line across the plot which follows the cursor.

    + +

    constrainZoomTo

    this.constrainZoomTo = 'none'

    ’none’, ‘x’ or ‘y’

    + +

    intersectionThreshold

    this.intersectionThreshold = 2

    pixel distance from data point or marker to consider cursor lines intersecting with point.  If data point markers are not shown, this should be >= 1 or will often miss point intersections.

    + +

    showCursorLegend

    this.showCursorLegend = false

    Replace the plot legend with an enhanced legend displaying intersection information.

    + +

    cursorLegendFormatString

    this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString

    Format string used in the cursor legend.  If showTooltipDataPosition is true, this will also be the default format string used by tooltipFormatString.

    + +

    constrainOutsideZoom

    this.constrainOutsideZoom = true

    True to limit actual zoom area to edges of grid, even when zooming outside of plot area.  That is, can’t zoom out by mousing outside plot.

    + +

    showTooltipOutsideZoom

    this.showTooltipOutsideZoom = false

    True will keep updating the tooltip when zooming of the grid.

    + +

    methods

    + +

    $.jqplot.Cursor.zoomProxy

    $.jqplot.Cursor.zoomProxy = function(targetPlot,
    controllerPlot)

    links targetPlot to controllerPlot so that plot zooming of targetPlot will be controlled by zooming on the controllerPlot. controllerPlot will not actually zoom, but acts as an overview plot.  Note, the zoom options must be set to true for zoomProxy to work.

    + +
    + + + + + + + + + + +
    this.style = 'crosshair'
    CSS spec for cursor style
    this.show = $.jqplot.config.enablePlugins
    wether to show the cursor or not.
    this.showTooltip = true
    show a cursor position tooltip.
    this.followMouse = false
    Tooltip follows the mouse, it is not at a fixed location.
    this.tooltipLocation = 'se'
    Where to position tooltip.
    this.tooltipOffset = 6
    Pixel offset of tooltip from the grid boudaries or cursor center.
    this.showTooltipGridPosition = false
    show the grid pixel coordinates of the mouse.
    this.showTooltipUnitPosition = true
    show the unit (data) coordinates of the mouse.
    this.showTooltipDataPosition = false
    Used with showVerticalLine to show intersecting data points in the tooltip.
    this.tooltipFormatString = '%.4P, %.4P'
    sprintf format string for the tooltip.
    this.useAxesFormatters = true
    Use the x and y axes formatters to format the text in the tooltip.
    this.tooltipAxisGroups = []
    Show position for the specified axes.
    this.zoom = false
    Enable plot zooming.
    this.looseZoom = false
    Will expand zoom range to provide more rounded tick values.
    this.clickReset = false
    Will reset plot zoom if single click on plot without drag.
    this.dblClickReset = true
    Will reset plot zoom if double click on plot without drag.
    this.showVerticalLine = false
    draw a vertical line across the plot which follows the cursor.
    this.showHorizontalLine = false
    draw a horizontal line across the plot which follows the cursor.
    this.constrainZoomTo = 'none'
    ‘none’, ‘x’ or ‘y’
    this.intersectionThreshold = 2
    pixel distance from data point or marker to consider cursor lines intersecting with point.
    this.showCursorLegend = false
    Replace the plot legend with an enhanced legend displaying intersection information.
    this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString
    Format string used in the cursor legend.
    this.constrainOutsideZoom = true
    True to limit actual zoom area to edges of grid, even when zooming outside of plot area.
    this.showTooltipOutsideZoom = false
    True will keep updating the tooltip when zooming of the grid.
    $.jqplot.Cursor.zoomProxy = function(targetPlot,
    controllerPlot)
    links targetPlot to controllerPlot so that plot zooming of targetPlot will be controlled by zooming on the controllerPlot.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-dateAxisRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-dateAxisRenderer-js.html new file mode 100644 index 0000000000..6b49b9412c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-dateAxisRenderer-js.html @@ -0,0 +1,93 @@ + + +$.jqplot.DateAxisRenderer + + + + + + + + + +

    A plugin for a jqPlot to render an axis as a series of date values.  This renderer has no options beyond those supplied by the Axis class.  It supplies it’s own tick formatter, so the tickOptions.formatter option should not be overridden.

    Thanks to Ken Synder for his enhanced Date instance methods which are included with this code http://kendsnyder.com/sandbox/date/.

    To use this renderer, include the plugin in your source

    <script type="text/javascript" language="javascript" src="plugins/jqplot.dateAxisRenderer.js"></script>

    and supply the appropriate options to your plot

    {axes:{xaxis:{renderer:$.jqplot.DateAxisRenderer}}}

    Dates can be passed into the axis in almost any recognizable value and will be parsed.  They will be rendered on the axis in the format specified by tickOptions.formatString.  e.g. tickOptions.formatString = ‘%Y-%m-%d’.

    Accecptable format codes are:

    Code    Result                  Description
    +            == Years ==
    +%Y      2008                Four-digit year
    +%y      08                  Two-digit year
    +            == Months ==
    +%m      09                  Two-digit month
    +%#m     9                   One or two-digit month
    +%B      September           Full month name
    +%b      Sep                 Abbreviated month name
    +            == Days ==
    +%d      05                  Two-digit day of month
    +%#d     5                   One or two-digit day of month
    +%e      5                   One or two-digit day of month
    +%A      Sunday              Full name of the day of the week
    +%a      Sun                 Abbreviated name of the day of the week
    +%w      0                   Number of the day of the week (0 = Sunday, 6 = Saturday)
    +%o      th                  The ordinal suffix string following the day of the month
    +            == Hours ==
    +%H      23                  Hours in 24-hour format (two digits)
    +%#H     3                   Hours in 24-hour integer format (one or two digits)
    +%I      11                  Hours in 12-hour format (two digits)
    +%#I     3                   Hours in 12-hour integer format (one or two digits)
    +%p      PM                  AM or PM
    +            == Minutes ==
    +%M      09                  Minutes (two digits)
    +%#M     9                   Minutes (one or two digits)
    +            == Seconds ==
    +%S      02                  Seconds (two digits)
    +%#S     2                   Seconds (one or two digits)
    +%s      1206567625723       Unix timestamp (Seconds past 1970-01-01 00:00:00)
    +            == Milliseconds ==
    +%N      008                 Milliseconds (three digits)
    +%#N     8                   Milliseconds (one to three digits)
    +            == Timezone ==
    +%O      360                 difference in minutes between local time and GMT
    +%Z      Mountain Standard Time  Name of timezone as reported by browser
    +%G      -06:00              Hours and minutes between GMT
    +            == Shortcuts ==
    +%F      2008-03-26          %Y-%m-%d
    +%T      05:06:30            %H:%M:%S
    +%X      05:06:30            %H:%M:%S
    +%x      03/26/08            %m/%d/%y
    +%D      03/26/08            %m/%d/%y
    +%#c     Wed Mar 26 15:31:00 2008  %a %b %e %H:%M:%S %Y
    +%v      3-Sep-2008          %e-%b-%Y
    +%R      15:31               %H:%M
    +%r      3:31:00 PM          %I:%M:%S %p
    +            == Characters ==
    +%n      \n                  Newline
    +%t      \t                  Tab
    +%%      %                   Percent Symbol
    Summary
    $.jqplot.DateAxisRendererA plugin for a jqPlot to render an axis as a series of date values.
    Properties
    tickRendererA class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    + +

    Properties

    + +

    tickRenderer

    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer. this.tickRenderer = $.jqplot.AxisTickRenderer; this.labelRenderer = $.jqplot.AxisLabelRenderer;

    + +
    + + + + + + + + + + +
    A “tick” object showing the value of a tick/gridline on the plot.
    An individual axis object.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-donutRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-donutRenderer-js.html new file mode 100644 index 0000000000..b7359a01af --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-donutRenderer-js.html @@ -0,0 +1,98 @@ + + +$.jqplot.DonutRenderer + + + + + + + + + +

    Plugin renderer to draw a donut chart. x values, if present, will be used as slice labels. y values give slice size.

    To use this renderer, you need to include the donut renderer plugin, for example:

    <script type="text/javascript" src="plugins/jqplot.donutRenderer.js"></script>

    Properties described here are passed into the $.jqplot function as options on the series renderer.  For example:

    plot2 = $.jqplot('chart2', [s1, s2], {
    +    seriesDefaults: {
    +        renderer:$.jqplot.DonutRenderer,
    +        rendererOptions:{
    +             sliceMargin: 2,
    +             innerDiameter: 110,
    +             startAngle: -90
    +         }
    +     }
    +});

    A donut plot will trigger events on the plot target according to user interaction.  All events return the event object, the series index, the point (slice) index, and the point data for the appropriate slice.

    ’jqplotDataMouseOver’triggered when user mouseing over a slice.
    ’jqplotDataHighlight’triggered the first time user mouses over a slice, if highlighting is enabled.
    ’jqplotDataUnhighlight’triggered when a user moves the mouse out of a highlighted slice.
    ’jqplotDataClick’triggered when the user clicks on a slice.
    ’jqplotDataRightClick’tiggered when the user right clicks on a slice if the “captureRightClick” option is set to true on the plot.
    Summary
    $.jqplot.DonutRendererPlugin renderer to draw a donut chart.
    Properties
    diameterOuter diameter of the donut, auto computed by default
    innerDiameterInner diameter of the donut, auto calculated by default.
    thicknessthickness of the donut, auto computed by default Overridden by if innerDiameter is specified.
    paddingpadding between the donut and plot edges, legend, etc.
    sliceMarginangular spacing between donut slices in degrees.
    ringMarginpixel distance between rings, or multiple series in a donut plot.
    filltrue or false, wether to fil the slices.
    shadowOffsetoffset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    shadowAlphatransparency of the shadow (0 = transparent, 1 = opaque)
    shadowDepthnumber of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    highlightMouseOverTrue to highlight slice when moused over.
    highlightMouseDownTrue to highlight when a mouse button is pressed over a slice.
    highlightColorsan array of colors to use when highlighting a slice.
    dataLabelsEither ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    showDataLabelstrue to show data labels on slices.
    dataLabelFormatStringFormat string for data labels.
    dataLabelThreshold
    dataLabelPositionFactorA Multiplier (0-1) of the pie radius which controls position of label on slice.
    dataLabelNudgeNumber of pixels to slide the label away from (+) or toward (-) the center of the pie.
    startAngleAngle to start drawing donut in degrees.
    $.jqplot.DonutLegendRendererLegend Renderer specific to donut plots.
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    + +

    Properties

    + +

    diameter

    this.diameter = null

    Outer diameter of the donut, auto computed by default

    + +

    innerDiameter

    this.innerDiameter = null

    Inner diameter of the donut, auto calculated by default.  If specified will override thickness value.

    + +

    thickness

    this.thickness = null

    thickness of the donut, auto computed by default Overridden by if innerDiameter is specified.

    + +

    padding

    this.padding = 20

    padding between the donut and plot edges, legend, etc.

    + +

    sliceMargin

    this.sliceMargin = 0

    angular spacing between donut slices in degrees.

    + +

    ringMargin

    this.ringMargin = null

    pixel distance between rings, or multiple series in a donut plot. null will compute ringMargin based on sliceMargin.

    + +

    fill

    this.fill = true

    true or false, wether to fil the slices.

    + +

    shadowOffset

    this.shadowOffset = 2

    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.

    + +

    shadowAlpha

    this.shadowAlpha = 0.07

    transparency of the shadow (0 = transparent, 1 = opaque)

    + +

    shadowDepth

    this.shadowDepth = 5

    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.

    + +

    highlightMouseOver

    this.highlightMouseOver = true

    True to highlight slice when moused over.  This must be false to enable highlightMouseDown to highlight when clicking on a slice.

    + +

    highlightMouseDown

    this.highlightMouseDown = false

    True to highlight when a mouse button is pressed over a slice.  This will be disabled if highlightMouseOver is true.

    + +

    highlightColors

    this.highlightColors = []

    an array of colors to use when highlighting a slice.

    + +

    dataLabels

    this.dataLabels = 'percent'

    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.  Defaults to percentage of each pie slice.

    + +

    showDataLabels

    this.showDataLabels = false

    true to show data labels on slices.

    + +

    dataLabelFormatString

    this.dataLabelFormatString = null

    Format string for data labels.  If none, ‘%s’ is used for “label” and for arrays, ‘%d’ for value and ‘%d%%’ for percentage.

    + +

    dataLabelThreshold

    this.dataLabelThreshold = 3
    Threshhold in percentage (0100) of pie area, below which no label will be displayed.  This applies to all label types, not just to percentage labels.
    + +

    dataLabelPositionFactor

    this.dataLabelPositionFactor = 0.4

    A Multiplier (0-1) of the pie radius which controls position of label on slice.  Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie.

    + +

    dataLabelNudge

    this.dataLabelNudge = 0

    Number of pixels to slide the label away from (+) or toward (-) the center of the pie.

    + +

    startAngle

    this.startAngle = 0

    Angle to start drawing donut in degrees.  According to orientation of canvas coordinate system: 0 = on the positive x axis -90 = on the positive y axis.  90 = on the negaive y axis.  180 or - 180 = on the negative x axis.

    + +

    $.jqplot.DonutLegendRenderer

    Legend Renderer specific to donut plots.  Set by default when user creates a donut plot.

    Summary
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    + +

    Properties

    + +

    numberRows

    this.numberRows = null

    Maximum number of rows in the legend.  0 or null for unlimited.

    + +

    numberColumns

    this.numberColumns = null

    Maximum number of columns in the legend.  0 or null for unlimited.

    + +
    + + + + + + + + + + +
    this.diameter = null
    Outer diameter of the donut, auto computed by default
    this.innerDiameter = null
    Inner diameter of the donut, auto calculated by default.
    this.thickness = null
    thickness of the donut, auto computed by default Overridden by if innerDiameter is specified.
    this.padding = 20
    padding between the donut and plot edges, legend, etc.
    this.sliceMargin = 0
    angular spacing between donut slices in degrees.
    this.ringMargin = null
    pixel distance between rings, or multiple series in a donut plot.
    this.fill = true
    true or false, wether to fil the slices.
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightColors = []
    an array of colors to use when highlighting a slice.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.showDataLabels = false
    true to show data labels on slices.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelThreshold = 3
    this.dataLabelPositionFactor = 0.4
    A Multiplier (0-1) of the pie radius which controls position of label on slice.
    this.dataLabelNudge = 0
    Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
    this.startAngle = 0
    Angle to start drawing donut in degrees.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-dragable-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-dragable-js.html new file mode 100644 index 0000000000..7220de4ecc --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-dragable-js.html @@ -0,0 +1,45 @@ + + +$.jqplot.Dragable + + + + + + + + + +

    Plugin to make plotted points dragable by the user.

    Summary
    $.jqplot.DragablePlugin to make plotted points dragable by the user.
    Properties
    colorCSS color spec for the dragged point (and adjacent line segment or bar).
    constrainToConstrain dragging motion to an axis or to none.
    + +

    Properties

    + +

    color

    this.color

    CSS color spec for the dragged point (and adjacent line segment or bar).

    + +

    constrainTo

    this.constrainTo = 'none'

    Constrain dragging motion to an axis or to none.  Allowable values are ‘none’, ‘x’, ‘y’

    + +
    + + + + + + + + + + +
    this.color
    CSS color spec for the dragged point (and adjacent line segment or bar).
    this.constrainTo = 'none'
    Constrain dragging motion to an axis or to none.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-enhancedLegendRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-enhancedLegendRenderer-js.html new file mode 100644 index 0000000000..e430478f7a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-enhancedLegendRenderer-js.html @@ -0,0 +1,49 @@ + + +/Users/chris/Sites/lib/jqplot/build/plugins/jqplot.enhancedLegendRenderer.js + + + + + + + + + +
    Summary
    jqplot.enhancedLegendRenderer.js
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    seriesTogglefalse to not enable series on/off toggling on the legend.
    disableIEFadingtrue to toggle series with a show/hide method only and not allow fading in/out.
    + +

    Properties

    + +

    numberRows

    this.numberRows = null

    Maximum number of rows in the legend.  0 or null for unlimited.

    + +

    numberColumns

    this.numberColumns = null

    Maximum number of columns in the legend.  0 or null for unlimited.

    + +

    seriesToggle

    this.seriesToggle = 'normal'

    false to not enable series on/off toggling on the legend. true or a fadein/fadeout speed (number of milliseconds or ‘fast’, ‘normal’, ‘slow’) to enable show/hide of series on click of legend item.

    + +

    disableIEFading

    this.disableIEFading = true

    true to toggle series with a show/hide method only and not allow fading in/out.  This is to overcome poor performance of fade in some versions of IE.

    + +
    + + + + + + + + + + +
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.seriesToggle = 'normal'
    false to not enable series on/off toggling on the legend.
    this.disableIEFading = true
    true to toggle series with a show/hide method only and not allow fading in/out.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-funnelRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-funnelRenderer-js.html new file mode 100644 index 0000000000..eb95a8f3ab --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-funnelRenderer-js.html @@ -0,0 +1,87 @@ + + +$.jqplot.FunnelRenderer + + + + + + + + + +

    Plugin renderer to draw a funnel chart. x values, if present, will be used as labels. y values give area size.

    Funnel charts will draw a single series only.

    To use this renderer, you need to include the funnel renderer plugin, for example:

    <script type="text/javascript" src="plugins/jqplot.funnelRenderer.js"></script>

    Properties described here are passed into the $.jqplot function as options on the series renderer.  For example:

    plot2 = $.jqplot('chart2', [s1, s2], {
    +    seriesDefaults: {
    +        renderer:$.jqplot.FunnelRenderer,
    +        rendererOptions:{
    +             sectionMargin: 12,
    +             widthRatio: 0.3
    +         }
    +     }
    +});

    IMPORTANT

    The funnel renderer will reorder data in descending order so the largest value in the data set is first and displayed on top of the funnel.  Data will then be displayed in descending order down the funnel.  The area of each funnel section will correspond to the value of each data point relative to the sum of all values.  That is section area is proportional to section value divided by sum of all section values.

    If your data is not in descending order when passed into the plot, it will be reordered when stored in the series.data property.  A copy of the unordered data is kept in the series._unorderedData property.

    A funnel plot will trigger events on the plot target according to user interaction.  All events return the event object, the series index, the point (section) index, and the point data for the appropriate section.  Note the point index will referr to the ordered data, not the original unordered data.

    ’jqplotDataMouseOver’triggered when mousing over a section.
    ’jqplotDataHighlight’triggered the first time user mouses over a section, if highlighting is enabled.
    ’jqplotDataUnhighlight’triggered when a user moves the mouse out of a highlighted section.
    ’jqplotDataClick’triggered when the user clicks on a section.
    ’jqplotDataRightClick’tiggered when the user right clicks on a section if the “captureRightClick” option is set to true on the plot.
    Summary
    $.jqplot.FunnelRendererPlugin renderer to draw a funnel chart.
    Properties
    paddingpadding between the funnel and plot edges, legend, etc.
    sectionMarginspacing between funnel sections in pixels.
    filltrue or false, wether to fill the areas.
    shadowOffsetoffset of the shadow from the area and offset of each succesive stroke of the shadow from the last.
    shadowAlphatransparency of the shadow (0 = transparent, 1 = opaque)
    shadowDepthnumber of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    highlightMouseOverTrue to highlight area when moused over.
    highlightMouseDownTrue to highlight when a mouse button is pressed over a area.
    highlightColorsarray of colors to use when highlighting an area.
    widthRatioThe ratio of the width of the top of the funnel to the bottom.
    lineWidthwidth of line if areas are stroked and not filled.
    dataLabelsEither ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    showDataLabelstrue to show data labels on slices.
    dataLabelFormatStringFormat string for data labels.
    dataLabelThreshold
    $.jqplot.FunnelLegendRendererLegend Renderer specific to funnel plots.
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    + +

    Properties

    + +

    padding

    this.padding = {top: 20, right: 20, bottom: 20, left: 20}

    padding between the funnel and plot edges, legend, etc.

    + +

    sectionMargin

    this.sectionMargin = 6

    spacing between funnel sections in pixels.

    + +

    fill

    this.fill = true

    true or false, wether to fill the areas.

    + +

    shadowOffset

    this.shadowOffset = 2

    offset of the shadow from the area and offset of each succesive stroke of the shadow from the last.

    + +

    shadowAlpha

    this.shadowAlpha = 0.07

    transparency of the shadow (0 = transparent, 1 = opaque)

    + +

    shadowDepth

    this.shadowDepth = 5

    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.

    + +

    highlightMouseOver

    this.highlightMouseOver = true

    True to highlight area when moused over.  This must be false to enable highlightMouseDown to highlight when clicking on a area.

    + +

    highlightMouseDown

    this.highlightMouseDown = false

    True to highlight when a mouse button is pressed over a area.  This will be disabled if highlightMouseOver is true.

    + +

    highlightColors

    this.highlightColors = []

    array of colors to use when highlighting an area.

    + +

    widthRatio

    this.widthRatio = 0.2

    The ratio of the width of the top of the funnel to the bottom. a ratio of 0 will make an upside down pyramid.

    + +

    lineWidth

    this.lineWidth = 2

    width of line if areas are stroked and not filled.

    + +

    dataLabels

    this.dataLabels = 'percent'

    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.  Defaults to percentage of each pie slice.

    + +

    showDataLabels

    this.showDataLabels = false

    true to show data labels on slices.

    + +

    dataLabelFormatString

    this.dataLabelFormatString = null

    Format string for data labels.  If none, ‘%s’ is used for “label” and for arrays, ‘%d’ for value and ‘%d%%’ for percentage.

    + +

    dataLabelThreshold

    this.dataLabelThreshold = 3
    Threshhold in percentage (0100) of pie area, below which no label will be displayed.  This applies to all label types, not just to percentage labels.
    + +

    $.jqplot.FunnelLegendRenderer

    Legend Renderer specific to funnel plots.  Set by default when the user creates a funnel plot.

    Summary
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    + +

    Properties

    + +

    numberRows

    this.numberRows = null

    Maximum number of rows in the legend.  0 or null for unlimited.

    + +

    numberColumns

    this.numberColumns = null

    Maximum number of columns in the legend.  0 or null for unlimited.

    + +
    + + + + + + + + + + +
    this.padding = {top: 20, right: 20, bottom: 20, left: 20}
    padding between the funnel and plot edges, legend, etc.
    this.sectionMargin = 6
    spacing between funnel sections in pixels.
    this.fill = true
    true or false, wether to fill the areas.
    this.shadowOffset = 2
    offset of the shadow from the area and offset of each succesive stroke of the shadow from the last.
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.highlightMouseOver = true
    True to highlight area when moused over.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a area.
    this.highlightColors = []
    array of colors to use when highlighting an area.
    this.widthRatio = 0.2
    The ratio of the width of the top of the funnel to the bottom.
    this.lineWidth = 2
    width of line if areas are stroked and not filled.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.showDataLabels = false
    true to show data labels on slices.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelThreshold = 3
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-highlighter-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-highlighter-js.html new file mode 100644 index 0000000000..9d58dcf9c3 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-highlighter-js.html @@ -0,0 +1,80 @@ + + +$.jqplot.Highlighter + + + + + + + + + +

    Plugin which will highlight data points when they are moused over.

    To use this plugin, include the js file in your source:

    <script type="text/javascript" src="plugins/jqplot.highlighter.js"></script>

    A tooltip providing information about the data point is enabled by default.  To disable the tooltip, set “showTooltip” to false.

    You can control what data is displayed in the tooltip with various options.  The “tooltipAxes” option controls wether the x, y or both data values are displayed.

    Some chart types (e.g. hi-low-close) have more than one y value per data point.  To display the additional values in the tooltip, set the “yvalues” option to the desired number of y values present (3 for a hlc chart).

    By default, data values will be formatted with the same formatting specifiers as used to format the axis ticks.  A custom format code can be supplied with the tooltipFormatString option.  This will apply to all values in the tooltip.

    For more complete control, the “formatString” option can be set.  This Allows conplete control over tooltip formatting.  Values are passed to the format string in an order determined by the “tooltipAxes” and “yvalues” options.  So, if you have a hi-low-close chart and you just want to display the hi-low-close values in the tooltip, you could set a formatString like:

    highlighter: {
    +    tooltipAxes: 'y',
    +    yvalues: 3,
    +    formatString:'<table class="jqplot-highlighter">
    +        <tr><td>hi:</td><td>%s</td></tr>
    +        <tr><td>low:</td><td>%s</td></tr>
    +        <tr><td>close:</td><td>%s</td></tr></table>'
    +}
    Summary
    $.jqplot.HighlighterPlugin which will highlight data points when they are moused over.
    Properties
    showtrue to show the highlight.
    markerRendererRenderer used to draw the marker of the highlighted point.
    showMarkertrue to show the marker
    lineWidthAdjustPixels to add to the lineWidth of the highlight.
    sizeAdjustPixels to add to the overall size of the highlight.
    showTooltipShow a tooltip with data point values.
    tooltipLocationWhere to position tooltip, ‘n’, ‘ne’, ‘e’, ‘se’, ‘s’, ‘sw’, ‘w’, ‘nw’
    fadeTooltiptrue = fade in/out tooltip, flase = show/hide tooltip
    tooltipFadeSpeed‘slow’, ‘def’, ‘fast’, or number of milliseconds.
    tooltipOffsetPixel offset of tooltip from the highlight.
    tooltipAxesWhich axes to display in tooltip, ‘x’, ‘y’ or ‘both’, ‘xy’ or ‘yx’ ‘both’ and ‘xy’ are equivalent, ‘yx’ reverses order of labels.
    useAxesFormattersUse the x and y axes formatters to format the text in the tooltip.
    tooltipFormatStringsprintf format string for the tooltip.
    formatStringalternative to tooltipFormatString will format the whole tooltip text, populating with x, y values as indicated by tooltipAxes option.
    yvaluesNumber of y values to expect in the data point array.
    bringSeriesToFrontThis option requires jQuery 1.4+ True to bring the series of the highlighted point to the front of other series.
    + +

    Properties

    + +

    show

    this.show = $.jqplot.config.enablePlugins

    true to show the highlight.

    + +

    markerRenderer

    this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false})

    Renderer used to draw the marker of the highlighted point.  Renderer will assimilate attributes from the data point being highlighted, so no attributes need set on the renderer directly.  Default is to turn off shadow drawing on the highlighted point.

    + +

    showMarker

    this.showMarker = true

    true to show the marker

    + +

    lineWidthAdjust

    this.lineWidthAdjust = 2.5

    Pixels to add to the lineWidth of the highlight.

    + +

    sizeAdjust

    this.sizeAdjust = 5

    Pixels to add to the overall size of the highlight.

    + +

    showTooltip

    this.showTooltip = true

    Show a tooltip with data point values.

    + +

    tooltipLocation

    this.tooltipLocation = 'nw'

    Where to position tooltip, ‘n’, ‘ne’, ‘e’, ‘se’, ‘s’, ‘sw’, ‘w’, ‘nw’

    + +

    fadeTooltip

    this.fadeTooltip = true

    true = fade in/out tooltip, flase = show/hide tooltip

    + +

    tooltipFadeSpeed

    this.tooltipFadeSpeed = "fast"

    ’slow’, ‘def’, ‘fast’, or number of milliseconds.

    + +

    tooltipOffset

    this.tooltipOffset = 2

    Pixel offset of tooltip from the highlight.

    + +

    tooltipAxes

    this.tooltipAxes = 'both'

    Which axes to display in tooltip, ‘x’, ‘y’ or ‘both’, ‘xy’ or ‘yx’ ‘both’ and ‘xy’ are equivalent, ‘yx’ reverses order of labels.

    + +

    useAxesFormatters

    this.useAxesFormatters = true

    Use the x and y axes formatters to format the text in the tooltip.

    + +

    tooltipFormatString

    this.tooltipFormatString = '%.5P'

    sprintf format string for the tooltip.  Uses Ash Searle’s javascript sprintf implementation found here: http://hexmen.com/blog/2007/03/printf-sprintf/ See http://perldoc.perl.org/functions/sprintf.html for reference.  Additional “p” and “P” format specifiers added by Chris Leonello.

    + +

    formatString

    this.formatString = null

    alternative to tooltipFormatString will format the whole tooltip text, populating with x, y values as indicated by tooltipAxes option.  So, you could have a tooltip like: ‘Date: %s, number of cats: %d’ to format the whole tooltip at one go.  If useAxesFormatters is true, values will be formatted according to Axes formatters and you can populate your tooltip string with %s placeholders.

    + +

    yvalues

    this.yvalues = 1

    Number of y values to expect in the data point array.  Typically this is 1.  Certain plots, like OHLC, will have more y values in each data point array.

    + +

    bringSeriesToFront

    this.bringSeriesToFront = false

    This option requires jQuery 1.4+ True to bring the series of the highlighted point to the front of other series.

    + +
    + + + + + + + + + + +
    this.show = $.jqplot.config.enablePlugins
    true to show the highlight.
    this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false})
    Renderer used to draw the marker of the highlighted point.
    this.showMarker = true
    true to show the marker
    this.lineWidthAdjust = 2.5
    Pixels to add to the lineWidth of the highlight.
    this.sizeAdjust = 5
    Pixels to add to the overall size of the highlight.
    this.showTooltip = true
    Show a tooltip with data point values.
    this.tooltipLocation = 'nw'
    Where to position tooltip, ‘n’, ‘ne’, ‘e’, ‘se’, ‘s’, ‘sw’, ‘w’, ‘nw’
    this.fadeTooltip = true
    true = fade in/out tooltip, flase = show/hide tooltip
    this.tooltipFadeSpeed = "fast"
    ‘slow’, ‘def’, ‘fast’, or number of milliseconds.
    this.tooltipOffset = 2
    Pixel offset of tooltip from the highlight.
    this.tooltipAxes = 'both'
    Which axes to display in tooltip, ‘x’, ‘y’ or ‘both’, ‘xy’ or ‘yx’ ‘both’ and ‘xy’ are equivalent, ‘yx’ reverses order of labels.
    this.useAxesFormatters = true
    Use the x and y axes formatters to format the text in the tooltip.
    this.tooltipFormatString = '%.5P'
    sprintf format string for the tooltip.
    this.formatString = null
    alternative to tooltipFormatString will format the whole tooltip text, populating with x, y values as indicated by tooltipAxes option.
    this.yvalues = 1
    Number of y values to expect in the data point array.
    this.bringSeriesToFront = false
    This option requires jQuery 1.4+ True to bring the series of the highlighted point to the front of other series.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-logAxisRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-logAxisRenderer-js.html new file mode 100644 index 0000000000..302c6b7c4f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-logAxisRenderer-js.html @@ -0,0 +1,45 @@ + + +$.jqplot.LogAxisRenderer + + + + + + + + + +

    A plugin for a jqPlot to render a logarithmic axis.

    To use this renderer, include the plugin in your source

    <script type="text/javascript" language="javascript" src="plugins/jqplot.logAxisRenderer.js"></script>

    and supply the appropriate options to your plot

    {axes:{xaxis:{renderer:$.jqplot.LogAxisRenderer}}}
    Summary
    $.jqplot.LogAxisRendererA plugin for a jqPlot to render a logarithmic axis.
    axisDefaultsDefault properties which will be applied directly to the series.
    PropertiesProperties
    tickRendererA class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    + +

    axisDefaults

    Default properties which will be applied directly to the series.

    + +

    Properties

    Properties

    / basethe logarithmic base, commonly 2, 10 or Math.E
    tickDistribution’even’ or ‘power’.  ‘even’ gives equal pixel spacing of the ticks on the plot.  ‘power’ gives ticks in powers of 10.
    + +

    tickRenderer

    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer. this.tickRenderer = $.jqplot.AxisTickRenderer; this.labelRenderer = $.jqplot.AxisLabelRenderer;

    + +
    + + + + + + + + + + +
    A “tick” object showing the value of a tick/gridline on the plot.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-mekkoAxisRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-mekkoAxisRenderer-js.html new file mode 100644 index 0000000000..2781762503 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-mekkoAxisRenderer-js.html @@ -0,0 +1,49 @@ + + +$.jqplot.MekkoAxisRenderer + + + + + + + + + +

    An axis renderer for a Mekko chart.  Should be used with a Mekko chart where the mekkoRenderer is used on the series.  Displays the Y axis as a range from 0 to 1 (0 to 100%) and the x axis with a tick for each series scaled to the sum of all the y values.

    Summary
    $.jqplot.MekkoAxisRendererAn axis renderer for a Mekko chart.
    Properties
    tickModeHow to space the ticks on the axis.
    barLabelRendererrenderer to use to draw labels under each bar.
    barLabelsarray of labels to put under each bar.
    barLabelOptionsoptions object to pass to the bar label renderer.
    + +

    Properties

    + +

    tickMode

    this.tickMode

    How to space the ticks on the axis.  ‘bar’ will place a tick at the width of each bar.  This is the default for the x axis.  ‘even’ will place ticks at even intervals.  This is the default for x2 axis and y axis.  y axis cannot be changed.

    + +

    barLabelRenderer

    this.barLabelRenderer = $.jqplot.AxisLabelRenderer

    renderer to use to draw labels under each bar.

    + +

    barLabels

    this.barLabels = this.barLabels || []

    array of labels to put under each bar.

    + +

    barLabelOptions

    this.barLabelOptions = {}

    options object to pass to the bar label renderer.

    + +
    + + + + + + + + + + +
    this.tickMode
    How to space the ticks on the axis.
    this.barLabelRenderer = $.jqplot.AxisLabelRenderer
    renderer to use to draw labels under each bar.
    this.barLabels = this.barLabels || []
    array of labels to put under each bar.
    this.barLabelOptions = {}
    options object to pass to the bar label renderer.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-mekkoRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-mekkoRenderer-js.html new file mode 100644 index 0000000000..5f46a49b5c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-mekkoRenderer-js.html @@ -0,0 +1,62 @@ + + +$.jqplot.MekkoRenderer + + + + + + + + + +

    Draws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph. the $.jqplot.MekkoAxisRenderer should be used with mekko charts.  The mekko renderer overrides the default legend renderer with it’s own $.jqplot.MekkoLegendRenderer which allows more flexibility to specify number of rows and columns in the legend.

    Data is specified per bar in the chart.  You can specify data as an array of y values, or as an array of [label, value] pairs.  Note that labels are used only on the first series.  Labels on subsequent series are ignored:

    bar1 = [['shirts', 8],['hats', 14],['shoes', 6],['gloves', 16],['dolls', 12]];
    +bar2 = [15,6,9,13,6];
    +bar3 = [['grumpy',4],['sneezy',2],['happy',7],['sleepy',9],['doc',7]];

    If you want to place labels for each bar under the axis, you use the barLabels option on the axes.  The bar labels can be styled with the “.jqplot-mekko-barLabel” css class.

    barLabels = ['Mickey Mouse', 'Donald Duck', 'Goofy'];
    +axes:{xaxis:{barLabels:barLabels}}
    Summary
    $.jqplot.MekkoRendererDraws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph.
    Properties
    borderColorcolor of the borders between areas on the chart
    showBordersTrue to draw borders lines between areas on the chart.
    Functions
    setGridDataconverts the user data values to grid coordinates and stores them in the gridData array.
    makeGridDataconverts any arbitrary data values to grid coordinates and returns them.
    $.jqplot.MekkoLegendRendererLegend renderer used by mekko charts with options for controlling number or rows and columns as well as placement outside of plot area.
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    + +

    Properties

    + +

    borderColor

    this.borderColor = null

    color of the borders between areas on the chart

    + +

    showBorders

    this.showBorders = true

    True to draw borders lines between areas on the chart.  False will draw borders lines with the same color as the area.

    + +

    Functions

    + +

    setGridData

    $.jqplot.MekkoRenderer.prototype.setGridData = function(plot)

    converts the user data values to grid coordinates and stores them in the gridData array.  Will convert user data into appropriate rectangles.  Called with scope of a series.

    + +

    makeGridData

    $.jqplot.MekkoRenderer.prototype.makeGridData = function(data,
    plot)

    converts any arbitrary data values to grid coordinates and returns them.  This method exists so that plugins can use a series’ linerenderer to generate grid data points without overwriting the grid data associated with that series.  Called with scope of a series.

    + +

    $.jqplot.MekkoLegendRenderer

    Legend renderer used by mekko charts with options for controlling number or rows and columns as well as placement outside of plot area.

    Summary
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    + +

    Properties

    + +

    numberRows

    this.numberRows = null

    Maximum number of rows in the legend.  0 or null for unlimited.

    + +

    numberColumns

    this.numberColumns = null

    Maximum number of columns in the legend.  0 or null for unlimited.

    + +
    + + + + + + + + + + +
    this.borderColor = null
    color of the borders between areas on the chart
    this.showBorders = true
    True to draw borders lines between areas on the chart.
    $.jqplot.MekkoRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    $.jqplot.MekkoRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    An axis renderer for a Mekko chart.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-meterGaugeRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-meterGaugeRenderer-js.html new file mode 100644 index 0000000000..5d70045a09 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-meterGaugeRenderer-js.html @@ -0,0 +1,103 @@ + + +$.jqplot.MeterGaugeRenderer + + + + + + + + + +

    Plugin renderer to draw a meter gauge chart.

    Data consists of a single series with 1 data point to position the gauge needle.

    To use this renderer, you need to include the meter gauge renderer plugin, for example:

    <script type="text/javascript" src="plugins/jqplot.meterGaugeRenderer.js"></script>

    Properties described here are passed into the $.jqplot function as options on the series renderer.  For example:

    plot0 = $.jqplot('chart0',[[18]],{
    +    title: 'Network Speed',
    +    seriesDefaults: {
    +        renderer: $.jqplot.MeterGaugeRenderer,
    +        rendererOptions: {
    +            label: 'MB/s'
    +        }
    +    }
    +});

    A meterGauge plot does not support events.

    Summary
    $.jqplot.MeterGaugeRendererPlugin renderer to draw a meter gauge chart.
    Properties
    diameterOuter diameter of the meterGauge, auto computed by default
    paddingpadding between the meterGauge and plot edges, auto calculated by default.
    shadowOffsetoffset of the shadow from the gauge ring and offset of each succesive stroke of the shadow from the last.
    shadowAlphatransparency of the shadow (0 = transparent, 1 = opaque)
    shadowDepthnumber of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    backgroundbackground color of the inside of the gauge.
    ringColorcolor of the outer ring, hub, and needle of the gauge.
    tickColorcolor of the tick marks around the gauge.
    ringWidthwidth of the ring around the gauge.
    minMinimum value on the gauge.
    maxMaximum value on the gauge.
    ticksArray of tick values.
    showTickstrue to show ticks around gauge.
    showTickLabelstrue to show tick labels next to ticks.
    labelA gauge label like ‘kph’ or ‘Volts’
    labelHeightAdjustNumber of Pixels to offset the label up (-) or down (+) from its default position.
    labelPositionWhere to position the label, either ‘inside’ or ‘bottom’.
    intervalsArray of ranges to be drawn around the gauge.
    intervalColorsArray of colors to use for the intervals.
    intervalInnerRadiusRadius of the inner circle of the interval ring.
    intervalOuterRadiusRadius of the outer circle of the interval ring.
    tickSpacingDegrees between ticks.
    hubRadiusRadius of the hub at the bottom center of gauge which the needle attaches to.
    tickPaddingpadding of the tick marks to the outer ring and the tick labels to marks.
    needleThicknessMaximum thickness the needle.
    needlePadPadding between needle and inner edge of the ring when the needle is at the min or max gauge value.
    pegNeedleTrue will stop needle just below/above the min/max values if data is below/above min/max, as if the meter is “pegged”.
    + +

    Properties

    + +

    diameter

    this.diameter = null

    Outer diameter of the meterGauge, auto computed by default

    + +

    padding

    this.padding = null

    padding between the meterGauge and plot edges, auto calculated by default.

    + +

    shadowOffset

    this.shadowOffset = 2

    offset of the shadow from the gauge ring and offset of each succesive stroke of the shadow from the last.

    + +

    shadowAlpha

    this.shadowAlpha = 0.07

    transparency of the shadow (0 = transparent, 1 = opaque)

    + +

    shadowDepth

    this.shadowDepth = 4

    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.

    + +

    background

    this.background = "#efefef"

    background color of the inside of the gauge.

    + +

    ringColor

    this.ringColor = "#BBC6D0"

    color of the outer ring, hub, and needle of the gauge.

    + +

    tickColor

    this.tickColor = "989898"

    color of the tick marks around the gauge.

    + +

    ringWidth

    this.ringWidth = null

    width of the ring around the gauge.  Auto computed by default.

    + +

    min

    this.min

    Minimum value on the gauge.  Auto computed by default

    + +

    max

    this.max

    Maximum value on the gauge.  Auto computed by default

    + +

    ticks

    this.ticks = []

    Array of tick values.  Auto computed by default.

    + +

    showTicks

    this.showTicks = true

    true to show ticks around gauge.

    + +

    showTickLabels

    this.showTickLabels = true

    true to show tick labels next to ticks.

    + +

    label

    this.label = null

    A gauge label like ‘kph’ or ‘Volts’

    + +

    labelHeightAdjust

    this.labelHeightAdjust = 0

    Number of Pixels to offset the label up (-) or down (+) from its default position.

    + +

    labelPosition

    this.labelPosition = 'inside'

    Where to position the label, either ‘inside’ or ‘bottom’.

    + +

    intervals

    this.intervals = []

    Array of ranges to be drawn around the gauge.  Array of form:

    [value1, value2, ...]

    indicating the values for the first, second, ... intervals.

    + +

    intervalColors

    this.intervalColors = [ "#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"]

    Array of colors to use for the intervals.

    + +

    intervalInnerRadius

    this.intervalInnerRadius = null

    Radius of the inner circle of the interval ring.

    + +

    intervalOuterRadius

    this.intervalOuterRadius = null

    Radius of the outer circle of the interval ring.

    + +

    tickSpacing

    this.tickSpacing = 30

    Degrees between ticks.  This is a target number, if incompatible span and ticks are supplied, a suitable spacing close to this value will be computed.

    + +

    hubRadius

    this.hubRadius = null

    Radius of the hub at the bottom center of gauge which the needle attaches to.  Auto computed by default

    + +

    tickPadding

    this.tickPadding = null

    padding of the tick marks to the outer ring and the tick labels to marks.  Auto computed by default.

    + +

    needleThickness

    this.needleThickness = null

    Maximum thickness the needle.  Auto computed by default.

    + +

    needlePad

    this.needlePad = 6

    Padding between needle and inner edge of the ring when the needle is at the min or max gauge value.

    + +

    pegNeedle

    this.pegNeedle = true

    True will stop needle just below/above the min/max values if data is below/above min/max, as if the meter is “pegged”.

    + +
    + + + + + + + + + + +
    this.diameter = null
    Outer diameter of the meterGauge, auto computed by default
    this.padding = null
    padding between the meterGauge and plot edges, auto calculated by default.
    this.shadowOffset = 2
    offset of the shadow from the gauge ring and offset of each succesive stroke of the shadow from the last.
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowDepth = 4
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.background = "#efefef"
    background color of the inside of the gauge.
    this.ringColor = "#BBC6D0"
    color of the outer ring, hub, and needle of the gauge.
    this.tickColor = "989898"
    color of the tick marks around the gauge.
    this.ringWidth = null
    width of the ring around the gauge.
    this.min
    Minimum value on the gauge.
    this.max
    Maximum value on the gauge.
    this.ticks = []
    Array of tick values.
    this.showTicks = true
    true to show ticks around gauge.
    this.showTickLabels = true
    true to show tick labels next to ticks.
    this.label = null
    A gauge label like ‘kph’ or ‘Volts’
    this.labelHeightAdjust = 0
    Number of Pixels to offset the label up (-) or down (+) from its default position.
    this.labelPosition = 'inside'
    Where to position the label, either ‘inside’ or ‘bottom’.
    this.intervals = []
    Array of ranges to be drawn around the gauge.
    this.intervalColors = [ "#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"]
    Array of colors to use for the intervals.
    this.intervalInnerRadius = null
    Radius of the inner circle of the interval ring.
    this.intervalOuterRadius = null
    Radius of the outer circle of the interval ring.
    this.tickSpacing = 30
    Degrees between ticks.
    this.hubRadius = null
    Radius of the hub at the bottom center of gauge which the needle attaches to.
    this.tickPadding = null
    padding of the tick marks to the outer ring and the tick labels to marks.
    this.needleThickness = null
    Maximum thickness the needle.
    this.needlePad = 6
    Padding between needle and inner edge of the ring when the needle is at the min or max gauge value.
    this.pegNeedle = true
    True will stop needle just below/above the min/max values if data is below/above min/max, as if the meter is “pegged”.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-ohlcRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-ohlcRenderer-js.html new file mode 100644 index 0000000000..445886ec6b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-ohlcRenderer-js.html @@ -0,0 +1,65 @@ + + +$.jqplot.OHLCRenderer + + + + + + + + + +

    jqPlot Plugin to draw Open Hi Low Close, Candlestick and Hi Low Close charts.

    To use this plugin, include the renderer js file in your source:

    <script type="text/javascript" src="plugins/jqplot.ohlcRenderer.js"></script>

    You will most likely want to use a date axis renderer for the x axis also, so include the date axis render js file also:

    <script type="text/javascript" src="plugins/jqplot.dateAxisRenderer.js"></script>

    Then you set the renderer in the series options on your plot

    series: [{renderer:$.jqplot.OHLCRenderer}]

    For OHLC and candlestick charts, data should be specified like so:

    dat = [['07/06/2009',138.7,139.68,135.18,135.4], ['06/29/2009',143.46,144.66,139.79,140.02], ...]

    If the data array has only 4 values per point instead of 5, the renderer will create a Hi Low Close chart instead.  In that case, data should be supplied like:

    dat = [['07/06/2009',139.68,135.18,135.4], ['06/29/2009',144.66,139.79,140.02], ...]

    To generate a candlestick chart instead of an OHLC chart, set the “candlestick” option to true:

    series: [{renderer:$.jqplot.OHLCRenderer, rendererOptions:{candleStick:true}}],
    Summary
    $.jqplot.OHLCRendererjqPlot Plugin to draw Open Hi Low Close, Candlestick and Hi Low Close charts.
    Properties
    candleSticktrue to render chart as candleStick.
    tickLengthlength of the line in pixels indicating open and close price.
    bodyWidthwidth of the candlestick body in pixels.
    openColorcolor of the open price tick mark.
    closeColorcolor of the close price tick mark.
    wickColorcolor of the hi-lo line thorugh the candlestick body.
    fillUpBodytrue to render an “up” day (close price greater than open price) with a filled candlestick body.
    fillDownBodytrue to render a “down” day (close price lower than open price) with a filled candlestick body.
    upBodyColorColor of candlestick body of an “up” day.
    downBodyColorColor of candlestick body on a “down” day.
    hlctrue if is a hi-low-close chart (no open price).
    lineWidthWidth of the hi-low line and open/close ticks.
    + +

    Properties

    + +

    candleStick

    this.candleStick = false

    true to render chart as candleStick.  Must have an open price, cannot be a hlc chart.

    + +

    tickLength

    this.tickLength = 'auto'

    length of the line in pixels indicating open and close price.  Default will auto calculate based on plot width and number of points displayed.

    + +

    bodyWidth

    this.bodyWidth = 'auto'

    width of the candlestick body in pixels.  Default will auto calculate based on plot width and number of candlesticks displayed.

    + +

    openColor

    this.openColor = null

    color of the open price tick mark.  Default is series color.

    + +

    closeColor

    this.closeColor = null

    color of the close price tick mark.  Default is series color.

    + +

    wickColor

    this.wickColor = null

    color of the hi-lo line thorugh the candlestick body.  Default is the series color.

    + +

    fillUpBody

    this.fillUpBody = false

    true to render an “up” day (close price greater than open price) with a filled candlestick body.

    + +

    fillDownBody

    this.fillDownBody = true

    true to render a “down” day (close price lower than open price) with a filled candlestick body.

    + +

    upBodyColor

    this.upBodyColor = null

    Color of candlestick body of an “up” day.  Default is series color.

    + +

    downBodyColor

    this.downBodyColor = null

    Color of candlestick body on a “down” day.  Default is series color.

    + +

    hlc

    this.hlc = false

    true if is a hi-low-close chart (no open price).  This is determined automatically from the series data.

    + +

    lineWidth

    this.lineWidth = 1.5

    Width of the hi-low line and open/close ticks.  Must be set in the rendererOptions for the series.

    + +
    + + + + + + + + + + +
    this.candleStick = false
    true to render chart as candleStick.
    this.tickLength = 'auto'
    length of the line in pixels indicating open and close price.
    this.bodyWidth = 'auto'
    width of the candlestick body in pixels.
    this.openColor = null
    color of the open price tick mark.
    this.closeColor = null
    color of the close price tick mark.
    this.wickColor = null
    color of the hi-lo line thorugh the candlestick body.
    this.fillUpBody = false
    true to render an “up” day (close price greater than open price) with a filled candlestick body.
    this.fillDownBody = true
    true to render a “down” day (close price lower than open price) with a filled candlestick body.
    this.upBodyColor = null
    Color of candlestick body of an “up” day.
    this.downBodyColor = null
    Color of candlestick body on a “down” day.
    this.hlc = false
    true if is a hi-low-close chart (no open price).
    this.lineWidth = 1.5
    Width of the hi-low line and open/close ticks.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-pieRenderer-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-pieRenderer-js.html new file mode 100644 index 0000000000..1d0ddfeed2 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-pieRenderer-js.html @@ -0,0 +1,93 @@ + + +$.jqplot.PieRenderer + + + + + + + + + +

    Plugin renderer to draw a pie chart. x values, if present, will be used as slice labels. y values give slice size.

    To use this renderer, you need to include the pie renderer plugin, for example:

    <script type="text/javascript" src="plugins/jqplot.pieRenderer.js"></script>

    Properties described here are passed into the $.jqplot function as options on the series renderer.  For example:

    plot2 = $.jqplot('chart2', [s1, s2], {
    +    seriesDefaults: {
    +        renderer:$.jqplot.PieRenderer,
    +        rendererOptions:{
    +             sliceMargin: 2,
    +             startAngle: -90
    +         }
    +     }
    +});

    A pie plot will trigger events on the plot target according to user interaction.  All events return the event object, the series index, the point (slice) index, and the point data for the appropriate slice.

    ’jqplotDataMouseOver’triggered when user mouseing over a slice.
    ’jqplotDataHighlight’triggered the first time user mouses over a slice, if highlighting is enabled.
    ’jqplotDataUnhighlight’triggered when a user moves the mouse out of a highlighted slice.
    ’jqplotDataClick’triggered when the user clicks on a slice.
    ’jqplotDataRightClick’tiggered when the user right clicks on a slice if the “captureRightClick” option is set to true on the plot.
    Summary
    $.jqplot.PieRendererPlugin renderer to draw a pie chart.
    Properties
    diameterOuter diameter of the pie, auto computed by default
    paddingpadding between the pie and plot edges, legend, etc.
    sliceMarginangular spacing between pie slices in degrees.
    filltrue or false, wether to fil the slices.
    shadowOffsetoffset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    shadowAlphatransparency of the shadow (0 = transparent, 1 = opaque)
    shadowDepthnumber of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    highlightMouseOverTrue to highlight slice when moused over.
    highlightMouseDownTrue to highlight when a mouse button is pressed over a slice.
    highlightColorsan array of colors to use when highlighting a slice.
    dataLabelsEither ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    showDataLabelstrue to show data labels on slices.
    dataLabelFormatStringFormat string for data labels.
    dataLabelThresholdThreshhold in percentage (0-100) of pie area, below which no label will be displayed.
    dataLabelPositionFactorA Multiplier (0-1) of the pie radius which controls position of label on slice.
    dataLabelNudgeNumber of pixels to slide the label away from (+) or toward (-) the center of the pie.
    dataLabelCenterOnTrue to center the data label at its position.
    startAngleAngle to start drawing pie in degrees.
    $.jqplot.PieLegendRendererLegend Renderer specific to pie plots.
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    + +

    Properties

    + +

    diameter

    this.diameter = null

    Outer diameter of the pie, auto computed by default

    + +

    padding

    this.padding = 20

    padding between the pie and plot edges, legend, etc.

    + +

    sliceMargin

    this.sliceMargin = 0

    angular spacing between pie slices in degrees.

    + +

    fill

    this.fill = true

    true or false, wether to fil the slices.

    + +

    shadowOffset

    this.shadowOffset = 2

    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.

    + +

    shadowAlpha

    this.shadowAlpha = 0.07

    transparency of the shadow (0 = transparent, 1 = opaque)

    + +

    shadowDepth

    this.shadowDepth = 5

    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.

    + +

    highlightMouseOver

    this.highlightMouseOver = true

    True to highlight slice when moused over.  This must be false to enable highlightMouseDown to highlight when clicking on a slice.

    + +

    highlightMouseDown

    this.highlightMouseDown = false

    True to highlight when a mouse button is pressed over a slice.  This will be disabled if highlightMouseOver is true.

    + +

    highlightColors

    this.highlightColors = []

    an array of colors to use when highlighting a slice.

    + +

    dataLabels

    this.dataLabels = 'percent'

    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.  Defaults to percentage of each pie slice.

    + +

    showDataLabels

    this.showDataLabels = false

    true to show data labels on slices.

    + +

    dataLabelFormatString

    this.dataLabelFormatString = null

    Format string for data labels.  If none, ‘%s’ is used for “label” and for arrays, ‘%d’ for value and ‘%d%%’ for percentage.

    + +

    dataLabelThreshold

    this.dataLabelThreshold = 3

    Threshhold in percentage (0-100) of pie area, below which no label will be displayed.  This applies to all label types, not just to percentage labels.

    + +

    dataLabelPositionFactor

    this.dataLabelPositionFactor = 0.52

    A Multiplier (0-1) of the pie radius which controls position of label on slice.  Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie.

    + +

    dataLabelNudge

    this.dataLabelNudge = 2

    Number of pixels to slide the label away from (+) or toward (-) the center of the pie.

    + +

    dataLabelCenterOn

    this.dataLabelCenterOn = true

    True to center the data label at its position.  False to set the inside facing edge of the label at its position.

    + +

    startAngle

    this.startAngle = 0

    Angle to start drawing pie in degrees.  According to orientation of canvas coordinate system: 0 = on the positive x axis -90 = on the positive y axis.  90 = on the negaive y axis.  180 or - 180 = on the negative x axis.

    + +

    $.jqplot.PieLegendRenderer

    Legend Renderer specific to pie plots.  Set by default when user creates a pie plot.

    Summary
    Properties
    numberRowsMaximum number of rows in the legend.
    numberColumnsMaximum number of columns in the legend.
    + +

    Properties

    + +

    numberRows

    this.numberRows = null

    Maximum number of rows in the legend.  0 or null for unlimited.

    + +

    numberColumns

    this.numberColumns = null

    Maximum number of columns in the legend.  0 or null for unlimited.

    + +
    + + + + + + + + + + +
    this.diameter = null
    Outer diameter of the pie, auto computed by default
    this.padding = 20
    padding between the pie and plot edges, legend, etc.
    this.sliceMargin = 0
    angular spacing between pie slices in degrees.
    this.fill = true
    true or false, wether to fil the slices.
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightColors = []
    an array of colors to use when highlighting a slice.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.showDataLabels = false
    true to show data labels on slices.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelThreshold = 3
    Threshhold in percentage (0-100) of pie area, below which no label will be displayed.
    this.dataLabelPositionFactor = 0.52
    A Multiplier (0-1) of the pie radius which controls position of label on slice.
    this.dataLabelNudge = 2
    Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
    this.dataLabelCenterOn = true
    True to center the data label at its position.
    this.startAngle = 0
    Angle to start drawing pie in degrees.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-pointLabels-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-pointLabels-js.html new file mode 100644 index 0000000000..157961012e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-pointLabels-js.html @@ -0,0 +1,72 @@ + + +$.jqplot.PointLabels + + + + + + + + + +

    Plugin for putting labels at the data points.

    To use this plugin, include the js file in your source:

    <script type="text/javascript" src="plugins/jqplot.pointLabels.js"></script>

    By default, the last value in the data ponit array in the data series is used for the label.  For most series renderers, extra data can be added to the data point arrays and the last value will be used as the label.

    For instance, this series:

    [[1,4], [3,5], [7,2]]

    Would, by default, use the y values in the labels.  Extra data can be added to the series like so:

    [[1,4,'mid'], [3 5,'hi'], [7,2,'low']]

    And now the point labels would be ‘mid’, ‘low’, and ‘hi’.

    Options to the point labels and a custom labels array can be passed into the “pointLabels” option on the series option like so:

    series:[{pointLabels:{
    +   labels:['mid', 'hi', 'low'],
    +   location:'se',
    +   ypadding: 12
    +   }
    +}]

    A custom labels array in the options takes precendence over any labels in the series data.  If you have a custom labels array in the options, but still want to use values from the series array as labels, set the “labelsFromSeries” option to true.

    By default, html entities (<, >, etc.) are escaped in point labels.  If you want to include actual html markup in the labels, set the “escapeHTML” option to false.

    Summary
    $.jqplot.PointLabelsPlugin for putting labels at the data points.
    Properties
    showshow the labels or not.
    locationcompass location where to position the label around the point.
    labelsFromSeriestrue to use labels within data point arrays.
    seriesLabelIndexarray index for location of labels within data point arrays.
    labelsarray of arrays of labels, one array for each series.
    stackedValuetrue to display value as stacked in a stacked plot.
    ypaddingvertical padding in pixels between point and label
    xpaddinghorizontal padding in pixels between point and label
    escapeHTMLtrue to escape html entities in the labels.
    edgeToleranceNumber of pixels that the label must be away from an axis boundary in order to be drawn.
    formatterA class of a formatter for the tick text.
    formatStringstring passed to the formatter.
    hideZerostrue to not show a label for a value which is 0.
    + +

    Properties

    + +

    show

    this.show = $.jqplot.config.enablePlugins

    show the labels or not.

    + +

    location

    this.location = 'n'

    compass location where to position the label around the point.  ‘n’, ‘ne’, ‘e’, ‘se’, ‘s’, ‘sw’, ‘w’, ‘nw’

    + +

    labelsFromSeries

    this.labelsFromSeries = false

    true to use labels within data point arrays.

    + +

    seriesLabelIndex

    this.seriesLabelIndex = null

    array index for location of labels within data point arrays. if null, will use the last element of the data point array.

    + +

    labels

    this.labels = []

    array of arrays of labels, one array for each series.

    + +

    stackedValue

    this.stackedValue = false

    true to display value as stacked in a stacked plot. no effect if labels is specified.

    + +

    ypadding

    this.ypadding = 6

    vertical padding in pixels between point and label

    + +

    xpadding

    this.xpadding = 6

    horizontal padding in pixels between point and label

    + +

    escapeHTML

    this.escapeHTML = true

    true to escape html entities in the labels.  If you want to include markup in the labels, set to false.

    + +

    edgeTolerance

    this.edgeTolerance = -5

    Number of pixels that the label must be away from an axis boundary in order to be drawn.  Negative values will allow overlap with the grid boundaries.

    + +

    formatter

    this.formatter = $.jqplot.DefaultTickFormatter

    A class of a formatter for the tick text.  sprintf by default.

    + +

    formatString

    this.formatString = ''

    string passed to the formatter.

    + +

    hideZeros

    this.hideZeros = false

    true to not show a label for a value which is 0.

    + +
    + + + + + + + + + + +
    this.show = $.jqplot.config.enablePlugins
    show the labels or not.
    this.location = 'n'
    compass location where to position the label around the point.
    this.labelsFromSeries = false
    true to use labels within data point arrays.
    this.seriesLabelIndex = null
    array index for location of labels within data point arrays.
    this.labels = []
    array of arrays of labels, one array for each series.
    this.stackedValue = false
    true to display value as stacked in a stacked plot.
    this.ypadding = 6
    vertical padding in pixels between point and label
    this.xpadding = 6
    horizontal padding in pixels between point and label
    this.escapeHTML = true
    true to escape html entities in the labels.
    this.edgeTolerance = -5
    Number of pixels that the label must be away from an axis boundary in order to be drawn.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    this.formatString = ''
    string passed to the formatter.
    this.hideZeros = false
    true to not show a label for a value which is 0.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-trendline-js.html b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-trendline-js.html new file mode 100644 index 0000000000..ea296691f2 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/plugins/jqplot-trendline-js.html @@ -0,0 +1,67 @@ + + +$.jqplot.Trendline + + + + + + + + + +

    Plugin which will automatically compute and draw trendlines for plotted data.

    Summary
    $.jqplot.TrendlinePlugin which will automatically compute and draw trendlines for plotted data.
    Properties
    showWether or not to show the trend line.
    colorCSS color spec for the trend line.
    rendererRenderer to use to draw the trend line.
    rendererOptionsOptions to pass to the line renderer.
    labelLabel for the trend line to use in the legend.
    typeEither ‘exponential’, ‘exp’, or ‘linear’.
    shadowtrue or false, wether or not to show the shadow.
    markerRendererRenderer to use to draw markers on the line.
    lineWidthWidth of the trend line.
    shadowAngleAngle of the shadow on the trend line.
    shadowOffsetpixel offset for each stroke of the shadow.
    shadowAlphaAlpha transparency of the shadow.
    shadowDepthnumber of strokes to make of the shadow.
    + +

    Properties

    + +

    show

    this.show = $.jqplot.config.enablePlugins

    Wether or not to show the trend line.

    + +

    color

    this.color = '#666666'

    CSS color spec for the trend line.  By default this wil be the same color as the primary line.

    + +

    renderer

    this.renderer = new $.jqplot.LineRenderer()

    Renderer to use to draw the trend line.  The data series that is plotted may not be rendered as a line.  Therefore, we use our own line renderer here to draw a trend line.

    + +

    rendererOptions

    this.rendererOptions = {marker:{show:false}}

    Options to pass to the line renderer.  By default, markers are not shown on trend lines.

    + +

    label

    this.label = ''

    Label for the trend line to use in the legend.

    + +

    type

    this.type = 'linear'

    Either ‘exponential’, ‘exp’, or ‘linear’.

    + +

    shadow

    this.shadow = true

    true or false, wether or not to show the shadow.

    + +

    markerRenderer

    this.markerRenderer = {show:false}

    Renderer to use to draw markers on the line.  I think this is wrong.

    + +

    lineWidth

    this.lineWidth = 1.5

    Width of the trend line.

    + +

    shadowAngle

    this.shadowAngle = 45

    Angle of the shadow on the trend line.

    + +

    shadowOffset

    this.shadowOffset = 1.0

    pixel offset for each stroke of the shadow.

    + +

    shadowAlpha

    this.shadowAlpha = 0.07

    Alpha transparency of the shadow.

    + +

    shadowDepth

    this.shadowDepth = 3

    number of strokes to make of the shadow.

    + +
    + + + + + + + + + + +
    this.show = $.jqplot.config.enablePlugins
    Wether or not to show the trend line.
    this.color = '#666666'
    CSS color spec for the trend line.
    this.renderer = new $.jqplot.LineRenderer()
    Renderer to use to draw the trend line.
    this.rendererOptions = {marker:{show:false}}
    Options to pass to the line renderer.
    this.label = ''
    Label for the trend line to use in the legend.
    this.type = 'linear'
    Either ‘exponential’, ‘exp’, or ‘linear’.
    this.shadow = true
    true or false, wether or not to show the shadow.
    this.markerRenderer = {show:false}
    Renderer to use to draw markers on the line.
    this.lineWidth = 1.5
    Width of the trend line.
    this.shadowAngle = 45
    Angle of the shadow on the trend line.
    this.shadowOffset = 1.0
    pixel offset for each stroke of the shadow.
    this.shadowAlpha = 0.07
    Alpha transparency of the shadow.
    this.shadowDepth = 3
    number of strokes to make of the shadow.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/files/usage-txt.html b/phpgwapi/js/jquery/jqplot/docs/files/usage-txt.html new file mode 100644 index 0000000000..377d0a457e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/files/usage-txt.html @@ -0,0 +1,58 @@ + + +jqPlot Usage + + + + + + + + + +

    Usage Documentation

    Introduction

    jqPlot is a jQuery plugin to generate pure client-side javascript charts in your web pages.

    The jqPlot home page is at http://www.jqplot.com/.

    The project page and downloads are at http://www.bitbucket.org/cleonello/jqplot/.

    Below are a few examples to demonstrate jqPlot usage.  These plots are shown as static images.  Many more examples of dynamically rendered plots can be seen on the test and examples pages here: ../../tests/.

    Include the Files

    jqPlot requires jQuery (1.4+ required for certain features). jQuery 1.4.4 is included in the distribution.  To use jqPlot include jquery, the jqPlot jQuery plugin, jqPlot css file and optionally the excanvas script for IE support in your web page.  Note, excanvas is required only for IE versions below 9.  IE 9 includes native support for the canvas element and does not require excanvas:

    <!--[if lt IE 9]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->
    +<script language="javascript" type="text/javascript" src="jquery-1.4.4.min.js"></script>
    +<script language="javascript" type="text/javascript" src="jquery.jqplot.min.js"></script>
    +<link rel="stylesheet" type="text/css" href="jquery.jqplot.css" />

    Add a plot container

    Add a container (target) to your web page where you want your plot to show up.  Be sure to give your target a width and a height:

    <div id="chartdiv" style="height:400px;width:300px; "></div>

    Create a plot

    Then, create the actual plot by calling the $.jqplot plugin with the id of your target and some data:

    $.jqplot('chartdiv',  [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]]);

    Which will produce a chart like:

    Plot Options

    You can customize the plot by passing options to the $.jqplot function.  Options are described in jqPlot Options in the jqPlotOptions.txt file.  An example of options usage:

    $.jqplot('chartdiv',  [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]],
    +{ title:'Exponential Line',
    +  axes:{yaxis:{min:-10, max:240}},
    +  series:[{color:'#5FAB78'}]
    +});

    Which will produce a plot like:

    Using Plugins

    You can use jqPlot plugins (that is, plugins to the jqPlot plugin) by including them in your html after you include the jqPlot plugin.  Here is how to include the log axis plugin:

    <link rel="stylesheet" type="text/css" href="jquery.jqplot.css" />
    +<!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->
    +<script language="javascript" type="text/javascript" src="jquery-1.4.4.min.js"></script>
    +<script language="javascript" type="text/javascript" src="jquery.jqplot.min.js"></script>
    +<script language="javascript" type="text/javascript" src="jqplot.logAxisRenderer.js"></script>

    Important note: For jqplot builds r529 and above (0.9.7r529 and higher), you must explicitly enable plugins via either the { show: true } plugin option to the plot or by using the $.jqplot.config.enablePlugins = true; config options set on the page before plot creation.  Only plugins that can be immediately active upon loading are affected.  This includes non-renderer plugins like cursor, dragable, highlighter, and trendline.

    Here is a the same $.jqplot call but with a log y axis:

    $.jqplot('chartdiv',  [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]],
    +{ title:'Exponential Line',
    +  axes:{yaxis:{renderer: $.jqplot.LogAxisRenderer}},
    +  series:[{color:'#5FAB78'}]
    +});

    Which produces a plot like:

    You can further customize with options specific to the log axis plugin:

    $.jqplot('chartdiv',  [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]],
    +{ title:'Exponential Line',
    +  axes:{yaxis:{renderer: $.jqplot.LogAxisRenderer, tickDistribution:'power'}},
    +  series:[{color:'#5FAB78'}]
    +});

    Which makes a plot like:

    For a full list of options, see jqPlot Options in the jqPlotOptions.txt file.

    You can add as many plugins as you wish.  Order is generally not important.  Some plugins, like the highlighter plugin which highlights data points near the mouse, don’t need any extra options or setup to function.  Highlighter does have additional options which the user can set.

    Other plugins, the barRenderer for example, provide functionality the must be specified in the chart options object.  To render a series as a bar graph with the bar renderer, you would first include the plugin after jqPlot:

    <script language="javascript" type="text/javascript" src="plugins/jqplot.barRenderer.min.js"></script>

    Then you would create a chart like:

    $.jqplot('chartdiv',  [[34.53, 56.32, 25.1, 18.6]], {series:[{renderer:$.jqplot.BarRenderer}]});

    Here the default LineRenderer is replaced by a BarRenderer to generate a bar graph for the first (an only) series.

    + +
    + + + + + + + + + + +
    This document is out of date.
    + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index.html b/phpgwapi/js/jquery/jqplot/docs/index.html new file mode 100644 index 0000000000..295fd4a6fa --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Classes.html b/phpgwapi/js/jquery/jqplot/docs/index/Classes.html new file mode 100644 index 0000000000..af33314d67 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Classes.html @@ -0,0 +1,70 @@ + + +Class Index + + + + + + + + + +
    Class Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    $#!
     $.jqplot
     $.jqplot.AxisLabelRenderer
     $.jqplot.AxisTickRenderer
     $.jqplot.BarRenderer
     $.jqplot.BezierCurveRenderer.js
     $.jqplot.BlockRenderer
     $.jqplot.BubbleRenderer
     $.jqplot.CanvasAxisLabelRenderer
     $.jqplot.CanvasAxisTickRenderer
     $.jqplot.CanvasGridRenderer
     $.jqplot.CanvasOverlay
     $.jqplot.CategoryAxisRenderer
     $.jqplot.ciParser
     $.jqplot.Cursor
     $.jqplot.DateAxisRenderer
     $.jqplot.DivTitleRenderer
     $.jqplot.DonutLegendRenderer
     $.jqplot.DonutRenderer
     $.jqplot.Dragable
     $.jqplot.FunnelLegendRenderer
     $.jqplot.FunnelRenderer
     $.jqplot.Highlighter
     $.jqplot.LinearAxisRenderer
     $.jqplot.LineRenderer
     $.jqplot.LogAxisRenderer
     $.jqplot.MarkerRenderer
     $.jqplot.MekkoAxisRenderer
     $.jqplot.MekkoLegendRenderer
     $.jqplot.MekkoRenderer
     $.jqplot.MeterGaugeRenderer
     $.jqplot.OHLCRenderer
     $.jqplot.PieLegendRenderer
     $.jqplot.PieRenderer
     $.jqplot.PointLabels
     $.jqplot.shadowRenderer
     $.jqplot.shapeRenderer
     $.jqplot.ThemeEngine
     $.jqplot.Trendline
    A
     Axis
    D
     DashedHorizontalLine
     DashedVerticalLine
    G
     Grid
    H
     HorizontalLine
    J
     jqPlot
    L
     Legend
     Line
    S
     Series
    T
     Title
    V
     VerticalLine
    + +
    jQuery function called by the user to create a plot.
    Renderer to place labels on the axes.
    A “tick” object showing the value of a tick/gridline on the plot.
    A plugin renderer for jqPlot to draw a bar plot.
    Renderer which draws lines as stacked bezier curves.
    Plugin renderer to draw a x-y block chart.
    Plugin renderer to draw a bubble chart.
    Renderer to draw axis labels with a canvas element to support advanced featrues such as rotated text.
    Renderer to draw axis ticks with a canvas element to support advanced featrues such as rotated text.
    The default jqPlot grid renderer, creating a grid on a canvas element.
    A plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series.
    Data Renderer function which converts a custom JSON data object into jqPlot data format.
    Plugin class representing the cursor as displayed on the plot.
    A plugin for a jqPlot to render an axis as a series of date values.
    The default title renderer for jqPlot.
    Legend Renderer specific to donut plots.
    Plugin renderer to draw a donut chart.
    Plugin to make plotted points dragable by the user.
    Legend Renderer specific to funnel plots.
    Plugin renderer to draw a funnel chart.
    Plugin which will highlight data points when they are moused over.
    The default jqPlot axis renderer, creating a numeric axis.
    The default line renderer for jqPlot, this class has no options beyond the Series class.
    A plugin for a jqPlot to render a logarithmic axis.
    The default jqPlot marker renderer, rendering the points on the line.
    An axis renderer for a Mekko chart.
    Legend renderer used by mekko charts with options for controlling number or rows and columns as well as placement outside of plot area.
    Draws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph.
    Plugin renderer to draw a meter gauge chart.
    jqPlot Plugin to draw Open Hi Low Close, Candlestick and Hi Low Close charts.
    Legend Renderer specific to pie plots.
    Plugin renderer to draw a pie chart.
    Plugin for putting labels at the data points.
    The default jqPlot shadow renderer, rendering shadows behind shapes.
    The default jqPlot shape renderer.
    Theme Engine provides a programatic way to change some of the more common jqplot styling options such as fonts, colors and grid options.
    Plugin which will automatically compute and draw trendlines for plotted data.
    + + + +
    An individual axis object.
    + + + +
    A straight dashed horizontal line.
    A straight dashed vertical line.
    + + + +
    Object representing the grid on which the plot is drawn.
    + + + +
    A straight horizontal line.
    + + + +
    Plot object returned by call to $.jqplot.
    + + + +
    Legend object.
    A straight line.
    + + + +
    An individual data series object.
    + + + +
    Plot Title object.
    + + + +
    A straight vertical line.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Files.html b/phpgwapi/js/jquery/jqplot/docs/index/Files.html new file mode 100644 index 0000000000..05b39b6f32 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Files.html @@ -0,0 +1,34 @@ + + +File Index + + + + + + + + + +
    File Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    J
     jqplot.enhancedLegendRenderer.js
    + + + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Functions.html b/phpgwapi/js/jquery/jqplot/docs/index/Functions.html new file mode 100644 index 0000000000..9212f4678d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Functions.html @@ -0,0 +1,66 @@ + + +Function Index + + + + + + + + + +
    Function Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    C
     copy, $.jqplot.ThemeEngine
    D
     destroy, jqPlot
     draw
     drawSeries, jqPlot
    G
     get, $.jqplot.ThemeEngine
     getThemeNames, $.jqplot.ThemeEngine
     getThemes, $.jqplot.ThemeEngine
    I
     init, jqPlot
    M
     makeGridData
     moveBlock, $.jqplot.BlockRenderer
     moveSeriesToBack, jqPlot
     moveSeriesToFront, jqPlot
    N
     newTheme, $.jqplot.ThemeEngine
    R
     redraw, jqPlot
     reInitialize, jqPlot
     remove, $.jqplot.ThemeEngine
     rename, $.jqplot.ThemeEngine
     replot, jqPlot
     resetAxesScale, jqPlot
     restoreOriginalSeriesOrder, jqPlot
     restorePreviousSeriesOrder, jqPlot
    S
     setGridData
    Z
     zoomProxy, $.jqplot.Cursor.$.jqplot.Cursor
    + +
    $.jqplot.ThemeEngine.prototype.copy = function (sourceName,
    targetName,
    obj)
    Create a copy of an existing theme in the themeEngine, adding it the themeEngine.
    + + + +
    this.destroy = function()
    Releases all resources occupied by the plot
    $.jqplot.ShadowRenderer.prototype.draw = function(ctx,
    points,
    options)
    draws an transparent black (i.e.
    $.jqplot.ShapeRenderer.prototype.draw = function(ctx,
    points,
    options)
    draws the shape.
    this.draw = function()
    Draws all elements of the plot into the container.
    this.drawSeries = function(options,
    idx)
    Redraws all or just one series on the plot.
    + + + +
    $.jqplot.ThemeEngine.prototype.get = function(name)
    Get and return the named theme or the active theme if no name given.
    $.jqplot.ThemeEngine.prototype.getThemeNames = function()
    Return the list of theme names in this manager in alpha-numerical order.
    $.jqplot.ThemeEngine.prototype.getThemes = function()
    Return a list of themes in alpha-numerical order by name.
    + + + +
    this.init = function(target,
    data,
    options)
    sets the plot target, checks data and applies user options to plot.
    + + + +
    $.jqplot.BezierCurveRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    $.jqplot.LineRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    $.jqplot.MekkoRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    this.moveBlock = function (idx,
    x,
    y,
    duration)
    Moves an individual block.
    this.moveSeriesToBack = function (idx)
    This method requires jQuery 1.4+ Moves the specified series canvas behind all other series canvases.
    this.moveSeriesToFront = function (idx)
    This method requires jQuery 1.4+ Moves the specified series canvas in front of all other series canvases.
    + + + +
    $.jqplot.ThemeEngine.prototype.newTheme = function(name,
    obj)
    Create a new theme based on the default theme, adding it the themeEngine.
    + + + +
    this.redraw = function(clear)
    Empties the plot target div and redraws the plot.
    this.reInitialize = function ()
    reinitialize plot for replotting.
    $.jqplot.ThemeEngine.prototype.remove = function(name)
    Remove the given theme from the themeEngine.
    $.jqplot.ThemeEngine.prototype.rename = function (oldName,
    newName)
    Rename a theme.
    this.replot = function(options)
    Does a reinitialization of the plot followed by a redraw.
    this.resetAxesScale = function(axes,
    options)
    Reset the specified axes min, max, numberTicks and tickInterval properties to null or reset these properties on all axes if no list of axes is provided.
    this.restoreOriginalSeriesOrder = function ()
    This method requires jQuery 1.4+ Restore the series canvas order to its original order when the plot was created.
    this.restorePreviousSeriesOrder = function ()
    This method requires jQuery 1.4+ Restore the series canvas order to its previous state.
    + + + +
    $.jqplot.BezierCurveRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    $.jqplot.LineRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    $.jqplot.MekkoRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    + + + +
    $.jqplot.Cursor.zoomProxy = function(targetPlot,
    controllerPlot)
    links targetPlot to controllerPlot so that plot zooming of targetPlot will be controlled by zooming on the controllerPlot.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/General.html b/phpgwapi/js/jquery/jqplot/docs/index/General.html new file mode 100644 index 0000000000..51839b4476 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/General.html @@ -0,0 +1,46 @@ + + +Index + + + + + + + + + +
    Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    $#!
     $.jqplot
     $.jqplot.AxisLabelRenderer
     $.jqplot.AxisTickRenderer
     $.jqplot.BarRenderer
     $.jqplot.BezierCurveRenderer.js
     $.jqplot.BlockRenderer
     $.jqplot.BubbleRenderer
     $.jqplot.CanvasAxisLabelRenderer
     $.jqplot.CanvasAxisTickRenderer
     $.jqplot.CanvasGridRenderer
     $.jqplot.CanvasOverlay
     $.jqplot.CategoryAxisRenderer
     $.jqplot.ciParser
     $.jqplot.Cursor
     $.jqplot.DateAxisRenderer
     $.jqplot.DivTitleRenderer
     $.jqplot.DonutLegendRenderer
     $.jqplot.DonutRenderer
     $.jqplot.Dragable
     $.jqplot.FunnelLegendRenderer
     $.jqplot.FunnelRenderer
     $.jqplot.Highlighter
     $.jqplot.LinearAxisRenderer
     $.jqplot.LineRenderer
     $.jqplot.LogAxisRenderer
     $.jqplot.MarkerRenderer
     $.jqplot.MekkoAxisRenderer
     $.jqplot.MekkoLegendRenderer
     $.jqplot.MekkoRenderer
     $.jqplot.MeterGaugeRenderer
     $.jqplot.OHLCRenderer
     $.jqplot.PieLegendRenderer
     $.jqplot.PieRenderer
     $.jqplot.PointLabels
     $.jqplot.shadowRenderer
     $.jqplot.shapeRenderer
     $.jqplot.ThemeEngine
     $.jqplot.Trendline
    A
     activeTheme, $.jqplot.ThemeEngine
     addLegendRowHooks, $.jqplot.$.jqplot
     alpha, $.jqplot.shadowRenderer
     angle
     autoscale, Axis
     autoscaleBubbles, $.jqplot.BubbleRenderer
     autoscaleMultiplier, $.jqplot.BubbleRenderer
     autoscalePointsFactor, $.jqplot.BubbleRenderer
     Available Options
     axes, jqPlot
     axesDefaults, jqPlot
     Axis
     axisDefaults, $.jqplot.LogAxisRenderer
    B
     background
     barDirection, $.jqplot.BarRenderer
     barLabelOptions, $.jqplot.MekkoAxisRenderer
     barLabelRenderer, $.jqplot.MekkoAxisRenderer
     barLabels, $.jqplot.MekkoAxisRenderer
     barMargin, $.jqplot.BarRenderer
     barPadding, $.jqplot.BarRenderer
     barWidth, $.jqplot.BarRenderer
     bodyWidth, $.jqplot.OHLCRenderer
     border, Legend
     borderColor
     borderWidth
     breakOnNull, Series
     breakPoints, $.jqplot.LinearAxisRenderer
     breakTickLabel, $.jqplot.LinearAxisRenderer
     bringSeriesToFront, $.jqplot.Highlighter
     bubbleAlpha, $.jqplot.BubbleRenderer
     bubbleGradients, $.jqplot.BubbleRenderer
    C
     candleStick, $.jqplot.OHLCRenderer
     Change Log
     Changes
     clearRect, $.jqplot.shapeRenderer
     clickReset, $.jqplot.Cursor
     closeColor, $.jqplot.OHLCRenderer
     color
     constrainOutsideZoom, $.jqplot.Cursor
     constrainTo, $.jqplot.Dragable
     constrainZoomTo, $.jqplot.Cursor
     copy, $.jqplot.ThemeEngine
     Copyright&License
     css, $.jqplot.BlockRenderer
     cursorLegendFormatString, $.jqplot.Cursor
    + +
    jQuery function called by the user to create a plot.
    Renderer to place labels on the axes.
    A “tick” object showing the value of a tick/gridline on the plot.
    A plugin renderer for jqPlot to draw a bar plot.
    Renderer which draws lines as stacked bezier curves.
    Plugin renderer to draw a x-y block chart.
    Plugin renderer to draw a bubble chart.
    Renderer to draw axis labels with a canvas element to support advanced featrues such as rotated text.
    Renderer to draw axis ticks with a canvas element to support advanced featrues such as rotated text.
    The default jqPlot grid renderer, creating a grid on a canvas element.
    A plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series.
    Data Renderer function which converts a custom JSON data object into jqPlot data format.
    Plugin class representing the cursor as displayed on the plot.
    A plugin for a jqPlot to render an axis as a series of date values.
    The default title renderer for jqPlot.
    Legend Renderer specific to donut plots.
    Plugin renderer to draw a donut chart.
    Plugin to make plotted points dragable by the user.
    Legend Renderer specific to funnel plots.
    Plugin renderer to draw a funnel chart.
    Plugin which will highlight data points when they are moused over.
    The default jqPlot axis renderer, creating a numeric axis.
    The default line renderer for jqPlot, this class has no options beyond the Series class.
    A plugin for a jqPlot to render a logarithmic axis.
    The default jqPlot marker renderer, rendering the points on the line.
    An axis renderer for a Mekko chart.
    Legend renderer used by mekko charts with options for controlling number or rows and columns as well as placement outside of plot area.
    Draws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph.
    Plugin renderer to draw a meter gauge chart.
    jqPlot Plugin to draw Open Hi Low Close, Candlestick and Hi Low Close charts.
    Legend Renderer specific to pie plots.
    Plugin renderer to draw a pie chart.
    Plugin for putting labels at the data points.
    The default jqPlot shadow renderer, rendering shadows behind shapes.
    The default jqPlot shape renderer.
    Theme Engine provides a programatic way to change some of the more common jqplot styling options such as fonts, colors and grid options.
    Plugin which will automatically compute and draw trendlines for plotted data.
    + + + +
    this.activeTheme=null
    Pointer to currently active theme
    called at the end of legend draw, so plugins can add rows to the legend table.
    this.alpha = 0.07
    alpha transparency of shadow stroke.
    this.angle = 0
    angle of text, measured clockwise from x axis.
    this.angle = 0
    angle of text, measured clockwise from x axis.
    this.angle = 45
    Angle of the shadow in degrees.
    this.autoscale = false
    Autoscale the axis min and max values to provide sensible tick spacing.
    this.autoscaleBubbles = true
    True to scale the bubble radius based on plot size.
    this.autoscaleMultiplier = 1.0
    Multiplier the bubble size if autoscaleBubbles is true.
    this.autoscalePointsFactor = -0.07
    Factor which decreases bubble size based on how many bubbles on on the chart.
    See jqPlot Options for a list of options available thorugh the options object (not complete yet!)
    this.axes = {xaxis: new Axis('xaxis'), yaxis: new Axis('yaxis'), x2axis: new Axis('x2axis'), y2axis: new Axis('y2axis'), y3axis: new Axis('y3axis'), y4axis: new Axis('y4axis'), y5axis: new Axis('y5axis'), y6axis: new Axis('y6axis'), y7axis: new Axis('y7axis'), y8axis: new Axis('y8axis'), y9axis: new Axis('y9axis')}
    up to 4 axes are supported, each with it’s own options, See Axis for axis specific options.
    default options that will be applied to all axes.
    An individual axis object.
    Default properties which will be applied directly to the series.
    + + + +
    this.background = "#efefef"
    background color of the inside of the gauge.
    this.background = '#fffdf6'
    css spec for the background color.
    this.background
    css spec for the background of the legend box.
    this.barDirection = 'vertical'
    ‘vertical’ = up and down bars, ‘horizontal’ = side to side bars
    this.barLabelOptions = {}
    options object to pass to the bar label renderer.
    this.barLabelRenderer = $.jqplot.AxisLabelRenderer
    renderer to use to draw labels under each bar.
    this.barLabels = this.barLabels || []
    array of labels to put under each bar.
    this.barMargin = 10
    Number of pixels between groups of bars at adjacent axis values.
    this.barPadding = 8
    Number of pixels between adjacent bars at the same axis value.
    this.barWidth = null
    Width of the bar in pixels (auto by devaul).
    this.bodyWidth = 'auto'
    width of the candlestick body in pixels.
    this.border
    css spec for the border around the legend box.
    this.borderColor = null
    color of the borders between areas on the chart
    this.borderColor = null
    color of the border adjacent to the axis.
    this.borderColor = '#999999'
    css spec for the color of the grid border.
    this.borderWidth = null
    width of line stroked at the border of the axis.
    this.borderWidth = 2.0
    width of the border in pixels.
    this.breakOnNull = false
    Wether line segments should be be broken at null value.
    this.breakPoints = null
    EXPERIMENTAL!! 
    this.breakTickLabel = "&asymp
    Label to use at the axis break if breakPoints are specified.
    this.bringSeriesToFront = false
    This option requires jQuery 1.4+ True to bring the series of the highlighted point to the front of other series.
    this.bubbleAlpha = 1.0
    Alpha transparency to apply to all bubbles in this series.
    this.bubbleGradients = false
    True to color the bubbles with gradient fills instead of flat colors.
    + + + +
    this.candleStick = false
    true to render chart as candleStick.
    See Change Log
    this.clearRect = false
    true to cear a rectangle.
    this.clickReset = false
    Will reset plot zoom if single click on plot without drag.
    this.closeColor = null
    color of the close price tick mark.
    this.color
    CSS color spec for the dragged point (and adjacent line segment or bar).
    this.color = '#666666'
    color of marker.
    this.color = '#666666'
    CSS color spec for the trend line.
    color of the line
    color of the line
    color of the line
    color of the line
    this.color
    css color spec for the series
    color of the line
    this.constrainOutsideZoom = true
    True to limit actual zoom area to edges of grid, even when zooming outside of plot area.
    this.constrainTo = 'none'
    Constrain dragging motion to an axis or to none.
    this.constrainZoomTo = 'none'
    ‘none’, ‘x’ or ‘y’
    $.jqplot.ThemeEngine.prototype.copy = function (sourceName,
    targetName,
    obj)
    Create a copy of an existing theme in the themeEngine, adding it the themeEngine.
    Copyright © 2009-2011 Chris Leonello jqPlot is currently available for use in all personal or commercial projects under both the MIT and GPL version 2.0 licenses.
    this.css = {padding:'2px', border:'1px solid #999', textAlign:'center'}
    default css styles that will be applied to all data blocks.
    this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString
    Format string used in the cursor legend.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/General2.html b/phpgwapi/js/jquery/jqplot/docs/index/General2.html new file mode 100644 index 0000000000..aa7f4c85bf --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/General2.html @@ -0,0 +1,42 @@ + + +Index + + + + + + + + + +
    Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    D
     DashedHorizontalLine
     DashedVerticalLine
     dashPattern
     data, jqPlot
     dataLabelCenterOn, $.jqplot.PieRenderer
     dataLabelFormatString
     dataLabelNudge
     dataLabelPositionFactor
     dataLabels
     dataLabelThreshold
     dblClickReset, $.jqplot.Cursor
     defaultAxisStart, jqPlot
     depth, $.jqplot.shadowRenderer
     destroy, jqPlot
     diameter
     disableIEFading
     disableStack, Series
     downBodyColor, $.jqplot.OHLCRenderer
     draw
     drawBorder, Grid
     drawGridlines, Grid
     drawSeries, jqPlot
    E
     edgeTolerance, $.jqplot.PointLabels
     enableFontSupport
     escapeHtml
     escapeHTML
     eventListenerHooks, $.jqplot.$.jqplot
    F
     fadeTooltip, $.jqplot.Highlighter
     fill
     fillAlpha, Series
     fillAndStroke, Series
     fillAxis, Series
     fillColor, Series
     fillDownBody, $.jqplot.OHLCRenderer
     fillRect, $.jqplot.shapeRenderer
     fillStyle, $.jqplot.shapeRenderer
     fillToValue, Series
     fillToZero, Series
     fillUpBody, $.jqplot.OHLCRenderer
     followMouse, $.jqplot.Cursor
     fontFamily
     fontSize
     fontStretch
     fontWeight
     forceTickAt0, $.jqplot.LinearAxisRenderer
     forceTickAt100, $.jqplot.LinearAxisRenderer
     formatString
     formatter
     Functions
    + +
    A straight dashed horizontal line.
    A straight dashed vertical line.
    dashPattern: [8,8] }
    Array of line, space settings in pixels.
    dashPattern: [8,8] }
    Array of line, space settings in pixels.
    this.data = []
    user’s data.
    this.dataLabelCenterOn = true
    True to center the data label at its position.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelNudge = 0
    Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
    this.dataLabelNudge = 2
    Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
    this.dataLabelPositionFactor = 0.4
    A Multiplier (0-1) of the pie radius which controls position of label on slice.
    this.dataLabelPositionFactor = 0.52
    A Multiplier (0-1) of the pie radius which controls position of label on slice.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.dataLabelThreshold = 3
    this.dataLabelThreshold = 3
    this.dataLabelThreshold = 3
    Threshhold in percentage (0-100) of pie area, below which no label will be displayed.
    this.dblClickReset = true
    Will reset plot zoom if double click on plot without drag.
    this.defaultAxisStart = 1
    1-D data series are internally converted into 2-D [x,y] data point arrays by jqPlot.
    this.depth = 3
    how many times the shadow is stroked.
    this.destroy = function()
    Releases all resources occupied by the plot
    this.diameter = null
    Outer diameter of the donut, auto computed by default
    this.diameter = null
    Outer diameter of the meterGauge, auto computed by default
    this.diameter = null
    Outer diameter of the pie, auto computed by default
    this.disableIEFading = true
    true to toggle series with a show/hide method only and not allow fading in/out.
    this.disableStack = false
    true to not stack this series with other series in the plot.
    this.downBodyColor = null
    Color of candlestick body on a “down” day.
    $.jqplot.ShadowRenderer.prototype.draw = function(ctx,
    points,
    options)
    draws an transparent black (i.e.
    $.jqplot.ShapeRenderer.prototype.draw = function(ctx,
    points,
    options)
    draws the shape.
    this.draw = function()
    Draws all elements of the plot into the container.
    this.drawBorder = true
    True to draw border around grid.
    this.drawGridlines = true
    wether to draw the gridlines on the plot.
    this.drawSeries = function(options,
    idx)
    Redraws all or just one series on the plot.
    + + + +
    this.edgeTolerance = -5
    Number of pixels that the label must be away from an axis boundary in order to be drawn.
    this.enableFontSupport = true
    true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
    this.enableFontSupport = true
    true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
    this.escapeHtml = false
    true to escape html in the box label.
    this.escapeHtml = true
    True to escape html in bubble label text.
    this.escapeHTML = false
    true to escape HTML entities in the label.
    this.escapeHTML = false
    true to escape HTML entities in the label.
    this.escapeHTML = true
    true to escape html entities in the labels.
    called at the end of plot drawing, binds listeners to the event canvas which lays on top of the grid area.
    + + + +
    this.fadeTooltip = true
    true = fade in/out tooltip, flase = show/hide tooltip
    this.fill = true
    true or false, wether to fil the slices.
    this.fill = true
    true or false, wether to fill the areas.
    this.fill = true
    true or false, wether to fil the slices.
    this.fill = false
    whether to fill the shape.
    this.fill = false
    whether to fill the shape.
    this.fill = false
    true or false, wether to fill under lines or in bars.
    this.fillAlpha
    Alpha transparency to apply to the fill under the line.
    this.fillAndStroke = false
    If true will stroke the line (with color this.color) as well as fill under it.
    this.fillAxis = 'y'
    Either ‘x’ or ‘y’.
    this.fillColor
    CSS color spec to use for fill under line.
    this.fillDownBody = true
    true to render a “down” day (close price lower than open price) with a filled candlestick body.
    this.fillRect = false
    true to draw shape as a filled rectangle.
    this.fillStyle = '#999999'
    css color spec for the fill style.
    this.fillToValue = 0
    fill a filled series to this value on the fill axis.
    this.fillToZero = false
    true will force bar and filled series to fill toward zero on the fill Axis.
    this.fillUpBody = false
    true to render an “up” day (close price greater than open price) with a filled candlestick body.
    this.followMouse = false
    Tooltip follows the mouse, it is not at a fixed location.
    this.fontFamily
    css spec for the font-family css attribute.
    this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'
    CSS spec for the font-family css attribute.
    this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'
    css spec for the font-family css attribute.
    this.fontFamily
    css font-family spec for the legend text.
    this.fontFamily
    css font-family spec for the text.
    this.fontSize
    css spec for the font-size css attribute.
    this.fontSize = '11pt'
    CSS spec for font size.
    this.fontSize = '10pt'
    CSS spec for font size.
    this.fontSize
    css spec for the font-size attribute.
    this.fontSize
    css font-size spec for the legend text.
    this.fontSize
    css font-size spec for the text.
    this.fontStretch = 1.0
    Multiplier to condense or expand font width.
    this.fontStretch = 1.0
    Multiplier to condense or expand font width.
    this.fontWeight = 'normal'
    this.fontWeight = 'normal'
    CSS spec for fontWeight
    this.forceTickAt0 = false
    This will ensure that there is always a tick mark at 0.
    this.forceTickAt100 = false
    This will ensure that there is always a tick mark at 100.
    this.formatString = ''
    string passed to the formatter.
    this.formatString = ''
    string passed to the formatter.
    this.formatString = null
    alternative to tooltipFormatString will format the whole tooltip text, populating with x, y values as indicated by tooltipAxes option.
    this.formatString = ''
    string passed to the formatter.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/General3.html b/phpgwapi/js/jquery/jqplot/docs/index/General3.html new file mode 100644 index 0000000000..b420086157 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/General3.html @@ -0,0 +1,50 @@ + + +Index + + + + + + + + + +
    Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    G
     get, $.jqplot.ThemeEngine
     getThemeNames, $.jqplot.ThemeEngine
     getThemes, $.jqplot.ThemeEngine
     GPL Version 2
     grid, jqPlot
     Grid
     gridLineColor, Grid
     gridLineWidth, Grid
     groups, $.jqplot.BarRenderer
    H
     hideZeros, $.jqplot.PointLabels
     highlightAlpha, $.jqplot.BubbleRenderer
     highlightColor, $.jqplot.LineRenderer
     highlightColors
     highlightMouseDown
     highlightMouseOver
     hlc, $.jqplot.OHLCRenderer
     Hooks, $.jqplot
     HorizontalLine
     hubRadius, $.jqplot.MeterGaugeRenderer
    I
     index, Series
     init, jqPlot
     innerDiameter, $.jqplot.DonutRenderer
     insertBreaks, $.jqplot.BlockRenderer
     intersectionThreshold, $.jqplot.Cursor
     intervalColors, $.jqplot.MeterGaugeRenderer
     intervalInnerRadius, $.jqplot.MeterGaugeRenderer
     intervalOuterRadius, $.jqplot.MeterGaugeRenderer
     intervals, $.jqplot.MeterGaugeRenderer
     Introduction
     isarc
     isMinorTick
    J
     jqPlot
     jqPlot Charts
     jqPlot CSS Customization
     jqPlot Options
     jqPlot Pugin Hooks, $.jqplot
     jqPlot Usage
     jqplot.enhancedLegendRenderer.js
    L
     label
     labelHeightAdjust, $.jqplot.MeterGaugeRenderer
     labelOptions, Axis
     labelPosition
     labelRenderer, Axis
     labels
     labelsFromSeries, $.jqplot.PointLabels
     legend, jqPlot
     Legend
     Line
     lineCap
     lineJoin
     lineWidth
     lineWidthAdjust, $.jqplot.Highlighter
     location
     looseZoom, $.jqplot.Cursor
    + +
    $.jqplot.ThemeEngine.prototype.get = function(name)
    Get and return the named theme or the active theme if no name given.
    $.jqplot.ThemeEngine.prototype.getThemeNames = function()
    Return the list of theme names in this manager in alpha-numerical order.
    $.jqplot.ThemeEngine.prototype.getThemes = function()
    Return a list of themes in alpha-numerical order by name.
    GNU GENERAL PUBLIC LICENSE Version 2, June 1991
    this.grid = new Grid()
    See Grid for grid specific options.
    Object representing the grid on which the plot is drawn.
    this.gridLineColor = '#cccccc'
    color of the grid lines.
    this.gridLineWidth = 1.0
    width of the grid lines.
    this.groups = 1
    group bars into this many groups
    + + + +
    this.hideZeros = false
    true to not show a label for a value which is 0.
    this.highlightAlpha = null
    Alpha transparency to apply when highlighting bubble.
    this.highlightColor = null
    color to use when highlighting an area on a filled plot.
    this.highlightColors = []
    an array of colors to use when highlighting a bar.
    this.highlightColors = []
    An array of colors to use when highlighting a slice.
    this.highlightColors = []
    an array of colors to use when highlighting a slice.
    this.highlightColors = []
    array of colors to use when highlighting an area.
    this.highlightColors = []
    an array of colors to use when highlighting a slice.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a bubble.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a area.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over an area on a filled plot.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.highlightMouseOver = true
    True to highlight bubbles when moused over.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.highlightMouseOver = true
    True to highlight area when moused over.
    this.highlightMouseOver = true
    True to highlight area on a filled plot when moused over.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.hlc = false
    true if is a hi-low-close chart (no open price).
    A straight horizontal line.
    this.hubRadius = null
    Radius of the hub at the bottom center of gauge which the needle attaches to.
    + + + +
    this.index
    0 based index of this series in the plot series array.
    this.init = function(target,
    data,
    options)
    sets the plot target, checks data and applies user options to plot.
    this.innerDiameter = null
    Inner diameter of the donut, auto calculated by default.
    this.insertBreaks = true
    true to turn spaces in data block label into html breaks br /.
    this.intersectionThreshold = 2
    pixel distance from data point or marker to consider cursor lines intersecting with point.
    this.intervalColors = [ "#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"]
    Array of colors to use for the intervals.
    this.intervalInnerRadius = null
    Radius of the inner circle of the interval ring.
    this.intervalOuterRadius = null
    Radius of the outer circle of the interval ring.
    this.intervals = []
    Array of ranges to be drawn around the gauge.
    jqPlot requires jQuery (1.4+ required for certain features).
    this.isarc = false
    wether the shadow is an arc or not.
    this.isarc = false
    wether the shadow is an arc or not.
    this.isMinorTick = false
    if this is a minor tick.
    this.isMinorTick = false
    if this is a minor tick.
    + + + +
    Plot object returned by call to $.jqplot.
    Pure JavaScript plotting plugin for jQuery.
    Much of the styling of jqPlot is done by css.
    This document is out of date.
    + + + +
    this.label = ''
    The text or html for the label.
    this.label = ''
    label for the axis.
    this.label = null
    A gauge label like ‘kph’ or ‘Volts’
    this.label = ''
    Label for the trend line to use in the legend.
    this.label = null
    Label for the axis
    this.label = ''
    Line label to use in the legend.
    this.labelHeightAdjust = 0
    Number of Pixels to offset the label up (-) or down (+) from its default position.
    this.labelOptions = {}
    Options passed to the label renderer.
    this.labelPosition = 'auto'
    ‘auto’, ‘start’, ‘middle’ or ‘end’.
    this.labelPosition = 'inside'
    Where to position the label, either ‘inside’ or ‘bottom’.
    this.labelRenderer = $.jqplot.AxisLabelRenderer
    A class of a rendering engine for creating an axis label.
    this.labels = []
    array of arrays of labels, one array for each series.
    this.labels = []
    Array of labels to use.
    this.labelsFromSeries = false
    true to use labels within data point arrays.
    this.legend = new Legend()
    see $.jqplot.TableLegendRenderer
    Legend object.
    A straight line.
    this.lineCap = 'round'
    how ends of the shadow line are rendered.
    this.lineCap = 'round'
    how ends of the shadow line are rendered.
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    this.lineCap = 'round'
    Canvas lineCap style at ends of line.
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    this.lineJoin = 'miter'
    How line segments of the shadow are joined.
    this.lineJoin = 'miter'
    How line segments of the shadow are joined.
    this.lineJoin = 'round'
    Canvas lineJoin style between segments of series.
    this.lineWidth = 2
    width of line if areas are stroked and not filled.
    this.lineWidth = 2
    size of the line for non-filled markers.
    this.lineWidth = 1.5
    Width of the hi-low line and open/close ticks.
    this.lineWidth = 1.5
    width of the shadow line stroke.
    this.lineWidth = 1.5
    Width of the trend line.
    Width of the line.
    Width of the line.
    Width of the line.
    Width of the line.
    this.lineWidth = 2.5
    width of the line in pixels.
    Width of the line.
    this.lineWidthAdjust = 2.5
    Pixels to add to the lineWidth of the highlight.
    this.location = 'n'
    compass location where to position the label around the point.
    this.location = 'ne'
    Placement of the legend.
    this.looseZoom = false
    Will expand zoom range to provide more rounded tick values.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/General4.html b/phpgwapi/js/jquery/jqplot/docs/index/General4.html new file mode 100644 index 0000000000..7f6ea48807 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/General4.html @@ -0,0 +1,50 @@ + + +Index + + + + + + + + + +
    Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    M
     makeGridData
     marginBottom, Legend
     marginLeft, Legend
     marginRight, Legend
     marginTop, Legend
     mark
     markerOptions, Series
     markerRenderer
     markSize
     max
     methods
     Methods, $.jqplot.BlockRenderer
     min
     MIT License
     moveBlock, $.jqplot.BlockRenderer
     moveSeriesToBack, jqPlot
     moveSeriesToFront, jqPlot
    N
     name
     needlePad, $.jqplot.MeterGaugeRenderer
     needleThickness, $.jqplot.MeterGaugeRenderer
     neighborThreshold, Series
     newTheme, $.jqplot.ThemeEngine
     numberColumns
     numberRows
     numberTicks, Axis
    O
     objects, $.jqplot.CanvasOverlay
     offset, $.jqplot.shadowRenderer
     openColor, $.jqplot.OHLCRenderer
     Options Tutorial
     Options Usage
    P
     pad, Axis
     padding
     padMax, Axis
     padMin, Axis
     pegNeedle, $.jqplot.MeterGaugeRenderer
     placement, Legend
     postDrawHooks, $.jqplot.$.jqplot
     postDrawSeriesHooks, $.jqplot.$.jqplot
     postDrawSeriesShadowHooks, $.jqplot.$.jqplot
     postInitHooks, $.jqplot.$.jqplot
     postParseOptionsHooks, $.jqplot.$.jqplot
     postParseSeriesOptionsHooks, $.jqplot.$.jqplot
     postSeriesInitHooks, $.jqplot.$.jqplot
     predraw, Legend
     preDrawHooks, $.jqplot.$.jqplot
     preDrawLegendHooks, $.jqplot.$.jqplot
     preDrawSeriesHooks, $.jqplot.$.jqplot
     preDrawSeriesShadowHooks, $.jqplot.$.jqplot
     prefix
     preInitHooks, $.jqplot.$.jqplot
     preParseOptionsHooks, $.jqplot.$.jqplot
     preParseSeriesOptionsHooks, $.jqplot.$.jqplot
     preSeriesInitHooks, $.jqplot.$.jqplot
     Properties
     pt2px
    R
     redraw, jqPlot
     reInitialize, jqPlot
     remove, $.jqplot.ThemeEngine
     rename, $.jqplot.ThemeEngine
     renderer
     rendererOptions
     replot, jqPlot
     resetAxesScale, jqPlot
     restoreOriginalSeriesOrder, jqPlot
     restorePreviousSeriesOrder, jqPlot
     ringColor, $.jqplot.MeterGaugeRenderer
     ringMargin, $.jqplot.DonutRenderer
     ringWidth, $.jqplot.MeterGaugeRenderer
     rowSpacing, Legend
    + +
    $.jqplot.BezierCurveRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    $.jqplot.LineRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    $.jqplot.MekkoRenderer.prototype.makeGridData = function(data,
    plot)
    converts any arbitrary data values to grid coordinates and returns them.
    this.marginBottom = null
    CSS margin for the legend DOM element.
    this.marginLeft = null
    CSS margin for the legend DOM element.
    this.marginRight = null
    CSS margin for the legend DOM element.
    this.marginTop = null
    CSS margin for the legend DOM element.
    this.mark = 'outside'
    tick mark on the axis.
    this.mark = 'outside'
    tick mark on the axis.
    this.markerOptions = {}
    renderer specific options to pass to the markerRenderer, see $.jqplot.MarkerRenderer.
    this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false})
    Renderer used to draw the marker of the highlighted point.
    this.markerRenderer = {show:false}
    Renderer to use to draw markers on the line.
    this.markerRenderer = $.jqplot.MarkerRenderer
    A class of a renderer which will draw marker (e.g.
    this.markSize = 6
    Length of the tick marks in pixels.
    this.markSize = 4
    Length of the tick marks in pixels.
    this.max
    Maximum value on the gauge.
    this.max=null
    maximum value of the axis (in data units, not pixels).
    this.min
    Minimum value on the gauge.
    this.min=null
    minimum value of the axis (in data units, not pixels).
    Copyright © 2009-2011 Chris Leonello
    this.moveBlock = function (idx,
    x,
    y,
    duration)
    Moves an individual block.
    this.moveSeriesToBack = function (idx)
    This method requires jQuery 1.4+ Moves the specified series canvas behind all other series canvases.
    this.moveSeriesToFront = function (idx)
    This method requires jQuery 1.4+ Moves the specified series canvas in front of all other series canvases.
    + + + +
    Optional name for this overlay object.
    Optional name for this overlay object.
    Optional name for this overlay object.
    Optional name for this overlay object.
    Optional name for this overlay object.
    this.needlePad = 6
    Padding between needle and inner edge of the ring when the needle is at the min or max gauge value.
    this.needleThickness = null
    Maximum thickness the needle.
    this.neighborThreshold = 4
    how close or far (in pixels) the cursor must be from a point marker to detect the point.
    $.jqplot.ThemeEngine.prototype.newTheme = function(name,
    obj)
    Create a new theme based on the default theme, adding it the themeEngine.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberTicks
    Desired number of ticks.
    + + + +
    this.objects = []
    this.offset = 1
    Pixel offset at the given shadow angle of each shadow stroke from the last stroke.
    this.openColor = null
    color of the open price tick mark.
    This document will help you understand how jqPlot’s options relate to the API documentation and the jqPlot object itself.
    See Options Tutorial
    + + + +
    this.pad = 1.2
    Padding to extend the range above and below the data bounds.
    this.padding = 20
    padding between the donut and plot edges, legend, etc.
    this.padding = {top: 20, right: 20, bottom: 20, left: 20}
    padding between the funnel and plot edges, legend, etc.
    this.padding = null
    padding between the meterGauge and plot edges, auto calculated by default.
    this.padding = 20
    padding between the pie and plot edges, legend, etc.
    this.padMax = null
    Padding to extend the range above data bounds.
    this.padMin = null
    Padding to extend the range below data bounds.
    this.pegNeedle = true
    True will stop needle just below/above the min/max values if data is below/above min/max, as if the meter is “pegged”.
    this.placement = "insideGrid"
    “insideGrid” places legend inside the grid area of the plot.
    called after plot draw.
    called after each series is drawn.
    called after series shadows are drawn.
    called after initialization.
    called after user options are parsed.
    called after series related options are parsed.
    called after series is initialized.
    Wether to draw the legend before the series or not.
    called before plot draw.
    called before the legend is drawn.
    called before each series is drawn.
    called before series shadows are drawn.
    this.prefix = ''
    String to prepend to the tick label.
    this.prefix = ''
    String to prepend to the tick label.
    called before initialization.
    called before user options are parsed.
    called before series related options are parsed.
    called before series is initialized.
    Properties
    Axes options are specified within an axes object at the top level of the plot options like so:
    These properties are specified at the top of the options object like so:
    Properties will be assigned from a series array at the top level of the options.
    this.pt2px = null
    Point to pixel scaling factor, used for computing height of bounding box around a label.
    this.pt2px = null
    Point to pixel scaling factor, used for computing height of bounding box around a label.
    + + + +
    this.redraw = function(clear)
    Empties the plot target div and redraws the plot.
    this.reInitialize = function ()
    reinitialize plot for replotting.
    $.jqplot.ThemeEngine.prototype.remove = function(name)
    Remove the given theme from the themeEngine.
    $.jqplot.ThemeEngine.prototype.rename = function (oldName,
    newName)
    Rename a theme.
    this.renderer = new $.jqplot.LineRenderer()
    Renderer to use to draw the trend line.
    this.renderer = $.jqplot.LinearAxisRenderer
    A class of a rendering engine that handles tick generation, scaling input data to pixel grid units and drawing the axis element.
    this.renderer = $.jqplot.CanvasGridRenderer
    Instance of a renderer which will actually render the grid, see $.jqplot.CanvasGridRenderer.
    this.renderer = $.jqplot.LineRenderer
    A class of a renderer which will draw the series, see $.jqplot.LineRenderer.
    this.renderer = $.jqplot.DivTitleRenderer
    A class for creating a DOM element for the title, see $.jqplot.DivTitleRenderer.
    this.rendererOptions = {marker:{show:false}}
    Options to pass to the line renderer.
    this.rendererOptions = {}
    renderer specific options.
    this.rendererOptions = {}
    Options to pass on to the renderer, see $.jqplot.CanvasGridRenderer.
    this.rendererOptions = {}
    renderer specific options passed to the renderer.
    this.rendererOptions = {}
    Options to pass on to the renderer.
    this.rendererOptions = {}
    renderer specific options passed to the renderer.
    this.replot = function(options)
    Does a reinitialization of the plot followed by a redraw.
    this.resetAxesScale = function(axes,
    options)
    Reset the specified axes min, max, numberTicks and tickInterval properties to null or reset these properties on all axes if no list of axes is provided.
    this.restoreOriginalSeriesOrder = function ()
    This method requires jQuery 1.4+ Restore the series canvas order to its original order when the plot was created.
    this.restorePreviousSeriesOrder = function ()
    This method requires jQuery 1.4+ Restore the series canvas order to its previous state.
    this.ringColor = "#BBC6D0"
    color of the outer ring, hub, and needle of the gauge.
    this.ringMargin = null
    pixel distance between rings, or multiple series in a donut plot.
    this.ringWidth = null
    width of the ring around the gauge.
    this.rowSpacing = '0.5em'
    css padding-top spec for the rows in the legend.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/General5.html b/phpgwapi/js/jquery/jqplot/docs/index/General5.html new file mode 100644 index 0000000000..6d6ed5b23c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/General5.html @@ -0,0 +1,34 @@ + + +Index + + + + + + + + + +
    Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    S
     sectionMargin, $.jqplot.FunnelRenderer
     series, jqPlot
     Series
     seriesColors, jqPlot
     seriesDefaults, jqPlot
     seriesLabelIndex, $.jqplot.PointLabels
     seriesToggle
     setGridData
     shadow
     shadowAlpha
     shadowAngle
     shadowColor, Grid
     shadowDepth
     shadowOffset
     shadowRenderer, $.jqplot.MarkerRenderer
     shadowWidth, Grid
     shapeRenderer, $.jqplot.MarkerRenderer
     show
     showBorders, $.jqplot.MekkoRenderer
     showCursorLegend, $.jqplot.Cursor
     showDataLabels
     showGridline
     showHorizontalLine, $.jqplot.Cursor
     showLabel
     showLabels
     showLine, Series
     showMark
     showMarker
     showMinorTicks, Axis
     showSwatch, Legend
     showTickLabels, $.jqplot.MeterGaugeRenderer
     showTickMarks, Axis
     showTicks
     showTooltip
     showTooltipDataPosition, $.jqplot.Cursor
     showTooltipGridPosition, $.jqplot.Cursor
     showTooltipOutsideZoom, $.jqplot.Cursor
     showTooltipUnitPosition, $.jqplot.Cursor
     showVerticalLine, $.jqplot.Cursor
     size
     sizeAdjust, $.jqplot.Highlighter
     sliceMargin
     sortData, jqPlot
     sortMergedLabels, $.jqplot.CategoryAxisRenderer
     stackedValue, $.jqplot.PointLabels
     stackSeries, jqPlot
     start, Line
     startAngle
     stop, Line
     strokeRect, $.jqplot.shapeRenderer
     strokeStyle, $.jqplot.shapeRenderer
     style
     syncTicks, Axis
    + +
    this.sectionMargin = 6
    spacing between funnel sections in pixels.
    this.series = []
    Array of series object options.
    An individual data series object.
    this.seriesColors = $.jqplot.config.defaultColors
    Ann array of CSS color specifications that will be applied, in order, to the series in the plot.
    seriesDefaults: {}, series:[] }
    default options that will be applied to all series.
    this.seriesLabelIndex = null
    array index for location of labels within data point arrays.
    this.seriesToggle = 'normal'
    false to not enable series on/off toggling on the legend.
    $.jqplot.BezierCurveRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    $.jqplot.LineRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    $.jqplot.MekkoRenderer.prototype.setGridData = function(plot)
    converts the user data values to grid coordinates and stores them in the gridData array.
    this.shadow = true
    wether or not to draw a shadow on the line
    this.shadow = true
    true or false, wether or not to show the shadow.
    wether or not to draw a shadow on the line
    wether or not to draw a shadow on the line
    this.shadow = true
    wether to show a shadow behind the grid.
    wether or not to draw a shadow on the line
    wether or not to draw a shadow on the line
    this.shadow = true
    wether or not to draw a shadow on the line
    wether or not to draw a shadow on the line
    this.shadowAlpha = 0.08
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = '0.07'
    Alpha channel transparency of shadow.
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = 0.07
    Alpha transparency of the shadow.
    Alpha channel transparency of shadow.
    Alpha channel transparency of shadow.
    this.shadowAlpha = '0.07'
    Alpha channel transparency of shadow.
    Alpha channel transparency of shadow.
    Alpha channel transparency of shadow.
    this.shadowAlpha = '0.1'
    Alpha channel transparency of shadow.
    Alpha channel transparency of shadow.
    this.shadowAngle = 45
    Shadow angle in degrees
    this.shadowAngle = 45
    Angle of the shadow on the trend line.
    Shadow angle in degrees
    Shadow angle in degrees
    this.shadowAngle = 45
    shadow angle in degrees
    Shadow angle in degrees
    Shadow angle in degrees
    this.shadowAngle = 45
    Shadow angle in degrees
    Shadow angle in degrees
    this.shadowColor = null
    an optional css color spec for the shadow in ‘rgba(n, n, n, n)’ form
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowDepth = 4
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 3
    number of strokes to make of the shadow.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 2
    offset of the shadow from the area and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 1
    Shadow offset from line in pixels
    this.shadowOffset = 2
    offset of the shadow from the gauge ring and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 1.0
    pixel offset for each stroke of the shadow.
    Shadow offset from line in pixels
    Shadow offset from line in pixels
    this.shadowOffset = 1.5
    Offset of each shadow stroke from the border in pixels
    Shadow offset from line in pixels
    Shadow offset from line in pixels
    this.shadowOffset = 1.25
    Shadow offset from line in pixels
    Shadow offset from line in pixels
    this.shadowRenderer = new $.jqplot.ShadowRenderer()
    Renderer that will draws the shadows on the marker.
    this.shadowWidth = 3
    width of the stoke for the shadow
    this.shapeRenderer = new $.jqplot.ShapeRenderer()
    Renderer that will draw the marker.
    this.show = true
    wether or not to show the tick (mark and label).
    this.show = true
    wether or not to show the tick (mark and label).
    this.show = true
    wether or not to show the tick (mark and label).
    this.show = true
    wether or not to show the tick (mark and label).
    this.show = $.jqplot.config.enablePlugins
    wether to show the cursor or not.
    this.show = $.jqplot.config.enablePlugins
    true to show the highlight.
    this.show = true
    wether or not to show the marker.
    this.show = $.jqplot.config.enablePlugins
    show the labels or not.
    this.show = $.jqplot.config.enablePlugins
    Wether or not to show the trend line.
    this.show = false
    Wether to display the axis on the graph.
    true to show (draw), false to not draw.
    true to show (draw), false to not draw.
    true to show (draw), false to not draw.
    this.show = false
    Wether to display the legend on the graph.
    true to show (draw), false to not draw.
    this.show = true
    wether or not to draw the series.
    this.show = true
    wether or not to show the title
    true to show (draw), false to not draw.
    this.showBorders = true
    True to draw borders lines between areas on the chart.
    this.showCursorLegend = false
    Replace the plot legend with an enhanced legend displaying intersection information.
    this.showDataLabels = false
    true to show data labels on slices.
    this.showDataLabels = false
    true to show data labels on slices.
    this.showDataLabels = false
    true to show data labels on slices.
    this.showGridline = true
    wether or not to draw the gridline on the grid at this tick.
    this.showGridline = true
    wether or not to draw the gridline on the grid at this tick.
    this.showHorizontalLine = false
    draw a horizontal line across the plot which follows the cursor.
    this.showLabel = true
    wether or not to show the label.
    this.showLabel = true
    wether or not to show the label.
    this.showLabel = true
    wether or not to show the label.
    this.showLabel = true
    true to show the axis label.
    this.showLabel = true
    true to show label for this series in the legend.
    this.showLabels = true
    True to show labels on bubbles (if any), false to not show.
    this.showLabels = true
    true to show the label text on the legend.
    this.showLine = true
    wether to actually draw the line or not.
    this.showMark = true
    wether or not to show the mark on the axis.
    this.showMark = true
    wether or not to show the mark on the axis.
    this.showMarker = true
    true to show the marker
    this.showMarker = true
    wether or not to show the markers at the data points.
    this.showMinorTicks = true
    Wether or not to show minor ticks.
    this.showSwatches = true
    true to show the color swatches on the legend.
    this.showTickLabels = true
    true to show tick labels next to ticks.
    this.showTickMarks = true
    Wether to show the tick marks (line crossing grid) or not.
    this.showTicks = true
    true to show ticks around gauge.
    this.showTicks = true
    Wether to show the ticks (both marks and labels) or not.
    this.showTooltip = true
    show a cursor position tooltip.
    this.showTooltip = true
    Show a tooltip with data point values.
    this.showTooltipDataPosition = false
    Used with showVerticalLine to show intersecting data points in the tooltip.
    this.showTooltipGridPosition = false
    show the grid pixel coordinates of the mouse.
    this.showTooltipOutsideZoom = false
    True will keep updating the tooltip when zooming of the grid.
    this.showTooltipUnitPosition = true
    show the unit (data) coordinates of the mouse.
    this.showVerticalLine = false
    draw a vertical line across the plot which follows the cursor.
    this.size = 4
    Length of the tick beyond the grid in pixels.
    this.size = 9.0
    Size of the marker (diameter or circle, length of edge of square, etc.)
    this.sizeAdjust = 5
    Pixels to add to the overall size of the highlight.
    this.sliceMargin = 0
    angular spacing between donut slices in degrees.
    this.sliceMargin = 0
    angular spacing between pie slices in degrees.
    this.sortData = true
    false to not sort the data passed in by the user.
    this.sortMergedLabels = false
    True to sort tick labels when labels are created by merging x axis values from multiple series.
    this.stackedValue = false
    true to display value as stacked in a stacked plot.
    this.stackSeries = false
    true or false, creates a stack or “mountain” plot.
    [x, y] coordinates for the start of the line.
    this.startAngle = 0
    Angle to start drawing donut in degrees.
    this.startAngle = 0
    Angle to start drawing pie in degrees.
    stop: [] }
    [x, y] coordinates for the end of the line.
    this.strokeRect = false
    true to draw shape as a stroked rectangle.
    this.strokeStyle = '#999999'
    css color spec for the stoke style
    this.style = 'crosshair'
    CSS spec for cursor style
    this.style = 'filledCircle'
    One of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare
    this.syncTicks = null
    true to try and synchronize tick spacing across multiple axes so that ticks and grid lines line up.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/General6.html b/phpgwapi/js/jquery/jqplot/docs/index/General6.html new file mode 100644 index 0000000000..51f3c028e9 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/General6.html @@ -0,0 +1,58 @@ + + +Index + + + + + + + + + +
    Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    T
     text, Title
     textAlign, Title
     textColor
     themes, $.jqplot.ThemeEngine
     thickness, $.jqplot.DonutRenderer
     tickColor, $.jqplot.MeterGaugeRenderer
     tickInterval, Axis
     tickLength, $.jqplot.OHLCRenderer
     tickMode, $.jqplot.MekkoAxisRenderer
     tickOptions, Axis
     tickPadding, $.jqplot.MeterGaugeRenderer
     tickRenderer
     ticks
     tickSpacing
     title, jqPlot
     Title
     tooltipAxes, $.jqplot.Highlighter
     tooltipAxisGroups, $.jqplot.Cursor
     tooltipFadeSpeed, $.jqplot.Highlighter
     tooltipFormatString
     tooltipLocation
     tooltipOffset
     type, $.jqplot.Trendline
    U
     upBodyColor, $.jqplot.OHLCRenderer
     Usage
     useAxesFormatters
     useNegativeColors, Series
     useSeriesColor, Axis
    V
     varyBarColor, $.jqplot.BarRenderer
     varyBlockColors, $.jqplot.BlockRenderer
     varyBubbleColors, $.jqplot.BubbleRenderer
     Version
     VerticalLine
    W
     waterfall, $.jqplot.BarRenderer
     wickColor, $.jqplot.OHLCRenderer
     widthRatio, $.jqplot.FunnelRenderer
    X
     xaxis
     xmax, HorizontalLine
     xmin, HorizontalLine
     xoffset, Legend
     xpadding, $.jqplot.PointLabels
    Y
     y, HorizontalLine
     yaxis
     yoffset, Legend
     ypadding, $.jqplot.PointLabels
     yvalues, $.jqplot.Highlighter
    Z
     zoom, $.jqplot.Cursor
     zoomProxy, $.jqplot.Cursor.$.jqplot.Cursor
    + +
    this.text = text
    text of the title;
    this.textAlign
    css text-align spec for the text.
    this.textColor
    css spec for the color attribute.
    this.textColor = '#666666'
    css spec for the color attribute.
    this.textColor = '#666666'
    css spec for the color attribute.
    this.textColor
    css color spec for the legend text.
    this.textColor
    css color spec for the text.
    this.themes = {}
    hash of themes managed by the theme engine.
    this.thickness = null
    thickness of the donut, auto computed by default Overridden by if innerDiameter is specified.
    this.tickColor = "989898"
    color of the tick marks around the gauge.
    this.tickInterval
    number of units between ticks.
    this.tickLength = 'auto'
    length of the line in pixels indicating open and close price.
    this.tickMode
    How to space the ticks on the axis.
    this.tickOptions = {}
    Options that will be passed to the tickRenderer, see $.jqplot.AxisTickRenderer options.
    this.tickPadding = null
    padding of the tick marks to the outer ring and the tick labels to marks.
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    this.tickRenderer = $.jqplot.AxisTickRenderer
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    this.ticks = []
    Array of tick values.
    this.ticks = []
    1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis.
    this.tickSpacing = 30
    Degrees between ticks.
    this.tickSpacing = 75
    Approximate pixel spacing between ticks on graph.
    this.title = new Title()
    Title object.
    Plot Title object.
    this.tooltipAxes = 'both'
    Which axes to display in tooltip, ‘x’, ‘y’ or ‘both’, ‘xy’ or ‘yx’ ‘both’ and ‘xy’ are equivalent, ‘yx’ reverses order of labels.
    this.tooltipAxisGroups = []
    Show position for the specified axes.
    this.tooltipFadeSpeed = "fast"
    ‘slow’, ‘def’, ‘fast’, or number of milliseconds.
    this.tooltipFormatString = '%.4P, %.4P'
    sprintf format string for the tooltip.
    this.tooltipFormatString = '%.5P'
    sprintf format string for the tooltip.
    this.tooltipLocation = 'se'
    Where to position tooltip.
    this.tooltipLocation = 'nw'
    Where to position tooltip, ‘n’, ‘ne’, ‘e’, ‘se’, ‘s’, ‘sw’, ‘w’, ‘nw’
    this.tooltipOffset = 6
    Pixel offset of tooltip from the grid boudaries or cursor center.
    this.tooltipOffset = 2
    Pixel offset of tooltip from the highlight.
    this.type = 'linear'
    Either ‘exponential’, ‘exp’, or ‘linear’.
    + + + +
    this.upBodyColor = null
    Color of candlestick body of an “up” day.
    See jqPlot Usage
    this.useAxesFormatters = true
    Use the x and y axes formatters to format the text in the tooltip.
    this.useAxesFormatters = true
    Use the x and y axes formatters to format the text in the tooltip.
    this.useNegativeColors = true
    true to color negative values differently in filled and bar charts.
    this.useSeriesColor = false
    Use the color of the first series associated with this axis for the tick marks and line bordering this axis.
    + + + +
    this.varyBarColor = false
    true to color each bar of a series separately rather than have every bar of a given series the same color.
    this.varyBlockColors = false
    true to vary the color of each block in this series according to the seriesColors array.
    this.varyBubbleColors = true
    True to vary the color of each bubble in this series according to the seriesColors array.
    1.0.0b2_r792
    A straight vertical line.
    + + + +
    this.waterfall = false
    true to enable waterfall plot.
    this.wickColor = null
    color of the hi-lo line thorugh the candlestick body.
    this.widthRatio = 0.2
    The ratio of the width of the top of the funnel to the bottom.
    + + + +
    X axis to use for positioning/scaling the line.
    X axis to use for positioning/scaling the line.
    X axis to use for positioning/scaling the line.
    X axis to use for positioning/scaling the line.
    this.xaxis = 'xaxis'
    which x axis to use with this series, either ‘xaxis’ or ‘x2axis’.
    X axis to use for positioning/scaling the line.
    x value for the end of the line, null to scale to axis max.
    x value for the start of the line, null to scale to axis min.
    this.xoffset = 0
    DEPRECATED.
    this.xpadding = 6
    horizontal padding in pixels between point and label
    + + + +
    y value to position the line
    Y axis to use for positioning/scaling the line.
    Y axis to use for positioning/scaling the line.
    Y axis to use for positioning/scaling the line.
    Y axis to use for positioning/scaling the line.
    this.yaxis = 'yaxis'
    which y axis to use with this series, either ‘yaxis’ or ‘y2axis’.
    yaxis: 'yaxis', x: null, ymin: null, ymax: null, yOffset: '6px', // number or string. Number interpreted as units, string as pixels. yminOffset: null, ymaxOffset: null }
    Y axis to use for positioning/scaling the line.
    this.yoffset = 0
    DEPRECATED.
    this.ypadding = 6
    vertical padding in pixels between point and label
    this.yvalues = 1
    Number of y values to expect in the data point array.
    + + + +
    this.zoom = false
    Enable plot zooming.
    $.jqplot.Cursor.zoomProxy = function(targetPlot,
    controllerPlot)
    links targetPlot to controllerPlot so that plot zooming of targetPlot will be controlled by zooming on the controllerPlot.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Hooks.html b/phpgwapi/js/jquery/jqplot/docs/index/Hooks.html new file mode 100644 index 0000000000..79456ac4d3 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Hooks.html @@ -0,0 +1,46 @@ + + +Hook Index + + + + + + + + + +
    Hook Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    A
     addLegendRowHooks, $.jqplot.$.jqplot
    E
     eventListenerHooks, $.jqplot.$.jqplot
    J
     jqPlot Pugin Hooks, $.jqplot
    P
     postDrawHooks, $.jqplot.$.jqplot
     postDrawSeriesHooks, $.jqplot.$.jqplot
     postDrawSeriesShadowHooks, $.jqplot.$.jqplot
     postInitHooks, $.jqplot.$.jqplot
     postParseOptionsHooks, $.jqplot.$.jqplot
     postParseSeriesOptionsHooks, $.jqplot.$.jqplot
     postSeriesInitHooks, $.jqplot.$.jqplot
     preDrawHooks, $.jqplot.$.jqplot
     preDrawLegendHooks, $.jqplot.$.jqplot
     preDrawSeriesHooks, $.jqplot.$.jqplot
     preDrawSeriesShadowHooks, $.jqplot.$.jqplot
     preInitHooks, $.jqplot.$.jqplot
     preParseOptionsHooks, $.jqplot.$.jqplot
     preParseSeriesOptionsHooks, $.jqplot.$.jqplot
     preSeriesInitHooks, $.jqplot.$.jqplot
    + +
    called at the end of legend draw, so plugins can add rows to the legend table.
    + + + +
    called at the end of plot drawing, binds listeners to the event canvas which lays on top of the grid area.
    + + + + + + + +
    called after plot draw.
    called after each series is drawn.
    called after series shadows are drawn.
    called after initialization.
    called after user options are parsed.
    called after series related options are parsed.
    called after series is initialized.
    called before plot draw.
    called before the legend is drawn.
    called before each series is drawn.
    called before series shadows are drawn.
    called before initialization.
    called before user options are parsed.
    called before series related options are parsed.
    called before series is initialized.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Properties.html b/phpgwapi/js/jquery/jqplot/docs/index/Properties.html new file mode 100644 index 0000000000..16fa8c5dec --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Properties.html @@ -0,0 +1,50 @@ + + +Property Index + + + + + + + + + +
    Property Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    A
     activeTheme, $.jqplot.ThemeEngine
     alpha, $.jqplot.shadowRenderer
     angle
     autoscale, Axis
     autoscaleBubbles, $.jqplot.BubbleRenderer
     autoscaleMultiplier, $.jqplot.BubbleRenderer
     autoscalePointsFactor, $.jqplot.BubbleRenderer
     axes, jqPlot
     axesDefaults, jqPlot
     axisDefaults, $.jqplot.LogAxisRenderer
    B
     background
     barDirection, $.jqplot.BarRenderer
     barLabelOptions, $.jqplot.MekkoAxisRenderer
     barLabelRenderer, $.jqplot.MekkoAxisRenderer
     barLabels, $.jqplot.MekkoAxisRenderer
     barMargin, $.jqplot.BarRenderer
     barPadding, $.jqplot.BarRenderer
     barWidth, $.jqplot.BarRenderer
     bodyWidth, $.jqplot.OHLCRenderer
     border, Legend
     borderColor
     borderWidth
     breakOnNull, Series
     breakPoints, $.jqplot.LinearAxisRenderer
     breakTickLabel, $.jqplot.LinearAxisRenderer
     bringSeriesToFront, $.jqplot.Highlighter
     bubbleAlpha, $.jqplot.BubbleRenderer
     bubbleGradients, $.jqplot.BubbleRenderer
    C
     candleStick, $.jqplot.OHLCRenderer
     clearRect, $.jqplot.shapeRenderer
     clickReset, $.jqplot.Cursor
     closeColor, $.jqplot.OHLCRenderer
     color
     constrainOutsideZoom, $.jqplot.Cursor
     constrainTo, $.jqplot.Dragable
     constrainZoomTo, $.jqplot.Cursor
     css, $.jqplot.BlockRenderer
     cursorLegendFormatString, $.jqplot.Cursor
    D
     dashPattern
     data, jqPlot
     dataLabelCenterOn, $.jqplot.PieRenderer
     dataLabelFormatString
     dataLabelNudge
     dataLabelPositionFactor
     dataLabels
     dataLabelThreshold
     dblClickReset, $.jqplot.Cursor
     defaultAxisStart, jqPlot
     depth, $.jqplot.shadowRenderer
     diameter
     disableIEFading
     disableStack, Series
     downBodyColor, $.jqplot.OHLCRenderer
     drawBorder, Grid
     drawGridlines, Grid
    E
     edgeTolerance, $.jqplot.PointLabels
     enableFontSupport
     escapeHtml
     escapeHTML
    + +
    this.activeTheme=null
    Pointer to currently active theme
    this.alpha = 0.07
    alpha transparency of shadow stroke.
    this.angle = 0
    angle of text, measured clockwise from x axis.
    this.angle = 0
    angle of text, measured clockwise from x axis.
    this.angle = 45
    Angle of the shadow in degrees.
    this.autoscale = false
    Autoscale the axis min and max values to provide sensible tick spacing.
    this.autoscaleBubbles = true
    True to scale the bubble radius based on plot size.
    this.autoscaleMultiplier = 1.0
    Multiplier the bubble size if autoscaleBubbles is true.
    this.autoscalePointsFactor = -0.07
    Factor which decreases bubble size based on how many bubbles on on the chart.
    this.axes = {xaxis: new Axis('xaxis'), yaxis: new Axis('yaxis'), x2axis: new Axis('x2axis'), y2axis: new Axis('y2axis'), y3axis: new Axis('y3axis'), y4axis: new Axis('y4axis'), y5axis: new Axis('y5axis'), y6axis: new Axis('y6axis'), y7axis: new Axis('y7axis'), y8axis: new Axis('y8axis'), y9axis: new Axis('y9axis')}
    up to 4 axes are supported, each with it’s own options, See Axis for axis specific options.
    default options that will be applied to all axes.
    Default properties which will be applied directly to the series.
    + + + +
    this.background = "#efefef"
    background color of the inside of the gauge.
    this.background = '#fffdf6'
    css spec for the background color.
    this.background
    css spec for the background of the legend box.
    this.barDirection = 'vertical'
    ‘vertical’ = up and down bars, ‘horizontal’ = side to side bars
    this.barLabelOptions = {}
    options object to pass to the bar label renderer.
    this.barLabelRenderer = $.jqplot.AxisLabelRenderer
    renderer to use to draw labels under each bar.
    this.barLabels = this.barLabels || []
    array of labels to put under each bar.
    this.barMargin = 10
    Number of pixels between groups of bars at adjacent axis values.
    this.barPadding = 8
    Number of pixels between adjacent bars at the same axis value.
    this.barWidth = null
    Width of the bar in pixels (auto by devaul).
    this.bodyWidth = 'auto'
    width of the candlestick body in pixels.
    this.border
    css spec for the border around the legend box.
    this.borderColor = null
    color of the borders between areas on the chart
    this.borderColor = null
    color of the border adjacent to the axis.
    this.borderColor = '#999999'
    css spec for the color of the grid border.
    this.borderWidth = null
    width of line stroked at the border of the axis.
    this.borderWidth = 2.0
    width of the border in pixels.
    this.breakOnNull = false
    Wether line segments should be be broken at null value.
    this.breakPoints = null
    EXPERIMENTAL!! 
    this.breakTickLabel = "&asymp
    Label to use at the axis break if breakPoints are specified.
    this.bringSeriesToFront = false
    This option requires jQuery 1.4+ True to bring the series of the highlighted point to the front of other series.
    this.bubbleAlpha = 1.0
    Alpha transparency to apply to all bubbles in this series.
    this.bubbleGradients = false
    True to color the bubbles with gradient fills instead of flat colors.
    + + + +
    this.candleStick = false
    true to render chart as candleStick.
    this.clearRect = false
    true to cear a rectangle.
    this.clickReset = false
    Will reset plot zoom if single click on plot without drag.
    this.closeColor = null
    color of the close price tick mark.
    this.color
    CSS color spec for the dragged point (and adjacent line segment or bar).
    this.color = '#666666'
    color of marker.
    this.color = '#666666'
    CSS color spec for the trend line.
    color of the line
    color of the line
    color of the line
    color of the line
    this.color
    css color spec for the series
    color of the line
    this.constrainOutsideZoom = true
    True to limit actual zoom area to edges of grid, even when zooming outside of plot area.
    this.constrainTo = 'none'
    Constrain dragging motion to an axis or to none.
    this.constrainZoomTo = 'none'
    ‘none’, ‘x’ or ‘y’
    this.css = {padding:'2px', border:'1px solid #999', textAlign:'center'}
    default css styles that will be applied to all data blocks.
    this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString
    Format string used in the cursor legend.
    + + + +
    dashPattern: [8,8] }
    Array of line, space settings in pixels.
    dashPattern: [8,8] }
    Array of line, space settings in pixels.
    this.data = []
    user’s data.
    this.dataLabelCenterOn = true
    True to center the data label at its position.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelFormatString = null
    Format string for data labels.
    this.dataLabelNudge = 0
    Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
    this.dataLabelNudge = 2
    Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
    this.dataLabelPositionFactor = 0.4
    A Multiplier (0-1) of the pie radius which controls position of label on slice.
    this.dataLabelPositionFactor = 0.52
    A Multiplier (0-1) of the pie radius which controls position of label on slice.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.dataLabels = 'percent'
    Either ‘label’, ‘value’, ‘percent’ or an array of labels to place on the pie slices.
    this.dataLabelThreshold = 3
    this.dataLabelThreshold = 3
    this.dataLabelThreshold = 3
    Threshhold in percentage (0-100) of pie area, below which no label will be displayed.
    this.dblClickReset = true
    Will reset plot zoom if double click on plot without drag.
    this.defaultAxisStart = 1
    1-D data series are internally converted into 2-D [x,y] data point arrays by jqPlot.
    this.depth = 3
    how many times the shadow is stroked.
    this.diameter = null
    Outer diameter of the donut, auto computed by default
    this.diameter = null
    Outer diameter of the meterGauge, auto computed by default
    this.diameter = null
    Outer diameter of the pie, auto computed by default
    this.disableIEFading = true
    true to toggle series with a show/hide method only and not allow fading in/out.
    this.disableStack = false
    true to not stack this series with other series in the plot.
    this.downBodyColor = null
    Color of candlestick body on a “down” day.
    this.drawBorder = true
    True to draw border around grid.
    this.drawGridlines = true
    wether to draw the gridlines on the plot.
    + + + +
    this.edgeTolerance = -5
    Number of pixels that the label must be away from an axis boundary in order to be drawn.
    this.enableFontSupport = true
    true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
    this.enableFontSupport = true
    true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
    this.escapeHtml = false
    true to escape html in the box label.
    this.escapeHtml = true
    True to escape html in bubble label text.
    this.escapeHTML = false
    true to escape HTML entities in the label.
    this.escapeHTML = false
    true to escape HTML entities in the label.
    this.escapeHTML = true
    true to escape html entities in the labels.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Properties2.html b/phpgwapi/js/jquery/jqplot/docs/index/Properties2.html new file mode 100644 index 0000000000..92c65bf74a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Properties2.html @@ -0,0 +1,50 @@ + + +Property Index + + + + + + + + + +
    Property Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    F
     fadeTooltip, $.jqplot.Highlighter
     fill
     fillAlpha, Series
     fillAndStroke, Series
     fillAxis, Series
     fillColor, Series
     fillDownBody, $.jqplot.OHLCRenderer
     fillRect, $.jqplot.shapeRenderer
     fillStyle, $.jqplot.shapeRenderer
     fillToValue, Series
     fillToZero, Series
     fillUpBody, $.jqplot.OHLCRenderer
     followMouse, $.jqplot.Cursor
     fontFamily
     fontSize
     fontStretch
     fontWeight
     forceTickAt0, $.jqplot.LinearAxisRenderer
     forceTickAt100, $.jqplot.LinearAxisRenderer
     formatString
     formatter
    G
     grid, jqPlot
     gridLineColor, Grid
     gridLineWidth, Grid
     groups, $.jqplot.BarRenderer
    H
     hideZeros, $.jqplot.PointLabels
     highlightAlpha, $.jqplot.BubbleRenderer
     highlightColor, $.jqplot.LineRenderer
     highlightColors
     highlightMouseDown
     highlightMouseOver
     hlc, $.jqplot.OHLCRenderer
     hubRadius, $.jqplot.MeterGaugeRenderer
    I
     index, Series
     innerDiameter, $.jqplot.DonutRenderer
     insertBreaks, $.jqplot.BlockRenderer
     intersectionThreshold, $.jqplot.Cursor
     intervalColors, $.jqplot.MeterGaugeRenderer
     intervalInnerRadius, $.jqplot.MeterGaugeRenderer
     intervalOuterRadius, $.jqplot.MeterGaugeRenderer
     intervals, $.jqplot.MeterGaugeRenderer
     isarc
     isMinorTick
    L
     label
     labelHeightAdjust, $.jqplot.MeterGaugeRenderer
     labelOptions, Axis
     labelPosition
     labelRenderer, Axis
     labels
     labelsFromSeries, $.jqplot.PointLabels
     legend, jqPlot
     lineCap
     lineJoin
     lineWidth
     lineWidthAdjust, $.jqplot.Highlighter
     location
     looseZoom, $.jqplot.Cursor
    + +
    this.fadeTooltip = true
    true = fade in/out tooltip, flase = show/hide tooltip
    this.fill = true
    true or false, wether to fil the slices.
    this.fill = true
    true or false, wether to fill the areas.
    this.fill = true
    true or false, wether to fil the slices.
    this.fill = false
    whether to fill the shape.
    this.fill = false
    whether to fill the shape.
    this.fill = false
    true or false, wether to fill under lines or in bars.
    this.fillAlpha
    Alpha transparency to apply to the fill under the line.
    this.fillAndStroke = false
    If true will stroke the line (with color this.color) as well as fill under it.
    this.fillAxis = 'y'
    Either ‘x’ or ‘y’.
    this.fillColor
    CSS color spec to use for fill under line.
    this.fillDownBody = true
    true to render a “down” day (close price lower than open price) with a filled candlestick body.
    this.fillRect = false
    true to draw shape as a filled rectangle.
    this.fillStyle = '#999999'
    css color spec for the fill style.
    this.fillToValue = 0
    fill a filled series to this value on the fill axis.
    this.fillToZero = false
    true will force bar and filled series to fill toward zero on the fill Axis.
    this.fillUpBody = false
    true to render an “up” day (close price greater than open price) with a filled candlestick body.
    this.followMouse = false
    Tooltip follows the mouse, it is not at a fixed location.
    this.fontFamily
    css spec for the font-family css attribute.
    this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'
    CSS spec for the font-family css attribute.
    this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'
    css spec for the font-family css attribute.
    this.fontFamily
    css font-family spec for the legend text.
    this.fontFamily
    css font-family spec for the text.
    this.fontSize
    css spec for the font-size css attribute.
    this.fontSize = '11pt'
    CSS spec for font size.
    this.fontSize = '10pt'
    CSS spec for font size.
    this.fontSize
    css spec for the font-size attribute.
    this.fontSize
    css font-size spec for the legend text.
    this.fontSize
    css font-size spec for the text.
    this.fontStretch = 1.0
    Multiplier to condense or expand font width.
    this.fontStretch = 1.0
    Multiplier to condense or expand font width.
    this.fontWeight = 'normal'
    this.fontWeight = 'normal'
    CSS spec for fontWeight
    this.forceTickAt0 = false
    This will ensure that there is always a tick mark at 0.
    this.forceTickAt100 = false
    This will ensure that there is always a tick mark at 100.
    this.formatString = ''
    string passed to the formatter.
    this.formatString = ''
    string passed to the formatter.
    this.formatString = null
    alternative to tooltipFormatString will format the whole tooltip text, populating with x, y values as indicated by tooltipAxes option.
    this.formatString = ''
    string passed to the formatter.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    this.formatter = $.jqplot.DefaultTickFormatter
    A class of a formatter for the tick text.
    + + + +
    this.grid = new Grid()
    See Grid for grid specific options.
    this.gridLineColor = '#cccccc'
    color of the grid lines.
    this.gridLineWidth = 1.0
    width of the grid lines.
    this.groups = 1
    group bars into this many groups
    + + + +
    this.hideZeros = false
    true to not show a label for a value which is 0.
    this.highlightAlpha = null
    Alpha transparency to apply when highlighting bubble.
    this.highlightColor = null
    color to use when highlighting an area on a filled plot.
    this.highlightColors = []
    an array of colors to use when highlighting a bar.
    this.highlightColors = []
    An array of colors to use when highlighting a slice.
    this.highlightColors = []
    an array of colors to use when highlighting a slice.
    this.highlightColors = []
    array of colors to use when highlighting an area.
    this.highlightColors = []
    an array of colors to use when highlighting a slice.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a bubble.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a area.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over an area on a filled plot.
    this.highlightMouseDown = false
    True to highlight when a mouse button is pressed over a slice.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.highlightMouseOver = true
    True to highlight bubbles when moused over.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.highlightMouseOver = true
    True to highlight area when moused over.
    this.highlightMouseOver = true
    True to highlight area on a filled plot when moused over.
    this.highlightMouseOver = true
    True to highlight slice when moused over.
    this.hlc = false
    true if is a hi-low-close chart (no open price).
    this.hubRadius = null
    Radius of the hub at the bottom center of gauge which the needle attaches to.
    + + + +
    this.index
    0 based index of this series in the plot series array.
    this.innerDiameter = null
    Inner diameter of the donut, auto calculated by default.
    this.insertBreaks = true
    true to turn spaces in data block label into html breaks br /.
    this.intersectionThreshold = 2
    pixel distance from data point or marker to consider cursor lines intersecting with point.
    this.intervalColors = [ "#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"]
    Array of colors to use for the intervals.
    this.intervalInnerRadius = null
    Radius of the inner circle of the interval ring.
    this.intervalOuterRadius = null
    Radius of the outer circle of the interval ring.
    this.intervals = []
    Array of ranges to be drawn around the gauge.
    this.isarc = false
    wether the shadow is an arc or not.
    this.isarc = false
    wether the shadow is an arc or not.
    this.isMinorTick = false
    if this is a minor tick.
    this.isMinorTick = false
    if this is a minor tick.
    + + + +
    this.label = ''
    The text or html for the label.
    this.label = ''
    label for the axis.
    this.label = null
    A gauge label like ‘kph’ or ‘Volts’
    this.label = ''
    Label for the trend line to use in the legend.
    this.label = null
    Label for the axis
    this.label = ''
    Line label to use in the legend.
    this.labelHeightAdjust = 0
    Number of Pixels to offset the label up (-) or down (+) from its default position.
    this.labelOptions = {}
    Options passed to the label renderer.
    this.labelPosition = 'auto'
    ‘auto’, ‘start’, ‘middle’ or ‘end’.
    this.labelPosition = 'inside'
    Where to position the label, either ‘inside’ or ‘bottom’.
    this.labelRenderer = $.jqplot.AxisLabelRenderer
    A class of a rendering engine for creating an axis label.
    this.labels = []
    array of arrays of labels, one array for each series.
    this.labels = []
    Array of labels to use.
    this.labelsFromSeries = false
    true to use labels within data point arrays.
    this.legend = new Legend()
    see $.jqplot.TableLegendRenderer
    this.lineCap = 'round'
    how ends of the shadow line are rendered.
    this.lineCap = 'round'
    how ends of the shadow line are rendered.
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    this.lineCap = 'round'
    Canvas lineCap style at ends of line.
    Type of ending placed on the line [‘round’, ‘butt’, ‘square’]
    this.lineJoin = 'miter'
    How line segments of the shadow are joined.
    this.lineJoin = 'miter'
    How line segments of the shadow are joined.
    this.lineJoin = 'round'
    Canvas lineJoin style between segments of series.
    this.lineWidth = 2
    width of line if areas are stroked and not filled.
    this.lineWidth = 2
    size of the line for non-filled markers.
    this.lineWidth = 1.5
    Width of the hi-low line and open/close ticks.
    this.lineWidth = 1.5
    width of the shadow line stroke.
    this.lineWidth = 1.5
    Width of the trend line.
    Width of the line.
    Width of the line.
    Width of the line.
    Width of the line.
    this.lineWidth = 2.5
    width of the line in pixels.
    Width of the line.
    this.lineWidthAdjust = 2.5
    Pixels to add to the lineWidth of the highlight.
    this.location = 'n'
    compass location where to position the label around the point.
    this.location = 'ne'
    Placement of the legend.
    this.looseZoom = false
    Will expand zoom range to provide more rounded tick values.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Properties3.html b/phpgwapi/js/jquery/jqplot/docs/index/Properties3.html new file mode 100644 index 0000000000..f912df5bde --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Properties3.html @@ -0,0 +1,50 @@ + + +Property Index + + + + + + + + + +
    Property Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    M
     marginBottom, Legend
     marginLeft, Legend
     marginRight, Legend
     marginTop, Legend
     mark
     markerOptions, Series
     markerRenderer
     markSize
     max
     min
    N
     name
     needlePad, $.jqplot.MeterGaugeRenderer
     needleThickness, $.jqplot.MeterGaugeRenderer
     neighborThreshold, Series
     numberColumns
     numberRows
     numberTicks, Axis
    O
     objects, $.jqplot.CanvasOverlay
     offset, $.jqplot.shadowRenderer
     openColor, $.jqplot.OHLCRenderer
    P
     pad, Axis
     padding
     padMax, Axis
     padMin, Axis
     pegNeedle, $.jqplot.MeterGaugeRenderer
     placement, Legend
     predraw, Legend
     prefix
     pt2px
    R
     renderer
     rendererOptions
     ringColor, $.jqplot.MeterGaugeRenderer
     ringMargin, $.jqplot.DonutRenderer
     ringWidth, $.jqplot.MeterGaugeRenderer
     rowSpacing, Legend
    + +
    this.marginBottom = null
    CSS margin for the legend DOM element.
    this.marginLeft = null
    CSS margin for the legend DOM element.
    this.marginRight = null
    CSS margin for the legend DOM element.
    this.marginTop = null
    CSS margin for the legend DOM element.
    this.mark = 'outside'
    tick mark on the axis.
    this.mark = 'outside'
    tick mark on the axis.
    this.markerOptions = {}
    renderer specific options to pass to the markerRenderer, see $.jqplot.MarkerRenderer.
    this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false})
    Renderer used to draw the marker of the highlighted point.
    this.markerRenderer = {show:false}
    Renderer to use to draw markers on the line.
    this.markerRenderer = $.jqplot.MarkerRenderer
    A class of a renderer which will draw marker (e.g.
    this.markSize = 6
    Length of the tick marks in pixels.
    this.markSize = 4
    Length of the tick marks in pixels.
    this.max
    Maximum value on the gauge.
    this.max=null
    maximum value of the axis (in data units, not pixels).
    this.min
    Minimum value on the gauge.
    this.min=null
    minimum value of the axis (in data units, not pixels).
    + + + +
    Optional name for this overlay object.
    Optional name for this overlay object.
    Optional name for this overlay object.
    Optional name for this overlay object.
    Optional name for this overlay object.
    this.needlePad = 6
    Padding between needle and inner edge of the ring when the needle is at the min or max gauge value.
    this.needleThickness = null
    Maximum thickness the needle.
    this.neighborThreshold = 4
    how close or far (in pixels) the cursor must be from a point marker to detect the point.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberColumns = null
    Maximum number of columns in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberRows = null
    Maximum number of rows in the legend.
    this.numberTicks
    Desired number of ticks.
    + + + +
    this.objects = []
    this.offset = 1
    Pixel offset at the given shadow angle of each shadow stroke from the last stroke.
    this.openColor = null
    color of the open price tick mark.
    + + + +
    this.pad = 1.2
    Padding to extend the range above and below the data bounds.
    this.padding = 20
    padding between the donut and plot edges, legend, etc.
    this.padding = {top: 20, right: 20, bottom: 20, left: 20}
    padding between the funnel and plot edges, legend, etc.
    this.padding = null
    padding between the meterGauge and plot edges, auto calculated by default.
    this.padding = 20
    padding between the pie and plot edges, legend, etc.
    this.padMax = null
    Padding to extend the range above data bounds.
    this.padMin = null
    Padding to extend the range below data bounds.
    this.pegNeedle = true
    True will stop needle just below/above the min/max values if data is below/above min/max, as if the meter is “pegged”.
    this.placement = "insideGrid"
    “insideGrid” places legend inside the grid area of the plot.
    Wether to draw the legend before the series or not.
    this.prefix = ''
    String to prepend to the tick label.
    this.prefix = ''
    String to prepend to the tick label.
    this.pt2px = null
    Point to pixel scaling factor, used for computing height of bounding box around a label.
    this.pt2px = null
    Point to pixel scaling factor, used for computing height of bounding box around a label.
    + + + +
    this.renderer = new $.jqplot.LineRenderer()
    Renderer to use to draw the trend line.
    this.renderer = $.jqplot.LinearAxisRenderer
    A class of a rendering engine that handles tick generation, scaling input data to pixel grid units and drawing the axis element.
    this.renderer = $.jqplot.CanvasGridRenderer
    Instance of a renderer which will actually render the grid, see $.jqplot.CanvasGridRenderer.
    this.renderer = $.jqplot.LineRenderer
    A class of a renderer which will draw the series, see $.jqplot.LineRenderer.
    this.renderer = $.jqplot.DivTitleRenderer
    A class for creating a DOM element for the title, see $.jqplot.DivTitleRenderer.
    this.rendererOptions = {marker:{show:false}}
    Options to pass to the line renderer.
    this.rendererOptions = {}
    renderer specific options.
    this.rendererOptions = {}
    Options to pass on to the renderer, see $.jqplot.CanvasGridRenderer.
    this.rendererOptions = {}
    renderer specific options passed to the renderer.
    this.rendererOptions = {}
    Options to pass on to the renderer.
    this.rendererOptions = {}
    renderer specific options passed to the renderer.
    this.ringColor = "#BBC6D0"
    color of the outer ring, hub, and needle of the gauge.
    this.ringMargin = null
    pixel distance between rings, or multiple series in a donut plot.
    this.ringWidth = null
    width of the ring around the gauge.
    this.rowSpacing = '0.5em'
    css padding-top spec for the rows in the legend.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Properties4.html b/phpgwapi/js/jquery/jqplot/docs/index/Properties4.html new file mode 100644 index 0000000000..e29ed69d07 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Properties4.html @@ -0,0 +1,34 @@ + + +Property Index + + + + + + + + + +
    Property Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    S
     sectionMargin, $.jqplot.FunnelRenderer
     series, jqPlot
     seriesColors, jqPlot
     seriesDefaults, jqPlot
     seriesLabelIndex, $.jqplot.PointLabels
     seriesToggle
     shadow
     shadowAlpha
     shadowAngle
     shadowColor, Grid
     shadowDepth
     shadowOffset
     shadowRenderer, $.jqplot.MarkerRenderer
     shadowWidth, Grid
     shapeRenderer, $.jqplot.MarkerRenderer
     show
     showBorders, $.jqplot.MekkoRenderer
     showCursorLegend, $.jqplot.Cursor
     showDataLabels
     showGridline
     showHorizontalLine, $.jqplot.Cursor
     showLabel
     showLabels
     showLine, Series
     showMark
     showMarker
     showMinorTicks, Axis
     showSwatch, Legend
     showTickLabels, $.jqplot.MeterGaugeRenderer
     showTickMarks, Axis
     showTicks
     showTooltip
     showTooltipDataPosition, $.jqplot.Cursor
     showTooltipGridPosition, $.jqplot.Cursor
     showTooltipOutsideZoom, $.jqplot.Cursor
     showTooltipUnitPosition, $.jqplot.Cursor
     showVerticalLine, $.jqplot.Cursor
     size
     sizeAdjust, $.jqplot.Highlighter
     sliceMargin
     sortData, jqPlot
     sortMergedLabels, $.jqplot.CategoryAxisRenderer
     stackedValue, $.jqplot.PointLabels
     stackSeries, jqPlot
     start, Line
     startAngle
     stop, Line
     strokeRect, $.jqplot.shapeRenderer
     strokeStyle, $.jqplot.shapeRenderer
     style
     syncTicks, Axis
    + +
    this.sectionMargin = 6
    spacing between funnel sections in pixels.
    this.series = []
    Array of series object options.
    this.seriesColors = $.jqplot.config.defaultColors
    Ann array of CSS color specifications that will be applied, in order, to the series in the plot.
    seriesDefaults: {}, series:[] }
    default options that will be applied to all series.
    this.seriesLabelIndex = null
    array index for location of labels within data point arrays.
    this.seriesToggle = 'normal'
    false to not enable series on/off toggling on the legend.
    this.shadow = true
    wether or not to draw a shadow on the line
    this.shadow = true
    true or false, wether or not to show the shadow.
    wether or not to draw a shadow on the line
    wether or not to draw a shadow on the line
    this.shadow = true
    wether to show a shadow behind the grid.
    wether or not to draw a shadow on the line
    wether or not to draw a shadow on the line
    this.shadow = true
    wether or not to draw a shadow on the line
    wether or not to draw a shadow on the line
    this.shadowAlpha = 0.08
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = '0.07'
    Alpha channel transparency of shadow.
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = 0.07
    transparency of the shadow (0 = transparent, 1 = opaque)
    this.shadowAlpha = 0.07
    Alpha transparency of the shadow.
    Alpha channel transparency of shadow.
    Alpha channel transparency of shadow.
    this.shadowAlpha = '0.07'
    Alpha channel transparency of shadow.
    Alpha channel transparency of shadow.
    Alpha channel transparency of shadow.
    this.shadowAlpha = '0.1'
    Alpha channel transparency of shadow.
    Alpha channel transparency of shadow.
    this.shadowAngle = 45
    Shadow angle in degrees
    this.shadowAngle = 45
    Angle of the shadow on the trend line.
    Shadow angle in degrees
    Shadow angle in degrees
    this.shadowAngle = 45
    shadow angle in degrees
    Shadow angle in degrees
    Shadow angle in degrees
    this.shadowAngle = 45
    Shadow angle in degrees
    Shadow angle in degrees
    this.shadowColor = null
    an optional css color spec for the shadow in ‘rgba(n, n, n, n)’ form
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowDepth = 4
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 5
    number of strokes to apply to the shadow, each stroke offset shadowOffset from the last.
    this.shadowDepth = 3
    number of strokes to make of the shadow.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowDepth = 3
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    Number of times shadow is stroked, each stroke offset shadowOffset from the last.
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 2
    offset of the shadow from the area and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 1
    Shadow offset from line in pixels
    this.shadowOffset = 2
    offset of the shadow from the gauge ring and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 2
    offset of the shadow from the slice and offset of each succesive stroke of the shadow from the last.
    this.shadowOffset = 1.0
    pixel offset for each stroke of the shadow.
    Shadow offset from line in pixels
    Shadow offset from line in pixels
    this.shadowOffset = 1.5
    Offset of each shadow stroke from the border in pixels
    Shadow offset from line in pixels
    Shadow offset from line in pixels
    this.shadowOffset = 1.25
    Shadow offset from line in pixels
    Shadow offset from line in pixels
    this.shadowRenderer = new $.jqplot.ShadowRenderer()
    Renderer that will draws the shadows on the marker.
    this.shadowWidth = 3
    width of the stoke for the shadow
    this.shapeRenderer = new $.jqplot.ShapeRenderer()
    Renderer that will draw the marker.
    this.show = true
    wether or not to show the tick (mark and label).
    this.show = true
    wether or not to show the tick (mark and label).
    this.show = true
    wether or not to show the tick (mark and label).
    this.show = true
    wether or not to show the tick (mark and label).
    this.show = $.jqplot.config.enablePlugins
    wether to show the cursor or not.
    this.show = $.jqplot.config.enablePlugins
    true to show the highlight.
    this.show = true
    wether or not to show the marker.
    this.show = $.jqplot.config.enablePlugins
    show the labels or not.
    this.show = $.jqplot.config.enablePlugins
    Wether or not to show the trend line.
    this.show = false
    Wether to display the axis on the graph.
    true to show (draw), false to not draw.
    true to show (draw), false to not draw.
    true to show (draw), false to not draw.
    this.show = false
    Wether to display the legend on the graph.
    true to show (draw), false to not draw.
    this.show = true
    wether or not to draw the series.
    this.show = true
    wether or not to show the title
    true to show (draw), false to not draw.
    this.showBorders = true
    True to draw borders lines between areas on the chart.
    this.showCursorLegend = false
    Replace the plot legend with an enhanced legend displaying intersection information.
    this.showDataLabels = false
    true to show data labels on slices.
    this.showDataLabels = false
    true to show data labels on slices.
    this.showDataLabels = false
    true to show data labels on slices.
    this.showGridline = true
    wether or not to draw the gridline on the grid at this tick.
    this.showGridline = true
    wether or not to draw the gridline on the grid at this tick.
    this.showHorizontalLine = false
    draw a horizontal line across the plot which follows the cursor.
    this.showLabel = true
    wether or not to show the label.
    this.showLabel = true
    wether or not to show the label.
    this.showLabel = true
    wether or not to show the label.
    this.showLabel = true
    true to show the axis label.
    this.showLabel = true
    true to show label for this series in the legend.
    this.showLabels = true
    True to show labels on bubbles (if any), false to not show.
    this.showLabels = true
    true to show the label text on the legend.
    this.showLine = true
    wether to actually draw the line or not.
    this.showMark = true
    wether or not to show the mark on the axis.
    this.showMark = true
    wether or not to show the mark on the axis.
    this.showMarker = true
    true to show the marker
    this.showMarker = true
    wether or not to show the markers at the data points.
    this.showMinorTicks = true
    Wether or not to show minor ticks.
    this.showSwatches = true
    true to show the color swatches on the legend.
    this.showTickLabels = true
    true to show tick labels next to ticks.
    this.showTickMarks = true
    Wether to show the tick marks (line crossing grid) or not.
    this.showTicks = true
    true to show ticks around gauge.
    this.showTicks = true
    Wether to show the ticks (both marks and labels) or not.
    this.showTooltip = true
    show a cursor position tooltip.
    this.showTooltip = true
    Show a tooltip with data point values.
    this.showTooltipDataPosition = false
    Used with showVerticalLine to show intersecting data points in the tooltip.
    this.showTooltipGridPosition = false
    show the grid pixel coordinates of the mouse.
    this.showTooltipOutsideZoom = false
    True will keep updating the tooltip when zooming of the grid.
    this.showTooltipUnitPosition = true
    show the unit (data) coordinates of the mouse.
    this.showVerticalLine = false
    draw a vertical line across the plot which follows the cursor.
    this.size = 4
    Length of the tick beyond the grid in pixels.
    this.size = 9.0
    Size of the marker (diameter or circle, length of edge of square, etc.)
    this.sizeAdjust = 5
    Pixels to add to the overall size of the highlight.
    this.sliceMargin = 0
    angular spacing between donut slices in degrees.
    this.sliceMargin = 0
    angular spacing between pie slices in degrees.
    this.sortData = true
    false to not sort the data passed in by the user.
    this.sortMergedLabels = false
    True to sort tick labels when labels are created by merging x axis values from multiple series.
    this.stackedValue = false
    true to display value as stacked in a stacked plot.
    this.stackSeries = false
    true or false, creates a stack or “mountain” plot.
    [x, y] coordinates for the start of the line.
    this.startAngle = 0
    Angle to start drawing donut in degrees.
    this.startAngle = 0
    Angle to start drawing pie in degrees.
    stop: [] }
    [x, y] coordinates for the end of the line.
    this.strokeRect = false
    true to draw shape as a stroked rectangle.
    this.strokeStyle = '#999999'
    css color spec for the stoke style
    this.style = 'crosshair'
    CSS spec for cursor style
    this.style = 'filledCircle'
    One of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare
    this.syncTicks = null
    true to try and synchronize tick spacing across multiple axes so that ticks and grid lines line up.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/index/Properties5.html b/phpgwapi/js/jquery/jqplot/docs/index/Properties5.html new file mode 100644 index 0000000000..308354ef15 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/index/Properties5.html @@ -0,0 +1,58 @@ + + +Property Index + + + + + + + + + +
    Property Index
    $#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
    T
     text, Title
     textAlign, Title
     textColor
     themes, $.jqplot.ThemeEngine
     thickness, $.jqplot.DonutRenderer
     tickColor, $.jqplot.MeterGaugeRenderer
     tickInterval, Axis
     tickLength, $.jqplot.OHLCRenderer
     tickMode, $.jqplot.MekkoAxisRenderer
     tickOptions, Axis
     tickPadding, $.jqplot.MeterGaugeRenderer
     tickRenderer
     ticks
     tickSpacing
     title, jqPlot
     tooltipAxes, $.jqplot.Highlighter
     tooltipAxisGroups, $.jqplot.Cursor
     tooltipFadeSpeed, $.jqplot.Highlighter
     tooltipFormatString
     tooltipLocation
     tooltipOffset
     type, $.jqplot.Trendline
    U
     upBodyColor, $.jqplot.OHLCRenderer
     useAxesFormatters
     useNegativeColors, Series
     useSeriesColor, Axis
    V
     varyBarColor, $.jqplot.BarRenderer
     varyBlockColors, $.jqplot.BlockRenderer
     varyBubbleColors, $.jqplot.BubbleRenderer
    W
     waterfall, $.jqplot.BarRenderer
     wickColor, $.jqplot.OHLCRenderer
     widthRatio, $.jqplot.FunnelRenderer
    X
     xaxis
     xmax, HorizontalLine
     xmin, HorizontalLine
     xoffset, Legend
     xpadding, $.jqplot.PointLabels
    Y
     y, HorizontalLine
     yaxis
     yoffset, Legend
     ypadding, $.jqplot.PointLabels
     yvalues, $.jqplot.Highlighter
    Z
     zoom, $.jqplot.Cursor
    + +
    this.text = text
    text of the title;
    this.textAlign
    css text-align spec for the text.
    this.textColor
    css spec for the color attribute.
    this.textColor = '#666666'
    css spec for the color attribute.
    this.textColor = '#666666'
    css spec for the color attribute.
    this.textColor
    css color spec for the legend text.
    this.textColor
    css color spec for the text.
    this.themes = {}
    hash of themes managed by the theme engine.
    this.thickness = null
    thickness of the donut, auto computed by default Overridden by if innerDiameter is specified.
    this.tickColor = "989898"
    color of the tick marks around the gauge.
    this.tickInterval
    number of units between ticks.
    this.tickLength = 'auto'
    length of the line in pixels indicating open and close price.
    this.tickMode
    How to space the ticks on the axis.
    this.tickOptions = {}
    Options that will be passed to the tickRenderer, see $.jqplot.AxisTickRenderer options.
    this.tickPadding = null
    padding of the tick marks to the outer ring and the tick labels to marks.
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    this.tickRenderer = $.jqplot.AxisTickRenderer
    A class of a rendering engine for creating the ticks labels displayed on the plot, See $.jqplot.AxisTickRenderer.
    this.ticks = []
    Array of tick values.
    this.ticks = []
    1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis.
    this.tickSpacing = 30
    Degrees between ticks.
    this.tickSpacing = 75
    Approximate pixel spacing between ticks on graph.
    this.title = new Title()
    Title object.
    this.tooltipAxes = 'both'
    Which axes to display in tooltip, ‘x’, ‘y’ or ‘both’, ‘xy’ or ‘yx’ ‘both’ and ‘xy’ are equivalent, ‘yx’ reverses order of labels.
    this.tooltipAxisGroups = []
    Show position for the specified axes.
    this.tooltipFadeSpeed = "fast"
    ‘slow’, ‘def’, ‘fast’, or number of milliseconds.
    this.tooltipFormatString = '%.4P, %.4P'
    sprintf format string for the tooltip.
    this.tooltipFormatString = '%.5P'
    sprintf format string for the tooltip.
    this.tooltipLocation = 'se'
    Where to position tooltip.
    this.tooltipLocation = 'nw'
    Where to position tooltip, ‘n’, ‘ne’, ‘e’, ‘se’, ‘s’, ‘sw’, ‘w’, ‘nw’
    this.tooltipOffset = 6
    Pixel offset of tooltip from the grid boudaries or cursor center.
    this.tooltipOffset = 2
    Pixel offset of tooltip from the highlight.
    this.type = 'linear'
    Either ‘exponential’, ‘exp’, or ‘linear’.
    + + + +
    this.upBodyColor = null
    Color of candlestick body of an “up” day.
    this.useAxesFormatters = true
    Use the x and y axes formatters to format the text in the tooltip.
    this.useAxesFormatters = true
    Use the x and y axes formatters to format the text in the tooltip.
    this.useNegativeColors = true
    true to color negative values differently in filled and bar charts.
    this.useSeriesColor = false
    Use the color of the first series associated with this axis for the tick marks and line bordering this axis.
    + + + +
    this.varyBarColor = false
    true to color each bar of a series separately rather than have every bar of a given series the same color.
    this.varyBlockColors = false
    true to vary the color of each block in this series according to the seriesColors array.
    this.varyBubbleColors = true
    True to vary the color of each bubble in this series according to the seriesColors array.
    + + + +
    this.waterfall = false
    true to enable waterfall plot.
    this.wickColor = null
    color of the hi-lo line thorugh the candlestick body.
    this.widthRatio = 0.2
    The ratio of the width of the top of the funnel to the bottom.
    + + + +
    X axis to use for positioning/scaling the line.
    X axis to use for positioning/scaling the line.
    X axis to use for positioning/scaling the line.
    X axis to use for positioning/scaling the line.
    this.xaxis = 'xaxis'
    which x axis to use with this series, either ‘xaxis’ or ‘x2axis’.
    X axis to use for positioning/scaling the line.
    x value for the end of the line, null to scale to axis max.
    x value for the start of the line, null to scale to axis min.
    this.xoffset = 0
    DEPRECATED.
    this.xpadding = 6
    horizontal padding in pixels between point and label
    + + + +
    y value to position the line
    Y axis to use for positioning/scaling the line.
    Y axis to use for positioning/scaling the line.
    Y axis to use for positioning/scaling the line.
    Y axis to use for positioning/scaling the line.
    this.yaxis = 'yaxis'
    which y axis to use with this series, either ‘yaxis’ or ‘y2axis’.
    yaxis: 'yaxis', x: null, ymin: null, ymax: null, yOffset: '6px', // number or string. Number interpreted as units, string as pixels. yminOffset: null, ymaxOffset: null }
    Y axis to use for positioning/scaling the line.
    this.yoffset = 0
    DEPRECATED.
    this.ypadding = 6
    vertical padding in pixels between point and label
    this.yvalues = 1
    Number of y values to expect in the data point array.
    + + + +
    this.zoom = false
    Enable plot zooming.
    + +
    + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/javascript/main.js b/phpgwapi/js/jquery/jqplot/docs/javascript/main.js new file mode 100644 index 0000000000..efcdca9669 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/javascript/main.js @@ -0,0 +1,836 @@ +// This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure +// Natural Docs is licensed under the GPL + + +// +// Browser Styles +// ____________________________________________________________________________ + +var agt=navigator.userAgent.toLowerCase(); +var browserType; +var browserVer; + +if (agt.indexOf("opera") != -1) + { + browserType = "Opera"; + + if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1) + { browserVer = "Opera7"; } + else if (agt.indexOf("opera 8") != -1 || agt.indexOf("opera/8") != -1) + { browserVer = "Opera8"; } + else if (agt.indexOf("opera 9") != -1 || agt.indexOf("opera/9") != -1) + { browserVer = "Opera9"; } + } + +else if (agt.indexOf("applewebkit") != -1) + { + browserType = "Safari"; + + if (agt.indexOf("version/3") != -1) + { browserVer = "Safari3"; } + else if (agt.indexOf("safari/4") != -1) + { browserVer = "Safari2"; } + } + +else if (agt.indexOf("khtml") != -1) + { + browserType = "Konqueror"; + } + +else if (agt.indexOf("msie") != -1) + { + browserType = "IE"; + + if (agt.indexOf("msie 6") != -1) + { browserVer = "IE6"; } + else if (agt.indexOf("msie 7") != -1) + { browserVer = "IE7"; } + } + +else if (agt.indexOf("gecko") != -1) + { + browserType = "Firefox"; + + if (agt.indexOf("rv:1.7") != -1) + { browserVer = "Firefox1"; } + else if (agt.indexOf("rv:1.8)") != -1 || agt.indexOf("rv:1.8.0") != -1) + { browserVer = "Firefox15"; } + else if (agt.indexOf("rv:1.8.1") != -1) + { browserVer = "Firefox2"; } + } + + +// +// Support Functions +// ____________________________________________________________________________ + + +function GetXPosition(item) + { + var position = 0; + + if (item.offsetWidth != null) + { + while (item != document.body && item != null) + { + position += item.offsetLeft; + item = item.offsetParent; + }; + }; + + return position; + }; + + +function GetYPosition(item) + { + var position = 0; + + if (item.offsetWidth != null) + { + while (item != document.body && item != null) + { + position += item.offsetTop; + item = item.offsetParent; + }; + }; + + return position; + }; + + +function MoveToPosition(item, x, y) + { + // Opera 5 chokes on the px extension, so it can use the Microsoft one instead. + + if (item.style.left != null) + { + item.style.left = x + "px"; + item.style.top = y + "px"; + } + else if (item.style.pixelLeft != null) + { + item.style.pixelLeft = x; + item.style.pixelTop = y; + }; + }; + + +// +// Menu +// ____________________________________________________________________________ + + +function ToggleMenu(id) + { + if (!window.document.getElementById) + { return; }; + + var display = window.document.getElementById(id).style.display; + + if (display == "none") + { display = "block"; } + else + { display = "none"; } + + window.document.getElementById(id).style.display = display; + } + +function HideAllBut(ids, max) + { + if (document.getElementById) + { + ids.sort( function(a,b) { return a - b; } ); + var number = 1; + + while (number < max) + { + if (ids.length > 0 && number == ids[0]) + { ids.shift(); } + else + { + document.getElementById("MGroupContent" + number).style.display = "none"; + }; + + number++; + }; + }; + } + + +// +// Tooltips +// ____________________________________________________________________________ + + +var tooltipTimer = 0; + +function ShowTip(event, tooltipID, linkID) + { + if (tooltipTimer) + { clearTimeout(tooltipTimer); }; + + var docX = event.clientX + window.pageXOffset; + var docY = event.clientY + window.pageYOffset; + + var showCommand = "ReallyShowTip('" + tooltipID + "', '" + linkID + "', " + docX + ", " + docY + ")"; + + tooltipTimer = setTimeout(showCommand, 1000); + } + +function ReallyShowTip(tooltipID, linkID, docX, docY) + { + tooltipTimer = 0; + + var tooltip; + var link; + + if (document.getElementById) + { + tooltip = document.getElementById(tooltipID); + link = document.getElementById(linkID); + } +/* else if (document.all) + { + tooltip = eval("document.all['" + tooltipID + "']"); + link = eval("document.all['" + linkID + "']"); + } +*/ + if (tooltip) + { + var left = GetXPosition(link); + var top = GetYPosition(link); + top += link.offsetHeight; + + + // The fallback method is to use the mouse X and Y relative to the document. We use a separate if and test if its a number + // in case some browser snuck through the above if statement but didn't support everything. + + if (!isFinite(top) || top == 0) + { + left = docX; + top = docY; + } + + // Some spacing to get it out from under the cursor. + + top += 10; + + // Make sure the tooltip doesnt get smushed by being too close to the edge, or in some browsers, go off the edge of the + // page. We do it here because Konqueror does get offsetWidth right even if it doesnt get the positioning right. + + if (tooltip.offsetWidth != null) + { + var width = tooltip.offsetWidth; + var docWidth = document.body.clientWidth; + + if (left + width > docWidth) + { left = docWidth - width - 1; } + + // If there's a horizontal scroll bar we could go past zero because it's using the page width, not the window width. + if (left < 0) + { left = 0; }; + } + + MoveToPosition(tooltip, left, top); + tooltip.style.visibility = "visible"; + } + } + +function HideTip(tooltipID) + { + if (tooltipTimer) + { + clearTimeout(tooltipTimer); + tooltipTimer = 0; + } + + var tooltip; + + if (document.getElementById) + { tooltip = document.getElementById(tooltipID); } + else if (document.all) + { tooltip = eval("document.all['" + tooltipID + "']"); } + + if (tooltip) + { tooltip.style.visibility = "hidden"; } + } + + +// +// Blockquote fix for IE +// ____________________________________________________________________________ + + +function NDOnLoad() + { + if (browserVer == "IE6") + { + var scrollboxes = document.getElementsByTagName('blockquote'); + + if (scrollboxes.item(0)) + { + NDDoResize(); + window.onresize=NDOnResize; + }; + }; + }; + + +var resizeTimer = 0; + +function NDOnResize() + { + if (resizeTimer != 0) + { clearTimeout(resizeTimer); }; + + resizeTimer = setTimeout(NDDoResize, 250); + }; + + +function NDDoResize() + { + var scrollboxes = document.getElementsByTagName('blockquote'); + + var i; + var item; + + i = 0; + while (item = scrollboxes.item(i)) + { + item.style.width = 100; + i++; + }; + + i = 0; + while (item = scrollboxes.item(i)) + { + item.style.width = item.parentNode.offsetWidth; + i++; + }; + + clearTimeout(resizeTimer); + resizeTimer = 0; + } + + + +/* ________________________________________________________________________________________________________ + + Class: SearchPanel + ________________________________________________________________________________________________________ + + A class handling everything associated with the search panel. + + Parameters: + + name - The name of the global variable that will be storing this instance. Is needed to be able to set timeouts. + mode - The mode the search is going to work in. Pass CommandLineOption()>, so the + value will be something like "HTML" or "FramedHTML". + + ________________________________________________________________________________________________________ +*/ + + +function SearchPanel(name, mode, resultsPath) + { + if (!name || !mode || !resultsPath) + { alert("Incorrect parameters to SearchPanel."); }; + + + // Group: Variables + // ________________________________________________________________________ + + /* + var: name + The name of the global variable that will be storing this instance of the class. + */ + this.name = name; + + /* + var: mode + The mode the search is going to work in, such as "HTML" or "FramedHTML". + */ + this.mode = mode; + + /* + var: resultsPath + The relative path from the current HTML page to the results page directory. + */ + this.resultsPath = resultsPath; + + /* + var: keyTimeout + The timeout used between a keystroke and when a search is performed. + */ + this.keyTimeout = 0; + + /* + var: keyTimeoutLength + The length of in thousandths of a second. + */ + this.keyTimeoutLength = 500; + + /* + var: lastSearchValue + The last search string executed, or an empty string if none. + */ + this.lastSearchValue = ""; + + /* + var: lastResultsPage + The last results page. The value is only relevant if is set. + */ + this.lastResultsPage = ""; + + /* + var: deactivateTimeout + + The timeout used between when a control is deactivated and when the entire panel is deactivated. Is necessary + because a control may be deactivated in favor of another control in the same panel, in which case it should stay + active. + */ + this.deactivateTimout = 0; + + /* + var: deactivateTimeoutLength + The length of in thousandths of a second. + */ + this.deactivateTimeoutLength = 200; + + + + + // Group: DOM Elements + // ________________________________________________________________________ + + + // Function: DOMSearchField + this.DOMSearchField = function() + { return document.getElementById("MSearchField"); }; + + // Function: DOMSearchType + this.DOMSearchType = function() + { return document.getElementById("MSearchType"); }; + + // Function: DOMPopupSearchResults + this.DOMPopupSearchResults = function() + { return document.getElementById("MSearchResults"); }; + + // Function: DOMPopupSearchResultsWindow + this.DOMPopupSearchResultsWindow = function() + { return document.getElementById("MSearchResultsWindow"); }; + + // Function: DOMSearchPanel + this.DOMSearchPanel = function() + { return document.getElementById("MSearchPanel"); }; + + + + + // Group: Event Handlers + // ________________________________________________________________________ + + + /* + Function: OnSearchFieldFocus + Called when focus is added or removed from the search field. + */ + this.OnSearchFieldFocus = function(isActive) + { + this.Activate(isActive); + }; + + + /* + Function: OnSearchFieldChange + Called when the content of the search field is changed. + */ + this.OnSearchFieldChange = function() + { + if (this.keyTimeout) + { + clearTimeout(this.keyTimeout); + this.keyTimeout = 0; + }; + + var searchValue = this.DOMSearchField().value.replace(/ +/g, ""); + + if (searchValue != this.lastSearchValue) + { + if (searchValue != "") + { + this.keyTimeout = setTimeout(this.name + ".Search()", this.keyTimeoutLength); + } + else + { + if (this.mode == "HTML") + { this.DOMPopupSearchResultsWindow().style.display = "none"; }; + this.lastSearchValue = ""; + }; + }; + }; + + + /* + Function: OnSearchTypeFocus + Called when focus is added or removed from the search type. + */ + this.OnSearchTypeFocus = function(isActive) + { + this.Activate(isActive); + }; + + + /* + Function: OnSearchTypeChange + Called when the search type is changed. + */ + this.OnSearchTypeChange = function() + { + var searchValue = this.DOMSearchField().value.replace(/ +/g, ""); + + if (searchValue != "") + { + this.Search(); + }; + }; + + + + // Group: Action Functions + // ________________________________________________________________________ + + + /* + Function: CloseResultsWindow + Closes the results window. + */ + this.CloseResultsWindow = function() + { + this.DOMPopupSearchResultsWindow().style.display = "none"; + this.Activate(false, true); + }; + + + /* + Function: Search + Performs a search. + */ + this.Search = function() + { + this.keyTimeout = 0; + + var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + var searchTopic = this.DOMSearchType().value; + + var pageExtension = searchValue.substr(0,1); + + if (pageExtension.match(/^[a-z]/i)) + { pageExtension = pageExtension.toUpperCase(); } + else if (pageExtension.match(/^[0-9]/)) + { pageExtension = 'Numbers'; } + else + { pageExtension = "Symbols"; }; + + var resultsPage; + var resultsPageWithSearch; + var hasResultsPage; + + // indexSectionsWithContent is defined in searchdata.js + if (indexSectionsWithContent[searchTopic][pageExtension] == true) + { + resultsPage = this.resultsPath + '/' + searchTopic + pageExtension + '.html'; + resultsPageWithSearch = resultsPage+'?'+escape(searchValue); + hasResultsPage = true; + } + else + { + resultsPage = this.resultsPath + '/NoResults.html'; + resultsPageWithSearch = resultsPage; + hasResultsPage = false; + }; + + var resultsFrame; + if (this.mode == "HTML") + { resultsFrame = window.frames.MSearchResults; } + else if (this.mode == "FramedHTML") + { resultsFrame = window.top.frames['Content']; }; + + + if (resultsPage != this.lastResultsPage || + + // Bug in IE. If everything becomes hidden in a run, none of them will be able to be reshown in the next for some + // reason. It counts the right number of results, and you can even read the display as "block" after setting it, but it + // just doesn't work in IE 6 or IE 7. So if we're on the right page but the previous search had no results, reload the + // page anyway to get around the bug. + (browserType == "IE" && hasResultsPage && + (!resultsFrame.searchResults || resultsFrame.searchResults.lastMatchCount == 0)) ) + + { + resultsFrame.location.href = resultsPageWithSearch; + } + + // So if the results page is right and there's no IE bug, reperform the search on the existing page. We have to check if there + // are results because NoResults.html doesn't have any JavaScript, and it would be useless to do anything on that page even + // if it did. + else if (hasResultsPage) + { + // We need to check if this exists in case the frame is present but didn't finish loading. + if (resultsFrame.searchResults) + { resultsFrame.searchResults.Search(searchValue); } + + // Otherwise just reload instead of waiting. + else + { resultsFrame.location.href = resultsPageWithSearch; }; + }; + + + var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + + if (this.mode == "HTML" && domPopupSearchResultsWindow.style.display != "block") + { + var domSearchType = this.DOMSearchType(); + + var left = GetXPosition(domSearchType); + var top = GetYPosition(domSearchType) + domSearchType.offsetHeight; + + MoveToPosition(domPopupSearchResultsWindow, left, top); + domPopupSearchResultsWindow.style.display = 'block'; + }; + + + this.lastSearchValue = searchValue; + this.lastResultsPage = resultsPage; + }; + + + + // Group: Activation Functions + // Functions that handle whether the entire panel is active or not. + // ________________________________________________________________________ + + + /* + Function: Activate + + Activates or deactivates the search panel, resetting things to their default values if necessary. You can call this on every + control's OnBlur() and it will handle not deactivating the entire panel when focus is just switching between them transparently. + + Parameters: + + isActive - Whether you're activating or deactivating the panel. + ignoreDeactivateDelay - Set if you're positive the action will deactivate the panel and thus want to skip the delay. + */ + this.Activate = function(isActive, ignoreDeactivateDelay) + { + // We want to ignore isActive being false while the results window is open. + if (isActive || (this.mode == "HTML" && this.DOMPopupSearchResultsWindow().style.display == "block")) + { + if (this.inactivateTimeout) + { + clearTimeout(this.inactivateTimeout); + this.inactivateTimeout = 0; + }; + + this.DOMSearchPanel().className = 'MSearchPanelActive'; + + var searchField = this.DOMSearchField(); + + if (searchField.value == 'Search') + { searchField.value = ""; } + } + else if (!ignoreDeactivateDelay) + { + this.inactivateTimeout = setTimeout(this.name + ".InactivateAfterTimeout()", this.inactivateTimeoutLength); + } + else + { + this.InactivateAfterTimeout(); + }; + }; + + + /* + Function: InactivateAfterTimeout + + Called by , which is set by . Inactivation occurs on a timeout because a control may + receive OnBlur() when focus is really transferring to another control in the search panel. In this case we don't want to + actually deactivate the panel because not only would that cause a visible flicker but it could also reset the search value. + So by doing it on a timeout instead, there's a short period where the second control's OnFocus() can cancel the deactivation. + */ + this.InactivateAfterTimeout = function() + { + this.inactivateTimeout = 0; + + this.DOMSearchPanel().className = 'MSearchPanelInactive'; + this.DOMSearchField().value = "Search"; + + this.lastSearchValue = ""; + this.lastResultsPage = ""; + }; + }; + + + + +/* ________________________________________________________________________________________________________ + + Class: SearchResults + _________________________________________________________________________________________________________ + + The class that handles everything on the search results page. + _________________________________________________________________________________________________________ +*/ + + +function SearchResults(name, mode) + { + /* + var: mode + The mode the search is going to work in, such as "HTML" or "FramedHTML". + */ + this.mode = mode; + + /* + var: lastMatchCount + The number of matches from the last run of . + */ + this.lastMatchCount = 0; + + + /* + Function: Toggle + Toggles the visibility of the passed element ID. + */ + this.Toggle = function(id) + { + if (this.mode == "FramedHTML") + { return; }; + + var parentElement = document.getElementById(id); + + var element = parentElement.firstChild; + + while (element && element != parentElement) + { + if (element.nodeName == 'DIV' && element.className == 'ISubIndex') + { + if (element.style.display == 'block') + { element.style.display = "none"; } + else + { element.style.display = 'block'; } + }; + + if (element.nodeName == 'DIV' && element.hasChildNodes()) + { element = element.firstChild; } + else if (element.nextSibling) + { element = element.nextSibling; } + else + { + do + { + element = element.parentNode; + } + while (element && element != parentElement && !element.nextSibling); + + if (element && element != parentElement) + { element = element.nextSibling; }; + }; + }; + }; + + + /* + Function: Search + + Searches for the passed string. If there is no parameter, it takes it from the URL query. + + Always returns true, since other documents may try to call it and that may or may not be possible. + */ + this.Search = function(search) + { + if (!search) + { + search = window.location.search; + search = search.substring(1); // Remove the leading ? + search = unescape(search); + }; + + search = search.replace(/^ +/, ""); + search = search.replace(/ +$/, ""); + search = search.toLowerCase(); + + if (search.match(/[^a-z0-9]/)) // Just a little speedup so it doesn't have to go through the below unnecessarily. + { + search = search.replace(/\_/g, "_und"); + search = search.replace(/\ +/gi, "_spc"); + search = search.replace(/\~/g, "_til"); + search = search.replace(/\!/g, "_exc"); + search = search.replace(/\@/g, "_att"); + search = search.replace(/\#/g, "_num"); + search = search.replace(/\$/g, "_dol"); + search = search.replace(/\%/g, "_pct"); + search = search.replace(/\^/g, "_car"); + search = search.replace(/\&/g, "_amp"); + search = search.replace(/\*/g, "_ast"); + search = search.replace(/\(/g, "_lpa"); + search = search.replace(/\)/g, "_rpa"); + search = search.replace(/\-/g, "_min"); + search = search.replace(/\+/g, "_plu"); + search = search.replace(/\=/g, "_equ"); + search = search.replace(/\{/g, "_lbc"); + search = search.replace(/\}/g, "_rbc"); + search = search.replace(/\[/g, "_lbk"); + search = search.replace(/\]/g, "_rbk"); + search = search.replace(/\:/g, "_col"); + search = search.replace(/\;/g, "_sco"); + search = search.replace(/\"/g, "_quo"); + search = search.replace(/\'/g, "_apo"); + search = search.replace(/\/g, "_ran"); + search = search.replace(/\,/g, "_com"); + search = search.replace(/\./g, "_per"); + search = search.replace(/\?/g, "_que"); + search = search.replace(/\//g, "_sla"); + search = search.replace(/[^a-z0-9\_]i/gi, "_zzz"); + }; + + var resultRows = document.getElementsByTagName("div"); + var matches = 0; + + var i = 0; + while (i < resultRows.length) + { + var row = resultRows.item(i); + + if (row.className == "SRResult") + { + var rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); + + if (search.length <= rowMatchName.length && rowMatchName.substr(0, search.length) == search) + { + row.style.display = "block"; + matches++; + } + else + { row.style.display = "none"; }; + }; + + i++; + }; + + document.getElementById("Searching").style.display="none"; + + if (matches == 0) + { document.getElementById("NoMatches").style.display="block"; } + else + { document.getElementById("NoMatches").style.display="none"; } + + this.lastMatchCount = matches; + + return true; + }; + }; + diff --git a/phpgwapi/js/jquery/jqplot/docs/javascript/searchdata.js b/phpgwapi/js/jquery/jqplot/docs/javascript/searchdata.js new file mode 100644 index 0000000000..691a4e6c3b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/javascript/searchdata.js @@ -0,0 +1,182 @@ +var indexSectionsWithContent = { + "General": { + "Symbols": true, + "Numbers": false, + "A": true, + "B": true, + "C": true, + "D": true, + "E": true, + "F": true, + "G": true, + "H": true, + "I": true, + "J": true, + "K": false, + "L": true, + "M": true, + "N": true, + "O": true, + "P": true, + "Q": false, + "R": true, + "S": true, + "T": true, + "U": true, + "V": true, + "W": true, + "X": true, + "Y": true, + "Z": true + }, + "Functions": { + "Symbols": false, + "Numbers": false, + "A": false, + "B": false, + "C": true, + "D": true, + "E": false, + "F": false, + "G": true, + "H": false, + "I": true, + "J": false, + "K": false, + "L": false, + "M": true, + "N": true, + "O": false, + "P": false, + "Q": false, + "R": true, + "S": true, + "T": false, + "U": false, + "V": false, + "W": false, + "X": false, + "Y": false, + "Z": true + }, + "Files": { + "Symbols": false, + "Numbers": false, + "A": false, + "B": false, + "C": false, + "D": false, + "E": false, + "F": false, + "G": false, + "H": false, + "I": false, + "J": true, + "K": false, + "L": false, + "M": false, + "N": false, + "O": false, + "P": false, + "Q": false, + "R": false, + "S": false, + "T": false, + "U": false, + "V": false, + "W": false, + "X": false, + "Y": false, + "Z": false + }, + "Classes": { + "Symbols": true, + "Numbers": false, + "A": true, + "B": false, + "C": false, + "D": true, + "E": false, + "F": false, + "G": true, + "H": true, + "I": false, + "J": true, + "K": false, + "L": true, + "M": false, + "N": false, + "O": false, + "P": false, + "Q": false, + "R": false, + "S": true, + "T": true, + "U": false, + "V": true, + "W": false, + "X": false, + "Y": false, + "Z": false + }, + "Hooks": { + "Symbols": false, + "Numbers": false, + "A": true, + "B": false, + "C": false, + "D": false, + "E": true, + "F": false, + "G": false, + "H": false, + "I": false, + "J": true, + "K": false, + "L": false, + "M": false, + "N": false, + "O": false, + "P": true, + "Q": false, + "R": false, + "S": false, + "T": false, + "U": false, + "V": false, + "W": false, + "X": false, + "Y": false, + "Z": false + }, + "Properties": { + "Symbols": false, + "Numbers": false, + "A": true, + "B": true, + "C": true, + "D": true, + "E": true, + "F": true, + "G": true, + "H": true, + "I": true, + "J": false, + "K": false, + "L": true, + "M": true, + "N": true, + "O": true, + "P": true, + "Q": false, + "R": true, + "S": true, + "T": true, + "U": true, + "V": true, + "W": true, + "X": true, + "Y": true, + "Z": true + } + } \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesA.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesA.html new file mode 100644 index 0000000000..2f4dab5779 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesA.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesD.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesD.html new file mode 100644 index 0000000000..135eeb6a24 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesD.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesG.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesG.html new file mode 100644 index 0000000000..36f121b0ac --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesG.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesH.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesH.html new file mode 100644 index 0000000000..c411b320f9 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesH.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesJ.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesJ.html new file mode 100644 index 0000000000..b22500983c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesJ.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesL.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesL.html new file mode 100644 index 0000000000..6a93b819d9 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesL.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesS.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesS.html new file mode 100644 index 0000000000..53823e7dc0 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesS.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesSymbols.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesSymbols.html new file mode 100644 index 0000000000..33176d7b96 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesSymbols.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesT.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesT.html new file mode 100644 index 0000000000..782f11db17 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesT.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/ClassesV.html b/phpgwapi/js/jquery/jqplot/docs/search/ClassesV.html new file mode 100644 index 0000000000..62d2e7cb2f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/ClassesV.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FilesJ.html b/phpgwapi/js/jquery/jqplot/docs/search/FilesJ.html new file mode 100644 index 0000000000..23a16d7fe4 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FilesJ.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsC.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsC.html new file mode 100644 index 0000000000..40135d3a6c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsC.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    copy, $.jqplot.ThemeEngine
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsD.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsD.html new file mode 100644 index 0000000000..2c2bed5db5 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsD.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    destroy, jqPlot
    drawSeries, jqPlot
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsG.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsG.html new file mode 100644 index 0000000000..561eabc01b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsG.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    get, $.jqplot.ThemeEngine
    getThemeNames, $.jqplot.ThemeEngine
    getThemes, $.jqplot.ThemeEngine
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsI.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsI.html new file mode 100644 index 0000000000..4509098359 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsI.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    init, jqPlot
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsM.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsM.html new file mode 100644 index 0000000000..170b47a67c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsM.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    moveBlock, $.jqplot.BlockRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsN.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsN.html new file mode 100644 index 0000000000..7cc60bfeca --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsN.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    newTheme, $.jqplot.ThemeEngine
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsR.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsR.html new file mode 100644 index 0000000000..fac0dbcc8c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsR.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    redraw, jqPlot
    reInitialize, jqPlot
    remove, $.jqplot.ThemeEngine
    rename, $.jqplot.ThemeEngine
    replot, jqPlot
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsS.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsS.html new file mode 100644 index 0000000000..add3f34ecd --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsS.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/FunctionsZ.html b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsZ.html new file mode 100644 index 0000000000..4b364e9830 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/FunctionsZ.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    zoomProxy, $.jqplot.Cursor.$.jqplot.Cursor
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralA.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralA.html new file mode 100644 index 0000000000..29f0aa0ed8 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralA.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    activeTheme, $.jqplot.ThemeEngine
    addLegendRowHooks, $.jqplot.$.jqplot
    alpha, $.jqplot.shadowRenderer
    autoscale, Axis
    autoscaleBubbles, $.jqplot.BubbleRenderer
    autoscaleMultiplier, $.jqplot.BubbleRenderer
    autoscalePointsFactor, $.jqplot.BubbleRenderer
    axes, jqPlot
    axesDefaults, jqPlot
    axisDefaults, $.jqplot.LogAxisRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralB.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralB.html new file mode 100644 index 0000000000..783b186a9a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralB.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    barDirection, $.jqplot.BarRenderer
    barLabelOptions, $.jqplot.MekkoAxisRenderer
    barLabelRenderer, $.jqplot.MekkoAxisRenderer
    barLabels, $.jqplot.MekkoAxisRenderer
    barMargin, $.jqplot.BarRenderer
    barPadding, $.jqplot.BarRenderer
    barWidth, $.jqplot.BarRenderer
    bodyWidth, $.jqplot.OHLCRenderer
    border, Legend
    breakOnNull, Series
    breakPoints, $.jqplot.LinearAxisRenderer
    breakTickLabel, $.jqplot.LinearAxisRenderer
    bringSeriesToFront, $.jqplot.Highlighter
    bubbleAlpha, $.jqplot.BubbleRenderer
    bubbleGradients, $.jqplot.BubbleRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralC.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralC.html new file mode 100644 index 0000000000..a38cdbc204 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralC.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    candleStick, $.jqplot.OHLCRenderer
    clearRect, $.jqplot.shapeRenderer
    clickReset, $.jqplot.Cursor
    closeColor, $.jqplot.OHLCRenderer
    constrainOutsideZoom, $.jqplot.Cursor
    constrainTo, $.jqplot.Dragable
    constrainZoomTo, $.jqplot.Cursor
    copy, $.jqplot.ThemeEngine
    css, $.jqplot.BlockRenderer
    cursorLegendFormatString, $.jqplot.Cursor
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralD.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralD.html new file mode 100644 index 0000000000..635a77789b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralD.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralE.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralE.html new file mode 100644 index 0000000000..f84f62de81 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralE.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    edgeTolerance, $.jqplot.PointLabels
    eventListenerHooks, $.jqplot.$.jqplot
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralF.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralF.html new file mode 100644 index 0000000000..5f06dd7cac --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralF.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralG.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralG.html new file mode 100644 index 0000000000..092df15051 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralG.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    get, $.jqplot.ThemeEngine
    getThemeNames, $.jqplot.ThemeEngine
    getThemes, $.jqplot.ThemeEngine
    grid, jqPlot
    groups, $.jqplot.BarRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralH.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralH.html new file mode 100644 index 0000000000..14787ed0c2 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralH.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    hideZeros, $.jqplot.PointLabels
    highlightAlpha, $.jqplot.BubbleRenderer
    highlightColor, $.jqplot.LineRenderer
    hlc, $.jqplot.OHLCRenderer
    Hooks, $.jqplot
    hubRadius, $.jqplot.MeterGaugeRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralI.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralI.html new file mode 100644 index 0000000000..686b62fc73 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralI.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    index, Series
    init, jqPlot
    innerDiameter, $.jqplot.DonutRenderer
    insertBreaks, $.jqplot.BlockRenderer
    intersectionThreshold, $.jqplot.Cursor
    intervalColors, $.jqplot.MeterGaugeRenderer
    intervalInnerRadius, $.jqplot.MeterGaugeRenderer
    intervalOuterRadius, $.jqplot.MeterGaugeRenderer
    intervals, $.jqplot.MeterGaugeRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralJ.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralJ.html new file mode 100644 index 0000000000..821dfbca0a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralJ.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralL.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralL.html new file mode 100644 index 0000000000..4be72ad53b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralL.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralM.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralM.html new file mode 100644 index 0000000000..653f2e3716 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralM.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    marginBottom, Legend
    marginLeft, Legend
    marginRight, Legend
    marginTop, Legend
    Methods, $.jqplot.BlockRenderer
    moveBlock, $.jqplot.BlockRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralN.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralN.html new file mode 100644 index 0000000000..aa5da8e64e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralN.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    needlePad, $.jqplot.MeterGaugeRenderer
    needleThickness, $.jqplot.MeterGaugeRenderer
    newTheme, $.jqplot.ThemeEngine
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralO.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralO.html new file mode 100644 index 0000000000..2d22b44bc7 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralO.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    objects, $.jqplot.CanvasOverlay
    offset, $.jqplot.shadowRenderer
    openColor, $.jqplot.OHLCRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralP.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralP.html new file mode 100644 index 0000000000..5342549248 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralP.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    pad, Axis
    padMax, Axis
    padMin, Axis
    pegNeedle, $.jqplot.MeterGaugeRenderer
    placement, Legend
    postDrawHooks, $.jqplot.$.jqplot
    postDrawSeriesHooks, $.jqplot.$.jqplot
    postDrawSeriesShadowHooks, $.jqplot.$.jqplot
    postInitHooks, $.jqplot.$.jqplot
    postParseOptionsHooks, $.jqplot.$.jqplot
    postParseSeriesOptionsHooks, $.jqplot.$.jqplot
    postSeriesInitHooks, $.jqplot.$.jqplot
    predraw, Legend
    preDrawHooks, $.jqplot.$.jqplot
    preDrawLegendHooks, $.jqplot.$.jqplot
    preDrawSeriesHooks, $.jqplot.$.jqplot
    preDrawSeriesShadowHooks, $.jqplot.$.jqplot
    preInitHooks, $.jqplot.$.jqplot
    preParseOptionsHooks, $.jqplot.$.jqplot
    preParseSeriesOptionsHooks, $.jqplot.$.jqplot
    preSeriesInitHooks, $.jqplot.$.jqplot
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralR.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralR.html new file mode 100644 index 0000000000..830dac937b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralR.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    redraw, jqPlot
    reInitialize, jqPlot
    remove, $.jqplot.ThemeEngine
    rename, $.jqplot.ThemeEngine
    replot, jqPlot
    ringColor, $.jqplot.MeterGaugeRenderer
    ringMargin, $.jqplot.DonutRenderer
    ringWidth, $.jqplot.MeterGaugeRenderer
    rowSpacing, Legend
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralS.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralS.html new file mode 100644 index 0000000000..b6bb53b7cc --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralS.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    sectionMargin, $.jqplot.FunnelRenderer
    series, jqPlot
    seriesColors, jqPlot
    seriesLabelIndex, $.jqplot.PointLabels
    shadowRenderer, $.jqplot.MarkerRenderer
    shapeRenderer, $.jqplot.MarkerRenderer
    showBorders, $.jqplot.MekkoRenderer
    showCursorLegend, $.jqplot.Cursor
    showHorizontalLine, $.jqplot.Cursor
    showLine, Series
    showSwatch, Legend
    showTickLabels, $.jqplot.MeterGaugeRenderer
    showTooltipDataPosition, $.jqplot.Cursor
    showTooltipGridPosition, $.jqplot.Cursor
    showTooltipOutsideZoom, $.jqplot.Cursor
    showTooltipUnitPosition, $.jqplot.Cursor
    showVerticalLine, $.jqplot.Cursor
    sizeAdjust, $.jqplot.Highlighter
    sortData, jqPlot
    sortMergedLabels, $.jqplot.CategoryAxisRenderer
    stackedValue, $.jqplot.PointLabels
    stackSeries, jqPlot
    start, Line
    stop, Line
    strokeRect, $.jqplot.shapeRenderer
    strokeStyle, $.jqplot.shapeRenderer
    syncTicks, Axis
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralSymbols.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralSymbols.html new file mode 100644 index 0000000000..33176d7b96 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralSymbols.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralT.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralT.html new file mode 100644 index 0000000000..551bb65eba --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralT.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    text, Title
    textAlign, Title
    themes, $.jqplot.ThemeEngine
    thickness, $.jqplot.DonutRenderer
    tickColor, $.jqplot.MeterGaugeRenderer
    tickLength, $.jqplot.OHLCRenderer
    tickMode, $.jqplot.MekkoAxisRenderer
    tickPadding, $.jqplot.MeterGaugeRenderer
    title, jqPlot
    tooltipAxes, $.jqplot.Highlighter
    tooltipAxisGroups, $.jqplot.Cursor
    tooltipFadeSpeed, $.jqplot.Highlighter
    type, $.jqplot.Trendline
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralU.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralU.html new file mode 100644 index 0000000000..31bcbf1227 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralU.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    upBodyColor, $.jqplot.OHLCRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralV.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralV.html new file mode 100644 index 0000000000..51af427ec9 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralV.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    varyBarColor, $.jqplot.BarRenderer
    varyBlockColors, $.jqplot.BlockRenderer
    varyBubbleColors, $.jqplot.BubbleRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralW.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralW.html new file mode 100644 index 0000000000..ce589762e5 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralW.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    waterfall, $.jqplot.BarRenderer
    wickColor, $.jqplot.OHLCRenderer
    widthRatio, $.jqplot.FunnelRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralX.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralX.html new file mode 100644 index 0000000000..1794161a5d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralX.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    xmax, HorizontalLine
    xmin, HorizontalLine
    xoffset, Legend
    xpadding, $.jqplot.PointLabels
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralY.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralY.html new file mode 100644 index 0000000000..cc799a365e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralY.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    y, HorizontalLine
    yoffset, Legend
    ypadding, $.jqplot.PointLabels
    yvalues, $.jqplot.Highlighter
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/GeneralZ.html b/phpgwapi/js/jquery/jqplot/docs/search/GeneralZ.html new file mode 100644 index 0000000000..1e8baa0808 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/GeneralZ.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    zoom, $.jqplot.Cursor
    zoomProxy, $.jqplot.Cursor.$.jqplot.Cursor
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/HooksA.html b/phpgwapi/js/jquery/jqplot/docs/search/HooksA.html new file mode 100644 index 0000000000..82b17cda67 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/HooksA.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    addLegendRowHooks, $.jqplot.$.jqplot
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/HooksE.html b/phpgwapi/js/jquery/jqplot/docs/search/HooksE.html new file mode 100644 index 0000000000..fe464932ec --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/HooksE.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    eventListenerHooks, $.jqplot.$.jqplot
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/HooksJ.html b/phpgwapi/js/jquery/jqplot/docs/search/HooksJ.html new file mode 100644 index 0000000000..f94e003683 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/HooksJ.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/HooksP.html b/phpgwapi/js/jquery/jqplot/docs/search/HooksP.html new file mode 100644 index 0000000000..eb28c716c0 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/HooksP.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    postDrawHooks, $.jqplot.$.jqplot
    postDrawSeriesHooks, $.jqplot.$.jqplot
    postDrawSeriesShadowHooks, $.jqplot.$.jqplot
    postInitHooks, $.jqplot.$.jqplot
    postParseOptionsHooks, $.jqplot.$.jqplot
    postParseSeriesOptionsHooks, $.jqplot.$.jqplot
    postSeriesInitHooks, $.jqplot.$.jqplot
    preDrawHooks, $.jqplot.$.jqplot
    preDrawLegendHooks, $.jqplot.$.jqplot
    preDrawSeriesHooks, $.jqplot.$.jqplot
    preDrawSeriesShadowHooks, $.jqplot.$.jqplot
    preInitHooks, $.jqplot.$.jqplot
    preParseOptionsHooks, $.jqplot.$.jqplot
    preParseSeriesOptionsHooks, $.jqplot.$.jqplot
    preSeriesInitHooks, $.jqplot.$.jqplot
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/NoResults.html b/phpgwapi/js/jquery/jqplot/docs/search/NoResults.html new file mode 100644 index 0000000000..d2459c05e1 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/NoResults.html @@ -0,0 +1,15 @@ + + + + + + + + + + + + +
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesA.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesA.html new file mode 100644 index 0000000000..6905ebbe53 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesA.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    activeTheme, $.jqplot.ThemeEngine
    alpha, $.jqplot.shadowRenderer
    autoscale, Axis
    autoscaleBubbles, $.jqplot.BubbleRenderer
    autoscaleMultiplier, $.jqplot.BubbleRenderer
    autoscalePointsFactor, $.jqplot.BubbleRenderer
    axes, jqPlot
    axesDefaults, jqPlot
    axisDefaults, $.jqplot.LogAxisRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesB.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesB.html new file mode 100644 index 0000000000..783b186a9a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesB.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    barDirection, $.jqplot.BarRenderer
    barLabelOptions, $.jqplot.MekkoAxisRenderer
    barLabelRenderer, $.jqplot.MekkoAxisRenderer
    barLabels, $.jqplot.MekkoAxisRenderer
    barMargin, $.jqplot.BarRenderer
    barPadding, $.jqplot.BarRenderer
    barWidth, $.jqplot.BarRenderer
    bodyWidth, $.jqplot.OHLCRenderer
    border, Legend
    breakOnNull, Series
    breakPoints, $.jqplot.LinearAxisRenderer
    breakTickLabel, $.jqplot.LinearAxisRenderer
    bringSeriesToFront, $.jqplot.Highlighter
    bubbleAlpha, $.jqplot.BubbleRenderer
    bubbleGradients, $.jqplot.BubbleRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesC.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesC.html new file mode 100644 index 0000000000..a8e4296ee7 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesC.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    candleStick, $.jqplot.OHLCRenderer
    clearRect, $.jqplot.shapeRenderer
    clickReset, $.jqplot.Cursor
    closeColor, $.jqplot.OHLCRenderer
    constrainOutsideZoom, $.jqplot.Cursor
    constrainTo, $.jqplot.Dragable
    constrainZoomTo, $.jqplot.Cursor
    css, $.jqplot.BlockRenderer
    cursorLegendFormatString, $.jqplot.Cursor
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesD.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesD.html new file mode 100644 index 0000000000..725cd19f0a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesD.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesE.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesE.html new file mode 100644 index 0000000000..2dadb0993d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesE.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    edgeTolerance, $.jqplot.PointLabels
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesF.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesF.html new file mode 100644 index 0000000000..edbc3557a5 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesF.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesG.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesG.html new file mode 100644 index 0000000000..3a7573d17c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesG.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    grid, jqPlot
    groups, $.jqplot.BarRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesH.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesH.html new file mode 100644 index 0000000000..8370a42566 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesH.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    hideZeros, $.jqplot.PointLabels
    highlightAlpha, $.jqplot.BubbleRenderer
    highlightColor, $.jqplot.LineRenderer
    hlc, $.jqplot.OHLCRenderer
    hubRadius, $.jqplot.MeterGaugeRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesI.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesI.html new file mode 100644 index 0000000000..c254cf57d3 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesI.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    index, Series
    innerDiameter, $.jqplot.DonutRenderer
    insertBreaks, $.jqplot.BlockRenderer
    intersectionThreshold, $.jqplot.Cursor
    intervalColors, $.jqplot.MeterGaugeRenderer
    intervalInnerRadius, $.jqplot.MeterGaugeRenderer
    intervalOuterRadius, $.jqplot.MeterGaugeRenderer
    intervals, $.jqplot.MeterGaugeRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesL.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesL.html new file mode 100644 index 0000000000..1c8c930ac3 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesL.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesM.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesM.html new file mode 100644 index 0000000000..f6c73bdc81 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesM.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    marginBottom, Legend
    marginLeft, Legend
    marginRight, Legend
    marginTop, Legend
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesN.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesN.html new file mode 100644 index 0000000000..2b11fa9201 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesN.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    needlePad, $.jqplot.MeterGaugeRenderer
    needleThickness, $.jqplot.MeterGaugeRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesO.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesO.html new file mode 100644 index 0000000000..daba150071 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesO.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    objects, $.jqplot.CanvasOverlay
    offset, $.jqplot.shadowRenderer
    openColor, $.jqplot.OHLCRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesP.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesP.html new file mode 100644 index 0000000000..a80f21dc03 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesP.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    pad, Axis
    padMax, Axis
    padMin, Axis
    pegNeedle, $.jqplot.MeterGaugeRenderer
    placement, Legend
    predraw, Legend
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesR.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesR.html new file mode 100644 index 0000000000..a462e09912 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesR.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    ringColor, $.jqplot.MeterGaugeRenderer
    ringMargin, $.jqplot.DonutRenderer
    ringWidth, $.jqplot.MeterGaugeRenderer
    rowSpacing, Legend
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesS.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesS.html new file mode 100644 index 0000000000..8df1d24737 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesS.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    sectionMargin, $.jqplot.FunnelRenderer
    series, jqPlot
    seriesColors, jqPlot
    seriesLabelIndex, $.jqplot.PointLabels
    shadowRenderer, $.jqplot.MarkerRenderer
    shapeRenderer, $.jqplot.MarkerRenderer
    showBorders, $.jqplot.MekkoRenderer
    showCursorLegend, $.jqplot.Cursor
    showHorizontalLine, $.jqplot.Cursor
    showLine, Series
    showSwatch, Legend
    showTickLabels, $.jqplot.MeterGaugeRenderer
    showTooltipDataPosition, $.jqplot.Cursor
    showTooltipGridPosition, $.jqplot.Cursor
    showTooltipOutsideZoom, $.jqplot.Cursor
    showTooltipUnitPosition, $.jqplot.Cursor
    showVerticalLine, $.jqplot.Cursor
    sizeAdjust, $.jqplot.Highlighter
    sortData, jqPlot
    sortMergedLabels, $.jqplot.CategoryAxisRenderer
    stackedValue, $.jqplot.PointLabels
    stackSeries, jqPlot
    start, Line
    stop, Line
    strokeRect, $.jqplot.shapeRenderer
    strokeStyle, $.jqplot.shapeRenderer
    syncTicks, Axis
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesT.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesT.html new file mode 100644 index 0000000000..bd46b5d189 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesT.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    text, Title
    textAlign, Title
    themes, $.jqplot.ThemeEngine
    thickness, $.jqplot.DonutRenderer
    tickColor, $.jqplot.MeterGaugeRenderer
    tickLength, $.jqplot.OHLCRenderer
    tickMode, $.jqplot.MekkoAxisRenderer
    tickPadding, $.jqplot.MeterGaugeRenderer
    title, jqPlot
    tooltipAxes, $.jqplot.Highlighter
    tooltipAxisGroups, $.jqplot.Cursor
    tooltipFadeSpeed, $.jqplot.Highlighter
    type, $.jqplot.Trendline
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesU.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesU.html new file mode 100644 index 0000000000..df97c192a6 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesU.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    upBodyColor, $.jqplot.OHLCRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesV.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesV.html new file mode 100644 index 0000000000..ebd8349ebc --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesV.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    varyBarColor, $.jqplot.BarRenderer
    varyBlockColors, $.jqplot.BlockRenderer
    varyBubbleColors, $.jqplot.BubbleRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesW.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesW.html new file mode 100644 index 0000000000..ce589762e5 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesW.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    waterfall, $.jqplot.BarRenderer
    wickColor, $.jqplot.OHLCRenderer
    widthRatio, $.jqplot.FunnelRenderer
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesX.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesX.html new file mode 100644 index 0000000000..1794161a5d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesX.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    xmax, HorizontalLine
    xmin, HorizontalLine
    xoffset, Legend
    xpadding, $.jqplot.PointLabels
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesY.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesY.html new file mode 100644 index 0000000000..cc799a365e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesY.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    y, HorizontalLine
    yoffset, Legend
    ypadding, $.jqplot.PointLabels
    yvalues, $.jqplot.Highlighter
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/search/PropertiesZ.html b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesZ.html new file mode 100644 index 0000000000..9da6ccfc7d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/search/PropertiesZ.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + +
    Loading...
    zoom, $.jqplot.Cursor
    Searching...
    No Matches
    \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/docs/styles/1.css b/phpgwapi/js/jquery/jqplot/docs/styles/1.css new file mode 100644 index 0000000000..17e9cbc30f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/styles/1.css @@ -0,0 +1,767 @@ +/* + IMPORTANT: If you're editing this file in the output directory of one of + your projects, your changes will be overwritten the next time you run + Natural Docs. Instead, copy this file to your project directory, make your + changes, and you can use it with -s. Even better would be to make a CSS + file in your project directory with only your changes, which you can then + use with -s [original style] [your changes]. + + On the other hand, if you're editing this file in the Natural Docs styles + directory, the changes will automatically be applied to all your projects + that use this style the next time Natural Docs is run on them. + + This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure + Natural Docs is licensed under the GPL +*/ + +body { + font: 10pt Verdana, Arial, sans-serif; + color: #000000; + margin: 0; padding: 0; + } + +.ContentPage, +.IndexPage, +.FramedMenuPage { + background-color: #E8E8E8; + } +.FramedContentPage, +.FramedIndexPage, +.FramedSearchResultsPage, +.PopupSearchResultsPage { + background-color: #FFFFFF; + } + + +a:link, +a:visited { color: #900000; text-decoration: none } +a:hover { color: #900000; text-decoration: underline } +a:active { color: #FF0000; text-decoration: underline } + +td { + vertical-align: top } + +img { border: 0; } + + +/* + Comment out this line to use web-style paragraphs (blank line between + paragraphs, no indent) instead of print-style paragraphs (no blank line, + indented.) +*/ +p { + text-indent: 5ex; margin: 0 } + + +/* Opera doesn't break with just wbr, but will if you add this. */ +.Opera wbr:after { + content: "\00200B"; + } + + +/* Blockquotes are used as containers for things that may need to scroll. */ +blockquote { + padding: 0; + margin: 0; + overflow: auto; + } + + +.Firefox1 blockquote { + padding-bottom: .5em; + } + +/* Turn off scrolling when printing. */ +@media print { + blockquote { + overflow: visible; + } + .IE blockquote { + width: auto; + } + } + + + +#Menu { + font-size: 9pt; + padding: 10px 0 0 0; + } +.ContentPage #Menu, +.IndexPage #Menu { + position: absolute; + top: 0; + left: 0; + width: 31ex; + overflow: hidden; + } +.ContentPage .Firefox #Menu, +.IndexPage .Firefox #Menu { + width: 27ex; + } + + + .MTitle { + font-size: 16pt; font-weight: bold; font-variant: small-caps; + text-align: center; + padding: 5px 10px 15px 10px; + border-bottom: 1px dotted #000000; + margin-bottom: 15px } + + .MSubTitle { + font-size: 9pt; font-weight: normal; font-variant: normal; + margin-top: 1ex; margin-bottom: 5px } + + + .MEntry a:link, + .MEntry a:hover, + .MEntry a:visited { color: #606060; margin-right: 0 } + .MEntry a:active { color: #A00000; margin-right: 0 } + + + .MGroup { + font-variant: small-caps; font-weight: bold; + margin: 1em 0 1em 10px; + } + + .MGroupContent { + font-variant: normal; font-weight: normal } + + .MGroup a:link, + .MGroup a:hover, + .MGroup a:visited { color: #545454; margin-right: 10px } + .MGroup a:active { color: #A00000; margin-right: 10px } + + + .MFile, + .MText, + .MLink, + .MIndex { + padding: 1px 17px 2px 10px; + margin: .25em 0 .25em 0; + } + + .MText { + font-size: 8pt; font-style: italic } + + .MLink { + font-style: italic } + + #MSelected { + color: #000000; background-color: #FFFFFF; + /* Replace padding with border. */ + padding: 0 10px 0 10px; + border-width: 1px 2px 2px 0; border-style: solid; border-color: #000000; + margin-right: 5px; + } + + /* Close off the left side when its in a group. */ + .MGroup #MSelected { + padding-left: 9px; border-left-width: 1px } + + /* A treat for Mozilla users. Blatantly non-standard. Will be replaced with CSS 3 attributes when finalized/supported. */ + .Firefox #MSelected { + -moz-border-radius-topright: 10px; + -moz-border-radius-bottomright: 10px } + .Firefox .MGroup #MSelected { + -moz-border-radius-topleft: 10px; + -moz-border-radius-bottomleft: 10px } + + + #MSearchPanel { + padding: 0px 6px; + margin: .25em 0; + } + + + #MSearchField { + font: italic 9pt Verdana, sans-serif; + color: #606060; + background-color: #E8E8E8; + border: none; + padding: 2px 4px; + width: 100%; + } + /* Only Opera gets it right. */ + .Firefox #MSearchField, + .IE #MSearchField, + .Safari #MSearchField { + width: 94%; + } + .Opera9 #MSearchField, + .Konqueror #MSearchField { + width: 97%; + } + .FramedMenuPage .Firefox #MSearchField, + .FramedMenuPage .Safari #MSearchField, + .FramedMenuPage .Konqueror #MSearchField { + width: 98%; + } + + /* Firefox doesn't do this right in frames without #MSearchPanel added on. + It's presence doesn't hurt anything other browsers. */ + #MSearchPanel.MSearchPanelInactive:hover #MSearchField { + background-color: #FFFFFF; + border: 1px solid #C0C0C0; + padding: 1px 3px; + } + .MSearchPanelActive #MSearchField { + background-color: #FFFFFF; + border: 1px solid #C0C0C0; + font-style: normal; + padding: 1px 3px; + } + + #MSearchType { + visibility: hidden; + font: 8pt Verdana, sans-serif; + width: 98%; + padding: 0; + border: 1px solid #C0C0C0; + } + .MSearchPanelActive #MSearchType, + /* As mentioned above, Firefox doesn't do this right in frames without #MSearchPanel added on. */ + #MSearchPanel.MSearchPanelInactive:hover #MSearchType, + #MSearchType:focus { + visibility: visible; + color: #606060; + } + #MSearchType option#MSearchEverything { + font-weight: bold; + } + + .Opera8 .MSearchPanelInactive:hover, + .Opera8 .MSearchPanelActive { + margin-left: -1px; + } + + + iframe#MSearchResults { + width: 60ex; + height: 15em; + } + #MSearchResultsWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #000000; + background-color: #E8E8E8; + } + #MSearchResultsWindowClose { + font-weight: bold; + font-size: 8pt; + display: block; + padding: 2px 5px; + } + #MSearchResultsWindowClose:link, + #MSearchResultsWindowClose:visited { + color: #000000; + text-decoration: none; + } + #MSearchResultsWindowClose:active, + #MSearchResultsWindowClose:hover { + color: #800000; + text-decoration: none; + background-color: #F4F4F4; + } + + + + +#Content { + padding-bottom: 15px; + } + +.ContentPage #Content { + border-width: 0 0 1px 1px; + border-style: solid; + border-color: #000000; + background-color: #FFFFFF; + font-size: 9pt; /* To make 31ex match the menu's 31ex. */ + margin-left: 31ex; + } +.ContentPage .Firefox #Content { + margin-left: 27ex; + } + + + + .CTopic { + font-size: 10pt; + margin-bottom: 3em; + } + + + .CTitle { + font-size: 12pt; font-weight: bold; + border-width: 0 0 1px 0; border-style: solid; border-color: #A0A0A0; + margin: 0 15px .5em 15px } + + .CGroup .CTitle { + font-size: 16pt; font-variant: small-caps; + padding-left: 15px; padding-right: 15px; + border-width: 0 0 2px 0; border-color: #000000; + margin-left: 0; margin-right: 0 } + + .CClass .CTitle, + .CInterface .CTitle, + .CDatabase .CTitle, + .CDatabaseTable .CTitle, + .CSection .CTitle { + font-size: 18pt; + color: #FFFFFF; background-color: #A0A0A0; + padding: 10px 15px 10px 15px; + border-width: 2px 0; border-color: #000000; + margin-left: 0; margin-right: 0 } + + #MainTopic .CTitle { + font-size: 20pt; + color: #FFFFFF; background-color: #7070C0; + padding: 10px 15px 10px 15px; + border-width: 0 0 3px 0; border-color: #000000; + margin-left: 0; margin-right: 0 } + + .CBody { + margin-left: 15px; margin-right: 15px } + + + .CToolTip { + position: absolute; visibility: hidden; + left: 0; top: 0; + background-color: #FFFFE0; + padding: 5px; + border-width: 1px 2px 2px 1px; border-style: solid; border-color: #000000; + font-size: 8pt; + } + + .Opera .CToolTip { + max-width: 98%; + } + + /* Scrollbars would be useless. */ + .CToolTip blockquote { + overflow: hidden; + } + .IE6 .CToolTip blockquote { + overflow: visible; + } + + .CHeading { + font-weight: bold; font-size: 10pt; + margin: 1.5em 0 .5em 0; + } + + .CBody pre { + font: 10pt "Courier New", Courier, monospace; + margin: 1em 0; + } + + .CBody ul { + /* I don't know why CBody's margin doesn't apply, but it's consistent across browsers so whatever. + Reapply it here as padding. */ + padding-left: 15px; padding-right: 15px; + margin: .5em 5ex .5em 5ex; + } + + .CDescriptionList { + margin: .5em 5ex 0 5ex } + + .CDLEntry { + font: 10pt "Courier New", Courier, monospace; color: #808080; + padding-bottom: .25em; + white-space: nowrap } + + .CDLDescription { + font-size: 10pt; /* For browsers that don't inherit correctly, like Opera 5. */ + padding-bottom: .5em; padding-left: 5ex } + + + .CTopic img { + text-align: center; + display: block; + margin: 1em auto; + } + .CImageCaption { + font-variant: small-caps; + font-size: 8pt; + color: #808080; + text-align: center; + position: relative; + top: 1em; + } + + .CImageLink { + color: #808080; + font-style: italic; + } + a.CImageLink:link, + a.CImageLink:visited, + a.CImageLink:hover { color: #808080 } + + + + + +.Prototype { + font: 10pt "Courier New", Courier, monospace; + padding: 5px 3ex; + border-width: 1px; border-style: solid; + margin: 0 5ex 1.5em 5ex; + } + + .Prototype td { + font-size: 10pt; + } + + .PDefaultValue, + .PDefaultValuePrefix, + .PTypePrefix { + color: #8F8F8F; + } + .PTypePrefix { + text-align: right; + } + .PAfterParameters { + vertical-align: bottom; + } + + .IE .Prototype table { + padding: 0; + } + + .CFunction .Prototype { + background-color: #F4F4F4; border-color: #D0D0D0 } + .CProperty .Prototype { + background-color: #F4F4FF; border-color: #C0C0E8 } + .CVariable .Prototype { + background-color: #FFFFF0; border-color: #E0E0A0 } + + .CClass .Prototype { + border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0; + background-color: #F4F4F4; + } + .CInterface .Prototype { + border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0D0; + background-color: #F4F4FF; + } + + .CDatabaseIndex .Prototype, + .CConstant .Prototype { + background-color: #D0D0D0; border-color: #000000 } + .CType .Prototype, + .CEnumeration .Prototype { + background-color: #FAF0F0; border-color: #E0B0B0; + } + .CDatabaseTrigger .Prototype, + .CEvent .Prototype, + .CDelegate .Prototype { + background-color: #F0FCF0; border-color: #B8E4B8 } + + .CToolTip .Prototype { + margin: 0 0 .5em 0; + white-space: nowrap; + } + + + + + +.Summary { + margin: 1.5em 5ex 0 5ex } + + .STitle { + font-size: 12pt; font-weight: bold; + margin-bottom: .5em } + + + .SBorder { + background-color: #FFFFF0; + padding: 15px; + border: 1px solid #C0C060 } + + /* In a frame IE 6 will make them too long unless you set the width to 100%. Without frames it will be correct without a width + or slightly too long (but not enough to scroll) with a width. This arbitrary weirdness simply astounds me. IE 7 has the same + problem with frames, haven't tested it without. */ + .FramedContentPage .IE .SBorder { + width: 100% } + + /* A treat for Mozilla users. Blatantly non-standard. Will be replaced with CSS 3 attributes when finalized/supported. */ + .Firefox .SBorder { + -moz-border-radius: 20px } + + + .STable { + font-size: 9pt; width: 100% } + + .SEntry { + width: 30% } + .SDescription { + width: 70% } + + + .SMarked { + background-color: #F8F8D8 } + + .SDescription { padding-left: 2ex } + .SIndent1 .SEntry { padding-left: 1.5ex } .SIndent1 .SDescription { padding-left: 3.5ex } + .SIndent2 .SEntry { padding-left: 3.0ex } .SIndent2 .SDescription { padding-left: 5.0ex } + .SIndent3 .SEntry { padding-left: 4.5ex } .SIndent3 .SDescription { padding-left: 6.5ex } + .SIndent4 .SEntry { padding-left: 6.0ex } .SIndent4 .SDescription { padding-left: 8.0ex } + .SIndent5 .SEntry { padding-left: 7.5ex } .SIndent5 .SDescription { padding-left: 9.5ex } + + .SDescription a { color: #800000} + .SDescription a:active { color: #A00000 } + + .SGroup td { + padding-top: .5em; padding-bottom: .25em } + + .SGroup .SEntry { + font-weight: bold; font-variant: small-caps } + + .SGroup .SEntry a { color: #800000 } + .SGroup .SEntry a:active { color: #F00000 } + + + .SMain td, + .SClass td, + .SDatabase td, + .SDatabaseTable td, + .SSection td { + font-size: 10pt; + padding-bottom: .25em } + + .SClass td, + .SDatabase td, + .SDatabaseTable td, + .SSection td { + padding-top: 1em } + + .SMain .SEntry, + .SClass .SEntry, + .SDatabase .SEntry, + .SDatabaseTable .SEntry, + .SSection .SEntry { + font-weight: bold; + } + + .SMain .SEntry a, + .SClass .SEntry a, + .SDatabase .SEntry a, + .SDatabaseTable .SEntry a, + .SSection .SEntry a { color: #000000 } + + .SMain .SEntry a:active, + .SClass .SEntry a:active, + .SDatabase .SEntry a:active, + .SDatabaseTable .SEntry a:active, + .SSection .SEntry a:active { color: #A00000 } + + + + + +.ClassHierarchy { + margin: 0 15px 1em 15px } + + .CHEntry { + border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0; + margin-bottom: 3px; + padding: 2px 2ex; + font-size: 10pt; + background-color: #F4F4F4; color: #606060; + } + + .Firefox .CHEntry { + -moz-border-radius: 4px; + } + + .CHCurrent .CHEntry { + font-weight: bold; + border-color: #000000; + color: #000000; + } + + .CHChildNote .CHEntry { + font-style: italic; + font-size: 8pt; + } + + .CHIndent { + margin-left: 3ex; + } + + .CHEntry a:link, + .CHEntry a:visited, + .CHEntry a:hover { + color: #606060; + } + .CHEntry a:active { + color: #800000; + } + + + + + +#Index { + background-color: #FFFFFF; + } + +/* As opposed to .PopupSearchResultsPage #Index */ +.IndexPage #Index, +.FramedIndexPage #Index, +.FramedSearchResultsPage #Index { + padding: 15px; + } + +.IndexPage #Index { + border-width: 0 0 1px 1px; + border-style: solid; + border-color: #000000; + font-size: 9pt; /* To make 27ex match the menu's 27ex. */ + margin-left: 27ex; + } + + + .IPageTitle { + font-size: 20pt; font-weight: bold; + color: #FFFFFF; background-color: #7070C0; + padding: 10px 15px 10px 15px; + border-width: 0 0 3px 0; border-color: #000000; border-style: solid; + margin: -15px -15px 0 -15px } + + .FramedSearchResultsPage .IPageTitle { + margin-bottom: 15px; + } + + .INavigationBar { + font-size: 10pt; + text-align: center; + background-color: #FFFFF0; + padding: 5px; + border-bottom: solid 1px black; + margin: 0 -15px 15px -15px; + } + + .INavigationBar a { + font-weight: bold } + + .IHeading { + font-size: 16pt; font-weight: bold; + padding: 2.5em 0 .5em 0; + text-align: center; + width: 3.5ex; + } + #IFirstHeading { + padding-top: 0; + } + + .IEntry { + font-size: 10pt; + padding-left: 1ex; + } + .PopupSearchResultsPage .IEntry { + font-size: 8pt; + padding: 1px 5px; + } + .PopupSearchResultsPage .Opera9 .IEntry, + .FramedSearchResultsPage .Opera9 .IEntry { + text-align: left; + } + .FramedSearchResultsPage .IEntry { + padding: 0; + } + + .ISubIndex { + padding-left: 3ex; padding-bottom: .5em } + .PopupSearchResultsPage .ISubIndex { + display: none; + } + + /* While it may cause some entries to look like links when they aren't, I found it's much easier to read the + index if everything's the same color. */ + .ISymbol { + font-weight: bold; color: #900000 } + + .IndexPage .ISymbolPrefix, + .FramedIndexPage .ISymbolPrefix { + font-size: 10pt; + text-align: right; + color: #C47C7C; + background-color: #F8F8F8; + border-right: 3px solid #E0E0E0; + border-left: 1px solid #E0E0E0; + padding: 0 1px 0 2px; + } + .PopupSearchResultsPage .ISymbolPrefix, + .FramedSearchResultsPage .ISymbolPrefix { + color: #900000; + } + .PopupSearchResultsPage .ISymbolPrefix { + font-size: 8pt; + } + + .IndexPage #IFirstSymbolPrefix, + .FramedIndexPage #IFirstSymbolPrefix { + border-top: 1px solid #E0E0E0; + } + .IndexPage #ILastSymbolPrefix, + .FramedIndexPage #ILastSymbolPrefix { + border-bottom: 1px solid #E0E0E0; + } + .IndexPage #IOnlySymbolPrefix, + .FramedIndexPage #IOnlySymbolPrefix { + border-top: 1px solid #E0E0E0; + border-bottom: 1px solid #E0E0E0; + } + + a.IParent, + a.IFile { + display: block; + } + + .PopupSearchResultsPage .SRStatus { + padding: 2px 5px; + font-size: 8pt; + font-style: italic; + } + .FramedSearchResultsPage .SRStatus { + font-size: 10pt; + font-style: italic; + } + + .SRResult { + display: none; + } + + + +#Footer { + font-size: 8pt; + color: #989898; + text-align: right; + } + +#Footer p { + text-indent: 0; + margin-bottom: .5em; + } + +.ContentPage #Footer, +.IndexPage #Footer { + text-align: right; + margin: 2px; + } + +.FramedMenuPage #Footer { + text-align: center; + margin: 5em 10px 10px 10px; + padding-top: 1em; + border-top: 1px solid #C8C8C8; + } + + #Footer a:link, + #Footer a:hover, + #Footer a:visited { color: #989898 } + #Footer a:active { color: #A00000 } + diff --git a/phpgwapi/js/jquery/jqplot/docs/styles/2.css b/phpgwapi/js/jquery/jqplot/docs/styles/2.css new file mode 100644 index 0000000000..12117d4e6c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/styles/2.css @@ -0,0 +1,174 @@ +html, body { + height: 100%; +} + +/* +div.Firefox { + height: 100%; +} +*/ + +.MTitle { + font-variant: normal; +} + +.MLink { + font-style: normal; +} + +.CBody { +margin-left: 30px; +margin-right: 30px; +} + +p { + text-indent: 0; + margin-bottom: 1em; + } + +.CBody p { +/* + padding-top: 4px; + padding-bottom: 4px; +*/ +} + +#Menu { + margin-top: 94px; + border: 0px; +} + +body.ContentPage { + background-image: url('../../images/background.jpg'); + background-color: #818181; + background-position: left top; + background-repeat: repeat-x; +} + +.MGroup a:link, +.MGroup a:hover, +.MGroup a:visited { color: #bfbfbf; margin-right: 10px } +.MGroup a:active { color: #f58f07; margin-right: 10px } + + +.MEntry a:link, +.MEntry a:hover, +.MEntry a:visited { color: #bfbfbf; margin-right: 0 } +.MEntry a:active { color: #f58f07; margin-right: 0 } + +#Footer { + color: #bfbfbf; +} + +#Footer a:link, #Footer a:hover, #Footer a:visited { + color: #5c93f0; +} + +#MainTopic div.CTitle.logo { + color: #292929; + font-size: 0px; + font-style: normal; + font-weight: normal; + border-width: 0px; + padding: 0px; + margin: 0px; + background-position: left top; + background-repeat: no-repeat; + background-image: url('../../images/logo.jpg'); + background-color: #292929; + height: 94px; + position: relative; + +} + +#MainTopic h1.CTitle a { + display: none; +} + + +#MainTopic div.CBody p:first-child { + margin-top: 24px; +} + +.ContentPage #Content { + border: 0px; +/* height: 100%; */ +} + +#IPageLogo { + width: 780px; + color: #292929; + font-style: normal; + font-weight: normal; + border-width: 0px; + padding: 0px; + margin: 0px; + background-position: left top; + background-repeat: no-repeat; + background-image: url('../../images/logo.jpg'); + background-color: #292929; + height: 94px; + position: relative; + left: 27ex; +} + +#Menu, #IPageLogo { + font-size: 9pt; +} + +body.IndexPage { + background-image: url('../../images/background.jpg'); +} + +/*#IPageLogo:hover { + cursor: pointer; +}*/ + +.IPageTitle { + background-color:#FFFFF0; + color: #333333; + border: 0px; +} + + + +div.nav { + position:relative; + top: 70px; + text-align: right; +} + +a.nav span { + font-size: 11px; + position: relative; + bottom: 2px; +} + +a.nav:visited { + text-decoration: none; + border: 0px; + color: #aaaaaa; +} + +a.nav, a.nav:link { + border: 0px; + text-decoration: none; + font-family: Tahoma, "Helvetica Neue", "Trebuchet MS", Verdana, Arial, sans-serif; + font-size: 16px; + color: #aaaaaa; + margin-right: 11px; +} + +a.nav:hover { + text-decoration: none; + border: 0px; + color: #E0771C; +} + +a.nav:active { + text-decoration: none; + border: 0px; + color: #E0771C; +} + + diff --git a/phpgwapi/js/jquery/jqplot/docs/styles/main.css b/phpgwapi/js/jquery/jqplot/docs/styles/main.css new file mode 100644 index 0000000000..a672a94920 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/docs/styles/main.css @@ -0,0 +1,2 @@ +@import URL("1.css"); +@import URL("2.css"); diff --git a/phpgwapi/js/jquery/jqplot/examples/.htaccess b/phpgwapi/js/jquery/jqplot/examples/.htaccess new file mode 100644 index 0000000000..6a460be572 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/.htaccess @@ -0,0 +1,13 @@ +AddType application/x-httpd-php .php .html .htm + +##### +# Other methods that may work: +##### +# AddType application/x-httpd-php5 .php .html .htm + +# AddHandler php5-script .html + +# handler for phpsuexec.. +# +# SetHandler application/x-httpd-php5 +# \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/OHLC.html b/phpgwapi/js/jquery/jqplot/examples/OHLC.html new file mode 100644 index 0000000000..0e3e2c3f16 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/OHLC.html @@ -0,0 +1,331 @@ + + + + + + OHLC Charts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    
    +
    +
    
    +
    +
    
    +
    +
    
    +
    +
    
    +

    The examples below use the folowing code:

    +
    
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/OHLC2.html b/phpgwapi/js/jquery/jqplot/examples/OHLC2.html
    new file mode 100644
    index 0000000000..372a9bcfda
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/OHLC2.html
    @@ -0,0 +1,194 @@
    +
    +
    +
    +
    +  
    +  Open Hi Low Close and Canclestick Charts
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +
    +  
    +
    +
    +  
    +  
    +
    +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/ajax-loader.gif b/phpgwapi/js/jquery/jqplot/examples/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..3288d1035d70bb86517e2c233f1a904e41f06b29 GIT binary patch literal 3208 zcmc(iX;4#H9>pJdFE7h`I{IF)0|5<6L}(j=N}5%L009EB2nYfyF)E0PvIqo$u!IC; z4PgyY5|S9AEh38G)(9eq4TbH7_UHg@yWrlIJ$6smIADL7s^P;_O;ykRc9soXl`UC*LwQJXkii*0rx|*7rI2=x7WaRkx_~XZqFJ8R3c=2Kg zf@aSAv8+BJ8+^hyay>(QR@t*blbKzsf0}bscEqRc5Hd3o(-N5RyW=zWB*zQw6Zh>* z2CROCDAbu#D`)S|J_o(lL9Yn3l*+8RdiRD_>iNz$#_IAzCna&Wl5 zSF_(rRCDD!wi#i8oAm&jYtn2_@VB%2-H*G%bN#|(6R6N?wM)3u`PiGzwuX7qmTgyF zpE)h0kuoxQ9?=kW7Y!=R@DmhU9)vwT*EZWzJ zrt+=2tqFts72yIp?|gvdLhs8Hfku^Z(){gmN%Y=K#P|%fkvgUj~HfIp3CuXqCtYGtJ#me+n+-LmP( z*XNuk%!aH8bIE@_Bj46>M*dSro|7<6vZ7WUHh5YQzN$>IJFqCb|CT!wj~R2C2%=q{ zpt8rzY$aw?W?=Ustv{jo?Ow@ZRkLe<)NItY>Cyhle*wR59dTdF6(@{5^ zAQBOB*hNtc3bkY-8{Cm$nFS@elbTtSqrt7MB{h_4y+~`!mVa}?c&N>&?P}GqdMuhQ z&@TD5Czd((DcG_Su~dKKV)Pj$-qi1WHM8_vc^O4?^!oY|tmK~i!{fjd&@_1E(T~r7 z_REZy&hMT^ySJB3W7l$4YhR`M(J7S5S~+4Q&3HPa)z%zPpisOp$^ zTEe99ig2$5_qFr!$;7A6CJ}PJmRhli>w?LC}Y`#HLGy6 zMU4EhL~dKCN5Ut;U2jd*83ShBNiu zcJB0l9>1Modc?-oM<R4?}3g}UJ%@K);kriq>)e*rh%hdqM)5Q)*+O8 zXm;SEbs@koiYS!9YXIclSg+5m_s~yrW#kKMdiRszg(gCP5HPmP7L)vCf8@fxUh6qY z@Z#TmkjzAZX{rwE+q|K~F2v5{_@vt%>yT_a#fF03SFt{0RXvDAiaY~K9CgS1O>frXgAjBCS}mEd4mIWZ$=ovd5| zR?GRdU}d6+Q`+JRW)|=v7$)XNkn3yE`!nAiSCvOB1jKT zG<1aK3s<0b0m==egTD#8i(Of=1pGDTOCho0XpIOMQ&P87cVKY1W=C6kIg z9cH=@a&zbm2+`|{(_?YC9fdm?1TY~-pwlBn?>=(~1pDKbco6jloP;0-cqRiwV1A_S zEyV0Dj8Pwy!nekzaN>{)7rgZ&_QLxK{~1yRe865^yx>}+a!ECd>#MMwddow z@CU{l+Rt$xuXuf}?ga{3IAr?Raql^c@a%sI0U5m}HvJ5O1#I%_MMPt#BH>OqUZ{-k zt>4Xzz=%jT*FVW(uYkWyx}9Gw$HdN*qU?Bit#ji(Wi7p-u|_8?h^%szIS^s^fNM}b zgGy>|=cbEufpguY5_6w~&ZLv=Bo06UF9EYIY;Er-1VK)SyF&!|J{axiE1z^(hXwVq zsFS=K-#zC}CcOs^8W{KAt+kK)jYDgDYbCXv{{rwsgqtIU3<910$CJi)s?? z_t8k{>7*0~4l~LLF7$WXT5OSq5QCTbP_l!SN|{R}3D&eWA8~0ltWh1IL+ZBX4rRSt zWF6Om3WDMu4xK^1(BF`2cL}rUCzhHAB`@j5&R-yk_l*t;mPGY|u2^o|myvcOdrg0W z%=lX;f^Vkqfp?u7*4qQq%A3Mpf!xspWBSKS@O%r*TSM}?dl(@*%{0Jm_8;(h{R__M Bt + + + + + Filled (Area) Charts + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Area charts support highlighting and mouse events by default. The options and handlers and callbacks are essentially the same as with bar, pie, donut and funnel charts. One notable exception for area charts is that no data point index will be provided to the callback and the entire data set for the highlighted area will be returned. This is because the area is not associated with one particular data point, but with the entire data set of the series.

    + +
    Moused Over: Nothing
    + +
    + +

    For the chart below, mouseover has been disabled and click handling is enabled by setting "highlightMouseDown: true". For "fillToZero" area charts that have both negative and positive values as shown below, clicking in either the positive of negative regions will generate the same result.

    + +
    You Clicked: Nothing yet
    + +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/axisLabel.html b/phpgwapi/js/jquery/jqplot/examples/axisLabel.html new file mode 100644 index 0000000000..d3a921bae8 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/axisLabel.html @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/axisLabelsRotatedText.html b/phpgwapi/js/jquery/jqplot/examples/axisLabelsRotatedText.html new file mode 100644 index 0000000000..0596d36580 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/axisLabelsRotatedText.html @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/axisLabelsRotatedText2.html b/phpgwapi/js/jquery/jqplot/examples/axisLabelsRotatedText2.html new file mode 100644 index 0000000000..01ee915504 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/axisLabelsRotatedText2.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/axisScalingForceTicAt.html b/phpgwapi/js/jquery/jqplot/examples/axisScalingForceTicAt.html new file mode 100644 index 0000000000..e43f18692b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/axisScalingForceTicAt.html @@ -0,0 +1,219 @@ + + + + + + Random Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    
    +
    +
    
    +
    +
    
    +
    +
    
    +
    +
    
    +
    + + +
    + + +
    +
    + + +
    + +
    
    +
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/barLinePieStack.html b/phpgwapi/js/jquery/jqplot/examples/barLinePieStack.html
    new file mode 100644
    index 0000000000..6287ca7833
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/barLinePieStack.html
    @@ -0,0 +1,230 @@
    +
    +
    +
    +
    +  
    +  Multiple Chart types on same page
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +		
    +		
    +		
    +		
    +		
    +		
    +
    +  
    +  
    +  
    +  
    +  
    +   
    +    
    +  
    +  
    +  
    +
    +  
    +  
    +
    +    
    +
    +
    +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/barMissingValues.html b/phpgwapi/js/jquery/jqplot/examples/barMissingValues.html new file mode 100644 index 0000000000..54b05a4372 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/barMissingValues.html @@ -0,0 +1,63 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/barTest.html b/phpgwapi/js/jquery/jqplot/examples/barTest.html new file mode 100644 index 0000000000..889038689e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/barTest.html @@ -0,0 +1,307 @@ + + + + + + Bar Charts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    To create bar plots, you have to include the "jqplot.barRenderer.js" file in your source.

    + +

    Below is a default bar plot. Bars will highlight on mouseover. Events are triggered when you mouseover a bar and also when you click on a bar. Here We capture the 'jqplotDataClick' event and display the clicked series index, point index and data values. When series data is assigned as a 1-dimensional array as in this example, jqPlot automatically converts it into a 2-dimensional array for plotting. So a series defined as [2, 6, 7, 10] will become [[1,2], [2,6], [3,7], [4,10]].

    + +

    You Clicked: Nothing yet
    + +
    +
    
    +
    +    

    The plot target also fires a 'jqplotDataMouseOver' when the cursor is moused over a bar even if highlighting is turned off. This event will fire continuously as the user mouses over the bar. 'jqplotDataHighlight' fires only once when the user first passes over the bar. Additionally, a 'jqplotDataUnhighlight' event is fired when the user moves out of a bar (if highlighting is enabled).

    + +

    Moused Over: Nothing
    + +
    +
    
    +    
    +    
    Moused Over: Nothing
    +
    Clicked: Nothing
    + +
    +
    
    +    
    +    

    The next example has the plot's 'captureRightClick' option set to true. This causes the plot to fire a 'jqplotRightClick' event the the user clicks the right mouse button over a bar. Here, the 'highlightMouseDown' option is also set to true. This will highlight a slice on mouse down instead of on move over. Highlighting will occur for either left or right click.

    + +
    You Right Clicked: Nothing yet
    + +
    +
    
    +    
    +    
    +
    
    +    
    +    
    +
    
    +        
    +

    A pie chart is added to test for incompatibilities.

    +
    +
    
    +
    +

    The nex example shows the placement of point labels on negative bars. They shou be placed on the opposite position. That is, if it is placed 'north' to the positive bars, then it should be placed 'south' to the negative bars.

    +
    +
    
    +
    +
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/barTest2.html b/phpgwapi/js/jquery/jqplot/examples/barTest2.html
    new file mode 100644
    index 0000000000..b71cda394f
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/barTest2.html
    @@ -0,0 +1,103 @@
    +
    +
    +
    +
    +  
    +  
    +  Bar Charts
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +  
    +  
    +  
    +  
    +     
    +    
    +  
    +  
    +
    +        
    +    
    +
    
    +
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/bezierCurve.html b/phpgwapi/js/jquery/jqplot/examples/bezierCurve.html
    new file mode 100644
    index 0000000000..0e89295ff4
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/bezierCurve.html
    @@ -0,0 +1,96 @@
    +
    +
    +
    +
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +		
    +
    +
    +
    +
    +
    +

    The Bezier curve renderer can distinguish between two different input data formats. This first example has the data passed in as 2 data points, the second one defining the Bezier curve to the end point. With this format, non-default axes renderers will require specifying the minimum and maximum on the axes.

    +
    +    [[xstart, ystart], [cp1x, cp1y, cp2x, cp2y, xend, yend]];
    +
    +
    +

    This second example has the data broken out into 4 points, which will be assembled to define the Bezier Curve. With this format, any axes renderer can be used without explicitly specifying the minimum and maximum.

    +
    +    [[xstart, ystart], [cp1x, cp1y], [cp2x, cp2y], [xend, yend]];
    +
    +
    +

    Here is an example using a date axis renderer with Bezier curves. The data looks like:

    +
    +    [['01/01/2010', 6], ['02/01/2010', 9], ['03/01/2010', 8], ['04/01/2010', 3]]
    +
    + +
    + +

    Note that jqPlot converts the datetime strings into timestamps internally, so further explicit modification of the x value (date value) of series data points will have to be with integer time stamp data. So, you would do something like:

    + +
    +    plot3.series[2].data
    +    [[1262322000000, 6], [1265000400000, 9], [1267419600000, 8], [1270094400000, 3]]
    +    plot3.series[2].data[1][0] = 1265900400000
    +    plot3.drawSeries(2)
    +
    + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/blockPlot.html b/phpgwapi/js/jquery/jqplot/examples/blockPlot.html new file mode 100644 index 0000000000..daea4e85df --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/blockPlot.html @@ -0,0 +1,149 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + +

    Below is an example block plot. This plot also uses the Enhanced Legend Renderer plugin. Clicking on an item in the legend will toggle display of the appropriate series.

    +
    +

    Blocks can be moved by selecting the series, the point, and an optional duration parameter. If specified, duration will animate the movement. Duration is either a number in milliseconds, or the keywords 'fast' or 'slow'. Higher numbers will cause a slower animation.

    + Series: + Point: + Duration: + X: + Y: + + +

    This second chart is like the first except the "varyBlockColors" renderer option is set to true. This will vary the color of each block in a series separately. This allows displaying a third dimension to the data such as grouping beverage products by producer and by category such as "cola", "tea", "energy drink", etc.

    + +

    Also, the legend has it's "showSwathces" option set to false, since the blocks of each series will be of varying color and won't correspond to one swatch color. This still enables the user to show and hide the series by clicking on a label in the legend.

    + +
    + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/breakOnNull.html b/phpgwapi/js/jquery/jqplot/examples/breakOnNull.html new file mode 100644 index 0000000000..d77bce28d1 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/breakOnNull.html @@ -0,0 +1,51 @@ + + + + + + Break On Null Test + + + + + + + + + + + + + + + + + + + +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/bubbleChart2.html b/phpgwapi/js/jquery/jqplot/examples/bubbleChart2.html new file mode 100644 index 0000000000..38f021411b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/bubbleChart2.html @@ -0,0 +1,253 @@ + + + + + + Bubble Chart Examples + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Bubble charts represent 3 dimensional data. Data is passed in to a bubble chart as a series of [x, y, radius, <label or object>]. The optional fourth element of the data point can either be either a label string or an object having 'label' and/or 'color' properties to assign to the bubble.

    + +

    By default, all bubbles are scaled according to the size of the plot area. The radius value in the data point will be adjusted to fit the bubbles in the chart. If the "autoscaleBubbles" option is set to false, the radius value in the data will be taken as a literal pixel value for the radius of the points.

    + +

    The below chart show basic customization of bubble appearance with the "bubbleAlpha" and "highlightAlpha" options.

    + +
    +
    
    +
    +
    +
    +
    +    
    +    
    +
    CompanyR Value
    +
    
    +
    +

    Below is a basic bubble chart showing usage of the optional label and color properties passed in with the data.

    + +
    +
    
    +
    +

    The next chart uses the "bubbleGradients: true" option to specify gradient fills on the bubbles. Radial gradients are not supported in IE* and will be automatically disabled.

    + +
    + +

    *Radial gradients are not supported in IE because they are not supported in the excanvas emulation layer used by jqPlot to render charts in IE. jqPlot renders charts using the HTML canvas element which is supported by nearly every browser except IE. Excanvas translates the canvas rendering to VML rendering for IE, but unfortunately does not properly handle radial gradients.

    + +
    
    +
    +

    The following bubble chart shows the "autoscalePointsFactor" and "autoscaleMultiplier" options which can be used to control bubble scaling. The "autoscalePointsFactor" options controls bubble scaling with the number of points on the plot. A negative value will decrease bubble size and number of bubbles increases. The "autoscaleMultiplier" will makes all bubbles larger or smaller for values greater or less than 1.0.

    + +

    This chart also demonstrates some of the highlighting options. Bubble highlighting is controlled with the "highlightMouseOver" and "highlightMouseDown" boolean options. Here the "highlightMouseDown: true" option is set which causes the plot to highlight on mousedown (click). This automatically sets the "highlightMouseOver" option to false.

    + +

    Events are also trigger with plot interaction. Specifically, "jqplotDataHighlight", "jqplotDataUnhighlight", "jqplotDataClick" and "jqplotDataRightClick" events are triggered. Handlers are passed an event object, the series index, the point index, and the bubble data.

    + +
    +
    
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/bubblechart.html b/phpgwapi/js/jquery/jqplot/examples/bubblechart.html
    new file mode 100644
    index 0000000000..abb8f68aa9
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/bubblechart.html
    @@ -0,0 +1,69 @@
    +
    +
    +
    +
    +  
    +  Bubble Chart Test
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +
    +
    +  
    +  
    +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/candlestickCanvasOverlay.html b/phpgwapi/js/jquery/jqplot/examples/candlestickCanvasOverlay.html new file mode 100644 index 0000000000..20dec4cb30 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/candlestickCanvasOverlay.html @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/canvasOverlay.html b/phpgwapi/js/jquery/jqplot/examples/canvasOverlay.html new file mode 100644 index 0000000000..57689b9811 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/canvasOverlay.html @@ -0,0 +1,238 @@ + + + + + + + Bar Charts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    
    +
    +    
    +
    
    +
    +
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/catchError.html b/phpgwapi/js/jquery/jqplot/examples/catchError.html
    new file mode 100644
    index 0000000000..16303785ed
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/catchError.html
    @@ -0,0 +1,53 @@
    +
    +
    +
    +
    +  
    +  Simple Test
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +
    +
    +  
    +  
    +
    +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/categoryHorizontalBar.html b/phpgwapi/js/jquery/jqplot/examples/categoryHorizontalBar.html new file mode 100644 index 0000000000..353c924c7a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/categoryHorizontalBar.html @@ -0,0 +1,81 @@ + + + + + Test 3 + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/categoryVsLinearAxes.html b/phpgwapi/js/jquery/jqplot/examples/categoryVsLinearAxes.html new file mode 100644 index 0000000000..054ad54011 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/categoryVsLinearAxes.html @@ -0,0 +1,73 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/chartInTable.html b/phpgwapi/js/jquery/jqplot/examples/chartInTable.html new file mode 100644 index 0000000000..6e2021eb72 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/chartInTable.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + +
    +
    +
    + +
    + + diff --git a/phpgwapi/js/jquery/jqplot/examples/ciParser.html b/phpgwapi/js/jquery/jqplot/examples/ciParser.html new file mode 100644 index 0000000000..792be50455 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/ciParser.html @@ -0,0 +1,110 @@ + + + + + + Data Renderers, AJAX and JSON Data + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    JSON data formatted according the the City Index API spec can be read in directly by jqPlot thorugh the use of the dataRenderer option and a custom ciParser data renderer. The ciParser data renderer will translate either a JSON encoded string or JSON object.

    + +

    To use the the ciParser, include the jqplot.json2.js and jqplot.ciParser.js files. Specify the $.jqplot.ciParser as the renderer in the plot's "dataRenderer" option. The City Index JSON data can then be passed into the jqplot function as shown in the examples below:

    + +

    Here, a stringified JSON data objects is passed into the jqplot function.

    +
    +
    
    +

    This example uses the same City Index data format, but passes in a JSON object instead of a string.

    +
    +
    
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/customHighlighterCursorTrendline.html b/phpgwapi/js/jquery/jqplot/examples/customHighlighterCursorTrendline.html
    new file mode 100644
    index 0000000000..07a4f630e1
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/customHighlighterCursorTrendline.html
    @@ -0,0 +1,69 @@
    +
    +
    +
    +
    +  
    +  Simple Test
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +   
    +  
    +  
    +  
    +  
    +
    +  
    +  
    +
    +
    + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/customPieTests.html b/phpgwapi/js/jquery/jqplot/examples/customPieTests.html new file mode 100644 index 0000000000..6ea6974c42 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/customPieTests.html @@ -0,0 +1,72 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/dataLabels.html b/phpgwapi/js/jquery/jqplot/examples/dataLabels.html new file mode 100644 index 0000000000..9effc0edd4 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/dataLabels.html @@ -0,0 +1,190 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Data labels can be automatically added to pie chart and donut chart slices as well as funnel chart areas. what labels are displayed is controlled by the series "dataLabel" option. There are 4 types of data labels to display:

    +

      +
    • "label" - label of the point. +
    • "value" - value of the point. +
    • "percent" - percent of the whole (pie/donut/funnel) of the point. +
    • Array - custom array of data point labels, one for each point. +
    + +

    Formatting of labels is controlled through the series "dataLabelsFormatString" option. By default, the format string will be set based on the label type: +

      +
    • "label" - '%s', raw string. +
    • "value" - '%d', integer format. +
    • "percent" - '%d%%', integer with % sign appended. +
    • Array - '%s', raw string. +
    + +

    The following examples will clarify usage as well as other options. By default, data labels are turned off. They are enabled by setting the "showDataLabels: true" option. Below is the default configuration for a pie chart:

    + +
    + +
    
    + 
    +    

    Notice that no data label was shown for "Insignia". This is because the area of its slice is less than the "dataLabelThreshold" (3% by default). The threshold is applicable no matter what type of label we used. We can change the threshold and the format string for the label in the following example:

    + +

    + +
    
    +    
    +    

    Data labels function similarly for funnel and donut plots. Here is a funnel plot with the "dataLabels" option set to display the point label. Note that the label for "Insignia" is not displayed because Insignia represents less than 3% of the overall chart area, which is below the dataLabelThreshold:

    + +

    + +
    
    +    
    +    

    The last example shows usage of a custom dataLabels array. Again, labels for small sections will not be displayed unless the "dataLabelThreshold" is reduced (it is set to 3 percent by default).

    + +
    + +
    
    +    
    + 
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/dataRenderer.html b/phpgwapi/js/jquery/jqplot/examples/dataRenderer.html
    new file mode 100644
    index 0000000000..d3719d8c62
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/dataRenderer.html
    @@ -0,0 +1,178 @@
    +
    +
    +
    +
    +  
    +  Data Renderers, AJAX and JSON Data
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +  
    +
    +
    +
    +  
    +
    +
    +
    +
    +
    +  
    +
    +
    +  
    +  
    +
    +

    The "dataRenderer" plot options allows you to specify a data preprocessor for your plot. This enables jqPlot to accept data in any arbitrary format (e.g. AJAX data soruces, JSON strings, etc.). Below are some examples illustrating how to use dataRenderers.

    + +

    In this simple example, we create a dataRenderer which takes an array of x values and returns an array of [x, sin(x)] value pairs. Data renderers are passes the plot data and a reference to the plot as arguments.

    +
    +
    
    +

    An example of how to use a dataRenderer to fetch data from a server via an AJAX callback. Here the "data" passed into the plot is actually the url of the data source.

    +
    +
    
    +

    This example uses a more complicated dataRenderer that has been encapsulated as a jqplot plugin and loaded separately. This plugin accepts JSON data objects or strings formatted according to the City Index data format and returns jqPlot formatted data. This example uses a JSON encoded string.

    +
    +
    
    +

    This example uses the same City Index data format, but passes in a JSON object instead of a string.

    +
    +
    
    +
    +

    There is a third argument passed to the data renderer, dataRendererOptions. It was not used in these examples, but can be set as a separate option on the plot to pass additional arguments into the renderer if needed.

    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/dataTracking.html b/phpgwapi/js/jquery/jqplot/examples/dataTracking.html new file mode 100644 index 0000000000..09fe32d4ef --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/dataTracking.html @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/donutTest.html b/phpgwapi/js/jquery/jqplot/examples/donutTest.html new file mode 100644 index 0000000000..8cd0b7be38 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/donutTest.html @@ -0,0 +1,84 @@ + + + + + + Donut Chart Test + + + + + + + + + + + + + + + + + + + + + + +
    +

    To create donut plots, you have to include the "jqplot.donutRenderer.js" file in your source. You can view the javascript that generated these plots by clicking the "View Code" button below.

    + + +

    Below is a default donut plot. Slices will highlight on mouseover. Events are triggered when you mouseover a slice and also when you click on a slice. Here We capture the 'jqplotDataClick' event and display the clicked series index, point index and data values.

    + +

    You Clicked: Nothing yet
    + +
    + +

    Below is a customized donut plot with 2 series. Renderer options for sliceMargin, innerDiameter, and startAngle have been specified. Here We capture the 'jqplotDataHighlight' event and display the currently highlighted series index, point index and data values.

    + +

    The plot target also fires a 'jqplotDataMouseOver' when the cursor is moused over a slice even if highlighting is turned off. This event will fire continuously as the user mouses over the slice. 'jqplotDataHighlight' fires only once when the user first passes over the slice. Additionally, a 'jqplotDataUnhighlight' event is fired when the user moves out of a slice (if highlighting is enabled).

    + +

    Moused Over: Nothing
    + +
    + +

    The next example has the plot's 'captureRightClick' option set to true. This causes the plot to fire a 'jqplotRightClick' event the the user clicks the right mouse button over a slice. Note, click highlighting is the same for both right and left clicks, although separate events are triggered.

    + +

    You Right Clicked: Nothing yet
    + +
    + +

    The fourth example shows a plot with no sliceMargin and with the shadow turned on.

    + +
    + +

    The last example shows a donut with all of the default colors. Mouse over to see the default highlight colors. Series colors can be specified with the "seriesColors" option on the plot or on the series. The highlight colors are specified with the 'highlightColors' option on the series renderer.

    + +
    + +

    A simple line chart is added to test for imcompatabilities.

    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/donutTest.js b/phpgwapi/js/jquery/jqplot/examples/donutTest.js new file mode 100644 index 0000000000..58b421747c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/donutTest.js @@ -0,0 +1,96 @@ +$(document).ready(function(){ + + $.jqplot.config.enablePlugins = true; + + s1 = [['a',2], ['b',8], ['c',14], ['d',20]]; + s2 = [['a', 4], ['b', 12], ['c', 6], ['d', 3]]; + s3 = [['a', 2], ['b', 1], ['c', 3], ['d', 3]]; + s4 = [['a', 4], ['b', 3], ['c', 2], ['d', 1]]; + + s5 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]; + + plot1 = $.jqplot('chart1', [s1], { + seriesDefaults:{ + renderer:$.jqplot.DonutRenderer + }, + legend: {show:true} + }); + + plot2 = $.jqplot('chart2', [s1, s2], { + seriesDefaults: { + renderer:$.jqplot.DonutRenderer, + rendererOptions:{ + sliceMargin: 2, + innerDiameter: 110, + startAngle: -90 + } + } + }); + + plot3 = $.jqplot('chart3', [s1, s2, s3], { + captureRightClick: true, + seriesDefaults:{ + renderer:$.jqplot.DonutRenderer, + shadow: false, + rendererOptions:{ + innerDiameter: 110, + startAngle: -90, + sliceMargin: 2, + highlightMouseDown: true + } + }, + legend: { + show: true, + location: 'e', + placement: 'outside' + } + }); + + plot4 = $.jqplot('chart4', [s1, s2, s3, s4], { + seriesDefaults:{ + renderer:$.jqplot.DonutRenderer + }, + legend: { + show: true, + location: 's', + placement: 'outside', + rendererOptions:{ + numberRows: 1 + } + } + }); + + plot5 = $.jqplot('chart5', [s5], { + seriesDefaults:{ + renderer:$.jqplot.DonutRenderer + } + }); + + plot6 = $.jqplot('chart6', [[1,2,3,4]]); + + $('#chart1').bind('jqplotDataClick', + function (ev, seriesIndex, pointIndex, data) { + $('#info1').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $('#chart2').bind('jqplotDataHighlight', + function (ev, seriesIndex, pointIndex, data) { + $('#info2').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $('#chart2').bind('jqplotDataUnhighlight', + function (ev) { + $('#info2').html('Nothing'); + } + ); + + $('#chart3').bind('jqplotDataRightClick', + function (ev, seriesIndex, pointIndex, data) { + $('#info3').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $(document).unload(function() {$('*').unbind(); }); +}); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/donutTest2.html b/phpgwapi/js/jquery/jqplot/examples/donutTest2.html new file mode 100644 index 0000000000..a671d6041e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/donutTest2.html @@ -0,0 +1,58 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + + +

    +
    +
    
    +  
    +
    \ No newline at end of file
    diff --git a/phpgwapi/js/jquery/jqplot/examples/dynamicplot.html b/phpgwapi/js/jquery/jqplot/examples/dynamicplot.html
    new file mode 100644
    index 0000000000..6d8f4aee6b
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/dynamicplot.html
    @@ -0,0 +1,347 @@
    +
    +
    +
    +
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +
    +
    +
    +  
    +  
    +
    +
    + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/example.js b/phpgwapi/js/jquery/jqplot/examples/example.js new file mode 100644 index 0000000000..779bc7b815 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/example.js @@ -0,0 +1,12 @@ +$(document).ready(function(){ + $('script.code').each(function(index) { + if ($('pre.code').eq(index).length ) { + $('pre.code').eq(index).text($(this).html()); + } + else { + var str = $(this).html(); + $('div.jqplot-target').eq(index).after($('
    '+str+'
    ')); + } + }); + $(document).unload(function() {$('*').unbind(); }); +}); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/examples.css b/phpgwapi/js/jquery/jqplot/examples/examples.css new file mode 100644 index 0000000000..09e8cf83d4 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/examples.css @@ -0,0 +1,34 @@ +body { + margin:20px; + font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; +} + +div.nav { + margin-bottom:10px; +} + +pre.code-block{ + background: #D8F4DC; + border: 1px solid rgb(200, 200, 200); + padding-top: 1em; + padding-left: 3em; + padding-bottom: 1em; + margin-top: 1em; + margin-bottom: 3em; + +} + +pre.code { + background: #D8F4DC; + border: 1px solid rgb(200, 200, 200); + padding-top: 1em; + padding-left: 3em; + padding-bottom: 1em; + margin-top: 1em; + margin-bottom: 4em; + +} + +p { + margin: 2em 0; +} \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/fillToZero.html b/phpgwapi/js/jquery/jqplot/examples/fillToZero.html new file mode 100644 index 0000000000..48762fb00f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/fillToZero.html @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/filledLine.html b/phpgwapi/js/jquery/jqplot/examples/filledLine.html new file mode 100644 index 0000000000..3ea0fca8bf --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/filledLine.html @@ -0,0 +1,77 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/filledLineCategoryAxis.html b/phpgwapi/js/jquery/jqplot/examples/filledLineCategoryAxis.html new file mode 100644 index 0000000000..0d6267125d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/filledLineCategoryAxis.html @@ -0,0 +1,79 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/funnelTest.html b/phpgwapi/js/jquery/jqplot/examples/funnelTest.html new file mode 100644 index 0000000000..a0402e609d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/funnelTest.html @@ -0,0 +1,77 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + +
    +

    To create donut plots, you have to include the "jqplot.funnelRenderer.js" file in your source. You can view the javascript that generated these plots by clicking the "View Code" button below.

    + + +

    Below is a default funnel plot. Sections will highlight on mouseover. Events are triggered when you mouseover a section and also when you click on a section. Here We capture the 'jqplotDataClick' event and display the clicked series index, point index and data values.

    + +

    You Clicked: Nothing yet
    + +
    + +

    Below is a customized funnel plot. Renderer options for sectionMargin and widthRatio have been set. Here We capture the 'jqplotDataHighlight' event and display the currently highlighted series index, point index and data values.

    + +

    The plot target also fires a 'jqplotDataMouseOver' when the cursor is moused over a slice even if highlighting is turned off. This event will fire continuously as the user mouses over the slice. 'jqplotDataHighlight' fires only once when the user first passes over the slice. Additionally, a 'jqplotDataUnhighlight' event is fired when the user moves out of a slice (if highlighting is enabled).

    + +

    Moused Over: Nothing
    + +
    + +

    The next example has the plot's 'captureRightClick' option set to true. This causes the plot to fire a 'jqplotRightClick' event the the user clicks the right mouse button over a slice. Note, click highlighting is the same for both right and left clicks, although separate events are triggered. Here the series 'highlightMouseDown' option is set to true to highlight sections when a mouse down event occurs on them. This automatically disables highlighting on mouseover.

    + +

    You Right Clicked: Nothing yet
    + +
    + +

    A small chart to test for plugin compatabiity.

    +
    + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/funnelTest.js b/phpgwapi/js/jquery/jqplot/examples/funnelTest.js new file mode 100644 index 0000000000..f45235efed --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/funnelTest.js @@ -0,0 +1,74 @@ +$(document).ready(function(){ + + s1 = [['Sony',7], ['Samsumg',13], ['LG',14], ['Vizio',5]]; + s2 = [['a', 4], ['b', 12], ['c', 6], ['d', 3]]; + s3 = [['a', 2], ['b', 1], ['c', 3], ['d', 3]]; + s4 = [['a', 4], ['b', 3], ['c', 2], ['d', 1]]; + + s5 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]; + + plot1 = $.jqplot('chart1', [s1], { + seriesDefaults:{ + renderer:$.jqplot.FunnelRenderer + } + }); + + plot2 = $.jqplot('chart2', [s1], { + seriesDefaults:{ + renderer:$.jqplot.FunnelRenderer, + rendererOptions: { + widthRatio: 0.5, + sectionMargin: 0 + } + }, + legend: { + show:true, + location: 'e' + } + }); + + plot3 = $.jqplot('chart3', [s1], { + captureRightClick: true, + seriesDefaults:{ + renderer:$.jqplot.FunnelRenderer, + rendererOptions: { + widthRatio: 0.2, + sectionMargin: 0, + highlightMouseDown: true + } + }, + legend: { + show:true, + location: 'e', + placement: 'outside' + } + }); + + plot4 = $.jqplot('chart4', [[1,2,3,4]]); + + $('#chart1').bind('jqplotDataClick', + function (ev, seriesIndex, pointIndex, data) { + $('#info1').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $('#chart2').bind('jqplotDataHighlight', + function (ev, seriesIndex, pointIndex, data) { + $('#info2').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $('#chart2').bind('jqplotDataUnhighlight', + function (ev) { + $('#info2').html('Nothing'); + } + ); + + $('#chart3').bind('jqplotDataRightClick', + function (ev, seriesIndex, pointIndex, data) { + $('#info3').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $(document).unload(function() {$('*').unbind(); }); +}); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/gridCustomization.html b/phpgwapi/js/jquery/jqplot/examples/gridCustomization.html new file mode 100644 index 0000000000..0cf80fd376 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/gridCustomization.html @@ -0,0 +1,55 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/gridPadding.html b/phpgwapi/js/jquery/jqplot/examples/gridPadding.html new file mode 100644 index 0000000000..d9c7ead026 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/gridPadding.html @@ -0,0 +1,93 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Setting custom gridPadding on charts. The red border indicates the plot target container. By default, the grid will size itself to fit axes, titles, etc. within the plot target. This values will be overridden if a "gridPadding" option is specified.

    +

    The default computed gridPadding:

    +
    +
    
    +

    Setting all gridPadding to 0 hides the title under the plot:

    +
    +
    
    +

    If a gridPadding member is null or undefined, the default will be used:

    +
    +
    
    +

    Just specify padding on the sides we need, defaults used for others:

    +
    +
    
    +  
    +
    diff --git a/phpgwapi/js/jquery/jqplot/examples/hiddenPlot.html b/phpgwapi/js/jquery/jqplot/examples/hiddenPlot.html
    new file mode 100644
    index 0000000000..3c7ee98414
    --- /dev/null
    +++ b/phpgwapi/js/jquery/jqplot/examples/hiddenPlot.html
    @@ -0,0 +1,215 @@
    +
    +
    +
    +
    +  
    +  Plots in Hidden Containers
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +  	
    +  
    +
    +  
    +  
    +  
    +  
    +
    +    
    +

    This page demonstrates using plots within containers that are initially hidden. Examples are shown for jQuery UI tabs and Accordions

    +
    + +
    +

    Tab 2 and tab 3 contain plots which are initially hidden. Using a combination of alternate sizing specification and the plots "replot" method the plots are properly displayed when their containers are shown.

    +

    The alternate sizing specifications for setting plot height and width are needed because a hidden element (or child of a hidden element) has no size. The first example in tab 2 uses custom "data-height" and "data-width" attributes on the plot target element to specify height. The second example uses "width" and "height" properties specified on the options object passed into the $.jqplot() function.

    + +

    The default size is 300px wide by 400px high. The default setting can be overriden by specifying different values to the $.jqplot.config.defaultHeight and $.jqplot.config.defaultWidth properties. Height and width values are taken in this order of prececence:

    + +
      +
    1. The css properties if available and plot is not hidden with display:none.
    2. +
    3. Options object passed into the $.jqplot() function.
    4. +
    5. Custom data-height and data-width attributes on the plot target.
    6. +
    7. The config defaults.
    8. +
    + +

    Here is how the replot method can be used to bind to the "tabsshow" event of the UI tabs:

    + +
    +    $('#tabs').bind('tabsshow', function(event, ui) {
    +      if (ui.index == 1) {
    +        plot1.replot();
    +      }
    +      else if (ui.index == 2) {
    +        plot2.replot();
    +      }
    +    });
    +
    + +

    The ui.index property is the index of the tab that was shown.

    +
    + +
    +

    This plot was in an initially hidden container. It's hieght and width are set by the "data-height" and "data-width" properties of the plot container.

    +
    +
    + +
    +

    This plot is in an initially hidden container. It's height and width are set by the 'height' and 'width' properties of the options object passed into the plot constructor.

    +
    +
    + +
    + +
    + +

    Section 1

    +
    +

    Secion 2 contains a plot. Sizing plots in hidden accordion sections is very similar to sizing in a tab widget. Because of the default animation on accordions, however, the plot will not draw itself until the entire accordion panel is shown.

    + +

    Binidng to the accordion "accordionchange" event is also similar as with tabs:

    + +
    +    $('#accordion').bind('accordionchange', function(event, ui) {
    +      var index = $(this).find("h3").index ( ui.newHeader[0] );
    +      if (index == 1) {
    +        plot3.replot();
    +      }
    +    });
    +    
    +
    + +

    Section 2

    +
    +

    + This plot also has it's height and width set with the data-height and data-width attributes. Note, if you want the accordian widget to properly size itself before the plot is shown, you must also specify a css height and width on the plot target. +

    +
    +
    + +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/highlighter.html b/phpgwapi/js/jquery/jqplot/examples/highlighter.html new file mode 100644 index 0000000000..2258ca7f08 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/highlighter.html @@ -0,0 +1,94 @@ + + + + + + Highlighter Test + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/highlighter2.html b/phpgwapi/js/jquery/jqplot/examples/highlighter2.html new file mode 100644 index 0000000000..174b00c81d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/highlighter2.html @@ -0,0 +1,62 @@ + + + + + + Highlighter Test + + + + + + + + + + + + + + + + + + +

    This page demonstrates creating your own custom highlighter by attaching a callback to the 'jqplotMouseMove' event.

    +
    + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/highlighter3.html b/phpgwapi/js/jquery/jqplot/examples/highlighter3.html new file mode 100644 index 0000000000..806b5dc517 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/highlighter3.html @@ -0,0 +1,94 @@ + + + + + + Highlighter Test + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/horizontalLine.html b/phpgwapi/js/jquery/jqplot/examples/horizontalLine.html new file mode 100644 index 0000000000..c828b206f2 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/horizontalLine.html @@ -0,0 +1,50 @@ + + + + + + Horizontal Line (const. y values) + + + + + + + + + + + + + + + + + + +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/intticks.html b/phpgwapi/js/jquery/jqplot/examples/intticks.html new file mode 100644 index 0000000000..ae5a6cfb6f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/intticks.html @@ -0,0 +1,178 @@ + + + + + + Enhanced Tick Algorithm + + + + + + + + + + + + + + + + + + + + + +

    Tests of enhancements to axis tick generation algorithm. Axis now checks to see if the tick interval (delta between ticks) is less than the precision of the tick format string. If it is, it will try to increase the tick interval, number of ticks or change the axis minimum or maximum so that it is at least as great as the tick label precision.

    + +

    Note, if the user has specified the axis tickInterval, numberTicks, min or max options, the algorithm may not be able to produce the desired ticks.

    + +

    This helps in situations where the user wants to display ticks formatted as integer values on a plot with a very small range. For example, a plot with a y axis range from 0 to 2 and 6 ticks will have a tickInterval of 0.4 and ticks like [0, 0.4, 0.8, 1.2, 1.6, 2]. When formatted as integers, the plot displays ticks like [0, 0, 1, 1, 2, 2]. The new algorithm will try to adjust the number of ticks or the axis minimum or maximum to generate ticks like [0, 1, 2].

    + +
    +
    +
    +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png new file mode 100644 index 0000000000000000000000000000000000000000..954e22dbd99e8c6dd7091335599abf2d10bf8003 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEr#)R9Ln2z=UU%d=WFXS=@V?HT z#xG*`>Yvsgk=}99w^d^D^d*@m74oMo<%#FcopJf?u00-~YVKV2wzrI*_R6;UORMea zBFVSEnN~eiVA6V&z`E)YLz5Aok^D)In}Yn=OzDpgR5Wv0XfT8pOkmV{sKAJ-PO9#T zZK}IXj&Q-V!U)!LcB_3K0&C*{ literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png new file mode 100644 index 0000000000000000000000000000000000000000..64ece5707d91a6edf9fad4bfcce0c4dbcafcf58d GIT binary patch literal 251 zcmVbvPcjKS|RKP(6sDcCAB(_QB%0978a<$Ah$!b|E zwn;|HO0i8cQj@~)s!ajF0S002ovPDHLkV1oEp BYH0uf literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..abdc01082bf3534eafecc5819d28c9574d44ea89 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQY-ImG zFPf9b{J;c_6SHRK%WcbN_hZpM=(Ry;4Rxv2@@2Y=$K57eF$X$=!PC{xWt~$(69B)$ BI)4BF literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..9b383f4d2eab09c0f2a739d6b232c32934bc620b GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour1U*q978O6-yYw{%b*}|_(02F z@qbE9)0CJMo;*v*PWv`Vh2h6EmG8IS-Cm{3U~` zFlmZ}YMcJY=eo?o%*@I?2`NblNeMudl#t?{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png new file mode 100644 index 0000000000000000000000000000000000000000..39d5824d6af5456f1e89fc7847ea3599ea5fd815 GIT binary patch literal 3762 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 literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..f1273672d253263b7564e9e21d69d7d9d0b337d9 GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l%l7LV~E7mxPQ=F85a&M@g_{ d|GeK{$Y5lo%PMu^>wln`44$rjF6*2UngE4^EGqy2 literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_222222_256x240.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..b273ff111d219c9b9a8b96d57683d0075fb7871a GIT binary patch literal 4369 zcmd^?`8O2)_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmPmYTG^FX}c% zlGE{DS1Q;~I7-6ze&TN@+F-xsI6sd%SwK#*O5K|pDRZqEy< zJg0Nd8F@!OxqElm`~U#piM22@u@8B<moyKE%ct`B(jysxK+1m?G)UyIFs1t0}L zemGR&?jGaM1YQblj?v&@0iXS#fi-VbR9zLEnHLP?xQ|=%Ihrc7^yPWR!tW$yH!zrw z#I2}_!JnT^(qk)VgJr`NGdPtT^dmQIZc%=6nTAyJDXk+^3}wUOilJuwq>s=T_!9V) zr1)DT6VQ2~rgd@!Jlrte3}}m~j}juCS`J4(d-5+e-3@EzzTJNCE2z)w(kJ90z*QE) zBtnV@4mM>jTrZZ*$01SnGov0&=A-JrX5Ge%Pce1Vj}=5YQqBD^W@n4KmFxxpFK`uH zP;(xKV+6VJ2|g+?_Lct7`uElL<&jzGS8Gfva2+=8A@#V+xsAj9|Dkg)vL5yhX@~B= zN2KZSAUD%QH`x>H+@Ou(D1~Pyv#0nc&$!1kI?IO01yw3jD0@80qvc?T*Nr8?-%rC8 z@5$|WY?Hqp`ixmEkzeJTz_`_wsSRi1%Zivd`#+T{Aib6-rf$}M8sz6v zb6ERbr-SniO2wbOv!M4)nb}6UVzoVZEh5kQWh_5x4rYy3c!871NeaM(_p=4(kbS6U#x<*k8Wg^KHs2ttCz<+pBxQ$Z zQMv;kVm5_fF_vH`Mzrq$Y&6u?j6~ftIV0Yg)Nw7JysIN_ z-_n*K_v1c&D}-1{NbBwS2h#m1y0a5RiEcYil+58$8IDh49bPnzE7R8In6P%V{2IZU z7#clr=V4yyrRe@oXNqbqo^^LvlLE?%8XaI&N(Np90-psU}7kqmbWk zZ;YBwJNnNs$~d!mx9oMGyT( znaBoj0d}gpQ^aRr?6nW)$4god*`@Uh2e+YpS@0(Mw{|z|6ko3NbTvDiCu3YO+)egL z>uW(^ahKFj>iJ-JF!^KhKQyPTznJa;xyHYwxJgr16&Wid_9)-%*mEwo{B_|M9t@S1 zf@T@q?b2Qgl!~_(Roe;fdK)y|XG0;ls;ZbT)w-aOVttk#daQcY7$cpY496H*`m@+L zeP#$&yRbBjFWv}B)|5-1v=(66M_;V1SWv6MHnO}}1=vby&9l+gaP?|pXwp0AFDe#L z&MRJ^*qX6wgxhA_`*o=LGZ>G_NTX%AKHPz4bO^R72ZYK}ale3lffDgM8H!Wrw{B7A z{?c_|dh2J*y8b04c37OmqUw;#;G<* z@nz@dV`;7&^$)e!B}cd5tl0{g(Q>5_7H^@bEJi7;fQ4B$NGZerH#Ae1#8WDTH`iB&) zC6Et3BYY#mcJxh&)b2C^{aLq~psFN)Q1SucCaBaBUr%5PYX{~-q{KGEh)*;n;?75k z=hq%i^I}rd;z-#YyI`8-OfMpWz5kgJE3I!3ean6=UZi!BxG7i(YBk? z02HM7wS0)Wni{dWbQMRtd-A)_Az!t>F;IwWf~!*)-Az4}yryNkz&9)w>ElA80Oc`6 zHo#9H!Y3*Qx9n@Jn)!w6G^hb;e_n8zpIyXCN`JFkPc)^Q?2MsLNFhMgrcZI-<#1ne zjH;KFf?4eAT9mQZ}ZfHLGA#d%s;SZK4p0FwZT2S^{ zQ2BG1xJsbK6?yrHTjJi|5C0u=!|r!?*4FL%y%3q#(d+e>b_2I9!*iI!30}42Ia0bq zUf`Z?LGSEvtz8s``Tg5o_CP(FbR0X$FlE0yCnB7suDPmI2=yOg^*2#cY9o`X z;NY-3VBHZjnVcGS){GZ98{e+lq~O$u6pEcgd0CrnIsWffN1MbCZDH<7c^hv+Z0Ucf0{w zSzi^qKuUHD9Dgp0EAGg@@$zr32dQx>N=ws`MESEsmzgT2&L;?MSTo&ky&!-JR3g~1 zPGTt515X)wr+Bx(G9lWd;@Y3^Vl}50Wb&6-Tiy;HPS0drF`rC}qYq22K4)G#AoD0X zYw$E+Bz@Zr^50MAwu@$?%f9$r4WHH?*2|67&FXFhXBrVFGmg)6?h3^-1?t;UzH0*I zNVf9wQLNLnG2@q>6CGm>&y|lC`iCFfYd}9i%+xkl^5oBJ?<;aneCfcHqJh7Yl5uLS z9Fx-(kMdcNyZejXh22N{mCw_rX1O!cOE&3>e(ZH81PR95wQC37En4O{w;{3q9n1t&;p)D%&Z%Nw$gSPa!nz8Slh7=ko2am)XARwOWw zpsz0~K!s{(dM$NB=(A=kkp>T(*yU6<_dwIx>cH4+LWl282hXa6-EUq>R3t?G2623< z*RwTN%-fgBmD{fu*ejNn)1@KG?Sg*8z3hYtkQJQjB6 zQ|x>wA=o$=O)+nLmgTXW3_6diA;b4EY{*i*R%6dO2EMg z@6g?M3rpbnfB@hOdUeb96=~I?OIA3@BWAGmTwiQ{x5Cqq<8c10L!P zd@Qk^BseTX%$Q7^s}5n%HB|)gKx}H$d8Sb$bBnq9-AglT2dGR2(+I;_fL|R4p$odJ zllfb0NqI)7=^z~qAm1V{(PkpxXsQ#4*NH9yYZ`Vf@)?#ueGgtCmGGY|9U#v|hRdg- zQ%0#cGIfXCd{Y)JB~qykO;KPvHu|5Ck&(Hn%DF~cct@}j+87xhs2ew;fLm5#2+mb| z8{9e*YI(u|gt|{x1G+U=DA3y)9s2w7@cvQ($ZJIA)x$e~5_3LKFV~ASci8W}jF&VeJoPDUy(BB>ExJpck;%;!`0AAo zAcHgcnT8%OX&UW_n|%{2B|<6Wp2MMGvd5`T2KKv;ltt_~H+w00x6+SlAD`{K4!9zx z*1?EpQ%Lwiik){3n{-+YNrT;fH_niD_Ng9|58@m8RsKFVF!6pk@qxa{BH-&8tsim0 zdAQ(GyC^9ane7_KW*#^vMIoeQdpJqmPp%%px3GIftbwESu#+vPyI*YTuJ6+4`z{s? zpkv~0x4c_PFH`-tqafw5)>4AuQ78SkZ!$8}INLK;Egr;2tS18hEO5=t;QDmZ-qu?I zG+=DN`nR72Xto{{bJp||`k}-2G;5#xg8E~xgz22)^_Z;=K|4@(E&5J)SY2of=olcw z5)@L)_Ntcm!*5nEy0M9v0`S33;pO4TN;>4(Z+19p_0>u#e-vE zXCU(6gAvu~I7Cw(xd%0e59MNLw^U37ZDbsBrj%eDCexw8a3G`nTcXVNL6{B7Hj@i& zbVB{;ApEtHk76q08DJ48dSxd$C(;$K6=FpU<~l9pVoT9arW^Vu{%Bcn4`eIpkOVC| z$)AKYG_`ypM{0@BUb3^9lqi_c?ONH|4UJMJWDowMVjacycX7}9g={O7swOB+{;+?; zjBo!9?+nd)ie#x5IbFW-zBOo0c4q@9wGVt5;pNt`=-~Zgcw#*`m($6ibxtZ`H=e=} zF#GZ~5$%AUn};8U#tRem0J(JTR}d4vR(dgK2ML~lZsPhayJ2h1%sD4FVst| zKF)+@`iNzLRjg4=K8@**0=5cE>%?FDc({I^+g9USk<8$&^qD~@%W0i4b|yMG*p4`N zh}I!ltTRI8Ex$+@V{02Br%xq#O?UlhO{r8WsaZnZCZq0MK9%AXU%MDLT;3=0A9(BV z9VxxxJd7jo$hw3q;3o?yBLmA=azBUrd9>-<_ANs0n3?-Ic*6&ytb@H~?0E(*d>T5n z-HiH2jsDf6uWhID%#n>SzOqrFCPDfUcu5QPd?<(=w6pv1BE#nsxS{n!UnC9qAha1< z;3cpZ9A-e$+Y)%b;w@!!YRA9p%Kf9IHGGg^{+p`mh;q8i7}&e@V3EQaMsItEMS&=X plT@$;k0WcB_jb;cn%_Idz4HO$QU*abf4}+wi?e96N>fbq{{i|W0@(ln literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_228ef1_256x240.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_228ef1_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..c357355aa7bb9201f3d40b8996449ffa1035dd6a GIT binary patch literal 5355 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 Y^OOM2(oM+v|NSx_Y8qC-Ajq!3AfU8Dx90^_ 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 literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_ffd27a_256x240.png b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/images/ui-icons_ffd27a_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..e117effa3dca24e7978cfc5f8b967f661e81044f GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/jquery-ui-1.8.6.custom.css b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/jquery-ui-1.8.6.custom.css new file mode 100644 index 0000000000..dc60200616 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/css/ui-lightness/jquery-ui-1.8.6.custom.css @@ -0,0 +1,572 @@ +/* + * jQuery UI CSS Framework 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* 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%; } + + +/* + * jQuery UI CSS Framework 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; } +.ui-widget-content a { color: #333333; } +.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } +.ui-widget-header a { color: #ffffff; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; } +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* 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_ffffff_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_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-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.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; border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); } +.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/* + * jQuery UI Resizable 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.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: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; 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;}/* + * jQuery UI Selectable 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/* + * jQuery UI Accordion 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.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 .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 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; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; }/* + * jQuery UI Autocomplete 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* + * jQuery UI Button 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/* + * jQuery UI Dialog 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } +.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 { position: relative; 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 .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* + * jQuery UI Slider 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.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; background-position: 0 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; }/* + * jQuery UI Tabs 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.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 { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* + * jQuery UI Datepicker 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.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 { 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 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*/ +}/* + * jQuery UI Progressbar 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/js/jquery-ui-1.8.1.custom.min.js b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/js/jquery-ui-1.8.1.custom.min.js new file mode 100644 index 0000000000..9ea846d658 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/js/jquery-ui-1.8.1.custom.min.js @@ -0,0 +1,756 @@ +/*! + * jQuery UI 1.8.1 + * + * Copyright (c) 2010 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(c){c.ui={version:"1.8.1",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a=0)&&c(a).is(":focusable")}})}(jQuery); +;/*! + * jQuery UI Widget 1.8.1 + * + * Copyright (c) 2010 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/Widget + */ +(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype= +b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g= +b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create(); +this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f, +h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a= +b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery); +;/*! + * jQuery UI Mouse 1.8.1 + * + * Copyright (c) 2010 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/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&& +this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault(); +return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&& +this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX- +a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); +;/* + * jQuery UI Position 1.8.1 + * + * Copyright (c) 2010 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/Position + */ +(function(c){c.ui=c.ui||{};var m=/left|center|right/,n=/top|center|bottom/,p=c.fn.position,q=c.fn.offset;c.fn.position=function(a){if(!a||!a.of)return p.apply(this,arguments);a=c.extend({},a);var b=c(a.of),d=(a.collision||"flip").split(" "),e=a.offset?a.offset.split(" "):[0,0],g,h,i;if(a.of.nodeType===9){g=b.width();h=b.height();i={top:0,left:0}}else if(a.of.scrollTo&&a.of.document){g=b.width();h=b.height();i={top:b.scrollTop(),left:b.scrollLeft()}}else if(a.of.preventDefault){a.at="left top";g=h= +0;i={top:a.of.pageY,left:a.of.pageX}}else{g=b.outerWidth();h=b.outerHeight();i=b.offset()}c.each(["my","at"],function(){var f=(a[this]||"").split(" ");if(f.length===1)f=m.test(f[0])?f.concat(["center"]):n.test(f[0])?["center"].concat(f):["center","center"];f[0]=m.test(f[0])?f[0]:"center";f[1]=n.test(f[1])?f[1]:"center";a[this]=f});if(d.length===1)d[1]=d[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(a.at[0]==="right")i.left+=g;else if(a.at[0]==="center")i.left+= +g/2;if(a.at[1]==="bottom")i.top+=h;else if(a.at[1]==="center")i.top+=h/2;i.left+=e[0];i.top+=e[1];return this.each(function(){var f=c(this),k=f.outerWidth(),l=f.outerHeight(),j=c.extend({},i);if(a.my[0]==="right")j.left-=k;else if(a.my[0]==="center")j.left-=k/2;if(a.my[1]==="bottom")j.top-=l;else if(a.my[1]==="center")j.top-=l/2;j.left=parseInt(j.left);j.top=parseInt(j.top);c.each(["left","top"],function(o,r){c.ui.position[d[o]]&&c.ui.position[d[o]][r](j,{targetWidth:g,targetHeight:h,elemWidth:k, +elemHeight:l,offset:e,my:a.my,at:a.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(j,{using:a.using}))})};c.ui.position={fit:{left:function(a,b){var d=c(window);b=a.left+b.elemWidth-d.width()-d.scrollLeft();a.left=b>0?a.left-b:Math.max(0,a.left)},top:function(a,b){var d=c(window);b=a.top+b.elemHeight-d.height()-d.scrollTop();a.top=b>0?a.top-b:Math.max(0,a.top)}},flip:{left:function(a,b){if(b.at[0]!=="center"){var d=c(window);d=a.left+b.elemWidth-d.width()-d.scrollLeft();var e=b.my[0]==="left"? +-b.elemWidth:b.my[0]==="right"?b.elemWidth:0,g=-2*b.offset[0];a.left+=a.left<0?e+b.targetWidth+g:d>0?e-b.targetWidth+g:0}},top:function(a,b){if(b.at[1]!=="center"){var d=c(window);d=a.top+b.elemHeight-d.height()-d.scrollTop();var e=b.my[1]==="top"?-b.elemHeight:b.my[1]==="bottom"?b.elemHeight:0,g=b.at[1]==="top"?b.targetHeight:-b.targetHeight,h=-2*b.offset[1];a.top+=a.top<0?e+b.targetHeight+h:d>0?e+g+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(a,b){if(/static/.test(c.curCSS(a,"position")))a.style.position= +"relative";var d=c(a),e=d.offset(),g=parseInt(c.curCSS(a,"top",true),10)||0,h=parseInt(c.curCSS(a,"left",true),10)||0;e={top:b.top-e.top+g,left:b.left-e.left+h};"using"in b?b.using.call(a,e):d.css(e)};c.fn.offset=function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(){c.offset.setOffset(this,a)});return q.call(this)}}})(jQuery); +;/* + * jQuery UI Draggable 1.8.1 + * + * Copyright (c) 2010 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/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== +"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= +this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top- +this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions(); +d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.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";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element, +b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this== +a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]|| +0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], +this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top- +(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment== +"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&& +a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"), +10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], +this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft(): +f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.leftthis.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?e:!(e-this.offset.click.left').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options; +if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!= +"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e=j&&f<=l||h>=j&&h<=l||fl)&&(e>=i&& +e<=k||g>=i&&g<=k||ek);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), +top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= +this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!d(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", +nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var e=0;e');/sw|se|ne|nw/.test(g)&&f.css({zIndex:++a.zIndex});"se"==g&&f.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[g]=".ui-resizable-"+g;this.element.append(f)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== +String)this.handles[i]=d(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=d(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}d(this.handles[i])}};this._renderAxis(this.element);this._handles=d(".ui-resizable-handle",this.element).disableSelection(); +this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();d(this.element).addClass("ui-resizable-autohide").hover(function(){d(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){d(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){d(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()}; +if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(d(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(), +e=this.element;this.resizing=true;this.documentScroll={top:d(document).scrollTop(),left:d(document).scrollLeft()};if(e.is(".ui-draggable")||/absolute/.test(e.css("position")))e.css({position:"absolute",top:c.top,left:c.left});d.browser.opera&&/relative/.test(e.css("position"))&&e.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var g=m(this.helper.css("top"));if(a.containment){c+=d(a.containment).scrollLeft()||0;g+=d(a.containment).scrollTop()||0}this.offset= +this.helper.offset();this.position={left:c,top:g};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:c,top:g};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio: +this.originalSize.width/this.originalSize.height||1;a=d(".ui-resizable-"+this.axis).css("cursor");d("body").css("cursor",a=="auto"?this.axis+"-resize":a);e.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,e=this._change[this.axis];if(!e)return false;c=e.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize", +b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var e=this._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName);e=g&&d.ui.hasScroll(e[0],"left")?0:c.sizeDiff.height; +g={width:c.size.width-(g?0:c.sizeDiff.width),height:c.size.height-e};e=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var f=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(d.extend(g,{top:f,left:e}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}d("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop", +b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(k(b.left))this.position.left=b.left;if(k(b.top))this.position.top=b.top;if(k(b.height))this.size.height=b.height;if(k(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,e=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(e=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(e=="nw"){b.top= +a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,e=k(b.width)&&a.maxWidth&&a.maxWidthb.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(f)b.width=a.minWidth;if(h)b.height=a.minHeight;if(e)b.width=a.maxWidth;if(g)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height, +l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(f&&l)b.left=i-a.minWidth;if(e&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(g&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a');var a=d.browser.msie&&d.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+ +a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return d.extend(this._change.n.apply(this, +arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return d.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){d.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});d.extend(d.ui.resizable, +{version:"1.8.1"});d.ui.plugin.add("resizable","alsoResize",{start:function(){var b=d(this).data("resizable").options,a=function(c){d(c).each(function(){d(this).data("resizable-alsoresize",{width:parseInt(d(this).width(),10),height:parseInt(d(this).height(),10),left:parseInt(d(this).css("left"),10),top:parseInt(d(this).css("top"),10)})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else d.each(b.alsoResize,function(c){a(c)}); +else a(b.alsoResize)},resize:function(){var b=d(this).data("resizable"),a=b.options,c=b.originalSize,e=b.originalPosition,g={height:b.size.height-c.height||0,width:b.size.width-c.width||0,top:b.position.top-e.top||0,left:b.position.left-e.left||0},f=function(h,i){d(h).each(function(){var j=d(this),l=d(this).data("resizable-alsoresize"),p={};d.each((i&&i.length?i:["width","height","top","left"])||["width","height","top","left"],function(n,o){if((n=(l[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(/relative/.test(j.css("position"))&& +d.browser.opera){b._revertToRelativePosition=true;j.css({position:"absolute",top:"auto",left:"auto"})}j.css(p)})};typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?d.each(a.alsoResize,function(h,i){f(h,i)}):f(a.alsoResize)},stop:function(){var b=d(this).data("resizable");if(b._revertToRelativePosition&&d.browser.opera){b._revertToRelativePosition=false;el.css({position:"relative"})}d(this).removeData("resizable-alsoresize-start")}});d.ui.plugin.add("resizable","animate",{stop:function(b){var a= +d(this).data("resizable"),c=a.options,e=a._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName),f=g&&d.ui.hasScroll(e[0],"left")?0:a.sizeDiff.height;g={width:a.size.width-(g?0:a.sizeDiff.width),height:a.size.height-f};f=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(d.extend(g,h&&f?{top:h,left:f}:{}),{duration:c.animateDuration,easing:c.animateEasing, +step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};e&&e.length&&d(e[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});d.ui.plugin.add("resizable","containment",{start:function(){var b=d(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof d?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement= +d(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:d(document),left:0,top:0,width:d(document).width(),height:d(document).height()||document.body.parentNode.scrollHeight}}else{var e=d(a),g=[];d(["Top","Right","Left","Bottom"]).each(function(i,j){g[i]=m(e.css("padding"+j))});b.containerOffset=e.offset();b.containerPosition=e.position();b.containerSize={height:e.innerHeight()-g[3],width:e.innerWidth()-g[1]};c=b.containerOffset; +var f=b.containerSize.height,h=b.containerSize.width;h=d.ui.hasScroll(a,"left")?a.scrollWidth:h;f=d.ui.hasScroll(a)?a.scrollHeight:f;b.parentData={element:a,left:c.left,top:c.top,width:h,height:f}}}},resize:function(b){var a=d(this).data("resizable"),c=a.options,e=a.containerOffset,g=a.position;b=a._aspectRatio||b.shiftKey;var f={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))f=e;if(g.left<(a._helper?e.left:0)){a.size.width+=a._helper?a.position.left-e.left: +a.position.left-f.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?e.left:0}if(g.top<(a._helper?e.top:0)){a.size.height+=a._helper?a.position.top-e.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?e.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-f.left:a.offset.left-f.left)+a.sizeDiff.width);e=Math.abs((a._helper?a.offset.top-f.top:a.offset.top- +e.top)+a.sizeDiff.height);g=a.containerElement.get(0)==a.element.parent().get(0);f=/relative|absolute/.test(a.containerElement.css("position"));if(g&&f)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(e+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-e;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=d(this).data("resizable"),a=b.options,c=b.containerOffset,e=b.containerPosition, +g=b.containerElement,f=d(b.helper),h=f.offset(),i=f.outerWidth()-b.sizeDiff.width;f=f.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f});b._helper&&!a.animate&&/static/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f})}});d.ui.plugin.add("resizable","ghost",{start:function(){var b=d(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25, +display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=d(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=d(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});d.ui.plugin.add("resizable","grid",{resize:function(){var b= +d(this).data("resizable"),a=b.options,c=b.size,e=b.originalSize,g=b.originalPosition,f=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-e.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-e.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a}else if(/^(ne)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}else{if(/^(sw)$/.test(f)){b.size.width=e.width+h;b.size.height= +e.height+a}else{b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}b.position.left=g.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery); +;/* + * jQuery UI Selectable 1.8.1 + * + * Copyright (c) 2010 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/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var d=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(d.options.filter,d.element[0]);f.each(function(){var c=e(this),b=c.offset();e.data(this,"selectable-item",{element:this,$element:c,left:b.left,top:b.top,right:b.left+c.outerWidth(),bottom:b.top+c.outerHeight(),startselected:false,selected:c.hasClass("ui-selected"), +selecting:c.hasClass("ui-selecting"),unselecting:c.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e(document.createElement("div")).css({border:"1px dotted black"}).addClass("ui-selectable-helper")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this}, +_mouseStart:function(d){var f=this;this.opos=[d.pageX,d.pageY];if(!this.options.disabled){var c=this.options;this.selectees=e(c.filter,this.element[0]);this._trigger("start",d);e(c.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:d.clientX,top:d.clientY,width:0,height:0});c.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!d.metaKey){b.$element.removeClass("ui-selected"); +b.selected=false;b.$element.addClass("ui-unselecting");b.unselecting=true;f._trigger("unselecting",d,{unselecting:b.element})}});e(d.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){b.$element.removeClass("ui-unselecting").addClass("ui-selecting");b.unselecting=false;b.selecting=true;b.selected=true;f._trigger("selecting",d,{selecting:b.element});return false}})}},_mouseDrag:function(d){var f=this;this.dragged=true;if(!this.options.disabled){var c=this.options, +b=this.opos[0],g=this.opos[1],h=d.pageX,i=d.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(c.tolerance=="touch")k=!(a.left>h||a.righti||a.bottomb&&a.rightg&&a.bottom *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable"); +this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(self, +arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem= +c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset, +{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment(); +if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start", +a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute"); +if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a, +c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]== +document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate", +null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem): +d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c}, +_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")},_getDragHorizontalDirection:function(){var a= +this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)? +h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"), +b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)? +i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement, +c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height= +this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()- +parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0], +this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b= +1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update", +g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity", +this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},_create:function(){var a=this.options,b=this;this.running=0;this.element.addClass("ui-accordion ui-widget ui-helper-reset"); +this.element[0].nodeName=="UL"&&this.element.children("li").addClass("ui-accordion-li-fix");this.headers=this.element.find(a.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c(this).removeClass("ui-state-focus")}); +this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");if(a.navigation){var d=this.element.find("a").filter(a.navigationFilter);if(d.length){var f=d.closest(".ui-accordion-header");this.active=f.length?f:d.closest(".ui-accordion-content").prev()}}this.active=this._findActive(this.active||a.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active"); +this._createIcons();this.resize();this.element.attr("role","tablist");this.headers.attr("role","tab").bind("keydown",function(g){return b._keydown(g)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();this.active.length?this.active.attr("aria-expanded","true").attr("tabIndex","0"):this.headers.eq(0).attr("tabIndex","0");c.browser.safari||this.headers.find("a").attr("tabIndex","-1");a.event&&this.headers.bind(a.event+ +".accordion",function(g){b._clickHandler.call(b,g,this);g.preventDefault()})},_createIcons:function(){var a=this.options;if(a.icons){c("").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion"); +this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(a.autoHeight||a.fillHeight)b.css("height", +"");return this},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();b&&this._createIcons()}},_keydown:function(a){var b=c.ui.keyCode;if(!(this.options.disabled||a.altKey||a.ctrlKey)){var d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target}, +a.target);a.preventDefault()}if(g){c(a.target).attr("tabIndex","-1");c(g).attr("tabIndex","0");g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0, +b-c(this).innerHeight()+c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a=="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d= +this.options;if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]==this.active[0];d.active=d.collapsible&&b?false:c(".ui-accordion-header",this.element).index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected); +a.next().addClass("ui-accordion-content-active")}e=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):e,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(e,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); +this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},e=this.active=c([]);this._toggle(e,f,g)}},_toggle:function(a,b,d,f,g){var e=this.options,k=this;this.toShow=a;this.toHide=b;this.data=d;var i=function(){if(k)return k._completed.apply(k,arguments)};this._trigger("changestart",null,this.data);this.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]), +toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var h=e.duration,j=e.animated;if(j&&!f[j]&&!c.easing[j])j="slide";f[j]||(f[j]=function(l){this.slide(l,{easing:j, +duration:h||700})});f[j](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}i(true)}b.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();a.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(a){var b=this.options;this.running=a?0:--this.running;if(!this.running){b.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion, +{version:"1.8.1",animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},e={},k;b=a.toShow;k=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(i,h){e[h]="hide";i=(""+c.css(a.toShow[0], +h)).match(/^([\d+-.]+)(.*)$/);g[h]={value:i[1],unit:i[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(e,{step:function(i,h){if(h.prop=="height")f=h.end-h.start===0?0:(h.now-h.start)/(h.end-h.start);a.toShow[0].style[h.prop]=f*g[h.prop].value+g[h.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css("width",k);a.toShow.css({overflow:d});a.complete()}})}else a.toHide.animate({height:"hide"}, +a);else a.toShow.animate({height:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); +;/* + * jQuery UI Autocomplete 1.8.1 + * + * Copyright (c) 2010 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/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function(e){e.widget("ui.autocomplete",{options:{minLength:1,delay:300},_create:function(){var a=this,b=this.element[0].ownerDocument;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){var d=e.ui.keyCode;switch(c.keyCode){case d.PAGE_UP:a._move("previousPage",c);break;case d.PAGE_DOWN:a._move("nextPage",c);break;case d.UP:a._move("previous",c);c.preventDefault(); +break;case d.DOWN:a._move("next",c);c.preventDefault();break;case d.ENTER:a.menu.active&&c.preventDefault();case d.TAB:if(!a.menu.active)return;a.menu.select(c);break;case d.ESCAPE:a.element.val(a.term);a.close(c);break;case d.LEFT:case d.RIGHT:case d.SHIFT:case d.CONTROL:case d.ALT:break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){a.search(null,c)},a.options.delay);break}}).bind("focus.autocomplete",function(){a.selectedItem=null;a.previous=a.element.val()}).bind("blur.autocomplete", +function(c){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("
      ").addClass("ui-autocomplete").appendTo("body",b).menu({focus:function(c,d){d=d.item.data("item.autocomplete");false!==a._trigger("focus",null,{item:d})&&/^key/.test(c.originalEvent.type)&&a.element.val(d.value)},selected:function(c,d){d=d.item.data("item.autocomplete");false!==a._trigger("select", +c,{item:d})&&a.element.val(d.value);a.close(c);c=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=c}a.selectedItem=d},blur:function(){a.menu.element.is(":visible")&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup"); +this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource()},_initSource:function(){var a,b;if(e.isArray(this.options.source)){a=this.options.source;this.source=function(c,d){d(e.ui.autocomplete.filter(a,c.term))}}else if(typeof this.options.source==="string"){b=this.options.source;this.source=function(c,d){e.getJSON(b,c,d)}}else this.source=this.options.source},search:function(a,b){a= +a!=null?a:this.element.val();if(a.length").data("item.autocomplete",b).append("
      "+b.label+"").appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&& +/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")},filter:function(a,b){var c=new RegExp(e.ui.autocomplete.escapeRegex(b),"i");return e.grep(a,function(d){return c.test(d.label||d.value||d)})}})})(jQuery); +(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(b){if(e(b.target).closest(".ui-menu-item a").length){b.preventDefault();a.select(b)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", +-1).mouseenter(function(b){a.activate(b,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var c=b.offset().top-this.element.offset().top,d=this.element.attr("scrollTop"),f=this.element.height();if(c<0)this.element.attr("scrollTop",d+c);else c>f&&this.element.attr("scrollTop",d+c-f+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:b})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); +this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prev().length},last:function(){return this.active&&!this.active.next().length},move:function(a,b,c){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);a.length?this.activate(c,a):this.activate(c,this.element.children(b))}else this.activate(c,this.element.children(b))},nextPage:function(a){if(this.hasScroll())if(!this.active|| +this.last())this.activate(a,this.element.children(":first"));else{var b=this.active.offset().top,c=this.element.height(),d=this.element.children("li").filter(function(){var f=e(this).offset().top-b-c+e(this).height();return f<10&&f>-10});d.length||(d=this.element.children(":last"));this.activate(a,d)}else this.activate(a,this.element.children(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(":last")); +else{var b=this.active.offset().top,c=this.element.height();result=this.element.children("li").filter(function(){var d=e(this).offset().top-b+c-e(this).height();return d<10&&d>-10});result.length||(result=this.element.children(":first"));this.activate(a,result)}else this.activate(a,this.element.children(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(), +d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":""));d.primary&&b.prepend("");d.secondary&&b.append("");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon");this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}}); +a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset");this._init()},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()}, +destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery); +;/* + * jQuery UI Dialog 1.8.1 + * + * Copyright (c) 2010 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: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function(c){c.widget("ui.dialog",{options:{autoOpen:true,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:1E3},_create:function(){this.originalTitle=this.element.attr("title");var a=this,b=a.options,d=b.title||a.originalTitle||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
      ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ +b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
      ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), +h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", +e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); +a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== +b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index", +c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;d.next().length&&d.appendTo("body");a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== +f[0]&&e.shiftKey){g.focus(1);return false}}});c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();a._trigger("open");a._isOpen=true;return a}},_createButtons:function(a){var b=this,d=false,e=c("
      ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a, +function(g,f){g=c('').text(g).click(function(){f.apply(b.element[0],arguments)}).appendTo(e);c.fn.button&&g.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging"); +b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition,originalSize:f.originalSize,position:f.position,size:f.size}}a=a===undefined?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position"); +a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize",f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop", +f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0];a=a||c.ui.dialog.prototype.options.position;if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(e,g){if(+b[e]===b[e]){d[e]=b[e];b[e]= +g}})}else if(typeof a==="object"){if("left"in a){b[0]="left";d[0]=a.left}else if("right"in a){b[0]="right";d[0]=-a.right}if("top"in a){b[1]="top";d[1]=a.top}else if("bottom"in a){b[1]="bottom";d[1]=-a.bottom}}(a=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position({my:b.join(" "),at:b.join(" "),offset:d.join(" "),of:window,collision:"fit",using:function(e){var g=c(this).css(e).offset().top;g<0&&c(this).css("top",e.top-g)}});a||this.uiDialog.hide()},_setOption:function(a, +b){var d=this,e=d.uiDialog,g=e.is(":data(resizable)"),f=false;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");break;case "draggable":b?d._makeDraggable():e.draggable("destroy");break; +case "height":f=true;break;case "maxHeight":g&&e.resizable("option","maxHeight",b);f=true;break;case "maxWidth":g&&e.resizable("option","maxWidth",b);f=true;break;case "minHeight":g&&e.resizable("option","minHeight",b);f=true;break;case "minWidth":g&&e.resizable("option","minWidth",b);f=true;break;case "position":d._position(b);break;case "resizable":g&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title", +d.uiDialogTitlebar).html(""+(b||" "));break;case "width":f=true;break}c.Widget.prototype._setOption.apply(d,arguments);f&&d._size()},_size:function(){var a=this.options,b;this.element.css({width:"auto",minHeight:0,height:0});b=this.uiDialog.css({height:"auto",width:a.width}).height();this.element.css(a.height==="auto"?{minHeight:Math.max(a.minHeight-b,0),height:"auto"}:{minHeight:0,height:Math.max(a.height-b,0)}).show();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight", +this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.1",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&& +c(document).bind(c.ui.dialog.overlay.events,function(d){return c(d.target).zIndex()>=c.ui.dialog.overlay.maxZ})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("
      ").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&& +b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight, +document.body.offsetHeight);return a");if(!a.values)a.values=[this._valueMin(),this._valueMin()];if(a.values.length&&a.values.length!==2)a.values=[a.values[0],a.values[0]]}else this.range=d("
      ");this.range.appendTo(this.element).addClass("ui-slider-range");if(a.range==="min"||a.range==="max")this.range.addClass("ui-slider-range-"+a.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("").appendTo(this.element).addClass("ui-slider-handle"); +if(a.values&&a.values.length)for(;d(".ui-slider-handle",this.element).length").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){a.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(a.disabled)d(this).blur(); +else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),g,h,i;if(!b.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e= +false;if(!b._keySliding){b._keySliding=true;d(this).addClass("ui-state-active");g=b._start(c,f);if(g===false)return}break}i=b.options.step;g=b.options.values&&b.options.values.length?(h=b.values(f)):(h=b.value());switch(c.keyCode){case d.ui.keyCode.HOME:h=b._valueMin();break;case d.ui.keyCode.END:h=b._valueMax();break;case d.ui.keyCode.PAGE_UP:h=g+(b._valueMax()-b._valueMin())/5;break;case d.ui.keyCode.PAGE_DOWN:h=g-(b._valueMax()-b._valueMin())/5;break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(g=== +b._valueMax())return;h=g+i;break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(g===b._valueMin())return;h=g-i;break}b._slide(c,f,h);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(b._keySliding){b._keySliding=false;b._stop(c,e);b._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"); +this._mouseDestroy();return this},_mouseCapture:function(b){var a=this.options,c,e,f,g,h,i;if(a.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c={x:b.pageX,y:b.pageY};e=this._normValueFromMouse(c);f=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(j){var k=Math.abs(e-h.values(j));if(f>k){f=k;g=d(this);i=j}});if(a.range===true&&this.values(1)===a.min){i+=1;g=d(this.handles[i])}if(this._start(b, +i)===false)return false;this._mouseSliding=true;h._handleIndex=i;g.addClass("ui-state-active").focus();a=g.offset();this._clickOffset=!d(b.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:b.pageX-a.left-g.width()/2,top:b.pageY-a.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)};e=this._normValueFromMouse(c);this._slide(b,i,e);return this._animateOff=true},_mouseStart:function(){return true}, +_mouseDrag:function(b){var a=this._normValueFromMouse({x:b.pageX,y:b.pageY});this._slide(b,this._handleIndex,a);return false},_mouseStop:function(b){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(b,this._handleIndex);this._change(b,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(b){var a; +if(this.orientation==="horizontal"){a=this.elementSize.width;b=b.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{a=this.elementSize.height;b=b.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}a=b/a;if(a>1)a=1;if(a<0)a=0;if(this.orientation==="vertical")a=1-a;b=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+a*b)},_start:function(b,a){var c={handle:this.handles[a],value:this.value()};if(this.options.values&&this.options.values.length){c.value= +this.values(a);c.values=this.values()}return this._trigger("start",b,c)},_slide:function(b,a,c){var e;if(this.options.values&&this.options.values.length){e=this.values(a?0:1);if(this.options.values.length===2&&this.options.range===true&&(a===0&&c>e||a===1&&c1){this.options.values[b]=this._trimAlignValue(a);this._refreshValue();this._change(null,b)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;fthis._valueMax())return this._valueMax();var a=this.options.step,c=b%a;b=b-c;if(c>=a/2)b+=a;return parseFloat(b.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,a=this.options,c=this, +e=!this._animateOff?a.animate:false,f,g={},h,i,j,k;if(this.options.values&&this.options.values.length)this.handles.each(function(l){f=(c.values(l)-c._valueMin())/(c._valueMax()-c._valueMin())*100;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](g,a.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(l===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},a.animate);if(l===1)c.range[e?"animate":"css"]({width:f-h+"%"},{queue:false,duration:a.animate})}else{if(l=== +0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},a.animate);if(l===1)c.range[e?"animate":"css"]({height:f-h+"%"},{queue:false,duration:a.animate})}h=f});else{i=this.value();j=this._valueMin();k=this._valueMax();f=k!==j?(i-j)/(k-j)*100:0;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](g,a.animate);if(b==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},a.animate);if(b==="max"&&this.orientation==="horizontal")this.range[e? +"animate":"css"]({width:100-f+"%"},{queue:false,duration:a.animate});if(b==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},a.animate);if(b==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:a.animate})}}});d.extend(d.ui.slider,{version:"1.8.1"})})(jQuery); +;/* + * jQuery UI Tabs 1.8.1 + * + * Copyright (c) 2010 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/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(d){var s=0,u=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
      ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:'
    • #{label}
    • '},_create:function(){this._tabify(true)},_setOption:function(c,e){if(c=="selected")this.options.collapsible&&e==this.options.selected|| +this.select(e);else{this.options[c]=e;this._tabify()}},_tabId:function(c){return c.title&&c.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+ ++s},_sanitizeSelector:function(c){return c.replace(/:/g,"\\:")},_cookie:function(){var c=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++u);return d.cookie.apply(null,[c].concat(d.makeArray(arguments)))},_ui:function(c,e){return{tab:c,panel:e,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var c= +d(this);c.html(c.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function e(g,f){g.css({display:""});!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}this.list=this.element.find("ol,ul").eq(0);this.lis=d("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);var a=this,b=this.options,h=/^#.+/;this.anchors.each(function(g,f){var j=d(f).attr("href"),l=j.split("#")[0],p;if(l&&(l===location.toString().split("#")[0]|| +(p=d("base")[0])&&l===p.href)){j=f.hash;f.href=j}if(h.test(j))a.panels=a.panels.add(a._sanitizeSelector(j));else if(j!="#"){d.data(f,"href.tabs",j);d.data(f,"load.tabs",j.replace(/#.*$/,""));j=a._tabId(f);f.href="#"+j;f=d("#"+j);if(!f.length){f=d(b.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else b.disabled.push(g)});if(c){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); +this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(b.selected===undefined){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){b.selected=g;return false}});if(typeof b.selected!="number"&&b.cookie)b.selected=parseInt(a._cookie(),10);if(typeof b.selected!="number"&&this.lis.filter(".ui-tabs-selected").length)b.selected= +this.lis.index(this.lis.filter(".ui-tabs-selected"));b.selected=b.selected||(this.lis.length?0:-1)}else if(b.selected===null)b.selected=-1;b.selected=b.selected>=0&&this.anchors[b.selected]||b.selected<0?b.selected:0;b.disabled=d.unique(b.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(b.selected,b.disabled)!=-1&&b.disabled.splice(d.inArray(b.selected,b.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); +if(b.selected>=0&&this.anchors.length){this.panels.eq(b.selected).removeClass("ui-tabs-hide");this.lis.eq(b.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[b.selected],a.panels[b.selected]))});this.load(b.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else b.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));this.element[b.collapsible?"addClass": +"removeClass"]("ui-tabs-collapsible");b.cookie&&this._cookie(b.selected,b.cookie);c=0;for(var i;i=this.lis[c];c++)d(i)[d.inArray(c,b.disabled)!=-1&&!d(i).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");b.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(b.event!="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+g)};this.lis.bind("mouseover.tabs", +function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(b.fx)if(d.isArray(b.fx)){m=b.fx[0];o=b.fx[1]}else m=o=b.fx;var q=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",function(){e(f,o);a._trigger("show", +null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},r=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")};this.anchors.bind(b.event+".tabs", +function(){var g=this,f=d(this).closest("li"),j=a.panels.filter(":not(.ui-tabs-hide)"),l=d(a._sanitizeSelector(this.hash));if(f.hasClass("ui-tabs-selected")&&!b.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}b.selected=a.anchors.index(this);a.abort();if(b.collapsible)if(f.hasClass("ui-tabs-selected")){b.selected=-1;b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){r(g, +j)}).dequeue("tabs");this.blur();return false}else if(!j.length){b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this));this.blur();return false}b.cookie&&a._cookie(b.selected,b.cookie);if(l.length){j.length&&a.element.queue("tabs",function(){r(g,j)});a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";d.browser.msie&&this.blur()});this.anchors.bind("click.tabs", +function(){return false})},destroy:function(){var c=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e=d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(b,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this, +"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});c.cookie&&this._cookie(null,c.cookie);return this},add:function(c,e,a){if(a===undefined)a=this.anchors.length;var b=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,e));c=!c.indexOf("#")?c.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs", +true);var i=d("#"+c);i.length||(i=d(h.panelTemplate).attr("id",c).data("destroy.tabs",true));i.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);i.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]);i.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");i.removeClass("ui-tabs-hide"); +this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(c){var e=this.options,a=this.lis.eq(c).remove(),b=this.panels.eq(c).remove();if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(c+(c+1=c?--h:h});this._tabify();this._trigger("remove", +null,this._ui(a.find("a")[0],b[0]));return this},enable:function(c){var e=this.options;if(d.inArray(c,e.disabled)!=-1){this.lis.eq(c).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=c});this._trigger("enable",null,this._ui(this.anchors[c],this.panels[c]));return this}},disable:function(c){var e=this.options;if(c!=e.selected){this.lis.eq(c).addClass("ui-state-disabled");e.disabled.push(c);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}return this}, +select:function(c){if(typeof c=="string")c=this.anchors.index(this.anchors.filter("[href$="+c+"]"));else if(c===null)c=-1;if(c==-1&&this.options.collapsible)c=this.options.selected;this.anchors.eq(c).trigger(this.options.event+".tabs");return this},load:function(c){var e=this,a=this.options,b=this.anchors.eq(c)[0],h=d.data(b,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(b,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(c).addClass("ui-state-processing"); +if(a.spinner){var i=d("span",b);i.data("label.tabs",i.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(b.hash)).html(k);e._cleanup();a.cache&&d.data(b,"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.error(k,n,c,b)}catch(m){}}}));e.element.dequeue("tabs");return this}}, +abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(c,e){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.1"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(c,e){var a=this,b=this.options,h=a._rotate||(a._rotate= +function(i){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=b.selected;a.select(++k')}function E(a,b){d.extend(a, +b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.1"}});var y=(new Date).getTime();d.extend(J.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]= +f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id)a.id="dp"+ ++this.uuid;var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('
      ')}}, +_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&& +b.append.remove();if(c){b.append=d(''+c+"");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('').addClass(this._triggerClass).html(f== +""?c:d("").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;gh){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a, +c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b), +true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){a="dp"+ ++this.uuid;this._dialogInput=d('');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor==Date? +this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]); +d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}}, +_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b= +d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false; +for(var b=0;b-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target|| +a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a); +d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&& +d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f, +h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover"); +this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover"); +this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"); +a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(), +k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"]; +a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val(): +"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&& +!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth; +b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){a=this._getInst(d(a)[0]); +a.input&&a._selectingMonthYear&&!d.browser.msie&&a.input.focus();a._selectingMonthYear=!a._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a, +"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")|| +this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null; +for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c, +k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",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",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c? +c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+112?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear|| +a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay? +new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&nn;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a)); +n=this._canAdjustMonth(a,-1,m,g)?''+n+"":f?"":''+n+"";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m, +g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?''+r+"":f?"":''+r+"";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&& +a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'":"";e=e?'
      '+(c?h:"")+(this._isInRange(a,r)?'":"")+(c?"":h)+"
      ":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),G=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var K=this._getDefaultDate(a),H="",C=0;C1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='
      '+(/all|left/.test(t)&&C==0?c? +f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'
      ';var A=k?'":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="=5?' class="ui-datepicker-week-end"':"")+'>'+s[q]+""}x+=A+"";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, +A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var N=0;N";var O=!k?"":'";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,I=B&&!G||!F[0]||j&&qo;O+='";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=O+""}g++;if(g>11){g=0;m++}x+="
      '+this._get(a,"weekHeader")+"
      '+this._get(a,"calculateWeek")(q)+""+(B&&!w?" ":I?''+q.getDate()+ +"":''+q.getDate()+"")+"
      "+(l?""+(i[0]>0&&D==i[1]-1?'
      ':""):"");L+=x}H+=L}H+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'': +"");a._keyEvent=false;return H},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='
      ',o="";if(h||!k)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(j+=o+(h||!(k&&l)?" ":""));if(h||!l)j+=''+c+"";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b, +i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?" ":"")+o;j+="
      ";return j},_adjustInstDate:function(a,b,c){var e= +a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a, +"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a); +c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a, +"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker= +function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b)); +return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new J;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.1";window["DP_jQuery_"+y]=d})(jQuery); +;/* + * jQuery UI Progressbar 1.8.1 + * + * Copyright (c) 2010 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/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(b){b.widget("ui.progressbar",{options:{value:0},_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=b("
      ").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); +this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===undefined)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){switch(a){case "value":this.options.value=c;this._refreshValue();this._trigger("change");break}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;if(athis._valueMax())a=this._valueMax();return a}, +_valueMin:function(){return 0},_valueMax:function(){return 100},_refreshValue:function(){var a=this.value();this.valueDiv[a===this._valueMax()?"addClass":"removeClass"]("ui-corner-right").width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.1"})})(jQuery); +;/* + * jQuery UI Effects 1.8.1 + * + * Copyright (c) 2010 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/Effects/ + */ +jQuery.effects||function(f){function k(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], +16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return l.transparent;return l[f.trim(c).toLowerCase()]}function q(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return k(b)}function m(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, +a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function n(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in r||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function s(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function j(c,a,b,d){if(typeof c=="object"){d= +a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(f.isFunction(b)){d=b;b=null}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=q(b.elem,a);b.end=k(b.end);b.colorInit= +true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var l={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],transparent:[255,255,255]},o=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=n(m.call(this)),p,t=e.attr("className");f.each(o,function(u, +i){c[i]&&e[i+"Class"](c[i])});p=n(m.call(this));e.attr("className",t);e.animate(s(h,p),a,b,function(){f.each(o,function(u,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a? +f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===undefined?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.1",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"}); +c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=j.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c|| +typeof c=="number"||f.fx.speeds[c])return this._show.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c])return this._hide.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||typeof c=="boolean"||f.isFunction(c))return this.__toggle.apply(this, +arguments);else{var a=j.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c, +a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+ +b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2, +10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)* +a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ +e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); +;/* + * jQuery UI Effects Fold 1.8.1 + * + * Copyright (c) 2010 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/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100* +f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); +;/* + * jQuery UI Effects Highlight 1.8.1 + * + * Copyright (c) 2010 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/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& +this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Pulsate 1.8.1 + * + * Copyright (c) 2010 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/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); +b.dequeue()})})}})(jQuery); +; \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/jquery-ui/js/jquery-ui-1.8.6.custom.min.js b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/js/jquery-ui-1.8.6.custom.min.js new file mode 100644 index 0000000000..312c019945 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/jquery-ui/js/jquery-ui-1.8.6.custom.min.js @@ -0,0 +1,778 @@ +/*! + * jQuery UI 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.6",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,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,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this, +"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position"); +if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f, +"border"+this+"Width",true))||0;if(m)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h, +d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");if("area"===b){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&k(a)}return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b?a.href||!isNaN(d):!isNaN(d))&&k(a)},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}}); +c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&& +this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX- +a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); +;/* + * jQuery UI Position 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Position + */ +(function(c){c.ui=c.ui||{};var n=/left|center|right/,o=/top|center|bottom/,t=c.fn.position,u=c.fn.offset;c.fn.position=function(b){if(!b||!b.of)return t.apply(this,arguments);b=c.extend({},b);var a=c(b.of),d=a[0],g=(b.collision||"flip").split(" "),e=b.offset?b.offset.split(" "):[0,0],h,k,j;if(d.nodeType===9){h=a.width();k=a.height();j={top:0,left:0}}else if(d.setTimeout){h=a.width();k=a.height();j={top:a.scrollTop(),left:a.scrollLeft()}}else if(d.preventDefault){b.at="left top";h=k=0;j={top:b.of.pageY, +left:b.of.pageX}}else{h=a.outerWidth();k=a.outerHeight();j=a.offset()}c.each(["my","at"],function(){var f=(b[this]||"").split(" ");if(f.length===1)f=n.test(f[0])?f.concat(["center"]):o.test(f[0])?["center"].concat(f):["center","center"];f[0]=n.test(f[0])?f[0]:"center";f[1]=o.test(f[1])?f[1]:"center";b[this]=f});if(g.length===1)g[1]=g[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(b.at[0]==="right")j.left+=h;else if(b.at[0]==="center")j.left+=h/2;if(b.at[1]==="bottom")j.top+= +k;else if(b.at[1]==="center")j.top+=k/2;j.left+=e[0];j.top+=e[1];return this.each(function(){var f=c(this),l=f.outerWidth(),m=f.outerHeight(),p=parseInt(c.curCSS(this,"marginLeft",true))||0,q=parseInt(c.curCSS(this,"marginTop",true))||0,v=l+p+parseInt(c.curCSS(this,"marginRight",true))||0,w=m+q+parseInt(c.curCSS(this,"marginBottom",true))||0,i=c.extend({},j),r;if(b.my[0]==="right")i.left-=l;else if(b.my[0]==="center")i.left-=l/2;if(b.my[1]==="bottom")i.top-=m;else if(b.my[1]==="center")i.top-=m/2; +i.left=parseInt(i.left);i.top=parseInt(i.top);r={left:i.left-p,top:i.top-q};c.each(["left","top"],function(s,x){c.ui.position[g[s]]&&c.ui.position[g[s]][x](i,{targetWidth:h,targetHeight:k,elemWidth:l,elemHeight:m,collisionPosition:r,collisionWidth:v,collisionHeight:w,offset:e,my:b.my,at:b.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(i,{using:b.using}))})};c.ui.position={fit:{left:function(b,a){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();b.left=d>0? +b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+= +a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b), +g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery); +;/* + * jQuery UI Draggable 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== +"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= +this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top- +this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions(); +d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.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";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element, +b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this== +a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]|| +0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], +this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top- +(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment== +"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&& +a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"), +10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], +this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft(): +f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.leftthis.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?e:!(e-this.offset.click.left').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options; +if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!= +"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e=j&&f<=l||h>=j&&h<=l||fl)&&(e>= +i&&e<=k||g>=i&&g<=k||ek);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), +top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= +this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!e(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", +nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var d=0;d');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== +String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),k=0;k=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,k);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection(); +this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){e(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()}; +if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(), +d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset= +this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio: +this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis];if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize", +b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height; +f={width:c.size.width-(f?0:c.sizeDiff.width),height:c.size.height-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f,{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop", +b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(l(b.left))this.position.left=b.left;if(l(b.top))this.position.top=b.top;if(l(b.height))this.size.height=b.height;if(l(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,d=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(d=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(d=="nw"){b.top= +a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,d=l(b.width)&&a.maxWidth&&a.maxWidthb.width,h=l(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height, +k=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&k)b.left=i-a.minWidth;if(d&&k)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+ +a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this, +arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable, +{version:"1.8.6"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(),10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize, +function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top-f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var k=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:k.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n= +(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(k.css("position"))){c._revertToRelativePosition=true;k.css({position:"absolute",top:"auto",left:"auto"})}k.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType?e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition= +false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a=e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left- +a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing,step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize", +b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top", +"Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset;var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset, +f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left:a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left= +a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top-d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+ +a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition,f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&& +e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative", +height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b=e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width= +d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},l=function(b){return!isNaN(parseInt(b,10))}})(jQuery); +;/* + * jQuery UI Selectable 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"), +selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("
      ")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX, +c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");b.unselecting=true;f._trigger("unselecting", +c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=this;this.dragged=true;if(!this.options.disabled){var d= +this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.righti||a.bottomb&&a.rightg&&a.bottom *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable"); +this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this, +arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem= +c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset, +{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment(); +if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start", +a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute"); +if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a, +c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]== +document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate", +null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem): +d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute|| +"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")}, +_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!= +this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a= +this.currentItem.find(":data(sortable-item)"),b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable"); +if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h= +0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width= +this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f}, +update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b= +null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this)); +this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])? +g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive", +g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over= +0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"); +a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); +if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var f=d.closest(".ui-accordion-header");a.active=f.length?f:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion", +function(g){return a._keydown(g)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(g){a._clickHandler.call(a,g,this);g.preventDefault()})},_createIcons:function(){var a=this.options;if(a.icons){c("").addClass("ui-icon "+ +a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex"); +this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons(); +b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target); +a.preventDefault()}if(g){c(a.target).attr("tabIndex",-1);c(g).attr("tabIndex",0);g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+ +c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height("").height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a==="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=this.options; +if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.active=d.collapsible&&b?false:this.headers.index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected); +a.next().addClass("ui-accordion-content-active")}h=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):h,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(h,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); +this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},h=this.active=c([]);this._toggle(h,f,g)}},_toggle:function(a,b,d,f,g){var h=this,e=h.options;h.toShow=a;h.toHide=b;h.data=d;var j=function(){if(h)return h._completed.apply(h,arguments)};h._trigger("changestart",null,h.data);h.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]),toHide:b,complete:j, +down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!f[k]&&!c.easing[k])k="slide";f[k]||(f[k]=function(l){this.slide(l,{easing:k,duration:i||700})}); +f[k](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.6",animations:{slide:function(a, +b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},h={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){h[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/);g[i]={value:j[1], +unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(h,{step:function(j,i){if(i.prop=="height")f=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=f*g[i.prop].value+g[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide",paddingTop:"hide", +paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); +;/* + * jQuery UI Autocomplete 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function(e){e.widget("ui.autocomplete",{options:{appendTo:"body",delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},_create:function(){var a=this,b=this.element[0].ownerDocument,f;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.attr("readonly"))){f=false;var d=e.ui.keyCode;switch(c.keyCode){case d.PAGE_UP:a._move("previousPage", +c);break;case d.PAGE_DOWN:a._move("nextPage",c);break;case d.UP:a._move("previous",c);c.preventDefault();break;case d.DOWN:a._move("next",c);c.preventDefault();break;case d.ENTER:case d.NUMPAD_ENTER:if(a.menu.active){f=true;c.preventDefault()}case d.TAB:if(!a.menu.active)return;a.menu.select(c);break;case d.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!=a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay); +break}}}).bind("keypress.autocomplete",function(c){if(f){f=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("
        ").addClass("ui-autocomplete").appendTo(e(this.options.appendTo|| +"body",b)[0]).mousedown(function(c){var d=a.menu.element[0];e(c.target).closest(".ui-menu-item").length||setTimeout(function(){e(document).one("mousedown",function(g){g.target!==a.element[0]&&g.target!==d&&!e.ui.contains(d,g.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,d){d=d.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:d})&&/^key/.test(c.originalEvent.type)&&a.element.val(d.value)},selected:function(c,d){d=d.item.data("item.autocomplete"); +var g=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=g;setTimeout(function(){a.previous=g},1)}false!==a._trigger("select",c,{item:d})&&a.element.val(d.value);a.term=a.element.val();a.close(c);a.selectedItem=d},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup"); +this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a,b){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(e(b||"body",this.element[0].ownerDocument)[0])},_initSource:function(){var a=this,b,f;if(e.isArray(this.options.source)){b=this.options.source;this.source=function(c,d){d(e.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){f=this.options.source;this.source= +function(c,d){a.xhr&&a.xhr.abort();a.xhr=e.getJSON(f,c,function(g,i,h){h===a.xhr&&d(g);a.xhr=null})}}else this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length").data("item.autocomplete",b).append(e("").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, +"\\$&")},filter:function(a,b){var f=new RegExp(e.ui.autocomplete.escapeRegex(b),"i");return e.grep(a,function(c){return f.test(c.label||c.value||c)})}})})(jQuery); +(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(b){if(e(b.target).closest(".ui-menu-item a").length){b.preventDefault();a.select(b)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", +-1).mouseenter(function(b){a.activate(b,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var f=b.offset().top-this.element.offset().top,c=this.element.attr("scrollTop"),d=this.element.height();if(f<0)this.element.attr("scrollTop",c+f);else f>=d&&this.element.attr("scrollTop",c+f-d+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:b})}, +deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,f){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0); +a.length?this.activate(f,a):this.activate(f,this.element.children(b))}else this.activate(f,this.element.children(b))},nextPage:function(a){if(this.hasScroll())if(!this.active||this.last())this.activate(a,this.element.children(".ui-menu-item:first"));else{var b=this.active.offset().top,f=this.element.height(),c=this.element.children(".ui-menu-item").filter(function(){var d=e(this).offset().top-b-f+e(this).height();return d<10&&d>-10});c.length||(c=this.element.children(".ui-menu-item:last"));this.activate(a, +c)}else this.activate(a,this.element.children(".ui-menu-item").filter(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(".ui-menu-item:last"));else{var b=this.active.offset().top,f=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var c=e(this).offset().top-b+f-e(this).height();return c<10&&c>-10});result.length||(result=this.element.children(".ui-menu-item:first")); +this.activate(a,result)}else this.activate(a,this.element.children(".ui-menu-item").filter(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":d.primary?"-primary":"-secondary"));d.primary&&b.prepend("");d.secondary&&b.append("");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary"); +this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":visible").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end().end()}, +destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery); +;/* + * jQuery UI Dialog 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function(c,j){var k={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},l={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:{my:"center",at:"center",of:window,collision:"fit",using:function(a){var b=c(this).css(a).offset().top; +b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
        ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex", +-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
        ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role", +"button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id",e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose= +b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");a.uiDialog.remove();a.originalTitle&& +a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!==b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))}); +c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a); +d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target===f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(); +a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("
        ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("
        ").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;f=c('').attr(h,true).unbind("click").click(function(){h.click.apply(b.element[0], +arguments)}).appendTo(g);c.fn.button&&f.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f, +h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition,originalSize:f.originalSize,position:f.position,size:f.size}}a=a===j?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw"; +d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize",f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position", +g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position, +a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(a);e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f);if(g in k)e=true;if(g in l)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b); +break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy"); +g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a=this.options,b,d;this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d, +height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height-b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.6",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}}); +c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay"); +a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("
        ");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("").appendTo(this.element).addClass("ui-slider-handle"); +if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur(); +else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),h,g,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e= +false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");h=a._start(c,f);if(h===false)return}break}i=a.options.step;h=a.options.values&&a.options.values.length?(g=a.values(f)):(g=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:g=a._valueMin();break;case d.ui.keyCode.END:g=a._valueMax();break;case d.ui.keyCode.PAGE_UP:g=a._trimAlignValue(h+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:g=a._trimAlignValue(h-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(h=== +a._valueMax())return;g=a._trimAlignValue(h+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(h===a._valueMin())return;g=a._trimAlignValue(h-i);break}a._slide(c,f,g);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"); +this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,h,g;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c=this._normValueFromMouse({x:a.pageX,y:a.pageY});e=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(i){var j=Math.abs(c-h.values(i));if(e>j){e=j;f=d(this);g=i}});if(b.range===true&&this.values(1)===b.min){g+=1;f=d(this.handles[g])}if(this._start(a, +g)===false)return false;this._mouseSliding=true;h._handleIndex=g;f.addClass("ui-state-active").focus();b=f.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-f.width()/2,top:a.pageY-b.top-f.height()/2-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};this._slide(a,g,c);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(a){var b= +this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;if(this.orientation==="horizontal"){b= +this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b); +c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;fthis._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a= +this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,h={},g,i,j,l;if(this.options.values&&this.options.values.length)this.handles.each(function(k){f=(c.values(k)-c._valueMin())/(c._valueMax()-c._valueMin())*100;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](h,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(k===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({width:f- +g+"%"},{queue:false,duration:b.animate})}else{if(k===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({height:f-g+"%"},{queue:false,duration:b.animate})}g=f});else{i=this.value();j=this._valueMin();l=this._valueMax();f=l!==j?(i-j)/(l-j)*100:0;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](h,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"}, +b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.6"})})(jQuery); +;/* + * jQuery UI Tabs 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(d,p){function u(){return++v}function w(){return++x}var v=0,x=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
        ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
      • #{label}
      • "},_create:function(){this._tabify(true)},_setOption:function(b,e){if(b=="selected")this.options.collapsible&& +e==this.options.selected||this.select(e);else{this.options[b]=e;this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[b].concat(d.makeArray(arguments)))},_ui:function(b,e){return{tab:b,panel:e,index:this.anchors.index(b)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b= +d(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(b){function e(g,f){g.css("display","");!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}var a=this,c=this.options,h=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=d(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);this.anchors.each(function(g,f){var i=d(f).attr("href"),l=i.split("#")[0],q;if(l&&(l===location.toString().split("#")[0]|| +(q=d("base")[0])&&l===q.href)){i=f.hash;f.href=i}if(h.test(i))a.panels=a.panels.add(a._sanitizeSelector(i));else if(i&&i!=="#"){d.data(f,"href.tabs",i);d.data(f,"load.tabs",i.replace(/#.*$/,""));i=a._tabId(f);f.href="#"+i;f=d("#"+i);if(!f.length){f=d(c.panelTemplate).attr("id",i).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else c.disabled.push(g)});if(b){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); +this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(c.selected===p){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){c.selected=g;return false}});if(typeof c.selected!=="number"&&c.cookie)c.selected=parseInt(a._cookie(),10);if(typeof c.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)c.selected= +this.lis.index(this.lis.filter(".ui-tabs-selected"));c.selected=c.selected||(this.lis.length?0:-1)}else if(c.selected===null)c.selected=-1;c.selected=c.selected>=0&&this.anchors[c.selected]||c.selected<0?c.selected:0;c.disabled=d.unique(c.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(c.selected,c.disabled)!=-1&&c.disabled.splice(d.inArray(c.selected,c.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); +if(c.selected>=0&&this.anchors.length){d(a._sanitizeSelector(a.anchors[c.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(c.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[c.selected],d(a._sanitizeSelector(a.anchors[c.selected].hash))))});this.load(c.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else c.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")); +this.element[c.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");c.cookie&&this._cookie(c.selected,c.cookie);b=0;for(var j;j=this.lis[b];b++)d(j)[d.inArray(b,c.disabled)!=-1&&!d(j).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");c.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(c.event!=="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+ +g)};this.lis.bind("mouseover.tabs",function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(c.fx)if(d.isArray(c.fx)){m=c.fx[0];o=c.fx[1]}else m=o=c.fx;var r=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal", +function(){e(f,o);a._trigger("show",null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},s=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")}; +this.anchors.bind(c.event+".tabs",function(){var g=this,f=d(g).closest("li"),i=a.panels.filter(":not(.ui-tabs-hide)"),l=d(a._sanitizeSelector(g.hash));if(f.hasClass("ui-tabs-selected")&&!c.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a.panels.filter(":animated").length||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}c.selected=a.anchors.index(this);a.abort();if(c.collapsible)if(f.hasClass("ui-tabs-selected")){c.selected=-1;c.cookie&& +a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){s(g,i)}).dequeue("tabs");this.blur();return false}else if(!i.length){c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this));this.blur();return false}c.cookie&&a._cookie(c.selected,c.cookie);if(l.length){i.length&&a.element.queue("tabs",function(){s(g,i)});a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier."; +d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(b){if(typeof b=="string")b=this.anchors.index(this.anchors.filter("[href$="+b+"]"));return b},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e= +d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(c,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});b.cookie&&this._cookie(null,b.cookie);return this},add:function(b, +e,a){if(a===p)a=this.anchors.length;var c=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,b).replace(/#\{label\}/g,e));b=!b.indexOf("#")?b.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var j=d("#"+b);j.length||(j=d(h.panelTemplate).attr("id",b).data("destroy.tabs",true));j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);j.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]); +j.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");j.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){c._trigger("show",null,c._ui(c.anchors[0],c.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(b){b=this._getIndex(b);var e=this.options,a=this.lis.eq(b).remove(),c=this.panels.eq(b).remove(); +if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(b+(b+1=b?--h:h});this._tabify();this._trigger("remove",null,this._ui(a.find("a")[0],c[0]));return this},enable:function(b){b=this._getIndex(b);var e=this.options;if(d.inArray(b,e.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=b});this._trigger("enable",null, +this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(b){b=this._getIndex(b);var e=this.options;if(b!=e.selected){this.lis.eq(b).addClass("ui-state-disabled");e.disabled.push(b);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[b],this.panels[b]))}return this},select:function(b){b=this._getIndex(b);if(b==-1)if(this.options.collapsible&&this.options.selected!=-1)b=this.options.selected;else return this;this.anchors.eq(b).trigger(this.options.event+".tabs");return this}, +load:function(b){b=this._getIndex(b);var e=this,a=this.options,c=this.anchors.eq(b)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(a.spinner){var j=d("span",c);j.data("label.tabs",j.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(c.hash)).html(k);e._cleanup();a.cache&&d.data(c,"cache.tabs", +true);e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.error(k,n,b,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(b, +e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.6"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k')}function E(a,b){d.extend(a, +b);for(var c in b)if(b[c]==null||b[c]==G)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.6"}});var y=(new Date).getTime();d.extend(K.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]= +f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('
        ')}}, +_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&& +b.append.remove();if(c){b.append=d(''+c+"");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('').addClass(this._triggerClass).html(f== +""?c:d("").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;gh){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a, +c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b), +true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor== +Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]); +d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}}, +_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b= +d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false; +for(var b=0;b-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target|| +a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a); +d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&& +d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f, +h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover"); +this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover"); +this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"); +a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(), +k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"]; +a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val(): +"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&& +!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth; +b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){var b= +this._getInst(d(a)[0]);b.input&&b._selectingMonthYear&&setTimeout(function(){b.input.focus()},0);b._selectingMonthYear=!b._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a= +d(a);this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a, +"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b== +"object"?b.toString():b+"";if(b=="")return null;for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1 +-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",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",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24* +60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+112?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e? +"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k= +this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&nn;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a, +"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a));n=this._canAdjustMonth(a,-1,m,g)?''+n+"":f?"":''+ +n+"";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m,g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?''+r+"":f?"":''+r+"";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&&a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'":"";e=e?'
        '+(c?h:"")+(this._isInRange(a,r)?'":"")+(c?"":h)+"
        ":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var L=this._getDefaultDate(a),I="",C=0;C1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='
        '+(/all|left/.test(t)&&C==0?c? +f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'
        ';var A=k?'":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="=5?' class="ui-datepicker-week-end"':"")+'>'+s[q]+""}x+=A+"";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, +A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var O=0;O";var P=!k?"":'";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,J=B&&!H||!F[0]||j&&qo;P+='";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=P+""}g++;if(g>11){g=0;m++}x+="
        '+this._get(a,"weekHeader")+"
        '+this._get(a,"calculateWeek")(q)+""+(B&&!w?" ":J?''+q.getDate()+ +"":''+q.getDate()+"")+"
        "+(l?""+(i[0]>0&&D==i[1]-1?'
        ':""):"");M+=x}I+=M}I+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'': +"");a._keyEvent=false;return I},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='
        ',o="";if(h||!k)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(j+=o+(h||!(k&&l)?" ":""));if(h||!l)j+=''+c+"";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b, +i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?" ":"")+o;j+="
        ";return j},_adjustInstDate:function(a,b,c){var e= +a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a, +"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a); +c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a, +"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker= +function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b)); +return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new K;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.6";window["DP_jQuery_"+y]=d})(jQuery); +;/* + * jQuery UI Progressbar 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(b,c){b.widget("ui.progressbar",{options:{value:0},min:0,max:100,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.max,"aria-valuenow":this._value()});this.valueDiv=b("
        ").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); +this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===c)return this._value();this._setOption("value",a);return this},_setOption:function(a,d){if(a==="value"){this.options.value=d;this._refreshValue();this._trigger("change");this._value()===this.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.max,Math.max(this.min,a))},_refreshValue:function(){var a= +this.value();this.valueDiv.toggleClass("ui-corner-right",a===this.max).width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.6"})})(jQuery); +;/* + * jQuery UI Effects 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/ + */ +jQuery.effects||function(f,j){function m(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], +16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return n.transparent;return n[f.trim(c).toLowerCase()]}function s(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return m(b)}function o(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, +a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function p(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in t||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function u(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d= +a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}function l(c){if(!c||typeof c==="number"||f.fx.speeds[c])return true;if(typeof c==="string"&&!f.effects[c])return true;return false}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor", +"borderColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=s(b.elem,a);b.end=m(b.end);b.colorInit=true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var n={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],transparent:[255,255,255]},q=["add","remove","toggle"],t={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d= +b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=p(o.call(this)),r,v=e.attr("className");f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});r=p(o.call(this));e.attr("className",v);e.animate(u(h,r),a,b,function(){f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a? +f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this, +[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.6",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a, +{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a= +k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)});return d.call(this,b)},_show:f.fn.show,show:function(c){if(l(c))return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(l(c))return this._hide.apply(this,arguments);else{var a= +k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(l(c)||typeof c==="boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c, +a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d* +(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c, +a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c, +a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ +e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); +;/* + * jQuery UI Effects Fade 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Fold 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100* +f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); +;/* + * jQuery UI Effects Highlight 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& +this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Pulsate 1.8.6 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); +b.dequeue()})})}})(jQuery); +; \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/jsondata.txt b/phpgwapi/js/jquery/jqplot/examples/jsondata.txt new file mode 100644 index 0000000000..b6a0cffac9 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/jsondata.txt @@ -0,0 +1 @@ +[[1, 3, 2, 4, 6, 9]] \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/legendLabels.html b/phpgwapi/js/jquery/jqplot/examples/legendLabels.html new file mode 100644 index 0000000000..f8bd3a735f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/legendLabels.html @@ -0,0 +1,205 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

        The following charts demonstrate some options of the EnhancedLegendRendrer. Some of the enhancements are:

        +
          +
        • Control of number of rows and/or columns.
        • +
        • Clickable swatches and labels to toggle series on/off.
        • +
        • Placement of legend inside or outside of the plot (this has since been added to the default legend functionality).
        • +
        • Ability to hide legend swatches and or labels.
        • +
        + +

        The first plot has legend labels in 3 columns. They are clickable.

        + +
        + +
        
        +    
        +

        The second chart has legend labels in 2 columns placed outside of the plot. The showLabels option is false, but the labels are still clickable.

        +

        The legend renderer's "seriesToggle" option has been set to 900 to produce a slow, 900 ms fade. You can set this to a number or to 'fast', 'normal' or 'slow'.

        +

        Also, the disableIEFading option is set to false to allow fading on IE (as opposed to simple show/hide). In IE, series will be toggled with a show()/hide() method by default as opposed to fadeIn()/fadeOut() because of poor performance on some machines.

        +
        + +
        
        +
        +

        The third plot has legend labels in 1 row outside and below the chart area. The showSwatches option is false, but the labels are still clickable.

        +
        + + +
        
        +

        The fourth chart is a pie plot. Pie plots use their own legend renderer, since a pie plot is only 1 series. The pie legend renderer has also been updated to handle custom rows/columns, although it is not clickable.

        +
        + +
        
        +    
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/legendLabels2.html b/phpgwapi/js/jquery/jqplot/examples/legendLabels2.html
        new file mode 100644
        index 0000000000..4b2d9aa8c3
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/legendLabels2.html
        @@ -0,0 +1,228 @@
        +
        +
        +
        +
        +  
        +  Simple Test
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +
        +
        +
        +
        +  
        +
        +  
        +
        +
        +
        +
        +
        +
        + 
        +  
        +  
        +
        +
        +

        This example demonstrates how to use the legend "location: 'outsideGrid'" option. This option will place the legend outside of the grid but inside of the plot target. It will shrink the grid to accommodate the plot target. Borders have been added to the plot target container elements to clarify how the legend is drawn in each case.

        + +
        + +
        
        +    
        +
        + +
        
        +
        +
        + +
        
        +
        +
        + +
        
        +
        +
        + +
        
        +    
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/linepiebar.html b/phpgwapi/js/jquery/jqplot/examples/linepiebar.html
        new file mode 100644
        index 0000000000..4bae135570
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/linepiebar.html
        @@ -0,0 +1,158 @@
        +
        +
        + 
        +     
        +  
        +  
        +    
        +    
        +    
        +
        +    
        +    
        +    
        +    
        +    
        +    
        +    
        +    
        +    
        +    
        +    
        +
        +    
        +
        + 
        + 
        +
        +
        + 
        +
        +
        + + + diff --git a/phpgwapi/js/jquery/jqplot/examples/markerStyles.html b/phpgwapi/js/jquery/jqplot/examples/markerStyles.html new file mode 100644 index 0000000000..3517c77686 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/markerStyles.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + +
        + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/mekkoChart.html b/phpgwapi/js/jquery/jqplot/examples/mekkoChart.html new file mode 100644 index 0000000000..9d37bc6ce6 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/mekkoChart.html @@ -0,0 +1,224 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + +

        Mekko charts make a number of customizations to the series, axes and legend. You can create a Mekko chart by including the renderers:

        +
        +<script language="javascript" type="text/javascript" src="../src/plugins/jqplot.mekkoRenderer.js"></script>
        +<script language="javascript" type="text/javascript" src="../src/plugins/jqplot.mekkoAxisRenderer.js"></script>
        +
        + +

        Data is specified per bar in the chart. You can specify data as an array of y values, or as an array of [label, value] pairs. Note that labels are used only on the first series. Labels on subsequent series are ignored:

        +
        +bar1 = [['shirts', 8],['hats', 14],['shoes', 6],['gloves', 16],['dolls', 12]];
        +bar2 = [15,6,9,13,6];
        +bar3 = [['grumpy',4],['sneezy',2],['happy',7],['sleepy',9],['doc',7]];
        +
        + +

        If you want to place labels for each bar under the axis, you use the barLabels option on the axes. The bar labels can be styled with the ".jqplot-mekko-barLabel" css class.

        +
        +barLabels = ['Mickey Mouse', 'Donald Duck', 'Goofy'];
        +axes:{xaxis:{barLabels:barLabels}}
        +
        + +
        + +

        You can add a secondary x axes, and the tick spacing of the axes can be separately controlled with the "tickMode" option. "bar" will produce tics at bar boundaries, "even" will produce evenly spaced ticks. If you set the axes max greater than the sum of the data range (the maximum x value), the plot will be padded. Note that you should set the max on both axes to the same value.

        + +
        +axes:{
        +    xaxis:{
        +        barLabels:barLabels,
        +        max: 175
        +    }, 
        +    x2axis:{
        +        show:true, 
        +        tickMode:'even', 
        +        max: 175
        +    }
        +}
        +
        + +

        Here the borders between chart areas have been given a custom color using the "borderColor" option on the series renderer.

        + +
        +    seriesDefaults:{renderer:$.jqplot.MekkoRenderer, rendererOptions: {borderColor: '#dddddd'}}
        +
        + +

        Additionally, the legend can be placed "outside" (the default for a mekko chart) or "inside" of the grid area with the "placement" option on the legend renderer.

        + +
        +legend:{
        +    show:true, 
        +    rendererOptions:{placement: "insideGrid"}, 
        +    location:'e'
        +},
        +
        + +
        + +

        Legend labels can be specified independently of the series with the "labels" option on the legend. These will override any labels specified with the series. There are also options to control the number of rows and number of columns in the legend as well as placement.

        + +

        Here the legend is positioned to the "north" and set to render 1 row tall (number of columns determined automatically). Note that an extra css specification was added to pad the bottom of the title of this chart to give room for the legend above the plot.

        + +
        +legendLabels = ['hotels', 'rides', 'buses', 'instruments', 'totes'];
        +
        +legend:{
        +    show:true, 
        +    location: 'n',
        +    labels: legendLabels,
        +    rendererOptions:{numberRows: 1, placement: "outside"}
        +},    
        +
        + +

        Also, the borders between the chart areas have been turned off with the "showBorders: false" option.

        + +
        +    seriesDefaults:{renderer:$.jqplot.MekkoRenderer, rendererOptions: {showBorders: false}}
        +
        + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/meterGauge.html b/phpgwapi/js/jquery/jqplot/examples/meterGauge.html new file mode 100644 index 0000000000..74d4242b57 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/meterGauge.html @@ -0,0 +1,132 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + +

        A meter gauge plot shows a data value in a speedometer style gauge. The "series" in consists of a single data value that positions the needle on the gauge. The span of the gauge will be automatically determined, or can be set with the "min" and "max" values in the "rendererOptions" of the series. The plot below also specifies a chart title and a "label" for the gauge.

        + +
        + +

        For small gauges, it can be desirable to turn off the tick labels by setting the "showTickLabels" option in the rendererOptions to false. Also, colored interval bands can be specified. The interval ranges are specified as an array of values the "intervals" option and custom colors for each interval can be specified with the "intervalColors" option.

        + +
        + +

        The inner and outer radii of the interval band will automatically adjust when tick Labels are turned on. Also, the gauge minimum and maximum can be specified with the "min" and "max" options in the rendererOptions.

        + +
        + +

        The inner and outer radii of the interval band can also be specified with the "intervalInnerRadius" and "intervalOuterRadius" options. In the plot below, the "labelPosition" option was set to "bottom" to put the gauge label below the plot. The "labelHeightAdjust" option was set to -5 to raise the label slightly (5 pixels) to place it closer to the gauge.

        +

        The gauge automatically resizes to best fit the container. The font size of the tick labels and gauge labels do not size to the container, however. The font size of the tick labels can be controlled by styling the css ".jqplot-meterGauge-ticks" class and the gauge label by the "jqplot-meterGauge-label" class.

        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/meterGauge2.html b/phpgwapi/js/jquery/jqplot/examples/meterGauge2.html new file mode 100644 index 0000000000..db0e9f70bb --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/meterGauge2.html @@ -0,0 +1,159 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/minMaxLines.html b/phpgwapi/js/jquery/jqplot/examples/minMaxLines.html
        new file mode 100644
        index 0000000000..c16de06d31
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/minMaxLines.html
        @@ -0,0 +1,60 @@
        +
        +
        +
        +
        +  
        +  Horizontal Bar with Vertical lines Test
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +
        +  
        +
        +
        +  
        +  
        +
        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/missingValues.html b/phpgwapi/js/jquery/jqplot/examples/missingValues.html new file mode 100644 index 0000000000..e8eb76c7e3 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/missingValues.html @@ -0,0 +1,119 @@ + + + + + + Null Value Handling + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        
        +    
        +
        
        +    
        +
        
        +    
        +
        
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/multiAxesRotatedText.html b/phpgwapi/js/jquery/jqplot/examples/multiAxesRotatedText.html
        new file mode 100644
        index 0000000000..8c83f8749b
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/multiAxesRotatedText.html
        @@ -0,0 +1,69 @@
        +
        +
        +
        +
        +	
        +	untitled
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +	
        +	
        +
        +
        +
        +
        +
        + + + + diff --git a/phpgwapi/js/jquery/jqplot/examples/multipleBarColors.html b/phpgwapi/js/jquery/jqplot/examples/multipleBarColors.html new file mode 100644 index 0000000000..6965d9206b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/multipleBarColors.html @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +

        Individual bars can now have different colors. This is achieved by setting the "varyBarColor" option to true in the series rendererOptions. The default is to assign each bar a different color from the default "seriesColors" array. You can customize the seriesColors array to assign whatever colors you like to the bars.

        +
        +
        + +

        Bars and filled series are colored differently for positive and negative values by default. Negative values will be a slightly darker and less saturated than their positive counterparts for visual effect. This applies to only bar and filled line charts by default.

        + +
        + +

        If you want to use only the colors defined in the "seriesColors" array and not colors from the "negativeSeriesColors" array, set the "useNegativeColors" option to false. This way negative values and positive values will pull their colors from the same color array.

        + +

        Note that there are only 16 colors defined in the default color arrays. Color arrays will cylcle through colors continuously when the last color is used.

        + +
        + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/multipleLines.html b/phpgwapi/js/jquery/jqplot/examples/multipleLines.html new file mode 100644 index 0000000000..f5d8950f89 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/multipleLines.html @@ -0,0 +1,46 @@ + + + + + + Multiple lines Test + + + + + + + + + + + + + + + + + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/multipleYAxes.html b/phpgwapi/js/jquery/jqplot/examples/multipleYAxes.html new file mode 100644 index 0000000000..639c23d0fa --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/multipleYAxes.html @@ -0,0 +1,104 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + +
        +
        +
        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/nav.inc b/phpgwapi/js/jquery/jqplot/examples/nav.inc new file mode 100644 index 0000000000..b41d92c662 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/nav.inc @@ -0,0 +1,35 @@ + diff --git a/phpgwapi/js/jquery/jqplot/examples/noDataOptions.html b/phpgwapi/js/jquery/jqplot/examples/noDataOptions.html new file mode 100644 index 0000000000..fdf8d38622 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/noDataOptions.html @@ -0,0 +1,78 @@ + + + + + + Data Loading Indicator + + + + + + + + + + + + + + + + + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/pieTest.html b/phpgwapi/js/jquery/jqplot/examples/pieTest.html new file mode 100644 index 0000000000..201b873015 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/pieTest.html @@ -0,0 +1,103 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

        This page tests for 3 conditions. Plotting pies with a slice that begins at 0 and ends at and near 2*pi (360 degrees), disabling the trendline plugin on pies, and plotting a pie that has a 0 value (or a very small value relative to other values) in the data set.

        +
        +
        
        +    
        +
        
        +    
        +
        
        +    
        +
        
        +    
        +
        
        +    
        +
        
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/pieTest2.html b/phpgwapi/js/jquery/jqplot/examples/pieTest2.html
        new file mode 100644
        index 0000000000..7cd0f10e24
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/pieTest2.html
        @@ -0,0 +1,166 @@
        +
        +
        +
        +
        +  
        +  Pie Chart Test
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +    
        +  
        +  
        +  
        +  
        +  
        +  
        +
        +  
        +  
        +  
        +     
        +    
        +  
        +  
        +
        +
        +

        To create pie plots, you have to include the "jqplot.pieRenderer.js" file in your source.

        + +

        Below is a default pie plot. Slices will highlight on mouseover. Events are triggered when you mouseover a slice and also when you click on a slice. Here We capture the 'jqplotDataClick' event and display the clicked series index, point index and data values.

        + +

        You Clicked: Nothing yet
        + +
        + +

        Below is a customized customized pie plot where options for sliceMargin and startAngle have been specified. Here We capture the 'jqplotDataHighlight' event and display the currently highlighted series index, point index and data values.

        + +

        The plot target also fires a 'jqplotDataMouseOver' when the cursor is moused over a slice even if highlighting is turned off. This event will fire continuously as the user mouses over the slice. 'jqplotDataHighlight' fires only once when the user first passes over the slice. Additionally, a 'jqplotDataUnhighlight' event is fired when the user moves out of a slice (if highlighting is enabled).

        + +

        Moused Over: Nothing
        + +
        + +

        The next example has the plot's 'captureRightClick' option set to true. This causes the plot to fire a 'jqplotRightClick' event the the user clicks the right mouse button over a slice.

        + +

        The 'highlightMouseDown' option is also set to true. This will highlight a slice on mouse down instead of on move over. Highlighting will occur for either left or right click.

        + +
        You Right Clicked: Nothing yet
        + +
        + +

        The last example shows a pie with all of the default colors. Mouse over to see the default highlight colors. Series colors can be specified with the "seriesColors" option on the plot. The highlight colors are specified with the 'highlightColors' option on the series renderer.

        + +
        + +

        A simple line chart is added to test for imcompatabilities.

        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/pieTest2.js b/phpgwapi/js/jquery/jqplot/examples/pieTest2.js new file mode 100644 index 0000000000..91073fe63c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/pieTest2.js @@ -0,0 +1,80 @@ +$(document).ready(function(){ + + $.jqplot.config.enablePlugins = true; + + s1 = [['a',2], ['b',6], ['c',7], ['d',10]]; + s2 = [['a', 4], ['b', 7], ['c', 6], ['d', 3]]; + s3 = [['a', 2], ['b', 1], ['c', 3], ['d', 3]]; + s4 = [['a', 4], ['b', 3], ['c', 2], ['d', 1]]; + + s5 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]; + + plot1 = $.jqplot('chart1', [s1], { + seriesDefaults:{ + renderer:$.jqplot.PieRenderer + }, + legend: {show:true} + }); + + plot2 = $.jqplot('chart2', [s2], { + seriesDefaults: { + renderer:$.jqplot.PieRenderer, + rendererOptions:{ + sliceMargin: 4, + startAngle: -90 + } + } + }); + + plot3 = $.jqplot('chart3', [s3], { + captureRightClick: true, + seriesDefaults:{ + renderer:$.jqplot.PieRenderer, + shadow: false, + rendererOptions:{ + startAngle: 90, + sliceMargin: 4, + highlightMouseDown: true + } + }, + legend: { + show: true, + location: 'e', + placement: 'outside' + } + }); + + plot5 = $.jqplot('chart5', [s5], { + seriesDefaults:{ + renderer:$.jqplot.PieRenderer + } + }); + + plot6 = $.jqplot('chart6', [[1,2,3,4]]); + + $('#chart1').bind('jqplotDataClick', + function (ev, seriesIndex, pointIndex, data) { + $('#info1').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $('#chart2').bind('jqplotDataHighlight', + function (ev, seriesIndex, pointIndex, data) { + $('#info2').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $('#chart2').bind('jqplotDataUnhighlight', + function (ev) { + $('#info2').html('Nothing'); + } + ); + + $('#chart3').bind('jqplotDataRightClick', + function (ev, seriesIndex, pointIndex, data) { + $('#info3').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data); + } + ); + + $(document).unload(function() {$('*').unbind(); }); +}); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/pieTest3.html b/phpgwapi/js/jquery/jqplot/examples/pieTest3.html new file mode 100644 index 0000000000..e94f6a2121 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/pieTest3.html @@ -0,0 +1,95 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        
        + 
        +    
        + 
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/pieTest4.html b/phpgwapi/js/jquery/jqplot/examples/pieTest4.html
        new file mode 100644
        index 0000000000..ffa0954554
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/pieTest4.html
        @@ -0,0 +1,249 @@
        +
        +
        +
        +
        +  
        +  Simple Test
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +    
        +  
        +  
        +  
        +  
        +  
        +
        +  
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + 
        +    
        +  
        +  
        +
        +
        +
        +               
        +    
        + +
        
        + 
        +    
        + +
        
        +
        +    
        +
        
        +  
        +    
        +
        
        +
        +    
        +
        
        +
        +    
        +
        
        +
        +    
        +
        
        +
        +    
        +
        
        +
        +    
        +
        
        +
        +    
        +
        
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/pointLabels.html b/phpgwapi/js/jquery/jqplot/examples/pointLabels.html
        new file mode 100644
        index 0000000000..f5c52b9d50
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/pointLabels.html
        @@ -0,0 +1,92 @@
        +
        +
        +
        +
        +  
        +  Zooming with Point Labels
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +
        +  
        +
        +
        +  
        +  
        +
        +    

        Click and drag to zoom. Double click on plot or click "Reset Zoom" button to reset zoom.

        +
        +
        + + + +
        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/pointLabels2.html b/phpgwapi/js/jquery/jqplot/examples/pointLabels2.html new file mode 100644 index 0000000000..9f96712f24 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/pointLabels2.html @@ -0,0 +1,47 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/prefix.html b/phpgwapi/js/jquery/jqplot/examples/prefix.html new file mode 100644 index 0000000000..1944983259 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/prefix.html @@ -0,0 +1,89 @@ + + + + + + Test + + + + + + + + + + + + + + + + + + + + + + +

        Example of the "prefix" axis tick option. This option adds a prefix to the tick label if and only if no formatString option is specified.

        +
        +
        
        +    
        +    

        A new configuration option, $.jqplot.config.defaultTickFormatString, has been added as well. When no user formatString is specified, linear axes previously used a hard coded '%.1f' default format string. The config option controls this default format string. This allows an alternative way to format tick labels, with or without a prefix, if no formatString option is specified.

        +
        +
        
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/resetAxisTicks.html b/phpgwapi/js/jquery/jqplot/examples/resetAxisTicks.html
        new file mode 100644
        index 0000000000..a185268680
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/resetAxisTicks.html
        @@ -0,0 +1,104 @@
        +
        +
        +
        +
        +  
        +  Single Negative Point
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +
        +  
        +
        +
        +  
        +  
        +
        +
        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/resizablePlot.html b/phpgwapi/js/jquery/jqplot/examples/resizablePlot.html new file mode 100644 index 0000000000..71358bbb96 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/resizablePlot.html @@ -0,0 +1,148 @@ + + + + + + Plots in Hidden Containers + + + + + + + + + + + + + + + + + + + + + + + + + +

        Plot targets can be placed inside of resizable containers for dynamic plot sizing. The examples here use the jQuery UI package for resizing functionality.

        + + + + +
        +
        +
        +
        +
        + +

        The first plot has good resize performance in Firefox, Safari and other canvas enabled browsers. The plot will resize dynamically with the container. IE performance will be slow since IE doesn't natively support the canvas element.

        + +

        Resizing is handled by binding a handler to the 'resize' event. The handler function replots the plot during resize. Here, the plot targets's height and width must be specified as a percentage of the container and the container must be visible.

        + +

        The event handler looks like:

        +
        +    $('#resizable1').bind('resize', function(event, ui) {
        +        plot1.replot();
        +    });
        +
        +
        + + +
        + +
        +
        +
        +
        +

        The second plot uses an alternative sizing method that is more responsive in all browsers, especially IE. The differnece? First, the plot target is given a static height and width that will fit inside the resizable container. Then, instead of resizing dynamically with the container, the plots replot() method is called at the end of the resize. When resizing is done, the plot targets hieght and width are set to a percentage of the container's and then the replot method is called.

        + +

        Also, an options object is passed into the replot method. It contains a single option, resetAxes, which, if true, resets all axes so the min, max, numberTicks and tickInterval are recalculated.

        +
        +    $('#resizable2').bind('resizestop', function(event, ui) {
        +        $('#chart2').height($('#resizable2').height()*0.96);
        +        $('#chart2').width($('#resizable2').width()*0.96);
        +        plot2.replot({resetAxes:true});
        +    });
        +
        + +

        You can also pass in option objects to reset specific axes like:

        + +
        +    {resetAxes:['yaxis', 'y2axis']};
        +    
        +    or
        +    
        +    {resetAxes:{yaxis:true, y2axis:true}};
        +
        + +
        + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/resizablePlot2.html b/phpgwapi/js/jquery/jqplot/examples/resizablePlot2.html new file mode 100644 index 0000000000..7571ab5595 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/resizablePlot2.html @@ -0,0 +1,146 @@ + + + + + + Resizable Plots + + + + + + + + + + + + + + + + + + + + + + + + +

        Plot targets can be placed inside of resizable containers for dynamic plot sizing. The examples here use the jQuery UI package for resizing functionality.

        + + + + +
        +
        +
        +
        +
        + +

        The first plot has good resize performance in Firefox, Safari and other canvas enabled browsers. The plot will resize dynamically with the container. IE performance will be slow since IE doesn't natively support the canvas element.

        + +

        Resizing is handled by binding a handler to the 'resize' event. The handler function replots the plot during resize. Here, the plot targets's height and width must be specified as a percentage of the container and the container must be visible.

        + +

        The event handler looks like:

        +
        +    $('#resizable1').bind('resize', function(event, ui) {
        +        plot1.replot();
        +    });
        +
        +
        + + +
        + +
        +
        +
        +
        +

        The second plot uses an alternative sizing method that is more responsive in all browsers, especially IE. The differnece? First, the plot target is given a static height and width that will fit inside the resizable container. Then, instead of resizing dynamically with the container, the plots replot() method is called at the end of the resize. When resizing is done, the plot targets hieght and width are set to a percentage of the container's and then the replot method is called.

        + +

        Also, an options object is passed into the replot method. It contains a single option, resetAxes, which, if true, resets all axes so the min, max, numberTicks and tickInterval are recalculated.

        +
        +    $('#resizable2').bind('resizestop', function(event, ui) {
        +        $('#chart2').height($('#resizable2').height()*0.96);
        +        $('#chart2').width($('#resizable2').width()*0.96);
        +        plot2.replot({resetAxes:true});
        +    });
        +
        + +

        You can also pass in option objects to reset specific axes like:

        + +
        +    {resetAxes:['yaxis', 'y2axis']};
        +    
        +    or
        +    
        +    {resetAxes:{yaxis:true, y2axis:true}};
        +
        + +
        + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/rotatedTickLabels.html b/phpgwapi/js/jquery/jqplot/examples/rotatedTickLabels.html new file mode 100644 index 0000000000..abdb55dcc3 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/rotatedTickLabels.html @@ -0,0 +1,61 @@ + + + + + jqPlot Test 2 + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/rotatedTickLabelsZoom.html b/phpgwapi/js/jquery/jqplot/examples/rotatedTickLabelsZoom.html new file mode 100644 index 0000000000..68c3c723ef --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/rotatedTickLabelsZoom.html @@ -0,0 +1,68 @@ + + + + + jqPlot Test 2 + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/seriesCanvasReorder.html b/phpgwapi/js/jquery/jqplot/examples/seriesCanvasReorder.html new file mode 100644 index 0000000000..1e19eab15b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/seriesCanvasReorder.html @@ -0,0 +1,92 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + +

        When lines overlap each other it can be difficult to tell what is going on with the series below the top. The highlighter plugin, the enhancedLegendRenderer plugin and special methods of plot help with this situation.

        + +

        The highlighter plugin has been enhanced with a "bringSeriesToFront" option which will bring the series of the highlighted point to the front when a data point is highlighted. Note, however, when highlighting a point which coincides with multiple series, highlighter will detect this as the top most series and no highlighting effect will be noticed.

        + +

        The enhancedLegendRenderer plugin enabled clickable legend labels which will show/hide series. This functionality can be disabled by setting the "seriesToggle" option on the legend renderer to false. You can also change the fade duration of the series by setting the seriesToggle option to a millisecond value like 450, or the 'slow' or 'fast' keywords.

        + +

        On IE, series are simple toggled without the fading. This avoids some erratic behaviour with fading elements on IE. IE fading can be re-enabled be setting the disableIEFading option to false.

        + +

        The plot object has 4 methods which can bring a series forward or push it backward on the stack. Click the buttons below to bring individual series to the front. The "Last Order" button will toggle the current series order with the last displayed series order. The "Original" button will reset the series to display in the order when the plot was created.

        + + +
        + + + + + + + + +

        The 4 methods to achieve this effect are:

        + +
        +    plot.moveSeriesToFront(series index);
        +    plot.restorePreviousSeriesOrder();
        +    plot.restoreOriginalSeriesOrder();
        +    plot.moveSeriesToBack(series index);
        +
        + +

        moveSeriesToBack is not demonstrated here, but is available.

        + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/seriesUpdate.html b/phpgwapi/js/jquery/jqplot/examples/seriesUpdate.html new file mode 100644 index 0000000000..6258505a14 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/seriesUpdate.html @@ -0,0 +1,122 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + +

        This example demonstrates how to update a point in a series and then redraw just that series. You can select a series, a point and change it's x and y value with the form below the chart.

        + +
        + +
        + Series: + Point: + X: + Y: + +
        + +

        The mechanism to update data in a series and then redraw the series is simple. update the data in the "plot.series[seriesIndex].data[dataIndex]" and then redraw just that series with "plot.drawSeries(options, seriesIndex);" Here is the relavent code which updates the series on this chart:

        + +
        +    var f = document.forms[0];
        +    var seriesIndex = f.seriesId.selectedIndex;
        +    var series = plot1.series[seriesIndex];
        +    var data = series.data[f.pointId.selectedIndex];
        +    var xval = parseFloat(f.xvalue.value);
        +    var yval = parseFloat(f.yvalue.value);
        +    data[0] = xval;
        +    data[1] = yval;
        +    plot1.drawSeries({}, seriesIndex);
        +
        + +

        You can also update an entire series dataset at once and redraw the series like so:

        + +
        +    plot1.series[2].data = [[1,4], [2,6], [3,4], [4,1], [5,7]];
        +    plot1.drawSeries({}, 2);
        +
        + +

        You can test this by clicking the button below. You should see the entire "bears" line drop lower on the chart.

        + + + +

        Note that the redrawSeries method does not do any axes scaling or redraw any other elements on the chart. It is intended to be a lightweight method to redraw just one series. Also note, if no series Index is passed in as the second parameter to drawSeries, it will redraw all series without rescaling or redrawing other plot elements.

        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/shadowTests.html b/phpgwapi/js/jquery/jqplot/examples/shadowTests.html new file mode 100644 index 0000000000..f3dda7cd2a --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/shadowTests.html @@ -0,0 +1,132 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/singlePoint.html b/phpgwapi/js/jquery/jqplot/examples/singlePoint.html new file mode 100644 index 0000000000..9eef5010b0 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/singlePoint.html @@ -0,0 +1,69 @@ + + + + + + Single Negative Point + + + + + + + + + + + + + + + + + + + + + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/sparkLine.html b/phpgwapi/js/jquery/jqplot/examples/sparkLine.html new file mode 100644 index 0000000000..5b900c2fa3 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/sparkLine.html @@ -0,0 +1,47 @@ + + + + + + Sparkline Test + + + + + + + + + + + + + + + + + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/stackedBar2.html b/phpgwapi/js/jquery/jqplot/examples/stackedBar2.html new file mode 100644 index 0000000000..ef211d69a8 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/stackedBar2.html @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/stackedBar3.html b/phpgwapi/js/jquery/jqplot/examples/stackedBar3.html new file mode 100644 index 0000000000..00c3b0603b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/stackedBar3.html @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/stackedBarCategoryVsLinearAxes.html b/phpgwapi/js/jquery/jqplot/examples/stackedBarCategoryVsLinearAxes.html new file mode 100644 index 0000000000..3a6aae2d64 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/stackedBarCategoryVsLinearAxes.html @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/stackedCategoryAxis.html b/phpgwapi/js/jquery/jqplot/examples/stackedCategoryAxis.html new file mode 100644 index 0000000000..2c1e7b86c1 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/stackedCategoryAxis.html @@ -0,0 +1,89 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/stackedFilledLine.html b/phpgwapi/js/jquery/jqplot/examples/stackedFilledLine.html new file mode 100644 index 0000000000..a38124af91 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/stackedFilledLine.html @@ -0,0 +1,76 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/stackedLine.html b/phpgwapi/js/jquery/jqplot/examples/stackedLine.html new file mode 100644 index 0000000000..e6d94f5e5c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/stackedLine.html @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/test2.html b/phpgwapi/js/jquery/jqplot/examples/test2.html new file mode 100644 index 0000000000..7ca904df4d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/test2.html @@ -0,0 +1,64 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + +
        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/theming.html b/phpgwapi/js/jquery/jqplot/examples/theming.html new file mode 100644 index 0000000000..368fa02f4c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/theming.html @@ -0,0 +1,481 @@ + + + + + + Theming Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

        jqPlot has basic theming support for commonly styled atributes of plot elements. Upon creation, each plot will have a "themeEngine" that controls modificaition, adding, removing and activating of plot themes. In addition, each plot will have a "Default" theme which corresponds to the styling of the plot at plot creation.

        + +

        Creation of new themes is easy. A "style" object is created with properties for the various plot elements to be styles. Attached to each of those is an ojbect with the actual styling properties. A simple style object might look like:

        + +
        +    gabe = {
        +        series: [
        +            {color: 'rgba(216, 159, 60, 0.4)'},
        +            {color: 'rgba(159, 216, 60, 0.4)'},
        +            {color: 'rgba(60, 159, 216, 0.4)'},
        +        ],
        +        grid: {
        +            backgroundColor: '#DEA493'
        +        }
        +    }
        +
        + +

        This new style would then be added to the plot's themeEngine as a new theme. it can then be activated by calling the plot's activateTheme method.

        +
        +    plot1b.themeEngine.newTheme('gabe', gabe);
        +    plot1b.activateTheme('gabe');
        +
        + +
        +

        Select Theme for area plot: + +

        + +

        Themes can be reused between plots. Here a style object is created and assigned to two different plots. For convenience, the theme is given the same name when added to each plot's themeEngine. Since each plot keeps it's own copy of the theme, the names do not need to be the same. Also note that themes are added as deep copies by value and not by reference. This avoids strange behavior due to the cascading nature of css related styles.

        + +
        +    temp = {
        +        seriesStyles: {
        +            seriesColors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo'],
        +            highlightColors: ['lightpink', 'lightsalmon', 'lightyellow', 'lightgreen', 'lightblue', 'mediumslateblue']
        +        },
        +        legend: {
        +            fontSize: '8pt'
        +        },
        +        title: {
        +            fontSize: '18pt'
        +        },
        +        grid: {
        +            backgroundColor: 'rgb(211, 233, 195)'
        +        }
        +    };
        +    
        +    plot3.themeEngine.newTheme('uma', temp);
        +    plot5.themeEngine.newTheme('uma', temp);
        +
        + +

        Select Theme for funnel and pie charts at same time: + +

        + +
        + +

        Select Theme for funnel plot: + +

        + +
        + +

        Select Theme for pie chart: + +

        + +

        There are various was to create and edit themes for a plot. Below are two different methods for creating additional themes for a line plot and adding them to the plots themeEngine. Here the axesStyles property is used to supply styling to all axes at one time. A similar property, seriesStyles, exists for styling all series of a plot at one time. Note, neither of these methods is as straightforward as using the newTheme() method of the plots themeEngine, but are included for illustrative purposes.

        + +
         
        +    e1 = plot1.themeEngine;
        +    brass = e1.copy('Default', 'brass');
        +    brass.title.fontFamily = 'Copperplate, Impact';
        +    brass.grid.backgroundColor = "rgb(216, 198, 114)";
        +    brass.grid.drawGridlines = false;
        +    brass.series[0].lineWidth = 6.5;
        +    brass.series[0].markerOptions.show = false;
        +    brass.axesStyles.label.fontFamily = "Copperplate, 'Copperplate Gothic Light', Impact";
        +    brass.axesStyles.ticks.fontFamily = "Copperplate, 'Copperplate Gothic Light', Impact";
        +    brass.axesStyles.label.fontSize = '14pt';
        +    
        +    temp = {
        +        grid: {
        +            backgroundColor: "#593D2B",
        +            gridLineColor: '#E8E8E8',
        +            gridLineWidth: 3
        +        },
        +        title: {
        +            fontFamily: '"Comic Sans MS", cursive',
        +            fontSize: '18pt',
        +            textColor: '#C7CC4E'
        +        },
        +        seriesStyles: {
        +            color: "#DBBCAF",
        +            lineWidth: 8,
        +            markerOptions: {
        +                show: false
        +            }
        +        },
        +        axes: {
        +            xaxis: {
        +                label: {
        +                    fontFamily: '"Comic Sans MS", cursive',
        +                    textColor: '#C7CC4E'
        +                }
        +            }
        +        }
        +    };
        +    
        +    chocolate = plot1.themeEngine.copy('Default', 'chocolate', temp);
        +
        + +
        + +

        Select theme for line chart: + +

        + +

        The example below shows more extensive use of the various styling options to give the chart a rather ugly and dated appearence. Note that, for bar (and funnel, pie and donut charts), highlightColors can be specified as an array of colors which will be applied to each bar individually, as a single string giving a color to apply to all bars, or as an empty array which will force jqPlot to auto calculate highlight colors based on the current bar color.

        + +

        +    oldstyle = {
        +        title: {
        +            fontFamily: 'Times New Roman',
        +            textColor: 'black'
        +        },
        +        axesStyles: {
        +           borderWidth: 0,
        +           ticks: {
        +               fontSize: '12pt',
        +               fontFamily: 'Times New Roman',
        +               textColor: 'black'
        +           },
        +           label: {
        +               fontFamily: 'Times New Roman',
        +               textColor: 'black'
        +           }
        +        },
        +        grid: {
        +            backgroundColor: 'white',
        +            borderWidth: 0,
        +            gridLineColor: 'black',
        +            gridLineWidth: 2,
        +            borderColor: 'black'
        +        },
        +        series: [
        +            {color: 'red', highlightColors: ['aqua', 'black', 'blue', 'fuchsia', 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'purple', 'red', 'silver', 'teal', 'white', 'yellow']},
        +            {color: 'green', highlightColors: []},
        +            {color: 'blue', highlightColors: []},
        +            {color: 'yellow', highlightColors: 'rgb(255, 245, 185)'}
        +        ],
        +        legend: {
        +            background: 'white',
        +            textColor: 'black',
        +            fontFamily: 'Times New Roman',
        +            border: '1px solid black'
        +        }
        +    };
        +    
        +    plot2.themeEngine.newTheme('oldstyle', oldstyle);
        +
        + +
        + +

        Select theme for bar chart: + +

        + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/trendlineDragableCustomization.html b/phpgwapi/js/jquery/jqplot/examples/trendlineDragableCustomization.html new file mode 100644 index 0000000000..6c51b847ad --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/trendlineDragableCustomization.html @@ -0,0 +1,82 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + +
        +
        + + diff --git a/phpgwapi/js/jquery/jqplot/examples/ui.html b/phpgwapi/js/jquery/jqplot/examples/ui.html new file mode 100644 index 0000000000..e8dff6d3b7 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/ui.html @@ -0,0 +1,191 @@ + + + + + + Error Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

        This page demonstrates placing plots within jQuery UI widgets. Tab 2 and tab 3 contain plots. Using a combination of alternate sizing specification and the jqplot "replot" method the plots are properly displayed when their containers are shown.

        + +

        The alternate sizing specifications for setting plot height and width are needed because a hidden element (or child of a hidden element) has no size. The first example in tab 2 uses custom "data-height" and "data-width" attributes on the plot target element. The second example uses "width" and "height" properties specified on the options object passed into the $.jqplot() function.

        + +

        The default plot size is 300px wide by 400px high. The default setting can be overridden by specifying different values to the $.jqplot.config.defaultHeight and $.jqplot.config.defaultWidth properties. Height and width values are taken in this order of precedence: +

        + +
          +
        1. The css properties of the plot target if available (not available with display:none;).
        2. +
        3. Options object passed into the $.jqplot() function.
        4. +
        5. Custom data-height and data-width attributes on the plot target.
        6. +
        7. The config defaults.
        8. +
        + +
        + +
        + Tabs 2 and 3 have plots. Since tabs 2 and 3 are initially inactive, their contents (and the plots) are initially hidden. +
        + +
        +

        This plot was in an initially hidden container. It's hieght and width are set by the "data-height" and "data-width" properties of the plot container.

        +
        +
        + +
        +

        This plot is in an initially hidden container. It's height and width are set by the 'height' and 'width' properties of the options object passed into the plot constructor.

        +
        +
        + +
        + +

        In the accordion below, section 2 contains a plot. Sizing plots in hidden accordion sections is very similar to sizing in a tab widget. Because of the default animation on accordions, however, the plot will not draw itself until the entire accordion panel is shown.

        + +
        + +

        Section 1

        +
        + Here is section 1 there is no plot. Section 2 has a plot that will display once the section is completely shown. +
        + +

        Section 2

        +
        +

        + This plot also has it's height and width set with the data-height and data-width attributes. Note, if you want the accordion widget to properly size itself before the plot is shown, you must also specify a css height and width on the plot target. +

        +
        +
        + +
        + +

        Code for generating the plots follows. It is critical to bind the callback to the UI widgets "show" or "change" method which calls the plots "replot" method. Without this, the plot won't properly redraw itself when it's container becomes visible.

        + +

        + Note in the ui.index and plot._drawCount properties in the tabsshow callback. ui.index gives the index of the activated tab. plot._drawCount keeps track of how many times the plot was visibly drawn (or redrawn/replotted). Generally, replot only needs to be called the first time the plot is visibly drawn, hence the check for plot._drawCount == 0. +

        + + + diff --git a/phpgwapi/js/jquery/jqplot/examples/verticalLine.html b/phpgwapi/js/jquery/jqplot/examples/verticalLine.html new file mode 100644 index 0000000000..ef18632475 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/verticalLine.html @@ -0,0 +1,51 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/waterfall.html b/phpgwapi/js/jquery/jqplot/examples/waterfall.html new file mode 100644 index 0000000000..9eba1ec935 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/waterfall.html @@ -0,0 +1,134 @@ + + + + + + Waterfall Chart + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

        Waterfall chart using default bar colors.

        +
        +
        
        +    

        Waterfall chart using custom colors and "useNegativeColors" set to "false".

        +
        +
        
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/waterfall2.html b/phpgwapi/js/jquery/jqplot/examples/waterfall2.html
        new file mode 100644
        index 0000000000..ea494dcef4
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/waterfall2.html
        @@ -0,0 +1,204 @@
        +
        +
        +
        +
        +  
        +  Waterfall Chart
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +  
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +  
        +     
        +  
        +  
        +
        +    
        +
        
        +    
        +
        
        +    
        +
        
        +    
        +
        
        +  
        +
        \ No newline at end of file
        diff --git a/phpgwapi/js/jquery/jqplot/examples/zoom1.html b/phpgwapi/js/jquery/jqplot/examples/zoom1.html
        new file mode 100644
        index 0000000000..dcbc586b35
        --- /dev/null
        +++ b/phpgwapi/js/jquery/jqplot/examples/zoom1.html
        @@ -0,0 +1,148 @@
        +
        +
        +
        +
        +  
        +  
        +  
        +  
        +  
        +  
        +
        +  
        +  
        +  
        +  
        +  
        +  
        +	
        +	
        +	
        +	
        +		
        +
        +
        +
        +
        +
        + + + +
        + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/zoom2.html b/phpgwapi/js/jquery/jqplot/examples/zoom2.html new file mode 100644 index 0000000000..45e92f3598 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/zoom2.html @@ -0,0 +1,71 @@ + + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + +
        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/zoom3.html b/phpgwapi/js/jquery/jqplot/examples/zoom3.html new file mode 100644 index 0000000000..17bf46674b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/zoom3.html @@ -0,0 +1,67 @@ + + + + + Zoom plugin with multiple Y Axes + + + + + + + + + + + + + + + + + + + +

        Click and drag to zoom. Double click on plot or click "Reset Zoom" button to reset zoom.

        +
        +
        + +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/zoom4.html b/phpgwapi/js/jquery/jqplot/examples/zoom4.html new file mode 100644 index 0000000000..8880300c44 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/zoom4.html @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/zoomOptions.html b/phpgwapi/js/jquery/jqplot/examples/zoomOptions.html new file mode 100644 index 0000000000..42177d6b00 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/zoomOptions.html @@ -0,0 +1,99 @@ + + + + + Simple Test + + + + + + + + + + + + + + + + + + + + + + + +

        Zooming has been enhanced to maintain plot zoom while the mouse moves over the entire document, not just the plot. Two new options have been added to the cursor plugin to further enhance zooming:

        + +
        +
        constrainOutsideZoom
        +
        True to limit the resulting zoom area to the edges of grid, even if the cursor is outside of the grid. That is, you can't expand the axis ranges by moving the cursor outside of the plot area when this is true. If set to false, you can effectively zoom out by mousing outside of the plot region. Default false.
        +
        showTooltipOutsideZoom
        +
        True to keep showing and updating the tooltip even when the cursor is outside of the plot area. Not applicable if zoomOutsidePlot is false. Default false
        +
        + +

        The fist plot demonstrates the default functionality where you can move the mouse off of the plot while zooming but the actual area zoomed will not extend beyond the axes.

        +
        +
        + +

        The second plot sets constrainOutsideZoom to false, so zooming will not only function when the mouse is outside of the plot, but the zoom range will be extended to the mouse position outside of the grid.

        +
        +
        + +

        The third plot is like the third, but showTooltipOutsideZoom is true and the tooltip is set to follow the mouse, so you have an idea of what your range is while zooming.

        +
        +
        + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/examples/zoomProxy.html b/phpgwapi/js/jquery/jqplot/examples/zoomProxy.html new file mode 100644 index 0000000000..e0faa551e4 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/examples/zoomProxy.html @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + +
        +
        + + + + + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/excanvas.js b/phpgwapi/js/jquery/jqplot/excanvas.js new file mode 100644 index 0000000000..f3b70f470d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/excanvas.js @@ -0,0 +1,1434 @@ +// Memory Leaks patch from http://explorercanvas.googlecode.com/svn/trunk/ +// svn : r73 +// ------------------------------------------------------------------ +// Copyright 2006 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// Known Issues: +// +// * Patterns only support repeat. +// * Radial gradient are not implemented. The VML version of these look very +// different from the canvas one. +// * Clipping paths are not implemented. +// * Coordsize. The width and height attribute have higher priority than the +// width and height style values which isn't correct. +// * Painting mode isn't implemented. +// * Canvas width/height should is using content-box by default. IE in +// Quirks mode will draw the canvas using border-box. Either change your +// doctype to HTML5 +// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype) +// or use Box Sizing Behavior from WebFX +// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html) +// * Non uniform scaling does not correctly scale strokes. +// * Optimize. There is always room for speed improvements. + +// Only add this code if we do not already have a canvas implementation +if (!document.createElement('canvas').getContext) { + +(function() { + + // alias some functions to make (compiled) code shorter + var m = Math; + var mr = m.round; + var ms = m.sin; + var mc = m.cos; + var abs = m.abs; + var sqrt = m.sqrt; + + // this is used for sub pixel precision + var Z = 10; + var Z2 = Z / 2; + + var IE_VERSION = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1]; + + /** + * This funtion is assigned to the elements as element.getContext(). + * @this {HTMLElement} + * @return {CanvasRenderingContext2D_} + */ + function getContext() { + return this.context_ || + (this.context_ = new CanvasRenderingContext2D_(this)); + } + + var slice = Array.prototype.slice; + + /** + * Binds a function to an object. The returned function will always use the + * passed in {@code obj} as {@code this}. + * + * Example: + * + * g = bind(f, obj, a, b) + * g(c, d) // will do f.call(obj, a, b, c, d) + * + * @param {Function} f The function to bind the object to + * @param {Object} obj The object that should act as this when the function + * is called + * @param {*} var_args Rest arguments that will be used as the initial + * arguments when the function is called + * @return {Function} A new function that has bound this + */ + function bind(f, obj, var_args) { + var a = slice.call(arguments, 2); + return function() { + return f.apply(obj, a.concat(slice.call(arguments))); + }; + } + + function encodeHtmlAttribute(s) { + return String(s).replace(/&/g, '&').replace(/"/g, '"'); + } + + function addNamespace(doc, prefix, urn) { + if (!doc.namespaces[prefix]) { + doc.namespaces.add(prefix, urn, '#default#VML'); + } + } + + function addNamespacesAndStylesheet(doc) { + addNamespace(doc, 'g_vml_', 'urn:schemas-microsoft-com:vml'); + addNamespace(doc, 'g_o_', 'urn:schemas-microsoft-com:office:office'); + + // Setup default CSS. Only add one style sheet per document + if (!doc.styleSheets['ex_canvas_']) { + var ss = doc.createStyleSheet(); + ss.owningElement.id = 'ex_canvas_'; + ss.cssText = 'canvas{display:inline-block;overflow:hidden;' + + // default size is 300x150 in Gecko and Opera + 'text-align:left;width:300px;height:150px}'; + } + } + + // Add namespaces and stylesheet at startup. + addNamespacesAndStylesheet(document); + + var G_vmlCanvasManager_ = { + init: function(opt_doc) { + var doc = opt_doc || document; + // Create a dummy element so that IE will allow canvas elements to be + // recognized. + doc.createElement('canvas'); + doc.attachEvent('onreadystatechange', bind(this.init_, this, doc)); + }, + + init_: function(doc) { + // find all canvas elements + var els = doc.getElementsByTagName('canvas'); + for (var i = 0; i < els.length; i++) { + this.initElement(els[i]); + } + }, + + /** + * Public initializes a canvas element so that it can be used as canvas + * element from now on. This is called automatically before the page is + * loaded but if you are creating elements using createElement you need to + * make sure this is called on the element. + * @param {HTMLElement} el The canvas element to initialize. + * @return {HTMLElement} the element that was created. + */ + initElement: function(el) { + if (!el.getContext) { + el.getContext = getContext; + + // Add namespaces and stylesheet to document of the element. + addNamespacesAndStylesheet(el.ownerDocument); + + // Remove fallback content. There is no way to hide text nodes so we + // just remove all childNodes. We could hide all elements and remove + // text nodes but who really cares about the fallback content. + el.innerHTML = ''; + + // do not use inline function because that will leak memory + el.attachEvent('onpropertychange', onPropertyChange); + el.attachEvent('onresize', onResize); + + var attrs = el.attributes; + if (attrs.width && attrs.width.specified) { + // TODO: use runtimeStyle and coordsize + // el.getContext().setWidth_(attrs.width.nodeValue); + el.style.width = attrs.width.nodeValue + 'px'; + } else { + el.width = el.clientWidth; + } + if (attrs.height && attrs.height.specified) { + // TODO: use runtimeStyle and coordsize + // el.getContext().setHeight_(attrs.height.nodeValue); + el.style.height = attrs.height.nodeValue + 'px'; + } else { + el.height = el.clientHeight; + } + //el.getContext().setCoordsize_() + } + return el; + }, + + // Memory Leaks patch : see http://code.google.com/p/explorercanvas/issues/detail?id=82 + uninitElement: function(el){ + if (el.getContext) { + var ctx = el.getContext(); + delete ctx.element_; + delete ctx.canvas; + el.innerHTML = ""; + //el.outerHTML = ""; + el.context_ = null; + el.getContext = null; + el.detachEvent("onpropertychange", onPropertyChange); + el.detachEvent("onresize", onResize); + } + } + }; + + function onPropertyChange(e) { + var el = e.srcElement; + + switch (e.propertyName) { + case 'width': + el.getContext().clearRect(); + el.style.width = el.attributes.width.nodeValue + 'px'; + // In IE8 this does not trigger onresize. + el.firstChild.style.width = el.clientWidth + 'px'; + break; + case 'height': + el.getContext().clearRect(); + el.style.height = el.attributes.height.nodeValue + 'px'; + el.firstChild.style.height = el.clientHeight + 'px'; + break; + } + } + + function onResize(e) { + var el = e.srcElement; + if (el.firstChild) { + el.firstChild.style.width = el.clientWidth + 'px'; + el.firstChild.style.height = el.clientHeight + 'px'; + } + } + + G_vmlCanvasManager_.init(); + + // precompute "00" to "FF" + var decToHex = []; + for (var i = 0; i < 16; i++) { + for (var j = 0; j < 16; j++) { + decToHex[i * 16 + j] = i.toString(16) + j.toString(16); + } + } + + function createMatrixIdentity() { + return [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1] + ]; + } + + function matrixMultiply(m1, m2) { + var result = createMatrixIdentity(); + + for (var x = 0; x < 3; x++) { + for (var y = 0; y < 3; y++) { + var sum = 0; + + for (var z = 0; z < 3; z++) { + sum += m1[x][z] * m2[z][y]; + } + + result[x][y] = sum; + } + } + return result; + } + + function copyState(o1, o2) { + o2.fillStyle = o1.fillStyle; + o2.lineCap = o1.lineCap; + o2.lineJoin = o1.lineJoin; + o2.lineWidth = o1.lineWidth; + o2.miterLimit = o1.miterLimit; + o2.shadowBlur = o1.shadowBlur; + o2.shadowColor = o1.shadowColor; + o2.shadowOffsetX = o1.shadowOffsetX; + o2.shadowOffsetY = o1.shadowOffsetY; + o2.strokeStyle = o1.strokeStyle; + o2.globalAlpha = o1.globalAlpha; + o2.font = o1.font; + o2.textAlign = o1.textAlign; + o2.textBaseline = o1.textBaseline; + o2.arcScaleX_ = o1.arcScaleX_; + o2.arcScaleY_ = o1.arcScaleY_; + o2.lineScale_ = o1.lineScale_; + } + + var colorData = { + aliceblue: '#F0F8FF', + antiquewhite: '#FAEBD7', + aquamarine: '#7FFFD4', + azure: '#F0FFFF', + beige: '#F5F5DC', + bisque: '#FFE4C4', + black: '#000000', + blanchedalmond: '#FFEBCD', + blueviolet: '#8A2BE2', + brown: '#A52A2A', + burlywood: '#DEB887', + cadetblue: '#5F9EA0', + chartreuse: '#7FFF00', + chocolate: '#D2691E', + coral: '#FF7F50', + cornflowerblue: '#6495ED', + cornsilk: '#FFF8DC', + crimson: '#DC143C', + cyan: '#00FFFF', + darkblue: '#00008B', + darkcyan: '#008B8B', + darkgoldenrod: '#B8860B', + darkgray: '#A9A9A9', + darkgreen: '#006400', + darkgrey: '#A9A9A9', + darkkhaki: '#BDB76B', + darkmagenta: '#8B008B', + darkolivegreen: '#556B2F', + darkorange: '#FF8C00', + darkorchid: '#9932CC', + darkred: '#8B0000', + darksalmon: '#E9967A', + darkseagreen: '#8FBC8F', + darkslateblue: '#483D8B', + darkslategray: '#2F4F4F', + darkslategrey: '#2F4F4F', + darkturquoise: '#00CED1', + darkviolet: '#9400D3', + deeppink: '#FF1493', + deepskyblue: '#00BFFF', + dimgray: '#696969', + dimgrey: '#696969', + dodgerblue: '#1E90FF', + firebrick: '#B22222', + floralwhite: '#FFFAF0', + forestgreen: '#228B22', + gainsboro: '#DCDCDC', + ghostwhite: '#F8F8FF', + gold: '#FFD700', + goldenrod: '#DAA520', + grey: '#808080', + greenyellow: '#ADFF2F', + honeydew: '#F0FFF0', + hotpink: '#FF69B4', + indianred: '#CD5C5C', + indigo: '#4B0082', + ivory: '#FFFFF0', + khaki: '#F0E68C', + lavender: '#E6E6FA', + lavenderblush: '#FFF0F5', + lawngreen: '#7CFC00', + lemonchiffon: '#FFFACD', + lightblue: '#ADD8E6', + lightcoral: '#F08080', + lightcyan: '#E0FFFF', + lightgoldenrodyellow: '#FAFAD2', + lightgreen: '#90EE90', + lightgrey: '#D3D3D3', + lightpink: '#FFB6C1', + lightsalmon: '#FFA07A', + lightseagreen: '#20B2AA', + lightskyblue: '#87CEFA', + lightslategray: '#778899', + lightslategrey: '#778899', + lightsteelblue: '#B0C4DE', + lightyellow: '#FFFFE0', + limegreen: '#32CD32', + linen: '#FAF0E6', + magenta: '#FF00FF', + mediumaquamarine: '#66CDAA', + mediumblue: '#0000CD', + mediumorchid: '#BA55D3', + mediumpurple: '#9370DB', + mediumseagreen: '#3CB371', + mediumslateblue: '#7B68EE', + mediumspringgreen: '#00FA9A', + mediumturquoise: '#48D1CC', + mediumvioletred: '#C71585', + midnightblue: '#191970', + mintcream: '#F5FFFA', + mistyrose: '#FFE4E1', + moccasin: '#FFE4B5', + navajowhite: '#FFDEAD', + oldlace: '#FDF5E6', + olivedrab: '#6B8E23', + orange: '#FFA500', + orangered: '#FF4500', + orchid: '#DA70D6', + palegoldenrod: '#EEE8AA', + palegreen: '#98FB98', + paleturquoise: '#AFEEEE', + palevioletred: '#DB7093', + papayawhip: '#FFEFD5', + peachpuff: '#FFDAB9', + peru: '#CD853F', + pink: '#FFC0CB', + plum: '#DDA0DD', + powderblue: '#B0E0E6', + rosybrown: '#BC8F8F', + royalblue: '#4169E1', + saddlebrown: '#8B4513', + salmon: '#FA8072', + sandybrown: '#F4A460', + seagreen: '#2E8B57', + seashell: '#FFF5EE', + sienna: '#A0522D', + skyblue: '#87CEEB', + slateblue: '#6A5ACD', + slategray: '#708090', + slategrey: '#708090', + snow: '#FFFAFA', + springgreen: '#00FF7F', + steelblue: '#4682B4', + tan: '#D2B48C', + thistle: '#D8BFD8', + tomato: '#FF6347', + turquoise: '#40E0D0', + violet: '#EE82EE', + wheat: '#F5DEB3', + whitesmoke: '#F5F5F5', + yellowgreen: '#9ACD32' + }; + + + function getRgbHslContent(styleString) { + var start = styleString.indexOf('(', 3); + var end = styleString.indexOf(')', start + 1); + var parts = styleString.substring(start + 1, end).split(','); + // add alpha if needed + if (parts.length != 4 || styleString.charAt(3) != 'a') { + parts[3] = 1; + } + return parts; + } + + function percent(s) { + return parseFloat(s) / 100; + } + + function clamp(v, min, max) { + return Math.min(max, Math.max(min, v)); + } + + function hslToRgb(parts){ + var r, g, b, h, s, l; + h = parseFloat(parts[0]) / 360 % 360; + if (h < 0) + h++; + s = clamp(percent(parts[1]), 0, 1); + l = clamp(percent(parts[2]), 0, 1); + if (s == 0) { + r = g = b = l; // achromatic + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hueToRgb(p, q, h + 1 / 3); + g = hueToRgb(p, q, h); + b = hueToRgb(p, q, h - 1 / 3); + } + + return '#' + decToHex[Math.floor(r * 255)] + + decToHex[Math.floor(g * 255)] + + decToHex[Math.floor(b * 255)]; + } + + function hueToRgb(m1, m2, h) { + if (h < 0) + h++; + if (h > 1) + h--; + + if (6 * h < 1) + return m1 + (m2 - m1) * 6 * h; + else if (2 * h < 1) + return m2; + else if (3 * h < 2) + return m1 + (m2 - m1) * (2 / 3 - h) * 6; + else + return m1; + } + + var processStyleCache = {}; + + function processStyle(styleString) { + if (styleString in processStyleCache) { + return processStyleCache[styleString]; + } + + var str, alpha = 1; + + styleString = String(styleString); + if (styleString.charAt(0) == '#') { + str = styleString; + } else if (/^rgb/.test(styleString)) { + var parts = getRgbHslContent(styleString); + var str = '#', n; + for (var i = 0; i < 3; i++) { + if (parts[i].indexOf('%') != -1) { + n = Math.floor(percent(parts[i]) * 255); + } else { + n = +parts[i]; + } + str += decToHex[clamp(n, 0, 255)]; + } + alpha = +parts[3]; + } else if (/^hsl/.test(styleString)) { + var parts = getRgbHslContent(styleString); + str = hslToRgb(parts); + alpha = parts[3]; + } else { + str = colorData[styleString] || styleString; + } + return processStyleCache[styleString] = {color: str, alpha: alpha}; + } + + var DEFAULT_STYLE = { + style: 'normal', + variant: 'normal', + weight: 'normal', + size: 10, + family: 'sans-serif' + }; + + // Internal text style cache + var fontStyleCache = {}; + + function processFontStyle(styleString) { + if (fontStyleCache[styleString]) { + return fontStyleCache[styleString]; + } + + var el = document.createElement('div'); + var style = el.style; + try { + style.font = styleString; + } catch (ex) { + // Ignore failures to set to invalid font. + } + + return fontStyleCache[styleString] = { + style: style.fontStyle || DEFAULT_STYLE.style, + variant: style.fontVariant || DEFAULT_STYLE.variant, + weight: style.fontWeight || DEFAULT_STYLE.weight, + size: style.fontSize || DEFAULT_STYLE.size, + family: style.fontFamily || DEFAULT_STYLE.family + }; + } + + function getComputedStyle(style, element) { + var computedStyle = {}; + + for (var p in style) { + computedStyle[p] = style[p]; + } + + // Compute the size + var canvasFontSize = parseFloat(element.currentStyle.fontSize), + fontSize = parseFloat(style.size); + + if (typeof style.size == 'number') { + computedStyle.size = style.size; + } else if (style.size.indexOf('px') != -1) { + computedStyle.size = fontSize; + } else if (style.size.indexOf('em') != -1) { + computedStyle.size = canvasFontSize * fontSize; + } else if(style.size.indexOf('%') != -1) { + computedStyle.size = (canvasFontSize / 100) * fontSize; + } else if (style.size.indexOf('pt') != -1) { + computedStyle.size = fontSize / .75; + } else { + computedStyle.size = canvasFontSize; + } + + // Different scaling between normal text and VML text. This was found using + // trial and error to get the same size as non VML text. + computedStyle.size *= 0.981; + + return computedStyle; + } + + function buildStyle(style) { + return style.style + ' ' + style.variant + ' ' + style.weight + ' ' + + style.size + 'px ' + style.family; + } + + var lineCapMap = { + 'butt': 'flat', + 'round': 'round' + }; + + function processLineCap(lineCap) { + return lineCapMap[lineCap] || 'square'; + } + + /** + * This class implements CanvasRenderingContext2D interface as described by + * the WHATWG. + * @param {HTMLElement} canvasElement The element that the 2D context should + * be associated with + */ + function CanvasRenderingContext2D_(canvasElement) { + this.m_ = createMatrixIdentity(); + + this.mStack_ = []; + this.aStack_ = []; + this.currentPath_ = []; + + // Canvas context properties + this.strokeStyle = '#000'; + this.fillStyle = '#000'; + + this.lineWidth = 1; + this.lineJoin = 'miter'; + this.lineCap = 'butt'; + this.miterLimit = Z * 1; + this.globalAlpha = 1; + this.font = '10px sans-serif'; + this.textAlign = 'left'; + this.textBaseline = 'alphabetic'; + this.canvas = canvasElement; + + var cssText = 'width:' + canvasElement.clientWidth + 'px;height:' + + canvasElement.clientHeight + 'px;overflow:hidden;position:absolute'; + var el = canvasElement.ownerDocument.createElement('div'); + el.style.cssText = cssText; + canvasElement.appendChild(el); + + var overlayEl = el.cloneNode(false); + // Use a non transparent background. + overlayEl.style.backgroundColor = 'red'; + overlayEl.style.filter = 'alpha(opacity=0)'; + canvasElement.appendChild(overlayEl); + + this.element_ = el; + this.arcScaleX_ = 1; + this.arcScaleY_ = 1; + this.lineScale_ = 1; + } + + var contextPrototype = CanvasRenderingContext2D_.prototype; + contextPrototype.clearRect = function() { + if (this.textMeasureEl_) { + this.textMeasureEl_.removeNode(true); + this.textMeasureEl_ = null; + } + this.element_.innerHTML = ''; + }; + + contextPrototype.beginPath = function() { + // TODO: Branch current matrix so that save/restore has no effect + // as per safari docs. + this.currentPath_ = []; + }; + + contextPrototype.moveTo = function(aX, aY) { + var p = getCoords(this, aX, aY); + this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y}); + this.currentX_ = p.x; + this.currentY_ = p.y; + }; + + contextPrototype.lineTo = function(aX, aY) { + var p = getCoords(this, aX, aY); + this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y}); + + this.currentX_ = p.x; + this.currentY_ = p.y; + }; + + contextPrototype.bezierCurveTo = function(aCP1x, aCP1y, + aCP2x, aCP2y, + aX, aY) { + var p = getCoords(this, aX, aY); + var cp1 = getCoords(this, aCP1x, aCP1y); + var cp2 = getCoords(this, aCP2x, aCP2y); + bezierCurveTo(this, cp1, cp2, p); + }; + + // Helper function that takes the already fixed cordinates. + function bezierCurveTo(self, cp1, cp2, p) { + self.currentPath_.push({ + type: 'bezierCurveTo', + cp1x: cp1.x, + cp1y: cp1.y, + cp2x: cp2.x, + cp2y: cp2.y, + x: p.x, + y: p.y + }); + self.currentX_ = p.x; + self.currentY_ = p.y; + } + + contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) { + // the following is lifted almost directly from + // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes + + var cp = getCoords(this, aCPx, aCPy); + var p = getCoords(this, aX, aY); + + var cp1 = { + x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_), + y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_) + }; + var cp2 = { + x: cp1.x + (p.x - this.currentX_) / 3.0, + y: cp1.y + (p.y - this.currentY_) / 3.0 + }; + + bezierCurveTo(this, cp1, cp2, p); + }; + + contextPrototype.arc = function(aX, aY, aRadius, + aStartAngle, aEndAngle, aClockwise) { + aRadius *= Z; + var arcType = aClockwise ? 'at' : 'wa'; + + var xStart = aX + mc(aStartAngle) * aRadius - Z2; + var yStart = aY + ms(aStartAngle) * aRadius - Z2; + + var xEnd = aX + mc(aEndAngle) * aRadius - Z2; + var yEnd = aY + ms(aEndAngle) * aRadius - Z2; + + // IE won't render arches drawn counter clockwise if xStart == xEnd. + if (xStart == xEnd && !aClockwise) { + xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something + // that can be represented in binary + } + + var p = getCoords(this, aX, aY); + var pStart = getCoords(this, xStart, yStart); + var pEnd = getCoords(this, xEnd, yEnd); + + this.currentPath_.push({type: arcType, + x: p.x, + y: p.y, + radius: aRadius, + xStart: pStart.x, + yStart: pStart.y, + xEnd: pEnd.x, + yEnd: pEnd.y}); + + }; + + contextPrototype.rect = function(aX, aY, aWidth, aHeight) { + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + }; + + contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) { + var oldPath = this.currentPath_; + this.beginPath(); + + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + this.stroke(); + + this.currentPath_ = oldPath; + }; + + contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) { + var oldPath = this.currentPath_; + this.beginPath(); + + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + this.fill(); + + this.currentPath_ = oldPath; + }; + + contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) { + var gradient = new CanvasGradient_('gradient'); + gradient.x0_ = aX0; + gradient.y0_ = aY0; + gradient.x1_ = aX1; + gradient.y1_ = aY1; + return gradient; + }; + + contextPrototype.createRadialGradient = function(aX0, aY0, aR0, + aX1, aY1, aR1) { + var gradient = new CanvasGradient_('gradientradial'); + gradient.x0_ = aX0; + gradient.y0_ = aY0; + gradient.r0_ = aR0; + gradient.x1_ = aX1; + gradient.y1_ = aY1; + gradient.r1_ = aR1; + return gradient; + }; + + contextPrototype.drawImage = function(image, var_args) { + var dx, dy, dw, dh, sx, sy, sw, sh; + + // to find the original width we overide the width and height + var oldRuntimeWidth = image.runtimeStyle.width; + var oldRuntimeHeight = image.runtimeStyle.height; + image.runtimeStyle.width = 'auto'; + image.runtimeStyle.height = 'auto'; + + // get the original size + var w = image.width; + var h = image.height; + + // and remove overides + image.runtimeStyle.width = oldRuntimeWidth; + image.runtimeStyle.height = oldRuntimeHeight; + + if (arguments.length == 3) { + dx = arguments[1]; + dy = arguments[2]; + sx = sy = 0; + sw = dw = w; + sh = dh = h; + } else if (arguments.length == 5) { + dx = arguments[1]; + dy = arguments[2]; + dw = arguments[3]; + dh = arguments[4]; + sx = sy = 0; + sw = w; + sh = h; + } else if (arguments.length == 9) { + sx = arguments[1]; + sy = arguments[2]; + sw = arguments[3]; + sh = arguments[4]; + dx = arguments[5]; + dy = arguments[6]; + dw = arguments[7]; + dh = arguments[8]; + } else { + throw Error('Invalid number of arguments'); + } + + var d = getCoords(this, dx, dy); + + var w2 = sw / 2; + var h2 = sh / 2; + + var vmlStr = []; + + var W = 10; + var H = 10; + + // For some reason that I've now forgotten, using divs didn't work + vmlStr.push(' ' , + '', + ''); + + this.element_.insertAdjacentHTML('BeforeEnd', vmlStr.join('')); + }; + + contextPrototype.stroke = function(aFill) { + var lineStr = []; + var lineOpen = false; + + var W = 10; + var H = 10; + + lineStr.push(''); + + if (!aFill) { + appendStroke(this, lineStr); + } else { + appendFill(this, lineStr, min, max); + } + + lineStr.push(''); + + this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); + }; + + function appendStroke(ctx, lineStr) { + var a = processStyle(ctx.strokeStyle); + var color = a.color; + var opacity = a.alpha * ctx.globalAlpha; + var lineWidth = ctx.lineScale_ * ctx.lineWidth; + + // VML cannot correctly render a line if the width is less than 1px. + // In that case, we dilute the color to make the line look thinner. + if (lineWidth < 1) { + opacity *= lineWidth; + } + + lineStr.push( + '' + ); + } + + function appendFill(ctx, lineStr, min, max) { + var fillStyle = ctx.fillStyle; + var arcScaleX = ctx.arcScaleX_; + var arcScaleY = ctx.arcScaleY_; + var width = max.x - min.x; + var height = max.y - min.y; + if (fillStyle instanceof CanvasGradient_) { + // TODO: Gradients transformed with the transformation matrix. + var angle = 0; + var focus = {x: 0, y: 0}; + + // additional offset + var shift = 0; + // scale factor for offset + var expansion = 1; + + if (fillStyle.type_ == 'gradient') { + var x0 = fillStyle.x0_ / arcScaleX; + var y0 = fillStyle.y0_ / arcScaleY; + var x1 = fillStyle.x1_ / arcScaleX; + var y1 = fillStyle.y1_ / arcScaleY; + var p0 = getCoords(ctx, x0, y0); + var p1 = getCoords(ctx, x1, y1); + var dx = p1.x - p0.x; + var dy = p1.y - p0.y; + angle = Math.atan2(dx, dy) * 180 / Math.PI; + + // The angle should be a non-negative number. + if (angle < 0) { + angle += 360; + } + + // Very small angles produce an unexpected result because they are + // converted to a scientific notation string. + if (angle < 1e-6) { + angle = 0; + } + } else { + var p0 = getCoords(ctx, fillStyle.x0_, fillStyle.y0_); + focus = { + x: (p0.x - min.x) / width, + y: (p0.y - min.y) / height + }; + + width /= arcScaleX * Z; + height /= arcScaleY * Z; + var dimension = m.max(width, height); + shift = 2 * fillStyle.r0_ / dimension; + expansion = 2 * fillStyle.r1_ / dimension - shift; + } + + // We need to sort the color stops in ascending order by offset, + // otherwise IE won't interpret it correctly. + var stops = fillStyle.colors_; + stops.sort(function(cs1, cs2) { + return cs1.offset - cs2.offset; + }); + + var length = stops.length; + var color1 = stops[0].color; + var color2 = stops[length - 1].color; + var opacity1 = stops[0].alpha * ctx.globalAlpha; + var opacity2 = stops[length - 1].alpha * ctx.globalAlpha; + + var colors = []; + for (var i = 0; i < length; i++) { + var stop = stops[i]; + colors.push(stop.offset * expansion + shift + ' ' + stop.color); + } + + // When colors attribute is used, the meanings of opacity and o:opacity2 + // are reversed. + lineStr.push(''); + } else if (fillStyle instanceof CanvasPattern_) { + if (width && height) { + var deltaLeft = -min.x; + var deltaTop = -min.y; + lineStr.push(''); + } + } else { + var a = processStyle(ctx.fillStyle); + var color = a.color; + var opacity = a.alpha * ctx.globalAlpha; + lineStr.push(''); + } + } + + contextPrototype.fill = function() { + this.stroke(true); + }; + + contextPrototype.closePath = function() { + this.currentPath_.push({type: 'close'}); + }; + + function getCoords(ctx, aX, aY) { + var m = ctx.m_; + return { + x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2, + y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2 + }; + }; + + contextPrototype.save = function() { + var o = {}; + copyState(this, o); + this.aStack_.push(o); + this.mStack_.push(this.m_); + this.m_ = matrixMultiply(createMatrixIdentity(), this.m_); + }; + + contextPrototype.restore = function() { + if (this.aStack_.length) { + copyState(this.aStack_.pop(), this); + this.m_ = this.mStack_.pop(); + } + }; + + function matrixIsFinite(m) { + return isFinite(m[0][0]) && isFinite(m[0][1]) && + isFinite(m[1][0]) && isFinite(m[1][1]) && + isFinite(m[2][0]) && isFinite(m[2][1]); + } + + function setM(ctx, m, updateLineScale) { + if (!matrixIsFinite(m)) { + return; + } + ctx.m_ = m; + + if (updateLineScale) { + // Get the line scale. + // Determinant of this.m_ means how much the area is enlarged by the + // transformation. So its square root can be used as a scale factor + // for width. + var det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; + ctx.lineScale_ = sqrt(abs(det)); + } + } + + contextPrototype.translate = function(aX, aY) { + var m1 = [ + [1, 0, 0], + [0, 1, 0], + [aX, aY, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), false); + }; + + contextPrototype.rotate = function(aRot) { + var c = mc(aRot); + var s = ms(aRot); + + var m1 = [ + [c, s, 0], + [-s, c, 0], + [0, 0, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), false); + }; + + contextPrototype.scale = function(aX, aY) { + this.arcScaleX_ *= aX; + this.arcScaleY_ *= aY; + var m1 = [ + [aX, 0, 0], + [0, aY, 0], + [0, 0, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), true); + }; + + contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) { + var m1 = [ + [m11, m12, 0], + [m21, m22, 0], + [dx, dy, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), true); + }; + + contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) { + var m = [ + [m11, m12, 0], + [m21, m22, 0], + [dx, dy, 1] + ]; + + setM(this, m, true); + }; + + /** + * The text drawing function. + * The maxWidth argument isn't taken in account, since no browser supports + * it yet. + */ + contextPrototype.drawText_ = function(text, x, y, maxWidth, stroke) { + var m = this.m_, + delta = 1000, + left = 0, + right = delta, + offset = {x: 0, y: 0}, + lineStr = []; + + var fontStyle = getComputedStyle(processFontStyle(this.font), + this.element_); + + var fontStyleString = buildStyle(fontStyle); + + var elementStyle = this.element_.currentStyle; + var textAlign = this.textAlign.toLowerCase(); + switch (textAlign) { + case 'left': + case 'center': + case 'right': + break; + case 'end': + textAlign = elementStyle.direction == 'ltr' ? 'right' : 'left'; + break; + case 'start': + textAlign = elementStyle.direction == 'rtl' ? 'right' : 'left'; + break; + default: + textAlign = 'left'; + } + + // 1.75 is an arbitrary number, as there is no info about the text baseline + switch (this.textBaseline) { + case 'hanging': + case 'top': + offset.y = fontStyle.size / 1.75; + break; + case 'middle': + break; + default: + case null: + case 'alphabetic': + case 'ideographic': + case 'bottom': + offset.y = -fontStyle.size / 2.25; + break; + } + + switch(textAlign) { + case 'right': + left = delta; + right = 0.05; + break; + case 'center': + left = right = delta / 2; + break; + } + + var d = getCoords(this, x + offset.x, y + offset.y); + + lineStr.push(''); + + if (stroke) { + appendStroke(this, lineStr); + } else { + // TODO: Fix the min and max params. + appendFill(this, lineStr, {x: -left, y: 0}, + {x: right, y: fontStyle.size}); + } + + var skewM = m[0][0].toFixed(3) + ',' + m[1][0].toFixed(3) + ',' + + m[0][1].toFixed(3) + ',' + m[1][1].toFixed(3) + ',0,0'; + + var skewOffset = mr(d.x / Z) + ',' + mr(d.y / Z); + + lineStr.push('', + '', + ''); + + this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); + }; + + contextPrototype.fillText = function(text, x, y, maxWidth) { + this.drawText_(text, x, y, maxWidth, false); + }; + + contextPrototype.strokeText = function(text, x, y, maxWidth) { + this.drawText_(text, x, y, maxWidth, true); + }; + + contextPrototype.measureText = function(text) { + if (!this.textMeasureEl_) { + var s = ''; + this.element_.insertAdjacentHTML('beforeEnd', s); + this.textMeasureEl_ = this.element_.lastChild; + } + var doc = this.element_.ownerDocument; + this.textMeasureEl_.innerHTML = ''; + this.textMeasureEl_.style.font = this.font; + // Don't use innerHTML or innerText because they allow markup/whitespace. + this.textMeasureEl_.appendChild(doc.createTextNode(text)); + return {width: this.textMeasureEl_.offsetWidth}; + }; + + /******** STUBS ********/ + contextPrototype.clip = function() { + // TODO: Implement + }; + + contextPrototype.arcTo = function() { + // TODO: Implement + }; + + contextPrototype.createPattern = function(image, repetition) { + return new CanvasPattern_(image, repetition); + }; + + // Gradient / Pattern Stubs + function CanvasGradient_(aType) { + this.type_ = aType; + this.x0_ = 0; + this.y0_ = 0; + this.r0_ = 0; + this.x1_ = 0; + this.y1_ = 0; + this.r1_ = 0; + this.colors_ = []; + } + + CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) { + aColor = processStyle(aColor); + this.colors_.push({offset: aOffset, + color: aColor.color, + alpha: aColor.alpha}); + }; + + function CanvasPattern_(image, repetition) { + assertImageIsValid(image); + switch (repetition) { + case 'repeat': + case null: + case '': + this.repetition_ = 'repeat'; + break + case 'repeat-x': + case 'repeat-y': + case 'no-repeat': + this.repetition_ = repetition; + break; + default: + throwException('SYNTAX_ERR'); + } + + this.src_ = image.src; + this.width_ = image.width; + this.height_ = image.height; + } + + function throwException(s) { + throw new DOMException_(s); + } + + function assertImageIsValid(img) { + if (!img || img.nodeType != 1 || img.tagName != 'IMG') { + throwException('TYPE_MISMATCH_ERR'); + } + if (img.readyState != 'complete') { + throwException('INVALID_STATE_ERR'); + } + } + + function DOMException_(s) { + this.code = this[s]; + this.message = s +': DOM Exception ' + this.code; + } + var p = DOMException_.prototype = new Error; + p.INDEX_SIZE_ERR = 1; + p.DOMSTRING_SIZE_ERR = 2; + p.HIERARCHY_REQUEST_ERR = 3; + p.WRONG_DOCUMENT_ERR = 4; + p.INVALID_CHARACTER_ERR = 5; + p.NO_DATA_ALLOWED_ERR = 6; + p.NO_MODIFICATION_ALLOWED_ERR = 7; + p.NOT_FOUND_ERR = 8; + p.NOT_SUPPORTED_ERR = 9; + p.INUSE_ATTRIBUTE_ERR = 10; + p.INVALID_STATE_ERR = 11; + p.SYNTAX_ERR = 12; + p.INVALID_MODIFICATION_ERR = 13; + p.NAMESPACE_ERR = 14; + p.INVALID_ACCESS_ERR = 15; + p.VALIDATION_ERR = 16; + p.TYPE_MISMATCH_ERR = 17; + + // set up externs + G_vmlCanvasManager = G_vmlCanvasManager_; + CanvasRenderingContext2D = CanvasRenderingContext2D_; + CanvasGradient = CanvasGradient_; + CanvasPattern = CanvasPattern_; + DOMException = DOMException_; +})(); + +} // if diff --git a/phpgwapi/js/jquery/jqplot/excanvas.min.js b/phpgwapi/js/jquery/jqplot/excanvas.min.js new file mode 100644 index 0000000000..c8fe662cc2 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/excanvas.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: @VERSION + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +if(!document.createElement("canvas").getContext){(function(){var ab=Math;var n=ab.round;var l=ab.sin;var A=ab.cos;var H=ab.abs;var N=ab.sqrt;var d=10;var f=d/2;var z=+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];function y(){return this.context_||(this.context_=new D(this))}var t=Array.prototype.slice;function g(j,m,p){var i=t.call(arguments,2);return function(){return j.apply(m,i.concat(t.call(arguments)))}}function af(i){return String(i).replace(/&/g,"&").replace(/"/g,""")}function Y(m,j,i){if(!m.namespaces[j]){m.namespaces.add(j,i,"#default#VML")}}function R(j){Y(j,"g_vml_","urn:schemas-microsoft-com:vml");Y(j,"g_o_","urn:schemas-microsoft-com:office:office");if(!j.styleSheets.ex_canvas_){var i=j.createStyleSheet();i.owningElement.id="ex_canvas_";i.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}R(document);var e={init:function(i){var j=i||document;j.createElement("canvas");j.attachEvent("onreadystatechange",g(this.init_,this,j))},init_:function(p){var m=p.getElementsByTagName("canvas");for(var j=0;j1){m--}if(6*m<1){return j+(i-j)*6*m}else{if(2*m<1){return i}else{if(3*m<2){return j+(i-j)*(2/3-m)*6}else{return j}}}}var C={};function F(j){if(j in C){return C[j]}var ag,Z=1;j=String(j);if(j.charAt(0)=="#"){ag=j}else{if(/^rgb/.test(j)){var p=M(j);var ag="#",ah;for(var m=0;m<3;m++){if(p[m].indexOf("%")!=-1){ah=Math.floor(c(p[m])*255)}else{ah=+p[m]}ag+=k[r(ah,0,255)]}Z=+p[3]}else{if(/^hsl/.test(j)){var p=M(j);ag=I(p);Z=p[3]}else{ag=b[j]||j}}}return C[j]={color:ag,alpha:Z}}var o={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var L={};function E(i){if(L[i]){return L[i]}var p=document.createElement("div");var m=p.style;try{m.font=i}catch(j){}return L[i]={style:m.fontStyle||o.style,variant:m.fontVariant||o.variant,weight:m.fontWeight||o.weight,size:m.fontSize||o.size,family:m.fontFamily||o.family}}function u(m,j){var i={};for(var ah in m){i[ah]=m[ah]}var ag=parseFloat(j.currentStyle.fontSize),Z=parseFloat(m.size);if(typeof m.size=="number"){i.size=m.size}else{if(m.size.indexOf("px")!=-1){i.size=Z}else{if(m.size.indexOf("em")!=-1){i.size=ag*Z}else{if(m.size.indexOf("%")!=-1){i.size=(ag/100)*Z}else{if(m.size.indexOf("pt")!=-1){i.size=Z/0.75}else{i.size=ag}}}}}i.size*=0.981;return i}function ac(i){return i.style+" "+i.variant+" "+i.weight+" "+i.size+"px "+i.family}var s={butt:"flat",round:"round"};function S(i){return s[i]||"square"}function D(i){this.m_=B();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=d*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var m="width:"+i.clientWidth+"px;height:"+i.clientHeight+"px;overflow:hidden;position:absolute";var j=i.ownerDocument.createElement("div");j.style.cssText=m;i.appendChild(j);var p=j.cloneNode(false);p.style.backgroundColor="red";p.style.filter="alpha(opacity=0)";i.appendChild(p);this.element_=j;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var q=D.prototype;q.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};q.beginPath=function(){this.currentPath_=[]};q.moveTo=function(j,i){var m=V(this,j,i);this.currentPath_.push({type:"moveTo",x:m.x,y:m.y});this.currentX_=m.x;this.currentY_=m.y};q.lineTo=function(j,i){var m=V(this,j,i);this.currentPath_.push({type:"lineTo",x:m.x,y:m.y});this.currentX_=m.x;this.currentY_=m.y};q.bezierCurveTo=function(m,j,ak,aj,ai,ag){var i=V(this,ai,ag);var ah=V(this,m,j);var Z=V(this,ak,aj);K(this,ah,Z,i)};function K(i,Z,m,j){i.currentPath_.push({type:"bezierCurveTo",cp1x:Z.x,cp1y:Z.y,cp2x:m.x,cp2y:m.y,x:j.x,y:j.y});i.currentX_=j.x;i.currentY_=j.y}q.quadraticCurveTo=function(ai,m,j,i){var ah=V(this,ai,m);var ag=V(this,j,i);var aj={x:this.currentX_+2/3*(ah.x-this.currentX_),y:this.currentY_+2/3*(ah.y-this.currentY_)};var Z={x:aj.x+(ag.x-this.currentX_)/3,y:aj.y+(ag.y-this.currentY_)/3};K(this,aj,Z,ag)};q.arc=function(al,aj,ak,ag,j,m){ak*=d;var ap=m?"at":"wa";var am=al+A(ag)*ak-f;var ao=aj+l(ag)*ak-f;var i=al+A(j)*ak-f;var an=aj+l(j)*ak-f;if(am==i&&!m){am+=0.125}var Z=V(this,al,aj);var ai=V(this,am,ao);var ah=V(this,i,an);this.currentPath_.push({type:ap,x:Z.x,y:Z.y,radius:ak,xStart:ai.x,yStart:ai.y,xEnd:ah.x,yEnd:ah.y})};q.rect=function(m,j,i,p){this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath()};q.strokeRect=function(m,j,i,p){var Z=this.currentPath_;this.beginPath();this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath();this.stroke();this.currentPath_=Z};q.fillRect=function(m,j,i,p){var Z=this.currentPath_;this.beginPath();this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath();this.fill();this.currentPath_=Z};q.createLinearGradient=function(j,p,i,m){var Z=new U("gradient");Z.x0_=j;Z.y0_=p;Z.x1_=i;Z.y1_=m;return Z};q.createRadialGradient=function(p,ag,m,j,Z,i){var ah=new U("gradientradial");ah.x0_=p;ah.y0_=ag;ah.r0_=m;ah.x1_=j;ah.y1_=Z;ah.r1_=i;return ah};q.drawImage=function(aq,m){var aj,ah,al,ay,ao,am,at,aA;var ak=aq.runtimeStyle.width;var ap=aq.runtimeStyle.height;aq.runtimeStyle.width="auto";aq.runtimeStyle.height="auto";var ai=aq.width;var aw=aq.height;aq.runtimeStyle.width=ak;aq.runtimeStyle.height=ap;if(arguments.length==3){aj=arguments[1];ah=arguments[2];ao=am=0;at=al=ai;aA=ay=aw}else{if(arguments.length==5){aj=arguments[1];ah=arguments[2];al=arguments[3];ay=arguments[4];ao=am=0;at=ai;aA=aw}else{if(arguments.length==9){ao=arguments[1];am=arguments[2];at=arguments[3];aA=arguments[4];aj=arguments[5];ah=arguments[6];al=arguments[7];ay=arguments[8]}else{throw Error("Invalid number of arguments")}}}var az=V(this,aj,ah);var p=at/2;var j=aA/2;var ax=[];var i=10;var ag=10;ax.push(" ','","");this.element_.insertAdjacentHTML("BeforeEnd",ax.join(""))};q.stroke=function(al){var aj=[];var Z=false;var m=10;var am=10;aj.push("ak.x){ak.x=j.x}if(ag.y==null||j.yak.y){ak.y=j.y}}}aj.push(' ">');if(!al){w(this,aj)}else{G(this,aj,ag,ak)}aj.push("");this.element_.insertAdjacentHTML("beforeEnd",aj.join(""))};function w(m,ag){var j=F(m.strokeStyle);var p=j.color;var Z=j.alpha*m.globalAlpha;var i=m.lineScale_*m.lineWidth;if(i<1){Z*=i}ag.push("')}function G(aq,ai,aK,ar){var aj=aq.fillStyle;var aB=aq.arcScaleX_;var aA=aq.arcScaleY_;var j=ar.x-aK.x;var p=ar.y-aK.y;if(aj instanceof U){var an=0;var aF={x:0,y:0};var ax=0;var am=1;if(aj.type_=="gradient"){var al=aj.x0_/aB;var m=aj.y0_/aA;var ak=aj.x1_/aB;var aM=aj.y1_/aA;var aJ=V(aq,al,m);var aI=V(aq,ak,aM);var ag=aI.x-aJ.x;var Z=aI.y-aJ.y;an=Math.atan2(ag,Z)*180/Math.PI;if(an<0){an+=360}if(an<0.000001){an=0}}else{var aJ=V(aq,aj.x0_,aj.y0_);aF={x:(aJ.x-aK.x)/j,y:(aJ.y-aK.y)/p};j/=aB*d;p/=aA*d;var aD=ab.max(j,p);ax=2*aj.r0_/aD;am=2*aj.r1_/aD-ax}var av=aj.colors_;av.sort(function(aN,i){return aN.offset-i.offset});var ap=av.length;var au=av[0].color;var at=av[ap-1].color;var az=av[0].alpha*aq.globalAlpha;var ay=av[ap-1].alpha*aq.globalAlpha;var aE=[];for(var aH=0;aH')}else{if(aj instanceof T){if(j&&p){var ah=-aK.x;var aC=-aK.y;ai.push("')}}else{var aL=F(aq.fillStyle);var aw=aL.color;var aG=aL.alpha*aq.globalAlpha;ai.push('')}}}q.fill=function(){this.stroke(true)};q.closePath=function(){this.currentPath_.push({type:"close"})};function V(j,Z,p){var i=j.m_;return{x:d*(Z*i[0][0]+p*i[1][0]+i[2][0])-f,y:d*(Z*i[0][1]+p*i[1][1]+i[2][1])-f}}q.save=function(){var i={};v(this,i);this.aStack_.push(i);this.mStack_.push(this.m_);this.m_=J(B(),this.m_)};q.restore=function(){if(this.aStack_.length){v(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function h(i){return isFinite(i[0][0])&&isFinite(i[0][1])&&isFinite(i[1][0])&&isFinite(i[1][1])&&isFinite(i[2][0])&&isFinite(i[2][1])}function aa(j,i,p){if(!h(i)){return}j.m_=i;if(p){var Z=i[0][0]*i[1][1]-i[0][1]*i[1][0];j.lineScale_=N(H(Z))}}q.translate=function(m,j){var i=[[1,0,0],[0,1,0],[m,j,1]];aa(this,J(i,this.m_),false)};q.rotate=function(j){var p=A(j);var m=l(j);var i=[[p,m,0],[-m,p,0],[0,0,1]];aa(this,J(i,this.m_),false)};q.scale=function(m,j){this.arcScaleX_*=m;this.arcScaleY_*=j;var i=[[m,0,0],[0,j,0],[0,0,1]];aa(this,J(i,this.m_),true)};q.transform=function(Z,p,ah,ag,j,i){var m=[[Z,p,0],[ah,ag,0],[j,i,1]];aa(this,J(m,this.m_),true)};q.setTransform=function(ag,Z,ai,ah,p,j){var i=[[ag,Z,0],[ai,ah,0],[p,j,1]];aa(this,i,true)};q.drawText_=function(am,ak,aj,ap,ai){var ao=this.m_,at=1000,j=0,ar=at,ah={x:0,y:0},ag=[];var i=u(E(this.font),this.element_);var p=ac(i);var au=this.element_.currentStyle;var Z=this.textAlign.toLowerCase();switch(Z){case"left":case"center":case"right":break;case"end":Z=au.direction=="ltr"?"right":"left";break;case"start":Z=au.direction=="rtl"?"right":"left";break;default:Z="left"}switch(this.textBaseline){case"hanging":case"top":ah.y=i.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":ah.y=-i.size/2.25;break}switch(Z){case"right":j=at;ar=0.05;break;case"center":j=ar=at/2;break}var aq=V(this,ak+ah.x,aj+ah.y);ag.push('');if(ai){w(this,ag)}else{G(this,ag,{x:-j,y:0},{x:ar,y:i.size})}var an=ao[0][0].toFixed(3)+","+ao[1][0].toFixed(3)+","+ao[0][1].toFixed(3)+","+ao[1][1].toFixed(3)+",0,0";var al=n(aq.x/d)+","+n(aq.y/d);ag.push('','','');this.element_.insertAdjacentHTML("beforeEnd",ag.join(""))};q.fillText=function(m,i,p,j){this.drawText_(m,i,p,j,false)};q.strokeText=function(m,i,p,j){this.drawText_(m,i,p,j,true)};q.measureText=function(m){if(!this.textMeasureEl_){var i='';this.element_.insertAdjacentHTML("beforeEnd",i);this.textMeasureEl_=this.element_.lastChild}var j=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(j.createTextNode(m));return{width:this.textMeasureEl_.offsetWidth}};q.clip=function(){};q.arcTo=function(){};q.createPattern=function(j,i){return new T(j,i)};function U(i){this.type_=i;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}U.prototype.addColorStop=function(j,i){i=F(i);this.colors_.push({offset:j,color:i.color,alpha:i.alpha})};function T(j,i){Q(j);switch(i){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=i;break;default:O("SYNTAX_ERR")}this.src_=j.src;this.width_=j.width;this.height_=j.height}function O(i){throw new P(i)}function Q(i){if(!i||i.nodeType!=1||i.tagName!="IMG"){O("TYPE_MISMATCH_ERR")}if(i.readyState!="complete"){O("INVALID_STATE_ERR")}}function P(i){this.code=this[i];this.message=i+": DOM Exception "+this.code}var X=P.prototype=new Error;X.INDEX_SIZE_ERR=1;X.DOMSTRING_SIZE_ERR=2;X.HIERARCHY_REQUEST_ERR=3;X.WRONG_DOCUMENT_ERR=4;X.INVALID_CHARACTER_ERR=5;X.NO_DATA_ALLOWED_ERR=6;X.NO_MODIFICATION_ALLOWED_ERR=7;X.NOT_FOUND_ERR=8;X.NOT_SUPPORTED_ERR=9;X.INUSE_ATTRIBUTE_ERR=10;X.INVALID_STATE_ERR=11;X.SYNTAX_ERR=12;X.INVALID_MODIFICATION_ERR=13;X.NAMESPACE_ERR=14;X.INVALID_ACCESS_ERR=15;X.VALIDATION_ERR=16;X.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=e;CanvasRenderingContext2D=D;CanvasGradient=U;CanvasPattern=T;DOMException=P})()}; \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/gpl-2.0.txt b/phpgwapi/js/jquery/jqplot/gpl-2.0.txt new file mode 100644 index 0000000000..864c6b8b7d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/gpl-2.0.txt @@ -0,0 +1,280 @@ +Title: GPL Version 2 + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/jqPlotCssStyling.txt b/phpgwapi/js/jquery/jqplot/jqPlotCssStyling.txt new file mode 100644 index 0000000000..041035d2ed --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/jqPlotCssStyling.txt @@ -0,0 +1,53 @@ +Title: jqPlot CSS Customization + +Much of the styling of jqPlot is done by css. The jqPlot css file is, unremarkably, +jquery.jqplot.css and resides in the same directory as jqPlot itself. + +There exist some styling related javascript properties on the plot objects themselves +(like fontStyle, fontSize, etc.). These can be set with the options object at plot creation. +Generally, setting these options is *NOT* the preferred way to customize the look of the +plot. Use the css file instead. *These options are deprecated and may disappear*. The +exceptions are certain background and color options which control attributes of something +renderered on a canvas. This would be line color, grid background, etc. These must +be set by the options object. For a list of available options, see . + +Objects in the plot that can be customized by css are given a css class like ".jqplot-*". +For example, the plot title will have a ".jqplot-title" class, the axes ".jqplot-axis", etc. + +Currently assigned classes in jqPlot +are as follows: + +.jqplot-target - Styles for the plot target div. These will be cascaded down +to all plot elements according to css rules. + +.jqplot-axis - Styles for all axes + +.jqplot-xaxis - Styles applied to the primary x axis only. + +.jqplot-yaxis - Styles applied to the primary y axis only. + +.jqplot-x2axis, .jqplot-x3axis, ... - Styles applied to the 2nd, 3rd, etc. x axis only. + +.jqplot-y2axis, .jqplot-y3axis, ... - Styles applied to the 2nd, 3rd, etc.y axis only. + +.jqplot-axis-tick - Styles applied to all axis ticks + +.jqplot-xaxis-tick - Styles applied to primary x axis ticks only. + +.jqplot-x2axis-tick - Styles applied to secondary x axis ticks only. + +.jqplot-yaxis-tick - Styles applied to primary y axis ticks only. + +.jqplot-y2axis-tick - Styles applied to secondary y axis ticks only. + +table.jqplot-table-legend - Styles applied to the legend box table. + +.jqplot-title - Styles applied to the title. + +.jqplot-cursor-tooltip - Styles applied to the cursor tooltip + +.jqplot-highlighter-tooltip - Styles applied to the highlighter tooltip. + +div.jqplot-table-legend-swatch - the div element used for the colored swatch on the legend. + +Note that axes will be assigned 2 classes like: class=".jqplot-axis .jqplot-xaxis". \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/jqPlotOptions.txt b/phpgwapi/js/jquery/jqplot/jqPlotOptions.txt new file mode 100644 index 0000000000..d2d1e68ccf --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/jqPlotOptions.txt @@ -0,0 +1,276 @@ +Title: jqPlot Options + +**This document is out of date. While the options described here should still be +relavent and valid, it has not been updated for many new options. Sorry for +this inconvenience.** + +This document describes the options available to jqPlot. These are set with the +third argument to the $.jqplot('target', data, options) function. Options are +using the following convention: + +{{{ +property: default, // notes +}}} + +This document is not complete! Not all options are shown! Also, Options marked +with ** in the notes are post 0.7.1 additions. They will be available in the next +release. Further information about the options can be found in the online API +documentation. For details on how the options relate to the API documentation, +see the in the optionsTutorial.txt file. + +{{{ +options = +{ + seriesColors: [ "#4bb2c5", "#c5b47f", "#EAA228", "#579575", "#839557", "#958c12", + "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc"], // colors that will + // be assigned to the series. If there are more series than colors, colors + // will wrap around and start at the beginning again. + + stackSeries: false, // if true, will create a stack plot. + // Currently supported by line and bar graphs. + + title: '', // Title for the plot. Can also be specified as an object like: + + title: { + text: '', // title for the plot, + show: true, + }, + + axesDefaults: { + show: false, // wether or not to renderer the axis. Determined automatically. + min: null, // minimum numerical value of the axis. Determined automatically. + max: null, // maximum numverical value of the axis. Determined automatically. + pad: 1.2, // a factor multiplied by the data range on the axis to give the + // axis range so that data points don't fall on the edges of the axis. + ticks: [], // a 1D [val1, val2, ...], or 2D [[val, label], [val, label], ...] + // array of ticks to use. Computed automatically. + numberTicks: undefined, + renderer: $.jqplot.LinearAxisRenderer, // renderer to use to draw the axis, + rendererOptions: {}, // options to pass to the renderer. LinearAxisRenderer + // has no options, + tickOptions: { + mark: 'outside', // Where to put the tick mark on the axis + // 'outside', 'inside' or 'cross', + showMark: true, + showGridline: true, // wether to draw a gridline (across the whole grid) at this tick, + markSize: 4, // length the tick will extend beyond the grid in pixels. For + // 'cross', length will be added above and below the grid boundary, + show: true, // wether to show the tick (mark and label), + showLabel: true, // wether to show the text label at the tick, + formatString: '', // format string to use with the axis tick formatter + } + showTicks: true, // wether or not to show the tick labels, + showTickMarks: true, // wether or not to show the tick marks + }, + + axes: { + xaxis: { + // same options as axesDefaults + }, + yaxis: { + // same options as axesDefaults + }, + x2axis: { + // same options as axesDefaults + }, + y2axis: { + // same options as axesDefaults + } + }, + + seriesDefaults: { + show: true, // wether to render the series. + xaxis: 'xaxis', // either 'xaxis' or 'x2axis'. + yaxis: 'yaxis', // either 'yaxis' or 'y2axis'. + label: '', // label to use in the legend for this line. + color: '', // CSS color spec to use for the line. Determined automatically. + lineWidth: 2.5, // Width of the line in pixels. + shadow: true, // show shadow or not. + shadowAngle: 45, // angle (degrees) of the shadow, clockwise from x axis. + shadowOffset: 1.25, // offset from the line of the shadow. + shadowDepth: 3, // Number of strokes to make when drawing shadow. Each + // stroke offset by shadowOffset from the last. + shadowAlpha: 0.1, // Opacity of the shadow. + showLine: true, // whether to render the line segments or not. + showMarker: true, // render the data point markers or not. + fill: false, // fill under the line, + fillAndStroke: false, // **stroke a line at top of fill area. + fillColor: undefined, // **custom fill color for filled lines (default is line color). + fillAlpha: undefined, // **custom alpha to apply to fillColor. + renderer: $.jqplot.LineRenderer], // renderer used to draw the series. + rendererOptions: {}, // options passed to the renderer. LineRenderer has no options. + markerRenderer: $.jqplot.MarkerRenderer, // renderer to use to draw the data + // point markers. + markerOptions: { + show: true, // wether to show data point markers. + style: 'filledCircle', // circle, diamond, square, filledCircle. + // filledDiamond or filledSquare. + lineWidth: 2, // width of the stroke drawing the marker. + size: 9, // size (diameter, edge length, etc.) of the marker. + color: '#666666' // color of marker, set to color of line by default. + shadow: true, // wether to draw shadow on marker or not. + shadowAngle: 45, // angle of the shadow. Clockwise from x axis. + shadowOffset: 1, // offset from the line of the shadow, + shadowDepth: 3, // Number of strokes to make when drawing shadow. Each stroke + // offset by shadowOffset from the last. + shadowAlpha: 0.07 // Opacity of the shadow + } + }, + + series:[ + {Each series has same options as seriesDefaults}, + {You can override each series individually here} + ], + + legend: { + show: false, + location: 'ne', // compass direction, nw, n, ne, e, se, s, sw, w. + xoffset: 12, // pixel offset of the legend box from the x (or x2) axis. + yoffset: 12, // pixel offset of the legend box from the y (or y2) axis. + }, + + grid: { + drawGridLines: true, // wether to draw lines across the grid or not. + gridLineColor: '#cccccc' // **Color of the grid lines. + background: '#fffdf6', // CSS color spec for background color of grid. + borderColor: '#999999', // CSS color spec for border around grid. + borderWidth: 2.0, // pixel width of border around grid. + shadow: true, // draw a shadow for grid. + shadowAngle: 45, // angle of the shadow. Clockwise from x axis. + shadowOffset: 1.5, // offset from the line of the shadow. + shadowWidth: 3, // width of the stroke for the shadow. + shadowDepth: 3, // Number of strokes to make when drawing shadow. + // Each stroke offset by shadowOffset from the last. + shadowAlpha: 0.07 // Opacity of the shadow + renderer: $.jqplot.CanvasGridRenderer, // renderer to use to draw the grid. + rendererOptions: {} // options to pass to the renderer. Note, the default + // CanvasGridRenderer takes no additional options. + }, + + // Plugin and renderer options. + + // BarRenderer. + // With BarRenderer, you can specify additional options in the rendererOptions object + // on the series or on the seriesDefaults object. Note, some options are respecified + // (like shadowDepth) to override lineRenderer defaults from which BarRenderer inherits. + + seriesDefaults: { + rendererOptions: { + barPadding: 8, // number of pixels between adjacent bars in the same + // group (same category or bin). + barMargin: 10, // number of pixels between adjacent groups of bars. + barDirection: 'vertical', // vertical or horizontal. + barWidth: null, // width of the bars. null to calculate automatically. + shadowOffset: 2, // offset from the bar edge to stroke the shadow. + shadowDepth: 5, // nuber of strokes to make for the shadow. + shadowAlpha: 0.8, // transparency of the shadow. + } + }, + + // Cursor + // Options are passed to the cursor plugin through the "cursor" object at the top + // level of the options object. + + cursor: { + style: 'crosshair', // A CSS spec for the cursor type to change the + // cursor to when over plot. + show: true, + showTooltip: true, // show a tooltip showing cursor position. + followMouse: false, // wether tooltip should follow the mouse or be stationary. + tooltipLocation: 'se', // location of the tooltip either relative to the mouse + // (followMouse=true) or relative to the plot. One of + // the compass directions, n, ne, e, se, etc. + tooltipOffset: 6, // pixel offset of the tooltip from the mouse or the axes. + showTooltipGridPosition: false, // show the grid pixel coordinates of the mouse + // in the tooltip. + showTooltipUnitPosition: true, // show the coordinates in data units of the mouse + // in the tooltip. + tooltipFormatString: '%.4P', // sprintf style format string for tooltip values. + useAxesFormatters: true, // wether to use the same formatter and formatStrings + // as used by the axes, or to use the formatString + // specified on the cursor with sprintf. + tooltipAxesGroups: [], // show only specified axes groups in tooltip. Would specify like: + // [['xaxis', 'yaxis'], ['xaxis', 'y2axis']]. By default, all axes + // combinations with for the series in the plot are shown. + + }, + + // Dragable + // Dragable options are specified with the "dragable" object at the top level + // of the options object. + + dragable: { + color: undefined, // custom color to use for the dragged point and dragged line + // section. default will use a transparent variant of the line color. + constrainTo: 'none', // Constrain dragging motion to an axis: 'x', 'y', or 'none'. + }, + + // Highlighter + // Highlighter options are specified with the "highlighter" object at the top level + // of the options object. + + highlighter: { + lineWidthAdjust: 2.5, // pixels to add to the size line stroking the data point marker + // when showing highlight. Only affects non filled data point markers. + sizeAdjust: 5, // pixels to add to the size of filled markers when drawing highlight. + showTooltip: true, // show a tooltip with data point values. + tooltipLocation: 'nw', // location of tooltip: n, ne, e, se, s, sw, w, nw. + fadeTooltip: true, // use fade effect to show/hide tooltip. + tooltipFadeSpeed: "fast"// slow, def, fast, or a number of milliseconds. + tooltipOffset: 2, // pixel offset of tooltip from the highlight. + tooltipAxes: 'both', // which axis values to display in the tooltip, x, y or both. + tooltipSeparator: ', ' // separator between values in the tooltip. + useAxesFormatters: true // use the same format string and formatters as used in the axes to + // display values in the tooltip. + tooltipFormatString: '%.5P' // sprintf format string for the tooltip. only used if + // useAxesFormatters is false. Will use sprintf formatter with + // this string, not the axes formatters. + }, + + // LogAxisRenderer + // LogAxisRenderer add 2 options to the axes object. These options are specified directly on + // the axes or axesDefaults object. + + axesDefaults: { + base: 10, // the logarithmic base. + tickDistribution: 'even', // 'even' or 'power'. 'even' will produce with even visiual (pixel) + // spacing on the axis. 'power' will produce ticks spaced by + // increasing powers of the log base. + }, + + // PieRenderer + // PieRenderer accepts options from the rendererOptions object of the series or seriesDefaults object. + + seriesDefaults: { + rendererOptions: { + diameter: undefined, // diameter of pie, auto computed by default. + padding: 20, // padding between pie and neighboring legend or plot margin. + sliceMargin: 0, // gap between slices. + fill: true, // render solid (filled) slices. + shadowOffset: 2, // offset of the shadow from the chart. + shadowDepth: 5, // Number of strokes to make when drawing shadow. Each stroke + // offset by shadowOffset from the last. + shadowAlpha: 0.07 // Opacity of the shadow + } + }, + + // Trendline + // Trendline takes options on the trendline object of the series or seriesDefaults object. + + seriesDefaults: { + trendline: { + show: true, // show the trend line + color: '#666666', // CSS color spec for the trend line. + label: '', // label for the trend line. + type: 'linear', // 'linear', 'exponential' or 'exp' + shadow: true, // show the trend line shadow. + lineWidth: 1.5, // width of the trend line. + shadowAngle: 45, // angle of the shadow. Clockwise from x axis. + shadowOffset: 1.5, // offset from the line of the shadow. + shadowDepth: 3, // Number of strokes to make when drawing shadow. + // Each stroke offset by shadowOffset from the last. + shadowAlpha: 0.07 // Opacity of the shadow + } + } +} +}}} \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/jquery.jqplot.css b/phpgwapi/js/jquery/jqplot/jquery.jqplot.css new file mode 100644 index 0000000000..c9bf6f923b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/jquery.jqplot.css @@ -0,0 +1,226 @@ +/*rules for the plot target div. These will be cascaded down to all plot elements according to css rules*/ +.jqplot-target { + position: relative; + color: #666666; + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + font-size: 1em; +/* height: 300px; + width: 400px;*/ +} + +/*rules applied to all axes*/ +.jqplot-axis { + font-size: 0.75em; +} + +.jqplot-xaxis { + margin-top: 10px; +} + +.jqplot-x2axis { + margin-bottom: 10px; +} + +.jqplot-yaxis { + margin-right: 10px; +} + +.jqplot-y2axis, .jqplot-y3axis, .jqplot-y4axis, .jqplot-y5axis, .jqplot-y6axis, .jqplot-y7axis, .jqplot-y8axis, .jqplot-y9axis { + margin-left: 10px; + margin-right: 10px; +} + +/*rules applied to all axis tick divs*/ +.jqplot-axis-tick, .jqplot-xaxis-tick, .jqplot-yaxis-tick, .jqplot-x2axis-tick, .jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick { + position: absolute; +} + + +.jqplot-xaxis-tick { + top: 0px; + /* initial position untill tick is drawn in proper place */ + left: 15px; +/* padding-top: 10px;*/ + vertical-align: top; +} + +.jqplot-x2axis-tick { + bottom: 0px; + /* initial position untill tick is drawn in proper place */ + left: 15px; +/* padding-bottom: 10px;*/ + vertical-align: bottom; +} + +.jqplot-yaxis-tick { + right: 0px; + /* initial position untill tick is drawn in proper place */ + top: 15px; +/* padding-right: 10px;*/ + text-align: right; +} + +.jqplot-yaxis-tick.jqplot-breakTick { + right: -20px; + margin-right: 0px; + padding:1px 5px 1px 5px; +/* background-color: white;*/ + z-index: 2; + font-size: 1.5em; +} + +.jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick { + left: 0px; + /* initial position untill tick is drawn in proper place */ + top: 15px; +/* padding-left: 10px;*/ +/* padding-right: 15px;*/ + text-align: left; +} + +.jqplot-meterGauge-tick { + font-size: 0.75em; + color: #999999; +} + +.jqplot-meterGauge-label { + font-size: 1em; + color: #999999; +} +.jqplot-xaxis-label { + margin-top: 10px; + font-size: 11pt; + position: absolute; +} + +.jqplot-x2axis-label { + margin-bottom: 10px; + font-size: 11pt; + position: absolute; +} + +.jqplot-yaxis-label { + margin-right: 10px; +/* text-align: center;*/ + font-size: 11pt; + position: absolute; +} + +.jqplot-y2axis-label, .jqplot-y3axis-label, .jqplot-y4axis-label, .jqplot-y5axis-label, .jqplot-y6axis-label, .jqplot-y7axis-label, .jqplot-y8axis-label, .jqplot-y9axis-label { +/* text-align: center;*/ + font-size: 11pt; + position: absolute; +} + +table.jqplot-table-legend { + margin-top: 12px; + margin-bottom: 12px; + margin-left: 12px; + margin-right: 12px; +} + +table.jqplot-table-legend, table.jqplot-cursor-legend { + background-color: rgba(255,255,255,0.6); + border: 1px solid #cccccc; + position: absolute; + font-size: 0.75em; +} + +td.jqplot-table-legend { + vertical-align:middle; +} + +td.jqplot-seriesToggle:hover, td.jqplot-seriesToggle:active { + cursor: pointer; +} + +td.jqplot-table-legend > div { + border: 1px solid #cccccc; + padding:1px; +} + +div.jqplot-table-legend-swatch { + width:0px; + height:0px; + border-top-width: 5px; + border-bottom-width: 5px; + border-left-width: 6px; + border-right-width: 6px; + border-top-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-right-style: solid; +} + +.jqplot-title { + top: 0px; + left: 0px; + padding-bottom: 0.5em; + font-size: 1.2em; +} + +table.jqplot-cursor-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; +} + + +.jqplot-cursor-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; + white-space: nowrap; + background: rgba(208,208,208,0.5); + padding: 1px; +} + +.jqplot-highlighter-tooltip { + border: 1px solid #cccccc; + font-size: 0.75em; + white-space: nowrap; + background: rgba(208,208,208,0.5); + padding: 1px; +} + +.jqplot-point-label { + font-size: 0.75em; + z-index: 2; +} + +td.jqplot-cursor-legend-swatch { +vertical-align:middle; +text-align:center; +} + +div.jqplot-cursor-legend-swatch { +width:1.2em; +height:0.7em; +} + +.jqplot-error { +/* Styles added to the plot target container when there is an error go here.*/ + text-align: center; +} + +.jqplot-error-message { +/* Styling of the custom error message div goes here.*/ + position: relative; + top: 46%; + display: inline-block; +} + +div.jqplot-bubble-label { + font-size: 0.8em; +/* background: rgba(90%, 90%, 90%, 0.15);*/ + padding-left: 2px; + padding-right: 2px; + color: rgb(20%, 20%, 20%); +} + +div.jqplot-bubble-label.jqplot-bubble-label-highlight { + background: rgba(90%, 90%, 90%, 0.7); +} + +div.jqplot-noData-container { + text-align: center; + background-color: rgba(96%, 96%, 96%, 0.3); +} diff --git a/phpgwapi/js/jquery/jqplot/jquery.jqplot.js b/phpgwapi/js/jquery/jqplot/jquery.jqplot.js new file mode 100644 index 0000000000..8a795a5cda --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/jquery.jqplot.js @@ -0,0 +1,8716 @@ +/** + * Title: jqPlot Charts + * + * Pure JavaScript plotting plugin for jQuery. + * + * About: Version + * + * 1.0.0b2_r792 + * + * About: Copyright & License + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT and GPL version 2.0 licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * See and contained within this distribution for further information. + * + * The author would appreciate an email letting him know of any substantial + * use of jqPlot. You can reach the author at: chris at jqplot dot com + * or see http://www.jqplot.com/info.php. This is, of course, not required. + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php. + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + * + * About: Introduction + * + * jqPlot requires jQuery (1.4+ required for certain features). jQuery 1.4.2 is included in the distribution. + * To use jqPlot include jQuery, the jqPlot jQuery plugin, the jqPlot css file and optionally + * the excanvas script for IE support in your web page: + * + * > + * > + * > + * > + * + * jqPlot can be customized by overriding the defaults of any of the objects which make + * up the plot. The general usage of jqplot is: + * + * > chart = $.jqplot('targetElemId', [dataArray,...], {optionsObject}); + * + * The options available to jqplot are detailed in in the jqPlotOptions.txt file. + * + * An actual call to $.jqplot() may look like the + * examples below: + * + * > chart = $.jqplot('chartdiv', [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]]); + * + * or + * + * > dataArray = [34,12,43,55,77]; + * > chart = $.jqplot('targetElemId', [dataArray, ...], {title:'My Plot', axes:{yaxis:{min:20, max:100}}}); + * + * For more inforrmation, see . + * + * About: Usage + * + * See + * + * About: Available Options + * + * See for a list of options available thorugh the options object (not complete yet!) + * + * About: Options Usage + * + * See + * + * About: Changes + * + * See + * + */ + +(function($) { + // make sure undefined is undefined + var undefined; + + $.fn.emptyForce = function() { + for ( var i = 0, elem; (elem = $(this)[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + if ($.jqplot_use_excanvas) { + elem.outerHTML = ""; + } + else { + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + elem = null; + } + + return $(this); + }; + + $.fn.removeChildForce = function(parent) { + while ( parent.firstChild ) { + this.removeChildForce( parent.firstChild ); + parent.removeChild( parent.firstChild ); + } + }; + + + /** + * Namespace: $.jqplot + * jQuery function called by the user to create a plot. + * + * Parameters: + * target - ID of target element to render the plot into. + * data - an array of data series. + * options - user defined options object. See the individual classes for available options. + * + * Properties: + * config - object to hold configuration information for jqPlot plot object. + * + * attributes: + * enablePlugins - False to disable plugins by default. Plugins must then be explicitly + * enabled in the individual plot options. Default: false. + * This property sets the "show" property of certain plugins to true or false. + * Only plugins that can be immediately active upon loading are affected. This includes + * non-renderer plugins like cursor, dragable, highlighter, and trendline. + * defaultHeight - Default height for plots where no css height specification exists. This + * is a jqplot wide default. + * defaultWidth - Default height for plots where no css height specification exists. This + * is a jqplot wide default. + */ + + $.jqplot = function(target, data, options) { + var _data, _options; + + if (options == null) { + if (jQuery.isArray(data)) { + _data = data; + _options = null; + } + + else if (typeof(data) === 'object') { + _data = null; + _options = data; + } + } + else { + _data = data; + _options = options; + } + var plot = new jqPlot(); + // remove any error class that may be stuck on target. + $('#'+target).removeClass('jqplot-error'); + + if ($.jqplot.config.catchErrors) { + try { + plot.init(target, _data, _options); + plot.draw(); + plot.themeEngine.init.call(plot); + return plot; + } + catch(e) { + var msg = $.jqplot.config.errorMessage || e.message; + $('#'+target).append('
        '+msg+'
        '); + $('#'+target).addClass('jqplot-error'); + document.getElementById(target).style.background = $.jqplot.config.errorBackground; + document.getElementById(target).style.border = $.jqplot.config.errorBorder; + document.getElementById(target).style.fontFamily = $.jqplot.config.errorFontFamily; + document.getElementById(target).style.fontSize = $.jqplot.config.errorFontSize; + document.getElementById(target).style.fontStyle = $.jqplot.config.errorFontStyle; + document.getElementById(target).style.fontWeight = $.jqplot.config.errorFontWeight; + } + } + else { + plot.init(target, _data, _options); + plot.draw(); + plot.themeEngine.init.call(plot); + return plot; + } + }; + + $.jqplot.version = "1.0.0b2_r792"; + + // canvas manager to reuse canvases on the plot. + // Should help solve problem of canvases not being freed and + // problem of waiting forever for firefox to decide to free memory. + $.jqplot.CanvasManager = function() { + // canvases are managed globally so that they can be reused + // across plots after they have been freed + if (typeof $.jqplot.CanvasManager.canvases == 'undefined') { + $.jqplot.CanvasManager.canvases = []; + $.jqplot.CanvasManager.free = []; + } + + var myCanvases = []; + + this.getCanvas = function() { + var canvas; + var makeNew = true; + + if (!$.jqplot.use_excanvas) { + for (var i = 0, l = $.jqplot.CanvasManager.canvases.length; i < l; i++) { + if ($.jqplot.CanvasManager.free[i] === true) { + makeNew = false; + canvas = $.jqplot.CanvasManager.canvases[i]; + // $(canvas).removeClass('jqplot-canvasManager-free').addClass('jqplot-canvasManager-inuse'); + $.jqplot.CanvasManager.free[i] = false; + myCanvases.push(i); + break; + } + } + } + + if (makeNew) { + canvas = document.createElement('canvas'); + myCanvases.push($.jqplot.CanvasManager.canvases.length); + $.jqplot.CanvasManager.canvases.push(canvas); + $.jqplot.CanvasManager.free.push(false); + } + + return canvas; + }; + + // this method has to be used after settings the dimesions + // on the element returned by getCanvas() + this.initCanvas = function(canvas) { + if ($.jqplot.use_excanvas) { + return window.G_vmlCanvasManager.initElement(canvas); + } + return canvas; + }; + + this.freeAllCanvases = function() { + for (var i = 0, l=myCanvases.length; i < l; i++) { + this.freeCanvas(myCanvases[i]); + } + myCanvases = []; + }; + + this.freeCanvas = function(idx) { + if ($.jqplot.use_excanvas) { + // excanvas can't be reused, but properly unset + window.G_vmlCanvasManager.uninitElement($.jqplot.CanvasManager.canvases[idx]); + $.jqplot.CanvasManager.canvases[idx] = null; + } + else { + var canvas = $.jqplot.CanvasManager.canvases[idx]; + canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); + $(canvas).unbind().removeAttr('class').removeAttr('style'); + // Style attributes seemed to be still hanging around. wierd. Some ticks + // still retained a left: 0px attribute after reusing a canvas. + $(canvas).css({left: '', top: '', position: ''}); + // setting size to 0 may save memory of unused canvases? + canvas.width = 0; + canvas.height = 0; + $.jqplot.CanvasManager.free[idx] = true; + } + }; + + }; + + + // Convienence function that won't hang IE or FF without FireBug. + $.jqplot.log = function() { + if (window.console) { + console.log.apply(console, arguments); + } + }; + + $.jqplot.config = { + enablePlugins:false, + defaultHeight:300, + defaultWidth:400, + UTCAdjust:false, + timezoneOffset: new Date(new Date().getTimezoneOffset() * 60000), + errorMessage: '', + errorBackground: '', + errorBorder: '', + errorFontFamily: '', + errorFontSize: '', + errorFontStyle: '', + errorFontWeight: '', + catchErrors: false, + defaultTickFormatString: "%.1f", + defaultColors: [ "#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"], + defaultNegativeColors: [ "#498991", "#C08840", "#9F9274", "#546D61", "#646C4A", "#6F6621", "#6E3F5F", "#4F64B0", "#A89050", "#C45923", "#187399", "#945381", "#959E5C", "#C7AF7B", "#478396", "#907294"] + }; + + + $.jqplot.arrayMax = function( array ){ + return Math.max.apply( Math, array ); + }; + + $.jqplot.arrayMin = function( array ){ + return Math.min.apply( Math, array ); + }; + + $.jqplot.enablePlugins = $.jqplot.config.enablePlugins; + + // canvas related tests taken from modernizer: + // Copyright (c) 2009 - 2010 Faruk Ates. + // http://www.modernizr.com + + $.jqplot.support_canvas = function() { + if (typeof $.jqplot.support_canvas.result == 'undefined') { + $.jqplot.support_canvas.result = !!document.createElement('canvas').getContext; + } + return $.jqplot.support_canvas.result; + }; + + $.jqplot.support_canvas_text = function() { + if (typeof $.jqplot.support_canvas_text.result == 'undefined') { + $.jqplot.support_canvas_text.result = !!(document.createElement('canvas').getContext && typeof document.createElement('canvas').getContext('2d').fillText == 'function'); + } + return $.jqplot.support_canvas_text.result; + }; + + $.jqplot.use_excanvas = ($.browser.msie && !$.jqplot.support_canvas()) ? true : false; + + /** + * + * Hooks: jqPlot Pugin Hooks + * + * $.jqplot.preInitHooks - called before initialization. + * $.jqplot.postInitHooks - called after initialization. + * $.jqplot.preParseOptionsHooks - called before user options are parsed. + * $.jqplot.postParseOptionsHooks - called after user options are parsed. + * $.jqplot.preDrawHooks - called before plot draw. + * $.jqplot.postDrawHooks - called after plot draw. + * $.jqplot.preDrawSeriesHooks - called before each series is drawn. + * $.jqplot.postDrawSeriesHooks - called after each series is drawn. + * $.jqplot.preDrawLegendHooks - called before the legend is drawn. + * $.jqplot.addLegendRowHooks - called at the end of legend draw, so plugins + * can add rows to the legend table. + * $.jqplot.preSeriesInitHooks - called before series is initialized. + * $.jqplot.postSeriesInitHooks - called after series is initialized. + * $.jqplot.preParseSeriesOptionsHooks - called before series related options + * are parsed. + * $.jqplot.postParseSeriesOptionsHooks - called after series related options + * are parsed. + * $.jqplot.eventListenerHooks - called at the end of plot drawing, binds + * listeners to the event canvas which lays on top of the grid area. + * $.jqplot.preDrawSeriesShadowHooks - called before series shadows are drawn. + * $.jqplot.postDrawSeriesShadowHooks - called after series shadows are drawn. + * + */ + + $.jqplot.preInitHooks = []; + $.jqplot.postInitHooks = []; + $.jqplot.preParseOptionsHooks = []; + $.jqplot.postParseOptionsHooks = []; + $.jqplot.preDrawHooks = []; + $.jqplot.postDrawHooks = []; + $.jqplot.preDrawSeriesHooks = []; + $.jqplot.postDrawSeriesHooks = []; + $.jqplot.preDrawLegendHooks = []; + $.jqplot.addLegendRowHooks = []; + $.jqplot.preSeriesInitHooks = []; + $.jqplot.postSeriesInitHooks = []; + $.jqplot.preParseSeriesOptionsHooks = []; + $.jqplot.postParseSeriesOptionsHooks = []; + $.jqplot.eventListenerHooks = []; + $.jqplot.preDrawSeriesShadowHooks = []; + $.jqplot.postDrawSeriesShadowHooks = []; + + // A superclass holding some common properties and methods. + $.jqplot.ElemContainer = function() { + this._elem; + this._plotWidth; + this._plotHeight; + this._plotDimensions = {height:null, width:null}; + }; + + $.jqplot.ElemContainer.prototype.createElement = function(el, offsets, clss, cssopts, attrib) { + this._offsets = offsets; + var klass = clss || 'jqplot'; + var elem = document.createElement(el); + this._elem = $(elem); + this._elem.addClass(klass); + this._elem.css(cssopts); + this._elem.attr(attrib); + // avoid memory leak; + elem = null; + return this._elem; + }; + + $.jqplot.ElemContainer.prototype.getWidth = function() { + if (this._elem) { + return this._elem.outerWidth(true); + } + else { + return null; + } + }; + + $.jqplot.ElemContainer.prototype.getHeight = function() { + if (this._elem) { + return this._elem.outerHeight(true); + } + else { + return null; + } + }; + + $.jqplot.ElemContainer.prototype.getPosition = function() { + if (this._elem) { + return this._elem.position(); + } + else { + return {top:null, left:null, bottom:null, right:null}; + } + }; + + $.jqplot.ElemContainer.prototype.getTop = function() { + return this.getPosition().top; + }; + + $.jqplot.ElemContainer.prototype.getLeft = function() { + return this.getPosition().left; + }; + + $.jqplot.ElemContainer.prototype.getBottom = function() { + return this._elem.css('bottom'); + }; + + $.jqplot.ElemContainer.prototype.getRight = function() { + return this._elem.css('right'); + }; + + + /** + * Class: Axis + * An individual axis object. Cannot be instantiated directly, but created + * by the Plot oject. Axis properties can be set or overriden by the + * options passed in from the user. + * + */ + function Axis(name) { + $.jqplot.ElemContainer.call(this); + // Group: Properties + // + // Axes options are specified within an axes object at the top level of the + // plot options like so: + // > { + // > axes: { + // > xaxis: {min: 5}, + // > yaxis: {min: 2, max: 8, numberTicks:4}, + // > x2axis: {pad: 1.5}, + // > y2axis: {ticks:[22, 44, 66, 88]} + // > } + // > } + // There are 2 x axes, 'xaxis' and 'x2axis', and + // 9 yaxes, 'yaxis', 'y2axis'. 'y3axis', ... Any or all of which may be specified. + this.name = name; + this._series = []; + // prop: show + // Wether to display the axis on the graph. + this.show = false; + // prop: tickRenderer + // A class of a rendering engine for creating the ticks labels displayed on the plot, + // See <$.jqplot.AxisTickRenderer>. + this.tickRenderer = $.jqplot.AxisTickRenderer; + // prop: tickOptions + // Options that will be passed to the tickRenderer, see <$.jqplot.AxisTickRenderer> options. + this.tickOptions = {}; + // prop: labelRenderer + // A class of a rendering engine for creating an axis label. + this.labelRenderer = $.jqplot.AxisLabelRenderer; + // prop: labelOptions + // Options passed to the label renderer. + this.labelOptions = {}; + // prop: label + // Label for the axis + this.label = null; + // prop: showLabel + // true to show the axis label. + this.showLabel = true; + // prop: min + // minimum value of the axis (in data units, not pixels). + this.min=null; + // prop: max + // maximum value of the axis (in data units, not pixels). + this.max=null; + // prop: autoscale + // Autoscale the axis min and max values to provide sensible tick spacing. + // If axis min or max are set, autoscale will be turned off. + // The numberTicks, tickInterval and pad options do work with + // autoscale, although tickInterval has not been tested yet. + // padMin and padMax do nothing when autoscale is on. + this.autoscale = false; + // prop: pad + // Padding to extend the range above and below the data bounds. + // The data range is multiplied by this factor to determine minimum and maximum axis bounds. + // A value of 0 will be interpreted to mean no padding, and pad will be set to 1.0. + this.pad = 1.2; + // prop: padMax + // Padding to extend the range above data bounds. + // The top of the data range is multiplied by this factor to determine maximum axis bounds. + // A value of 0 will be interpreted to mean no padding, and padMax will be set to 1.0. + this.padMax = null; + // prop: padMin + // Padding to extend the range below data bounds. + // The bottom of the data range is multiplied by this factor to determine minimum axis bounds. + // A value of 0 will be interpreted to mean no padding, and padMin will be set to 1.0. + this.padMin = null; + // prop: ticks + // 1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis. + // If no label is specified, the value is formatted into an appropriate label. + this.ticks = []; + // prop: numberTicks + // Desired number of ticks. Default is to compute automatically. + this.numberTicks; + // prop: tickInterval + // number of units between ticks. Mutually exclusive with numberTicks. + this.tickInterval; + // prop: renderer + // A class of a rendering engine that handles tick generation, + // scaling input data to pixel grid units and drawing the axis element. + this.renderer = $.jqplot.LinearAxisRenderer; + // prop: rendererOptions + // renderer specific options. See <$.jqplot.LinearAxisRenderer> for options. + this.rendererOptions = {}; + // prop: showTicks + // Wether to show the ticks (both marks and labels) or not. + // Will not override showMark and showLabel options if specified on the ticks themselves. + this.showTicks = true; + // prop: showTickMarks + // Wether to show the tick marks (line crossing grid) or not. + // Overridden by showTicks and showMark option of tick itself. + this.showTickMarks = true; + // prop: showMinorTicks + // Wether or not to show minor ticks. This is renderer dependent. + // The default <$.jqplot.LinearAxisRenderer> does not have minor ticks. + this.showMinorTicks = true; + // prop: useSeriesColor + // Use the color of the first series associated with this axis for the + // tick marks and line bordering this axis. + this.useSeriesColor = false; + // prop: borderWidth + // width of line stroked at the border of the axis. Defaults + // to the width of the grid boarder. + this.borderWidth = null; + // prop: borderColor + // color of the border adjacent to the axis. Defaults to grid border color. + this.borderColor = null; + // minimum and maximum values on the axis. + this._dataBounds = {min:null, max:null}; + // statistics (min, max, mean) as well as actual data intervals for each series attached to axis. + // holds collection of {intervals:[], min:, max:, mean: } objects for each series on axis. + this._intervalStats = []; + // pixel position from the top left of the min value and max value on the axis. + this._offsets = {min:null, max:null}; + this._ticks=[]; + this._label = null; + // prop: syncTicks + // true to try and synchronize tick spacing across multiple axes so that ticks and + // grid lines line up. This has an impact on autoscaling algorithm, however. + // In general, autoscaling an individual axis will work better if it does not + // have to sync ticks. + this.syncTicks = null; + // prop: tickSpacing + // Approximate pixel spacing between ticks on graph. Used during autoscaling. + // This number will be an upper bound, actual spacing will be less. + this.tickSpacing = 75; + // Properties to hold the original values for min, max, ticks, tickInterval and numberTicks + // so they can be restored if altered by plugins. + this._min = null; + this._max = null; + this._tickInterval = null; + this._numberTicks = null; + this.__ticks = null; + // hold original user options. + this._options = {}; + } + + Axis.prototype = new $.jqplot.ElemContainer(); + Axis.prototype.constructor = Axis; + + Axis.prototype.init = function() { + this.renderer = new this.renderer(); + // set the axis name + this.tickOptions.axis = this.name; + // if showMark or showLabel tick options not specified, use value of axis option. + // showTicks overrides showTickMarks. + if (this.tickOptions.showMark == null) { + this.tickOptions.showMark = this.showTicks; + } + if (this.tickOptions.showMark == null) { + this.tickOptions.showMark = this.showTickMarks; + } + if (this.tickOptions.showLabel == null) { + this.tickOptions.showLabel = this.showTicks; + } + + if (this.label == null || this.label == '') { + this.showLabel = false; + } + else { + this.labelOptions.label = this.label; + } + if (this.showLabel == false) { + this.labelOptions.show = false; + } + // set the default padMax, padMin if not specified + // special check, if no padding desired, padding + // should be set to 1.0 + if (this.pad == 0) { + this.pad = 1.0; + } + if (this.padMax == 0) { + this.padMax = 1.0; + } + if (this.padMin == 0) { + this.padMin = 1.0; + } + if (this.padMax == null) { + this.padMax = (this.pad-1)/2 + 1; + } + if (this.padMin == null) { + this.padMin = (this.pad-1)/2 + 1; + } + // now that padMin and padMax are correctly set, reset pad in case user has supplied + // padMin and/or padMax + this.pad = this.padMax + this.padMin - 1; + if (this.min != null || this.max != null) { + this.autoscale = false; + } + // if not set, sync ticks for y axes but not x by default. + if (this.syncTicks == null && this.name.indexOf('y') > -1) { + this.syncTicks = true; + } + else if (this.syncTicks == null){ + this.syncTicks = false; + } + this.renderer.init.call(this, this.rendererOptions); + + }; + + Axis.prototype.draw = function(ctx, plot) { + // Memory Leaks patch + if (this.__ticks) { + this.__ticks = null; + } + + return this.renderer.draw.call(this, ctx, plot); + + }; + + Axis.prototype.set = function() { + this.renderer.set.call(this); + }; + + Axis.prototype.pack = function(pos, offsets) { + if (this.show) { + this.renderer.pack.call(this, pos, offsets); + } + // these properties should all be available now. + if (this._min == null) { + this._min = this.min; + this._max = this.max; + this._tickInterval = this.tickInterval; + this._numberTicks = this.numberTicks; + this.__ticks = this._ticks; + } + }; + + // reset the axis back to original values if it has been scaled, zoomed, etc. + Axis.prototype.reset = function() { + this.renderer.reset.call(this); + }; + + Axis.prototype.resetScale = function(opts) { + $.extend(true, this, {min: null, max: null, numberTicks: null, tickInterval: null, _ticks: [], ticks: []}, opts); + this.resetDataBounds(); + }; + + Axis.prototype.resetDataBounds = function() { + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + var db = this._dataBounds; + db.min = null; + db.max = null; + // check for when to force min 0 on bar series plots. + var doforce = (this.show) ? true : false; + for (var i=0; i db.max) || db.max == null) { + db.max = d[j][0]; + } + } + else { + if ((d[j][minyidx] != null && d[j][minyidx] < db.min) || db.min == null) { + db.min = d[j][minyidx]; + } + if ((d[j][maxyidx] != null && d[j][maxyidx] > db.max) || db.max == null) { + db.max = d[j][maxyidx]; + } + } + } + + // Hack to not pad out bottom of bar plots unless user has specified a padding. + // every series will have a chance to set doforce to false. once it is set to + // false, it cannot be reset to true. + // If any series attached to axis is not a bar, wont force 0. + if (doforce && s.renderer.constructor !== $.jqplot.BarRenderer) { + doforce = false; + } + + else if (doforce && this._options.hasOwnProperty('forceTickAt0') && this._options.forceTickAt0 == false) { + doforce = false; + } + + else if (doforce && s.renderer.constructor === $.jqplot.BarRenderer) { + if (s.barDirection == 'vertical' && this.name != 'xaxis' && this.name != 'x2axis') { + if (this._options.pad != null || this._options.padMin != null) { + doforce = false; + } + } + + else if (s.barDirection == 'horizontal' && (this.name == 'xaxis' || this.name == 'x2axis')) { + if (this._options.pad != null || this._options.padMin != null) { + doforce = false; + } + } + + } + } + + if (doforce && this.renderer.constructor === $.jqplot.LinearAxisRenderer && db.min >= 0) { + this.padMin = 1.0; + this.forceTickAt0 = true; + } + }; + + /** + * Class: Legend + * Legend object. Cannot be instantiated directly, but created + * by the Plot oject. Legend properties can be set or overriden by the + * options passed in from the user. + */ + function Legend(options) { + $.jqplot.ElemContainer.call(this); + // Group: Properties + + // prop: show + // Wether to display the legend on the graph. + this.show = false; + // prop: location + // Placement of the legend. one of the compass directions: nw, n, ne, e, se, s, sw, w + this.location = 'ne'; + // prop: labels + // Array of labels to use. By default the renderer will look for labels on the series. + // Labels specified in this array will override labels specified on the series. + this.labels = []; + // prop: showLabels + // true to show the label text on the legend. + this.showLabels = true; + // prop: showSwatch + // true to show the color swatches on the legend. + this.showSwatches = true; + // prop: placement + // "insideGrid" places legend inside the grid area of the plot. + // "outsideGrid" places the legend outside the grid but inside the plot container, + // shrinking the grid to accomodate the legend. + // "inside" synonym for "insideGrid", + // "outside" places the legend ouside the grid area, but does not shrink the grid which + // can cause the legend to overflow the plot container. + this.placement = "insideGrid"; + // prop: xoffset + // DEPRECATED. Set the margins on the legend using the marginTop, marginLeft, etc. + // properties or via CSS margin styling of the .jqplot-table-legend class. + this.xoffset = 0; + // prop: yoffset + // DEPRECATED. Set the margins on the legend using the marginTop, marginLeft, etc. + // properties or via CSS margin styling of the .jqplot-table-legend class. + this.yoffset = 0; + // prop: border + // css spec for the border around the legend box. + this.border; + // prop: background + // css spec for the background of the legend box. + this.background; + // prop: textColor + // css color spec for the legend text. + this.textColor; + // prop: fontFamily + // css font-family spec for the legend text. + this.fontFamily; + // prop: fontSize + // css font-size spec for the legend text. + this.fontSize ; + // prop: rowSpacing + // css padding-top spec for the rows in the legend. + this.rowSpacing = '0.5em'; + // renderer + // A class that will create a DOM object for the legend, + // see <$.jqplot.TableLegendRenderer>. + this.renderer = $.jqplot.TableLegendRenderer; + // prop: rendererOptions + // renderer specific options passed to the renderer. + this.rendererOptions = {}; + // prop: predraw + // Wether to draw the legend before the series or not. + // Used with series specific legend renderers for pie, donut, mekko charts, etc. + this.preDraw = false; + // prop: marginTop + // CSS margin for the legend DOM element. This will set an element + // CSS style for the margin which will override any style sheet setting. + // The default will be taken from the stylesheet. + this.marginTop = null; + // prop: marginRight + // CSS margin for the legend DOM element. This will set an element + // CSS style for the margin which will override any style sheet setting. + // The default will be taken from the stylesheet. + this.marginRight = null; + // prop: marginBottom + // CSS margin for the legend DOM element. This will set an element + // CSS style for the margin which will override any style sheet setting. + // The default will be taken from the stylesheet. + this.marginBottom = null; + // prop: marginLeft + // CSS margin for the legend DOM element. This will set an element + // CSS style for the margin which will override any style sheet setting. + // The default will be taken from the stylesheet. + this.marginLeft = null; + + this.escapeHtml = false; + this._series = []; + + $.extend(true, this, options); + } + + Legend.prototype = new $.jqplot.ElemContainer(); + Legend.prototype.constructor = Legend; + + Legend.prototype.setOptions = function(options) { + $.extend(true, this, options); + + // Try to emulate deprecated behaviour + // if user has specified xoffset or yoffset, copy these to + // the margin properties. + + if (this.placement == 'inside') { + this.placement = 'insideGrid'; + } + + if (this.xoffset >0) { + if (this.placement == 'insideGrid') { + switch (this.location) { + case 'nw': + case 'w': + case 'sw': + if (this.marginLeft == null) { + this.marginLeft = this.xoffset + 'px'; + } + this.marginRight = '0px'; + break; + case 'ne': + case 'e': + case 'se': + default: + if (this.marginRight == null) { + this.marginRight = this.xoffset + 'px'; + } + this.marginLeft = '0px'; + break; + } + } + else if (this.placement == 'outside') { + switch (this.location) { + case 'nw': + case 'w': + case 'sw': + if (this.marginRight == null) { + this.marginRight = this.xoffset + 'px'; + } + this.marginLeft = '0px'; + break; + case 'ne': + case 'e': + case 'se': + default: + if (this.marginLeft == null) { + this.marginLeft = this.xoffset + 'px'; + } + this.marginRight = '0px'; + break; + } + } + this.xoffset = 0; + } + + if (this.yoffset >0) { + if (this.placement == 'outside') { + switch (this.location) { + case 'sw': + case 's': + case 'se': + if (this.marginTop == null) { + this.marginTop = this.yoffset + 'px'; + } + this.marginBottom = '0px'; + break; + case 'ne': + case 'n': + case 'nw': + default: + if (this.marginBottom == null) { + this.marginBottom = this.yoffset + 'px'; + } + this.marginTop = '0px'; + break; + } + } + else if (this.placement == 'insideGrid') { + switch (this.location) { + case 'sw': + case 's': + case 'se': + if (this.marginBottom == null) { + this.marginBottom = this.yoffset + 'px'; + } + this.marginTop = '0px'; + break; + case 'ne': + case 'n': + case 'nw': + default: + if (this.marginTop == null) { + this.marginTop = this.yoffset + 'px'; + } + this.marginBottom = '0px'; + break; + } + } + this.yoffset = 0; + } + + // TO-DO: + // Handle case where offsets are < 0. + // + }; + + Legend.prototype.init = function() { + this.renderer = new this.renderer(); + this.renderer.init.call(this, this.rendererOptions); + }; + + Legend.prototype.draw = function(offsets) { + for (var i=0; i<$.jqplot.preDrawLegendHooks.length; i++){ + $.jqplot.preDrawLegendHooks[i].call(this, offsets); + } + return this.renderer.draw.call(this, offsets); + }; + + Legend.prototype.pack = function(offsets) { + this.renderer.pack.call(this, offsets); + }; + + /** + * Class: Title + * Plot Title object. Cannot be instantiated directly, but created + * by the Plot oject. Title properties can be set or overriden by the + * options passed in from the user. + * + * Parameters: + * text - text of the title. + */ + function Title(text) { + $.jqplot.ElemContainer.call(this); + // Group: Properties + + // prop: text + // text of the title; + this.text = text; + // prop: show + // wether or not to show the title + this.show = true; + // prop: fontFamily + // css font-family spec for the text. + this.fontFamily; + // prop: fontSize + // css font-size spec for the text. + this.fontSize ; + // prop: textAlign + // css text-align spec for the text. + this.textAlign; + // prop: textColor + // css color spec for the text. + this.textColor; + // prop: renderer + // A class for creating a DOM element for the title, + // see <$.jqplot.DivTitleRenderer>. + this.renderer = $.jqplot.DivTitleRenderer; + // prop: rendererOptions + // renderer specific options passed to the renderer. + this.rendererOptions = {}; + } + + Title.prototype = new $.jqplot.ElemContainer(); + Title.prototype.constructor = Title; + + Title.prototype.init = function() { + this.renderer = new this.renderer(); + this.renderer.init.call(this, this.rendererOptions); + }; + + Title.prototype.draw = function(width) { + return this.renderer.draw.call(this, width); + }; + + Title.prototype.pack = function() { + this.renderer.pack.call(this); + }; + + + /** + * Class: Series + * An individual data series object. Cannot be instantiated directly, but created + * by the Plot oject. Series properties can be set or overriden by the + * options passed in from the user. + */ + function Series() { + $.jqplot.ElemContainer.call(this); + // Group: Properties + // Properties will be assigned from a series array at the top level of the + // options. If you had two series and wanted to change the color and line + // width of the first and set the second to use the secondary y axis with + // no shadow and supply custom labels for each: + // > { + // > series:[ + // > {color: '#ff4466', lineWidth: 5, label:'good line'}, + // > {yaxis: 'y2axis', shadow: false, label:'bad line'} + // > ] + // > } + + // prop: show + // wether or not to draw the series. + this.show = true; + // prop: xaxis + // which x axis to use with this series, either 'xaxis' or 'x2axis'. + this.xaxis = 'xaxis'; + this._xaxis; + // prop: yaxis + // which y axis to use with this series, either 'yaxis' or 'y2axis'. + this.yaxis = 'yaxis'; + this._yaxis; + this.gridBorderWidth = 2.0; + // prop: renderer + // A class of a renderer which will draw the series, + // see <$.jqplot.LineRenderer>. + this.renderer = $.jqplot.LineRenderer; + // prop: rendererOptions + // Options to pass on to the renderer. + this.rendererOptions = {}; + this.data = []; + this.gridData = []; + // prop: label + // Line label to use in the legend. + this.label = ''; + // prop: showLabel + // true to show label for this series in the legend. + this.showLabel = true; + // prop: color + // css color spec for the series + this.color; + // prop: lineWidth + // width of the line in pixels. May have different meanings depending on renderer. + this.lineWidth = 2.5; + // prop: lineJoin + // Canvas lineJoin style between segments of series. + this.lineJoin = 'round'; + // prop: lineCap + // Canvas lineCap style at ends of line. + this.lineCap = 'round'; + // prop: shadow + // wether or not to draw a shadow on the line + this.shadow = true; + // prop: shadowAngle + // Shadow angle in degrees + this.shadowAngle = 45; + // prop: shadowOffset + // Shadow offset from line in pixels + this.shadowOffset = 1.25; + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + this.shadowDepth = 3; + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + this.shadowAlpha = '0.1'; + // prop: breakOnNull + // Wether line segments should be be broken at null value. + // False will join point on either side of line. + this.breakOnNull = false; + // prop: markerRenderer + // A class of a renderer which will draw marker (e.g. circle, square, ...) at the data points, + // see <$.jqplot.MarkerRenderer>. + this.markerRenderer = $.jqplot.MarkerRenderer; + // prop: markerOptions + // renderer specific options to pass to the markerRenderer, + // see <$.jqplot.MarkerRenderer>. + this.markerOptions = {}; + // prop: showLine + // wether to actually draw the line or not. Series will still be renderered, even if no line is drawn. + this.showLine = true; + // prop: showMarker + // wether or not to show the markers at the data points. + this.showMarker = true; + // prop: index + // 0 based index of this series in the plot series array. + this.index; + // prop: fill + // true or false, wether to fill under lines or in bars. + // May not be implemented in all renderers. + this.fill = false; + // prop: fillColor + // CSS color spec to use for fill under line. Defaults to line color. + this.fillColor; + // prop: fillAlpha + // Alpha transparency to apply to the fill under the line. + // Use this to adjust alpha separate from fill color. + this.fillAlpha; + // prop: fillAndStroke + // If true will stroke the line (with color this.color) as well as fill under it. + // Applies only when fill is true. + this.fillAndStroke = false; + // prop: disableStack + // true to not stack this series with other series in the plot. + // To render properly, non-stacked series must come after any stacked series + // in the plot's data series array. So, the plot's data series array would look like: + // > [stackedSeries1, stackedSeries2, ..., nonStackedSeries1, nonStackedSeries2, ...] + // disableStack will put a gap in the stacking order of series, and subsequent + // stacked series will not fill down through the non-stacked series and will + // most likely not stack properly on top of the non-stacked series. + this.disableStack = false; + // _stack is set by the Plot if the plot is a stacked chart. + // will stack lines or bars on top of one another to build a "mountain" style chart. + // May not be implemented in all renderers. + this._stack = false; + // prop: neighborThreshold + // how close or far (in pixels) the cursor must be from a point marker to detect the point. + this.neighborThreshold = 4; + // prop: fillToZero + // true will force bar and filled series to fill toward zero on the fill Axis. + this.fillToZero = false; + // prop: fillToValue + // fill a filled series to this value on the fill axis. + // Works in conjunction with fillToZero, so that must be true. + this.fillToValue = 0; + // prop: fillAxis + // Either 'x' or 'y'. Which axis to fill the line toward if fillToZero is true. + // 'y' means fill up/down to 0 on the y axis for this series. + this.fillAxis = 'y'; + // prop: useNegativeColors + // true to color negative values differently in filled and bar charts. + this.useNegativeColors = true; + this._stackData = []; + // _plotData accounts for stacking. If plots not stacked, _plotData and data are same. If + // stacked, _plotData is accumulation of stacking data. + this._plotData = []; + // _plotValues hold the individual x and y values that will be plotted for this series. + this._plotValues = {x:[], y:[]}; + // statistics about the intervals between data points. Used for auto scaling. + this._intervals = {x:{}, y:{}}; + // data from the previous series, for stacked charts. + this._prevPlotData = []; + this._prevGridData = []; + this._stackAxis = 'y'; + this._primaryAxis = '_xaxis'; + // give each series a canvas to draw on. This should allow for redrawing speedups. + this.canvas = new $.jqplot.GenericCanvas(); + this.shadowCanvas = new $.jqplot.GenericCanvas(); + this.plugins = {}; + // sum of y values in this series. + this._sumy = 0; + this._sumx = 0; + this._type = ''; + } + + Series.prototype = new $.jqplot.ElemContainer(); + Series.prototype.constructor = Series; + + Series.prototype.init = function(index, gridbw, plot) { + // weed out any null values in the data. + this.index = index; + this.gridBorderWidth = gridbw; + var d = this.data; + var temp = [], i; + for (i=0; i. + this.renderer = $.jqplot.CanvasGridRenderer; + // prop: rendererOptions + // Options to pass on to the renderer, + // see <$.jqplot.CanvasGridRenderer>. + this.rendererOptions = {}; + this._offsets = {top:null, bottom:null, left:null, right:null}; + } + + Grid.prototype = new $.jqplot.ElemContainer(); + Grid.prototype.constructor = Grid; + + Grid.prototype.init = function() { + this.renderer = new this.renderer(); + this.renderer.init.call(this, this.rendererOptions); + }; + + Grid.prototype.createElement = function(offsets,plot) { + this._offsets = offsets; + return this.renderer.createElement.call(this, plot); + }; + + Grid.prototype.draw = function() { + this.renderer.draw.call(this); + }; + + $.jqplot.GenericCanvas = function() { + $.jqplot.ElemContainer.call(this); + this._ctx; + }; + + $.jqplot.GenericCanvas.prototype = new $.jqplot.ElemContainer(); + $.jqplot.GenericCanvas.prototype.constructor = $.jqplot.GenericCanvas; + + $.jqplot.GenericCanvas.prototype.createElement = function(offsets, clss, plotDimensions, plot) { + this._offsets = offsets; + var klass = 'jqplot'; + if (clss != undefined) { + klass = clss; + } + var elem; + + // if (this._elem) { + // // Memory Leaks patch + // if ($.jqplot.use_excanvas) { + // window.G_vmlCanvasManager.uninitElement(this._elem.get(0)); + // } + // } + // else { + // // don't use the canvas manager with excanvas. + // if ($.jqplot.use_excanvas) { + // elem = document.createElement('canvas'); + // } + // else { + // elem = plot.canvasManager.getCanvas(); + // } + + // } + + elem = plot.canvasManager.getCanvas(); + + // if new plotDimensions supplied, use them. + if (plotDimensions != null) { + this._plotDimensions = plotDimensions; + } + + elem.width = this._plotDimensions.width - this._offsets.left - this._offsets.right; + elem.height = this._plotDimensions.height - this._offsets.top - this._offsets.bottom; + this._elem = $(elem); + this._elem.css({ position: 'absolute', left: this._offsets.left, top: this._offsets.top }); + + this._elem.addClass(klass); + + elem = plot.canvasManager.initCanvas(elem); + + elem = null; + return this._elem; + }; + + $.jqplot.GenericCanvas.prototype.setContext = function() { + this._ctx = this._elem.get(0).getContext("2d"); + return this._ctx; + }; + + // Memory Leaks patch + $.jqplot.GenericCanvas.prototype.resetCanvas = function() { + if (this._elem) { + if ($.jqplot.use_excanvas) { + window.G_vmlCanvasManager.uninitElement(this._elem.get(0)); + } + + //this._elem.remove(); + this._elem.emptyForce(); + } + + this._ctx = null; + }; + + $.jqplot.HooksManager = function () { + this.hooks =[]; + }; + + $.jqplot.HooksManager.prototype.addOnce = function(fn) { + var havehook = false, i; + for (i=0; i { + // > axesDefaults:{min:0}, + // > series:[{color:'#6633dd'}], + // > title: 'A Plot' + // > } + // + // prop: data + // user's data. Data should *NOT* be specified in the options object, + // but be passed in as the second argument to the $.jqplot() function. + // The data property is described here soley for reference. + // The data should be in the form of an array of 2D or 1D arrays like + // > [ [[x1, y1], [x2, y2],...], [y1, y2, ...] ]. + this.data = []; + // prop dataRenderer + // A callable which can be used to preprocess data passed into the plot. + // Will be called with 2 arguments, the plot data and a reference to the plot. + this.dataRenderer; + // prop dataRendererOptions + // Options that will be passed to the dataRenderer. + // Can be of any type. + this.dataRendererOptions; + // prop noDataIndicator + // Options to set up a mock plot with a data loading indicator if no data is specified. + this.noDataIndicator = { + show: false, + indicator: 'Loading Data...', + axes: { + xaxis: { + min: 0, + max: 10, + tickInterval: 2, + show: true + }, + yaxis: { + min: 0, + max: 12, + tickInterval: 3, + show: true + } + } + }; + // The id of the dom element to render the plot into + this.targetId = null; + // the jquery object for the dom target. + this.target = null; + this.defaults = { + // prop: axesDefaults + // default options that will be applied to all axes. + // see for axes options. + axesDefaults: {}, + axes: {xaxis:{}, yaxis:{}, x2axis:{}, y2axis:{}, y3axis:{}, y4axis:{}, y5axis:{}, y6axis:{}, y7axis:{}, y8axis:{}, y9axis:{}}, + // prop: seriesDefaults + // default options that will be applied to all series. + // see for series options. + seriesDefaults: {}, + series:[] + }; + // prop: series + // Array of series object options. + // see for series specific options. + this.series = []; + // prop: axes + // up to 4 axes are supported, each with it's own options, + // See for axis specific options. + this.axes = {xaxis: new Axis('xaxis'), yaxis: new Axis('yaxis'), x2axis: new Axis('x2axis'), y2axis: new Axis('y2axis'), y3axis: new Axis('y3axis'), y4axis: new Axis('y4axis'), y5axis: new Axis('y5axis'), y6axis: new Axis('y6axis'), y7axis: new Axis('y7axis'), y8axis: new Axis('y8axis'), y9axis: new Axis('y9axis')}; + // prop: grid + // See for grid specific options. + this.grid = new Grid(); + // prop: legend + // see <$.jqplot.TableLegendRenderer> + this.legend = new Legend(); + this.baseCanvas = new $.jqplot.GenericCanvas(); + // array of series indicies. Keep track of order + // which series canvases are displayed, lowest + // to highest, back to front. + this.seriesStack = []; + this.previousSeriesStack = []; + this.eventCanvas = new $.jqplot.GenericCanvas(); + this._width = null; + this._height = null; + this._plotDimensions = {height:null, width:null}; + this._gridPadding = {top:null, right:null, bottom:null, left:null}; + this._defaultGridPadding = {top:10, right:10, bottom:23, left:10}; + // a shortcut for axis syncTicks options. Not implemented yet. + this.syncXTicks = true; + // a shortcut for axis syncTicks options. Not implemented yet. + this.syncYTicks = true; + // prop: seriesColors + // Ann array of CSS color specifications that will be applied, in order, + // to the series in the plot. Colors will wrap around so, if their + // are more series than colors, colors will be reused starting at the + // beginning. For pie charts, this specifies the colors of the slices. + this.seriesColors = $.jqplot.config.defaultColors; + this.negativeSeriesColors = $.jqplot.config.defaultNegativeColors; + // prop: sortData + // false to not sort the data passed in by the user. + // Many bar, stakced and other graphs as well as many plugins depend on + // having sorted data. + this.sortData = true; + var seriesColorsIndex = 0; + // prop textColor + // css spec for the css color attribute. Default for the entire plot. + this.textColor; + // prop; fontFamily + // css spec for the font-family attribute. Default for the entire plot. + this.fontFamily; + // prop: fontSize + // css spec for the font-size attribute. Default for the entire plot. + this.fontSize; + // prop: title + // Title object. See for specific options. As a shortcut, you + // can specify the title option as just a string like: title: 'My Plot' + // and this will create a new title object with the specified text. + this.title = new Title(); + // container to hold all of the merged options. Convienence for plugins. + this.options = {}; + // prop: stackSeries + // true or false, creates a stack or "mountain" plot. + // Not all series renderers may implement this option. + this.stackSeries = false; + // prop: defaultAxisStart + // 1-D data series are internally converted into 2-D [x,y] data point arrays + // by jqPlot. This is the default starting value for the missing x or y value. + // The added data will be a monotonically increasing series (e.g. [1, 2, 3, ...]) + // starting at this value. + this.defaultAxisStart = 1; + // array to hold the cumulative stacked series data. + // used to ajust the individual series data, which won't have access to other + // series data. + this._stackData = []; + // array that holds the data to be plotted. This will be the series data + // merged with the the appropriate data from _stackData according to the stackAxis. + this._plotData = []; + // Namespece to hold plugins. Generally non-renderer plugins add themselves to here. + this.plugins = {}; + // Count how many times the draw method has been called while the plot is visible. + // Mostly used to test if plot has never been dran (=0), has been successfully drawn + // into a visible container once (=1) or draw more than once into a visible container. + // Can use this in tests to see if plot has been visibly drawn at least one time. + // After plot has been visibly drawn once, it generally doesn't need redrawn if its + // container is hidden and shown. + this._drawCount = 0; + // this.doCustomEventBinding = true; + // prop: drawIfHidden + // True to execute the draw method even if the plot target is hidden. + // Generally, this should be false. Most plot elements will not be sized/ + // positioned correclty if renderered into a hidden container. To render into + // a hidden container, call the replot method when the container is shown. + this.drawIfHidden = false; + // true to intercept right click events and fire a 'jqplotRightClick' event. + // this will also block the context menu. + this.captureRightClick = false; + this.themeEngine = new $.jqplot.ThemeEngine(); + // sum of y values for all series in plot. + // used in mekko chart. + this._sumy = 0; + this._sumx = 0; + this.preInitHooks = new $.jqplot.HooksManager(); + this.postInitHooks = new $.jqplot.HooksManager(); + this.preParseOptionsHooks = new $.jqplot.HooksManager(); + this.postParseOptionsHooks = new $.jqplot.HooksManager(); + this.preDrawHooks = new $.jqplot.HooksManager(); + this.postDrawHooks = new $.jqplot.HooksManager(); + this.preDrawSeriesHooks = new $.jqplot.HooksManager(); + this.postDrawSeriesHooks = new $.jqplot.HooksManager(); + this.preDrawLegendHooks = new $.jqplot.HooksManager(); + this.addLegendRowHooks = new $.jqplot.HooksManager(); + this.preSeriesInitHooks = new $.jqplot.HooksManager(); + this.postSeriesInitHooks = new $.jqplot.HooksManager(); + this.preParseSeriesOptionsHooks = new $.jqplot.HooksManager(); + this.postParseSeriesOptionsHooks = new $.jqplot.HooksManager(); + this.eventListenerHooks = new $.jqplot.EventListenerManager(); + this.preDrawSeriesShadowHooks = new $.jqplot.HooksManager(); + this.postDrawSeriesShadowHooks = new $.jqplot.HooksManager(); + + this.colorGenerator = $.jqplot.ColorGenerator; + + this.canvasManager = new $.jqplot.CanvasManager(); + + // Group: methods + // + // method: init + // sets the plot target, checks data and applies user + // options to plot. + this.init = function(target, data, options) { + options = options || {}; + for (var i=0; i<$.jqplot.preInitHooks.length; i++) { + $.jqplot.preInitHooks[i].call(this, target, data, options); + } + + for (var i=0; i<this.preInitHooks.hooks.length; i++) { + this.preInitHooks.hooks[i].call(this, target, data, options); + } + + this.targetId = '#'+target; + this.target = $('#'+target); + // remove any error class that may be stuck on target. + this.target.removeClass('jqplot-error'); + if (!this.target.get(0)) { + throw "No plot target specified"; + } + + // make sure the target is positioned by some means and set css + if (this.target.css('position') == 'static') { + this.target.css('position', 'relative'); + } + if (!this.target.hasClass('jqplot-target')) { + this.target.addClass('jqplot-target'); + } + + // if no height or width specified, use a default. + if (!this.target.height()) { + var h; + if (options && options.height) { + h = parseInt(options.height, 10); + } + else if (this.target.attr('data-height')) { + h = parseInt(this.target.attr('data-height'), 10); + } + else { + h = parseInt($.jqplot.config.defaultHeight, 10); + } + this._height = h; + this.target.css('height', h+'px'); + } + else { + this._height = h = this.target.height(); + } + if (!this.target.width()) { + var w; + if (options && options.width) { + w = parseInt(options.width, 10); + } + else if (this.target.attr('data-width')) { + w = parseInt(this.target.attr('data-width'), 10); + } + else { + w = parseInt($.jqplot.config.defaultWidth, 10); + } + this._width = w; + this.target.css('width', w+'px'); + } + else { + this._width = w = this.target.width(); + } + + this._plotDimensions.height = this._height; + this._plotDimensions.width = this._width; + this.grid._plotDimensions = this._plotDimensions; + this.title._plotDimensions = this._plotDimensions; + this.baseCanvas._plotDimensions = this._plotDimensions; + this.eventCanvas._plotDimensions = this._plotDimensions; + this.legend._plotDimensions = this._plotDimensions; + if (this._height <=0 || this._width <=0 || !this._height || !this._width) { + throw "Canvas dimension not set"; + } + + if (options.dataRenderer && jQuery.isFunction(options.dataRenderer)) { + if (options.dataRendererOptions) { + this.dataRendererOptions = options.dataRendererOptions; + } + this.dataRenderer = options.dataRenderer; + data = this.dataRenderer(data, this, this.dataRendererOptions); + } + + if (options.noDataIndicator && jQuery.isPlainObject(options.noDataIndicator)) { + $.extend(true, this.noDataIndicator, options.noDataIndicator); + } + + if (data == null || jQuery.isArray(data) == false || data.length == 0 || jQuery.isArray(data[0]) == false || data[0].length == 0) { + + if (this.noDataIndicator.show == false) { + throw{ + name: "DataError", + message: "No data to plot." + }; + } + + else { + // have to be descructive here in order for plot to not try and render series. + // This means that $.jqplot() will have to be called again when there is data. + //delete options.series; + + for (var ax in this.noDataIndicator.axes) { + for (var prop in this.noDataIndicator.axes[ax]) { + this.axes[ax][prop] = this.noDataIndicator.axes[ax][prop]; + } + } + + this.postDrawHooks.add(function() { + var eh = this.eventCanvas.getHeight(); + var ew = this.eventCanvas.getWidth(); + var temp = $('<div class="jqplot-noData-container" style="position:absolute;"></div>'); + this.target.append(temp); + temp.height(eh); + temp.width(ew); + temp.css('top', this.eventCanvas._offsets.top); + temp.css('left', this.eventCanvas._offsets.left); + + var temp2 = $('<div class="jqplot-noData-contents" style="text-align:center; position:relative; margin-left:auto; margin-right:auto;"></div>'); + temp.append(temp2); + temp2.html(this.noDataIndicator.indicator); + var th = temp2.height(); + var tw = temp2.width(); + temp2.height(th); + temp2.width(tw); + temp2.css('top', (eh - th)/2 + 'px'); + }); + + } + } + + this.data = data; + + this.parseOptions(options); + + if (this.textColor) { + this.target.css('color', this.textColor); + } + if (this.fontFamily) { + this.target.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this.target.css('font-size', this.fontSize); + } + + this.title.init(); + this.legend.init(); + this._sumy = 0; + this._sumx = 0; + for (var i=0; i<this.series.length; i++) { + // set default stacking order for series canvases + this.seriesStack.push(i); + this.previousSeriesStack.push(i); + this.series[i].shadowCanvas._plotDimensions = this._plotDimensions; + this.series[i].canvas._plotDimensions = this._plotDimensions; + for (var j=0; j<$.jqplot.preSeriesInitHooks.length; j++) { + $.jqplot.preSeriesInitHooks[j].call(this.series[i], target, data, this.options.seriesDefaults, this.options.series[i], this); + } + for (var j=0; j<this.preSeriesInitHooks.hooks.length; j++) { + this.preSeriesInitHooks.hooks[j].call(this.series[i], target, data, this.options.seriesDefaults, this.options.series[i], this); + } + this.populatePlotData(this.series[i], i); + this.series[i]._plotDimensions = this._plotDimensions; + this.series[i].init(i, this.grid.borderWidth, this); + for (var j=0; j<$.jqplot.postSeriesInitHooks.length; j++) { + $.jqplot.postSeriesInitHooks[j].call(this.series[i], target, data, this.options.seriesDefaults, this.options.series[i], this); + } + for (var j=0; j<this.postSeriesInitHooks.hooks.length; j++) { + this.postSeriesInitHooks.hooks[j].call(this.series[i], target, data, this.options.seriesDefaults, this.options.series[i], this); + } + this._sumy += this.series[i]._sumy; + this._sumx += this.series[i]._sumx; + } + + for (var name in this.axes) { + this.axes[name]._plotDimensions = this._plotDimensions; + this.axes[name].init(); + } + + if (this.sortData) { + sortData(this.series); + } + this.grid.init(); + this.grid._axes = this.axes; + + this.legend._series = this.series; + + for (var i=0; i<$.jqplot.postInitHooks.length; i++) { + $.jqplot.postInitHooks[i].call(this, target, data, options); + } + + for (var i=0; i<this.postInitHooks.hooks.length; i++) { + this.postInitHooks.hooks[i].call(this, target, data, options); + } + }; + + // method: resetAxesScale + // Reset the specified axes min, max, numberTicks and tickInterval properties to null + // or reset these properties on all axes if no list of axes is provided. + // + // Parameters: + // axes - Boolean to reset or not reset all axes or an array or object of axis names to reset. + this.resetAxesScale = function(axes, options) { + var opts = options || {}; + var ax = axes || this.axes; + if (ax === true) { + ax = this.axes; + } + if (jQuery.isArray(ax)) { + for (var i = 0; i < ax.length; i++) { + this.axes[ax[i]].resetScale(opts[ax[i]]); + } + } + else if (typeof(ax) === 'object') { + for (var name in ax) { + this.axes[name].resetScale(opts[name]); + } + } + }; + // method: reInitialize + // reinitialize plot for replotting. + // not called directly. + this.reInitialize = function () { + // Plot should be visible and have a height and width. + // If plot doesn't have height and width for some + // reason, set it by other means. Plot must not have + // a display:none attribute, however. + + // + // Wont have options here + /* + if (!this.target.height()) { + var h; + if (options && options.height) { + h = parseInt(options.height, 10); + } + else if (this.target.attr('data-height')) { + h = parseInt(this.target.attr('data-height'), 10); + } + else { + h = parseInt($.jqplot.config.defaultHeight, 10); + } + this._height = h; + this.target.css('height', h+'px'); + } + else { + this._height = this.target.height(); + } + if (!this.target.width()) { + var w; + if (options && options.width) { + w = parseInt(options.width, 10); + } + else if (this.target.attr('data-width')) { + w = parseInt(this.target.attr('data-width'), 10); + } + else { + w = parseInt($.jqplot.config.defaultWidth, 10); + } + this._width = w; + this.target.css('width', w+'px'); + } + else { + this._width = this.target.width(); + } + */ + + this._height = this.target.height(); + this._width = this.target.width(); + + if (this._height <=0 || this._width <=0 || !this._height || !this._width) { + throw "Target dimension not set"; + } + + this._plotDimensions.height = this._height; + this._plotDimensions.width = this._width; + this.grid._plotDimensions = this._plotDimensions; + this.title._plotDimensions = this._plotDimensions; + this.baseCanvas._plotDimensions = this._plotDimensions; + this.eventCanvas._plotDimensions = this._plotDimensions; + this.legend._plotDimensions = this._plotDimensions; + + for (var n in this.axes) { + this.axes[n]._plotWidth = this._width; + this.axes[n]._plotHeight = this._height; + } + + this.title._plotWidth = this._width; + + if (this.textColor) { + this.target.css('color', this.textColor); + } + if (this.fontFamily) { + this.target.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this.target.css('font-size', this.fontSize); + } + + this._sumy = 0; + this._sumx = 0; + for (var i=0; i<this.series.length; i++) { + this.populatePlotData(this.series[i], i); + this.series[i]._plotDimensions = this._plotDimensions; + this.series[i].canvas._plotDimensions = this._plotDimensions; + //this.series[i].init(i, this.grid.borderWidth); + this._sumy += this.series[i]._sumy; + this._sumx += this.series[i]._sumx; + } + + for (var name in this.axes) { + // Memory Leaks patch : clear ticks elements + var t = this.axes[name]._ticks; + for (var i = 0; i < t.length; i++) { + var el = t[i]._elem; + if (el) { + // if canvas renderer + if ($.jqplot.use_excanvas) { + window.G_vmlCanvasManager.uninitElement(el.get(0)); + } + el.emptyForce(); + el = null; + t._elem = null; + } + } + t = null; + + this.axes[name]._plotDimensions = this._plotDimensions; + this.axes[name]._ticks = []; + this.axes[name].renderer.init.call(this.axes[name], {}); + } + + if (this.sortData) { + sortData(this.series); + } + + this.grid._axes = this.axes; + + this.legend._series = this.series; + }; + + // sort the series data in increasing order. + function sortData(series) { + var d, sd, pd, ppd, ret; + for (var i=0; i<series.length; i++) { + // d = series[i].data; + // sd = series[i]._stackData; + // pd = series[i]._plotData; + // ppd = series[i]._prevPlotData; + var check; + var bat = [series[i].data, series[i]._stackData, series[i]._plotData, series[i]._prevPlotData]; + for (var n=0; n<4; n++) { + check = true; + d = bat[n]; + if (series[i]._stackAxis == 'x') { + for (var j = 0; j < d.length; j++) { + if (typeof(d[j][1]) != "number") { + check = false; + break; + } + } + if (check) { + d.sort(function(a,b) { return a[1] - b[1]; }); + // sd.sort(function(a,b) { return a[1] - b[1]; }); + // pd.sort(function(a,b) { return a[1] - b[1]; }); + // ppd.sort(function(a,b) { return a[1] - b[1]; }); + } + } + else { + for (var j = 0; j < d.length; j++) { + if (typeof(d[j][0]) != "number") { + check = false; + break; + } + } + if (check) { + d.sort(function(a,b) { return a[0] - b[0]; }); + // sd.sort(function(a,b) { return a[0] - b[0]; }); + // pd.sort(function(a,b) { return a[0] - b[0]; }); + // ppd.sort(function(a,b) { return a[0] - b[0]; }); + } + } + } + + } + } + + // populate the _stackData and _plotData arrays for the plot and the series. + this.populatePlotData = function(series, index) { + // if a stacked chart, compute the stacked data + this._plotData = []; + this._stackData = []; + series._stackData = []; + series._plotData = []; + var plotValues = {x:[], y:[]}; + if (this.stackSeries && !series.disableStack) { + series._stack = true; + var sidx = series._stackAxis == 'x' ? 0 : 1; + var idx = sidx ? 0 : 1; + // push the current data into stackData + //this._stackData.push(this.series[i].data); + var temp = $.extend(true, [], series.data); + // create the data that will be plotted for this series + var plotdata = $.extend(true, [], series.data); + // for first series, nothing to add to stackData. + for (var j=0; j<index; j++) { + var cd = this.series[j].data; + for (var k=0; k<cd.length; k++) { + temp[k][0] += cd[k][0]; + temp[k][1] += cd[k][1]; + // only need to sum up the stack axis column of data + plotdata[k][sidx] += cd[k][sidx]; + } + } + for (var i=0; i<plotdata.length; i++) { + plotValues.x.push(plotdata[i][0]); + plotValues.y.push(plotdata[i][1]); + } + this._plotData.push(plotdata); + this._stackData.push(temp); + series._stackData = temp; + series._plotData = plotdata; + series._plotValues = plotValues; + } + else { + for (var i=0; i<series.data.length; i++) { + plotValues.x.push(series.data[i][0]); + plotValues.y.push(series.data[i][1]); + } + this._stackData.push(series.data); + this.series[index]._stackData = series.data; + this._plotData.push(series.data); + series._plotData = series.data; + series._plotValues = plotValues; + } + if (index>0) { + series._prevPlotData = this.series[index-1]._plotData; + } + series._sumy = 0; + series._sumx = 0; + for (i=series.data.length-1; i>-1; i--) { + series._sumy += series.data[i][1]; + series._sumx += series.data[i][0]; + } + }; + + // this.setData = function(seriesIndex, newdata) { + // // if newdata is null, assume all data is passed in as first argument + // if (newdata == null) { + + // } + // }; + + // function to safely return colors from the color array and wrap around at the end. + this.getNextSeriesColor = (function(t) { + var idx = 0; + var sc = t.seriesColors; + + return function () { + if (idx < sc.length) { + return sc[idx++]; + } + else { + idx = 0; + return sc[idx++]; + } + }; + })(this); + + this.parseOptions = function(options){ + for (var i=0; i<this.preParseOptionsHooks.hooks.length; i++) { + this.preParseOptionsHooks.hooks[i].call(this, options); + } + for (var i=0; i<$.jqplot.preParseOptionsHooks.length; i++) { + $.jqplot.preParseOptionsHooks[i].call(this, options); + } + this.options = $.extend(true, {}, this.defaults, options); + this.stackSeries = this.options.stackSeries; + if (this.options.seriesColors) { + this.seriesColors = this.options.seriesColors; + } + if (this.options.negativeSeriesColors) { + this.negativeSeriesColors = this.options.negativeSeriesColors; + } + if (this.options.captureRightClick) { + this.captureRightClick = this.options.captureRightClick; + } + this.defaultAxisStart = (options && options.defaultAxisStart != null) ? options.defaultAxisStart : this.defaultAxisStart; + var cg = new this.colorGenerator(this.seriesColors); + // this._gridPadding = this.options.gridPadding; + $.extend(true, this._gridPadding, this.options.gridPadding); + this.sortData = (this.options.sortData != null) ? this.options.sortData : this.sortData; + for (var n in this.axes) { + var axis = this.axes[n]; + axis._options = $.extend(true, {}, this.options.axesDefaults, this.options.axes[n]); + $.extend(true, axis, this.options.axesDefaults, this.options.axes[n]); + axis._plotWidth = this._width; + axis._plotHeight = this._height; + } + // if (this.data.length == 0) { + // this.data = []; + // for (var i=0; i<this.options.series.length; i++) { + // this.data.push(this.options.series.data); + // } + // } + + var normalizeData = function(data, dir, start) { + // return data as an array of point arrays, + // in form [[x1,y1...], [x2,y2...], ...] + var temp = []; + var i; + dir = dir || 'vertical'; + if (!jQuery.isArray(data[0])) { + // we have a series of scalars. One line with just y values. + // turn the scalar list of data into a data array of form: + // [[1, data[0]], [2, data[1]], ...] + for (i=0; i<data.length; i++) { + if (dir == 'vertical') { + temp.push([start + i, data[i]]); + } + else { + temp.push([data[i], start+i]); + } + } + } + else { + // we have a properly formatted data series, copy it. + $.extend(true, temp, data); + } + return temp; + }; + + for (var i=0; i<this.data.length; i++) { + var temp = new Series(); + for (var j=0; j<$.jqplot.preParseSeriesOptionsHooks.length; j++) { + $.jqplot.preParseSeriesOptionsHooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]); + } + for (var j=0; j<this.preParseSeriesOptionsHooks.hooks.length; j++) { + this.preParseSeriesOptionsHooks.hooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]); + } + $.extend(true, temp, {seriesColors:this.seriesColors, negativeSeriesColors:this.negativeSeriesColors}, this.options.seriesDefaults, this.options.series[i]); + var dir = 'vertical'; + if (temp.renderer === $.jqplot.BarRenderer && temp.rendererOptions && temp.rendererOptions.barDirection == 'horizontal') { + dir = 'horizontal'; + } + temp.data = normalizeData(this.data[i], dir, this.defaultAxisStart); + switch (temp.xaxis) { + case 'xaxis': + temp._xaxis = this.axes.xaxis; + break; + case 'x2axis': + temp._xaxis = this.axes.x2axis; + break; + default: + break; + } + temp._yaxis = this.axes[temp.yaxis]; + temp._xaxis._series.push(temp); + temp._yaxis._series.push(temp); + if (temp.show) { + temp._xaxis.show = true; + temp._yaxis.show = true; + } + + // parse the renderer options and apply default colors if not provided + if (!temp.color && temp.show != false) { + temp.color = cg.next(); + } + if (!temp.label) { + temp.label = 'Series '+ (i+1).toString(); + } + // temp.rendererOptions.show = temp.show; + // $.extend(true, temp.renderer, {color:this.seriesColors[i]}, this.rendererOptions); + this.series.push(temp); + for (var j=0; j<$.jqplot.postParseSeriesOptionsHooks.length; j++) { + $.jqplot.postParseSeriesOptionsHooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]); + } + for (var j=0; j<this.postParseSeriesOptionsHooks.hooks.length; j++) { + this.postParseSeriesOptionsHooks.hooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]); + } + } + + // copy the grid and title options into this object. + $.extend(true, this.grid, this.options.grid); + // if axis border properties aren't set, set default. + for (var n in this.axes) { + var axis = this.axes[n]; + if (axis.borderWidth == null) { + axis.borderWidth =this.grid.borderWidth; + } + if (axis.borderColor == null) { + if (n != 'xaxis' && n != 'x2axis' && axis.useSeriesColor === true && axis.show) { + axis.borderColor = axis._series[0].color; + } + else { + axis.borderColor = this.grid.borderColor; + } + } + } + + if (typeof this.options.title == 'string') { + this.title.text = this.options.title; + } + else if (typeof this.options.title == 'object') { + $.extend(true, this.title, this.options.title); + } + this.title._plotWidth = this._width; + this.legend.setOptions(this.options.legend); + + for (var i=0; i<$.jqplot.postParseOptionsHooks.length; i++) { + $.jqplot.postParseOptionsHooks[i].call(this, options); + } + for (var i=0; i<this.postParseOptionsHooks.hooks.length; i++) { + this.postParseOptionsHooks.hooks[i].call(this, options); + } + }; + + // method: destroy + // Releases all resources occupied by the plot + this.destroy = function() { + this.canvasManager.freeAllCanvases(); + this.target[0].innerHTML = ''; + }; + + // method: replot + // Does a reinitialization of the plot followed by + // a redraw. Method could be used to interactively + // change plot characteristics and then replot. + // + // Parameters: + // options - Options used for replotting. + // + // Properties: + // clear - false to not clear (empty) the plot container before replotting (default: true). + // resetAxes - true to reset all axes min, max, numberTicks and tickInterval setting so axes will rescale themselves. + // optionally pass in list of axes to reset (e.g. ['xaxis', 'y2axis']) (default: false). + this.replot = function(options) { + var opts = options || {}; + var clear = opts.clear || true; + var resetAxes = opts.resetAxes || false; + this.target.trigger('jqplotPreReplot'); + + if (clear) { + this.canvasManager.freeAllCanvases(); + // Memory Leaks patch + // this.target.find("table.jqplot-table-legend,table.jqplot-legend").each( function() { + // $(this).unbind(); + + // $(this).find(".jqplot-seriesToggle").each( function() { + // $(this).unbind(); + // }); + // $.gcCollect(this); + // }); + + // this.target.find(".jqplot-title").each( function() { + // $(this).unbind(); + // $.gcCollect(this); + // }); + + // $.gcClear(); + + if (this._eventCanvas) { + this.eventCanvas._elem.unbind(); + } + this.target.unbind(); + + // Couple of posts on Stack Overflow indicate that empty() doesn't + // always cear up the dom and release memory. Sometimes setting + // innerHTML property to null is needed. Particularly on IE, may + // have to directly set it to null, bypassing jQuery. + this.target.empty(); + } + this.reInitialize(); + if (resetAxes) { + this.resetAxesScale(resetAxes, opts.axes); + } + this.draw(); + this.target.trigger('jqplotPostReplot'); + }; + + // method: redraw + // Empties the plot target div and redraws the plot. + // This enables plot data and properties to be changed + // and then to comletely clear the plot and redraw. + // redraw *will not* reinitialize any plot elements. + // That is, axes will not be autoscaled and defaults + // will not be reapplied to any plot elements. redraw + // is used primarily with zooming. + // + // Parameters: + // clear - false to not clear (empty) the plot container before redrawing (default: true). + this.redraw = function(clear) { + clear = (clear != null) ? clear : true; + this.target.trigger('jqplotPreRedraw'); + if (clear) { + this.canvasManager.freeAllCanvases(); + this.eventCanvas._elem.unbind(); + this.target.unbind(); + this.target.empty(); + } + for (var ax in this.axes) { + this.axes[ax]._ticks = []; + } + for (var i=0; i<this.series.length; i++) { + this.populatePlotData(this.series[i], i); + } + this._sumy = 0; + this._sumx = 0; + for (i=0; i<this.series.length; i++) { + this._sumy += this.series[i]._sumy; + this._sumx += this.series[i]._sumx; + } + this.draw(); + this.target.trigger('jqplotPostRedraw'); + }; + + // method: draw + // Draws all elements of the plot into the container. + // Does not clear the container before drawing. + this.draw = function(){ + if (this.drawIfHidden || this.target.is(':visible')) { + this.target.trigger('jqplotPreDraw'); + var i, j; + for (i=0; i<$.jqplot.preDrawHooks.length; i++) { + $.jqplot.preDrawHooks[i].call(this); + } + for (i=0; i<this.preDrawHooks.hooks.length; i++) { + this.preDrawHooks.hooks[i].call(this); + } + // create an underlying canvas to be used for special features. + this.target.append(this.baseCanvas.createElement({left:0, right:0, top:0, bottom:0}, 'jqplot-base-canvas', null, this)); + this.baseCanvas.setContext(); + this.target.append(this.title.draw()); + this.title.pack({top:0, left:0}); + + // make room for the legend between the grid and the edge. + var legendElem = this.legend.draw(); + + var gridPadding = {top:0, left:0, bottom:0, right:0}; + + if (this.legend.placement == "outsideGrid") { + // temporarily append the legend to get dimensions + this.target.append(legendElem); + switch (this.legend.location) { + case 'n': + gridPadding.top += this.legend.getHeight(); + break; + case 's': + gridPadding.bottom += this.legend.getHeight(); + break; + case 'ne': + case 'e': + case 'se': + gridPadding.right += this.legend.getWidth(); + break; + case 'nw': + case 'w': + case 'sw': + gridPadding.left += this.legend.getWidth(); + break; + default: // same as 'ne' + gridPadding.right += this.legend.getWidth(); + break; + } + legendElem = legendElem.detach(); + } + + var ax = this.axes; + for (var name in ax) { + this.target.append(ax[name].draw(this.baseCanvas._ctx, this)); + ax[name].set(); + } + if (ax.yaxis.show) { + gridPadding.left += ax.yaxis.getWidth(); + } + var ra = ['y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis']; + var rapad = [0, 0, 0, 0, 0, 0, 0, 0]; + var gpr = 0; + var n; + for (n=0; n<8; n++) { + if (ax[ra[n]].show) { + gpr += ax[ra[n]].getWidth(); + rapad[n] = gpr; + } + } + gridPadding.right += gpr; + if (ax.x2axis.show) { + gridPadding.top += ax.x2axis.getHeight(); + } + if (this.title.show) { + gridPadding.top += this.title.getHeight(); + } + if (ax.xaxis.show) { + gridPadding.bottom += ax.xaxis.getHeight(); + } + + // end of gridPadding adjustments. + var arr = ['top', 'bottom', 'left', 'right']; + for (var n in arr) { + if (this._gridPadding[arr[n]] == null && gridPadding[arr[n]] > 0) { + this._gridPadding[arr[n]] = gridPadding[arr[n]]; + } + else if (this._gridPadding[arr[n]] == null) { + this._gridPadding[arr[n]] = this._defaultGridPadding[arr[n]]; + } + } + + var legendPadding = (this.legend.placement == 'outsideGrid') ? {top:this.title.getHeight(), left: 0, right: 0, bottom: 0} : this._gridPadding; + + ax.xaxis.pack({position:'absolute', bottom:this._gridPadding.bottom - ax.xaxis.getHeight(), left:0, width:this._width}, {min:this._gridPadding.left, max:this._width - this._gridPadding.right}); + ax.yaxis.pack({position:'absolute', top:0, left:this._gridPadding.left - ax.yaxis.getWidth(), height:this._height}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top}); + ax.x2axis.pack({position:'absolute', top:this._gridPadding.top - ax.x2axis.getHeight(), left:0, width:this._width}, {min:this._gridPadding.left, max:this._width - this._gridPadding.right}); + for (i=8; i>0; i--) { + ax[ra[i-1]].pack({position:'absolute', top:0, right:this._gridPadding.right - rapad[i-1]}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top}); + } + // ax.y2axis.pack({position:'absolute', top:0, right:0}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top}); + + this.target.append(this.grid.createElement(this._gridPadding, this)); + this.grid.draw(); + + // put the shadow canvases behind the series canvases so shadows don't overlap on stacked bars. + for (i=0; i<this.series.length; i++) { + // draw series in order of stacking. This affects only + // order in which canvases are added to dom. + j = this.seriesStack[i]; + this.target.append(this.series[j].shadowCanvas.createElement(this._gridPadding, 'jqplot-series-shadowCanvas', null, this)); + this.series[j].shadowCanvas.setContext(); + this.series[j].shadowCanvas._elem.data('seriesIndex', j); + } + + for (i=0; i<this.series.length; i++) { + // draw series in order of stacking. This affects only + // order in which canvases are added to dom. + j = this.seriesStack[i]; + this.target.append(this.series[j].canvas.createElement(this._gridPadding, 'jqplot-series-canvas', null, this)); + this.series[j].canvas.setContext(); + this.series[j].canvas._elem.data('seriesIndex', j); + } + // Need to use filled canvas to capture events in IE. + // Also, canvas seems to block selection of other elements in document on FF. + this.target.append(this.eventCanvas.createElement(this._gridPadding, 'jqplot-event-canvas', null, this)); + this.eventCanvas.setContext(); + this.eventCanvas._ctx.fillStyle = 'rgba(0,0,0,0)'; + this.eventCanvas._ctx.fillRect(0,0,this.eventCanvas._ctx.canvas.width, this.eventCanvas._ctx.canvas.height); + + // bind custom event handlers to regular events. + this.bindCustomEvents(); + + // draw legend before series if the series needs to know the legend dimensions. + if (this.legend.preDraw) { + this.eventCanvas._elem.before(legendElem); + this.legend.pack(legendPadding); + if (this.legend._elem) { + this.drawSeries({legendInfo:{location:this.legend.location, placement:this.legend.placement, width:this.legend.getWidth(), height:this.legend.getHeight(), xoffset:this.legend.xoffset, yoffset:this.legend.yoffset}}); + } + else { + this.drawSeries(); + } + } + else { // draw series before legend + this.drawSeries(); + if (this.series.length) { + $(this.series[this.series.length-1].canvas._elem).after(legendElem); + } + this.legend.pack(legendPadding); + } + + // register event listeners on the overlay canvas + for (var i=0; i<$.jqplot.eventListenerHooks.length; i++) { + // in the handler, this will refer to the eventCanvas dom element. + // make sure there are references back into plot objects. + this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]); + } + + // register event listeners on the overlay canvas + for (var i=0; i<this.eventListenerHooks.hooks.length; i++) { + // in the handler, this will refer to the eventCanvas dom element. + // make sure there are references back into plot objects. + this.eventCanvas._elem.bind(this.eventListenerHooks.hooks[i][0], {plot:this}, this.eventListenerHooks.hooks[i][1]); + } + + for (var i=0; i<$.jqplot.postDrawHooks.length; i++) { + $.jqplot.postDrawHooks[i].call(this); + } + + for (var i=0; i<this.postDrawHooks.hooks.length; i++) { + this.postDrawHooks.hooks[i].call(this); + } + + if (this.target.is(':visible')) { + this._drawCount += 1; + } + + this.target.trigger('jqplotPostDraw', [this]); + } + }; + + this.bindCustomEvents = function() { + this.eventCanvas._elem.bind('click', {plot:this}, this.onClick); + this.eventCanvas._elem.bind('dblclick', {plot:this}, this.onDblClick); + this.eventCanvas._elem.bind('mousedown', {plot:this}, this.onMouseDown); + this.eventCanvas._elem.bind('mousemove', {plot:this}, this.onMouseMove); + this.eventCanvas._elem.bind('mouseenter', {plot:this}, this.onMouseEnter); + this.eventCanvas._elem.bind('mouseleave', {plot:this}, this.onMouseLeave); + if (this.captureRightClick) { + this.eventCanvas._elem.bind('mouseup', {plot:this}, this.onRightClick); + this.eventCanvas._elem.get(0).oncontextmenu = function() { + return false; + }; + } + else { + this.eventCanvas._elem.bind('mouseup', {plot:this}, this.onMouseUp); + } + }; + + function getEventPosition(ev) { + var plot = ev.data.plot; + var go = plot.eventCanvas._elem.offset(); + var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top}; + var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null}; + var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis']; + var ax = plot.axes; + var n, axis; + for (n=11; n>0; n--) { + axis = an[n-1]; + if (ax[axis].show) { + dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]); + } + } + + return {offsets:go, gridPos:gridPos, dataPos:dataPos}; + } + + + // function to check if event location is over a area area + function checkIntersection(gridpos, plot) { + var series = plot.series; + var i, j, k, s, r, x, y, theta, sm, sa, minang, maxang; + var d0, d, p, pp, points, bw; + var threshold, t; + for (k=plot.seriesStack.length-1; k>=0; k--) { + i = plot.seriesStack[k]; + s = series[i]; + switch (s.renderer.constructor) { + case $.jqplot.BarRenderer: + x = gridpos.x; + y = gridpos.y; + for (j=0; j<s._barPoints.length; j++) { + points = s._barPoints[j]; + p = s.gridData[j]; + if (x>points[0][0] && x<points[2][0] && y>points[2][1] && y<points[0][1]) { + return {seriesIndex:s.index, pointIndex:j, gridData:p, data:s.data[j], points:s._barPoints[j]}; + } + } + break; + + case $.jqplot.DonutRenderer: + sa = s.startAngle/180*Math.PI; + x = gridpos.x - s._center[0]; + y = gridpos.y - s._center[1]; + r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + if (x > 0 && -y >= 0) { + theta = 2*Math.PI - Math.atan(-y/x); + } + else if (x > 0 && -y < 0) { + theta = -Math.atan(-y/x); + } + else if (x < 0) { + theta = Math.PI - Math.atan(-y/x); + } + else if (x == 0 && -y > 0) { + theta = 3*Math.PI/2; + } + else if (x == 0 && -y < 0) { + theta = Math.PI/2; + } + else if (x == 0 && y == 0) { + theta = 0; + } + if (sa) { + theta -= sa; + if (theta < 0) { + theta += 2*Math.PI; + } + else if (theta > 2*Math.PI) { + theta -= 2*Math.PI; + } + } + + sm = s.sliceMargin/180*Math.PI; + if (r < s._radius && r > s._innerRadius) { + for (j=0; j<s.gridData.length; j++) { + minang = (j>0) ? s.gridData[j-1][1]+sm : sm; + maxang = s.gridData[j][1]; + if (theta > minang && theta < maxang) { + return {seriesIndex:s.index, pointIndex:j, gridData:s.gridData[j], data:s.data[j]}; + } + } + } + break; + + case $.jqplot.PieRenderer: + sa = s.startAngle/180*Math.PI; + x = gridpos.x - s._center[0]; + y = gridpos.y - s._center[1]; + r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + if (x > 0 && -y >= 0) { + theta = 2*Math.PI - Math.atan(-y/x); + } + else if (x > 0 && -y < 0) { + theta = -Math.atan(-y/x); + } + else if (x < 0) { + theta = Math.PI - Math.atan(-y/x); + } + else if (x == 0 && -y > 0) { + theta = 3*Math.PI/2; + } + else if (x == 0 && -y < 0) { + theta = Math.PI/2; + } + else if (x == 0 && y == 0) { + theta = 0; + } + if (sa) { + theta -= sa; + if (theta < 0) { + theta += 2*Math.PI; + } + else if (theta > 2*Math.PI) { + theta -= 2*Math.PI; + } + } + + sm = s.sliceMargin/180*Math.PI; + if (r < s._radius) { + for (j=0; j<s.gridData.length; j++) { + minang = (j>0) ? s.gridData[j-1][1]+sm : sm; + maxang = s.gridData[j][1]; + if (theta > minang && theta < maxang) { + return {seriesIndex:s.index, pointIndex:j, gridData:s.gridData[j], data:s.data[j]}; + } + } + } + break; + + case $.jqplot.BubbleRenderer: + x = gridpos.x; + y = gridpos.y; + var ret = null; + + if (s.show) { + for (var j=0; j<s.gridData.length; j++) { + p = s.gridData[j]; + d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) ); + if (d <= p[2] && (d <= d0 || d0 == null)) { + d0 = d; + ret = {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + if (ret != null) { + return ret; + } + } + break; + + case $.jqplot.FunnelRenderer: + x = gridpos.x; + y = gridpos.y; + var v = s._vertices, + vfirst = v[0], + vlast = v[v.length-1], + lex, + rex, + cv; + + // equations of right and left sides, returns x, y values given height of section (y value and 2 points) + + function findedge (l, p1 , p2) { + var m = (p1[1] - p2[1])/(p1[0] - p2[0]); + var b = p1[1] - m*p1[0]; + var y = l + p1[1]; + + return [(y - b)/m, y]; + } + + // check each section + lex = findedge(y, vfirst[0], vlast[3]); + rex = findedge(y, vfirst[1], vlast[2]); + for (j=0; j<v.length; j++) { + cv = v[j]; + if (y >= cv[0][1] && y <= cv[3][1] && x >= lex[0] && x <= rex[0]) { + return {seriesIndex:s.index, pointIndex:j, gridData:null, data:s.data[j]}; + } + } + break; + + case $.jqplot.LineRenderer: + x = gridpos.x; + y = gridpos.y; + r = s.renderer; + if (s.show) { + if (s.fill) { + // first check if it is in bounding box + var inside = false; + if (x>s._boundingBox[0][0] && x<s._boundingBox[1][0] && y>s._boundingBox[1][1] && y<s._boundingBox[0][1]) { + // now check the crossing number + + var numPoints = s._areaPoints.length; + var ii; + var j = numPoints-1; + + for(var ii=0; ii < numPoints; ii++) { + var vertex1 = [s._areaPoints[ii][0], s._areaPoints[ii][1]]; + var vertex2 = [s._areaPoints[j][0], s._areaPoints[j][1]]; + + if (vertex1[1] < y && vertex2[1] >= y || vertex2[1] < y && vertex1[1] >= y) { + if (vertex1[0] + (y - vertex1[1]) / (vertex2[1] - vertex1[1]) * (vertex2[0] - vertex1[0]) < x) { + inside = !inside; + } + } + + j = ii; + } + } + if (inside) { + return {seriesIndex:i, pointIndex:null, gridData:s.gridData, data:s.data, points:s._areaPoints}; + } + break; + + } + else { + t = s.markerRenderer.size/2+s.neighborThreshold; + threshold = (t > 0) ? t : 0; + for (var j=0; j<s.gridData.length; j++) { + p = s.gridData[j]; + // neighbor looks different to OHLC chart. + if (r.constructor == $.jqplot.OHLCRenderer) { + if (r.candleStick) { + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + // if an open hi low close chart + else if (!r.hlc){ + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + // a hi low close chart + else { + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][1]) && y <= yp(s.data[j][2])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + + } + else if (p[0] != null && p[1] != null){ + d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) ); + if (d <= threshold && (d <= d0 || d0 == null)) { + d0 = d; + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + } + } + } + break; + + default: + x = gridpos.x; + y = gridpos.y; + r = s.renderer; + if (s.show) { + t = s.markerRenderer.size/2+s.neighborThreshold; + threshold = (t > 0) ? t : 0; + for (var j=0; j<s.gridData.length; j++) { + p = s.gridData[j]; + // neighbor looks different to OHLC chart. + if (r.constructor == $.jqplot.OHLCRenderer) { + if (r.candleStick) { + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + // if an open hi low close chart + else if (!r.hlc){ + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + // a hi low close chart + else { + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][1]) && y <= yp(s.data[j][2])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + + } + else { + d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) ); + if (d <= threshold && (d <= d0 || d0 == null)) { + d0 = d; + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + } + } + break; + } + } + + return null; + } + + + + this.onClick = function(ev) { + // Event passed in is normalized and will have data attribute. + // Event passed out is unnormalized. + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + var evt = jQuery.Event('jqplotClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + }; + + this.onDblClick = function(ev) { + // Event passed in is normalized and will have data attribute. + // Event passed out is unnormalized. + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + var evt = jQuery.Event('jqplotDblClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + }; + + this.onMouseDown = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + var evt = jQuery.Event('jqplotMouseDown'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + }; + + this.onMouseUp = function(ev) { + var positions = getEventPosition(ev); + var evt = jQuery.Event('jqplotMouseUp'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, ev.data.plot]); + }; + + this.onRightClick = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + if (p.captureRightClick) { + if (ev.which == 3) { + var evt = jQuery.Event('jqplotRightClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + } + else { + var evt = jQuery.Event('jqplotMouseUp'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + } + } + }; + + this.onMouseMove = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + var evt = jQuery.Event('jqplotMouseMove'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + }; + + this.onMouseEnter = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var evt = jQuery.Event('jqplotMouseEnter'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, p]); + }; + + this.onMouseLeave = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var evt = jQuery.Event('jqplotMouseLeave'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, p]); + }; + + // method: drawSeries + // Redraws all or just one series on the plot. No axis scaling + // is performed and no other elements on the plot are redrawn. + // options is an options object to pass on to the series renderers. + // It can be an empty object {}. idx is the series index + // to redraw if only one series is to be redrawn. + this.drawSeries = function(options, idx){ + var i, series, ctx; + // if only one argument passed in and it is a number, use it ad idx. + idx = (typeof(options) === "number" && idx == null) ? options : idx; + options = (typeof(options) === "object") ? options : {}; + // draw specified series + if (idx != undefined) { + series = this.series[idx]; + ctx = series.shadowCanvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + series.drawShadow(ctx, options, this); + ctx = series.canvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + series.draw(ctx, options, this); + if (series.renderer.constructor == $.jqplot.BezierCurveRenderer) { + if (idx < this.series.length - 1) { + this.drawSeries(idx+1); + } + } + } + + else { + // if call series drawShadow method first, in case all series shadows + // should be drawn before any series. This will ensure, like for + // stacked bar plots, that shadows don't overlap series. + for (i=0; i<this.series.length; i++) { + // first clear the canvas + series = this.series[i]; + ctx = series.shadowCanvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + series.drawShadow(ctx, options, this); + ctx = series.canvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + series.draw(ctx, options, this); + } + } + options = idx = i = series = ctx = null; + }; + + // method: moveSeriesToFront + // This method requires jQuery 1.4+ + // Moves the specified series canvas in front of all other series canvases. + // This effectively "draws" the specified series on top of all other series, + // although it is performed through DOM manipulation, no redrawing is performed. + // + // Parameters: + // idx - 0 based index of the series to move. This will be the index of the series + // as it was first passed into the jqplot function. + this.moveSeriesToFront = function (idx) { + idx = parseInt(idx, 10); + var stackIndex = $.inArray(idx, this.seriesStack); + // if already in front, return + if (stackIndex == -1) { + return; + } + if (stackIndex == this.seriesStack.length -1) { + this.previousSeriesStack = this.seriesStack.slice(0); + return; + } + var opidx = this.seriesStack[this.seriesStack.length -1]; + var serelem = this.series[idx].canvas._elem.detach(); + var shadelem = this.series[idx].shadowCanvas._elem.detach(); + this.series[opidx].shadowCanvas._elem.after(shadelem); + this.series[opidx].canvas._elem.after(serelem); + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack.splice(stackIndex, 1); + this.seriesStack.push(idx); + }; + + // method: moveSeriesToBack + // This method requires jQuery 1.4+ + // Moves the specified series canvas behind all other series canvases. + // + // Parameters: + // idx - 0 based index of the series to move. This will be the index of the series + // as it was first passed into the jqplot function. + this.moveSeriesToBack = function (idx) { + idx = parseInt(idx, 10); + var stackIndex = $.inArray(idx, this.seriesStack); + // if already in back, return + if (stackIndex == 0 || stackIndex == -1) { + return; + } + var opidx = this.seriesStack[0]; + var serelem = this.series[idx].canvas._elem.detach(); + var shadelem = this.series[idx].shadowCanvas._elem.detach(); + this.series[opidx].shadowCanvas._elem.before(shadelem); + this.series[opidx].canvas._elem.before(serelem); + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack.splice(stackIndex, 1); + this.seriesStack.unshift(idx); + }; + + // method: restorePreviousSeriesOrder + // This method requires jQuery 1.4+ + // Restore the series canvas order to its previous state. + // Useful to put a series back where it belongs after moving + // it to the front. + this.restorePreviousSeriesOrder = function () { + var i, j, serelem, shadelem, temp, move, keep; + // if no change, return. + if (this.seriesStack == this.previousSeriesStack) { + return; + } + for (i=1; i<this.previousSeriesStack.length; i++) { + move = this.previousSeriesStack[i]; + keep = this.previousSeriesStack[i-1]; + serelem = this.series[move].canvas._elem.detach(); + shadelem = this.series[move].shadowCanvas._elem.detach(); + this.series[keep].shadowCanvas._elem.after(shadelem); + this.series[keep].canvas._elem.after(serelem); + } + temp = this.seriesStack.slice(0); + this.seriesStack = this.previousSeriesStack.slice(0); + this.previousSeriesStack = temp; + }; + + // method: restoreOriginalSeriesOrder + // This method requires jQuery 1.4+ + // Restore the series canvas order to its original order + // when the plot was created. + this.restoreOriginalSeriesOrder = function () { + var i, j, arr=[], serelem, shadelem; + for (i=0; i<this.series.length; i++) { + arr.push(i); + } + if (this.seriesStack == arr) { + return; + } + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack = arr; + for (i=1; i<this.seriesStack.length; i++) { + serelem = this.series[i].canvas._elem.detach(); + shadelem = this.series[i].shadowCanvas._elem.detach(); + this.series[i-1].shadowCanvas._elem.after(shadelem); + this.series[i-1].canvas._elem.after(serelem); + } + }; + + this.activateTheme = function (name) { + this.themeEngine.activate(this, name); + }; + } + + + // conpute a highlight color or array of highlight colors from given colors. + $.jqplot.computeHighlightColors = function(colors) { + var ret; + if (jQuery.isArray(colors)) { + ret = []; + for (var i=0; i<colors.length; i++){ + var rgba = $.jqplot.getColorComponents(colors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + ret.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + } + } + else { + var rgba = $.jqplot.getColorComponents(colors); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + ret = 'rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'; + } + return ret; + }; + + $.jqplot.ColorGenerator = function(colors) { + colors = colors || $.jqplot.config.defaultColors; + var idx = 0; + + this.next = function () { + if (idx < colors.length) { + return colors[idx++]; + } + else { + idx = 0; + return colors[idx++]; + } + }; + + this.previous = function () { + if (idx > 0) { + return colors[idx--]; + } + else { + idx = colors.length-1; + return colors[idx]; + } + }; + + // get a color by index without advancing pointer. + this.get = function(i) { + var idx = i - colors.length * Math.floor(i/colors.length); + return colors[idx]; + }; + + this.setColors = function(c) { + colors = c; + }; + + this.reset = function() { + idx = 0; + }; + }; + + // convert a hex color string to rgb string. + // h - 3 or 6 character hex string, with or without leading # + // a - optional alpha + $.jqplot.hex2rgb = function(h, a) { + h = h.replace('#', ''); + if (h.length == 3) { + h = h.charAt(0)+h.charAt(0)+h.charAt(1)+h.charAt(1)+h.charAt(2)+h.charAt(2); + } + var rgb; + rgb = 'rgba('+parseInt(h.slice(0,2), 16)+', '+parseInt(h.slice(2,4), 16)+', '+parseInt(h.slice(4,6), 16); + if (a) { + rgb += ', '+a; + } + rgb += ')'; + return rgb; + }; + + // convert an rgb color spec to a hex spec. ignore any alpha specification. + $.jqplot.rgb2hex = function(s) { + var pat = /rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/; + var m = s.match(pat); + var h = '#'; + for (var i=1; i<4; i++) { + var temp; + if (m[i].search(/%/) != -1) { + temp = parseInt(255*m[i]/100, 10).toString(16); + if (temp.length == 1) { + temp = '0'+temp; + } + } + else { + temp = parseInt(m[i], 10).toString(16); + if (temp.length == 1) { + temp = '0'+temp; + } + } + h += temp; + } + return h; + }; + + // given a css color spec, return an rgb css color spec + $.jqplot.normalize2rgb = function(s, a) { + if (s.search(/^ *rgba?\(/) != -1) { + return s; + } + else if (s.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/) != -1) { + return $.jqplot.hex2rgb(s, a); + } + else { + throw 'invalid color spec'; + } + }; + + // extract the r, g, b, a color components out of a css color spec. + $.jqplot.getColorComponents = function(s) { + // check to see if a color keyword. + s = $.jqplot.colorKeywordMap[s] || s; + var rgb = $.jqplot.normalize2rgb(s); + var pat = /rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/; + var m = rgb.match(pat); + var ret = []; + for (var i=1; i<4; i++) { + if (m[i].search(/%/) != -1) { + ret[i-1] = parseInt(255*m[i]/100, 10); + } + else { + ret[i-1] = parseInt(m[i], 10); + } + } + ret[3] = parseFloat(m[4]) ? parseFloat(m[4]) : 1.0; + return ret; + }; + + $.jqplot.colorKeywordMap = {aliceblue: 'rgb(240, 248, 255)', antiquewhite: 'rgb(250, 235, 215)', aqua: 'rgb( 0, 255, 255)', aquamarine: 'rgb(127, 255, 212)', azure: 'rgb(240, 255, 255)', beige: 'rgb(245, 245, 220)', bisque: 'rgb(255, 228, 196)', black: 'rgb( 0, 0, 0)', blanchedalmond: 'rgb(255, 235, 205)', blue: 'rgb( 0, 0, 255)', blueviolet: 'rgb(138, 43, 226)', brown: 'rgb(165, 42, 42)', burlywood: 'rgb(222, 184, 135)', cadetblue: 'rgb( 95, 158, 160)', chartreuse: 'rgb(127, 255, 0)', chocolate: 'rgb(210, 105, 30)', coral: 'rgb(255, 127, 80)', cornflowerblue: 'rgb(100, 149, 237)', cornsilk: 'rgb(255, 248, 220)', crimson: 'rgb(220, 20, 60)', cyan: 'rgb( 0, 255, 255)', darkblue: 'rgb( 0, 0, 139)', darkcyan: 'rgb( 0, 139, 139)', darkgoldenrod: 'rgb(184, 134, 11)', darkgray: 'rgb(169, 169, 169)', darkgreen: 'rgb( 0, 100, 0)', darkgrey: 'rgb(169, 169, 169)', darkkhaki: 'rgb(189, 183, 107)', darkmagenta: 'rgb(139, 0, 139)', darkolivegreen: 'rgb( 85, 107, 47)', darkorange: 'rgb(255, 140, 0)', darkorchid: 'rgb(153, 50, 204)', darkred: 'rgb(139, 0, 0)', darksalmon: 'rgb(233, 150, 122)', darkseagreen: 'rgb(143, 188, 143)', darkslateblue: 'rgb( 72, 61, 139)', darkslategray: 'rgb( 47, 79, 79)', darkslategrey: 'rgb( 47, 79, 79)', darkturquoise: 'rgb( 0, 206, 209)', darkviolet: 'rgb(148, 0, 211)', deeppink: 'rgb(255, 20, 147)', deepskyblue: 'rgb( 0, 191, 255)', dimgray: 'rgb(105, 105, 105)', dimgrey: 'rgb(105, 105, 105)', dodgerblue: 'rgb( 30, 144, 255)', firebrick: 'rgb(178, 34, 34)', floralwhite: 'rgb(255, 250, 240)', forestgreen: 'rgb( 34, 139, 34)', fuchsia: 'rgb(255, 0, 255)', gainsboro: 'rgb(220, 220, 220)', ghostwhite: 'rgb(248, 248, 255)', gold: 'rgb(255, 215, 0)', goldenrod: 'rgb(218, 165, 32)', gray: 'rgb(128, 128, 128)', grey: 'rgb(128, 128, 128)', green: 'rgb( 0, 128, 0)', greenyellow: 'rgb(173, 255, 47)', honeydew: 'rgb(240, 255, 240)', hotpink: 'rgb(255, 105, 180)', indianred: 'rgb(205, 92, 92)', indigo: 'rgb( 75, 0, 130)', ivory: 'rgb(255, 255, 240)', khaki: 'rgb(240, 230, 140)', lavender: 'rgb(230, 230, 250)', lavenderblush: 'rgb(255, 240, 245)', lawngreen: 'rgb(124, 252, 0)', lemonchiffon: 'rgb(255, 250, 205)', lightblue: 'rgb(173, 216, 230)', lightcoral: 'rgb(240, 128, 128)', lightcyan: 'rgb(224, 255, 255)', lightgoldenrodyellow: 'rgb(250, 250, 210)', lightgray: 'rgb(211, 211, 211)', lightgreen: 'rgb(144, 238, 144)', lightgrey: 'rgb(211, 211, 211)', lightpink: 'rgb(255, 182, 193)', lightsalmon: 'rgb(255, 160, 122)', lightseagreen: 'rgb( 32, 178, 170)', lightskyblue: 'rgb(135, 206, 250)', lightslategray: 'rgb(119, 136, 153)', lightslategrey: 'rgb(119, 136, 153)', lightsteelblue: 'rgb(176, 196, 222)', lightyellow: 'rgb(255, 255, 224)', lime: 'rgb( 0, 255, 0)', limegreen: 'rgb( 50, 205, 50)', linen: 'rgb(250, 240, 230)', magenta: 'rgb(255, 0, 255)', maroon: 'rgb(128, 0, 0)', mediumaquamarine: 'rgb(102, 205, 170)', mediumblue: 'rgb( 0, 0, 205)', mediumorchid: 'rgb(186, 85, 211)', mediumpurple: 'rgb(147, 112, 219)', mediumseagreen: 'rgb( 60, 179, 113)', mediumslateblue: 'rgb(123, 104, 238)', mediumspringgreen: 'rgb( 0, 250, 154)', mediumturquoise: 'rgb( 72, 209, 204)', mediumvioletred: 'rgb(199, 21, 133)', midnightblue: 'rgb( 25, 25, 112)', mintcream: 'rgb(245, 255, 250)', mistyrose: 'rgb(255, 228, 225)', moccasin: 'rgb(255, 228, 181)', navajowhite: 'rgb(255, 222, 173)', navy: 'rgb( 0, 0, 128)', oldlace: 'rgb(253, 245, 230)', olive: 'rgb(128, 128, 0)', olivedrab: 'rgb(107, 142, 35)', orange: 'rgb(255, 165, 0)', orangered: 'rgb(255, 69, 0)', orchid: 'rgb(218, 112, 214)', palegoldenrod: 'rgb(238, 232, 170)', palegreen: 'rgb(152, 251, 152)', paleturquoise: 'rgb(175, 238, 238)', palevioletred: 'rgb(219, 112, 147)', papayawhip: 'rgb(255, 239, 213)', peachpuff: 'rgb(255, 218, 185)', peru: 'rgb(205, 133, 63)', pink: 'rgb(255, 192, 203)', plum: 'rgb(221, 160, 221)', powderblue: 'rgb(176, 224, 230)', purple: 'rgb(128, 0, 128)', red: 'rgb(255, 0, 0)', rosybrown: 'rgb(188, 143, 143)', royalblue: 'rgb( 65, 105, 225)', saddlebrown: 'rgb(139, 69, 19)', salmon: 'rgb(250, 128, 114)', sandybrown: 'rgb(244, 164, 96)', seagreen: 'rgb( 46, 139, 87)', seashell: 'rgb(255, 245, 238)', sienna: 'rgb(160, 82, 45)', silver: 'rgb(192, 192, 192)', skyblue: 'rgb(135, 206, 235)', slateblue: 'rgb(106, 90, 205)', slategray: 'rgb(112, 128, 144)', slategrey: 'rgb(112, 128, 144)', snow: 'rgb(255, 250, 250)', springgreen: 'rgb( 0, 255, 127)', steelblue: 'rgb( 70, 130, 180)', tan: 'rgb(210, 180, 140)', teal: 'rgb( 0, 128, 128)', thistle: 'rgb(216, 191, 216)', tomato: 'rgb(255, 99, 71)', turquoise: 'rgb( 64, 224, 208)', violet: 'rgb(238, 130, 238)', wheat: 'rgb(245, 222, 179)', white: 'rgb(255, 255, 255)', whitesmoke: 'rgb(245, 245, 245)', yellow: 'rgb(255, 255, 0)', yellowgreen: 'rgb(154, 205, 50)'}; + + + + // class: $.jqplot.AxisLabelRenderer + // Renderer to place labels on the axes. + $.jqplot.AxisLabelRenderer = function(options) { + // Group: Properties + $.jqplot.ElemContainer.call(this); + // name of the axis associated with this tick + this.axis; + // prop: show + // wether or not to show the tick (mark and label). + this.show = true; + // prop: label + // The text or html for the label. + this.label = ''; + this.fontFamily = null; + this.fontSize = null; + this.textColor = null; + this._elem; + // prop: escapeHTML + // true to escape HTML entities in the label. + this.escapeHTML = false; + + $.extend(true, this, options); + }; + + $.jqplot.AxisLabelRenderer.prototype = new $.jqplot.ElemContainer(); + $.jqplot.AxisLabelRenderer.prototype.constructor = $.jqplot.AxisLabelRenderer; + + $.jqplot.AxisLabelRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + $.jqplot.AxisLabelRenderer.prototype.draw = function(ctx, plot) { + // Memory Leaks patch + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + + this._elem = $('<div style="position:absolute;" class="jqplot-'+this.axis+'-label"></div>'); + + if (Number(this.label)) { + this._elem.css('white-space', 'nowrap'); + } + + if (!this.escapeHTML) { + this._elem.html(this.label); + } + else { + this._elem.text(this.label); + } + if (this.fontFamily) { + this._elem.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this._elem.css('font-size', this.fontSize); + } + if (this.textColor) { + this._elem.css('color', this.textColor); + } + + return this._elem; + }; + + $.jqplot.AxisLabelRenderer.prototype.pack = function() { + }; + + // class: $.jqplot.AxisTickRenderer + // A "tick" object showing the value of a tick/gridline on the plot. + $.jqplot.AxisTickRenderer = function(options) { + // Group: Properties + $.jqplot.ElemContainer.call(this); + // prop: mark + // tick mark on the axis. One of 'inside', 'outside', 'cross', '' or null. + this.mark = 'outside'; + // name of the axis associated with this tick + this.axis; + // prop: showMark + // wether or not to show the mark on the axis. + this.showMark = true; + // prop: showGridline + // wether or not to draw the gridline on the grid at this tick. + this.showGridline = true; + // prop: isMinorTick + // if this is a minor tick. + this.isMinorTick = false; + // prop: size + // Length of the tick beyond the grid in pixels. + // DEPRECATED: This has been superceeded by markSize + this.size = 4; + // prop: markSize + // Length of the tick marks in pixels. For 'cross' style, length + // will be stoked above and below axis, so total length will be twice this. + this.markSize = 6; + // prop: show + // wether or not to show the tick (mark and label). + // Setting this to false requires more testing. It is recommended + // to set showLabel and showMark to false instead. + this.show = true; + // prop: showLabel + // wether or not to show the label. + this.showLabel = true; + this.label = ''; + this.value = null; + this._styles = {}; + // prop: formatter + // A class of a formatter for the tick text. sprintf by default. + this.formatter = $.jqplot.DefaultTickFormatter; + // prop: prefix + // String to prepend to the tick label. + // Prefix is prepended to the formatted tick label. + this.prefix = ''; + // prop: formatString + // string passed to the formatter. + this.formatString = ''; + // prop: fontFamily + // css spec for the font-family css attribute. + this.fontFamily; + // prop: fontSize + // css spec for the font-size css attribute. + this.fontSize; + // prop: textColor + // css spec for the color attribute. + this.textColor; + // prop: escapeHTML + // true to escape HTML entities in the label. + this.escapeHTML = false; + this._elem; + this._breakTick = false; + + $.extend(true, this, options); + }; + + $.jqplot.AxisTickRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + $.jqplot.AxisTickRenderer.prototype = new $.jqplot.ElemContainer(); + $.jqplot.AxisTickRenderer.prototype.constructor = $.jqplot.AxisTickRenderer; + + $.jqplot.AxisTickRenderer.prototype.setTick = function(value, axisName, isMinor) { + this.value = value; + this.axis = axisName; + if (isMinor) { + this.isMinorTick = true; + } + return this; + }; + + $.jqplot.AxisTickRenderer.prototype.draw = function() { + if (!this.label) { + this.label = this.prefix + this.formatter(this.formatString, this.value); + } + var style = {position: 'absolute'}; + if (Number(this.label)) { + style['whitSpace'] = 'nowrap'; + } + + // Memory Leaks patch + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + + this._elem = $(document.createElement('div')); + this._elem.addClass("jqplot-"+this.axis+"-tick"); + + if (!this.escapeHTML) { + this._elem.html(this.label); + } + else { + this._elem.text(this.label); + } + + this._elem.css(style); + + for (var s in this._styles) { + this._elem.css(s, this._styles[s]); + } + if (this.fontFamily) { + this._elem.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this._elem.css('font-size', this.fontSize); + } + if (this.textColor) { + this._elem.css('color', this.textColor); + } + if (this._breakTick) { + this._elem.addClass('jqplot-breakTick'); + } + + return this._elem; + }; + + $.jqplot.DefaultTickFormatter = function (format, val) { + if (typeof val == 'number') { + if (!format) { + format = $.jqplot.config.defaultTickFormatString; + } + return $.jqplot.sprintf(format, val); + } + else { + return String(val); + } + }; + + $.jqplot.AxisTickRenderer.prototype.pack = function() { + }; + + // Class: $.jqplot.CanvasGridRenderer + // The default jqPlot grid renderer, creating a grid on a canvas element. + // The renderer has no additional options beyond the <Grid> class. + $.jqplot.CanvasGridRenderer = function(){ + this.shadowRenderer = new $.jqplot.ShadowRenderer(); + }; + + // called with context of Grid object + $.jqplot.CanvasGridRenderer.prototype.init = function(options) { + this._ctx; + $.extend(true, this, options); + // set the shadow renderer options + var sopts = {lineJoin:'miter', lineCap:'round', fill:false, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, lineWidth:this.shadowWidth, closePath:false, strokeStyle:this.shadowColor}; + this.renderer.shadowRenderer.init(sopts); + }; + + // called with context of Grid. + $.jqplot.CanvasGridRenderer.prototype.createElement = function(plot) { + var elem; + // Memory Leaks patch + if (this._elem) { + if ($.jqplot.use_excanvas) { + elem = this._elem.get(0); + window.G_vmlCanvasManager.uninitElement(elem); + elem = null; + } + + this._elem.emptyForce(); + this._elem = null; + } + + elem = plot.canvasManager.getCanvas(); + + var w = this._plotDimensions.width; + var h = this._plotDimensions.height; + elem.width = w; + elem.height = h; + this._elem = $(elem); + this._elem.addClass('jqplot-grid-canvas'); + this._elem.css({ position: 'absolute', left: 0, top: 0 }); + + elem = plot.canvasManager.initCanvas(elem); + + this._top = this._offsets.top; + this._bottom = h - this._offsets.bottom; + this._left = this._offsets.left; + this._right = w - this._offsets.right; + this._width = this._right - this._left; + this._height = this._bottom - this._top; + // avoid memory leak + elem = null; + return this._elem; + }; + + $.jqplot.CanvasGridRenderer.prototype.draw = function() { + this._ctx = this._elem.get(0).getContext("2d"); + var ctx = this._ctx; + var axes = this._axes; + // Add the grid onto the grid canvas. This is the bottom most layer. + ctx.save(); + ctx.clearRect(0, 0, this._plotDimensions.width, this._plotDimensions.height); + ctx.fillStyle = this.backgroundColor || this.background; + ctx.fillRect(this._left, this._top, this._width, this._height); + + if (true) { + ctx.save(); + ctx.lineJoin = 'miter'; + ctx.lineCap = 'butt'; + ctx.lineWidth = this.gridLineWidth; + ctx.strokeStyle = this.gridLineColor; + var b, e, s, m; + var ax = ['xaxis', 'yaxis', 'x2axis', 'y2axis']; + for (var i=4; i>0; i--) { + var name = ax[i-1]; + var axis = axes[name]; + var ticks = axis._ticks; + if (axis.show) { + for (var j=ticks.length; j>0; j--) { + var t = ticks[j-1]; + if (t.show) { + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (name) { + case 'xaxis': + // draw the grid line + if (t.showGridline && this.drawGridlines) { + drawLine(pos, this._top, pos, this._bottom); + } + + // draw the mark + if (t.showMark && t.mark) { + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (m) { + case 'outside': + b = this._bottom; + e = this._bottom+s; + break; + case 'inside': + b = this._bottom-s; + e = this._bottom; + break; + case 'cross': + b = this._bottom-s; + e = this._bottom+s; + break; + default: + b = this._bottom; + e = this._bottom+s; + break; + } + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [[pos,b],[pos,e]], {lineCap:'butt', lineWidth:this.gridLineWidth, offset:this.gridLineWidth*0.75, depth:2, fill:false, closePath:false}); + } + // draw the line + drawLine(pos, b, pos, e); + } + break; + case 'yaxis': + // draw the grid line + if (t.showGridline && this.drawGridlines) { + drawLine(this._right, pos, this._left, pos); + } + // draw the mark + if (t.showMark && t.mark) { + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (m) { + case 'outside': + b = this._left-s; + e = this._left; + break; + case 'inside': + b = this._left; + e = this._left+s; + break; + case 'cross': + b = this._left-s; + e = this._left+s; + break; + default: + b = this._left-s; + e = this._left; + break; + } + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false}); + } + drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor}); + } + break; + case 'x2axis': + // draw the grid line + if (t.showGridline && this.drawGridlines) { + drawLine(pos, this._bottom, pos, this._top); + } + // draw the mark + if (t.showMark && t.mark) { + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (m) { + case 'outside': + b = this._top-s; + e = this._top; + break; + case 'inside': + b = this._top; + e = this._top+s; + break; + case 'cross': + b = this._top-s; + e = this._top+s; + break; + default: + b = this._top-s; + e = this._top; + break; + } + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [[pos,b],[pos,e]], {lineCap:'butt', lineWidth:this.gridLineWidth, offset:this.gridLineWidth*0.75, depth:2, fill:false, closePath:false}); + } + drawLine(pos, b, pos, e); + } + break; + case 'y2axis': + // draw the grid line + if (t.showGridline && this.drawGridlines) { + drawLine(this._left, pos, this._right, pos); + } + // draw the mark + if (t.showMark && t.mark) { + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (m) { + case 'outside': + b = this._right; + e = this._right+s; + break; + case 'inside': + b = this._right-s; + e = this._right; + break; + case 'cross': + b = this._right-s; + e = this._right+s; + break; + default: + b = this._right; + e = this._right+s; + break; + } + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false}); + } + drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor}); + } + break; + default: + break; + } + } + } + t = null; + } + axis = null; + ticks = null; + } + // Now draw grid lines for additional y axes + ax = ['y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis']; + for (var i=7; i>0; i--) { + var axis = axes[ax[i-1]]; + var ticks = axis._ticks; + if (axis.show) { + var tn = ticks[axis.numberTicks-1]; + var t0 = ticks[0]; + var left = axis.getLeft(); + var points = [[left, tn.getTop() + tn.getHeight()/2], [left, t0.getTop() + t0.getHeight()/2 + 1.0]]; + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, points, {lineCap:'butt', fill:false, closePath:false}); + } + // draw the line + drawLine(points[0][0], points[0][1], points[1][0], points[1][1], {lineCap:'butt', strokeStyle:axis.borderColor, lineWidth:axis.borderWidth}); + // draw the tick marks + for (var j=ticks.length; j>0; j--) { + var t = ticks[j-1]; + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + if (t.showMark && t.mark) { + switch (m) { + case 'outside': + b = left; + e = left+s; + break; + case 'inside': + b = left-s; + e = left; + break; + case 'cross': + b = left-s; + e = left+s; + break; + default: + b = left; + e = left+s; + break; + } + points = [[b,pos], [e,pos]]; + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, points, {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false}); + } + // draw the line + drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor}); + } + t = null; + } + t0 = null; + } + axis = null; + ticks = null; + } + + ctx.restore(); + } + + function drawLine(bx, by, ex, ey, opts) { + ctx.save(); + opts = opts || {}; + if (opts.lineWidth == null || opts.lineWidth != 0){ + $.extend(true, ctx, opts); + ctx.beginPath(); + ctx.moveTo(bx, by); + ctx.lineTo(ex, ey); + ctx.stroke(); + ctx.restore(); + } + } + + if (this.shadow) { + var points = [[this._left, this._bottom], [this._right, this._bottom], [this._right, this._top]]; + this.renderer.shadowRenderer.draw(ctx, points); + } + // Now draw border around grid. Use axis border definitions. start at + // upper left and go clockwise. + if (this.borderWidth != 0 && this.drawBorder) { + drawLine (this._left, this._top, this._right, this._top, {lineCap:'round', strokeStyle:axes.x2axis.borderColor, lineWidth:axes.x2axis.borderWidth}); + drawLine (this._right, this._top, this._right, this._bottom, {lineCap:'round', strokeStyle:axes.y2axis.borderColor, lineWidth:axes.y2axis.borderWidth}); + drawLine (this._right, this._bottom, this._left, this._bottom, {lineCap:'round', strokeStyle:axes.xaxis.borderColor, lineWidth:axes.xaxis.borderWidth}); + drawLine (this._left, this._bottom, this._left, this._top, {lineCap:'round', strokeStyle:axes.yaxis.borderColor, lineWidth:axes.yaxis.borderWidth}); + } + // ctx.lineWidth = this.borderWidth; + // ctx.strokeStyle = this.borderColor; + // ctx.strokeRect(this._left, this._top, this._width, this._height); + + ctx.restore(); + ctx = null; + axes = null; + }; + + // Class: $.jqplot.DivTitleRenderer + // The default title renderer for jqPlot. This class has no options beyond the <Title> class. + $.jqplot.DivTitleRenderer = function() { + }; + + $.jqplot.DivTitleRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + $.jqplot.DivTitleRenderer.prototype.draw = function() { + // Memory Leaks patch + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + + var r = this.renderer; + var elem = document.createElement('div'); + this._elem = $(elem); + this._elem.addClass('jqplot-title'); + + if (!this.text) { + this.show = false; + this._elem.height(0); + this._elem.width(0); + } + else if (this.text) { + var color; + if (this.color) { + color = this.color; + } + else if (this.textColor) { + color = this.textColor; + } + + // don't trust that a stylesheet is present, set the position. + var styles = {position:'absolute', top:'0px', left:'0px'}; + + if (this._plotWidth) { + styles['width'] = this._plotWidth+'px'; + } + if (this.fontSize) { + styles['fontSize'] = this.fontSize; + } + if (this.textAlign) { + styles['textAlign'] = this.textAlign; + } + else { + styles['textAlign'] = 'center'; + } + if (color) { + styles['color'] = color; + } + if (this.paddingBottom) { + styles['paddingBottom'] = this.paddingBottom; + } + if (this.fontFamily) { + styles['fontFamily'] = this.fontFamily; + } + + this._elem.css(styles); + this._elem.text(this.text); + + + // styletext += (this._plotWidth) ? 'width:'+this._plotWidth+'px;' : ''; + // styletext += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; + // styletext += (this.textAlign) ? 'text-align:'+this.textAlign+';' : 'text-align:center;'; + // styletext += (color) ? 'color:'+color+';' : ''; + // styletext += (this.paddingBottom) ? 'padding-bottom:'+this.paddingBottom+';' : ''; + // this._elem = $('<div class="jqplot-title" style="'+styletext+'">'+this.text+'</div>'); + // if (this.fontFamily) { + // this._elem.css('font-family', this.fontFamily); + // } + } + + elem = null; + + return this._elem; + }; + + $.jqplot.DivTitleRenderer.prototype.pack = function() { + // nothing to do here + }; + + // Class: $.jqplot.LineRenderer + // The default line renderer for jqPlot, this class has no options beyond the <Series> class. + // Draws series as a line. + $.jqplot.LineRenderer = function(){ + this.shapeRenderer = new $.jqplot.ShapeRenderer(); + this.shadowRenderer = new $.jqplot.ShadowRenderer(); + }; + + // called with scope of series. + $.jqplot.LineRenderer.prototype.init = function(options, plot) { + options = options || {}; + this._type='line'; + var lopts = {highlightMouseOver: options.highlightMouseOver, highlightMouseDown: options.highlightMouseDown, highlightColor: options.highlightColor}; + + delete (options.highlightMouseOver); + delete (options.highlightMouseDown); + delete (options.highlightColor); + + $.extend(true, this.renderer, options); + // set the shape renderer options + var opts = {lineJoin:this.lineJoin, lineCap:this.lineCap, fill:this.fill, isarc:false, strokeStyle:this.color, fillStyle:this.fillColor, lineWidth:this.lineWidth, closePath:this.fill}; + this.renderer.shapeRenderer.init(opts); + // set the shadow renderer options + // scale the shadowOffset to the width of the line. + if (this.lineWidth > 2.5) { + var shadow_offset = this.shadowOffset* (1 + (Math.atan((this.lineWidth/2.5))/0.785398163 - 1)*0.6); + // var shadow_offset = this.shadowOffset; + } + // for skinny lines, don't make such a big shadow. + else { + var shadow_offset = this.shadowOffset*Math.atan((this.lineWidth/2.5))/0.785398163; + } + var sopts = {lineJoin:this.lineJoin, lineCap:this.lineCap, fill:this.fill, isarc:false, angle:this.shadowAngle, offset:shadow_offset, alpha:this.shadowAlpha, depth:this.shadowDepth, lineWidth:this.lineWidth, closePath:this.fill}; + this.renderer.shadowRenderer.init(sopts); + this._areaPoints = []; + this._boundingBox = [[],[]]; + + if (!this.isTrendline && this.fill) { + + // prop: highlightMouseOver + // True to highlight area on a filled plot when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on an area on a filled plot. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over an area on a filled plot. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColor + // color to use when highlighting an area on a filled plot. + this.highlightColor = null; + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (lopts.highlightMouseDown && lopts.highlightMouseOver == null) { + lopts.highlightMouseOver = false; + } + + $.extend(true, this, {highlightMouseOver: lopts.highlightMouseOver, highlightMouseDown: lopts.highlightMouseDown, highlightColor: lopts.highlightColor}); + + if (!this.highlightColor) { + this.highlightColor = $.jqplot.computeHighlightColors(this.fillColor); + } + // turn off (disable) the highlighter plugin + if (this.highlighter) { + this.highlighter.show = false; + } + } + + if (!this.isTrendline && plot) { + plot.plugins.lineRenderer = {}; + plot.postInitHooks.addOnce(postInit); + plot.postDrawHooks.addOnce(postPlotDraw); + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + } + + }; + + // Method: setGridData + // converts the user data values to grid coordinates and stores them + // in the gridData array. + // Called with scope of a series. + $.jqplot.LineRenderer.prototype.setGridData = function(plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var data = this._plotData; + var pdata = this._prevPlotData; + this.gridData = []; + this._prevGridData = []; + for (var i=0; i<this.data.length; i++) { + // if not a line series or if no nulls in data, push the converted point onto the array. + if (data[i][0] != null && data[i][1] != null) { + this.gridData.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1])]); + } + // else if there is a null, preserve it. + else if (data[i][0] == null) { + this.gridData.push([null, yp.call(this._yaxis, data[i][1])]); + } + else if (data[i][1] == null) { + this.gridData.push([xp.call(this._xaxis, data[i][0]), null]); + } + // if not a line series or if no nulls in data, push the converted point onto the array. + if (pdata[i] != null && pdata[i][0] != null && pdata[i][1] != null) { + this._prevGridData.push([xp.call(this._xaxis, pdata[i][0]), yp.call(this._yaxis, pdata[i][1])]); + } + // else if there is a null, preserve it. + else if (pdata[i] != null && pdata[i][0] == null) { + this._prevGridData.push([null, yp.call(this._yaxis, pdata[i][1])]); + } + else if (pdata[i] != null && pdata[i][0] != null && pdata[i][1] == null) { + this._prevGridData.push([xp.call(this._xaxis, pdata[i][0]), null]); + } + } + }; + + // Method: makeGridData + // converts any arbitrary data values to grid coordinates and + // returns them. This method exists so that plugins can use a series' + // linerenderer to generate grid data points without overwriting the + // grid data associated with that series. + // Called with scope of a series. + $.jqplot.LineRenderer.prototype.makeGridData = function(data, plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var gd = []; + var pgd = []; + for (var i=0; i<data.length; i++) { + // if not a line series or if no nulls in data, push the converted point onto the array. + if (data[i][0] != null && data[i][1] != null) { + gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1])]); + } + // else if there is a null, preserve it. + else if (data[i][0] == null) { + gd.push([null, yp.call(this._yaxis, data[i][1])]); + } + else if (data[i][1] == null) { + gd.push([xp.call(this._xaxis, data[i][0]), null]); + } + } + return gd; + }; + + + // called within scope of series. + $.jqplot.LineRenderer.prototype.draw = function(ctx, gd, options) { + var i; + var opts = (options != undefined) ? options : {}; + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var fillAndStroke = (opts.fillAndStroke != undefined) ? opts.fillAndStroke : this.fillAndStroke; + var xmin, ymin, xmax, ymax; + ctx.save(); + if (gd.length) { + if (showLine) { + // if we fill, we'll have to add points to close the curve. + if (fill) { + if (this.fillToZero) { + // have to break line up into shapes at axis crossings + var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors); + var negativeColor = negativeColors.get(this.index); + if (! this.useNegativeColors) { + negativeColor = opts.fillStyle; + } + var isnegative = false; + var posfs = opts.fillStyle; + + // if stoking line as well as filling, get a copy of line data. + if (fillAndStroke) { + var fasgd = gd.slice(0); + } + // if not stacked, fill down to axis + if (this.index == 0 || !this._stack) { + + var tempgd = []; + this._areaPoints = []; + var pyzero = this._yaxis.series_u2p(this.fillToValue); + var pxzero = this._xaxis.series_u2p(this.fillToValue); + + if (this.fillAxis == 'y') { + tempgd.push([gd[0][0], pyzero]); + this._areaPoints.push([gd[0][0], pyzero]); + + for (var i=0; i<gd.length-1; i++) { + tempgd.push(gd[i]); + this._areaPoints.push(gd[i]); + // do we have an axis crossing? + if (this._plotData[i][1] * this._plotData[i+1][1] < 0) { + if (this._plotData[i][1] < 0) { + isnegative = true; + opts.fillStyle = negativeColor; + } + else { + isnegative = false; + opts.fillStyle = posfs; + } + + var xintercept = gd[i][0] + (gd[i+1][0] - gd[i][0]) * (pyzero-gd[i][1])/(gd[i+1][1] - gd[i][1]); + tempgd.push([xintercept, pyzero]); + this._areaPoints.push([xintercept, pyzero]); + // now draw this shape and shadow. + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, tempgd, opts); + } + this.renderer.shapeRenderer.draw(ctx, tempgd, opts); + // now empty temp array and continue + tempgd = [[xintercept, pyzero]]; + // this._areaPoints = [[xintercept, pyzero]]; + } + } + if (this._plotData[gd.length-1][1] < 0) { + isnegative = true; + opts.fillStyle = negativeColor; + } + else { + isnegative = false; + opts.fillStyle = posfs; + } + tempgd.push(gd[gd.length-1]); + this._areaPoints.push(gd[gd.length-1]); + tempgd.push([gd[gd.length-1][0], pyzero]); + this._areaPoints.push([gd[gd.length-1][0], pyzero]); + } + // now draw this shape and shadow. + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, tempgd, opts); + } + this.renderer.shapeRenderer.draw(ctx, tempgd, opts); + + + // var gridymin = this._yaxis.series_u2p(0); + // // IE doesn't return new length on unshift + // gd.unshift([gd[0][0], gridymin]); + // len = gd.length; + // gd.push([gd[len - 1][0], gridymin]); + } + // if stacked, fill to line below + else { + var prev = this._prevGridData; + for (var i=prev.length; i>0; i--) { + gd.push(prev[i-1]); + // this._areaPoints.push(prev[i-1]); + } + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, gd, opts); + } + this._areaPoints = gd; + this.renderer.shapeRenderer.draw(ctx, gd, opts); + } + } + ///////////////////////// + // Not filled to zero + //////////////////////// + else { + // if stoking line as well as filling, get a copy of line data. + if (fillAndStroke) { + var fasgd = gd.slice(0); + } + // if not stacked, fill down to axis + if (this.index == 0 || !this._stack) { + // var gridymin = this._yaxis.series_u2p(this._yaxis.min) - this.gridBorderWidth / 2; + var gridymin = ctx.canvas.height; + // IE doesn't return new length on unshift + gd.unshift([gd[0][0], gridymin]); + var len = gd.length; + gd.push([gd[len - 1][0], gridymin]); + } + // if stacked, fill to line below + else { + var prev = this._prevGridData; + for (var i=prev.length; i>0; i--) { + gd.push(prev[i-1]); + } + } + this._areaPoints = gd; + + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, gd, opts); + } + + this.renderer.shapeRenderer.draw(ctx, gd, opts); + } + if (fillAndStroke) { + var fasopts = $.extend(true, {}, opts, {fill:false, closePath:false}); + this.renderer.shapeRenderer.draw(ctx, fasgd, fasopts); + ////////// + // TODO: figure out some way to do shadows nicely + // if (shadow) { + // this.renderer.shadowRenderer.draw(ctx, fasgd, fasopts); + // } + // now draw the markers + if (this.markerRenderer.show) { + for (i=0; i<fasgd.length; i++) { + this.markerRenderer.draw(fasgd[i][0], fasgd[i][1], ctx, opts.markerOptions); + } + } + } + } + else { + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, gd, opts); + } + + this.renderer.shapeRenderer.draw(ctx, gd, opts); + } + } + // calculate the bounding box + var xmin = xmax = ymin = ymax = null; + for (i=0; i<this._areaPoints.length; i++) { + var p = this._areaPoints[i]; + if (xmin > p[0] || xmin == null) { + xmin = p[0]; + } + if (ymax < p[1] || ymax == null) { + ymax = p[1]; + } + if (xmax < p[0] || xmax == null) { + xmax = p[0]; + } + if (ymin > p[1] || ymin == null) { + ymin = p[1]; + } + } + this._boundingBox = [[xmin, ymax], [xmax, ymin]]; + + // now draw the markers + if (this.markerRenderer.show && !fill) { + for (i=0; i<gd.length; i++) { + if (gd[i][0] != null && gd[i][1] != null) { + this.markerRenderer.draw(gd[i][0], gd[i][1], ctx, opts.markerOptions); + } + } + } + } + + ctx.restore(); + }; + + $.jqplot.LineRenderer.prototype.drawShadow = function(ctx, gd, options) { + // This is a no-op, shadows drawn with lines. + }; + + // called with scope of plot. + // make sure to not leave anything highlighted. + function postInit(target, data, options) { + for (var i=0; i<this.series.length; i++) { + if (this.series[i].renderer.constructor == $.jqplot.LineRenderer) { + // don't allow mouseover and mousedown at same time. + if (this.series[i].highlightMouseOver) { + this.series[i].highlightMouseDown = false; + } + } + } + this.target.bind('mouseout', {plot:this}, function (ev) { unhighlight(ev.data.plot); }); + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.lineRenderer && this.plugins.lineRenderer.highlightCanvas) { + this.plugins.lineRenderer.highlightCanvas.resetCanvas(); + this.plugins.lineRenderer.highlightCanvas = null; + } + + this.plugins.lineRenderer.highlightedSeriesIndex = null; + this.plugins.lineRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + + this.eventCanvas._elem.before(this.plugins.lineRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-lineRenderer-highlight-canvas', this._plotDimensions, this)); + this.plugins.lineRenderer.highlightCanvas.setContext(); + } + + function highlight (plot, sidx, pidx, points) { + var s = plot.series[sidx]; + var canvas = plot.plugins.lineRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.lineRenderer.highlightedSeriesIndex = sidx; + var opts = {fillStyle: s.highlightColor}; + s.renderer.shapeRenderer.draw(canvas._ctx, points, opts); + canvas = null; + } + + function unhighlight (plot) { + var canvas = plot.plugins.lineRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.lineRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + canvas = null; + } + + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.lineRenderer.highlightedSeriesIndex)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.lineRenderer.highlightedSeriesIndex)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.lineRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt = jQuery.Event('jqplotDataClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var idx = plot.plugins.lineRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + + // class: $.jqplot.LinearAxisRenderer + // The default jqPlot axis renderer, creating a numeric axis. + // The renderer has no additional options beyond the <Axis> object. + $.jqplot.LinearAxisRenderer = function() { + }; + + // called with scope of axis object. + $.jqplot.LinearAxisRenderer.prototype.init = function(options){ + // prop: breakPoints + // EXPERIMENTAL!! Use at your own risk! + // Works only with linear axes and the default tick renderer. + // Array of [start, stop] points to create a broken axis. + // Broken axes have a "jump" in them, which is an immediate + // transition from a smaller value to a larger value. + // Currently, axis ticks MUST be manually assigned if using breakPoints + // by using the axis ticks array option. + this.breakPoints = null; + // prop: breakTickLabel + // Label to use at the axis break if breakPoints are specified. + this.breakTickLabel = "≈"; + // prop: forceTickAt0 + // This will ensure that there is always a tick mark at 0. + // If data range is strictly positive or negative, + // this will force 0 to be inside the axis bounds unless + // the appropriate axis pad (pad, padMin or padMax) is set + // to 0, then this will force an axis min or max value at 0. + // This has know effect when any of the following options + // are set: autoscale, min, max, numberTicks or tickInterval. + this.forceTickAt0 = false; + // prop: forceTickAt100 + // This will ensure that there is always a tick mark at 100. + // If data range is strictly above or below 100, + // this will force 100 to be inside the axis bounds unless + // the appropriate axis pad (pad, padMin or padMax) is set + // to 0, then this will force an axis min or max value at 100. + // This has know effect when any of the following options + // are set: autoscale, min, max, numberTicks or tickInterval. + this.forceTickAt100 = false; + this._autoFormatString = ''; + this._overrideFormatString = false; + $.extend(true, this, options); + if (this.breakPoints) { + if (!$.isArray(this.breakPoints)) { + this.breakPoints = null; + } + else if (this.breakPoints.length < 2 || this.breakPoints[1] <= this.breakPoints[0]) { + this.breakPoints = null; + } + } + this.resetDataBounds(); + }; + + // called with scope of axis + $.jqplot.LinearAxisRenderer.prototype.draw = function(ctx, plot) { + if (this.show) { + // populate the axis label and value properties. + // createTicks is a method on the renderer, but + // call it within the scope of the axis. + this.renderer.createTicks.call(this); + // fill a div with axes labels in the right direction. + // Need to pregenerate each axis to get it's bounds and + // position it and the labels correctly on the plot. + var dim=0; + var temp; + // Added for theming. + if (this._elem) { + // Memory Leaks patch + //this._elem.empty(); + this._elem.emptyForce(); + this._elem = null; + } + + this._elem = $(document.createElement('div')); + this._elem.addClass('jqplot-axis jqplot-'+this.name); + this._elem.css('posiiton', 'absolute'); + + + if (this.name == 'xaxis' || this.name == 'x2axis') { + this._elem.width(this._plotDimensions.width); + } + else { + this._elem.height(this._plotDimensions.height); + } + + // create a _label object. + this.labelOptions.axis = this.name; + this._label = new this.labelRenderer(this.labelOptions); + if (this._label.show) { + var elem = this._label.draw(ctx, plot); + elem.appendTo(this._elem); + elem = null; + } + + var t = this._ticks; + var tick; + for (var i=0; i<t.length; i++) { + tick = t[i]; + if (tick.show && tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + this._elem.append(tick.draw(ctx, plot)); + } + } + tick = null; + t = null; + } + return this._elem; + }; + + // called with scope of an axis + $.jqplot.LinearAxisRenderer.prototype.reset = function() { + this.min = this._min; + this.max = this._max; + this.tickInterval = this._tickInterval; + this.numberTicks = this._numberTicks; + this._autoFormatString = ''; + if (this._overrideFormatString && this.tickOptions && this.tickOptions.formatString) { + this.tickOptions.formatString = ''; + } + + // this._ticks = this.__ticks; + }; + + // called with scope of axis + $.jqplot.LinearAxisRenderer.prototype.set = function() { + var dim = 0; + var temp; + var w = 0; + var h = 0; + var lshow = (this._label == null) ? false : this._label.show; + if (this.show) { + var t = this._ticks; + var tick; + for (var i=0; i<t.length; i++) { + tick = t[i]; + if (!tick._breakTick && tick.show && tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + temp = tick._elem.outerHeight(true); + } + else { + temp = tick._elem.outerWidth(true); + } + if (temp > dim) { + dim = temp; + } + } + } + tick = null; + t = null; + + if (lshow) { + w = this._label._elem.outerWidth(true); + h = this._label._elem.outerHeight(true); + } + if (this.name == 'xaxis') { + dim = dim + h; + this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'}); + } + else if (this.name == 'x2axis') { + dim = dim + h; + this._elem.css({'height':dim+'px', left:'0px', top:'0px'}); + } + else if (this.name == 'yaxis') { + dim = dim + w; + this._elem.css({'width':dim+'px', left:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + else { + dim = dim + w; + this._elem.css({'width':dim+'px', right:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + } + }; + + // called with scope of axis + $.jqplot.LinearAxisRenderer.prototype.createTicks = function() { + // we're are operating on an axis here + var ticks = this._ticks; + var userTicks = this.ticks; + var name = this.name; + // databounds were set on axis initialization. + var db = this._dataBounds; + var dim, interval; + var min, max; + var pos1, pos2; + var tt, i; + // get a copy of user's settings for min/max. + var userMin = this.min; + var userMax = this.max; + var userNT = this.numberTicks; + var userTI = this.tickInterval; + + // if we already have ticks, use them. + // ticks must be in order of increasing value. + + if (userTicks.length) { + // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed + for (i=0; i<userTicks.length; i++){ + var ut = userTicks[i]; + var t = new this.tickRenderer(this.tickOptions); + if (ut.constructor == Array) { + t.value = ut[0]; + if (this.breakPoints) { + if (ut[0] == this.breakPoints[0]) { + t.label = this.breakTickLabel; + t._breakTick = true; + t.showGridline = false; + t.showMark = false; + } + else if (ut[0] > this.breakPoints[0] && ut[0] <= this.breakPoints[1]) { + t.show = false; + t.showGridline = false; + t.label = ut[1]; + } + else { + t.label = ut[1]; + } + } + else { + t.label = ut[1]; + } + t.setTick(ut[0], this.name); + this._ticks.push(t); + } + + else { + t.value = ut; + if (this.breakPoints) { + if (ut == this.breakPoints[0]) { + t.label = this.breakTickLabel; + t._breakTick = true; + t.showGridline = false; + t.showMark = false; + } + else if (ut > this.breakPoints[0] && ut <= this.breakPoints[1]) { + t.show = false; + t.showGridline = false; + } + } + t.setTick(ut, this.name); + this._ticks.push(t); + } + } + this.numberTicks = userTicks.length; + this.min = this._ticks[0].value; + this.max = this._ticks[this.numberTicks-1].value; + this.tickInterval = (this.max - this.min) / (this.numberTicks - 1); + } + + // we don't have any ticks yet, let's make some! + else { + if (name == 'xaxis' || name == 'x2axis') { + dim = this._plotDimensions.width; + } + else { + dim = this._plotDimensions.height; + } + + // // if min, max and number of ticks specified, user can't specify interval. + // if (!this.autoscale && this.min != null && this.max != null && this.numberTicks != null) { + // console.log('doing this'); + // this.tickInterval = null; + // } + + // if max, min, and interval specified and interval won't fit, ignore interval. + // if (this.min != null && this.max != null && this.tickInterval != null) { + // if (parseInt((this.max-this.min)/this.tickInterval, 10) != (this.max-this.min)/this.tickInterval) { + // this.tickInterval = null; + // } + // } + + min = ((this.min != null) ? this.min : db.min); + max = ((this.max != null) ? this.max : db.max); + + var range = max - min; + var rmin, rmax; + var temp; + + // Doing complete autoscaling + if (this.min == null && this.max == null && this.numberTicks == null && this.tickInterval == null && !this.autoscale) { + // check to see if we can override tick format string with autocalculated one + if (this.tickOptions == null || !this.tickOptions.formatString) { + this._overrideFormatString = true; + } + + + // Check if user must have tick at 0 or 100 and ensure they are in range. + // The autoscaling algorithm will always place ticks at 0 and 100 if they are in range. + if (this.forceTickAt0) { + if (min > 0) { + min = 0; + } + if (max < 0) { + max = 0; + } + } + + if (this.forceTickAt100) { + if (min > 100) { + min = 100; + } + if (max < 100) { + max = 100; + } + } + + // console.log(this.name); + var threshold = 30; + var tdim = Math.max(dim, threshold+1); + var scalefact = (tdim-threshold)/300.0; + // scalefact = 1; + var ret = $.jqplot.LinearTickGenerator(min, max, scalefact); + // calculate a padded max and min, points should be less than these + // so that they aren't too close to the edges of the plot. + // User can adjust how much padding is allowed with pad, padMin and PadMax options. + var tumin = min + range*(this.padMin - 1); + var tumax = max - range*(this.padMax - 1); + + if (min <=tumin || max >= tumax) { + tumin = min - range*(this.padMin - 1); + tumax = max + range*(this.padMax - 1); + ret = $.jqplot.LinearTickGenerator(tumin, tumax, scalefact); + } + + + // if (ret[2] > max_number_ticks) { + // ret[4] = Math.ceil(r[2]/max_number_ticks) * ret[4]; + + // } + + this.min = ret[0]; + this.max = ret[1]; + this.numberTicks = ret[2]; + this._autoFormatString = ret[3]; + //this.tickInterval = Math.abs(this.max - this.min)/(this.numberTicks - 1); + this.tickInterval = ret[4]; + // console.log('numberticks: %s, interval: %s', ret[2], ret[4]); + } + + // User has specified some axis scale related option, can use auto algorithm + else { + + // if min and max are same, space them out a bit + if (min == max) { + var adj = 0.05; + if (min > 0) { + adj = Math.max(Math.log(min)/Math.LN10, 0.05); + } + min -= adj; + max += adj; + } + + // autoscale. Can't autoscale if min or max is supplied. + // Will use numberTicks and tickInterval if supplied. Ticks + // across multiple axes may not line up depending on how + // bars are to be plotted. + if (this.autoscale && this.min == null && this.max == null) { + var rrange, ti, margin; + var forceMinZero = false; + var forceZeroLine = false; + var intervals = {min:null, max:null, average:null, stddev:null}; + // if any series are bars, or if any are fill to zero, and if this + // is the axis to fill toward, check to see if we can start axis at zero. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + var faname = (s.fillAxis == 'x') ? s._xaxis.name : s._yaxis.name; + // check to see if this is the fill axis + if (this.name == faname) { + var vals = s._plotValues[s.fillAxis]; + var vmin = vals[0]; + var vmax = vals[0]; + for (var j=1; j<vals.length; j++) { + if (vals[j] < vmin) { + vmin = vals[j]; + } + else if (vals[j] > vmax) { + vmax = vals[j]; + } + } + var dp = (vmax - vmin) / vmax; + // is this sries a bar? + if (s.renderer.constructor == $.jqplot.BarRenderer) { + // if no negative values and could also check range. + if (vmin >= 0 && (s.fillToZero || dp > 0.1)) { + forceMinZero = true; + } + else { + forceMinZero = false; + if (s.fill && s.fillToZero && vmin < 0 && vmax > 0) { + forceZeroLine = true; + } + else { + forceZeroLine = false; + } + } + } + + // if not a bar and filling, use appropriate method. + else if (s.fill) { + if (vmin >= 0 && (s.fillToZero || dp > 0.1)) { + forceMinZero = true; + } + else if (vmin < 0 && vmax > 0 && s.fillToZero) { + forceMinZero = false; + forceZeroLine = true; + } + else { + forceMinZero = false; + forceZeroLine = false; + } + } + + // if not a bar and not filling, only change existing state + // if it doesn't make sense + else if (vmin < 0) { + forceMinZero = false; + } + } + } + + // check if we need make axis min at 0. + if (forceMinZero) { + // compute number of ticks + this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing); + this.min = 0; + userMin = 0; + // what order is this range? + // what tick interval does that give us? + ti = max/(this.numberTicks-1); + temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10))); + if (ti/temp == parseInt(ti/temp, 10)) { + ti += temp; + } + this.tickInterval = Math.ceil(ti/temp) * temp; + this.max = this.tickInterval * (this.numberTicks - 1); + } + + // check if we need to make sure there is a tick at 0. + else if (forceZeroLine) { + // compute number of ticks + this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing); + var ntmin = Math.ceil(Math.abs(min)/range*(this.numberTicks-1)); + var ntmax = this.numberTicks - 1 - ntmin; + ti = Math.max(Math.abs(min/ntmin), Math.abs(max/ntmax)); + temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10))); + this.tickInterval = Math.ceil(ti/temp) * temp; + this.max = this.tickInterval * ntmax; + this.min = -this.tickInterval * ntmin; + } + + // if nothing else, do autoscaling which will try to line up ticks across axes. + else { + if (this.numberTicks == null){ + if (this.tickInterval) { + this.numberTicks = 3 + Math.ceil(range / this.tickInterval); + } + else { + this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing); + } + } + + if (this.tickInterval == null) { + // get a tick interval + ti = range/(this.numberTicks - 1); + + if (ti < 1) { + temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10))); + } + else { + temp = 1; + } + this.tickInterval = Math.ceil(ti*temp*this.pad)/temp; + } + else { + temp = 1 / this.tickInterval; + } + + // try to compute a nicer, more even tick interval + // temp = Math.pow(10, Math.floor(Math.log(ti)/Math.LN10)); + // this.tickInterval = Math.ceil(ti/temp) * temp; + rrange = this.tickInterval * (this.numberTicks - 1); + margin = (rrange - range)/2; + + if (this.min == null) { + this.min = Math.floor(temp*(min-margin))/temp; + } + if (this.max == null) { + this.max = this.min + rrange; + } + } + } + + // Use the default algorithm which pads each axis to make the chart + // centered nicely on the grid. + else { + rmin = (this.min != null) ? this.min : min - range*(this.padMin - 1); + rmax = (this.max != null) ? this.max : max + range*(this.padMax - 1); + this.min = rmin; + this.max = rmax; + range = this.max - this.min; + + if (this.numberTicks == null){ + // if tickInterval is specified by user, we will ignore computed maximum. + // max will be equal or greater to fit even # of ticks. + if (this.tickInterval != null) { + this.numberTicks = Math.ceil((this.max - this.min)/this.tickInterval)+1; + this.max = this.min + this.tickInterval*(this.numberTicks-1); + } + else if (dim > 100) { + this.numberTicks = parseInt(3+(dim-100)/75, 10); + } + else { + this.numberTicks = 2; + } + } + + if (this.tickInterval == null) { + this.tickInterval = range / (this.numberTicks-1); + } + } + + if (this.renderer.constructor == $.jqplot.LinearAxisRenderer && this._autoFormatString == '') { + // fix for misleading tick display with small range and low precision. + range = this.max - this.min; + // figure out precision + var temptick = new this.tickRenderer(this.tickOptions); + // use the tick formatString or, the default. + var fs = temptick.formatString || $.jqplot.config.defaultTickFormatString; + var fs = fs.match($.jqplot.sprintf.regex)[0]; + var precision = 0; + if (fs) { + if (fs.search(/[fFeEgGpP]/) > -1) { + var m = fs.match(/\%\.(\d{0,})?[eEfFgGpP]/); + if (m) { + precision = parseInt(m[1], 10); + } + else { + precision = 6; + } + } + else if (fs.search(/[di]/) > -1) { + precision = 0; + } + // fact will be <= 1; + var fact = Math.pow(10, -precision); + if (this.tickInterval < fact) { + // need to correct underrange + if (userNT == null && userTI == null) { + this.tickInterval = fact; + if (userMax == null && userMin == null) { + // this.min = Math.floor((this._dataBounds.min - this.tickInterval)/fact) * fact; + this.min = Math.floor(this._dataBounds.min/fact) * fact; + if (this.min == this._dataBounds.min) { + this.min = this._dataBounds.min - this.tickInterval; + } + // this.max = Math.ceil((this._dataBounds.max + this.tickInterval)/fact) * fact; + this.max = Math.ceil(this._dataBounds.max/fact) * fact; + if (this.max == this._dataBounds.max) { + this.max = this._dataBounds.max + this.tickInterval; + } + var n = (this.max - this.min)/this.tickInterval; + n = n.toFixed(11); + n = Math.ceil(n); + this.numberTicks = n + 1; + } + else if (userMax == null) { + // add one tick for top of range. + var n = (this._dataBounds.max - this.min) / this.tickInterval; + n = n.toFixed(11); + this.numberTicks = Math.ceil(n) + 2; + this.max = this.min + this.tickInterval * (this.numberTicks-1); + } + else if (userMin == null) { + // add one tick for bottom of range. + var n = (this.max - this._dataBounds.min) / this.tickInterval; + n = n.toFixed(11); + this.numberTicks = Math.ceil(n) + 2; + this.min = this.max - this.tickInterval * (this.numberTicks-1); + } + else { + // calculate a number of ticks so max is within axis scale + this.numberTicks = Math.ceil((userMax - userMin)/this.tickInterval) + 1; + // if user's min and max don't fit evenly in ticks, adjust. + // This takes care of cases such as user min set to 0, max set to 3.5 but tick + // format string set to %d (integer ticks) + this.min = Math.floor(userMin*Math.pow(10, precision))/Math.pow(10, precision); + this.max = Math.ceil(userMax*Math.pow(10, precision))/Math.pow(10, precision); + // this.max = this.min + this.tickInterval*(this.numberTicks-1); + this.numberTicks = Math.ceil((this.max - this.min)/this.tickInterval) + 1; + } + } + } + } + } + + } + + if (this._overrideFormatString && this._autoFormatString != '') { + this.tickOptions = this.tickOptions || {}; + this.tickOptions.formatString = this._autoFormatString; + } + + for (var i=0; i<this.numberTicks; i++){ + tt = this.min + i * this.tickInterval; + var t = new this.tickRenderer(this.tickOptions); + // var t = new $.jqplot.AxisTickRenderer(this.tickOptions); + + t.setTick(tt, this.name); + this._ticks.push(t); + t = null; + } + } + ticks = null; + }; + + // Used to reset just the values of the ticks and then repack, which will + // recalculate the positioning functions. It is assuemd that the + // number of ticks is the same and the values of the new array are at the + // proper interval. + // This method needs to be called with the scope of an axis object, like: + // + // > plot.axes.yaxis.renderer.resetTickValues.call(plot.axes.yaxis, yarr); + // + $.jqplot.LinearAxisRenderer.prototype.resetTickValues = function(opts) { + if ($.isArray(opts) && opts.length == this._ticks.length) { + var t; + for (var i=0; i<opts.length; i++) { + t = this._ticks[i]; + t.value = opts[i]; + t.label = t.formatter(t.formatString, opts[i]); + t.label = t.prefix + t.label; + t._elem.html(t.label); + } + t = null; + this.min = $.jqplot.arrayMin(opts); + this.max = $.jqplot.arrayMax(opts); + this.pack(); + } + // Not implemented yet. + // else if ($.isPlainObject(opts)) { + // + // } + }; + + // called with scope of axis + $.jqplot.LinearAxisRenderer.prototype.pack = function(pos, offsets) { + // Add defaults for repacking from resetTickValues function. + pos = pos || {}; + offsets = offsets || this._offsets; + + var ticks = this._ticks; + var max = this.max; + var min = this.min; + var offmax = offsets.max; + var offmin = offsets.min; + var lshow = (this._label == null) ? false : this._label.show; + + for (var p in pos) { + this._elem.css(p, pos[p]); + } + + this._offsets = offsets; + // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left. + var pixellength = offmax - offmin; + var unitlength = max - min; + + // point to unit and unit to point conversions references to Plot DOM element top left corner. + if (this.breakPoints) { + unitlength = unitlength - this.breakPoints[1] + this.breakPoints[0]; + + this.p2u = function(p){ + return (p - offmin) * unitlength / pixellength + min; + }; + + this.u2p = function(u){ + if (u > this.breakPoints[0] && u < this.breakPoints[1]){ + u = this.breakPoints[0]; + } + if (u <= this.breakPoints[0]) { + return (u - min) * pixellength / unitlength + offmin; + } + else { + return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength + offmin; + } + }; + + if (this.name.charAt(0) == 'x'){ + this.series_u2p = function(u){ + if (u > this.breakPoints[0] && u < this.breakPoints[1]){ + u = this.breakPoints[0]; + } + if (u <= this.breakPoints[0]) { + return (u - min) * pixellength / unitlength; + } + else { + return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength; + } + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + min; + }; + } + + else { + this.series_u2p = function(u){ + if (u > this.breakPoints[0] && u < this.breakPoints[1]){ + u = this.breakPoints[0]; + } + if (u >= this.breakPoints[1]) { + return (u - max) * pixellength / unitlength; + } + else { + return (u + this.breakPoints[1] - this.breakPoints[0] - max) * pixellength / unitlength; + } + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + max; + }; + } + } + else { + this.p2u = function(p){ + return (p - offmin) * unitlength / pixellength + min; + }; + + this.u2p = function(u){ + return (u - min) * pixellength / unitlength + offmin; + }; + + if (this.name == 'xaxis' || this.name == 'x2axis'){ + this.series_u2p = function(u){ + return (u - min) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + min; + }; + } + + else { + this.series_u2p = function(u){ + return (u - max) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + max; + }; + } + } + + if (this.show) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + for (var i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'xaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + if (temp * t.angle < 0) { + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + } + // position at start + else { + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + } + break; + case 'end': + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + case 'start': + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + break; + case 'middle': + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + default: + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + } + } + else { + shim = -t.getWidth()/2; + } + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('left', val); + t.pack(); + } + } + if (lshow) { + var w = this._label._elem.outerWidth(true); + this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px'); + if (this.name == 'xaxis') { + this._label._elem.css('bottom', '0px'); + } + else { + this._label._elem.css('top', '0px'); + } + this._label.pack(); + } + } + else { + for (var i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'yaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + case 'end': + if (temp * t.angle < 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'start': + if (t.angle > 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'middle': + // if (t.angle > 0) { + // shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + // } + // else { + // shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + // } + shim = -t.getHeight()/2; + break; + default: + shim = -t.getHeight()/2; + break; + } + } + else { + shim = -t.getHeight()/2; + } + + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('top', val); + t.pack(); + } + } + if (lshow) { + var h = this._label._elem.outerHeight(true); + this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px'); + if (this.name == 'yaxis') { + this._label._elem.css('left', '0px'); + } + else { + this._label._elem.css('right', '0px'); + } + this._label.pack(); + } + } + } + + ticks = null; + }; + + + /** + * The following code was generaously given to me a while back by Scott Prahl. + * He did a good job at computing axes min, max and number of ticks for the + * case where the user has not set any scale related parameters (tickInterval, + * numberTicks, min or max). I had ignored this use case for a long time, + * focusing on the more difficult case where user has set some option controlling + * tick generation. Anyway, about time I got this into jqPlot. + * Thanks Scott!! + */ + + /** + * Copyright (c) 2010 Scott Prahl + * The next three routines are currently available for use in all personal + * or commercial projects under both the MIT and GPL version 2.0 licenses. + * This means that you can choose the license that best suits your project + * and use it accordingly. + */ + + // A good format string depends on the interval. If the interval is greater + // than 1 then there is no need to show any decimal digits. If it is < 1.0, then + // use the magnitude of the interval to determine the number of digits to show. + function bestFormatString (interval) + { + interval = Math.abs(interval); + if (interval > 1) {return '%d';} + + var expv = -Math.floor(Math.log(interval)/Math.LN10); + return '%.' + expv + 'f'; + } + + // This will return an interval of form 2 * 10^n, 5 * 10^n or 10 * 10^n + function bestLinearInterval(range, scalefact) { + var expv = Math.floor(Math.log(range)/Math.LN10); + var magnitude = Math.pow(10, expv); + // 0 < f < 10 + var f = range / magnitude; + // console.log('f: %s, scaled: %s ', f, f/scalefact); + // for large plots, scalefact will decrease f and increase number of ticks. + // for small plots, scalefact will increase f and decrease number of ticks. + f = f/scalefact; + + // for large plots, smaller interval, more ticks. + if (f<=0.38) {return 0.1*magnitude;} + if (f<=1.6) {return 0.2*magnitude;} + if (f<=4.0) {return 0.5*magnitude;} + if (f<=8.0) {return magnitude;} + // for very small plots, larger interval, less ticks in number ticks + if (f<=16.0) {return 2*magnitude;} + return 5*magnitude; + } + + // Given the min and max for a dataset, return suitable endpoints + // for the graphing, a good number for the number of ticks, and a + // format string so that extraneous digits are not displayed. + // returned is an array containing [min, max, nTicks, format] + $.jqplot.LinearTickGenerator = function(axis_min, axis_max, scalefact) { + // if endpoints are equal try to include zero otherwise include one + if (axis_min == axis_max) { + axis_max = (axis_max) ? 0 : 1; + } + + scalefact = scalefact || 1.0; + + // make sure range is positive + if (axis_max < axis_min) { + var a = axis_max; + axis_max = axis_min; + axis_min = a; + } + + var ss = bestLinearInterval(axis_max - axis_min, scalefact); + var r = []; + + // Figure out the axis min, max and number of ticks + // the min and max will be some multiple of the tick interval, + // 1*10^n, 2*10^n or 5*10^n. This gaurantees that, if the + // axis min is negative, 0 will be a tick. + r[0] = Math.floor(axis_min / ss) * ss; // min + r[1] = Math.ceil(axis_max / ss) * ss; // max + r[2] = Math.round((r[1]-r[0])/ss+1.0); // number of ticks + r[3] = bestFormatString(ss); // format string + r[4] = ss; // tick Interval + return r; + }; + + + // class: $.jqplot.MarkerRenderer + // The default jqPlot marker renderer, rendering the points on the line. + $.jqplot.MarkerRenderer = function(options){ + // Group: Properties + + // prop: show + // wether or not to show the marker. + this.show = true; + // prop: style + // One of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare + this.style = 'filledCircle'; + // prop: lineWidth + // size of the line for non-filled markers. + this.lineWidth = 2; + // prop: size + // Size of the marker (diameter or circle, length of edge of square, etc.) + this.size = 9.0; + // prop: color + // color of marker. Will be set to color of series by default on init. + this.color = '#666666'; + // prop: shadow + // wether or not to draw a shadow on the line + this.shadow = true; + // prop: shadowAngle + // Shadow angle in degrees + this.shadowAngle = 45; + // prop: shadowOffset + // Shadow offset from line in pixels + this.shadowOffset = 1; + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + this.shadowDepth = 3; + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + this.shadowAlpha = '0.07'; + // prop: shadowRenderer + // Renderer that will draws the shadows on the marker. + this.shadowRenderer = new $.jqplot.ShadowRenderer(); + // prop: shapeRenderer + // Renderer that will draw the marker. + this.shapeRenderer = new $.jqplot.ShapeRenderer(); + + $.extend(true, this, options); + }; + + $.jqplot.MarkerRenderer.prototype.init = function(options) { + $.extend(true, this, options); + var sdopt = {angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, lineWidth:this.lineWidth, depth:this.shadowDepth, closePath:true}; + if (this.style.indexOf('filled') != -1) { + sdopt.fill = true; + } + if (this.style.indexOf('ircle') != -1) { + sdopt.isarc = true; + sdopt.closePath = false; + } + this.shadowRenderer.init(sdopt); + + var shopt = {fill:false, isarc:false, strokeStyle:this.color, fillStyle:this.color, lineWidth:this.lineWidth, closePath:true}; + if (this.style.indexOf('filled') != -1) { + shopt.fill = true; + } + if (this.style.indexOf('ircle') != -1) { + shopt.isarc = true; + shopt.closePath = false; + } + this.shapeRenderer.init(shopt); + }; + + $.jqplot.MarkerRenderer.prototype.drawDiamond = function(x, y, ctx, fill, options) { + var stretch = 1.2; + var dx = this.size/2/stretch; + var dy = this.size/2*stretch; + var points = [[x-dx, y], [x, y+dy], [x+dx, y], [x, y-dy]]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.drawPlus = function(x, y, ctx, fill, options) { + var stretch = 1.0; + var dx = this.size/2*stretch; + var dy = this.size/2*stretch; + var points1 = [[x, y-dy], [x, y+dy]]; + var points2 = [[x+dx, y], [x-dx, y]]; + var opts = $.extend(true, {}, this.options, {closePath:false}); + if (this.shadow) { + this.shadowRenderer.draw(ctx, points1, {closePath:false}); + this.shadowRenderer.draw(ctx, points2, {closePath:false}); + } + this.shapeRenderer.draw(ctx, points1, opts); + this.shapeRenderer.draw(ctx, points2, opts); + }; + + $.jqplot.MarkerRenderer.prototype.drawX = function(x, y, ctx, fill, options) { + var stretch = 1.0; + var dx = this.size/2*stretch; + var dy = this.size/2*stretch; + var opts = $.extend(true, {}, this.options, {closePath:false}); + var points1 = [[x-dx, y-dy], [x+dx, y+dy]]; + var points2 = [[x-dx, y+dy], [x+dx, y-dy]]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points1, {closePath:false}); + this.shadowRenderer.draw(ctx, points2, {closePath:false}); + } + this.shapeRenderer.draw(ctx, points1, opts); + this.shapeRenderer.draw(ctx, points2, opts); + }; + + $.jqplot.MarkerRenderer.prototype.drawDash = function(x, y, ctx, fill, options) { + var stretch = 1.0; + var dx = this.size/2*stretch; + var dy = this.size/2*stretch; + var points = [[x-dx, y], [x+dx, y]]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.drawLine = function(p1, p2, ctx, fill, options) { + var points = [p1, p2]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.drawSquare = function(x, y, ctx, fill, options) { + var stretch = 1.0; + var dx = this.size/2/stretch; + var dy = this.size/2*stretch; + var points = [[x-dx, y-dy], [x-dx, y+dy], [x+dx, y+dy], [x+dx, y-dy]]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.drawCircle = function(x, y, ctx, fill, options) { + var radius = this.size/2; + var end = 2*Math.PI; + var points = [x, y, radius, 0, end, true]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.draw = function(x, y, ctx, options) { + options = options || {}; + // hack here b/c shape renderer uses canvas based color style options + // and marker uses css style names. + if (options.show == null || options.show != false) { + if (options.color && !options.fillStyle) { + options.fillStyle = options.color; + } + if (options.color && !options.strokeStyle) { + options.strokeStyle = options.color; + } + switch (this.style) { + case 'diamond': + this.drawDiamond(x,y,ctx, false, options); + break; + case 'filledDiamond': + this.drawDiamond(x,y,ctx, true, options); + break; + case 'circle': + this.drawCircle(x,y,ctx, false, options); + break; + case 'filledCircle': + this.drawCircle(x,y,ctx, true, options); + break; + case 'square': + this.drawSquare(x,y,ctx, false, options); + break; + case 'filledSquare': + this.drawSquare(x,y,ctx, true, options); + break; + case 'x': + this.drawX(x,y,ctx, true, options); + break; + case 'plus': + this.drawPlus(x,y,ctx, true, options); + break; + case 'dash': + this.drawDash(x,y,ctx, true, options); + break; + case 'line': + this.drawLine(x, y, ctx, false, options); + break; + default: + this.drawDiamond(x,y,ctx, false, options); + break; + } + } + }; + + // class: $.jqplot.shadowRenderer + // The default jqPlot shadow renderer, rendering shadows behind shapes. + $.jqplot.ShadowRenderer = function(options){ + // Group: Properties + + // prop: angle + // Angle of the shadow in degrees. Measured counter-clockwise from the x axis. + this.angle = 45; + // prop: offset + // Pixel offset at the given shadow angle of each shadow stroke from the last stroke. + this.offset = 1; + // prop: alpha + // alpha transparency of shadow stroke. + this.alpha = 0.07; + // prop: lineWidth + // width of the shadow line stroke. + this.lineWidth = 1.5; + // prop: lineJoin + // How line segments of the shadow are joined. + this.lineJoin = 'miter'; + // prop: lineCap + // how ends of the shadow line are rendered. + this.lineCap = 'round'; + // prop; closePath + // whether line path segment is closed upon itself. + this.closePath = false; + // prop: fill + // whether to fill the shape. + this.fill = false; + // prop: depth + // how many times the shadow is stroked. Each stroke will be offset by offset at angle degrees. + this.depth = 3; + this.strokeStyle = 'rgba(0,0,0,0.1)'; + // prop: isarc + // wether the shadow is an arc or not. + this.isarc = false; + + $.extend(true, this, options); + }; + + $.jqplot.ShadowRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + // function: draw + // draws an transparent black (i.e. gray) shadow. + // + // ctx - canvas drawing context + // points - array of points or [x, y, radius, start angle (rad), end angle (rad)] + $.jqplot.ShadowRenderer.prototype.draw = function(ctx, points, options) { + ctx.save(); + var opts = (options != null) ? options : {}; + var fill = (opts.fill != null) ? opts.fill : this.fill; + var closePath = (opts.closePath != null) ? opts.closePath : this.closePath; + var offset = (opts.offset != null) ? opts.offset : this.offset; + var alpha = (opts.alpha != null) ? opts.alpha : this.alpha; + var depth = (opts.depth != null) ? opts.depth : this.depth; + var isarc = (opts.isarc != null) ? opts.isarc : this.isarc; + ctx.lineWidth = (opts.lineWidth != null) ? opts.lineWidth : this.lineWidth; + ctx.lineJoin = (opts.lineJoin != null) ? opts.lineJoin : this.lineJoin; + ctx.lineCap = (opts.lineCap != null) ? opts.lineCap : this.lineCap; + ctx.strokeStyle = opts.strokeStyle || this.strokeStyle || 'rgba(0,0,0,'+alpha+')'; + ctx.fillStyle = opts.fillStyle || this.fillStyle || 'rgba(0,0,0,'+alpha+')'; + for (var j=0; j<depth; j++) { + ctx.translate(Math.cos(this.angle*Math.PI/180)*offset, Math.sin(this.angle*Math.PI/180)*offset); + ctx.beginPath(); + if (isarc) { + ctx.arc(points[0], points[1], points[2], points[3], points[4], true); + } + else if (points && points.length){ + var move = true; + for (var i=0; i<points.length; i++) { + // skip to the first non-null point and move to it. + if (points[i][0] != null && points[i][1] != null) { + if (move) { + ctx.moveTo(points[i][0], points[i][1]); + move = false; + } + else { + ctx.lineTo(points[i][0], points[i][1]); + } + } + else { + move = true; + } + } + + } + if (closePath) { + ctx.closePath(); + } + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + } + ctx.restore(); + }; + + // class: $.jqplot.shapeRenderer + // The default jqPlot shape renderer. Given a set of points will + // plot them and either stroke a line (fill = false) or fill them (fill = true). + // If a filled shape is desired, closePath = true must also be set to close + // the shape. + $.jqplot.ShapeRenderer = function(options){ + + this.lineWidth = 1.5; + // prop: lineJoin + // How line segments of the shadow are joined. + this.lineJoin = 'miter'; + // prop: lineCap + // how ends of the shadow line are rendered. + this.lineCap = 'round'; + // prop; closePath + // whether line path segment is closed upon itself. + this.closePath = false; + // prop: fill + // whether to fill the shape. + this.fill = false; + // prop: isarc + // wether the shadow is an arc or not. + this.isarc = false; + // prop: fillRect + // true to draw shape as a filled rectangle. + this.fillRect = false; + // prop: strokeRect + // true to draw shape as a stroked rectangle. + this.strokeRect = false; + // prop: clearRect + // true to cear a rectangle. + this.clearRect = false; + // prop: strokeStyle + // css color spec for the stoke style + this.strokeStyle = '#999999'; + // prop: fillStyle + // css color spec for the fill style. + this.fillStyle = '#999999'; + + $.extend(true, this, options); + }; + + $.jqplot.ShapeRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + // function: draw + // draws the shape. + // + // ctx - canvas drawing context + // points - array of points for shapes or + // [x, y, width, height] for rectangles or + // [x, y, radius, start angle (rad), end angle (rad)] for circles and arcs. + $.jqplot.ShapeRenderer.prototype.draw = function(ctx, points, options) { + ctx.save(); + var opts = (options != null) ? options : {}; + var fill = (opts.fill != null) ? opts.fill : this.fill; + var closePath = (opts.closePath != null) ? opts.closePath : this.closePath; + var fillRect = (opts.fillRect != null) ? opts.fillRect : this.fillRect; + var strokeRect = (opts.strokeRect != null) ? opts.strokeRect : this.strokeRect; + var clearRect = (opts.clearRect != null) ? opts.clearRect : this.clearRect; + var isarc = (opts.isarc != null) ? opts.isarc : this.isarc; + ctx.lineWidth = opts.lineWidth || this.lineWidth; + ctx.lineJoin = opts.lineJoin || this.lineJoin; + ctx.lineCap = opts.lineCap || this.lineCap; + ctx.strokeStyle = (opts.strokeStyle || opts.color) || this.strokeStyle; + ctx.fillStyle = opts.fillStyle || this.fillStyle; + ctx.beginPath(); + if (isarc) { + ctx.arc(points[0], points[1], points[2], points[3], points[4], true); + if (closePath) { + ctx.closePath(); + } + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + ctx.restore(); + return; + } + else if (clearRect) { + ctx.clearRect(points[0], points[1], points[2], points[3]); + ctx.restore(); + return; + } + else if (fillRect || strokeRect) { + if (fillRect) { + ctx.fillRect(points[0], points[1], points[2], points[3]); + } + if (strokeRect) { + ctx.strokeRect(points[0], points[1], points[2], points[3]); + ctx.restore(); + return; + } + } + else if (points && points.length){ + var move = true; + for (var i=0; i<points.length; i++) { + // skip to the first non-null point and move to it. + if (points[i][0] != null && points[i][1] != null) { + if (move) { + ctx.moveTo(points[i][0], points[i][1]); + move = false; + } + else { + ctx.lineTo(points[i][0], points[i][1]); + } + } + else { + move = true; + } + } + if (closePath) { + ctx.closePath(); + } + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + } + ctx.restore(); + }; + + // class $.jqplot.TableLegendRenderer + // The default legend renderer for jqPlot. + $.jqplot.TableLegendRenderer = function(){ + // + }; + + $.jqplot.TableLegendRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + $.jqplot.TableLegendRenderer.prototype.addrow = function (label, color, pad, reverse) { + var rs = (pad) ? this.rowSpacing+'px' : '0px'; + var tr; + var td; + var elem; + var div0; + var div1; + elem = document.createElement('tr'); + tr = $(elem); + tr.addClass('jqplot-table-legend'); + elem = null; + + if (reverse){ + tr.prependTo(this._elem); + } + + else{ + tr.appendTo(this._elem); + } + + if (this.showSwatches) { + td = $(document.createElement('td')); + td.addClass('jqplot-table-legend'); + td.css({textAlign: 'center', paddingTop: rs}); + + div0 = $(document.createElement('div')); + div1 = $(document.createElement('div')); + div1.addClass('jqplot-table-legend-swatch'); + div1.css({backgroundColor: color, borderColor: color}); + + tr.append(td.append(div0.append(div1))); + + // $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+ + // '<div><div class="jqplot-table-legend-swatch" style="background-color:'+color+';border-color:'+color+';"></div>'+ + // '</div></td>').appendTo(tr); + } + if (this.showLabels) { + td = $(document.createElement('td')); + td.addClass('jqplot-table-legend'); + td.css('paddingTop', rs); + tr.append(td); + + // elem = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>'); + // elem.appendTo(tr); + if (this.escapeHtml) { + td.text(label); + } + else { + td.html(label); + } + } + td = null; + div0 = null; + div1 = null; + tr = null; + elem = null; + }; + + // called with scope of legend + $.jqplot.TableLegendRenderer.prototype.draw = function() { + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + + if (this.show) { + var series = this._series; + // make a table. one line label per row. + var elem = document.createElement('table'); + this._elem = $(elem); + this._elem.addClass('jqplot-table-legend'); + + var ss = {position:'absolute'}; + if (this.background) { + ss['background'] = this.background; + } + if (this.border) { + ss['border'] = this.border; + } + if (this.fontSize) { + ss['fontSize'] = this.fontSize; + } + if (this.fontFamily) { + ss['fontFamily'] = this.fontFamily; + } + if (this.textColor) { + ss['textColor'] = this.textColor; + } + if (this.marginTop != null) { + ss['marginTop'] = this.marginTop; + } + if (this.marginBottom != null) { + ss['marginBottom'] = this.marginBottom; + } + if (this.marginLeft != null) { + ss['marginLeft'] = this.marginLeft; + } + if (this.marginRight != null) { + ss['marginRight'] = this.marginRight; + } + + + var pad = false, + reverse = false, + s; + for (var i = 0; i< series.length; i++) { + s = series[i]; + if (s._stack || s.renderer.constructor == $.jqplot.BezierCurveRenderer){ + reverse = true; + } + if (s.show && s.showLabel) { + var lt = this.labels[i] || s.label.toString(); + if (lt) { + var color = s.color; + if (reverse && i < series.length - 1){ + pad = true; + } + else if (reverse && i == series.length - 1){ + pad = false; + } + this.renderer.addrow.call(this, lt, color, pad, reverse); + pad = true; + } + // let plugins add more rows to legend. Used by trend line plugin. + for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) { + var item = $.jqplot.addLegendRowHooks[j].call(this, s); + if (item) { + this.renderer.addrow.call(this, item.label, item.color, pad); + pad = true; + } + } + lt = null; + } + } + } + return this._elem; + }; + + $.jqplot.TableLegendRenderer.prototype.pack = function(offsets) { + if (this.show) { + if (this.placement == 'insideGrid') { + switch (this.location) { + case 'nw': + var a = offsets.left; + var b = offsets.top; + this._elem.css('left', a); + this._elem.css('top', b); + break; + case 'n': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = offsets.top; + this._elem.css('left', a); + this._elem.css('top', b); + break; + case 'ne': + var a = offsets.right; + var b = offsets.top; + this._elem.css({right:a, top:b}); + break; + case 'e': + var a = offsets.right; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({right:a, top:b}); + break; + case 'se': + var a = offsets.right; + var b = offsets.bottom; + this._elem.css({right:a, bottom:b}); + break; + case 's': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = offsets.bottom; + this._elem.css({left:a, bottom:b}); + break; + case 'sw': + var a = offsets.left; + var b = offsets.bottom; + this._elem.css({left:a, bottom:b}); + break; + case 'w': + var a = offsets.left; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({left:a, top:b}); + break; + default: // same as 'se' + var a = offsets.right; + var b = offsets.bottom; + this._elem.css({right:a, bottom:b}); + break; + } + + } + else if (this.placement == 'outside'){ + switch (this.location) { + case 'nw': + var a = this._plotDimensions.width - offsets.left; + var b = offsets.top; + this._elem.css('right', a); + this._elem.css('top', b); + break; + case 'n': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = this._plotDimensions.height - offsets.top; + this._elem.css('left', a); + this._elem.css('bottom', b); + break; + case 'ne': + var a = this._plotDimensions.width - offsets.right; + var b = offsets.top; + this._elem.css({left:a, top:b}); + break; + case 'e': + var a = this._plotDimensions.width - offsets.right; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({left:a, top:b}); + break; + case 'se': + var a = this._plotDimensions.width - offsets.right; + var b = offsets.bottom; + this._elem.css({left:a, bottom:b}); + break; + case 's': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = this._plotDimensions.height - offsets.bottom; + this._elem.css({left:a, top:b}); + break; + case 'sw': + var a = this._plotDimensions.width - offsets.left; + var b = offsets.bottom; + this._elem.css({right:a, bottom:b}); + break; + case 'w': + var a = this._plotDimensions.width - offsets.left; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({right:a, top:b}); + break; + default: // same as 'se' + var a = offsets.right; + var b = offsets.bottom; + this._elem.css({right:a, bottom:b}); + break; + } + } + else { + switch (this.location) { + case 'nw': + this._elem.css({left:0, top:offsets.top}); + break; + case 'n': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + this._elem.css({left: a, top:offsets.top}); + break; + case 'ne': + this._elem.css({right:0, top:offsets.top}); + break; + case 'e': + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({right:offsets.right, top:b}); + break; + case 'se': + this._elem.css({right:offsets.right, bottom:offsets.bottom}); + break; + case 's': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + this._elem.css({left: a, bottom:offsets.bottom}); + break; + case 'sw': + this._elem.css({left:offsets.left, bottom:offsets.bottom}); + break; + case 'w': + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({left:offsets.left, top:b}); + break; + default: // same as 'se' + this._elem.css({right:offsets.right, bottom:offsets.bottom}); + break; + } + } + } + }; + + /** + * Class: $.jqplot.ThemeEngine + * Theme Engine provides a programatic way to change some of the more + * common jqplot styling options such as fonts, colors and grid options. + * A theme engine instance is created with each plot. The theme engine + * manages a collection of themes which can be modified, added to, or + * applied to the plot. + * + * The themeEngine class is not instantiated directly. + * When a plot is initialized, the current plot options are scanned + * an a default theme named "Default" is created. This theme is + * used as the basis for other themes added to the theme engine and + * is always available. + * + * A theme is a simple javascript object with styling parameters for + * various entities of the plot. A theme has the form: + * + * + * > { + * > _name:f "Default", + * > target: { + * > backgroundColor: "transparent" + * > }, + * > legend: { + * > textColor: null, + * > fontFamily: null, + * > fontSize: null, + * > border: null, + * > background: null + * > }, + * > title: { + * > textColor: "rgb(102, 102, 102)", + * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif", + * > fontSize: "19.2px", + * > textAlign: "center" + * > }, + * > seriesStyles: {}, + * > series: [{ + * > color: "#4bb2c5", + * > lineWidth: 2.5, + * > shadow: true, + * > fillColor: "#4bb2c5", + * > showMarker: true, + * > markerOptions: { + * > color: "#4bb2c5", + * > show: true, + * > style: 'filledCircle', + * > lineWidth: 1.5, + * > size: 4, + * > shadow: true + * > } + * > }], + * > grid: { + * > drawGridlines: true, + * > gridLineColor: "#cccccc", + * > gridLineWidth: 1, + * > backgroundColor: "#fffdf6", + * > borderColor: "#999999", + * > borderWidth: 2, + * > shadow: true + * > }, + * > axesStyles: { + * > label: {}, + * > ticks: {} + * > }, + * > axes: { + * > xaxis: { + * > borderColor: "#999999", + * > borderWidth: 2, + * > ticks: { + * > show: true, + * > showGridline: true, + * > showLabel: true, + * > showMark: true, + * > size: 4, + * > textColor: "", + * > whiteSpace: "nowrap", + * > fontSize: "12px", + * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif" + * > }, + * > label: { + * > textColor: "rgb(102, 102, 102)", + * > whiteSpace: "normal", + * > fontSize: "14.6667px", + * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif", + * > fontWeight: "400" + * > } + * > }, + * > yaxis: { + * > borderColor: "#999999", + * > borderWidth: 2, + * > ticks: { + * > show: true, + * > showGridline: true, + * > showLabel: true, + * > showMark: true, + * > size: 4, + * > textColor: "", + * > whiteSpace: "nowrap", + * > fontSize: "12px", + * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif" + * > }, + * > label: { + * > textColor: null, + * > whiteSpace: null, + * > fontSize: null, + * > fontFamily: null, + * > fontWeight: null + * > } + * > }, + * > x2axis: {... + * > }, + * > ... + * > y9axis: {... + * > } + * > } + * > } + * + * "seriesStyles" is a style object that will be applied to all series in the plot. + * It will forcibly override any styles applied on the individual series. "axesStyles" is + * a style object that will be applied to all axes in the plot. It will also forcibly + * override any styles on the individual axes. + * + * The example shown above has series options for a line series. Options for other + * series types are shown below: + * + * Bar Series: + * + * > { + * > color: "#4bb2c5", + * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"], + * > lineWidth: 2.5, + * > shadow: true, + * > barPadding: 2, + * > barMargin: 10, + * > barWidth: 15.09375, + * > highlightColors: ["rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)"] + * > } + * + * Pie Series: + * + * > { + * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"], + * > padding: 20, + * > sliceMargin: 0, + * > fill: true, + * > shadow: true, + * > startAngle: 0, + * > lineWidth: 2.5, + * > highlightColors: ["rgb(129,201,214)", "rgb(240,189,104)", "rgb(214,202,165)", "rgb(137,180,158)", "rgb(168,180,137)", "rgb(180,174,89)", "rgb(180,113,161)", "rgb(129,141,236)", "rgb(227,205,120)", "rgb(255,138,76)", "rgb(76,169,219)", "rgb(215,126,190)", "rgb(220,232,135)", "rgb(200,167,96)", "rgb(103,202,235)", "rgb(208,154,215)"] + * > } + * + * Funnel Series: + * + * > { + * > color: "#4bb2c5", + * > lineWidth: 2, + * > shadow: true, + * > padding: { + * > top: 20, + * > right: 20, + * > bottom: 20, + * > left: 20 + * > }, + * > sectionMargin: 6, + * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"], + * > highlightColors: ["rgb(147,208,220)", "rgb(242,199,126)", "rgb(220,210,178)", "rgb(154,191,172)", "rgb(180,191,154)", "rgb(191,186,112)", "rgb(191,133,174)", "rgb(147,157,238)", "rgb(231,212,139)", "rgb(255,154,102)", "rgb(102,181,224)", "rgb(221,144,199)", "rgb(225,235,152)", "rgb(200,167,96)", "rgb(124,210,238)", "rgb(215,169,221)"] + * > } + * + */ + $.jqplot.ThemeEngine = function(){ + // Group: Properties + // + // prop: themes + // hash of themes managed by the theme engine. + // Indexed by theme name. + this.themes = {}; + // prop: activeTheme + // Pointer to currently active theme + this.activeTheme=null; + + }; + + // called with scope of plot + $.jqplot.ThemeEngine.prototype.init = function() { + // get the Default theme from the current plot settings. + var th = new $.jqplot.Theme({_name:'Default'}); + var n, i, nn; + + for (n in th.target) { + if (n == "textColor") { + th.target[n] = this.target.css('color'); + } + else { + th.target[n] = this.target.css(n); + } + } + + if (this.title.show && this.title._elem) { + for (n in th.title) { + if (n == "textColor") { + th.title[n] = this.title._elem.css('color'); + } + else { + th.title[n] = this.title._elem.css(n); + } + } + } + + for (n in th.grid) { + th.grid[n] = this.grid[n]; + } + if (th.grid.backgroundColor == null && this.grid.background != null) { + th.grid.backgroundColor = this.grid.background; + } + if (this.legend.show && this.legend._elem) { + for (n in th.legend) { + if (n == 'textColor') { + th.legend[n] = this.legend._elem.css('color'); + } + else { + th.legend[n] = this.legend._elem.css(n); + } + } + } + var s; + + for (i=0; i<this.series.length; i++) { + s = this.series[i]; + if (s.renderer.constructor == $.jqplot.LineRenderer) { + th.series.push(new LineSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.BarRenderer) { + th.series.push(new BarSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.PieRenderer) { + th.series.push(new PieSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.DonutRenderer) { + th.series.push(new DonutSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.FunnelRenderer) { + th.series.push(new FunnelSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.MeterGaugeRenderer) { + th.series.push(new MeterSeriesProperties()); + } + else { + th.series.push({}); + } + for (n in th.series[i]) { + th.series[i][n] = s[n]; + } + } + var a, ax; + for (n in this.axes) { + ax = this.axes[n]; + a = th.axes[n] = new AxisProperties(); + a.borderColor = ax.borderColor; + a.borderWidth = ax.borderWidth; + if (ax._ticks && ax._ticks[0]) { + for (nn in a.ticks) { + if (ax._ticks[0].hasOwnProperty(nn)) { + a.ticks[nn] = ax._ticks[0][nn]; + } + else if (ax._ticks[0]._elem){ + a.ticks[nn] = ax._ticks[0]._elem.css(nn); + } + } + } + if (ax._label && ax._label.show) { + for (nn in a.label) { + // a.label[nn] = ax._label._elem.css(nn); + if (ax._label[nn]) { + a.label[nn] = ax._label[nn]; + } + else if (ax._label._elem){ + if (nn == 'textColor') { + a.label[nn] = ax._label._elem.css('color'); + } + else { + a.label[nn] = ax._label._elem.css(nn); + } + } + } + } + } + this.themeEngine._add(th); + this.themeEngine.activeTheme = this.themeEngine.themes[th._name]; + }; + /** + * Group: methods + * + * method: get + * + * Get and return the named theme or the active theme if no name given. + * + * parameter: + * + * name - name of theme to get. + * + * returns: + * + * Theme instance of given name. + */ + $.jqplot.ThemeEngine.prototype.get = function(name) { + if (!name) { + // return the active theme + return this.activeTheme; + } + else { + return this.themes[name]; + } + }; + + function numericalOrder(a,b) { return a-b; } + + /** + * method: getThemeNames + * + * Return the list of theme names in this manager in alpha-numerical order. + * + * parameter: + * + * None + * + * returns: + * + * A the list of theme names in this manager in alpha-numerical order. + */ + $.jqplot.ThemeEngine.prototype.getThemeNames = function() { + var tn = []; + for (var n in this.themes) { + tn.push(n); + } + return tn.sort(numericalOrder); + }; + + /** + * method: getThemes + * + * Return a list of themes in alpha-numerical order by name. + * + * parameter: + * + * None + * + * returns: + * + * A list of themes in alpha-numerical order by name. + */ + $.jqplot.ThemeEngine.prototype.getThemes = function() { + var tn = []; + var themes = []; + for (var n in this.themes) { + tn.push(n); + } + tn.sort(numericalOrder); + for (var i=0; i<tn.length; i++) { + themes.push(this.themes[tn[i]]); + } + return themes; + }; + + $.jqplot.ThemeEngine.prototype.activate = function(plot, name) { + // sometimes need to redraw whole plot. + var redrawPlot = false; + if (!name && this.activeTheme && this.activeTheme._name) { + name = this.activeTheme._name; + } + if (!this.themes.hasOwnProperty(name)) { + throw new Error("No theme of that name"); + } + else { + var th = this.themes[name]; + this.activeTheme = th; + var val, checkBorderColor = false, checkBorderWidth = false; + var arr = ['xaxis', 'x2axis', 'yaxis', 'y2axis']; + + for (i=0; i<arr.length; i++) { + var ax = arr[i]; + if (th.axesStyles.borderColor != null) { + plot.axes[ax].borderColor = th.axesStyles.borderColor; + } + if (th.axesStyles.borderWidth != null) { + plot.axes[ax].borderWidth = th.axesStyles.borderWidth; + } + } + + for (var axname in plot.axes) { + var axis = plot.axes[axname]; + if (axis.show) { + var thaxis = th.axes[axname] || {}; + var thaxstyle = th.axesStyles; + var thax = $.jqplot.extend(true, {}, thaxis, thaxstyle); + val = (th.axesStyles.borderColor != null) ? th.axesStyles.borderColor : thax.borderColor; + if (thax.borderColor != null) { + axis.borderColor = thax.borderColor; + redrawPlot = true; + } + val = (th.axesStyles.borderWidth != null) ? th.axesStyles.borderWidth : thax.borderWidth; + if (thax.borderWidth != null) { + axis.borderWidth = thax.borderWidth; + redrawPlot = true; + } + if (axis._ticks && axis._ticks[0]) { + for (var nn in thax.ticks) { + // val = null; + // if (th.axesStyles.ticks && th.axesStyles.ticks[nn] != null) { + // val = th.axesStyles.ticks[nn]; + // } + // else if (thax.ticks[nn] != null){ + // val = thax.ticks[nn] + // } + val = thax.ticks[nn]; + if (val != null) { + axis.tickOptions[nn] = val; + axis._ticks = []; + redrawPlot = true; + } + } + } + if (axis._label && axis._label.show) { + for (var nn in thax.label) { + // val = null; + // if (th.axesStyles.label && th.axesStyles.label[nn] != null) { + // val = th.axesStyles.label[nn]; + // } + // else if (thax.label && thax.label[nn] != null){ + // val = thax.label[nn] + // } + val = thax.label[nn]; + if (val != null) { + axis.labelOptions[nn] = val; + redrawPlot = true; + } + } + } + + } + } + + for (var n in th.grid) { + if (th.grid[n] != null) { + plot.grid[n] = th.grid[n]; + } + } + if (!redrawPlot) { + plot.grid.draw(); + } + + if (plot.legend.show) { + for (n in th.legend) { + if (th.legend[n] != null) { + plot.legend[n] = th.legend[n]; + } + } + } + if (plot.title.show) { + for (n in th.title) { + if (th.title[n] != null) { + plot.title[n] = th.title[n]; + } + } + } + + var i; + for (i=0; i<th.series.length; i++) { + var opts = {}; + var redrawSeries = false; + for (n in th.series[i]) { + val = (th.seriesStyles[n] != null) ? th.seriesStyles[n] : th.series[i][n]; + if (val != null) { + opts[n] = val; + if (n == 'color') { + plot.series[i].renderer.shapeRenderer.fillStyle = val; + plot.series[i].renderer.shapeRenderer.strokeStyle = val; + plot.series[i][n] = val; + } + else if (n == 'lineWidth') { + plot.series[i].renderer.shapeRenderer.lineWidth = val; + plot.series[i][n] = val; + } + else if (n == 'markerOptions') { + merge (plot.series[i].markerOptions, val); + merge (plot.series[i].markerRenderer, val); + } + else { + plot.series[i][n] = val; + } + redrawPlot = true; + } + } + } + + if (redrawPlot) { + plot.target.empty(); + plot.draw(); + } + + for (n in th.target) { + if (th.target[n] != null) { + plot.target.css(n, th.target[n]); + } + } + } + + }; + + $.jqplot.ThemeEngine.prototype._add = function(theme, name) { + if (name) { + theme._name = name; + } + if (!theme._name) { + theme._name = Date.parse(new Date()); + } + if (!this.themes.hasOwnProperty(theme._name)) { + this.themes[theme._name] = theme; + } + else { + throw new Error("jqplot.ThemeEngine Error: Theme already in use"); + } + }; + + // method remove + // Delete the named theme, return true on success, false on failure. + + + /** + * method: remove + * + * Remove the given theme from the themeEngine. + * + * parameters: + * + * name - name of the theme to remove. + * + * returns: + * + * true on success, false on failure. + */ + $.jqplot.ThemeEngine.prototype.remove = function(name) { + if (name == 'Default') { + return false; + } + return delete this.themes[name]; + }; + + /** + * method: newTheme + * + * Create a new theme based on the default theme, adding it the themeEngine. + * + * parameters: + * + * name - name of the new theme. + * obj - optional object of styles to be applied to this new theme. + * + * returns: + * + * new Theme object. + */ + $.jqplot.ThemeEngine.prototype.newTheme = function(name, obj) { + if (typeof(name) == 'object') { + obj = obj || name; + name = null; + } + if (obj && obj._name) { + name = obj._name; + } + else { + name = name || Date.parse(new Date()); + } + // var th = new $.jqplot.Theme(name); + var th = this.copy(this.themes['Default']._name, name); + $.jqplot.extend(th, obj); + return th; + }; + + // function clone(obj) { + // return eval(obj.toSource()); + // } + + function clone(obj){ + if(obj == null || typeof(obj) != 'object'){ + return obj; + } + + var temp = new obj.constructor(); + for(var key in obj){ + temp[key] = clone(obj[key]); + } + return temp; + } + + $.jqplot.clone = clone; + + function merge(obj1, obj2) { + if (obj2 == null || typeof(obj2) != 'object') { + return; + } + for (var key in obj2) { + if (key == 'highlightColors') { + obj1[key] = clone(obj2[key]); + } + if (obj2[key] != null && typeof(obj2[key]) == 'object') { + if (!obj1.hasOwnProperty(key)) { + obj1[key] = {}; + } + merge(obj1[key], obj2[key]); + } + else { + obj1[key] = obj2[key]; + } + } + } + + $.jqplot.merge = merge; + + // Use the jQuery 1.3.2 extend function since behaviour in jQuery 1.4 seems problematic + $.jqplot.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !toString.call(target) === "[object Function]" ) { + target = {}; + } + + for ( ; i < length; i++ ){ + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( var name in options ) { + var src = target[ name ], copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging object values + if ( deep && copy && typeof copy === "object" && !copy.nodeType ) { + target[ name ] = $.jqplot.extend( deep, + // Never move original objects, clone them + src || ( copy.length != null ? [ ] : { } ) + , copy ); + } + // Don't bring in undefined values + else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + // Return the modified object + return target; + }; + + /** + * method: rename + * + * Rename a theme. + * + * parameters: + * + * oldName - current name of the theme. + * newName - desired name of the theme. + * + * returns: + * + * new Theme object. + */ + $.jqplot.ThemeEngine.prototype.rename = function (oldName, newName) { + if (oldName == 'Default' || newName == 'Default') { + throw new Error ("jqplot.ThemeEngine Error: Cannot rename from/to Default"); + } + if (this.themes.hasOwnProperty(newName)) { + throw new Error ("jqplot.ThemeEngine Error: New name already in use."); + } + else if (this.themes.hasOwnProperty(oldName)) { + var th = this.copy (oldName, newName); + this.remove(oldName); + return th; + } + throw new Error("jqplot.ThemeEngine Error: Old name or new name invalid"); + }; + + /** + * method: copy + * + * Create a copy of an existing theme in the themeEngine, adding it the themeEngine. + * + * parameters: + * + * sourceName - name of the existing theme. + * targetName - name of the copy. + * obj - optional object of style parameter to apply to the new theme. + * + * returns: + * + * new Theme object. + */ + $.jqplot.ThemeEngine.prototype.copy = function (sourceName, targetName, obj) { + if (targetName == 'Default') { + throw new Error ("jqplot.ThemeEngine Error: Cannot copy over Default theme"); + } + if (!this.themes.hasOwnProperty(sourceName)) { + var s = "jqplot.ThemeEngine Error: Source name invalid"; + throw new Error(s); + } + if (this.themes.hasOwnProperty(targetName)) { + var s = "jqplot.ThemeEngine Error: Target name invalid"; + throw new Error(s); + } + else { + var th = clone(this.themes[sourceName]); + th._name = targetName; + $.jqplot.extend(true, th, obj); + this._add(th); + return th; + } + }; + + + $.jqplot.Theme = function(name, obj) { + if (typeof(name) == 'object') { + obj = obj || name; + name = null; + } + name = name || Date.parse(new Date()); + this._name = name; + this.target = { + backgroundColor: null + }; + this.legend = { + textColor: null, + fontFamily: null, + fontSize: null, + border: null, + background: null + }; + this.title = { + textColor: null, + fontFamily: null, + fontSize: null, + textAlign: null + }; + this.seriesStyles = {}; + this.series = []; + this.grid = { + drawGridlines: null, + gridLineColor: null, + gridLineWidth: null, + backgroundColor: null, + borderColor: null, + borderWidth: null, + shadow: null + }; + this.axesStyles = {label:{}, ticks:{}}; + this.axes = {}; + if (typeof(obj) == 'string') { + this._name = obj; + } + else if(typeof(obj) == 'object') { + $.jqplot.extend(true, this, obj); + } + }; + + var AxisProperties = function() { + this.borderColor = null; + this.borderWidth = null; + this.ticks = new AxisTicks(); + this.label = new AxisLabel(); + }; + + var AxisTicks = function() { + this.show = null; + this.showGridline = null; + this.showLabel = null; + this.showMark = null; + this.size = null; + this.textColor = null; + this.whiteSpace = null; + this.fontSize = null; + this.fontFamily = null; + }; + + var AxisLabel = function() { + this.textColor = null; + this.whiteSpace = null; + this.fontSize = null; + this.fontFamily = null; + this.fontWeight = null; + }; + + var LineSeriesProperties = function() { + this.color=null; + this.lineWidth=null; + this.shadow=null; + this.fillColor=null; + this.showMarker=null; + this.markerOptions = new MarkerOptions(); + }; + + var MarkerOptions = function() { + this.show = null; + this.style = null; + this.lineWidth = null; + this.size = null; + this.color = null; + this.shadow = null; + }; + + var BarSeriesProperties = function() { + this.color=null; + this.seriesColors=null; + this.lineWidth=null; + this.shadow=null; + this.barPadding=null; + this.barMargin=null; + this.barWidth=null; + this.highlightColors=null; + }; + + var PieSeriesProperties = function() { + this.seriesColors=null; + this.padding=null; + this.sliceMargin=null; + this.fill=null; + this.shadow=null; + this.startAngle=null; + this.lineWidth=null; + this.highlightColors=null; + }; + + var DonutSeriesProperties = function() { + this.seriesColors=null; + this.padding=null; + this.sliceMargin=null; + this.fill=null; + this.shadow=null; + this.startAngle=null; + this.lineWidth=null; + this.innerDiameter=null; + this.thickness=null; + this.ringMargin=null; + this.highlightColors=null; + }; + + var FunnelSeriesProperties = function() { + this.color=null; + this.lineWidth=null; + this.shadow=null; + this.padding=null; + this.sectionMargin=null; + this.seriesColors=null; + this.highlightColors=null; + }; + + var MeterSeriesProperties = function() { + this.padding=null; + this.backgroundColor=null; + this.ringColor=null; + this.tickColor=null; + this.ringWidth=null; + this.intervalColors=null; + this.intervalInnerRadius=null; + this.intervalOuterRadius=null; + this.hubRadius=null; + this.needleThickness=null; + this.needlePad=null; + }; + + + + + /** + * @description + * <p>Object with extended date parsing and formatting capabilities. + * This library borrows many concepts and ideas from the Date Instance + * Methods by Ken Snyder along with some parts of Ken's actual code.</p> + * + * <p>jsDate takes a different approach by not extending the built-in + * Date Object, improving date parsing, allowing for multiple formatting + * syntaxes and multiple and more easily expandable localization.</p> + * + * @author Chris Leonello + * @date #date# + * @version #VERSION# + * @copyright (c) 2010 Chris Leonello + * jsDate is currently available for use in all personal or commercial projects + * under both the MIT and GPL version 2.0 licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * <p>Ken's origianl Date Instance Methods and copyright notice:</p> + * <pre> + * Ken Snyder (ken d snyder at gmail dot com) + * 2008-09-10 + * version 2.0.2 (http://kendsnyder.com/sandbox/date/) + * Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/) + * </pre> + * + * @class + * @name jsDate + * @param {String | Number | Array | Date Object | Options Object} arguments Optional arguments, either a parsable date/time string, + * a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds], + * a Date object, or an options object of form {syntax: "perl", date:some Date} where all options are optional. + */ + + var jsDate = function () { + + this.syntax = jsDate.config.syntax; + this._type = "jsDate"; + this.utcOffset = new Date().getTimezoneOffset * 60000; + this.proxy = new Date(); + this.options = {}; + this.locale = jsDate.regional.getLocale(); + this.formatString = ''; + this.defaultCentury = jsDate.config.defaultCentury; + + switch ( arguments.length ) { + case 0: + break; + case 1: + // other objects either won't have a _type property or, + // if they do, it shouldn't be set to "jsDate", so + // assume it is an options argument. + if (get_type(arguments[0]) == "[object Object]" && arguments[0]._type != "jsDate") { + var opts = this.options = arguments[0]; + this.syntax = opts.syntax || this.syntax; + this.defaultCentury = opts.defaultCentury || this.defaultCentury; + this.proxy = jsDate.createDate(opts.date); + } + else { + this.proxy = jsDate.createDate(arguments[0]); + } + break; + default: + var a = []; + for ( var i=0; i<arguments.length; i++ ) { + a.push(arguments[i]); + } + this.proxy = new Date( this.utcOffset ); + this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) ); + if ( a.slice(3).length ) { + this.proxy.setHours.apply( this.proxy, a.slice(3) ); + } + break; + } + }; + + /** + * @namespace Configuration options that will be used as defaults for all instances on the page. + * @property {String} defaultLocale The default locale to use [en]. + * @property {String} syntax The default syntax to use [perl]. + */ + jsDate.config = { + defaultLocale: 'en', + syntax: 'perl', + defaultCentury: 1900 + }; + + /** + * Add an arbitrary amount to the currently stored date + * + * @param {Number} number + * @param {String} unit + * @returns {jsDate} + */ + + jsDate.prototype.add = function(number, unit) { + var factor = multipliers[unit] || multipliers.day; + if (typeof factor == 'number') { + this.proxy.setTime(this.proxy.getTime() + (factor * number)); + } else { + factor.add(this, number); + } + return this; + }; + + /** + * Create a new jqplot.date object with the same date + * + * @returns {jsDate} + */ + + jsDate.prototype.clone = function() { + return new jsDate(this.proxy.getTime()); + }; + + /** + * Find the difference between this jsDate and another date. + * + * @param {String| Number| Array| jsDate Object| Date Object} dateObj + * @param {String} unit + * @param {Boolean} allowDecimal + * @returns {Number} Number of units difference between dates. + */ + + jsDate.prototype.diff = function(dateObj, unit, allowDecimal) { + // ensure we have a Date object + dateObj = new jsDate(dateObj); + if (dateObj === null) { + return null; + } + // get the multiplying factor integer or factor function + var factor = multipliers[unit] || multipliers.day; + if (typeof factor == 'number') { + // multiply + var unitDiff = (this.proxy.getTime() - dateObj.proxy.getTime()) / factor; + } else { + // run function + var unitDiff = factor.diff(this.proxy, dateObj.proxy); + } + // if decimals are not allowed, round toward zero + return (allowDecimal ? unitDiff : Math[unitDiff > 0 ? 'floor' : 'ceil'](unitDiff)); + }; + + /** + * Get the abbreviated name of the current week day + * + * @returns {String} + */ + + jsDate.prototype.getAbbrDayName = function() { + return jsDate.regional[this.locale]["dayNamesShort"][this.proxy.getDay()]; + }; + + /** + * Get the abbreviated name of the current month + * + * @returns {String} + */ + + jsDate.prototype.getAbbrMonthName = function() { + return jsDate.regional[this.locale]["monthNamesShort"][this.proxy.getMonth()]; + }; + + /** + * Get UPPER CASE AM or PM for the current time + * + * @returns {String} + */ + + jsDate.prototype.getAMPM = function() { + return this.proxy.getHours() >= 12 ? 'PM' : 'AM'; + }; + + /** + * Get lower case am or pm for the current time + * + * @returns {String} + */ + + jsDate.prototype.getAmPm = function() { + return this.proxy.getHours() >= 12 ? 'pm' : 'am'; + }; + + /** + * Get the century (19 for 20th Century) + * + * @returns {Integer} Century (19 for 20th century). + */ + jsDate.prototype.getCentury = function() { + return parseInt(this.proxy.getFullYear()/100, 10); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getDate = function() { + return this.proxy.getDate(); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getDay = function() { + return this.proxy.getDay(); + }; + + /** + * Get the Day of week 1 (Monday) thru 7 (Sunday) + * + * @returns {Integer} Day of week 1 (Monday) thru 7 (Sunday) + */ + jsDate.prototype.getDayOfWeek = function() { + var dow = this.proxy.getDay(); + return dow===0?7:dow; + }; + + /** + * Get the day of the year + * + * @returns {Integer} 1 - 366, day of the year + */ + jsDate.prototype.getDayOfYear = function() { + var d = this.proxy; + var ms = d - new Date('' + d.getFullYear() + '/1/1 GMT'); + ms += d.getTimezoneOffset()*60000; + d = null; + return parseInt(ms/60000/60/24, 10)+1; + }; + + /** + * Get the name of the current week day + * + * @returns {String} + */ + + jsDate.prototype.getDayName = function() { + return jsDate.regional[this.locale]["dayNames"][this.proxy.getDay()]; + }; + + /** + * Get the week number of the given year, starting with the first Sunday as the first week + * @returns {Integer} Week number (13 for the 13th full week of the year). + */ + jsDate.prototype.getFullWeekOfYear = function() { + var d = this.proxy; + var doy = this.getDayOfYear(); + var rdow = 6-d.getDay(); + var woy = parseInt((doy+rdow)/7, 10); + return woy; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getFullYear = function() { + return this.proxy.getFullYear(); + }; + + /** + * Get the GMT offset in hours and minutes (e.g. +06:30) + * + * @returns {String} + */ + + jsDate.prototype.getGmtOffset = function() { + // divide the minutes offset by 60 + var hours = this.proxy.getTimezoneOffset() / 60; + // decide if we are ahead of or behind GMT + var prefix = hours < 0 ? '+' : '-'; + // remove the negative sign if any + hours = Math.abs(hours); + // add the +/- to the padded number of hours to : to the padded minutes + return prefix + addZeros(Math.floor(hours), 2) + ':' + addZeros((hours % 1) * 60, 2); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getHours = function() { + return this.proxy.getHours(); + }; + + /** + * Get the current hour on a 12-hour scheme + * + * @returns {Integer} + */ + + jsDate.prototype.getHours12 = function() { + var hours = this.proxy.getHours(); + return hours > 12 ? hours - 12 : (hours == 0 ? 12 : hours); + }; + + + jsDate.prototype.getIsoWeek = function() { + var d = this.proxy; + var woy = d.getWeekOfYear(); + var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay(); + // First week is 01 and not 00 as in the case of %U and %W, + // so we add 1 to the final result except if day 1 of the year + // is a Monday (then %W returns 01). + // We also need to subtract 1 if the day 1 of the year is + // Friday-Sunday, so the resulting equation becomes: + var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1); + if(idow == 53 && (new Date('' + d.getFullYear() + '/12/31')).getDay() < 4) + { + idow = 1; + } + else if(idow === 0) + { + d = new jsDate(new Date('' + (d.getFullYear()-1) + '/12/31')); + idow = d.getIsoWeek(); + } + d = null; + return idow; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getMilliseconds = function() { + return this.proxy.getMilliseconds(); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getMinutes = function() { + return this.proxy.getMinutes(); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getMonth = function() { + return this.proxy.getMonth(); + }; + + /** + * Get the name of the current month + * + * @returns {String} + */ + + jsDate.prototype.getMonthName = function() { + return jsDate.regional[this.locale]["monthNames"][this.proxy.getMonth()]; + }; + + /** + * Get the number of the current month, 1-12 + * + * @returns {Integer} + */ + + jsDate.prototype.getMonthNumber = function() { + return this.proxy.getMonth() + 1; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getSeconds = function() { + return this.proxy.getSeconds(); + }; + + /** + * Return a proper two-digit year integer + * + * @returns {Integer} + */ + + jsDate.prototype.getShortYear = function() { + return this.proxy.getYear() % 100; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getTime = function() { + return this.proxy.getTime(); + }; + + /** + * Get the timezone abbreviation + * + * @returns {String} Abbreviation for the timezone + */ + jsDate.prototype.getTimezoneAbbr = function() { + return this.proxy.toString().replace(/^.*\(([^)]+)\)$/, '$1'); + }; + + /** + * Get the browser-reported name for the current timezone (e.g. MDT, Mountain Daylight Time) + * + * @returns {String} + */ + jsDate.prototype.getTimezoneName = function() { + var match = /(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString()); + return match[1] || match[2] || 'GMT' + this.getGmtOffset(); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getTimezoneOffset = function() { + return this.proxy.getTimezoneOffset(); + }; + + + /** + * Get the week number of the given year, starting with the first Monday as the first week + * @returns {Integer} Week number (13 for the 13th week of the year). + */ + jsDate.prototype.getWeekOfYear = function() { + var doy = this.getDayOfYear(); + var rdow = 7 - this.getDayOfWeek(); + var woy = parseInt((doy+rdow)/7, 10); + return woy; + }; + + /** + * Get the current date as a Unix timestamp + * + * @returns {Integer} + */ + + jsDate.prototype.getUnix = function() { + return Math.round(this.proxy.getTime() / 1000, 0); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getYear = function() { + return this.proxy.getYear(); + }; + + /** + * Return a date one day ahead (or any other unit) + * + * @param {String} unit Optional, year | month | day | week | hour | minute | second | millisecond + * @returns {jsDate} + */ + + jsDate.prototype.next = function(unit) { + unit = unit || 'day'; + return this.clone().add(1, unit); + }; + + /** + * Set the jsDate instance to a new date. + * + * @param {String | Number | Array | Date Object | jsDate Object | Options Object} arguments Optional arguments, + * either a parsable date/time string, + * a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds], + * a Date object, jsDate Object or an options object of form {syntax: "perl", date:some Date} where all options are optional. + */ + jsDate.prototype.set = function() { + switch ( arguments.length ) { + case 0: + this.proxy = new Date(); + break; + case 1: + // other objects either won't have a _type property or, + // if they do, it shouldn't be set to "jsDate", so + // assume it is an options argument. + if (get_type(arguments[0]) == "[object Object]" && arguments[0]._type != "jsDate") { + var opts = this.options = arguments[0]; + this.syntax = opts.syntax || this.syntax; + this.defaultCentury = opts.defaultCentury || this.defaultCentury; + this.proxy = jsDate.createDate(opts.date); + } + else { + this.proxy = jsDate.createDate(arguments[0]); + } + break; + default: + var a = []; + for ( var i=0; i<arguments.length; i++ ) { + a.push(arguments[i]); + } + this.proxy = new Date( this.utcOffset ); + this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) ); + if ( a.slice(3).length ) { + this.proxy.setHours.apply( this.proxy, a.slice(3) ); + } + break; + } + }; + + /** + * Sets the day of the month for a specified date according to local time. + * @param {Integer} dayValue An integer from 1 to 31, representing the day of the month. + */ + jsDate.prototype.setDate = function(n) { + return this.proxy.setDate(n); + }; + + /** + * Sets the full year for a specified date according to local time. + * @param {Integer} yearValue The numeric value of the year, for example, 1995. + * @param {Integer} monthValue Optional, between 0 and 11 representing the months January through December. + * @param {Integer} dayValue Optional, between 1 and 31 representing the day of the month. If you specify the dayValue parameter, you must also specify the monthValue. + */ + jsDate.prototype.setFullYear = function() { + return this.proxy.setFullYear.apply(this.proxy, arguments); + }; + + /** + * Sets the hours for a specified date according to local time. + * + * @param {Integer} hoursValue An integer between 0 and 23, representing the hour. + * @param {Integer} minutesValue Optional, An integer between 0 and 59, representing the minutes. + * @param {Integer} secondsValue Optional, An integer between 0 and 59, representing the seconds. + * If you specify the secondsValue parameter, you must also specify the minutesValue. + * @param {Integer} msValue Optional, A number between 0 and 999, representing the milliseconds. + * If you specify the msValue parameter, you must also specify the minutesValue and secondsValue. + */ + jsDate.prototype.setHours = function() { + return this.proxy.setHours.apply(this.proxy, arguments); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setMilliseconds = function(n) { + return this.proxy.setMilliseconds(n); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setMinutes = function() { + return this.proxy.setMinutes.apply(this.proxy, arguments); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setMonth = function() { + return this.proxy.setMonth.apply(this.proxy, arguments); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setSeconds = function() { + return this.proxy.setSeconds.apply(this.proxy, arguments); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setTime = function(n) { + return this.proxy.setTime(n); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setYear = function() { + return this.proxy.setYear.apply(this.proxy, arguments); + }; + + /** + * Provide a formatted string representation of this date. + * + * @param {String} formatString A format string. + * See: {@link jsDate.formats}. + * @returns {String} Date String. + */ + + jsDate.prototype.strftime = function(formatString) { + formatString = formatString || this.formatString || jsDate.regional[this.locale]['formatString']; + return jsDate.strftime(this, formatString, this.syntax); + }; + + /** + * Return a String representation of this jsDate object. + * @returns {String} Date string. + */ + + jsDate.prototype.toString = function() { + return this.proxy.toString(); + }; + + /** + * Convert the current date to an 8-digit integer (%Y%m%d) + * + * @returns {Integer} + */ + + jsDate.prototype.toYmdInt = function() { + return (this.proxy.getFullYear() * 10000) + (this.getMonthNumber() * 100) + this.proxy.getDate(); + }; + + /** + * @namespace Holds localizations for month/day names. + * <p>jsDate attempts to detect locale when loaded and defaults to 'en'. + * If a localization is detected which is not available, jsDate defaults to 'en'. + * Additional localizations can be added after jsDate loads. After adding a localization, + * call the jsDate.regional.getLocale() method. Currently, en, fr and de are defined.</p> + * + * <p>Localizations must be an object and have the following properties defined: monthNames, monthNamesShort, dayNames, dayNamesShort and Localizations are added like:</p> + * <pre class="code"> + * jsDate.regional['en'] = { + * monthNames : 'January February March April May June July August September October November December'.split(' '), + * monthNamesShort : 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '), + * dayNames : 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '), + * dayNamesShort : 'Sun Mon Tue Wed Thu Fri Sat'.split(' ') + * }; + * </pre> + * <p>After adding localizations, call <code>jsDate.regional.getLocale();</code> to update the locale setting with the + * new localizations.</p> + */ + + jsDate.regional = { + 'en': { + monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'], + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'fr': { + monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'], + monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun','Jul','Aoû','Sep','Oct','Nov','Déc'], + dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'], + dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'de': { + monthNames: ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'], + monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'], + dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'], + dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'es': { + monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'], + monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun', 'Jul','Ago','Sep','Oct','Nov','Dic'], + dayNames: ['Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'], + dayNamesShort: ['Dom','Lun','Mar','Mié','Juv','Vie','Sáb'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'ru': { + monthNames: ['Январь','Февраль','Март','Ðпрель','Май','Июнь','Июль','ÐвгуÑÑ‚','СентÑбрь','ОктÑбрь','ÐоÑбрь','Декабрь'], + monthNamesShort: ['Янв','Фев','Мар','Ðпр','Май','Июн','Июл','Ðвг','Сен','Окт','ÐоÑ','Дек'], + dayNames: ['воÑкреÑенье','понедельник','вторник','Ñреда','четверг','пÑтница','Ñуббота'], + dayNamesShort: ['вÑк','пнд','втр','Ñрд','чтв','птн','Ñбт'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'ar': { + monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'حزيران','تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], + monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'], + dayNames: ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'], + dayNamesShort: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'pt': { + monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'], + monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'], + dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'], + dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'pt-BR': { + monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho', 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'], + monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'], + dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'], + dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'], + formatString: '%Y-%m-%d %H:%M:%S' + } + + + }; + + // Set english variants to 'en' + jsDate.regional['en-US'] = jsDate.regional['en-GB'] = jsDate.regional['en']; + + /** + * Try to determine the users locale based on the lang attribute of the html page. Defaults to 'en' + * if it cannot figure out a locale of if the locale does not have a localization defined. + * @returns {String} locale + */ + + jsDate.regional.getLocale = function () { + var l = jsDate.config.defaultLocale; + + if ( document && document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang ) { + l = document.getElementsByTagName('html')[0].lang; + if (!jsDate.regional.hasOwnProperty(l)) { + l = jsDate.config.defaultLocale; + } + } + + return l; + }; + + // ms in day + var day = 24 * 60 * 60 * 1000; + + // padd a number with zeros + var addZeros = function(num, digits) { + num = String(num); + var i = digits - num.length; + var s = String(Math.pow(10, i)).slice(1); + return s.concat(num); + }; + + // representations used for calculating differences between dates. + // This borrows heavily from Ken Snyder's work. + var multipliers = { + millisecond: 1, + second: 1000, + minute: 60 * 1000, + hour: 60 * 60 * 1000, + day: day, + week: 7 * day, + month: { + // add a number of months + add: function(d, number) { + // add any years needed (increments of 12) + multipliers.year.add(d, Math[number > 0 ? 'floor' : 'ceil'](number / 12)); + // ensure that we properly wrap betwen December and January + var prevMonth = d.getMonth() + (number % 12); + if (prevMonth == 12) { + prevMonth = 0; + d.setYear(d.getFullYear() + 1); + } else if (prevMonth == -1) { + prevMonth = 11; + d.setYear(d.getFullYear() - 1); + } + d.setMonth(prevMonth); + }, + // get the number of months between two Date objects (decimal to the nearest day) + diff: function(d1, d2) { + // get the number of years + var diffYears = d1.getFullYear() - d2.getFullYear(); + // get the number of remaining months + var diffMonths = d1.getMonth() - d2.getMonth() + (diffYears * 12); + // get the number of remaining days + var diffDays = d1.getDate() - d2.getDate(); + // return the month difference with the days difference as a decimal + return diffMonths + (diffDays / 30); + } + }, + year: { + // add a number of years + add: function(d, number) { + d.setYear(d.getFullYear() + Math[number > 0 ? 'floor' : 'ceil'](number)); + }, + // get the number of years between two Date objects (decimal to the nearest day) + diff: function(d1, d2) { + return multipliers.month.diff(d1, d2) / 12; + } + } + }; + // + // Alias each multiplier with an 's' to allow 'year' and 'years' for example. + // This comes from Ken Snyders work. + // + for (var unit in multipliers) { + if (unit.substring(unit.length - 1) != 's') { // IE will iterate newly added properties :| + multipliers[unit + 's'] = multipliers[unit]; + } + } + + // + // take a jsDate instance and a format code and return the formatted value. + // This is a somewhat modified version of Ken Snyder's method. + // + var format = function(d, code, syntax) { + // if shorcut codes are used, recursively expand those. + if (jsDate.formats[syntax]["shortcuts"][code]) { + return jsDate.strftime(d, jsDate.formats[syntax]["shortcuts"][code], syntax); + } else { + // get the format code function and addZeros() argument + var getter = (jsDate.formats[syntax]["codes"][code] || '').split('.'); + var nbr = d['get' + getter[0]] ? d['get' + getter[0]]() : ''; + if (getter[1]) { + nbr = addZeros(nbr, getter[1]); + } + return nbr; + } + }; + + /** + * @static + * Static function for convert a date to a string according to a given format. Also acts as namespace for strftime format codes. + * <p>strftime formatting can be accomplished without creating a jsDate object by calling jsDate.strftime():</p> + * <pre class="code"> + * var formattedDate = jsDate.strftime('Feb 8, 2006 8:48:32', '%Y-%m-%d %H:%M:%S'); + * </pre> + * @param {String | Number | Array | jsDate Object | Date Object} date A parsable date string, JavaScript time stamp, Array of form [year, month, day, hours, minutes, seconds, milliseconds], jsDate Object or Date object. + * @param {String} formatString String with embedded date formatting codes. + * See: {@link jsDate.formats}. + * @param {String} syntax Optional syntax to use [default perl]. + * @param {String} locale Optional locale to use. + * @returns {String} Formatted representation of the date. + */ + // + // Logic as implemented here is very similar to Ken Snyder's Date Instance Methods. + // + jsDate.strftime = function(d, formatString, syntax, locale) { + var syn = 'perl'; + var loc = jsDate.regional.getLocale(); + + // check if syntax and locale are available or reversed + if (syntax && jsDate.formats.hasOwnProperty(syntax)) { + syn = syntax; + } + else if (syntax && jsDate.regional.hasOwnProperty(syntax)) { + loc = syntax; + } + + if (locale && jsDate.formats.hasOwnProperty(locale)) { + syn = locale; + } + else if (locale && jsDate.regional.hasOwnProperty(locale)) { + loc = locale; + } + + if (get_type(d) != "[object Object]" || d._type != "jsDate") { + d = new jsDate(d); + d.locale = loc; + } + if (!formatString) { + formatString = d.formatString || jsDate.regional[loc]['formatString']; + } + // default the format string to year-month-day + var source = formatString || '%Y-%m-%d', + result = '', + match; + // replace each format code + while (source.length > 0) { + if (match = source.match(jsDate.formats[syn].codes.matcher)) { + result += source.slice(0, match.index); + result += (match[1] || '') + format(d, match[2], syn); + source = source.slice(match.index + match[0].length); + } else { + result += source; + source = ''; + } + } + return result; + }; + + /** + * @namespace + * Namespace to hold format codes and format shortcuts. "perl" and "php" format codes + * and shortcuts are defined by default. Additional codes and shortcuts can be + * added like: + * + * <pre class="code"> + * jsDate.formats["perl"] = { + * "codes": { + * matcher: /someregex/, + * Y: "fullYear", // name of "get" method without the "get", + * ..., // more codes + * }, + * "shortcuts": { + * F: '%Y-%m-%d', + * ..., // more shortcuts + * } + * }; + * </pre> + * + * <p>Additionally, ISO and SQL shortcuts are defined and can be accesses via: + * <code>jsDate.formats.ISO</code> and <code>jsDate.formats.SQL</code> + */ + + jsDate.formats = { + ISO:'%Y-%m-%dT%H:%M:%S.%N%G', + SQL:'%Y-%m-%d %H:%M:%S' + }; + + /** + * Perl format codes and shortcuts for strftime. + * + * A hash (object) of codes where each code must be an array where the first member is + * the name of a Date.prototype or jsDate.prototype function to call + * and optionally a second member indicating the number to pass to addZeros() + * + * <p>The following format codes are defined:</p> + * + * <pre class="code"> + * Code Result Description + * == Years == + * %Y 2008 Four-digit year + * %y 08 Two-digit year + * + * == Months == + * %m 09 Two-digit month + * %#m 9 One or two-digit month + * %B September Full month name + * %b Sep Abbreviated month name + * + * == Days == + * %d 05 Two-digit day of month + * %#d 5 One or two-digit day of month + * %e 5 One or two-digit day of month + * %A Sunday Full name of the day of the week + * %a Sun Abbreviated name of the day of the week + * %w 0 Number of the day of the week (0 = Sunday, 6 = Saturday) + * + * == Hours == + * %H 23 Hours in 24-hour format (two digits) + * %#H 3 Hours in 24-hour integer format (one or two digits) + * %I 11 Hours in 12-hour format (two digits) + * %#I 3 Hours in 12-hour integer format (one or two digits) + * %p PM AM or PM + * + * == Minutes == + * %M 09 Minutes (two digits) + * %#M 9 Minutes (one or two digits) + * + * == Seconds == + * %S 02 Seconds (two digits) + * %#S 2 Seconds (one or two digits) + * %s 1206567625723 Unix timestamp (Seconds past 1970-01-01 00:00:00) + * + * == Milliseconds == + * %N 008 Milliseconds (three digits) + * %#N 8 Milliseconds (one to three digits) + * + * == Timezone == + * %O 360 difference in minutes between local time and GMT + * %Z Mountain Standard Time Name of timezone as reported by browser + * %G 06:00 Hours and minutes between GMT + * + * == Shortcuts == + * %F 2008-03-26 %Y-%m-%d + * %T 05:06:30 %H:%M:%S + * %X 05:06:30 %H:%M:%S + * %x 03/26/08 %m/%d/%y + * %D 03/26/08 %m/%d/%y + * %#c Wed Mar 26 15:31:00 2008 %a %b %e %H:%M:%S %Y + * %v 3-Sep-2008 %e-%b-%Y + * %R 15:31 %H:%M + * %r 03:31:00 PM %I:%M:%S %p + * + * == Characters == + * %n \n Newline + * %t \t Tab + * %% % Percent Symbol + * </pre> + * + * <p>Formatting shortcuts that will be translated into their longer version. + * Be sure that format shortcuts do not refer to themselves: this will cause an infinite loop.</p> + * + * <p>Format codes and format shortcuts can be redefined after the jsDate + * module is imported.</p> + * + * <p>Note that if you redefine the whole hash (object), you must supply a "matcher" + * regex for the parser. The default matcher is:</p> + * + * <code>/()%(#?(%|[a-z]))/i</code> + * + * <p>which corresponds to the Perl syntax used by default.</p> + * + * <p>By customizing the matcher and format codes, nearly any strftime functionality is possible.</p> + */ + + jsDate.formats.perl = { + codes: { + // + // 2-part regex matcher for format codes + // + // first match must be the character before the code (to account for escaping) + // second match must be the format code character(s) + // + matcher: /()%(#?(%|[a-z]))/i, + // year + Y: 'FullYear', + y: 'ShortYear.2', + // month + m: 'MonthNumber.2', + '#m': 'MonthNumber', + B: 'MonthName', + b: 'AbbrMonthName', + // day + d: 'Date.2', + '#d': 'Date', + e: 'Date', + A: 'DayName', + a: 'AbbrDayName', + w: 'Day', + // hours + H: 'Hours.2', + '#H': 'Hours', + I: 'Hours12.2', + '#I': 'Hours12', + p: 'AMPM', + // minutes + M: 'Minutes.2', + '#M': 'Minutes', + // seconds + S: 'Seconds.2', + '#S': 'Seconds', + s: 'Unix', + // milliseconds + N: 'Milliseconds.3', + '#N': 'Milliseconds', + // timezone + O: 'TimezoneOffset', + Z: 'TimezoneName', + G: 'GmtOffset' + }, + + shortcuts: { + // date + F: '%Y-%m-%d', + // time + T: '%H:%M:%S', + X: '%H:%M:%S', + // local format date + x: '%m/%d/%y', + D: '%m/%d/%y', + // local format extended + '#c': '%a %b %e %H:%M:%S %Y', + // local format short + v: '%e-%b-%Y', + R: '%H:%M', + r: '%I:%M:%S %p', + // tab and newline + t: '\t', + n: '\n', + '%': '%' + } + }; + + /** + * PHP format codes and shortcuts for strftime. + * + * A hash (object) of codes where each code must be an array where the first member is + * the name of a Date.prototype or jsDate.prototype function to call + * and optionally a second member indicating the number to pass to addZeros() + * + * <p>The following format codes are defined:</p> + * + * <pre class="code"> + * Code Result Description + * === Days === + * %a Sun through Sat An abbreviated textual representation of the day + * %A Sunday - Saturday A full textual representation of the day + * %d 01 to 31 Two-digit day of the month (with leading zeros) + * %e 1 to 31 Day of the month, with a space preceding single digits. + * %j 001 to 366 Day of the year, 3 digits with leading zeros + * %u 1 - 7 (Mon - Sun) ISO-8601 numeric representation of the day of the week + * %w 0 - 6 (Sun - Sat) Numeric representation of the day of the week + * + * === Week === + * %U 13 Full Week number, starting with the first Sunday as the first week + * %V 01 through 53 ISO-8601:1988 week number, starting with the first week of the year + * with at least 4 weekdays, with Monday being the start of the week + * %W 46 A numeric representation of the week of the year, + * starting with the first Monday as the first week + * === Month === + * %b Jan through Dec Abbreviated month name, based on the locale + * %B January - December Full month name, based on the locale + * %h Jan through Dec Abbreviated month name, based on the locale (an alias of %b) + * %m 01 - 12 (Jan - Dec) Two digit representation of the month + * + * === Year === + * %C 19 Two digit century (year/100, truncated to an integer) + * %y 09 for 2009 Two digit year + * %Y 2038 Four digit year + * + * === Time === + * %H 00 through 23 Two digit representation of the hour in 24-hour format + * %I 01 through 12 Two digit representation of the hour in 12-hour format + * %l 1 through 12 Hour in 12-hour format, with a space preceeding single digits + * %M 00 through 59 Two digit representation of the minute + * %p AM/PM UPPER-CASE 'AM' or 'PM' based on the given time + * %P am/pm lower-case 'am' or 'pm' based on the given time + * %r 09:34:17 PM Same as %I:%M:%S %p + * %R 00:35 Same as %H:%M + * %S 00 through 59 Two digit representation of the second + * %T 21:34:17 Same as %H:%M:%S + * %X 03:59:16 Preferred time representation based on locale, without the date + * %z -0500 or EST Either the time zone offset from UTC or the abbreviation + * %Z -0500 or EST The time zone offset/abbreviation option NOT given by %z + * + * === Time and Date === + * %D 02/05/09 Same as %m/%d/%y + * %F 2009-02-05 Same as %Y-%m-%d (commonly used in database datestamps) + * %s 305815200 Unix Epoch Time timestamp (same as the time() function) + * %x 02/05/09 Preferred date representation, without the time + * + * === Miscellaneous === + * %n --- A newline character (\n) + * %t --- A Tab character (\t) + * %% --- A literal percentage character (%) + * </pre> + */ + + jsDate.formats.php = { + codes: { + // + // 2-part regex matcher for format codes + // + // first match must be the character before the code (to account for escaping) + // second match must be the format code character(s) + // + matcher: /()%((%|[a-z]))/i, + // day + a: 'AbbrDayName', + A: 'DayName', + d: 'Date.2', + e: 'Date', + j: 'DayOfYear.3', + u: 'DayOfWeek', + w: 'Day', + // week + U: 'FullWeekOfYear.2', + V: 'IsoWeek.2', + W: 'WeekOfYear.2', + // month + b: 'AbbrMonthName', + B: 'MonthName', + m: 'MonthNumber.2', + h: 'AbbrMonthName', + // year + C: 'Century.2', + y: 'ShortYear.2', + Y: 'FullYear', + // time + H: 'Hours.2', + I: 'Hours12.2', + l: 'Hours12', + p: 'AMPM', + P: 'AmPm', + M: 'Minutes.2', + S: 'Seconds.2', + s: 'Unix', + O: 'TimezoneOffset', + z: 'GmtOffset', + Z: 'TimezoneAbbr' + }, + + shortcuts: { + D: '%m/%d/%y', + F: '%Y-%m-%d', + T: '%H:%M:%S', + X: '%H:%M:%S', + x: '%m/%d/%y', + R: '%H:%M', + r: '%I:%M:%S %p', + t: '\t', + n: '\n', + '%': '%' + } + }; + // + // Conceptually, the logic implemented here is similar to Ken Snyder's Date Instance Methods. + // I use his idea of a set of parsers which can be regular expressions or functions, + // iterating through those, and then seeing if Date.parse() will create a date. + // The parser expressions and functions are a little different and some bugs have been + // worked out. Also, a lot of "pre-parsing" is done to fix implementation + // variations of Date.parse() between browsers. + // + jsDate.createDate = function(date) { + // if passing in multiple arguments, try Date constructor + if (date == null) { + return new Date(); + } + // If the passed value is already a date object, return it + if (date instanceof Date) { + return date; + } + // if (typeof date == 'number') return new Date(date * 1000); + // If the passed value is an integer, interpret it as a javascript timestamp + if (typeof date == 'number') { + return new Date(date); + } + + // Before passing strings into Date.parse(), have to normalize them for certain conditions. + // If strings are not formatted staccording to the EcmaScript spec, results from Date parse will be implementation dependent. + // + // For example: + // * FF and Opera assume 2 digit dates are pre y2k, Chome assumes <50 is pre y2k, 50+ is 21st century. + // * Chrome will correctly parse '1984-1-25' into localtime, FF and Opera will not parse. + // * Both FF, Chrome and Opera will parse '1984/1/25' into localtime. + + // remove leading and trailing spaces + var parsable = String(date).replace(/^\s*(.+)\s*$/g, '$1'); + + // replace dahses (-) with slashes (/) in dates like n[nnn]/n[n]/n[nnn] + parsable = parsable.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/, "$1/$2/$3"); + + ///////// + // Need to check for '15-Dec-09' also. + // FF will not parse, but Chrome will. + // Chrome will set date to 2009 as well. + ///////// + + // first check for 'dd-mmm-yyyy' or 'dd/mmm/yyyy' like '15-Dec-2010' + parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i, "$1 $2 $3"); + + // Now check for 'dd-mmm-yy' or 'dd/mmm/yy' and normalize years to default century. + var match = parsable.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i); + if (match && match.length > 3) { + var m3 = parseFloat(match[3]); + var ny = jsDate.config.defaultCentury + m3; + ny = String(ny); + + // now replace 2 digit year with 4 digit year + parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i, match[1] +' '+ match[2] +' '+ ny); + + } + + // Check for '1/19/70 8:14PM' + // where starts with mm/dd/yy or yy/mm/dd and have something after + // Check if 1st postiion is greater than 31, assume it is year. + // Assme all 2 digit years are 1900's. + // Finally, change them into US style mm/dd/yyyy representations. + match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/); + + function h1(parsable, match) { + var m1 = parseFloat(match[1]); + var m2 = parseFloat(match[2]); + var m3 = parseFloat(match[3]); + var cent = jsDate.config.defaultCentury; + var ny, nd, nm, str; + + if (m1 > 31) { // first number is a year + nd = m3; + nm = m2; + ny = cent + m1; + } + + else { // last number is the year + nd = m2; + nm = m1; + ny = cent + m3; + } + + str = nm+'/'+nd+'/'+ny; + + // now replace 2 digit year with 4 digit year + return parsable.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/, str); + + } + + if (match && match.length > 3) { + parsable = h1(parsable, match); + } + + // Now check for '1/19/70' with nothing after and do as above + var match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/); + + if (match && match.length > 3) { + parsable = h1(parsable, match); + } + + + var i = 0; + var length = jsDate.matchers.length; + var pattern, + ms, + current = parsable; + while (i < length) { + ms = Date.parse(current); + if (!isNaN(ms)) { + return new Date(ms); + } + pattern = jsDate.matchers[i]; + if (typeof pattern == 'function') { + var obj = pattern.call(jsDate, current); + if (obj instanceof Date) { + return obj; + } + } else { + current = parsable.replace(pattern[0], pattern[1]); + } + i++; + } + return NaN; + }; + + + /** + * @static + * Handy static utility function to return the number of days in a given month. + * @param {Integer} year Year + * @param {Integer} month Month (1-12) + * @returns {Integer} Number of days in the month. + */ + // + // handy utility method Borrowed right from Ken Snyder's Date Instance Mehtods. + // + jsDate.daysInMonth = function(year, month) { + if (month == 2) { + return new Date(year, 1, 29).getDate() == 29 ? 29 : 28; + } + return [undefined,31,undefined,31,30,31,30,31,31,30,31,30,31][month]; + }; + + + // + // An Array of regular expressions or functions that will attempt to match the date string. + // Functions are called with scope of a jsDate instance. + // + jsDate.matchers = [ + // convert dd.mmm.yyyy to mm/dd/yyyy (world date to US date). + [/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/, '$2/$1/$3'], + // convert yyyy-mm-dd to mm/dd/yyyy (ISO date to US date). + [/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/, '$2/$3/$1'], + // Handle 12 hour or 24 hour time with milliseconds am/pm and optional date part. + function(str) { + var match = str.match(/^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i); + // opt. date hour opt. minute opt. second opt. msec opt. am or pm + if (match) { + if (match[1]) { + var d = this.createDate(match[1]); + if (isNaN(d)) { + return; + } + } else { + var d = new Date(); + d.setMilliseconds(0); + } + var hour = parseFloat(match[2]); + if (match[6]) { + hour = match[6].toLowerCase() == 'am' ? (hour == 12 ? 0 : hour) : (hour == 12 ? 12 : hour + 12); + } + d.setHours(hour, parseInt(match[3] || 0, 10), parseInt(match[4] || 0, 10), ((parseFloat(match[5] || 0)) || 0)*1000); + return d; + } + else { + return str; + } + }, + // Handle ISO timestamp with time zone. + function(str) { + var match = str.match(/^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i); + if (match) { + if (match[1]) { + var d = this.createDate(match[1]); + if (isNaN(d)) { + return; + } + } else { + var d = new Date(); + d.setMilliseconds(0); + } + var hour = parseFloat(match[2]); + d.setHours(hour, parseInt(match[3], 10), parseInt(match[4], 10), parseFloat(match[5])*1000); + return d; + } + else { + return str; + } + }, + // Try to match ambiguous strings like 12/8/22. + // Use FF date assumption that 2 digit years are 20th century (i.e. 1900's). + // This may be redundant with pre processing of date already performed. + function(str) { + var match = str.match(/^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/); + if (match) { + var d = new Date(); + var cent = jsDate.config.defaultCentury; + var m1 = parseFloat(match[1]); + var m3 = parseFloat(match[3]); + var ny, nd, nm; + if (m1 > 31) { // first number is a year + nd = m3; + ny = cent + m1; + } + + else { // last number is the year + nd = m1; + ny = cent + m3; + } + + var nm = inArray(match[2], jsDate.regional[this.locale]["monthNamesShort"]); + + if (nm == -1) { + nm = inArray(match[2], jsDate.regional[this.locale]["monthNames"]); + } + + d.setFullYear(ny, nm, nd); + d.setHours(0,0,0,0); + return d; + } + + else { + return str; + } + } + ]; + + // + // I think John Reisig published this method on his blog, ejohn. + // + function inArray( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + } + + // + // Thanks to Kangax, Christian Sciberras and Stack Overflow for this method. + // + function get_type(thing){ + if(thing===null) return "[object Null]"; // special case + return Object.prototype.toString.call(thing); + } + + $.jsDate = jsDate; + + + /** + * JavaScript printf/sprintf functions. + * + * This code has been adapted from the publicly available sprintf methods + * by Ash Searle. His original header follows: + * + * This code is unrestricted: you are free to use it however you like. + * + * The functions should work as expected, performing left or right alignment, + * truncating strings, outputting numbers with a required precision etc. + * + * For complex cases, these functions follow the Perl implementations of + * (s)printf, allowing arguments to be passed out-of-order, and to set the + * precision or length of the output based on arguments instead of fixed + * numbers. + * + * See http://perldoc.perl.org/functions/sprintf.html for more information. + * + * Implemented: + * - zero and space-padding + * - right and left-alignment, + * - base X prefix (binary, octal and hex) + * - positive number prefix + * - (minimum) width + * - precision / truncation / maximum width + * - out of order arguments + * + * Not implemented (yet): + * - vector flag + * - size (bytes, words, long-words etc.) + * + * Will not implement: + * - %n or %p (no pass-by-reference in JavaScript) + * + * @version 2007.04.27 + * @author Ash Searle + * + * You can see the original work and comments on his blog: + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + */ + + /** + * @Modifications 2009.05.26 + * @author Chris Leonello + * + * Added %p %P specifier + * Acts like %g or %G but will not add more significant digits to the output than present in the input. + * Example: + * Format: '%.3p', Input: 0.012, Output: 0.012 + * Format: '%.3g', Input: 0.012, Output: 0.0120 + * Format: '%.4p', Input: 12.0, Output: 12.0 + * Format: '%.4g', Input: 12.0, Output: 12.00 + * Format: '%.4p', Input: 4.321e-5, Output: 4.321e-5 + * Format: '%.4g', Input: 4.321e-5, Output: 4.3210e-5 + */ + $.jqplot.sprintf = function() { + function pad(str, len, chr, leftJustify) { + var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr); + return leftJustify ? str + padding : padding + str; + + } + + function thousand_separate(value) { + var value_str = new String(value); + for (var i=10; i>0; i--) { + if (value_str == (value_str = value_str.replace(/^(\d+)(\d{3})/, "$1"+$.jqplot.sprintf.thousandsSeparator+"$2"))) break; + } + return value_str; + } + + function justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace) { + var diff = minWidth - value.length; + if (diff > 0) { + var spchar = ' '; + if (htmlSpace) { spchar = ' '; } + if (leftJustify || !zeroPad) { + value = pad(value, minWidth, spchar, leftJustify); + } else { + value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length); + } + } + return value; + } + + function formatBaseX(value, base, prefix, leftJustify, minWidth, precision, zeroPad, htmlSpace) { + // Note: casts negative numbers to positive ones + var number = value >>> 0; + prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || ''; + value = prefix + pad(number.toString(base), precision || 0, '0', false); + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); + } + + function formatString(value, leftJustify, minWidth, precision, zeroPad, htmlSpace) { + if (precision != null) { + value = value.slice(0, precision); + } + return justify(value, '', leftJustify, minWidth, zeroPad, htmlSpace); + } + + var a = arguments, i = 0, format = a[i++]; + + return format.replace($.jqplot.sprintf.regex, function(substring, valueIndex, flags, minWidth, _, precision, type) { + if (substring == '%%') { return '%'; } + + // parse flags + var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, htmlSpace = false, thousandSeparation = false; + for (var j = 0; flags && j < flags.length; j++) switch (flags.charAt(j)) { + case ' ': positivePrefix = ' '; break; + case '+': positivePrefix = '+'; break; + case '-': leftJustify = true; break; + case '0': zeroPad = true; break; + case '#': prefixBaseX = true; break; + case '&': htmlSpace = true; break; + case '\'': thousandSeparation = true; break; + } + + // parameters may be null, undefined, empty-string or real valued + // we want to ignore null, undefined and empty-string values + + if (!minWidth) { + minWidth = 0; + } + else if (minWidth == '*') { + minWidth = +a[i++]; + } + else if (minWidth.charAt(0) == '*') { + minWidth = +a[minWidth.slice(1, -1)]; + } + else { + minWidth = +minWidth; + } + + // Note: undocumented perl feature: + if (minWidth < 0) { + minWidth = -minWidth; + leftJustify = true; + } + + if (!isFinite(minWidth)) { + throw new Error('$.jqplot.sprintf: (minimum-)width must be finite'); + } + + if (!precision) { + precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0); + } + else if (precision == '*') { + precision = +a[i++]; + } + else if (precision.charAt(0) == '*') { + precision = +a[precision.slice(1, -1)]; + } + else { + precision = +precision; + } + + // grab value using valueIndex if required? + var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++]; + + switch (type) { + case 's': { + if (value == null) { + return ''; + } + return formatString(String(value), leftJustify, minWidth, precision, zeroPad, htmlSpace); + } + case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad, htmlSpace); + case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad,htmlSpace); + case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); + case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); + case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace).toUpperCase(); + case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); + case 'i': { + var number = parseInt(+value, 10); + if (isNaN(number)) { + return ''; + } + var prefix = number < 0 ? '-' : positivePrefix; + var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number)); + value = prefix + pad(number_str, precision, '0', false); + //value = prefix + pad(String(Math.abs(number)), precision, '0', false); + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); + } + case 'd': { + var number = Math.round(+value); + if (isNaN(number)) { + return ''; + } + var prefix = number < 0 ? '-' : positivePrefix; + var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number)); + value = prefix + pad(number_str, precision, '0', false); + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); + } + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + { + var number = +value; + if (isNaN(number)) { + return ''; + } + var prefix = number < 0 ? '-' : positivePrefix; + var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())]; + var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2]; + var number_str = Math.abs(number)[method](precision); + number_str = thousandSeparation ? thousand_separate(number_str): number_str; + value = prefix + number_str; + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform](); + } + case 'p': + case 'P': + { + // make sure number is a number + var number = +value; + if (isNaN(number)) { + return ''; + } + var prefix = number < 0 ? '-' : positivePrefix; + + var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/); + var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : parts[0].length; + var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0; + + if (Math.abs(number) < 1) { + if (sd + zeros <= precision) { + value = prefix + Math.abs(number).toPrecision(sd); + } + else { + if (sd <= precision - 1) { + value = prefix + Math.abs(number).toExponential(sd-1); + } + else { + value = prefix + Math.abs(number).toExponential(precision-1); + } + } + } + else { + var prec = (sd <= precision) ? sd : precision; + value = prefix + Math.abs(number).toPrecision(prec); + } + var textTransform = ['toString', 'toUpperCase']['pP'.indexOf(type) % 2]; + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform](); + } + case 'n': return ''; + default: return substring; + } + }); + }; + + $.jqplot.sprintf.thousandsSeparator = ','; + + $.jqplot.sprintf.regex = /%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g; + +})(jQuery); diff --git a/phpgwapi/js/jquery/jqplot/jquery.jqplot.min.css b/phpgwapi/js/jquery/jqplot/jquery.jqplot.min.css new file mode 100644 index 0000000000..d1b2fef03d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/jquery.jqplot.min.css @@ -0,0 +1 @@ +.jqplot-target{position:relative;color:#666;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:1em;}.jqplot-axis{font-size:.75em;}.jqplot-xaxis{margin-top:10px;}.jqplot-x2axis{margin-bottom:10px;}.jqplot-yaxis{margin-right:10px;}.jqplot-y2axis,.jqplot-y3axis,.jqplot-y4axis,.jqplot-y5axis,.jqplot-y6axis,.jqplot-y7axis,.jqplot-y8axis,.jqplot-y9axis{margin-left:10px;margin-right:10px;}.jqplot-axis-tick,.jqplot-xaxis-tick,.jqplot-yaxis-tick,.jqplot-x2axis-tick,.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{position:absolute;}.jqplot-xaxis-tick{top:0;left:15px;vertical-align:top;}.jqplot-x2axis-tick{bottom:0;left:15px;vertical-align:bottom;}.jqplot-yaxis-tick{right:0;top:15px;text-align:right;}.jqplot-yaxis-tick.jqplot-breakTick{right:-20px;margin-right:0;padding:1px 5px 1px 5px;z-index:2;font-size:1.5em;}.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{left:0;top:15px;text-align:left;}.jqplot-meterGauge-tick{font-size:.75em;color:#999;}.jqplot-meterGauge-label{font-size:1em;color:#999;}.jqplot-xaxis-label{margin-top:10px;font-size:11pt;position:absolute;}.jqplot-x2axis-label{margin-bottom:10px;font-size:11pt;position:absolute;}.jqplot-yaxis-label{margin-right:10px;font-size:11pt;position:absolute;}.jqplot-y2axis-label,.jqplot-y3axis-label,.jqplot-y4axis-label,.jqplot-y5axis-label,.jqplot-y6axis-label,.jqplot-y7axis-label,.jqplot-y8axis-label,.jqplot-y9axis-label{font-size:11pt;position:absolute;}table.jqplot-table-legend{margin-top:12px;margin-bottom:12px;margin-left:12px;margin-right:12px;}table.jqplot-table-legend,table.jqplot-cursor-legend{background-color:rgba(255,255,255,0.6);border:1px solid #ccc;position:absolute;font-size:.75em;}td.jqplot-table-legend{vertical-align:middle;}td.jqplot-seriesToggle:hover,td.jqplot-seriesToggle:active{cursor:pointer;}td.jqplot-table-legend>div{border:1px solid #ccc;padding:1px;}div.jqplot-table-legend-swatch{width:0;height:0;border-top-width:5px;border-bottom-width:5px;border-left-width:6px;border-right-width:6px;border-top-style:solid;border-bottom-style:solid;border-left-style:solid;border-right-style:solid;}.jqplot-title{top:0;left:0;padding-bottom:.5em;font-size:1.2em;}table.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em;}.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px;}.jqplot-highlighter-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px;}.jqplot-point-label{font-size:.75em;z-index:2;}td.jqplot-cursor-legend-swatch{vertical-align:middle;text-align:center;}div.jqplot-cursor-legend-swatch{width:1.2em;height:.7em;}.jqplot-error{text-align:center;}.jqplot-error-message{position:relative;top:46%;display:inline-block;}div.jqplot-bubble-label{font-size:.8em;padding-left:2px;padding-right:2px;color:rgb(20%,20%,20%);}div.jqplot-bubble-label.jqplot-bubble-label-highlight{background:rgba(90%,90%,90%,0.7);}div.jqplot-noData-container{text-align:center;background-color:rgba(96%,96%,96%,0.3);} \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/jquery.jqplot.min.js b/phpgwapi/js/jquery/jqplot/jquery.jqplot.min.js new file mode 100644 index 0000000000..56dc881cec --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/jquery.jqplot.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(w){var l;w.fn.emptyForce=function(){for(var O=0,P;(P=w(this)[O])!=null;O++){if(P.nodeType===1){jQuery.cleanData(P.getElementsByTagName("*"))}if(w.jqplot_use_excanvas){P.outerHTML=""}else{while(P.firstChild){P.removeChild(P.firstChild)}}P=null}return w(this)};w.fn.removeChildForce=function(O){while(O.firstChild){this.removeChildForce(O.firstChild);O.removeChild(O.firstChild)}};w.jqplot=function(U,R,P){var Q,O;if(P==null){if(jQuery.isArray(R)){Q=R;O=null}else{if(typeof(R)==="object"){Q=null;O=R}}}else{Q=R;O=P}var T=new C();w("#"+U).removeClass("jqplot-error");if(w.jqplot.config.catchErrors){try{T.init(U,Q,O);T.draw();T.themeEngine.init.call(T);return T}catch(S){var V=w.jqplot.config.errorMessage||S.message;w("#"+U).append('<div class="jqplot-error-message">'+V+"</div>");w("#"+U).addClass("jqplot-error");document.getElementById(U).style.background=w.jqplot.config.errorBackground;document.getElementById(U).style.border=w.jqplot.config.errorBorder;document.getElementById(U).style.fontFamily=w.jqplot.config.errorFontFamily;document.getElementById(U).style.fontSize=w.jqplot.config.errorFontSize;document.getElementById(U).style.fontStyle=w.jqplot.config.errorFontStyle;document.getElementById(U).style.fontWeight=w.jqplot.config.errorFontWeight}}else{T.init(U,Q,O);T.draw();T.themeEngine.init.call(T);return T}};w.jqplot.version="1.0.0b2_r792";w.jqplot.CanvasManager=function(){if(typeof w.jqplot.CanvasManager.canvases=="undefined"){w.jqplot.CanvasManager.canvases=[];w.jqplot.CanvasManager.free=[]}var O=[];this.getCanvas=function(){var R;var Q=true;if(!w.jqplot.use_excanvas){for(var S=0,P=w.jqplot.CanvasManager.canvases.length;S<P;S++){if(w.jqplot.CanvasManager.free[S]===true){Q=false;R=w.jqplot.CanvasManager.canvases[S];w.jqplot.CanvasManager.free[S]=false;O.push(S);break}}}if(Q){R=document.createElement("canvas");O.push(w.jqplot.CanvasManager.canvases.length);w.jqplot.CanvasManager.canvases.push(R);w.jqplot.CanvasManager.free.push(false)}return R};this.initCanvas=function(P){if(w.jqplot.use_excanvas){return window.G_vmlCanvasManager.initElement(P)}return P};this.freeAllCanvases=function(){for(var Q=0,P=O.length;Q<P;Q++){this.freeCanvas(O[Q])}O=[]};this.freeCanvas=function(P){if(w.jqplot.use_excanvas){window.G_vmlCanvasManager.uninitElement(w.jqplot.CanvasManager.canvases[P]);w.jqplot.CanvasManager.canvases[P]=null}else{var Q=w.jqplot.CanvasManager.canvases[P];Q.getContext("2d").clearRect(0,0,Q.width,Q.height);w(Q).unbind().removeAttr("class").removeAttr("style");w(Q).css({left:"",top:"",position:""});Q.width=0;Q.height=0;w.jqplot.CanvasManager.free[P]=true}}};w.jqplot.log=function(){if(window.console){console.log.apply(console,arguments)}};w.jqplot.config={enablePlugins:false,defaultHeight:300,defaultWidth:400,UTCAdjust:false,timezoneOffset:new Date(new Date().getTimezoneOffset()*60000),errorMessage:"",errorBackground:"",errorBorder:"",errorFontFamily:"",errorFontSize:"",errorFontStyle:"",errorFontWeight:"",catchErrors:false,defaultTickFormatString:"%.1f",defaultColors:["#4bb2c5","#EAA228","#c5b47f","#579575","#839557","#958c12","#953579","#4b5de4","#d8b83f","#ff5800","#0085cc","#c747a3","#cddf54","#FBD178","#26B4E3","#bd70c7"],defaultNegativeColors:["#498991","#C08840","#9F9274","#546D61","#646C4A","#6F6621","#6E3F5F","#4F64B0","#A89050","#C45923","#187399","#945381","#959E5C","#C7AF7B","#478396","#907294"]};w.jqplot.arrayMax=function(O){return Math.max.apply(Math,O)};w.jqplot.arrayMin=function(O){return Math.min.apply(Math,O)};w.jqplot.enablePlugins=w.jqplot.config.enablePlugins;w.jqplot.support_canvas=function(){if(typeof w.jqplot.support_canvas.result=="undefined"){w.jqplot.support_canvas.result=!!document.createElement("canvas").getContext}return w.jqplot.support_canvas.result};w.jqplot.support_canvas_text=function(){if(typeof w.jqplot.support_canvas_text.result=="undefined"){w.jqplot.support_canvas_text.result=!!(document.createElement("canvas").getContext&&typeof document.createElement("canvas").getContext("2d").fillText=="function")}return w.jqplot.support_canvas_text.result};w.jqplot.use_excanvas=(w.browser.msie&&!w.jqplot.support_canvas())?true:false;w.jqplot.preInitHooks=[];w.jqplot.postInitHooks=[];w.jqplot.preParseOptionsHooks=[];w.jqplot.postParseOptionsHooks=[];w.jqplot.preDrawHooks=[];w.jqplot.postDrawHooks=[];w.jqplot.preDrawSeriesHooks=[];w.jqplot.postDrawSeriesHooks=[];w.jqplot.preDrawLegendHooks=[];w.jqplot.addLegendRowHooks=[];w.jqplot.preSeriesInitHooks=[];w.jqplot.postSeriesInitHooks=[];w.jqplot.preParseSeriesOptionsHooks=[];w.jqplot.postParseSeriesOptionsHooks=[];w.jqplot.eventListenerHooks=[];w.jqplot.preDrawSeriesShadowHooks=[];w.jqplot.postDrawSeriesShadowHooks=[];w.jqplot.ElemContainer=function(){this._elem;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null}};w.jqplot.ElemContainer.prototype.createElement=function(R,T,P,Q,U){this._offsets=T;var O=P||"jqplot";var S=document.createElement(R);this._elem=w(S);this._elem.addClass(O);this._elem.css(Q);this._elem.attr(U);S=null;return this._elem};w.jqplot.ElemContainer.prototype.getWidth=function(){if(this._elem){return this._elem.outerWidth(true)}else{return null}};w.jqplot.ElemContainer.prototype.getHeight=function(){if(this._elem){return this._elem.outerHeight(true)}else{return null}};w.jqplot.ElemContainer.prototype.getPosition=function(){if(this._elem){return this._elem.position()}else{return{top:null,left:null,bottom:null,right:null}}};w.jqplot.ElemContainer.prototype.getTop=function(){return this.getPosition().top};w.jqplot.ElemContainer.prototype.getLeft=function(){return this.getPosition().left};w.jqplot.ElemContainer.prototype.getBottom=function(){return this._elem.css("bottom")};w.jqplot.ElemContainer.prototype.getRight=function(){return this._elem.css("right")};function m(O){w.jqplot.ElemContainer.call(this);this.name=O;this._series=[];this.show=false;this.tickRenderer=w.jqplot.AxisTickRenderer;this.tickOptions={};this.labelRenderer=w.jqplot.AxisLabelRenderer;this.labelOptions={};this.label=null;this.showLabel=true;this.min=null;this.max=null;this.autoscale=false;this.pad=1.2;this.padMax=null;this.padMin=null;this.ticks=[];this.numberTicks;this.tickInterval;this.renderer=w.jqplot.LinearAxisRenderer;this.rendererOptions={};this.showTicks=true;this.showTickMarks=true;this.showMinorTicks=true;this.useSeriesColor=false;this.borderWidth=null;this.borderColor=null;this._dataBounds={min:null,max:null};this._intervalStats=[];this._offsets={min:null,max:null};this._ticks=[];this._label=null;this.syncTicks=null;this.tickSpacing=75;this._min=null;this._max=null;this._tickInterval=null;this._numberTicks=null;this.__ticks=null;this._options={}}m.prototype=new w.jqplot.ElemContainer();m.prototype.constructor=m;m.prototype.init=function(){this.renderer=new this.renderer();this.tickOptions.axis=this.name;if(this.tickOptions.showMark==null){this.tickOptions.showMark=this.showTicks}if(this.tickOptions.showMark==null){this.tickOptions.showMark=this.showTickMarks}if(this.tickOptions.showLabel==null){this.tickOptions.showLabel=this.showTicks}if(this.label==null||this.label==""){this.showLabel=false}else{this.labelOptions.label=this.label}if(this.showLabel==false){this.labelOptions.show=false}if(this.pad==0){this.pad=1}if(this.padMax==0){this.padMax=1}if(this.padMin==0){this.padMin=1}if(this.padMax==null){this.padMax=(this.pad-1)/2+1}if(this.padMin==null){this.padMin=(this.pad-1)/2+1}this.pad=this.padMax+this.padMin-1;if(this.min!=null||this.max!=null){this.autoscale=false}if(this.syncTicks==null&&this.name.indexOf("y")>-1){this.syncTicks=true}else{if(this.syncTicks==null){this.syncTicks=false}}this.renderer.init.call(this,this.rendererOptions)};m.prototype.draw=function(O,P){if(this.__ticks){this.__ticks=null}return this.renderer.draw.call(this,O,P)};m.prototype.set=function(){this.renderer.set.call(this)};m.prototype.pack=function(P,O){if(this.show){this.renderer.pack.call(this,P,O)}if(this._min==null){this._min=this.min;this._max=this.max;this._tickInterval=this.tickInterval;this._numberTicks=this.numberTicks;this.__ticks=this._ticks}};m.prototype.reset=function(){this.renderer.reset.call(this)};m.prototype.resetScale=function(O){w.extend(true,this,{min:null,max:null,numberTicks:null,tickInterval:null,_ticks:[],ticks:[]},O);this.resetDataBounds()};m.prototype.resetDataBounds=function(){var O=this._dataBounds;O.min=null;O.max=null;var R=(this.show)?true:false;for(var Q=0;Q<this._series.length;Q++){var S=this._series[Q];var V=S._plotData;var T=1,U=1;if(S._type!=null&&S._type=="ohlc"){T=3;U=2}for(var P=0;P<V.length;P++){if(this.name=="xaxis"||this.name=="x2axis"){if((V[P][0]!=null&&V[P][0]<O.min)||O.min==null){O.min=V[P][0]}if((V[P][0]!=null&&V[P][0]>O.max)||O.max==null){O.max=V[P][0]}}else{if((V[P][T]!=null&&V[P][T]<O.min)||O.min==null){O.min=V[P][T]}if((V[P][U]!=null&&V[P][U]>O.max)||O.max==null){O.max=V[P][U]}}}if(R&&S.renderer.constructor!==w.jqplot.BarRenderer){R=false}else{if(R&&this._options.hasOwnProperty("forceTickAt0")&&this._options.forceTickAt0==false){R=false}else{if(R&&S.renderer.constructor===w.jqplot.BarRenderer){if(S.barDirection=="vertical"&&this.name!="xaxis"&&this.name!="x2axis"){if(this._options.pad!=null||this._options.padMin!=null){R=false}}else{if(S.barDirection=="horizontal"&&(this.name=="xaxis"||this.name=="x2axis")){if(this._options.pad!=null||this._options.padMin!=null){R=false}}}}}}}if(R&&this.renderer.constructor===w.jqplot.LinearAxisRenderer&&O.min>=0){this.padMin=1;this.forceTickAt0=true}};function h(O){w.jqplot.ElemContainer.call(this);this.show=false;this.location="ne";this.labels=[];this.showLabels=true;this.showSwatches=true;this.placement="insideGrid";this.xoffset=0;this.yoffset=0;this.border;this.background;this.textColor;this.fontFamily;this.fontSize;this.rowSpacing="0.5em";this.renderer=w.jqplot.TableLegendRenderer;this.rendererOptions={};this.preDraw=false;this.marginTop=null;this.marginRight=null;this.marginBottom=null;this.marginLeft=null;this.escapeHtml=false;this._series=[];w.extend(true,this,O)}h.prototype=new w.jqplot.ElemContainer();h.prototype.constructor=h;h.prototype.setOptions=function(O){w.extend(true,this,O);if(this.placement=="inside"){this.placement="insideGrid"}if(this.xoffset>0){if(this.placement=="insideGrid"){switch(this.location){case"nw":case"w":case"sw":if(this.marginLeft==null){this.marginLeft=this.xoffset+"px"}this.marginRight="0px";break;case"ne":case"e":case"se":default:if(this.marginRight==null){this.marginRight=this.xoffset+"px"}this.marginLeft="0px";break}}else{if(this.placement=="outside"){switch(this.location){case"nw":case"w":case"sw":if(this.marginRight==null){this.marginRight=this.xoffset+"px"}this.marginLeft="0px";break;case"ne":case"e":case"se":default:if(this.marginLeft==null){this.marginLeft=this.xoffset+"px"}this.marginRight="0px";break}}}this.xoffset=0}if(this.yoffset>0){if(this.placement=="outside"){switch(this.location){case"sw":case"s":case"se":if(this.marginTop==null){this.marginTop=this.yoffset+"px"}this.marginBottom="0px";break;case"ne":case"n":case"nw":default:if(this.marginBottom==null){this.marginBottom=this.yoffset+"px"}this.marginTop="0px";break}}else{if(this.placement=="insideGrid"){switch(this.location){case"sw":case"s":case"se":if(this.marginBottom==null){this.marginBottom=this.yoffset+"px"}this.marginTop="0px";break;case"ne":case"n":case"nw":default:if(this.marginTop==null){this.marginTop=this.yoffset+"px"}this.marginBottom="0px";break}}}this.yoffset=0}};h.prototype.init=function(){this.renderer=new this.renderer();this.renderer.init.call(this,this.rendererOptions)};h.prototype.draw=function(P){for(var O=0;O<w.jqplot.preDrawLegendHooks.length;O++){w.jqplot.preDrawLegendHooks[O].call(this,P)}return this.renderer.draw.call(this,P)};h.prototype.pack=function(O){this.renderer.pack.call(this,O)};function n(O){w.jqplot.ElemContainer.call(this);this.text=O;this.show=true;this.fontFamily;this.fontSize;this.textAlign;this.textColor;this.renderer=w.jqplot.DivTitleRenderer;this.rendererOptions={}}n.prototype=new w.jqplot.ElemContainer();n.prototype.constructor=n;n.prototype.init=function(){this.renderer=new this.renderer();this.renderer.init.call(this,this.rendererOptions)};n.prototype.draw=function(O){return this.renderer.draw.call(this,O)};n.prototype.pack=function(){this.renderer.pack.call(this)};function D(){w.jqplot.ElemContainer.call(this);this.show=true;this.xaxis="xaxis";this._xaxis;this.yaxis="yaxis";this._yaxis;this.gridBorderWidth=2;this.renderer=w.jqplot.LineRenderer;this.rendererOptions={};this.data=[];this.gridData=[];this.label="";this.showLabel=true;this.color;this.lineWidth=2.5;this.lineJoin="round";this.lineCap="round";this.shadow=true;this.shadowAngle=45;this.shadowOffset=1.25;this.shadowDepth=3;this.shadowAlpha="0.1";this.breakOnNull=false;this.markerRenderer=w.jqplot.MarkerRenderer;this.markerOptions={};this.showLine=true;this.showMarker=true;this.index;this.fill=false;this.fillColor;this.fillAlpha;this.fillAndStroke=false;this.disableStack=false;this._stack=false;this.neighborThreshold=4;this.fillToZero=false;this.fillToValue=0;this.fillAxis="y";this.useNegativeColors=true;this._stackData=[];this._plotData=[];this._plotValues={x:[],y:[]};this._intervals={x:{},y:{}};this._prevPlotData=[];this._prevGridData=[];this._stackAxis="y";this._primaryAxis="_xaxis";this.canvas=new w.jqplot.GenericCanvas();this.shadowCanvas=new w.jqplot.GenericCanvas();this.plugins={};this._sumy=0;this._sumx=0;this._type=""}D.prototype=new w.jqplot.ElemContainer();D.prototype.constructor=D;D.prototype.init=function(Q,U,S){this.index=Q;this.gridBorderWidth=U;var T=this.data;var P=[],R;for(R=0;R<T.length;R++){if(!this.breakOnNull){if(T[R]==null||T[R][0]==null||T[R][1]==null){continue}else{P.push(T[R])}}else{P.push(T[R])}}this.data=P;if(!this.fillColor){this.fillColor=this.color}if(this.fillAlpha){var O=w.jqplot.normalize2rgb(this.fillColor);var O=w.jqplot.getColorComponents(O);this.fillColor="rgba("+O[0]+","+O[1]+","+O[2]+","+this.fillAlpha+")"}this.renderer=new this.renderer();this.renderer.init.call(this,this.rendererOptions,S);this.markerRenderer=new this.markerRenderer();if(!this.markerOptions.color){this.markerOptions.color=this.color}if(this.markerOptions.show==null){this.markerOptions.show=this.showMarker}this.showMarker=this.markerOptions.show;this.markerRenderer.init(this.markerOptions)};D.prototype.draw=function(U,R,T){var P=(R==l)?{}:R;U=(U==l)?this.canvas._ctx:U;var O,S,Q;for(O=0;O<w.jqplot.preDrawSeriesHooks.length;O++){w.jqplot.preDrawSeriesHooks[O].call(this,U,P)}if(this.show){this.renderer.setGridData.call(this,T);if(!P.preventJqPlotSeriesDrawTrigger){w(U.canvas).trigger("jqplotSeriesDraw",[this.data,this.gridData])}S=[];if(P.data){S=P.data}else{if(!this._stack){S=this.data}else{S=this._plotData}}Q=P.gridData||this.renderer.makeGridData.call(this,S,T);this.renderer.draw.call(this,U,Q,P,T)}for(O=0;O<w.jqplot.postDrawSeriesHooks.length;O++){w.jqplot.postDrawSeriesHooks[O].call(this,U,P)}U=R=T=O=S=Q=null};D.prototype.drawShadow=function(U,R,T){var P=(R==l)?{}:R;U=(U==l)?this.shadowCanvas._ctx:U;var O,S,Q;for(O=0;O<w.jqplot.preDrawSeriesShadowHooks.length;O++){w.jqplot.preDrawSeriesShadowHooks[O].call(this,U,P)}if(this.shadow){this.renderer.setGridData.call(this,T);S=[];if(P.data){S=P.data}else{if(!this._stack){S=this.data}else{S=this._plotData}}Q=P.gridData||this.renderer.makeGridData.call(this,S,T);this.renderer.drawShadow.call(this,U,Q,P)}for(O=0;O<w.jqplot.postDrawSeriesShadowHooks.length;O++){w.jqplot.postDrawSeriesShadowHooks[O].call(this,U,P)}U=R=T=O=S=Q=null};D.prototype.toggleDisplay=function(P){var O,Q;if(P.data.series){O=P.data.series}else{O=this}if(P.data.speed){Q=P.data.speed}if(Q){if(O.canvas._elem.is(":hidden")){if(O.shadowCanvas._elem){O.shadowCanvas._elem.fadeIn(Q)}O.canvas._elem.fadeIn(Q);O.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+O.index).fadeIn(Q)}else{if(O.shadowCanvas._elem){O.shadowCanvas._elem.fadeOut(Q)}O.canvas._elem.fadeOut(Q);O.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+O.index).fadeOut(Q)}}else{if(O.canvas._elem.is(":hidden")){if(O.shadowCanvas._elem){O.shadowCanvas._elem.show()}O.canvas._elem.show();O.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+O.index).show()}else{if(O.shadowCanvas._elem){O.shadowCanvas._elem.hide()}O.canvas._elem.hide();O.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+O.index).hide()}}};function x(){w.jqplot.ElemContainer.call(this);this.drawGridlines=true;this.gridLineColor="#cccccc";this.gridLineWidth=1;this.background="#fffdf6";this.borderColor="#999999";this.borderWidth=2;this.drawBorder=true;this.shadow=true;this.shadowAngle=45;this.shadowOffset=1.5;this.shadowWidth=3;this.shadowDepth=3;this.shadowColor=null;this.shadowAlpha="0.07";this._left;this._top;this._right;this._bottom;this._width;this._height;this._axes=[];this.renderer=w.jqplot.CanvasGridRenderer;this.rendererOptions={};this._offsets={top:null,bottom:null,left:null,right:null}}x.prototype=new w.jqplot.ElemContainer();x.prototype.constructor=x;x.prototype.init=function(){this.renderer=new this.renderer();this.renderer.init.call(this,this.rendererOptions)};x.prototype.createElement=function(O,P){this._offsets=O;return this.renderer.createElement.call(this,P)};x.prototype.draw=function(){this.renderer.draw.call(this)};w.jqplot.GenericCanvas=function(){w.jqplot.ElemContainer.call(this);this._ctx};w.jqplot.GenericCanvas.prototype=new w.jqplot.ElemContainer();w.jqplot.GenericCanvas.prototype.constructor=w.jqplot.GenericCanvas;w.jqplot.GenericCanvas.prototype.createElement=function(S,Q,P,T){this._offsets=S;var O="jqplot";if(Q!=l){O=Q}var R;R=T.canvasManager.getCanvas();if(P!=null){this._plotDimensions=P}R.width=this._plotDimensions.width-this._offsets.left-this._offsets.right;R.height=this._plotDimensions.height-this._offsets.top-this._offsets.bottom;this._elem=w(R);this._elem.css({position:"absolute",left:this._offsets.left,top:this._offsets.top});this._elem.addClass(O);R=T.canvasManager.initCanvas(R);R=null;return this._elem};w.jqplot.GenericCanvas.prototype.setContext=function(){this._ctx=this._elem.get(0).getContext("2d");return this._ctx};w.jqplot.GenericCanvas.prototype.resetCanvas=function(){if(this._elem){if(w.jqplot.use_excanvas){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce()}this._ctx=null};w.jqplot.HooksManager=function(){this.hooks=[]};w.jqplot.HooksManager.prototype.addOnce=function(P){var Q=false,O;for(O=0;O<this.hooks.length;O++){if(this.hooks[O][0]==P){Q=true}}if(!Q){this.hooks.push(P)}};w.jqplot.HooksManager.prototype.add=function(O){this.hooks.push(O)};w.jqplot.EventListenerManager=function(){this.hooks=[]};w.jqplot.EventListenerManager.prototype.addOnce=function(R,Q){var S=false,P,O;for(O=0;O<this.hooks.length;O++){P=this.hooks[O];if(P[0]==R&&P[1]==Q){S=true}}if(!S){this.hooks.push([R,Q])}};w.jqplot.EventListenerManager.prototype.add=function(P,O){this.hooks.push([P,O])};function C(){this.data=[];this.dataRenderer;this.dataRendererOptions;this.noDataIndicator={show:false,indicator:"Loading Data...",axes:{xaxis:{min:0,max:10,tickInterval:2,show:true},yaxis:{min:0,max:12,tickInterval:3,show:true}}};this.targetId=null;this.target=null;this.defaults={axesDefaults:{},axes:{xaxis:{},yaxis:{},x2axis:{},y2axis:{},y3axis:{},y4axis:{},y5axis:{},y6axis:{},y7axis:{},y8axis:{},y9axis:{}},seriesDefaults:{},series:[]};this.series=[];this.axes={xaxis:new m("xaxis"),yaxis:new m("yaxis"),x2axis:new m("x2axis"),y2axis:new m("y2axis"),y3axis:new m("y3axis"),y4axis:new m("y4axis"),y5axis:new m("y5axis"),y6axis:new m("y6axis"),y7axis:new m("y7axis"),y8axis:new m("y8axis"),y9axis:new m("y9axis")};this.grid=new x();this.legend=new h();this.baseCanvas=new w.jqplot.GenericCanvas();this.seriesStack=[];this.previousSeriesStack=[];this.eventCanvas=new w.jqplot.GenericCanvas();this._width=null;this._height=null;this._plotDimensions={height:null,width:null};this._gridPadding={top:null,right:null,bottom:null,left:null};this._defaultGridPadding={top:10,right:10,bottom:23,left:10};this.syncXTicks=true;this.syncYTicks=true;this.seriesColors=w.jqplot.config.defaultColors;this.negativeSeriesColors=w.jqplot.config.defaultNegativeColors;this.sortData=true;var Q=0;this.textColor;this.fontFamily;this.fontSize;this.title=new n();this.options={};this.stackSeries=false;this.defaultAxisStart=1;this._stackData=[];this._plotData=[];this.plugins={};this._drawCount=0;this.drawIfHidden=false;this.captureRightClick=false;this.themeEngine=new w.jqplot.ThemeEngine();this._sumy=0;this._sumx=0;this.preInitHooks=new w.jqplot.HooksManager();this.postInitHooks=new w.jqplot.HooksManager();this.preParseOptionsHooks=new w.jqplot.HooksManager();this.postParseOptionsHooks=new w.jqplot.HooksManager();this.preDrawHooks=new w.jqplot.HooksManager();this.postDrawHooks=new w.jqplot.HooksManager();this.preDrawSeriesHooks=new w.jqplot.HooksManager();this.postDrawSeriesHooks=new w.jqplot.HooksManager();this.preDrawLegendHooks=new w.jqplot.HooksManager();this.addLegendRowHooks=new w.jqplot.HooksManager();this.preSeriesInitHooks=new w.jqplot.HooksManager();this.postSeriesInitHooks=new w.jqplot.HooksManager();this.preParseSeriesOptionsHooks=new w.jqplot.HooksManager();this.postParseSeriesOptionsHooks=new w.jqplot.HooksManager();this.eventListenerHooks=new w.jqplot.EventListenerManager();this.preDrawSeriesShadowHooks=new w.jqplot.HooksManager();this.postDrawSeriesShadowHooks=new w.jqplot.HooksManager();this.colorGenerator=w.jqplot.ColorGenerator;this.canvasManager=new w.jqplot.CanvasManager();this.init=function(Z,W,ab){ab=ab||{};for(var X=0;X<w.jqplot.preInitHooks.length;X++){w.jqplot.preInitHooks[X].call(this,Z,W,ab)}for(var X=0;X<this.preInitHooks.hooks.length;X++){this.preInitHooks.hooks[X].call(this,Z,W,ab)}this.targetId="#"+Z;this.target=w("#"+Z);this.target.removeClass("jqplot-error");if(!this.target.get(0)){throw"No plot target specified"}if(this.target.css("position")=="static"){this.target.css("position","relative")}if(!this.target.hasClass("jqplot-target")){this.target.addClass("jqplot-target")}if(!this.target.height()){var Y;if(ab&&ab.height){Y=parseInt(ab.height,10)}else{if(this.target.attr("data-height")){Y=parseInt(this.target.attr("data-height"),10)}else{Y=parseInt(w.jqplot.config.defaultHeight,10)}}this._height=Y;this.target.css("height",Y+"px")}else{this._height=Y=this.target.height()}if(!this.target.width()){var aa;if(ab&&ab.width){aa=parseInt(ab.width,10)}else{if(this.target.attr("data-width")){aa=parseInt(this.target.attr("data-width"),10)}else{aa=parseInt(w.jqplot.config.defaultWidth,10)}}this._width=aa;this.target.css("width",aa+"px")}else{this._width=aa=this.target.width()}this._plotDimensions.height=this._height;this._plotDimensions.width=this._width;this.grid._plotDimensions=this._plotDimensions;this.title._plotDimensions=this._plotDimensions;this.baseCanvas._plotDimensions=this._plotDimensions;this.eventCanvas._plotDimensions=this._plotDimensions;this.legend._plotDimensions=this._plotDimensions;if(this._height<=0||this._width<=0||!this._height||!this._width){throw"Canvas dimension not set"}if(ab.dataRenderer&&jQuery.isFunction(ab.dataRenderer)){if(ab.dataRendererOptions){this.dataRendererOptions=ab.dataRendererOptions}this.dataRenderer=ab.dataRenderer;W=this.dataRenderer(W,this,this.dataRendererOptions)}if(ab.noDataIndicator&&jQuery.isPlainObject(ab.noDataIndicator)){w.extend(true,this.noDataIndicator,ab.noDataIndicator)}if(W==null||jQuery.isArray(W)==false||W.length==0||jQuery.isArray(W[0])==false||W[0].length==0){if(this.noDataIndicator.show==false){throw {name:"DataError",message:"No data to plot."}}else{for(var S in this.noDataIndicator.axes){for(var U in this.noDataIndicator.axes[S]){this.axes[S][U]=this.noDataIndicator.axes[S][U]}}this.postDrawHooks.add(function(){var ah=this.eventCanvas.getHeight();var ae=this.eventCanvas.getWidth();var ad=w('<div class="jqplot-noData-container" style="position:absolute;"></div>');this.target.append(ad);ad.height(ah);ad.width(ae);ad.css("top",this.eventCanvas._offsets.top);ad.css("left",this.eventCanvas._offsets.left);var ag=w('<div class="jqplot-noData-contents" style="text-align:center; position:relative; margin-left:auto; margin-right:auto;"></div>');ad.append(ag);ag.html(this.noDataIndicator.indicator);var af=ag.height();var ac=ag.width();ag.height(af);ag.width(ac);ag.css("top",(ah-af)/2+"px")})}}this.data=W;this.parseOptions(ab);if(this.textColor){this.target.css("color",this.textColor)}if(this.fontFamily){this.target.css("font-family",this.fontFamily)}if(this.fontSize){this.target.css("font-size",this.fontSize)}this.title.init();this.legend.init();this._sumy=0;this._sumx=0;for(var X=0;X<this.series.length;X++){this.seriesStack.push(X);this.previousSeriesStack.push(X);this.series[X].shadowCanvas._plotDimensions=this._plotDimensions;this.series[X].canvas._plotDimensions=this._plotDimensions;for(var V=0;V<w.jqplot.preSeriesInitHooks.length;V++){w.jqplot.preSeriesInitHooks[V].call(this.series[X],Z,W,this.options.seriesDefaults,this.options.series[X],this)}for(var V=0;V<this.preSeriesInitHooks.hooks.length;V++){this.preSeriesInitHooks.hooks[V].call(this.series[X],Z,W,this.options.seriesDefaults,this.options.series[X],this)}this.populatePlotData(this.series[X],X);this.series[X]._plotDimensions=this._plotDimensions;this.series[X].init(X,this.grid.borderWidth,this);for(var V=0;V<w.jqplot.postSeriesInitHooks.length;V++){w.jqplot.postSeriesInitHooks[V].call(this.series[X],Z,W,this.options.seriesDefaults,this.options.series[X],this)}for(var V=0;V<this.postSeriesInitHooks.hooks.length;V++){this.postSeriesInitHooks.hooks[V].call(this.series[X],Z,W,this.options.seriesDefaults,this.options.series[X],this)}this._sumy+=this.series[X]._sumy;this._sumx+=this.series[X]._sumx}for(var T in this.axes){this.axes[T]._plotDimensions=this._plotDimensions;this.axes[T].init()}if(this.sortData){O(this.series)}this.grid.init();this.grid._axes=this.axes;this.legend._series=this.series;for(var X=0;X<w.jqplot.postInitHooks.length;X++){w.jqplot.postInitHooks[X].call(this,Z,W,ab)}for(var X=0;X<this.postInitHooks.hooks.length;X++){this.postInitHooks.hooks[X].call(this,Z,W,ab)}};this.resetAxesScale=function(X,T){var V=T||{};var W=X||this.axes;if(W===true){W=this.axes}if(jQuery.isArray(W)){for(var U=0;U<W.length;U++){this.axes[W[U]].resetScale(V[W[U]])}}else{if(typeof(W)==="object"){for(var S in W){this.axes[S].resetScale(V[S])}}}};this.reInitialize=function(){this._height=this.target.height();this._width=this.target.width();if(this._height<=0||this._width<=0||!this._height||!this._width){throw"Target dimension not set"}this._plotDimensions.height=this._height;this._plotDimensions.width=this._width;this.grid._plotDimensions=this._plotDimensions;this.title._plotDimensions=this._plotDimensions;this.baseCanvas._plotDimensions=this._plotDimensions;this.eventCanvas._plotDimensions=this._plotDimensions;this.legend._plotDimensions=this._plotDimensions;for(var W in this.axes){this.axes[W]._plotWidth=this._width;this.axes[W]._plotHeight=this._height}this.title._plotWidth=this._width;if(this.textColor){this.target.css("color",this.textColor)}if(this.fontFamily){this.target.css("font-family",this.fontFamily)}if(this.fontSize){this.target.css("font-size",this.fontSize)}this._sumy=0;this._sumx=0;for(var U=0;U<this.series.length;U++){this.populatePlotData(this.series[U],U);this.series[U]._plotDimensions=this._plotDimensions;this.series[U].canvas._plotDimensions=this._plotDimensions;this._sumy+=this.series[U]._sumy;this._sumx+=this.series[U]._sumx}for(var S in this.axes){var T=this.axes[S]._ticks;for(var U=0;U<T.length;U++){var V=T[U]._elem;if(V){if(w.jqplot.use_excanvas){window.G_vmlCanvasManager.uninitElement(V.get(0))}V.emptyForce();V=null;T._elem=null}}T=null;this.axes[S]._plotDimensions=this._plotDimensions;this.axes[S]._ticks=[];this.axes[S].renderer.init.call(this.axes[S],{})}if(this.sortData){O(this.series)}this.grid._axes=this.axes;this.legend._series=this.series};function O(W){var aa,ab,ac,S,Z;for(var X=0;X<W.length;X++){var T;var Y=[W[X].data,W[X]._stackData,W[X]._plotData,W[X]._prevPlotData];for(var U=0;U<4;U++){T=true;aa=Y[U];if(W[X]._stackAxis=="x"){for(var V=0;V<aa.length;V++){if(typeof(aa[V][1])!="number"){T=false;break}}if(T){aa.sort(function(ae,ad){return ae[1]-ad[1]})}}else{for(var V=0;V<aa.length;V++){if(typeof(aa[V][0])!="number"){T=false;break}}if(T){aa.sort(function(ae,ad){return ae[0]-ad[0]})}}}}}this.populatePlotData=function(W,X){this._plotData=[];this._stackData=[];W._stackData=[];W._plotData=[];var aa={x:[],y:[]};if(this.stackSeries&&!W.disableStack){W._stack=true;var Y=W._stackAxis=="x"?0:1;var Z=Y?0:1;var ab=w.extend(true,[],W.data);var ac=w.extend(true,[],W.data);for(var U=0;U<X;U++){var S=this.series[U].data;for(var T=0;T<S.length;T++){ab[T][0]+=S[T][0];ab[T][1]+=S[T][1];ac[T][Y]+=S[T][Y]}}for(var V=0;V<ac.length;V++){aa.x.push(ac[V][0]);aa.y.push(ac[V][1])}this._plotData.push(ac);this._stackData.push(ab);W._stackData=ab;W._plotData=ac;W._plotValues=aa}else{for(var V=0;V<W.data.length;V++){aa.x.push(W.data[V][0]);aa.y.push(W.data[V][1])}this._stackData.push(W.data);this.series[X]._stackData=W.data;this._plotData.push(W.data);W._plotData=W.data;W._plotValues=aa}if(X>0){W._prevPlotData=this.series[X-1]._plotData}W._sumy=0;W._sumx=0;for(V=W.data.length-1;V>-1;V--){W._sumy+=W.data[V][1];W._sumx+=W.data[V][0]}};this.getNextSeriesColor=(function(T){var S=0;var U=T.seriesColors;return function(){if(S<U.length){return U[S++]}else{S=0;return U[S++]}}})(this);this.parseOptions=function(aa){for(var X=0;X<this.preParseOptionsHooks.hooks.length;X++){this.preParseOptionsHooks.hooks[X].call(this,aa)}for(var X=0;X<w.jqplot.preParseOptionsHooks.length;X++){w.jqplot.preParseOptionsHooks[X].call(this,aa)}this.options=w.extend(true,{},this.defaults,aa);this.stackSeries=this.options.stackSeries;if(this.options.seriesColors){this.seriesColors=this.options.seriesColors}if(this.options.negativeSeriesColors){this.negativeSeriesColors=this.options.negativeSeriesColors}if(this.options.captureRightClick){this.captureRightClick=this.options.captureRightClick}this.defaultAxisStart=(aa&&aa.defaultAxisStart!=null)?aa.defaultAxisStart:this.defaultAxisStart;var S=new this.colorGenerator(this.seriesColors);w.extend(true,this._gridPadding,this.options.gridPadding);this.sortData=(this.options.sortData!=null)?this.options.sortData:this.sortData;for(var T in this.axes){var V=this.axes[T];V._options=w.extend(true,{},this.options.axesDefaults,this.options.axes[T]);w.extend(true,V,this.options.axesDefaults,this.options.axes[T]);V._plotWidth=this._width;V._plotHeight=this._height}var Y=function(ae,ac,af){var ab=[];var ad;ac=ac||"vertical";if(!jQuery.isArray(ae[0])){for(ad=0;ad<ae.length;ad++){if(ac=="vertical"){ab.push([af+ad,ae[ad]])}else{ab.push([ae[ad],af+ad])}}}else{w.extend(true,ab,ae)}return ab};for(var X=0;X<this.data.length;X++){var Z=new D();for(var W=0;W<w.jqplot.preParseSeriesOptionsHooks.length;W++){w.jqplot.preParseSeriesOptionsHooks[W].call(Z,this.options.seriesDefaults,this.options.series[X])}for(var W=0;W<this.preParseSeriesOptionsHooks.hooks.length;W++){this.preParseSeriesOptionsHooks.hooks[W].call(Z,this.options.seriesDefaults,this.options.series[X])}w.extend(true,Z,{seriesColors:this.seriesColors,negativeSeriesColors:this.negativeSeriesColors},this.options.seriesDefaults,this.options.series[X]);var U="vertical";if(Z.renderer===w.jqplot.BarRenderer&&Z.rendererOptions&&Z.rendererOptions.barDirection=="horizontal"){U="horizontal"}Z.data=Y(this.data[X],U,this.defaultAxisStart);switch(Z.xaxis){case"xaxis":Z._xaxis=this.axes.xaxis;break;case"x2axis":Z._xaxis=this.axes.x2axis;break;default:break}Z._yaxis=this.axes[Z.yaxis];Z._xaxis._series.push(Z);Z._yaxis._series.push(Z);if(Z.show){Z._xaxis.show=true;Z._yaxis.show=true}if(!Z.color&&Z.show!=false){Z.color=S.next()}if(!Z.label){Z.label="Series "+(X+1).toString()}this.series.push(Z);for(var W=0;W<w.jqplot.postParseSeriesOptionsHooks.length;W++){w.jqplot.postParseSeriesOptionsHooks[W].call(this.series[X],this.options.seriesDefaults,this.options.series[X])}for(var W=0;W<this.postParseSeriesOptionsHooks.hooks.length;W++){this.postParseSeriesOptionsHooks.hooks[W].call(this.series[X],this.options.seriesDefaults,this.options.series[X])}}w.extend(true,this.grid,this.options.grid);for(var T in this.axes){var V=this.axes[T];if(V.borderWidth==null){V.borderWidth=this.grid.borderWidth}if(V.borderColor==null){if(T!="xaxis"&&T!="x2axis"&&V.useSeriesColor===true&&V.show){V.borderColor=V._series[0].color}else{V.borderColor=this.grid.borderColor}}}if(typeof this.options.title=="string"){this.title.text=this.options.title}else{if(typeof this.options.title=="object"){w.extend(true,this.title,this.options.title)}}this.title._plotWidth=this._width;this.legend.setOptions(this.options.legend);for(var X=0;X<w.jqplot.postParseOptionsHooks.length;X++){w.jqplot.postParseOptionsHooks[X].call(this,aa)}for(var X=0;X<this.postParseOptionsHooks.hooks.length;X++){this.postParseOptionsHooks.hooks[X].call(this,aa)}};this.destroy=function(){this.canvasManager.freeAllCanvases();this.target[0].innerHTML=""};this.replot=function(T){var U=T||{};var S=U.clear||true;var V=U.resetAxes||false;this.target.trigger("jqplotPreReplot");if(S){this.canvasManager.freeAllCanvases();if(this._eventCanvas){this.eventCanvas._elem.unbind()}this.target.unbind();this.target.empty()}this.reInitialize();if(V){this.resetAxesScale(V,U.axes)}this.draw();this.target.trigger("jqplotPostReplot")};this.redraw=function(S){S=(S!=null)?S:true;this.target.trigger("jqplotPreRedraw");if(S){this.canvasManager.freeAllCanvases();this.eventCanvas._elem.unbind();this.target.unbind();this.target.empty()}for(var U in this.axes){this.axes[U]._ticks=[]}for(var T=0;T<this.series.length;T++){this.populatePlotData(this.series[T],T)}this._sumy=0;this._sumx=0;for(T=0;T<this.series.length;T++){this._sumy+=this.series[T]._sumy;this._sumx+=this.series[T]._sumx}this.draw();this.target.trigger("jqplotPostRedraw")};this.draw=function(){if(this.drawIfHidden||this.target.is(":visible")){this.target.trigger("jqplotPreDraw");var Y,X;for(Y=0;Y<w.jqplot.preDrawHooks.length;Y++){w.jqplot.preDrawHooks[Y].call(this)}for(Y=0;Y<this.preDrawHooks.hooks.length;Y++){this.preDrawHooks.hooks[Y].call(this)}this.target.append(this.baseCanvas.createElement({left:0,right:0,top:0,bottom:0},"jqplot-base-canvas",null,this));this.baseCanvas.setContext();this.target.append(this.title.draw());this.title.pack({top:0,left:0});var ad=this.legend.draw();var ac={top:0,left:0,bottom:0,right:0};if(this.legend.placement=="outsideGrid"){this.target.append(ad);switch(this.legend.location){case"n":ac.top+=this.legend.getHeight();break;case"s":ac.bottom+=this.legend.getHeight();break;case"ne":case"e":case"se":ac.right+=this.legend.getWidth();break;case"nw":case"w":case"sw":ac.left+=this.legend.getWidth();break;default:ac.right+=this.legend.getWidth();break}ad=ad.detach()}var S=this.axes;for(var U in S){this.target.append(S[U].draw(this.baseCanvas._ctx,this));S[U].set()}if(S.yaxis.show){ac.left+=S.yaxis.getWidth()}var V=["y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis"];var T=[0,0,0,0,0,0,0,0];var aa=0;var W;for(W=0;W<8;W++){if(S[V[W]].show){aa+=S[V[W]].getWidth();T[W]=aa}}ac.right+=aa;if(S.x2axis.show){ac.top+=S.x2axis.getHeight()}if(this.title.show){ac.top+=this.title.getHeight()}if(S.xaxis.show){ac.bottom+=S.xaxis.getHeight()}var Z=["top","bottom","left","right"];for(var W in Z){if(this._gridPadding[Z[W]]==null&&ac[Z[W]]>0){this._gridPadding[Z[W]]=ac[Z[W]]}else{if(this._gridPadding[Z[W]]==null){this._gridPadding[Z[W]]=this._defaultGridPadding[Z[W]]}}}var ab=(this.legend.placement=="outsideGrid")?{top:this.title.getHeight(),left:0,right:0,bottom:0}:this._gridPadding;S.xaxis.pack({position:"absolute",bottom:this._gridPadding.bottom-S.xaxis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right});S.yaxis.pack({position:"absolute",top:0,left:this._gridPadding.left-S.yaxis.getWidth(),height:this._height},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top});S.x2axis.pack({position:"absolute",top:this._gridPadding.top-S.x2axis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right});for(Y=8;Y>0;Y--){S[V[Y-1]].pack({position:"absolute",top:0,right:this._gridPadding.right-T[Y-1]},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top})}this.target.append(this.grid.createElement(this._gridPadding,this));this.grid.draw();for(Y=0;Y<this.series.length;Y++){X=this.seriesStack[Y];this.target.append(this.series[X].shadowCanvas.createElement(this._gridPadding,"jqplot-series-shadowCanvas",null,this));this.series[X].shadowCanvas.setContext();this.series[X].shadowCanvas._elem.data("seriesIndex",X)}for(Y=0;Y<this.series.length;Y++){X=this.seriesStack[Y];this.target.append(this.series[X].canvas.createElement(this._gridPadding,"jqplot-series-canvas",null,this));this.series[X].canvas.setContext();this.series[X].canvas._elem.data("seriesIndex",X)}this.target.append(this.eventCanvas.createElement(this._gridPadding,"jqplot-event-canvas",null,this));this.eventCanvas.setContext();this.eventCanvas._ctx.fillStyle="rgba(0,0,0,0)";this.eventCanvas._ctx.fillRect(0,0,this.eventCanvas._ctx.canvas.width,this.eventCanvas._ctx.canvas.height);this.bindCustomEvents();if(this.legend.preDraw){this.eventCanvas._elem.before(ad);this.legend.pack(ab);if(this.legend._elem){this.drawSeries({legendInfo:{location:this.legend.location,placement:this.legend.placement,width:this.legend.getWidth(),height:this.legend.getHeight(),xoffset:this.legend.xoffset,yoffset:this.legend.yoffset}})}else{this.drawSeries()}}else{this.drawSeries();if(this.series.length){w(this.series[this.series.length-1].canvas._elem).after(ad)}this.legend.pack(ab)}for(var Y=0;Y<w.jqplot.eventListenerHooks.length;Y++){this.eventCanvas._elem.bind(w.jqplot.eventListenerHooks[Y][0],{plot:this},w.jqplot.eventListenerHooks[Y][1])}for(var Y=0;Y<this.eventListenerHooks.hooks.length;Y++){this.eventCanvas._elem.bind(this.eventListenerHooks.hooks[Y][0],{plot:this},this.eventListenerHooks.hooks[Y][1])}for(var Y=0;Y<w.jqplot.postDrawHooks.length;Y++){w.jqplot.postDrawHooks[Y].call(this)}for(var Y=0;Y<this.postDrawHooks.hooks.length;Y++){this.postDrawHooks.hooks[Y].call(this)}if(this.target.is(":visible")){this._drawCount+=1}this.target.trigger("jqplotPostDraw",[this])}};this.bindCustomEvents=function(){this.eventCanvas._elem.bind("click",{plot:this},this.onClick);this.eventCanvas._elem.bind("dblclick",{plot:this},this.onDblClick);this.eventCanvas._elem.bind("mousedown",{plot:this},this.onMouseDown);this.eventCanvas._elem.bind("mousemove",{plot:this},this.onMouseMove);this.eventCanvas._elem.bind("mouseenter",{plot:this},this.onMouseEnter);this.eventCanvas._elem.bind("mouseleave",{plot:this},this.onMouseLeave);if(this.captureRightClick){this.eventCanvas._elem.bind("mouseup",{plot:this},this.onRightClick);this.eventCanvas._elem.get(0).oncontextmenu=function(){return false}}else{this.eventCanvas._elem.bind("mouseup",{plot:this},this.onMouseUp)}};function P(aa){var Z=aa.data.plot;var V=Z.eventCanvas._elem.offset();var Y={x:aa.pageX-V.left,y:aa.pageY-V.top};var W={xaxis:null,yaxis:null,x2axis:null,y2axis:null,y3axis:null,y4axis:null,y5axis:null,y6axis:null,y7axis:null,y8axis:null,y9axis:null};var X=["xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis"];var S=Z.axes;var T,U;for(T=11;T>0;T--){U=X[T-1];if(S[U].show){W[U]=S[U].series_p2u(Y[U.charAt(0)])}}return{offsets:V,gridPos:Y,dataPos:W}}function R(S,T){var X=T.series;var aC,aB,aA,av,aw,ap,ao,ac,aa,af,ag,aq;var az,aD,ax,Y,an,at;var U,au;for(aA=T.seriesStack.length-1;aA>=0;aA--){aC=T.seriesStack[aA];av=X[aC];switch(av.renderer.constructor){case w.jqplot.BarRenderer:ap=S.x;ao=S.y;for(aB=0;aB<av._barPoints.length;aB++){an=av._barPoints[aB];ax=av.gridData[aB];if(ap>an[0][0]&&ap<an[2][0]&&ao>an[2][1]&&ao<an[0][1]){return{seriesIndex:av.index,pointIndex:aB,gridData:ax,data:av.data[aB],points:av._barPoints[aB]}}}break;case w.jqplot.DonutRenderer:af=av.startAngle/180*Math.PI;ap=S.x-av._center[0];ao=S.y-av._center[1];aw=Math.sqrt(Math.pow(ap,2)+Math.pow(ao,2));if(ap>0&&-ao>=0){ac=2*Math.PI-Math.atan(-ao/ap)}else{if(ap>0&&-ao<0){ac=-Math.atan(-ao/ap)}else{if(ap<0){ac=Math.PI-Math.atan(-ao/ap)}else{if(ap==0&&-ao>0){ac=3*Math.PI/2}else{if(ap==0&&-ao<0){ac=Math.PI/2}else{if(ap==0&&ao==0){ac=0}}}}}}if(af){ac-=af;if(ac<0){ac+=2*Math.PI}else{if(ac>2*Math.PI){ac-=2*Math.PI}}}aa=av.sliceMargin/180*Math.PI;if(aw<av._radius&&aw>av._innerRadius){for(aB=0;aB<av.gridData.length;aB++){ag=(aB>0)?av.gridData[aB-1][1]+aa:aa;aq=av.gridData[aB][1];if(ac>ag&&ac<aq){return{seriesIndex:av.index,pointIndex:aB,gridData:av.gridData[aB],data:av.data[aB]}}}}break;case w.jqplot.PieRenderer:af=av.startAngle/180*Math.PI;ap=S.x-av._center[0];ao=S.y-av._center[1];aw=Math.sqrt(Math.pow(ap,2)+Math.pow(ao,2));if(ap>0&&-ao>=0){ac=2*Math.PI-Math.atan(-ao/ap)}else{if(ap>0&&-ao<0){ac=-Math.atan(-ao/ap)}else{if(ap<0){ac=Math.PI-Math.atan(-ao/ap)}else{if(ap==0&&-ao>0){ac=3*Math.PI/2}else{if(ap==0&&-ao<0){ac=Math.PI/2}else{if(ap==0&&ao==0){ac=0}}}}}}if(af){ac-=af;if(ac<0){ac+=2*Math.PI}else{if(ac>2*Math.PI){ac-=2*Math.PI}}}aa=av.sliceMargin/180*Math.PI;if(aw<av._radius){for(aB=0;aB<av.gridData.length;aB++){ag=(aB>0)?av.gridData[aB-1][1]+aa:aa;aq=av.gridData[aB][1];if(ac>ag&&ac<aq){return{seriesIndex:av.index,pointIndex:aB,gridData:av.gridData[aB],data:av.data[aB]}}}}break;case w.jqplot.BubbleRenderer:ap=S.x;ao=S.y;var al=null;if(av.show){for(var aB=0;aB<av.gridData.length;aB++){ax=av.gridData[aB];aD=Math.sqrt((ap-ax[0])*(ap-ax[0])+(ao-ax[1])*(ao-ax[1]));if(aD<=ax[2]&&(aD<=az||az==null)){az=aD;al={seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}if(al!=null){return al}}break;case w.jqplot.FunnelRenderer:ap=S.x;ao=S.y;var ar=av._vertices,W=ar[0],V=ar[ar.length-1],Z,ak,ae;function ay(aG,aI,aH){var aF=(aI[1]-aH[1])/(aI[0]-aH[0]);var aE=aI[1]-aF*aI[0];var aJ=aG+aI[1];return[(aJ-aE)/aF,aJ]}Z=ay(ao,W[0],V[3]);ak=ay(ao,W[1],V[2]);for(aB=0;aB<ar.length;aB++){ae=ar[aB];if(ao>=ae[0][1]&&ao<=ae[3][1]&&ap>=Z[0]&&ap<=ak[0]){return{seriesIndex:av.index,pointIndex:aB,gridData:null,data:av.data[aB]}}}break;case w.jqplot.LineRenderer:ap=S.x;ao=S.y;aw=av.renderer;if(av.show){if(av.fill){var ad=false;if(ap>av._boundingBox[0][0]&&ap<av._boundingBox[1][0]&&ao>av._boundingBox[1][1]&&ao<av._boundingBox[0][1]){var aj=av._areaPoints.length;var am;var aB=aj-1;for(var am=0;am<aj;am++){var ai=[av._areaPoints[am][0],av._areaPoints[am][1]];var ah=[av._areaPoints[aB][0],av._areaPoints[aB][1]];if(ai[1]<ao&&ah[1]>=ao||ah[1]<ao&&ai[1]>=ao){if(ai[0]+(ao-ai[1])/(ah[1]-ai[1])*(ah[0]-ai[0])<ap){ad=!ad}}aB=am}}if(ad){return{seriesIndex:aC,pointIndex:null,gridData:av.gridData,data:av.data,points:av._areaPoints}}break}else{au=av.markerRenderer.size/2+av.neighborThreshold;U=(au>0)?au:0;for(var aB=0;aB<av.gridData.length;aB++){ax=av.gridData[aB];if(aw.constructor==w.jqplot.OHLCRenderer){if(aw.candleStick){var ab=av._yaxis.series_u2p;if(ap>=ax[0]-aw._bodyWidth/2&&ap<=ax[0]+aw._bodyWidth/2&&ao>=ab(av.data[aB][2])&&ao<=ab(av.data[aB][3])){return{seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}else{if(!aw.hlc){var ab=av._yaxis.series_u2p;if(ap>=ax[0]-aw._tickLength&&ap<=ax[0]+aw._tickLength&&ao>=ab(av.data[aB][2])&&ao<=ab(av.data[aB][3])){return{seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}else{var ab=av._yaxis.series_u2p;if(ap>=ax[0]-aw._tickLength&&ap<=ax[0]+aw._tickLength&&ao>=ab(av.data[aB][1])&&ao<=ab(av.data[aB][2])){return{seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}}}else{if(ax[0]!=null&&ax[1]!=null){aD=Math.sqrt((ap-ax[0])*(ap-ax[0])+(ao-ax[1])*(ao-ax[1]));if(aD<=U&&(aD<=az||az==null)){az=aD;return{seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}}}}}break;default:ap=S.x;ao=S.y;aw=av.renderer;if(av.show){au=av.markerRenderer.size/2+av.neighborThreshold;U=(au>0)?au:0;for(var aB=0;aB<av.gridData.length;aB++){ax=av.gridData[aB];if(aw.constructor==w.jqplot.OHLCRenderer){if(aw.candleStick){var ab=av._yaxis.series_u2p;if(ap>=ax[0]-aw._bodyWidth/2&&ap<=ax[0]+aw._bodyWidth/2&&ao>=ab(av.data[aB][2])&&ao<=ab(av.data[aB][3])){return{seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}else{if(!aw.hlc){var ab=av._yaxis.series_u2p;if(ap>=ax[0]-aw._tickLength&&ap<=ax[0]+aw._tickLength&&ao>=ab(av.data[aB][2])&&ao<=ab(av.data[aB][3])){return{seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}else{var ab=av._yaxis.series_u2p;if(ap>=ax[0]-aw._tickLength&&ap<=ax[0]+aw._tickLength&&ao>=ab(av.data[aB][1])&&ao<=ab(av.data[aB][2])){return{seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}}}else{aD=Math.sqrt((ap-ax[0])*(ap-ax[0])+(ao-ax[1])*(ao-ax[1]));if(aD<=U&&(aD<=az||az==null)){az=aD;return{seriesIndex:aC,pointIndex:aB,gridData:ax,data:av.data[aB]}}}}}break}}return null}this.onClick=function(U){var T=P(U);var W=U.data.plot;var V=R(T.gridPos,W);var S=jQuery.Event("jqplotClick");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,V,W])};this.onDblClick=function(U){var T=P(U);var W=U.data.plot;var V=R(T.gridPos,W);var S=jQuery.Event("jqplotDblClick");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,V,W])};this.onMouseDown=function(U){var T=P(U);var W=U.data.plot;var V=R(T.gridPos,W);var S=jQuery.Event("jqplotMouseDown");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,V,W])};this.onMouseUp=function(U){var T=P(U);var S=jQuery.Event("jqplotMouseUp");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,null,U.data.plot])};this.onRightClick=function(U){var T=P(U);var W=U.data.plot;var V=R(T.gridPos,W);if(W.captureRightClick){if(U.which==3){var S=jQuery.Event("jqplotRightClick");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,V,W])}else{var S=jQuery.Event("jqplotMouseUp");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,V,W])}}};this.onMouseMove=function(U){var T=P(U);var W=U.data.plot;var V=R(T.gridPos,W);var S=jQuery.Event("jqplotMouseMove");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,V,W])};this.onMouseEnter=function(U){var T=P(U);var V=U.data.plot;var S=jQuery.Event("jqplotMouseEnter");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,null,V])};this.onMouseLeave=function(U){var T=P(U);var V=U.data.plot;var S=jQuery.Event("jqplotMouseLeave");S.pageX=U.pageX;S.pageY=U.pageY;w(this).trigger(S,[T.gridPos,T.dataPos,null,V])};this.drawSeries=function(U,S){var W,V,T;S=(typeof(U)==="number"&&S==null)?U:S;U=(typeof(U)==="object")?U:{};if(S!=l){V=this.series[S];T=V.shadowCanvas._ctx;T.clearRect(0,0,T.canvas.width,T.canvas.height);V.drawShadow(T,U,this);T=V.canvas._ctx;T.clearRect(0,0,T.canvas.width,T.canvas.height);V.draw(T,U,this);if(V.renderer.constructor==w.jqplot.BezierCurveRenderer){if(S<this.series.length-1){this.drawSeries(S+1)}}}else{for(W=0;W<this.series.length;W++){V=this.series[W];T=V.shadowCanvas._ctx;T.clearRect(0,0,T.canvas.width,T.canvas.height);V.drawShadow(T,U,this);T=V.canvas._ctx;T.clearRect(0,0,T.canvas.width,T.canvas.height);V.draw(T,U,this)}}U=S=W=V=T=null};this.moveSeriesToFront=function(T){T=parseInt(T,10);var W=w.inArray(T,this.seriesStack);if(W==-1){return}if(W==this.seriesStack.length-1){this.previousSeriesStack=this.seriesStack.slice(0);return}var S=this.seriesStack[this.seriesStack.length-1];var V=this.series[T].canvas._elem.detach();var U=this.series[T].shadowCanvas._elem.detach();this.series[S].shadowCanvas._elem.after(U);this.series[S].canvas._elem.after(V);this.previousSeriesStack=this.seriesStack.slice(0);this.seriesStack.splice(W,1);this.seriesStack.push(T)};this.moveSeriesToBack=function(T){T=parseInt(T,10);var W=w.inArray(T,this.seriesStack);if(W==0||W==-1){return}var S=this.seriesStack[0];var V=this.series[T].canvas._elem.detach();var U=this.series[T].shadowCanvas._elem.detach();this.series[S].shadowCanvas._elem.before(U);this.series[S].canvas._elem.before(V);this.previousSeriesStack=this.seriesStack.slice(0);this.seriesStack.splice(W,1);this.seriesStack.unshift(T)};this.restorePreviousSeriesOrder=function(){var Y,X,W,V,U,S,T;if(this.seriesStack==this.previousSeriesStack){return}for(Y=1;Y<this.previousSeriesStack.length;Y++){S=this.previousSeriesStack[Y];T=this.previousSeriesStack[Y-1];W=this.series[S].canvas._elem.detach();V=this.series[S].shadowCanvas._elem.detach();this.series[T].shadowCanvas._elem.after(V);this.series[T].canvas._elem.after(W)}U=this.seriesStack.slice(0);this.seriesStack=this.previousSeriesStack.slice(0);this.previousSeriesStack=U};this.restoreOriginalSeriesOrder=function(){var W,V,S=[],U,T;for(W=0;W<this.series.length;W++){S.push(W)}if(this.seriesStack==S){return}this.previousSeriesStack=this.seriesStack.slice(0);this.seriesStack=S;for(W=1;W<this.seriesStack.length;W++){U=this.series[W].canvas._elem.detach();T=this.series[W].shadowCanvas._elem.detach();this.series[W-1].shadowCanvas._elem.after(T);this.series[W-1].canvas._elem.after(U)}};this.activateTheme=function(S){this.themeEngine.activate(this,S)}}w.jqplot.computeHighlightColors=function(P){var R;if(jQuery.isArray(P)){R=[];for(var T=0;T<P.length;T++){var S=w.jqplot.getColorComponents(P[T]);var O=[S[0],S[1],S[2]];var U=O[0]+O[1]+O[2];for(var Q=0;Q<3;Q++){O[Q]=(U>570)?O[Q]*0.8:O[Q]+0.3*(255-O[Q]);O[Q]=parseInt(O[Q],10)}R.push("rgb("+O[0]+","+O[1]+","+O[2]+")")}}else{var S=w.jqplot.getColorComponents(P);var O=[S[0],S[1],S[2]];var U=O[0]+O[1]+O[2];for(var Q=0;Q<3;Q++){O[Q]=(U>570)?O[Q]*0.8:O[Q]+0.3*(255-O[Q]);O[Q]=parseInt(O[Q],10)}R="rgb("+O[0]+","+O[1]+","+O[2]+")"}return R};w.jqplot.ColorGenerator=function(P){P=P||w.jqplot.config.defaultColors;var O=0;this.next=function(){if(O<P.length){return P[O++]}else{O=0;return P[O++]}};this.previous=function(){if(O>0){return P[O--]}else{O=P.length-1;return P[O]}};this.get=function(R){var Q=R-P.length*Math.floor(R/P.length);return P[Q]};this.setColors=function(Q){P=Q};this.reset=function(){O=0}};w.jqplot.hex2rgb=function(Q,O){Q=Q.replace("#","");if(Q.length==3){Q=Q.charAt(0)+Q.charAt(0)+Q.charAt(1)+Q.charAt(1)+Q.charAt(2)+Q.charAt(2)}var P;P="rgba("+parseInt(Q.slice(0,2),16)+", "+parseInt(Q.slice(2,4),16)+", "+parseInt(Q.slice(4,6),16);if(O){P+=", "+O}P+=")";return P};w.jqplot.rgb2hex=function(T){var Q=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/;var O=T.match(Q);var S="#";for(var R=1;R<4;R++){var P;if(O[R].search(/%/)!=-1){P=parseInt(255*O[R]/100,10).toString(16);if(P.length==1){P="0"+P}}else{P=parseInt(O[R],10).toString(16);if(P.length==1){P="0"+P}}S+=P}return S};w.jqplot.normalize2rgb=function(P,O){if(P.search(/^ *rgba?\(/)!=-1){return P}else{if(P.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/)!=-1){return w.jqplot.hex2rgb(P,O)}else{throw"invalid color spec"}}};w.jqplot.getColorComponents=function(T){T=w.jqplot.colorKeywordMap[T]||T;var R=w.jqplot.normalize2rgb(T);var Q=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/;var O=R.match(Q);var P=[];for(var S=1;S<4;S++){if(O[S].search(/%/)!=-1){P[S-1]=parseInt(255*O[S]/100,10)}else{P[S-1]=parseInt(O[S],10)}}P[3]=parseFloat(O[4])?parseFloat(O[4]):1;return P};w.jqplot.colorKeywordMap={aliceblue:"rgb(240, 248, 255)",antiquewhite:"rgb(250, 235, 215)",aqua:"rgb( 0, 255, 255)",aquamarine:"rgb(127, 255, 212)",azure:"rgb(240, 255, 255)",beige:"rgb(245, 245, 220)",bisque:"rgb(255, 228, 196)",black:"rgb( 0, 0, 0)",blanchedalmond:"rgb(255, 235, 205)",blue:"rgb( 0, 0, 255)",blueviolet:"rgb(138, 43, 226)",brown:"rgb(165, 42, 42)",burlywood:"rgb(222, 184, 135)",cadetblue:"rgb( 95, 158, 160)",chartreuse:"rgb(127, 255, 0)",chocolate:"rgb(210, 105, 30)",coral:"rgb(255, 127, 80)",cornflowerblue:"rgb(100, 149, 237)",cornsilk:"rgb(255, 248, 220)",crimson:"rgb(220, 20, 60)",cyan:"rgb( 0, 255, 255)",darkblue:"rgb( 0, 0, 139)",darkcyan:"rgb( 0, 139, 139)",darkgoldenrod:"rgb(184, 134, 11)",darkgray:"rgb(169, 169, 169)",darkgreen:"rgb( 0, 100, 0)",darkgrey:"rgb(169, 169, 169)",darkkhaki:"rgb(189, 183, 107)",darkmagenta:"rgb(139, 0, 139)",darkolivegreen:"rgb( 85, 107, 47)",darkorange:"rgb(255, 140, 0)",darkorchid:"rgb(153, 50, 204)",darkred:"rgb(139, 0, 0)",darksalmon:"rgb(233, 150, 122)",darkseagreen:"rgb(143, 188, 143)",darkslateblue:"rgb( 72, 61, 139)",darkslategray:"rgb( 47, 79, 79)",darkslategrey:"rgb( 47, 79, 79)",darkturquoise:"rgb( 0, 206, 209)",darkviolet:"rgb(148, 0, 211)",deeppink:"rgb(255, 20, 147)",deepskyblue:"rgb( 0, 191, 255)",dimgray:"rgb(105, 105, 105)",dimgrey:"rgb(105, 105, 105)",dodgerblue:"rgb( 30, 144, 255)",firebrick:"rgb(178, 34, 34)",floralwhite:"rgb(255, 250, 240)",forestgreen:"rgb( 34, 139, 34)",fuchsia:"rgb(255, 0, 255)",gainsboro:"rgb(220, 220, 220)",ghostwhite:"rgb(248, 248, 255)",gold:"rgb(255, 215, 0)",goldenrod:"rgb(218, 165, 32)",gray:"rgb(128, 128, 128)",grey:"rgb(128, 128, 128)",green:"rgb( 0, 128, 0)",greenyellow:"rgb(173, 255, 47)",honeydew:"rgb(240, 255, 240)",hotpink:"rgb(255, 105, 180)",indianred:"rgb(205, 92, 92)",indigo:"rgb( 75, 0, 130)",ivory:"rgb(255, 255, 240)",khaki:"rgb(240, 230, 140)",lavender:"rgb(230, 230, 250)",lavenderblush:"rgb(255, 240, 245)",lawngreen:"rgb(124, 252, 0)",lemonchiffon:"rgb(255, 250, 205)",lightblue:"rgb(173, 216, 230)",lightcoral:"rgb(240, 128, 128)",lightcyan:"rgb(224, 255, 255)",lightgoldenrodyellow:"rgb(250, 250, 210)",lightgray:"rgb(211, 211, 211)",lightgreen:"rgb(144, 238, 144)",lightgrey:"rgb(211, 211, 211)",lightpink:"rgb(255, 182, 193)",lightsalmon:"rgb(255, 160, 122)",lightseagreen:"rgb( 32, 178, 170)",lightskyblue:"rgb(135, 206, 250)",lightslategray:"rgb(119, 136, 153)",lightslategrey:"rgb(119, 136, 153)",lightsteelblue:"rgb(176, 196, 222)",lightyellow:"rgb(255, 255, 224)",lime:"rgb( 0, 255, 0)",limegreen:"rgb( 50, 205, 50)",linen:"rgb(250, 240, 230)",magenta:"rgb(255, 0, 255)",maroon:"rgb(128, 0, 0)",mediumaquamarine:"rgb(102, 205, 170)",mediumblue:"rgb( 0, 0, 205)",mediumorchid:"rgb(186, 85, 211)",mediumpurple:"rgb(147, 112, 219)",mediumseagreen:"rgb( 60, 179, 113)",mediumslateblue:"rgb(123, 104, 238)",mediumspringgreen:"rgb( 0, 250, 154)",mediumturquoise:"rgb( 72, 209, 204)",mediumvioletred:"rgb(199, 21, 133)",midnightblue:"rgb( 25, 25, 112)",mintcream:"rgb(245, 255, 250)",mistyrose:"rgb(255, 228, 225)",moccasin:"rgb(255, 228, 181)",navajowhite:"rgb(255, 222, 173)",navy:"rgb( 0, 0, 128)",oldlace:"rgb(253, 245, 230)",olive:"rgb(128, 128, 0)",olivedrab:"rgb(107, 142, 35)",orange:"rgb(255, 165, 0)",orangered:"rgb(255, 69, 0)",orchid:"rgb(218, 112, 214)",palegoldenrod:"rgb(238, 232, 170)",palegreen:"rgb(152, 251, 152)",paleturquoise:"rgb(175, 238, 238)",palevioletred:"rgb(219, 112, 147)",papayawhip:"rgb(255, 239, 213)",peachpuff:"rgb(255, 218, 185)",peru:"rgb(205, 133, 63)",pink:"rgb(255, 192, 203)",plum:"rgb(221, 160, 221)",powderblue:"rgb(176, 224, 230)",purple:"rgb(128, 0, 128)",red:"rgb(255, 0, 0)",rosybrown:"rgb(188, 143, 143)",royalblue:"rgb( 65, 105, 225)",saddlebrown:"rgb(139, 69, 19)",salmon:"rgb(250, 128, 114)",sandybrown:"rgb(244, 164, 96)",seagreen:"rgb( 46, 139, 87)",seashell:"rgb(255, 245, 238)",sienna:"rgb(160, 82, 45)",silver:"rgb(192, 192, 192)",skyblue:"rgb(135, 206, 235)",slateblue:"rgb(106, 90, 205)",slategray:"rgb(112, 128, 144)",slategrey:"rgb(112, 128, 144)",snow:"rgb(255, 250, 250)",springgreen:"rgb( 0, 255, 127)",steelblue:"rgb( 70, 130, 180)",tan:"rgb(210, 180, 140)",teal:"rgb( 0, 128, 128)",thistle:"rgb(216, 191, 216)",tomato:"rgb(255, 99, 71)",turquoise:"rgb( 64, 224, 208)",violet:"rgb(238, 130, 238)",wheat:"rgb(245, 222, 179)",white:"rgb(255, 255, 255)",whitesmoke:"rgb(245, 245, 245)",yellow:"rgb(255, 255, 0)",yellowgreen:"rgb(154, 205, 50)"};w.jqplot.AxisLabelRenderer=function(O){w.jqplot.ElemContainer.call(this);this.axis;this.show=true;this.label="";this.fontFamily=null;this.fontSize=null;this.textColor=null;this._elem;this.escapeHTML=false;w.extend(true,this,O)};w.jqplot.AxisLabelRenderer.prototype=new w.jqplot.ElemContainer();w.jqplot.AxisLabelRenderer.prototype.constructor=w.jqplot.AxisLabelRenderer;w.jqplot.AxisLabelRenderer.prototype.init=function(O){w.extend(true,this,O)};w.jqplot.AxisLabelRenderer.prototype.draw=function(O,P){if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=w('<div style="position:absolute;" class="jqplot-'+this.axis+'-label"></div>');if(Number(this.label)){this._elem.css("white-space","nowrap")}if(!this.escapeHTML){this._elem.html(this.label)}else{this._elem.text(this.label)}if(this.fontFamily){this._elem.css("font-family",this.fontFamily)}if(this.fontSize){this._elem.css("font-size",this.fontSize)}if(this.textColor){this._elem.css("color",this.textColor)}return this._elem};w.jqplot.AxisLabelRenderer.prototype.pack=function(){};w.jqplot.AxisTickRenderer=function(O){w.jqplot.ElemContainer.call(this);this.mark="outside";this.axis;this.showMark=true;this.showGridline=true;this.isMinorTick=false;this.size=4;this.markSize=6;this.show=true;this.showLabel=true;this.label="";this.value=null;this._styles={};this.formatter=w.jqplot.DefaultTickFormatter;this.prefix="";this.formatString="";this.fontFamily;this.fontSize;this.textColor;this.escapeHTML=false;this._elem;this._breakTick=false;w.extend(true,this,O)};w.jqplot.AxisTickRenderer.prototype.init=function(O){w.extend(true,this,O)};w.jqplot.AxisTickRenderer.prototype=new w.jqplot.ElemContainer();w.jqplot.AxisTickRenderer.prototype.constructor=w.jqplot.AxisTickRenderer;w.jqplot.AxisTickRenderer.prototype.setTick=function(O,Q,P){this.value=O;this.axis=Q;if(P){this.isMinorTick=true}return this};w.jqplot.AxisTickRenderer.prototype.draw=function(){if(!this.label){this.label=this.prefix+this.formatter(this.formatString,this.value)}var P={position:"absolute"};if(Number(this.label)){P.whitSpace="nowrap"}if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=w(document.createElement("div"));this._elem.addClass("jqplot-"+this.axis+"-tick");if(!this.escapeHTML){this._elem.html(this.label)}else{this._elem.text(this.label)}this._elem.css(P);for(var O in this._styles){this._elem.css(O,this._styles[O])}if(this.fontFamily){this._elem.css("font-family",this.fontFamily)}if(this.fontSize){this._elem.css("font-size",this.fontSize)}if(this.textColor){this._elem.css("color",this.textColor)}if(this._breakTick){this._elem.addClass("jqplot-breakTick")}return this._elem};w.jqplot.DefaultTickFormatter=function(O,P){if(typeof P=="number"){if(!O){O=w.jqplot.config.defaultTickFormatString}return w.jqplot.sprintf(O,P)}else{return String(P)}};w.jqplot.AxisTickRenderer.prototype.pack=function(){};w.jqplot.CanvasGridRenderer=function(){this.shadowRenderer=new w.jqplot.ShadowRenderer()};w.jqplot.CanvasGridRenderer.prototype.init=function(P){this._ctx;w.extend(true,this,P);var O={lineJoin:"miter",lineCap:"round",fill:false,isarc:false,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.shadowWidth,closePath:false,strokeStyle:this.shadowColor};this.renderer.shadowRenderer.init(O)};w.jqplot.CanvasGridRenderer.prototype.createElement=function(R){var Q;if(this._elem){if(w.jqplot.use_excanvas){Q=this._elem.get(0);window.G_vmlCanvasManager.uninitElement(Q);Q=null}this._elem.emptyForce();this._elem=null}Q=R.canvasManager.getCanvas();var O=this._plotDimensions.width;var P=this._plotDimensions.height;Q.width=O;Q.height=P;this._elem=w(Q);this._elem.addClass("jqplot-grid-canvas");this._elem.css({position:"absolute",left:0,top:0});Q=R.canvasManager.initCanvas(Q);this._top=this._offsets.top;this._bottom=P-this._offsets.bottom;this._left=this._offsets.left;this._right=O-this._offsets.right;this._width=this._right-this._left;this._height=this._bottom-this._top;Q=null;return this._elem};w.jqplot.CanvasGridRenderer.prototype.draw=function(){this._ctx=this._elem.get(0).getContext("2d");var Y=this._ctx;var ab=this._axes;Y.save();Y.clearRect(0,0,this._plotDimensions.width,this._plotDimensions.height);Y.fillStyle=this.backgroundColor||this.background;Y.fillRect(this._left,this._top,this._width,this._height);if(true){Y.save();Y.lineJoin="miter";Y.lineCap="butt";Y.lineWidth=this.gridLineWidth;Y.strokeStyle=this.gridLineColor;var ae,ad,W,X;var T=["xaxis","yaxis","x2axis","y2axis"];for(var ac=4;ac>0;ac--){var ag=T[ac-1];var O=ab[ag];var af=O._ticks;if(O.show){for(var Z=af.length;Z>0;Z--){var U=af[Z-1];if(U.show){var R=Math.round(O.u2p(U.value))+0.5;switch(ag){case"xaxis":if(U.showGridline&&this.drawGridlines){V(R,this._top,R,this._bottom)}if(U.showMark&&U.mark){W=U.markSize;X=U.mark;var R=Math.round(O.u2p(U.value))+0.5;switch(X){case"outside":ae=this._bottom;ad=this._bottom+W;break;case"inside":ae=this._bottom-W;ad=this._bottom;break;case"cross":ae=this._bottom-W;ad=this._bottom+W;break;default:ae=this._bottom;ad=this._bottom+W;break}if(this.shadow){this.renderer.shadowRenderer.draw(Y,[[R,ae],[R,ad]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}V(R,ae,R,ad)}break;case"yaxis":if(U.showGridline&&this.drawGridlines){V(this._right,R,this._left,R)}if(U.showMark&&U.mark){W=U.markSize;X=U.mark;var R=Math.round(O.u2p(U.value))+0.5;switch(X){case"outside":ae=this._left-W;ad=this._left;break;case"inside":ae=this._left;ad=this._left+W;break;case"cross":ae=this._left-W;ad=this._left+W;break;default:ae=this._left-W;ad=this._left;break}if(this.shadow){this.renderer.shadowRenderer.draw(Y,[[ae,R],[ad,R]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}V(ae,R,ad,R,{strokeStyle:O.borderColor})}break;case"x2axis":if(U.showGridline&&this.drawGridlines){V(R,this._bottom,R,this._top)}if(U.showMark&&U.mark){W=U.markSize;X=U.mark;var R=Math.round(O.u2p(U.value))+0.5;switch(X){case"outside":ae=this._top-W;ad=this._top;break;case"inside":ae=this._top;ad=this._top+W;break;case"cross":ae=this._top-W;ad=this._top+W;break;default:ae=this._top-W;ad=this._top;break}if(this.shadow){this.renderer.shadowRenderer.draw(Y,[[R,ae],[R,ad]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}V(R,ae,R,ad)}break;case"y2axis":if(U.showGridline&&this.drawGridlines){V(this._left,R,this._right,R)}if(U.showMark&&U.mark){W=U.markSize;X=U.mark;var R=Math.round(O.u2p(U.value))+0.5;switch(X){case"outside":ae=this._right;ad=this._right+W;break;case"inside":ae=this._right-W;ad=this._right;break;case"cross":ae=this._right-W;ad=this._right+W;break;default:ae=this._right;ad=this._right+W;break}if(this.shadow){this.renderer.shadowRenderer.draw(Y,[[ae,R],[ad,R]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}V(ae,R,ad,R,{strokeStyle:O.borderColor})}break;default:break}}}U=null}O=null;af=null}T=["y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis"];for(var ac=7;ac>0;ac--){var O=ab[T[ac-1]];var af=O._ticks;if(O.show){var P=af[O.numberTicks-1];var S=af[0];var Q=O.getLeft();var aa=[[Q,P.getTop()+P.getHeight()/2],[Q,S.getTop()+S.getHeight()/2+1]];if(this.shadow){this.renderer.shadowRenderer.draw(Y,aa,{lineCap:"butt",fill:false,closePath:false})}V(aa[0][0],aa[0][1],aa[1][0],aa[1][1],{lineCap:"butt",strokeStyle:O.borderColor,lineWidth:O.borderWidth});for(var Z=af.length;Z>0;Z--){var U=af[Z-1];W=U.markSize;X=U.mark;var R=Math.round(O.u2p(U.value))+0.5;if(U.showMark&&U.mark){switch(X){case"outside":ae=Q;ad=Q+W;break;case"inside":ae=Q-W;ad=Q;break;case"cross":ae=Q-W;ad=Q+W;break;default:ae=Q;ad=Q+W;break}aa=[[ae,R],[ad,R]];if(this.shadow){this.renderer.shadowRenderer.draw(Y,aa,{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}V(ae,R,ad,R,{strokeStyle:O.borderColor})}U=null}S=null}O=null;af=null}Y.restore()}function V(al,ak,ai,ah,aj){Y.save();aj=aj||{};if(aj.lineWidth==null||aj.lineWidth!=0){w.extend(true,Y,aj);Y.beginPath();Y.moveTo(al,ak);Y.lineTo(ai,ah);Y.stroke();Y.restore()}}if(this.shadow){var aa=[[this._left,this._bottom],[this._right,this._bottom],[this._right,this._top]];this.renderer.shadowRenderer.draw(Y,aa)}if(this.borderWidth!=0&&this.drawBorder){V(this._left,this._top,this._right,this._top,{lineCap:"round",strokeStyle:ab.x2axis.borderColor,lineWidth:ab.x2axis.borderWidth});V(this._right,this._top,this._right,this._bottom,{lineCap:"round",strokeStyle:ab.y2axis.borderColor,lineWidth:ab.y2axis.borderWidth});V(this._right,this._bottom,this._left,this._bottom,{lineCap:"round",strokeStyle:ab.xaxis.borderColor,lineWidth:ab.xaxis.borderWidth});V(this._left,this._bottom,this._left,this._top,{lineCap:"round",strokeStyle:ab.yaxis.borderColor,lineWidth:ab.yaxis.borderWidth})}Y.restore();Y=null;ab=null};w.jqplot.DivTitleRenderer=function(){};w.jqplot.DivTitleRenderer.prototype.init=function(O){w.extend(true,this,O)};w.jqplot.DivTitleRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}var R=this.renderer;var Q=document.createElement("div");this._elem=w(Q);this._elem.addClass("jqplot-title");if(!this.text){this.show=false;this._elem.height(0);this._elem.width(0)}else{if(this.text){var O;if(this.color){O=this.color}else{if(this.textColor){O=this.textColor}}var P={position:"absolute",top:"0px",left:"0px"};if(this._plotWidth){P.width=this._plotWidth+"px"}if(this.fontSize){P.fontSize=this.fontSize}if(this.textAlign){P.textAlign=this.textAlign}else{P.textAlign="center"}if(O){P.color=O}if(this.paddingBottom){P.paddingBottom=this.paddingBottom}if(this.fontFamily){P.fontFamily=this.fontFamily}this._elem.css(P);this._elem.text(this.text)}}Q=null;return this._elem};w.jqplot.DivTitleRenderer.prototype.pack=function(){};w.jqplot.LineRenderer=function(){this.shapeRenderer=new w.jqplot.ShapeRenderer();this.shadowRenderer=new w.jqplot.ShadowRenderer()};w.jqplot.LineRenderer.prototype.init=function(P,T){P=P||{};this._type="line";var R={highlightMouseOver:P.highlightMouseOver,highlightMouseDown:P.highlightMouseDown,highlightColor:P.highlightColor};delete (P.highlightMouseOver);delete (P.highlightMouseDown);delete (P.highlightColor);w.extend(true,this.renderer,P);var S={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:false,strokeStyle:this.color,fillStyle:this.fillColor,lineWidth:this.lineWidth,closePath:this.fill};this.renderer.shapeRenderer.init(S);if(this.lineWidth>2.5){var Q=this.shadowOffset*(1+(Math.atan((this.lineWidth/2.5))/0.785398163-1)*0.6)}else{var Q=this.shadowOffset*Math.atan((this.lineWidth/2.5))/0.785398163}var O={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:false,angle:this.shadowAngle,offset:Q,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.lineWidth,closePath:this.fill};this.renderer.shadowRenderer.init(O);this._areaPoints=[];this._boundingBox=[[],[]];if(!this.isTrendline&&this.fill){this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColor=null;if(R.highlightMouseDown&&R.highlightMouseOver==null){R.highlightMouseOver=false}w.extend(true,this,{highlightMouseOver:R.highlightMouseOver,highlightMouseDown:R.highlightMouseDown,highlightColor:R.highlightColor});if(!this.highlightColor){this.highlightColor=w.jqplot.computeHighlightColors(this.fillColor)}if(this.highlighter){this.highlighter.show=false}}if(!this.isTrendline&&T){T.plugins.lineRenderer={};T.postInitHooks.addOnce(o);T.postDrawHooks.addOnce(M);T.eventListenerHooks.addOnce("jqplotMouseMove",d);T.eventListenerHooks.addOnce("jqplotMouseDown",a);T.eventListenerHooks.addOnce("jqplotMouseUp",L);T.eventListenerHooks.addOnce("jqplotClick",c);T.eventListenerHooks.addOnce("jqplotRightClick",j)}};w.jqplot.LineRenderer.prototype.setGridData=function(T){var P=this._xaxis.series_u2p;var S=this._yaxis.series_u2p;var Q=this._plotData;var R=this._prevPlotData;this.gridData=[];this._prevGridData=[];for(var O=0;O<this.data.length;O++){if(Q[O][0]!=null&&Q[O][1]!=null){this.gridData.push([P.call(this._xaxis,Q[O][0]),S.call(this._yaxis,Q[O][1])])}else{if(Q[O][0]==null){this.gridData.push([null,S.call(this._yaxis,Q[O][1])])}else{if(Q[O][1]==null){this.gridData.push([P.call(this._xaxis,Q[O][0]),null])}}}if(R[O]!=null&&R[O][0]!=null&&R[O][1]!=null){this._prevGridData.push([P.call(this._xaxis,R[O][0]),S.call(this._yaxis,R[O][1])])}else{if(R[O]!=null&&R[O][0]==null){this._prevGridData.push([null,S.call(this._yaxis,R[O][1])])}else{if(R[O]!=null&&R[O][0]!=null&&R[O][1]==null){this._prevGridData.push([P.call(this._xaxis,R[O][0]),null])}}}}};w.jqplot.LineRenderer.prototype.makeGridData=function(R,T){var Q=this._xaxis.series_u2p;var S=this._yaxis.series_u2p;var P=[];var U=[];for(var O=0;O<R.length;O++){if(R[O][0]!=null&&R[O][1]!=null){P.push([Q.call(this._xaxis,R[O][0]),S.call(this._yaxis,R[O][1])])}else{if(R[O][0]==null){P.push([null,S.call(this._yaxis,R[O][1])])}else{if(R[O][1]==null){P.push([Q.call(this._xaxis,R[O][0]),null])}}}}return P};w.jqplot.LineRenderer.prototype.draw=function(ad,an,P){var ah;var X=(P!=l)?P:{};var R=(X.shadow!=l)?X.shadow:this.shadow;var ao=(X.showLine!=l)?X.showLine:this.showLine;var ag=(X.fill!=l)?X.fill:this.fill;var O=(X.fillAndStroke!=l)?X.fillAndStroke:this.fillAndStroke;var Y,ae,ab,aj;ad.save();if(an.length){if(ao){if(ag){if(this.fillToZero){var S=new w.jqplot.ColorGenerator(this.negativeSeriesColors);var ak=S.get(this.index);if(!this.useNegativeColors){ak=X.fillStyle}var V=false;var W=X.fillStyle;if(O){var am=an.slice(0)}if(this.index==0||!this._stack){var ac=[];this._areaPoints=[];var al=this._yaxis.series_u2p(this.fillToValue);var Q=this._xaxis.series_u2p(this.fillToValue);if(this.fillAxis=="y"){ac.push([an[0][0],al]);this._areaPoints.push([an[0][0],al]);for(var ah=0;ah<an.length-1;ah++){ac.push(an[ah]);this._areaPoints.push(an[ah]);if(this._plotData[ah][1]*this._plotData[ah+1][1]<0){if(this._plotData[ah][1]<0){V=true;X.fillStyle=ak}else{V=false;X.fillStyle=W}var U=an[ah][0]+(an[ah+1][0]-an[ah][0])*(al-an[ah][1])/(an[ah+1][1]-an[ah][1]);ac.push([U,al]);this._areaPoints.push([U,al]);if(R){this.renderer.shadowRenderer.draw(ad,ac,X)}this.renderer.shapeRenderer.draw(ad,ac,X);ac=[[U,al]]}}if(this._plotData[an.length-1][1]<0){V=true;X.fillStyle=ak}else{V=false;X.fillStyle=W}ac.push(an[an.length-1]);this._areaPoints.push(an[an.length-1]);ac.push([an[an.length-1][0],al]);this._areaPoints.push([an[an.length-1][0],al])}if(R){this.renderer.shadowRenderer.draw(ad,ac,X)}this.renderer.shapeRenderer.draw(ad,ac,X)}else{var aa=this._prevGridData;for(var ah=aa.length;ah>0;ah--){an.push(aa[ah-1])}if(R){this.renderer.shadowRenderer.draw(ad,an,X)}this._areaPoints=an;this.renderer.shapeRenderer.draw(ad,an,X)}}else{if(O){var am=an.slice(0)}if(this.index==0||!this._stack){var T=ad.canvas.height;an.unshift([an[0][0],T]);var ai=an.length;an.push([an[ai-1][0],T])}else{var aa=this._prevGridData;for(var ah=aa.length;ah>0;ah--){an.push(aa[ah-1])}}this._areaPoints=an;if(R){this.renderer.shadowRenderer.draw(ad,an,X)}this.renderer.shapeRenderer.draw(ad,an,X)}if(O){var af=w.extend(true,{},X,{fill:false,closePath:false});this.renderer.shapeRenderer.draw(ad,am,af);if(this.markerRenderer.show){for(ah=0;ah<am.length;ah++){this.markerRenderer.draw(am[ah][0],am[ah][1],ad,X.markerOptions)}}}}else{if(R){this.renderer.shadowRenderer.draw(ad,an,X)}this.renderer.shapeRenderer.draw(ad,an,X)}}var Y=ab=ae=aj=null;for(ah=0;ah<this._areaPoints.length;ah++){var Z=this._areaPoints[ah];if(Y>Z[0]||Y==null){Y=Z[0]}if(aj<Z[1]||aj==null){aj=Z[1]}if(ab<Z[0]||ab==null){ab=Z[0]}if(ae>Z[1]||ae==null){ae=Z[1]}}this._boundingBox=[[Y,aj],[ab,ae]];if(this.markerRenderer.show&&!ag){for(ah=0;ah<an.length;ah++){if(an[ah][0]!=null&&an[ah][1]!=null){this.markerRenderer.draw(an[ah][0],an[ah][1],ad,X.markerOptions)}}}}ad.restore()};w.jqplot.LineRenderer.prototype.drawShadow=function(O,Q,P){};function o(R,Q,O){for(var P=0;P<this.series.length;P++){if(this.series[P].renderer.constructor==w.jqplot.LineRenderer){if(this.series[P].highlightMouseOver){this.series[P].highlightMouseDown=false}}}this.target.bind("mouseout",{plot:this},function(S){I(S.data.plot)})}function M(){if(this.plugins.lineRenderer&&this.plugins.lineRenderer.highlightCanvas){this.plugins.lineRenderer.highlightCanvas.resetCanvas();this.plugins.lineRenderer.highlightCanvas=null}this.plugins.lineRenderer.highlightedSeriesIndex=null;this.plugins.lineRenderer.highlightCanvas=new w.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.lineRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-lineRenderer-highlight-canvas",this._plotDimensions,this));this.plugins.lineRenderer.highlightCanvas.setContext()}function K(U,T,R,Q){var P=U.series[T];var O=U.plugins.lineRenderer.highlightCanvas;O._ctx.clearRect(0,0,O._ctx.canvas.width,O._ctx.canvas.height);P._highlightedPoint=R;U.plugins.lineRenderer.highlightedSeriesIndex=T;var S={fillStyle:P.highlightColor};P.renderer.shapeRenderer.draw(O._ctx,Q,S);O=null}function I(Q){var O=Q.plugins.lineRenderer.highlightCanvas;O._ctx.clearRect(0,0,O._ctx.canvas.width,O._ctx.canvas.height);for(var P=0;P<Q.series.length;P++){Q.series[P]._highlightedPoint=null}Q.plugins.lineRenderer.highlightedSeriesIndex=null;Q.target.trigger("jqplotDataUnhighlight");O=null}function d(S,R,V,U,T){if(U){var Q=[U.seriesIndex,U.pointIndex,U.data];var P=jQuery.Event("jqplotDataMouseOver");P.pageX=S.pageX;P.pageY=S.pageY;T.target.trigger(P,Q);if(T.series[Q[0]].highlightMouseOver&&!(Q[0]==T.plugins.lineRenderer.highlightedSeriesIndex)){var O=jQuery.Event("jqplotDataHighlight");O.pageX=S.pageX;O.pageY=S.pageY;T.target.trigger(O,Q);K(T,U.seriesIndex,U.pointIndex,U.points)}}else{if(U==null){I(T)}}}function a(R,Q,U,T,S){if(T){var P=[T.seriesIndex,T.pointIndex,T.data];if(S.series[P[0]].highlightMouseDown&&!(P[0]==S.plugins.lineRenderer.highlightedSeriesIndex)){var O=jQuery.Event("jqplotDataHighlight");O.pageX=R.pageX;O.pageY=R.pageY;S.target.trigger(O,P);K(S,T.seriesIndex,T.pointIndex,T.points)}}else{if(T==null){I(S)}}}function L(Q,P,T,S,R){var O=R.plugins.lineRenderer.highlightedSeriesIndex;if(O!=null&&R.series[O].highlightMouseDown){I(R)}}function c(R,Q,U,T,S){if(T){var P=[T.seriesIndex,T.pointIndex,T.data];var O=jQuery.Event("jqplotDataClick");O.pageX=R.pageX;O.pageY=R.pageY;S.target.trigger(O,P)}}function j(S,R,V,U,T){if(U){var Q=[U.seriesIndex,U.pointIndex,U.data];var O=T.plugins.lineRenderer.highlightedSeriesIndex;if(O!=null&&T.series[O].highlightMouseDown){I(T)}var P=jQuery.Event("jqplotDataRightClick");P.pageX=S.pageX;P.pageY=S.pageY;T.target.trigger(P,Q)}}w.jqplot.LinearAxisRenderer=function(){};w.jqplot.LinearAxisRenderer.prototype.init=function(O){this.breakPoints=null;this.breakTickLabel="≈";this.forceTickAt0=false;this.forceTickAt100=false;this._autoFormatString="";this._overrideFormatString=false;w.extend(true,this,O);if(this.breakPoints){if(!w.isArray(this.breakPoints)){this.breakPoints=null}else{if(this.breakPoints.length<2||this.breakPoints[1]<=this.breakPoints[0]){this.breakPoints=null}}}this.resetDataBounds()};w.jqplot.LinearAxisRenderer.prototype.draw=function(O,V){if(this.show){this.renderer.createTicks.call(this);var U=0;var P;if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=w(document.createElement("div"));this._elem.addClass("jqplot-axis jqplot-"+this.name);this._elem.css("posiiton","absolute");if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){var T=this._label.draw(O,V);T.appendTo(this._elem);T=null}var S=this._ticks;var R;for(var Q=0;Q<S.length;Q++){R=S[Q];if(R.show&&R.showLabel&&(!R.isMinorTick||this.showMinorTicks)){this._elem.append(R.draw(O,V))}}R=null;S=null}return this._elem};w.jqplot.LinearAxisRenderer.prototype.reset=function(){this.min=this._min;this.max=this._max;this.tickInterval=this._tickInterval;this.numberTicks=this._numberTicks;this._autoFormatString="";if(this._overrideFormatString&&this.tickOptions&&this.tickOptions.formatString){this.tickOptions.formatString=""}};w.jqplot.LinearAxisRenderer.prototype.set=function(){var V=0;var Q;var P=0;var U=0;var O=(this._label==null)?false:this._label.show;if(this.show){var T=this._ticks;var S;for(var R=0;R<T.length;R++){S=T[R];if(!S._breakTick&&S.show&&S.showLabel&&(!S.isMinorTick||this.showMinorTicks)){if(this.name=="xaxis"||this.name=="x2axis"){Q=S._elem.outerHeight(true)}else{Q=S._elem.outerWidth(true)}if(Q>V){V=Q}}}S=null;T=null;if(O){P=this._label._elem.outerWidth(true);U=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){V=V+U;this._elem.css({height:V+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){V=V+U;this._elem.css({height:V+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){V=V+P;this._elem.css({width:V+"px",left:"0px",top:"0px"});if(O&&this._label.constructor==w.jqplot.AxisLabelRenderer){this._label._elem.css("width",P+"px")}}else{V=V+P;this._elem.css({width:V+"px",right:"0px",top:"0px"});if(O&&this._label.constructor==w.jqplot.AxisLabelRenderer){this._label._elem.css("width",P+"px")}}}}}};w.jqplot.LinearAxisRenderer.prototype.createTicks=function(){var ax=this._ticks;var an=this.ticks;var ae=this.name;var ag=this._dataBounds;var O,T;var aJ,al;var V,U;var aH,aE;var ak=this.min;var aI=this.max;var aA=this.numberTicks;var aM=this.tickInterval;if(an.length){for(aE=0;aE<an.length;aE++){var aq=an[aE];var ay=new this.tickRenderer(this.tickOptions);if(aq.constructor==Array){ay.value=aq[0];if(this.breakPoints){if(aq[0]==this.breakPoints[0]){ay.label=this.breakTickLabel;ay._breakTick=true;ay.showGridline=false;ay.showMark=false}else{if(aq[0]>this.breakPoints[0]&&aq[0]<=this.breakPoints[1]){ay.show=false;ay.showGridline=false;ay.label=aq[1]}else{ay.label=aq[1]}}}else{ay.label=aq[1]}ay.setTick(aq[0],this.name);this._ticks.push(ay)}else{ay.value=aq;if(this.breakPoints){if(aq==this.breakPoints[0]){ay.label=this.breakTickLabel;ay._breakTick=true;ay.showGridline=false;ay.showMark=false}else{if(aq>this.breakPoints[0]&&aq<=this.breakPoints[1]){ay.show=false;ay.showGridline=false}}}ay.setTick(aq,this.name);this._ticks.push(ay)}}this.numberTicks=an.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value;this.tickInterval=(this.max-this.min)/(this.numberTicks-1)}else{if(ae=="xaxis"||ae=="x2axis"){O=this._plotDimensions.width}else{O=this._plotDimensions.height}aJ=((this.min!=null)?this.min:ag.min);al=((this.max!=null)?this.max:ag.max);var aa=al-aJ;var aw,ad;var Y;if(this.min==null&&this.max==null&&this.numberTicks==null&&this.tickInterval==null&&!this.autoscale){if(this.tickOptions==null||!this.tickOptions.formatString){this._overrideFormatString=true}if(this.forceTickAt0){if(aJ>0){aJ=0}if(al<0){al=0}}if(this.forceTickAt100){if(aJ>100){aJ=100}if(al<100){al=100}}var S=30;var at=Math.max(O,S+1);var ab=(at-S)/300;var ar=w.jqplot.LinearTickGenerator(aJ,al,ab);var ac=aJ+aa*(this.padMin-1);var au=al-aa*(this.padMax-1);if(aJ<=ac||al>=au){ac=aJ-aa*(this.padMin-1);au=al+aa*(this.padMax-1);ar=w.jqplot.LinearTickGenerator(ac,au,ab)}this.min=ar[0];this.max=ar[1];this.numberTicks=ar[2];this._autoFormatString=ar[3];this.tickInterval=ar[4]}else{if(aJ==al){var P=0.05;if(aJ>0){P=Math.max(Math.log(aJ)/Math.LN10,0.05)}aJ-=P;al+=P}if(this.autoscale&&this.min==null&&this.max==null){var Q,R,X;var ah=false;var ap=false;var af={min:null,max:null,average:null,stddev:null};for(var aE=0;aE<this._series.length;aE++){var az=this._series[aE];var ai=(az.fillAxis=="x")?az._xaxis.name:az._yaxis.name;if(this.name==ai){var av=az._plotValues[az.fillAxis];var aj=av[0];var aF=av[0];for(var aD=1;aD<av.length;aD++){if(av[aD]<aj){aj=av[aD]}else{if(av[aD]>aF){aF=av[aD]}}}var Z=(aF-aj)/aF;if(az.renderer.constructor==w.jqplot.BarRenderer){if(aj>=0&&(az.fillToZero||Z>0.1)){ah=true}else{ah=false;if(az.fill&&az.fillToZero&&aj<0&&aF>0){ap=true}else{ap=false}}}else{if(az.fill){if(aj>=0&&(az.fillToZero||Z>0.1)){ah=true}else{if(aj<0&&aF>0&&az.fillToZero){ah=false;ap=true}else{ah=false;ap=false}}}else{if(aj<0){ah=false}}}}}if(ah){this.numberTicks=2+Math.ceil((O-(this.tickSpacing-1))/this.tickSpacing);this.min=0;ak=0;R=al/(this.numberTicks-1);Y=Math.pow(10,Math.abs(Math.floor(Math.log(R)/Math.LN10)));if(R/Y==parseInt(R/Y,10)){R+=Y}this.tickInterval=Math.ceil(R/Y)*Y;this.max=this.tickInterval*(this.numberTicks-1)}else{if(ap){this.numberTicks=2+Math.ceil((O-(this.tickSpacing-1))/this.tickSpacing);var am=Math.ceil(Math.abs(aJ)/aa*(this.numberTicks-1));var aL=this.numberTicks-1-am;R=Math.max(Math.abs(aJ/am),Math.abs(al/aL));Y=Math.pow(10,Math.abs(Math.floor(Math.log(R)/Math.LN10)));this.tickInterval=Math.ceil(R/Y)*Y;this.max=this.tickInterval*aL;this.min=-this.tickInterval*am}else{if(this.numberTicks==null){if(this.tickInterval){this.numberTicks=3+Math.ceil(aa/this.tickInterval)}else{this.numberTicks=2+Math.ceil((O-(this.tickSpacing-1))/this.tickSpacing)}}if(this.tickInterval==null){R=aa/(this.numberTicks-1);if(R<1){Y=Math.pow(10,Math.abs(Math.floor(Math.log(R)/Math.LN10)))}else{Y=1}this.tickInterval=Math.ceil(R*Y*this.pad)/Y}else{Y=1/this.tickInterval}Q=this.tickInterval*(this.numberTicks-1);X=(Q-aa)/2;if(this.min==null){this.min=Math.floor(Y*(aJ-X))/Y}if(this.max==null){this.max=this.min+Q}}}}else{aw=(this.min!=null)?this.min:aJ-aa*(this.padMin-1);ad=(this.max!=null)?this.max:al+aa*(this.padMax-1);this.min=aw;this.max=ad;aa=this.max-this.min;if(this.numberTicks==null){if(this.tickInterval!=null){this.numberTicks=Math.ceil((this.max-this.min)/this.tickInterval)+1;this.max=this.min+this.tickInterval*(this.numberTicks-1)}else{if(O>100){this.numberTicks=parseInt(3+(O-100)/75,10)}else{this.numberTicks=2}}}if(this.tickInterval==null){this.tickInterval=aa/(this.numberTicks-1)}}if(this.renderer.constructor==w.jqplot.LinearAxisRenderer&&this._autoFormatString==""){aa=this.max-this.min;var aK=new this.tickRenderer(this.tickOptions);var ao=aK.formatString||w.jqplot.config.defaultTickFormatString;var ao=ao.match(w.jqplot.sprintf.regex)[0];var aG=0;if(ao){if(ao.search(/[fFeEgGpP]/)>-1){var aC=ao.match(/\%\.(\d{0,})?[eEfFgGpP]/);if(aC){aG=parseInt(aC[1],10)}else{aG=6}}else{if(ao.search(/[di]/)>-1){aG=0}}var W=Math.pow(10,-aG);if(this.tickInterval<W){if(aA==null&&aM==null){this.tickInterval=W;if(aI==null&&ak==null){this.min=Math.floor(this._dataBounds.min/W)*W;if(this.min==this._dataBounds.min){this.min=this._dataBounds.min-this.tickInterval}this.max=Math.ceil(this._dataBounds.max/W)*W;if(this.max==this._dataBounds.max){this.max=this._dataBounds.max+this.tickInterval}var aB=(this.max-this.min)/this.tickInterval;aB=aB.toFixed(11);aB=Math.ceil(aB);this.numberTicks=aB+1}else{if(aI==null){var aB=(this._dataBounds.max-this.min)/this.tickInterval;aB=aB.toFixed(11);this.numberTicks=Math.ceil(aB)+2;this.max=this.min+this.tickInterval*(this.numberTicks-1)}else{if(ak==null){var aB=(this.max-this._dataBounds.min)/this.tickInterval;aB=aB.toFixed(11);this.numberTicks=Math.ceil(aB)+2;this.min=this.max-this.tickInterval*(this.numberTicks-1)}else{this.numberTicks=Math.ceil((aI-ak)/this.tickInterval)+1;this.min=Math.floor(ak*Math.pow(10,aG))/Math.pow(10,aG);this.max=Math.ceil(aI*Math.pow(10,aG))/Math.pow(10,aG);this.numberTicks=Math.ceil((this.max-this.min)/this.tickInterval)+1}}}}}}}}if(this._overrideFormatString&&this._autoFormatString!=""){this.tickOptions=this.tickOptions||{};this.tickOptions.formatString=this._autoFormatString}for(var aE=0;aE<this.numberTicks;aE++){aH=this.min+aE*this.tickInterval;var ay=new this.tickRenderer(this.tickOptions);ay.setTick(aH,this.name);this._ticks.push(ay);ay=null}}ax=null};w.jqplot.LinearAxisRenderer.prototype.resetTickValues=function(Q){if(w.isArray(Q)&&Q.length==this._ticks.length){var P;for(var O=0;O<Q.length;O++){P=this._ticks[O];P.value=Q[O];P.label=P.formatter(P.formatString,Q[O]);P.label=P.prefix+P.label;P._elem.html(P.label)}P=null;this.min=w.jqplot.arrayMin(Q);this.max=w.jqplot.arrayMax(Q);this.pack()}};w.jqplot.LinearAxisRenderer.prototype.pack=function(Q,P){Q=Q||{};P=P||this._offsets;var ae=this._ticks;var aa=this.max;var Z=this.min;var V=P.max;var T=P.min;var X=(this._label==null)?false:this._label.show;for(var Y in Q){this._elem.css(Y,Q[Y])}this._offsets=P;var R=V-T;var S=aa-Z;if(this.breakPoints){S=S-this.breakPoints[1]+this.breakPoints[0];this.p2u=function(ag){return(ag-T)*S/R+Z};this.u2p=function(ag){if(ag>this.breakPoints[0]&&ag<this.breakPoints[1]){ag=this.breakPoints[0]}if(ag<=this.breakPoints[0]){return(ag-Z)*R/S+T}else{return(ag-this.breakPoints[1]+this.breakPoints[0]-Z)*R/S+T}};if(this.name.charAt(0)=="x"){this.series_u2p=function(ag){if(ag>this.breakPoints[0]&&ag<this.breakPoints[1]){ag=this.breakPoints[0]}if(ag<=this.breakPoints[0]){return(ag-Z)*R/S}else{return(ag-this.breakPoints[1]+this.breakPoints[0]-Z)*R/S}};this.series_p2u=function(ag){return ag*S/R+Z}}else{this.series_u2p=function(ag){if(ag>this.breakPoints[0]&&ag<this.breakPoints[1]){ag=this.breakPoints[0]}if(ag>=this.breakPoints[1]){return(ag-aa)*R/S}else{return(ag+this.breakPoints[1]-this.breakPoints[0]-aa)*R/S}};this.series_p2u=function(ag){return ag*S/R+aa}}}else{this.p2u=function(ag){return(ag-T)*S/R+Z};this.u2p=function(ag){return(ag-Z)*R/S+T};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(ag){return(ag-Z)*R/S};this.series_p2u=function(ag){return ag*S/R+Z}}else{this.series_u2p=function(ag){return(ag-aa)*R/S};this.series_p2u=function(ag){return ag*S/R+aa}}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(var ab=0;ab<ae.length;ab++){var W=ae[ab];if(W.show&&W.showLabel){var O;if(W.constructor==w.jqplot.CanvasAxisTickRenderer&&W.angle){var ad=(this.name=="xaxis")?1:-1;switch(W.labelPosition){case"auto":if(ad*W.angle<0){O=-W.getWidth()+W._textRenderer.height*Math.sin(-W._textRenderer.angle)/2}else{O=-W._textRenderer.height*Math.sin(W._textRenderer.angle)/2}break;case"end":O=-W.getWidth()+W._textRenderer.height*Math.sin(-W._textRenderer.angle)/2;break;case"start":O=-W._textRenderer.height*Math.sin(W._textRenderer.angle)/2;break;case"middle":O=-W.getWidth()/2+W._textRenderer.height*Math.sin(-W._textRenderer.angle)/2;break;default:O=-W.getWidth()/2+W._textRenderer.height*Math.sin(-W._textRenderer.angle)/2;break}}else{O=-W.getWidth()/2}var af=this.u2p(W.value)+O+"px";W._elem.css("left",af);W.pack()}}if(X){var U=this._label._elem.outerWidth(true);this._label._elem.css("left",T+R/2-U/2+"px");if(this.name=="xaxis"){this._label._elem.css("bottom","0px")}else{this._label._elem.css("top","0px")}this._label.pack()}}else{for(var ab=0;ab<ae.length;ab++){var W=ae[ab];if(W.show&&W.showLabel){var O;if(W.constructor==w.jqplot.CanvasAxisTickRenderer&&W.angle){var ad=(this.name=="yaxis")?1:-1;switch(W.labelPosition){case"auto":case"end":if(ad*W.angle<0){O=-W._textRenderer.height*Math.cos(-W._textRenderer.angle)/2}else{O=-W.getHeight()+W._textRenderer.height*Math.cos(W._textRenderer.angle)/2}break;case"start":if(W.angle>0){O=-W._textRenderer.height*Math.cos(-W._textRenderer.angle)/2}else{O=-W.getHeight()+W._textRenderer.height*Math.cos(W._textRenderer.angle)/2}break;case"middle":O=-W.getHeight()/2;break;default:O=-W.getHeight()/2;break}}else{O=-W.getHeight()/2}var af=this.u2p(W.value)+O+"px";W._elem.css("top",af);W.pack()}}if(X){var ac=this._label._elem.outerHeight(true);this._label._elem.css("top",V-R/2-ac/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{this._label._elem.css("right","0px")}this._label.pack()}}}ae=null};function e(O){O=Math.abs(O);if(O>1){return"%d"}var P=-Math.floor(Math.log(O)/Math.LN10);return"%."+P+"f"}function B(P,O){var Q=Math.floor(Math.log(P)/Math.LN10);var S=Math.pow(10,Q);var R=P/S;R=R/O;if(R<=0.38){return 0.1*S}if(R<=1.6){return 0.2*S}if(R<=4){return 0.5*S}if(R<=8){return S}if(R<=16){return 2*S}return 5*S}w.jqplot.LinearTickGenerator=function(Q,T,P){if(Q==T){T=(T)?0:1}P=P||1;if(T<Q){var O=T;T=Q;Q=O}var R=B(T-Q,P);var S=[];S[0]=Math.floor(Q/R)*R;S[1]=Math.ceil(T/R)*R;S[2]=Math.round((S[1]-S[0])/R+1);S[3]=e(R);S[4]=R;return S};w.jqplot.MarkerRenderer=function(O){this.show=true;this.style="filledCircle";this.lineWidth=2;this.size=9;this.color="#666666";this.shadow=true;this.shadowAngle=45;this.shadowOffset=1;this.shadowDepth=3;this.shadowAlpha="0.07";this.shadowRenderer=new w.jqplot.ShadowRenderer();this.shapeRenderer=new w.jqplot.ShapeRenderer();w.extend(true,this,O)};w.jqplot.MarkerRenderer.prototype.init=function(O){w.extend(true,this,O);var Q={angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,lineWidth:this.lineWidth,depth:this.shadowDepth,closePath:true};if(this.style.indexOf("filled")!=-1){Q.fill=true}if(this.style.indexOf("ircle")!=-1){Q.isarc=true;Q.closePath=false}this.shadowRenderer.init(Q);var P={fill:false,isarc:false,strokeStyle:this.color,fillStyle:this.color,lineWidth:this.lineWidth,closePath:true};if(this.style.indexOf("filled")!=-1){P.fill=true}if(this.style.indexOf("ircle")!=-1){P.isarc=true;P.closePath=false}this.shapeRenderer.init(P)};w.jqplot.MarkerRenderer.prototype.drawDiamond=function(Q,P,T,S,V){var O=1.2;var W=this.size/2/O;var U=this.size/2*O;var R=[[Q-W,P],[Q,P+U],[Q+W,P],[Q,P-U]];if(this.shadow){this.shadowRenderer.draw(T,R)}this.shapeRenderer.draw(T,R,V)};w.jqplot.MarkerRenderer.prototype.drawPlus=function(R,Q,U,T,X){var P=1;var Y=this.size/2*P;var V=this.size/2*P;var W=[[R,Q-V],[R,Q+V]];var S=[[R+Y,Q],[R-Y,Q]];var O=w.extend(true,{},this.options,{closePath:false});if(this.shadow){this.shadowRenderer.draw(U,W,{closePath:false});this.shadowRenderer.draw(U,S,{closePath:false})}this.shapeRenderer.draw(U,W,O);this.shapeRenderer.draw(U,S,O)};w.jqplot.MarkerRenderer.prototype.drawX=function(R,Q,U,T,X){var P=1;var Y=this.size/2*P;var V=this.size/2*P;var O=w.extend(true,{},this.options,{closePath:false});var W=[[R-Y,Q-V],[R+Y,Q+V]];var S=[[R-Y,Q+V],[R+Y,Q-V]];if(this.shadow){this.shadowRenderer.draw(U,W,{closePath:false});this.shadowRenderer.draw(U,S,{closePath:false})}this.shapeRenderer.draw(U,W,O);this.shapeRenderer.draw(U,S,O)};w.jqplot.MarkerRenderer.prototype.drawDash=function(Q,P,T,S,V){var O=1;var W=this.size/2*O;var U=this.size/2*O;var R=[[Q-W,P],[Q+W,P]];if(this.shadow){this.shadowRenderer.draw(T,R)}this.shapeRenderer.draw(T,R,V)};w.jqplot.MarkerRenderer.prototype.drawLine=function(T,S,O,R,P){var Q=[T,S];if(this.shadow){this.shadowRenderer.draw(O,Q)}this.shapeRenderer.draw(O,Q,P)};w.jqplot.MarkerRenderer.prototype.drawSquare=function(Q,P,T,S,V){var O=1;var W=this.size/2/O;var U=this.size/2*O;var R=[[Q-W,P-U],[Q-W,P+U],[Q+W,P+U],[Q+W,P-U]];if(this.shadow){this.shadowRenderer.draw(T,R)}this.shapeRenderer.draw(T,R,V)};w.jqplot.MarkerRenderer.prototype.drawCircle=function(P,V,R,U,S){var O=this.size/2;var Q=2*Math.PI;var T=[P,V,O,0,Q,true];if(this.shadow){this.shadowRenderer.draw(R,T)}this.shapeRenderer.draw(R,T,S)};w.jqplot.MarkerRenderer.prototype.draw=function(O,R,P,Q){Q=Q||{};if(Q.show==null||Q.show!=false){if(Q.color&&!Q.fillStyle){Q.fillStyle=Q.color}if(Q.color&&!Q.strokeStyle){Q.strokeStyle=Q.color}switch(this.style){case"diamond":this.drawDiamond(O,R,P,false,Q);break;case"filledDiamond":this.drawDiamond(O,R,P,true,Q);break;case"circle":this.drawCircle(O,R,P,false,Q);break;case"filledCircle":this.drawCircle(O,R,P,true,Q);break;case"square":this.drawSquare(O,R,P,false,Q);break;case"filledSquare":this.drawSquare(O,R,P,true,Q);break;case"x":this.drawX(O,R,P,true,Q);break;case"plus":this.drawPlus(O,R,P,true,Q);break;case"dash":this.drawDash(O,R,P,true,Q);break;case"line":this.drawLine(O,R,P,false,Q);break;default:this.drawDiamond(O,R,P,false,Q);break}}};w.jqplot.ShadowRenderer=function(O){this.angle=45;this.offset=1;this.alpha=0.07;this.lineWidth=1.5;this.lineJoin="miter";this.lineCap="round";this.closePath=false;this.fill=false;this.depth=3;this.strokeStyle="rgba(0,0,0,0.1)";this.isarc=false;w.extend(true,this,O)};w.jqplot.ShadowRenderer.prototype.init=function(O){w.extend(true,this,O)};w.jqplot.ShadowRenderer.prototype.draw=function(Y,W,aa){Y.save();var O=(aa!=null)?aa:{};var X=(O.fill!=null)?O.fill:this.fill;var V=(O.closePath!=null)?O.closePath:this.closePath;var S=(O.offset!=null)?O.offset:this.offset;var Q=(O.alpha!=null)?O.alpha:this.alpha;var U=(O.depth!=null)?O.depth:this.depth;var Z=(O.isarc!=null)?O.isarc:this.isarc;Y.lineWidth=(O.lineWidth!=null)?O.lineWidth:this.lineWidth;Y.lineJoin=(O.lineJoin!=null)?O.lineJoin:this.lineJoin;Y.lineCap=(O.lineCap!=null)?O.lineCap:this.lineCap;Y.strokeStyle=O.strokeStyle||this.strokeStyle||"rgba(0,0,0,"+Q+")";Y.fillStyle=O.fillStyle||this.fillStyle||"rgba(0,0,0,"+Q+")";for(var R=0;R<U;R++){Y.translate(Math.cos(this.angle*Math.PI/180)*S,Math.sin(this.angle*Math.PI/180)*S);Y.beginPath();if(Z){Y.arc(W[0],W[1],W[2],W[3],W[4],true)}else{if(W&&W.length){var P=true;for(var T=0;T<W.length;T++){if(W[T][0]!=null&&W[T][1]!=null){if(P){Y.moveTo(W[T][0],W[T][1]);P=false}else{Y.lineTo(W[T][0],W[T][1])}}else{P=true}}}}if(V){Y.closePath()}if(X){Y.fill()}else{Y.stroke()}}Y.restore()};w.jqplot.ShapeRenderer=function(O){this.lineWidth=1.5;this.lineJoin="miter";this.lineCap="round";this.closePath=false;this.fill=false;this.isarc=false;this.fillRect=false;this.strokeRect=false;this.clearRect=false;this.strokeStyle="#999999";this.fillStyle="#999999";w.extend(true,this,O)};w.jqplot.ShapeRenderer.prototype.init=function(O){w.extend(true,this,O)};w.jqplot.ShapeRenderer.prototype.draw=function(X,V,Z){X.save();var O=(Z!=null)?Z:{};var W=(O.fill!=null)?O.fill:this.fill;var T=(O.closePath!=null)?O.closePath:this.closePath;var U=(O.fillRect!=null)?O.fillRect:this.fillRect;var R=(O.strokeRect!=null)?O.strokeRect:this.strokeRect;var P=(O.clearRect!=null)?O.clearRect:this.clearRect;var Y=(O.isarc!=null)?O.isarc:this.isarc;X.lineWidth=O.lineWidth||this.lineWidth;X.lineJoin=O.lineJoin||this.lineJoin;X.lineCap=O.lineCap||this.lineCap;X.strokeStyle=(O.strokeStyle||O.color)||this.strokeStyle;X.fillStyle=O.fillStyle||this.fillStyle;X.beginPath();if(Y){X.arc(V[0],V[1],V[2],V[3],V[4],true);if(T){X.closePath()}if(W){X.fill()}else{X.stroke()}X.restore();return}else{if(P){X.clearRect(V[0],V[1],V[2],V[3]);X.restore();return}else{if(U||R){if(U){X.fillRect(V[0],V[1],V[2],V[3])}if(R){X.strokeRect(V[0],V[1],V[2],V[3]);X.restore();return}}else{if(V&&V.length){var Q=true;for(var S=0;S<V.length;S++){if(V[S][0]!=null&&V[S][1]!=null){if(Q){X.moveTo(V[S][0],V[S][1]);Q=false}else{X.lineTo(V[S][0],V[S][1])}}else{Q=true}}if(T){X.closePath()}if(W){X.fill()}else{X.stroke()}}}}}X.restore()};w.jqplot.TableLegendRenderer=function(){};w.jqplot.TableLegendRenderer.prototype.init=function(O){w.extend(true,this,O)};w.jqplot.TableLegendRenderer.prototype.addrow=function(X,R,O,V){var S=(O)?this.rowSpacing+"px":"0px";var W;var Q;var P;var U;var T;P=document.createElement("tr");W=w(P);W.addClass("jqplot-table-legend");P=null;if(V){W.prependTo(this._elem)}else{W.appendTo(this._elem)}if(this.showSwatches){Q=w(document.createElement("td"));Q.addClass("jqplot-table-legend");Q.css({textAlign:"center",paddingTop:S});U=w(document.createElement("div"));T=w(document.createElement("div"));T.addClass("jqplot-table-legend-swatch");T.css({backgroundColor:R,borderColor:R});W.append(Q.append(U.append(T)))}if(this.showLabels){Q=w(document.createElement("td"));Q.addClass("jqplot-table-legend");Q.css("paddingTop",S);W.append(Q);if(this.escapeHtml){Q.text(X)}else{Q.html(X)}}Q=null;U=null;T=null;W=null;P=null};w.jqplot.TableLegendRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}if(this.show){var T=this._series;var P=document.createElement("table");this._elem=w(P);this._elem.addClass("jqplot-table-legend");var Y={position:"absolute"};if(this.background){Y.background=this.background}if(this.border){Y.border=this.border}if(this.fontSize){Y.fontSize=this.fontSize}if(this.fontFamily){Y.fontFamily=this.fontFamily}if(this.textColor){Y.textColor=this.textColor}if(this.marginTop!=null){Y.marginTop=this.marginTop}if(this.marginBottom!=null){Y.marginBottom=this.marginBottom}if(this.marginLeft!=null){Y.marginLeft=this.marginLeft}if(this.marginRight!=null){Y.marginRight=this.marginRight}var O=false,V=false,X;for(var U=0;U<T.length;U++){X=T[U];if(X._stack||X.renderer.constructor==w.jqplot.BezierCurveRenderer){V=true}if(X.show&&X.showLabel){var S=this.labels[U]||X.label.toString();if(S){var Q=X.color;if(V&&U<T.length-1){O=true}else{if(V&&U==T.length-1){O=false}}this.renderer.addrow.call(this,S,Q,O,V);O=true}for(var R=0;R<w.jqplot.addLegendRowHooks.length;R++){var W=w.jqplot.addLegendRowHooks[R].call(this,X);if(W){this.renderer.addrow.call(this,W.label,W.color,O);O=true}}S=null}}}return this._elem};w.jqplot.TableLegendRenderer.prototype.pack=function(Q){if(this.show){if(this.placement=="insideGrid"){switch(this.location){case"nw":var P=Q.left;var O=Q.top;this._elem.css("left",P);this._elem.css("top",O);break;case"n":var P=(Q.left+(this._plotDimensions.width-Q.right))/2-this.getWidth()/2;var O=Q.top;this._elem.css("left",P);this._elem.css("top",O);break;case"ne":var P=Q.right;var O=Q.top;this._elem.css({right:P,top:O});break;case"e":var P=Q.right;var O=(Q.top+(this._plotDimensions.height-Q.bottom))/2-this.getHeight()/2;this._elem.css({right:P,top:O});break;case"se":var P=Q.right;var O=Q.bottom;this._elem.css({right:P,bottom:O});break;case"s":var P=(Q.left+(this._plotDimensions.width-Q.right))/2-this.getWidth()/2;var O=Q.bottom;this._elem.css({left:P,bottom:O});break;case"sw":var P=Q.left;var O=Q.bottom;this._elem.css({left:P,bottom:O});break;case"w":var P=Q.left;var O=(Q.top+(this._plotDimensions.height-Q.bottom))/2-this.getHeight()/2;this._elem.css({left:P,top:O});break;default:var P=Q.right;var O=Q.bottom;this._elem.css({right:P,bottom:O});break}}else{if(this.placement=="outside"){switch(this.location){case"nw":var P=this._plotDimensions.width-Q.left;var O=Q.top;this._elem.css("right",P);this._elem.css("top",O);break;case"n":var P=(Q.left+(this._plotDimensions.width-Q.right))/2-this.getWidth()/2;var O=this._plotDimensions.height-Q.top;this._elem.css("left",P);this._elem.css("bottom",O);break;case"ne":var P=this._plotDimensions.width-Q.right;var O=Q.top;this._elem.css({left:P,top:O});break;case"e":var P=this._plotDimensions.width-Q.right;var O=(Q.top+(this._plotDimensions.height-Q.bottom))/2-this.getHeight()/2;this._elem.css({left:P,top:O});break;case"se":var P=this._plotDimensions.width-Q.right;var O=Q.bottom;this._elem.css({left:P,bottom:O});break;case"s":var P=(Q.left+(this._plotDimensions.width-Q.right))/2-this.getWidth()/2;var O=this._plotDimensions.height-Q.bottom;this._elem.css({left:P,top:O});break;case"sw":var P=this._plotDimensions.width-Q.left;var O=Q.bottom;this._elem.css({right:P,bottom:O});break;case"w":var P=this._plotDimensions.width-Q.left;var O=(Q.top+(this._plotDimensions.height-Q.bottom))/2-this.getHeight()/2;this._elem.css({right:P,top:O});break;default:var P=Q.right;var O=Q.bottom;this._elem.css({right:P,bottom:O});break}}else{switch(this.location){case"nw":this._elem.css({left:0,top:Q.top});break;case"n":var P=(Q.left+(this._plotDimensions.width-Q.right))/2-this.getWidth()/2;this._elem.css({left:P,top:Q.top});break;case"ne":this._elem.css({right:0,top:Q.top});break;case"e":var O=(Q.top+(this._plotDimensions.height-Q.bottom))/2-this.getHeight()/2;this._elem.css({right:Q.right,top:O});break;case"se":this._elem.css({right:Q.right,bottom:Q.bottom});break;case"s":var P=(Q.left+(this._plotDimensions.width-Q.right))/2-this.getWidth()/2;this._elem.css({left:P,bottom:Q.bottom});break;case"sw":this._elem.css({left:Q.left,bottom:Q.bottom});break;case"w":var O=(Q.top+(this._plotDimensions.height-Q.bottom))/2-this.getHeight()/2;this._elem.css({left:Q.left,top:O});break;default:this._elem.css({right:Q.right,bottom:Q.bottom});break}}}}};w.jqplot.ThemeEngine=function(){this.themes={};this.activeTheme=null};w.jqplot.ThemeEngine.prototype.init=function(){var R=new w.jqplot.Theme({_name:"Default"});var U,P,T;for(U in R.target){if(U=="textColor"){R.target[U]=this.target.css("color")}else{R.target[U]=this.target.css(U)}}if(this.title.show&&this.title._elem){for(U in R.title){if(U=="textColor"){R.title[U]=this.title._elem.css("color")}else{R.title[U]=this.title._elem.css(U)}}}for(U in R.grid){R.grid[U]=this.grid[U]}if(R.grid.backgroundColor==null&&this.grid.background!=null){R.grid.backgroundColor=this.grid.background}if(this.legend.show&&this.legend._elem){for(U in R.legend){if(U=="textColor"){R.legend[U]=this.legend._elem.css("color")}else{R.legend[U]=this.legend._elem.css(U)}}}var Q;for(P=0;P<this.series.length;P++){Q=this.series[P];if(Q.renderer.constructor==w.jqplot.LineRenderer){R.series.push(new i())}else{if(Q.renderer.constructor==w.jqplot.BarRenderer){R.series.push(new E())}else{if(Q.renderer.constructor==w.jqplot.PieRenderer){R.series.push(new b())}else{if(Q.renderer.constructor==w.jqplot.DonutRenderer){R.series.push(new t())}else{if(Q.renderer.constructor==w.jqplot.FunnelRenderer){R.series.push(new H())}else{if(Q.renderer.constructor==w.jqplot.MeterGaugeRenderer){R.series.push(new r())}else{R.series.push({})}}}}}}for(U in R.series[P]){R.series[P][U]=Q[U]}}var O,S;for(U in this.axes){S=this.axes[U];O=R.axes[U]=new A();O.borderColor=S.borderColor;O.borderWidth=S.borderWidth;if(S._ticks&&S._ticks[0]){for(T in O.ticks){if(S._ticks[0].hasOwnProperty(T)){O.ticks[T]=S._ticks[0][T]}else{if(S._ticks[0]._elem){O.ticks[T]=S._ticks[0]._elem.css(T)}}}}if(S._label&&S._label.show){for(T in O.label){if(S._label[T]){O.label[T]=S._label[T]}else{if(S._label._elem){if(T=="textColor"){O.label[T]=S._label._elem.css("color")}else{O.label[T]=S._label._elem.css(T)}}}}}}this.themeEngine._add(R);this.themeEngine.activeTheme=this.themeEngine.themes[R._name]};w.jqplot.ThemeEngine.prototype.get=function(O){if(!O){return this.activeTheme}else{return this.themes[O]}};function z(P,O){return P-O}w.jqplot.ThemeEngine.prototype.getThemeNames=function(){var O=[];for(var P in this.themes){O.push(P)}return O.sort(z)};w.jqplot.ThemeEngine.prototype.getThemes=function(){var P=[];var O=[];for(var R in this.themes){P.push(R)}P.sort(z);for(var Q=0;Q<P.length;Q++){O.push(this.themes[P[Q]])}return O};w.jqplot.ThemeEngine.prototype.activate=function(ab,ag){var O=false;if(!ag&&this.activeTheme&&this.activeTheme._name){ag=this.activeTheme._name}if(!this.themes.hasOwnProperty(ag)){throw new Error("No theme of that name")}else{var T=this.themes[ag];this.activeTheme=T;var af,Z=false,Y=false;var P=["xaxis","x2axis","yaxis","y2axis"];for(ac=0;ac<P.length;ac++){var U=P[ac];if(T.axesStyles.borderColor!=null){ab.axes[U].borderColor=T.axesStyles.borderColor}if(T.axesStyles.borderWidth!=null){ab.axes[U].borderWidth=T.axesStyles.borderWidth}}for(var ae in ab.axes){var R=ab.axes[ae];if(R.show){var X=T.axes[ae]||{};var V=T.axesStyles;var S=w.jqplot.extend(true,{},X,V);af=(T.axesStyles.borderColor!=null)?T.axesStyles.borderColor:S.borderColor;if(S.borderColor!=null){R.borderColor=S.borderColor;O=true}af=(T.axesStyles.borderWidth!=null)?T.axesStyles.borderWidth:S.borderWidth;if(S.borderWidth!=null){R.borderWidth=S.borderWidth;O=true}if(R._ticks&&R._ticks[0]){for(var Q in S.ticks){af=S.ticks[Q];if(af!=null){R.tickOptions[Q]=af;R._ticks=[];O=true}}}if(R._label&&R._label.show){for(var Q in S.label){af=S.label[Q];if(af!=null){R.labelOptions[Q]=af;O=true}}}}}for(var aa in T.grid){if(T.grid[aa]!=null){ab.grid[aa]=T.grid[aa]}}if(!O){ab.grid.draw()}if(ab.legend.show){for(aa in T.legend){if(T.legend[aa]!=null){ab.legend[aa]=T.legend[aa]}}}if(ab.title.show){for(aa in T.title){if(T.title[aa]!=null){ab.title[aa]=T.title[aa]}}}var ac;for(ac=0;ac<T.series.length;ac++){var W={};var ad=false;for(aa in T.series[ac]){af=(T.seriesStyles[aa]!=null)?T.seriesStyles[aa]:T.series[ac][aa];if(af!=null){W[aa]=af;if(aa=="color"){ab.series[ac].renderer.shapeRenderer.fillStyle=af;ab.series[ac].renderer.shapeRenderer.strokeStyle=af;ab.series[ac][aa]=af}else{if(aa=="lineWidth"){ab.series[ac].renderer.shapeRenderer.lineWidth=af;ab.series[ac][aa]=af}else{if(aa=="markerOptions"){F(ab.series[ac].markerOptions,af);F(ab.series[ac].markerRenderer,af)}else{ab.series[ac][aa]=af}}}O=true}}}if(O){ab.target.empty();ab.draw()}for(aa in T.target){if(T.target[aa]!=null){ab.target.css(aa,T.target[aa])}}}};w.jqplot.ThemeEngine.prototype._add=function(P,O){if(O){P._name=O}if(!P._name){P._name=Date.parse(new Date())}if(!this.themes.hasOwnProperty(P._name)){this.themes[P._name]=P}else{throw new Error("jqplot.ThemeEngine Error: Theme already in use")}};w.jqplot.ThemeEngine.prototype.remove=function(O){if(O=="Default"){return false}return delete this.themes[O]};w.jqplot.ThemeEngine.prototype.newTheme=function(O,Q){if(typeof(O)=="object"){Q=Q||O;O=null}if(Q&&Q._name){O=Q._name}else{O=O||Date.parse(new Date())}var P=this.copy(this.themes.Default._name,O);w.jqplot.extend(P,Q);return P};function p(Q){if(Q==null||typeof(Q)!="object"){return Q}var O=new Q.constructor();for(var P in Q){O[P]=p(Q[P])}return O}w.jqplot.clone=p;function F(Q,P){if(P==null||typeof(P)!="object"){return}for(var O in P){if(O=="highlightColors"){Q[O]=p(P[O])}if(P[O]!=null&&typeof(P[O])=="object"){if(!Q.hasOwnProperty(O)){Q[O]={}}F(Q[O],P[O])}else{Q[O]=P[O]}}}w.jqplot.merge=F;w.jqplot.extend=function(){var T=arguments[0]||{},R=1,S=arguments.length,O=false,Q;if(typeof T==="boolean"){O=T;T=arguments[1]||{};R=2}if(typeof T!=="object"&&!toString.call(T)==="[object Function]"){T={}}for(;R<S;R++){if((Q=arguments[R])!=null){for(var P in Q){var U=T[P],V=Q[P];if(T===V){continue}if(O&&V&&typeof V==="object"&&!V.nodeType){T[P]=w.jqplot.extend(O,U||(V.length!=null?[]:{}),V)}else{if(V!==l){T[P]=V}}}}}return T};w.jqplot.ThemeEngine.prototype.rename=function(P,O){if(P=="Default"||O=="Default"){throw new Error("jqplot.ThemeEngine Error: Cannot rename from/to Default")}if(this.themes.hasOwnProperty(O)){throw new Error("jqplot.ThemeEngine Error: New name already in use.")}else{if(this.themes.hasOwnProperty(P)){var Q=this.copy(P,O);this.remove(P);return Q}}throw new Error("jqplot.ThemeEngine Error: Old name or new name invalid")};w.jqplot.ThemeEngine.prototype.copy=function(O,Q,S){if(Q=="Default"){throw new Error("jqplot.ThemeEngine Error: Cannot copy over Default theme")}if(!this.themes.hasOwnProperty(O)){var P="jqplot.ThemeEngine Error: Source name invalid";throw new Error(P)}if(this.themes.hasOwnProperty(Q)){var P="jqplot.ThemeEngine Error: Target name invalid";throw new Error(P)}else{var R=p(this.themes[O]);R._name=Q;w.jqplot.extend(true,R,S);this._add(R);return R}};w.jqplot.Theme=function(O,P){if(typeof(O)=="object"){P=P||O;O=null}O=O||Date.parse(new Date());this._name=O;this.target={backgroundColor:null};this.legend={textColor:null,fontFamily:null,fontSize:null,border:null,background:null};this.title={textColor:null,fontFamily:null,fontSize:null,textAlign:null};this.seriesStyles={};this.series=[];this.grid={drawGridlines:null,gridLineColor:null,gridLineWidth:null,backgroundColor:null,borderColor:null,borderWidth:null,shadow:null};this.axesStyles={label:{},ticks:{}};this.axes={};if(typeof(P)=="string"){this._name=P}else{if(typeof(P)=="object"){w.jqplot.extend(true,this,P)}}};var A=function(){this.borderColor=null;this.borderWidth=null;this.ticks=new g();this.label=new k()};var g=function(){this.show=null;this.showGridline=null;this.showLabel=null;this.showMark=null;this.size=null;this.textColor=null;this.whiteSpace=null;this.fontSize=null;this.fontFamily=null};var k=function(){this.textColor=null;this.whiteSpace=null;this.fontSize=null;this.fontFamily=null;this.fontWeight=null};var i=function(){this.color=null;this.lineWidth=null;this.shadow=null;this.fillColor=null;this.showMarker=null;this.markerOptions=new v()};var v=function(){this.show=null;this.style=null;this.lineWidth=null;this.size=null;this.color=null;this.shadow=null};var E=function(){this.color=null;this.seriesColors=null;this.lineWidth=null;this.shadow=null;this.barPadding=null;this.barMargin=null;this.barWidth=null;this.highlightColors=null};var b=function(){this.seriesColors=null;this.padding=null;this.sliceMargin=null;this.fill=null;this.shadow=null;this.startAngle=null;this.lineWidth=null;this.highlightColors=null};var t=function(){this.seriesColors=null;this.padding=null;this.sliceMargin=null;this.fill=null;this.shadow=null;this.startAngle=null;this.lineWidth=null;this.innerDiameter=null;this.thickness=null;this.ringMargin=null;this.highlightColors=null};var H=function(){this.color=null;this.lineWidth=null;this.shadow=null;this.padding=null;this.sectionMargin=null;this.seriesColors=null;this.highlightColors=null};var r=function(){this.padding=null;this.backgroundColor=null;this.ringColor=null;this.tickColor=null;this.ringWidth=null;this.intervalColors=null;this.intervalInnerRadius=null;this.intervalOuterRadius=null;this.hubRadius=null;this.needleThickness=null;this.needlePad=null};var N=function(){this.syntax=N.config.syntax;this._type="jsDate";this.utcOffset=new Date().getTimezoneOffset*60000;this.proxy=new Date();this.options={};this.locale=N.regional.getLocale();this.formatString="";this.defaultCentury=N.config.defaultCentury;switch(arguments.length){case 0:break;case 1:if(f(arguments[0])=="[object Object]"&&arguments[0]._type!="jsDate"){var Q=this.options=arguments[0];this.syntax=Q.syntax||this.syntax;this.defaultCentury=Q.defaultCentury||this.defaultCentury;this.proxy=N.createDate(Q.date)}else{this.proxy=N.createDate(arguments[0])}break;default:var O=[];for(var P=0;P<arguments.length;P++){O.push(arguments[P])}this.proxy=new Date(this.utcOffset);this.proxy.setFullYear.apply(this.proxy,O.slice(0,3));if(O.slice(3).length){this.proxy.setHours.apply(this.proxy,O.slice(3))}break}};N.config={defaultLocale:"en",syntax:"perl",defaultCentury:1900};N.prototype.add=function(Q,P){var O=s[P]||s.day;if(typeof O=="number"){this.proxy.setTime(this.proxy.getTime()+(O*Q))}else{O.add(this,Q)}return this};N.prototype.clone=function(){return new N(this.proxy.getTime())};N.prototype.diff=function(P,S,O){P=new N(P);if(P===null){return null}var Q=s[S]||s.day;if(typeof Q=="number"){var R=(this.proxy.getTime()-P.proxy.getTime())/Q}else{var R=Q.diff(this.proxy,P.proxy)}return(O?R:Math[R>0?"floor":"ceil"](R))};N.prototype.getAbbrDayName=function(){return N.regional[this.locale]["dayNamesShort"][this.proxy.getDay()]};N.prototype.getAbbrMonthName=function(){return N.regional[this.locale]["monthNamesShort"][this.proxy.getMonth()]};N.prototype.getAMPM=function(){return this.proxy.getHours()>=12?"PM":"AM"};N.prototype.getAmPm=function(){return this.proxy.getHours()>=12?"pm":"am"};N.prototype.getCentury=function(){return parseInt(this.proxy.getFullYear()/100,10)};N.prototype.getDate=function(){return this.proxy.getDate()};N.prototype.getDay=function(){return this.proxy.getDay()};N.prototype.getDayOfWeek=function(){var O=this.proxy.getDay();return O===0?7:O};N.prototype.getDayOfYear=function(){var P=this.proxy;var O=P-new Date(""+P.getFullYear()+"/1/1 GMT");O+=P.getTimezoneOffset()*60000;P=null;return parseInt(O/60000/60/24,10)+1};N.prototype.getDayName=function(){return N.regional[this.locale]["dayNames"][this.proxy.getDay()]};N.prototype.getFullWeekOfYear=function(){var R=this.proxy;var O=this.getDayOfYear();var Q=6-R.getDay();var P=parseInt((O+Q)/7,10);return P};N.prototype.getFullYear=function(){return this.proxy.getFullYear()};N.prototype.getGmtOffset=function(){var O=this.proxy.getTimezoneOffset()/60;var P=O<0?"+":"-";O=Math.abs(O);return P+y(Math.floor(O),2)+":"+y((O%1)*60,2)};N.prototype.getHours=function(){return this.proxy.getHours()};N.prototype.getHours12=function(){var O=this.proxy.getHours();return O>12?O-12:(O==0?12:O)};N.prototype.getIsoWeek=function(){var R=this.proxy;var Q=R.getWeekOfYear();var O=(new Date(""+R.getFullYear()+"/1/1")).getDay();var P=Q+(O>4||O<=1?0:1);if(P==53&&(new Date(""+R.getFullYear()+"/12/31")).getDay()<4){P=1}else{if(P===0){R=new N(new Date(""+(R.getFullYear()-1)+"/12/31"));P=R.getIsoWeek()}}R=null;return P};N.prototype.getMilliseconds=function(){return this.proxy.getMilliseconds()};N.prototype.getMinutes=function(){return this.proxy.getMinutes()};N.prototype.getMonth=function(){return this.proxy.getMonth()};N.prototype.getMonthName=function(){return N.regional[this.locale]["monthNames"][this.proxy.getMonth()]};N.prototype.getMonthNumber=function(){return this.proxy.getMonth()+1};N.prototype.getSeconds=function(){return this.proxy.getSeconds()};N.prototype.getShortYear=function(){return this.proxy.getYear()%100};N.prototype.getTime=function(){return this.proxy.getTime()};N.prototype.getTimezoneAbbr=function(){return this.proxy.toString().replace(/^.*\(([^)]+)\)$/,"$1")};N.prototype.getTimezoneName=function(){var O=/(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString());return O[1]||O[2]||"GMT"+this.getGmtOffset()};N.prototype.getTimezoneOffset=function(){return this.proxy.getTimezoneOffset()};N.prototype.getWeekOfYear=function(){var O=this.getDayOfYear();var Q=7-this.getDayOfWeek();var P=parseInt((O+Q)/7,10);return P};N.prototype.getUnix=function(){return Math.round(this.proxy.getTime()/1000,0)};N.prototype.getYear=function(){return this.proxy.getYear()};N.prototype.next=function(O){O=O||"day";return this.clone().add(1,O)};N.prototype.set=function(){switch(arguments.length){case 0:this.proxy=new Date();break;case 1:if(f(arguments[0])=="[object Object]"&&arguments[0]._type!="jsDate"){var Q=this.options=arguments[0];this.syntax=Q.syntax||this.syntax;this.defaultCentury=Q.defaultCentury||this.defaultCentury;this.proxy=N.createDate(Q.date)}else{this.proxy=N.createDate(arguments[0])}break;default:var O=[];for(var P=0;P<arguments.length;P++){O.push(arguments[P])}this.proxy=new Date(this.utcOffset);this.proxy.setFullYear.apply(this.proxy,O.slice(0,3));if(O.slice(3).length){this.proxy.setHours.apply(this.proxy,O.slice(3))}break}};N.prototype.setDate=function(O){return this.proxy.setDate(O)};N.prototype.setFullYear=function(){return this.proxy.setFullYear.apply(this.proxy,arguments)};N.prototype.setHours=function(){return this.proxy.setHours.apply(this.proxy,arguments)};N.prototype.setMilliseconds=function(O){return this.proxy.setMilliseconds(O)};N.prototype.setMinutes=function(){return this.proxy.setMinutes.apply(this.proxy,arguments)};N.prototype.setMonth=function(){return this.proxy.setMonth.apply(this.proxy,arguments)};N.prototype.setSeconds=function(){return this.proxy.setSeconds.apply(this.proxy,arguments)};N.prototype.setTime=function(O){return this.proxy.setTime(O)};N.prototype.setYear=function(){return this.proxy.setYear.apply(this.proxy,arguments)};N.prototype.strftime=function(O){O=O||this.formatString||N.regional[this.locale]["formatString"];return N.strftime(this,O,this.syntax)};N.prototype.toString=function(){return this.proxy.toString()};N.prototype.toYmdInt=function(){return(this.proxy.getFullYear()*10000)+(this.getMonthNumber()*100)+this.proxy.getDate()};N.regional={en:{monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],formatString:"%Y-%m-%d %H:%M:%S"},fr:{monthNames:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthNamesShort:["Jan","Fév","Mar","Avr","Mai","Jun","Jul","Aoû","Sep","Oct","Nov","Déc"],dayNames:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],dayNamesShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],formatString:"%Y-%m-%d %H:%M:%S"},de:{monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],formatString:"%Y-%m-%d %H:%M:%S"},es:{monthNames:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthNamesShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],dayNames:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"],dayNamesShort:["Dom","Lun","Mar","Mié","Juv","Vie","Sáb"],formatString:"%Y-%m-%d %H:%M:%S"},ru:{monthNames:["Январь","Февраль","Март","Ðпрель","Май","Июнь","Июль","ÐвгуÑÑ‚","СентÑбрь","ОктÑбрь","ÐоÑбрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Ðпр","Май","Июн","Июл","Ðвг","Сен","Окт","ÐоÑ","Дек"],dayNames:["воÑкреÑенье","понедельник","вторник","Ñреда","четверг","пÑтница","Ñуббота"],dayNamesShort:["вÑк","пнд","втр","Ñрд","чтв","птн","Ñбт"],formatString:"%Y-%m-%d %H:%M:%S"},ar:{monthNames:["كانون الثاني","شباط","آذار","نيسان","آذار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["السبت","الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة"],dayNamesShort:["سبت","أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة"],formatString:"%Y-%m-%d %H:%M:%S"},pt:{monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],formatString:"%Y-%m-%d %H:%M:%S"},"pt-BR":{monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],formatString:"%Y-%m-%d %H:%M:%S"}};N.regional["en-US"]=N.regional["en-GB"]=N.regional.en;N.regional.getLocale=function(){var O=N.config.defaultLocale;if(document&&document.getElementsByTagName("html")&&document.getElementsByTagName("html")[0].lang){O=document.getElementsByTagName("html")[0].lang;if(!N.regional.hasOwnProperty(O)){O=N.config.defaultLocale}}return O};var q=24*60*60*1000;var y=function(O,R){O=String(O);var P=R-O.length;var Q=String(Math.pow(10,P)).slice(1);return Q.concat(O)};var s={millisecond:1,second:1000,minute:60*1000,hour:60*60*1000,day:q,week:7*q,month:{add:function(Q,O){s.year.add(Q,Math[O>0?"floor":"ceil"](O/12));var P=Q.getMonth()+(O%12);if(P==12){P=0;Q.setYear(Q.getFullYear()+1)}else{if(P==-1){P=11;Q.setYear(Q.getFullYear()-1)}}Q.setMonth(P)},diff:function(S,Q){var O=S.getFullYear()-Q.getFullYear();var P=S.getMonth()-Q.getMonth()+(O*12);var R=S.getDate()-Q.getDate();return P+(R/30)}},year:{add:function(P,O){P.setYear(P.getFullYear()+Math[O>0?"floor":"ceil"](O))},diff:function(P,O){return s.month.diff(P,O)/12}}};for(var G in s){if(G.substring(G.length-1)!="s"){s[G+"s"]=s[G]}}var u=function(S,R,P){if(N.formats[P]["shortcuts"][R]){return N.strftime(S,N.formats[P]["shortcuts"][R],P)}else{var O=(N.formats[P]["codes"][R]||"").split(".");var Q=S["get"+O[0]]?S["get"+O[0]]():"";if(O[1]){Q=y(Q,O[1])}return Q}};N.strftime=function(U,R,Q,V){var P="perl";var T=N.regional.getLocale();if(Q&&N.formats.hasOwnProperty(Q)){P=Q}else{if(Q&&N.regional.hasOwnProperty(Q)){T=Q}}if(V&&N.formats.hasOwnProperty(V)){P=V}else{if(V&&N.regional.hasOwnProperty(V)){T=V}}if(f(U)!="[object Object]"||U._type!="jsDate"){U=new N(U);U.locale=T}if(!R){R=U.formatString||N.regional[T]["formatString"]}var O=R||"%Y-%m-%d",W="",S;while(O.length>0){if(S=O.match(N.formats[P].codes.matcher)){W+=O.slice(0,S.index);W+=(S[1]||"")+u(U,S[2],P);O=O.slice(S.index+S[0].length)}else{W+=O;O=""}}return W};N.formats={ISO:"%Y-%m-%dT%H:%M:%S.%N%G",SQL:"%Y-%m-%d %H:%M:%S"};N.formats.perl={codes:{matcher:/()%(#?(%|[a-z]))/i,Y:"FullYear",y:"ShortYear.2",m:"MonthNumber.2","#m":"MonthNumber",B:"MonthName",b:"AbbrMonthName",d:"Date.2","#d":"Date",e:"Date",A:"DayName",a:"AbbrDayName",w:"Day",H:"Hours.2","#H":"Hours",I:"Hours12.2","#I":"Hours12",p:"AMPM",M:"Minutes.2","#M":"Minutes",S:"Seconds.2","#S":"Seconds",s:"Unix",N:"Milliseconds.3","#N":"Milliseconds",O:"TimezoneOffset",Z:"TimezoneName",G:"GmtOffset"},shortcuts:{F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",D:"%m/%d/%y","#c":"%a %b %e %H:%M:%S %Y",v:"%e-%b-%Y",R:"%H:%M",r:"%I:%M:%S %p",t:"\t",n:"\n","%":"%"}};N.formats.php={codes:{matcher:/()%((%|[a-z]))/i,a:"AbbrDayName",A:"DayName",d:"Date.2",e:"Date",j:"DayOfYear.3",u:"DayOfWeek",w:"Day",U:"FullWeekOfYear.2",V:"IsoWeek.2",W:"WeekOfYear.2",b:"AbbrMonthName",B:"MonthName",m:"MonthNumber.2",h:"AbbrMonthName",C:"Century.2",y:"ShortYear.2",Y:"FullYear",H:"Hours.2",I:"Hours12.2",l:"Hours12",p:"AMPM",P:"AmPm",M:"Minutes.2",S:"Seconds.2",s:"Unix",O:"TimezoneOffset",z:"GmtOffset",Z:"TimezoneAbbr"},shortcuts:{D:"%m/%d/%y",F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",R:"%H:%M",r:"%I:%M:%S %p",t:"\t",n:"\n","%":"%"}};N.createDate=function(Q){if(Q==null){return new Date()}if(Q instanceof Date){return Q}if(typeof Q=="number"){return new Date(Q)}var V=String(Q).replace(/^\s*(.+)\s*$/g,"$1");V=V.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/,"$1/$2/$3");V=V.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i,"$1 $2 $3");var U=V.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i);if(U&&U.length>3){var Z=parseFloat(U[3]);var T=N.config.defaultCentury+Z;T=String(T);V=V.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i,U[1]+" "+U[2]+" "+T)}U=V.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/);function Y(ad,ac){var ai=parseFloat(ac[1]);var ah=parseFloat(ac[2]);var ag=parseFloat(ac[3]);var af=N.config.defaultCentury;var ab,aa,aj,ae;if(ai>31){aa=ag;aj=ah;ab=af+ai}else{aa=ah;aj=ai;ab=af+ag}ae=aj+"/"+aa+"/"+ab;return ad.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/,ae)}if(U&&U.length>3){V=Y(V,U)}var U=V.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/);if(U&&U.length>3){V=Y(V,U)}var S=0;var P=N.matchers.length;var X,O,W=V;while(S<P){O=Date.parse(W);if(!isNaN(O)){return new Date(O)}X=N.matchers[S];if(typeof X=="function"){var R=X.call(N,W);if(R instanceof Date){return R}}else{W=V.replace(X[0],X[1])}S++}return NaN};N.daysInMonth=function(O,P){if(P==2){return new Date(O,1,29).getDate()==29?29:28}return[l,31,l,31,30,31,30,31,31,30,31,30,31][P]};N.matchers=[[/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/,"$2/$1/$3"],[/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/,"$2/$3/$1"],function(R){var P=R.match(/^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i);if(P){if(P[1]){var Q=this.createDate(P[1]);if(isNaN(Q)){return}}else{var Q=new Date();Q.setMilliseconds(0)}var O=parseFloat(P[2]);if(P[6]){O=P[6].toLowerCase()=="am"?(O==12?0:O):(O==12?12:O+12)}Q.setHours(O,parseInt(P[3]||0,10),parseInt(P[4]||0,10),((parseFloat(P[5]||0))||0)*1000);return Q}else{return R}},function(R){var P=R.match(/^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i);if(P){if(P[1]){var Q=this.createDate(P[1]);if(isNaN(Q)){return}}else{var Q=new Date();Q.setMilliseconds(0)}var O=parseFloat(P[2]);Q.setHours(O,parseInt(P[3],10),parseInt(P[4],10),parseFloat(P[5])*1000);return Q}else{return R}},function(S){var Q=S.match(/^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/);if(Q){var R=new Date();var T=N.config.defaultCentury;var V=parseFloat(Q[1]);var U=parseFloat(Q[3]);var P,O,W;if(V>31){O=U;P=T+V}else{O=V;P=T+U}var W=J(Q[2],N.regional[this.locale]["monthNamesShort"]);if(W==-1){W=J(Q[2],N.regional[this.locale]["monthNames"])}R.setFullYear(P,W,O);R.setHours(0,0,0,0);return R}else{return S}}];function J(Q,R){if(R.indexOf){return R.indexOf(Q)}for(var O=0,P=R.length;O<P;O++){if(R[O]===Q){return O}}return -1}function f(O){if(O===null){return"[object Null]"}return Object.prototype.toString.call(O)}w.jsDate=N;w.jqplot.sprintf=function(){function U(aa,W,X,Z){var Y=(aa.length>=W)?"":Array(1+W-aa.length>>>0).join(X);return Z?aa+Y:Y+aa}function R(Y){var X=new String(Y);for(var W=10;W>0;W--){if(X==(X=X.replace(/^(\d+)(\d{3})/,"$1"+w.jqplot.sprintf.thousandsSeparator+"$2"))){break}}return X}function Q(ab,aa,ad,Y,Z,X){var ac=Y-ab.length;if(ac>0){var W=" ";if(X){W=" "}if(ad||!Z){ab=U(ab,Y,W,ad)}else{ab=ab.slice(0,aa.length)+U("",ac,"0",true)+ab.slice(aa.length)}}return ab}function V(ae,X,ac,Y,W,ab,ad,aa){var Z=ae>>>0;ac=ac&&Z&&{"2":"0b","8":"0","16":"0x"}[X]||"";ae=ac+U(Z.toString(X),ab||0,"0",false);return Q(ae,ac,Y,W,ad,aa)}function O(aa,ab,Y,W,Z,X){if(W!=null){aa=aa.slice(0,W)}return Q(aa,"",ab,Y,Z,X)}var P=arguments,S=0,T=P[S++];return T.replace(w.jqplot.sprintf.regex,function(ar,ad,ae,ah,au,ao,ab){if(ar=="%%"){return"%"}var ai=false,af="",ag=false,aq=false,ac=false,aa=false;for(var an=0;ae&&an<ae.length;an++){switch(ae.charAt(an)){case" ":af=" ";break;case"+":af="+";break;case"-":ai=true;break;case"0":ag=true;break;case"#":aq=true;break;case"&":ac=true;break;case"'":aa=true;break}}if(!ah){ah=0}else{if(ah=="*"){ah=+P[S++]}else{if(ah.charAt(0)=="*"){ah=+P[ah.slice(1,-1)]}else{ah=+ah}}}if(ah<0){ah=-ah;ai=true}if(!isFinite(ah)){throw new Error("$.jqplot.sprintf: (minimum-)width must be finite")}if(!ao){ao="fFeE".indexOf(ab)>-1?6:(ab=="d")?0:void (0)}else{if(ao=="*"){ao=+P[S++]}else{if(ao.charAt(0)=="*"){ao=+P[ao.slice(1,-1)]}else{ao=+ao}}}var ak=ad?P[ad.slice(0,-1)]:P[S++];switch(ab){case"s":if(ak==null){return""}return O(String(ak),ai,ah,ao,ag,ac);case"c":return O(String.fromCharCode(+ak),ai,ah,ao,ag,ac);case"b":return V(ak,2,aq,ai,ah,ao,ag,ac);case"o":return V(ak,8,aq,ai,ah,ao,ag,ac);case"x":return V(ak,16,aq,ai,ah,ao,ag,ac);case"X":return V(ak,16,aq,ai,ah,ao,ag,ac).toUpperCase();case"u":return V(ak,10,aq,ai,ah,ao,ag,ac);case"i":var Y=parseInt(+ak,10);if(isNaN(Y)){return""}var am=Y<0?"-":af;var ap=aa?R(String(Math.abs(Y))):String(Math.abs(Y));ak=am+U(ap,ao,"0",false);return Q(ak,am,ai,ah,ag,ac);case"d":var Y=Math.round(+ak);if(isNaN(Y)){return""}var am=Y<0?"-":af;var ap=aa?R(String(Math.abs(Y))):String(Math.abs(Y));ak=am+U(ap,ao,"0",false);return Q(ak,am,ai,ah,ag,ac);case"e":case"E":case"f":case"F":case"g":case"G":var Y=+ak;if(isNaN(Y)){return""}var am=Y<0?"-":af;var Z=["toExponential","toFixed","toPrecision"]["efg".indexOf(ab.toLowerCase())];var at=["toString","toUpperCase"]["eEfFgG".indexOf(ab)%2];var ap=Math.abs(Y)[Z](ao);ap=aa?R(ap):ap;ak=am+ap;return Q(ak,am,ai,ah,ag,ac)[at]();case"p":case"P":var Y=+ak;if(isNaN(Y)){return""}var am=Y<0?"-":af;var aj=String(Number(Math.abs(Y)).toExponential()).split(/e|E/);var X=(aj[0].indexOf(".")!=-1)?aj[0].length-1:aj[0].length;var al=(aj[1]<0)?-aj[1]-1:0;if(Math.abs(Y)<1){if(X+al<=ao){ak=am+Math.abs(Y).toPrecision(X)}else{if(X<=ao-1){ak=am+Math.abs(Y).toExponential(X-1)}else{ak=am+Math.abs(Y).toExponential(ao-1)}}}else{var W=(X<=ao)?X:ao;ak=am+Math.abs(Y).toPrecision(W)}var at=["toString","toUpperCase"]["pP".indexOf(ab)%2];return Q(ak,am,ai,ah,ag,ac)[at]();case"n":return"";default:return ar}})};w.jqplot.sprintf.thousandsSeparator=",";w.jqplot.sprintf.regex=/%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/jquery.js b/phpgwapi/js/jquery/jqplot/jquery.js new file mode 100644 index 0000000000..5d5a1d58ee --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/jquery.js @@ -0,0 +1,8936 @@ +/*! + * jQuery JavaScript Library v1.6.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu May 12 15:04:36 2011 -0400 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action ]( returned ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + bodyStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + div.detachEvent( "onclick", click ); + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + // We use our own, invisible, body + body = document.createElement( "body" ); + bodyStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + // Set background to avoid IE crashes when removing (#9028) + background: "none" + }; + for ( i in bodyStyle ) { + body.style[ i ] = bodyStyle[ i ]; + } + body.appendChild( div ); + documentElement.insertBefore( body, documentElement.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "<div style='width:4px;'></div>"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>"; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + body.innerHTML = ""; + documentElement.removeChild( body ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? thisCache[ jQuery.camelCase( name ) ] : thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + rinvalidChar = /\:/, + formHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class") || "") ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspace ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", + setClass = elem.className; + + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split( rspace ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + return (elem.value || "").replace(rreturn, ""); + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + name = notxml && jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) && + (typeof value === "boolean" || value === undefined || value.toLowerCase() === name.toLowerCase()) ) { + + hooks = boolHook; + + // Use formHook for forms and if the name contains certain characters + } else if ( formHook && (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { + hooks = formHook; + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml ) { + return hooks.get( elem, name ); + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + if ( jQuery.support.getSetAttribute ) { + // Use removeAttribute in browsers that support it + elem.removeAttribute( name ); + } else { + jQuery.attr( elem, name, "" ); + elem.removeAttributeNode( elem.getAttributeNode( name ) ); + } + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabIndex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Try to normalize/fix the name + name = notxml && jQuery.propFix[ name ] || name; + + hooks = jQuery.propHooks[ name ]; + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: {} +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + return elem[ jQuery.propFix[ name ] || name ] ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = value; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// Use the value property for back compat +// Use the formHook for button elements in IE6/7 (#1954) +jQuery.attrHooks.value = { + get: function( elem, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.get( elem, name ); + } + return elem.value; + }, + set: function( elem, value, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // propFix is more comprehensive and contains all fixes + jQuery.attrFix = jQuery.propFix; + + // Use this for any attribute on a form in IE6/7 + formHook = jQuery.attrHooks.name = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Check form objects in IE (multiple bugs related) + // Only use nodeValue if the attribute node exists on the form + var ret = elem.getAttributeNode( name ); + if ( ret ) { + ret.nodeValue = value; + return value; + } + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var hasOwn = Object.prototype.hasOwnProperty, + rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // set the correct event type + event.type = event.data; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + + // Chrome does something similar, the parentNode property + // can be accessed but is null. + if ( parent && parent !== document && !parent.parentNode ) { + return; + } + + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = "<a name='" + id + "'/>"; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = "<a href='#'></a>"; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "<p class='TEST'></p>"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "<div class='test e'></div><div class='test'></div>"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /<tbody/i, + rhtml = /<|&#?\w+;/, + rnocache = /<(?:script|object|embed|option|style)/i, + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /\/(java|ecma)script/i, + rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/, + wrapMap = { + option: [ 1, "<select multiple='multiple'>", "</select>" ], + legend: [ 1, "<fieldset>", "</fieldset>" ], + thead: [ 1, "<table>", "</table>" ], + tr: [ 2, "<table><tbody>", "</tbody></table>" ], + td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], + col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], + area: [ 1, "<map>", "</map>" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize <link> and <script> tags normally +if ( !jQuery.support.htmlSerialize ) { + wrapMap._default = [ 1, "div<div>", "</div>" ]; +} + +jQuery.fn.extend({ + text: function( text ) { + if ( jQuery.isFunction(text) ) { + return this.each(function(i) { + var self = jQuery( this ); + + self.text( text.call(this, i, self.text()) ); + }); + } + + if ( typeof text !== "object" && text !== undefined ) { + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + } + + return jQuery.text( this ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + return this.each(function() { + jQuery( this ).wrapAll( html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this ); + }); + } else if ( arguments.length ) { + var set = jQuery(arguments[0]); + set.push.apply( set, this.toArray() ); + return this.pushStack( set, "before", arguments ); + } + }, + + after: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } else if ( arguments.length ) { + var set = this.pushStack( this, "after", arguments ); + set.push.apply( set, jQuery(arguments[0]).toArray() ); + return set; + } + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + if ( value === undefined ) { + return this[0] && this[0].nodeType === 1 ? + this[0].innerHTML.replace(rinlinejQuery, "") : + null; + + // See if we can take a shortcut and just use innerHTML + } else if ( typeof value === "string" && !rnocache.test( value ) && + (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && + !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { + + value = value.replace(rxhtmlTag, "<$1></$2>"); + + try { + for ( var i = 0, l = this.length; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + if ( this[i].nodeType === 1 ) { + jQuery.cleanData( this[i].getElementsByTagName("*") ); + this[i].innerHTML = value; + } + } + + // If using innerHTML throws an exception, use the fallback method + } catch(e) { + this.empty().append( value ); + } + + } else if ( jQuery.isFunction( value ) ) { + this.each(function(i){ + var self = jQuery( this ); + + self.html( value.call(this, i, self.html()) ); + }); + + } else { + this.empty().append( value ); + } + + return this; + }, + + replaceWith: function( value ) { + if ( this[0] && this[0].parentNode ) { + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this), old = self.html(); + self.replaceWith( value.call( this, i, old ) ); + }); + } + + if ( typeof value !== "string" ) { + value = jQuery( value ).detach(); + } + + return this.each(function() { + var next = this.nextSibling, + parent = this.parentNode; + + jQuery( this ).remove(); + + if ( next ) { + jQuery(next).before( value ); + } else { + jQuery(parent).append( value ); + } + }); + } else { + return this.length ? + this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : + this; + } + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + var results, first, fragment, parent, + value = args[0], + scripts = []; + + // We can't cloneNode fragments that contain checked, in WebKit + if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { + return this.each(function() { + jQuery(this).domManip( args, table, callback, true ); + }); + } + + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call(this, i, table ? self.html() : undefined); + self.domManip( args, table, callback ); + }); + } + + if ( this[0] ) { + parent = value && value.parentNode; + + // If we're in a fragment, just use that instead of building a new one + if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { + results = { fragment: parent }; + + } else { + results = jQuery.buildFragment( args, this, scripts ); + } + + fragment = results.fragment; + + if ( fragment.childNodes.length === 1 ) { + first = fragment = fragment.firstChild; + } else { + first = fragment.firstChild; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + + for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) { + callback.call( + table ? + root(this[i], first) : + this[i], + // Make sure that we do not leak memory by inadvertently discarding + // the original fragment (which might have attached data) instead of + // using it; in addition, use the original fragment object for the last + // item instead of first because it can end up being emptied incorrectly + // in certain situations (Bug #8070). + // Fragments from the fragment cache must always be cloned and never used + // in place. + results.cacheable || (l > 1 && i < lastIndex) ? + jQuery.clone( fragment, true, true ) : + fragment + ); + } + } + + if ( scripts.length ) { + jQuery.each( scripts, evalScript ); + } + } + + return this; + } +}); + +function root( elem, cur ) { + return jQuery.nodeName(elem, "table") ? + (elem.getElementsByTagName("tbody")[0] || + elem.appendChild(elem.ownerDocument.createElement("tbody"))) : + elem; +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var internalKey = jQuery.expando, + oldData = jQuery.data( src ), + curData = jQuery.data( dest, oldData ); + + // Switch to use the internal data object, if it exists, for the next + // stage of data copying + if ( (oldData = oldData[ internalKey ]) ) { + var events = oldData.events; + curData = curData[ internalKey ] = jQuery.extend({}, oldData); + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( var type in events ) { + for ( var i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data ); + } + } + } + } +} + +function cloneFixAttributes( src, dest ) { + var nodeName; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + // clearAttributes removes the attributes, which we don't want, + // but also removes the attachEvent events, which we *do* want + if ( dest.clearAttributes ) { + dest.clearAttributes(); + } + + // mergeAttributes, in contrast, only merges back on the + // original attributes, not the events + if ( dest.mergeAttributes ) { + dest.mergeAttributes( src ); + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 fail to clone children inside object elements that use + // the proprietary classid attribute value (rather than the type + // attribute) to identify the type of content to display + if ( nodeName === "object" ) { + dest.outerHTML = src.outerHTML; + + } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + if ( src.checked ) { + dest.defaultChecked = dest.checked = src.checked; + } + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } + + // Event data gets referenced instead of copied if the expando + // gets copied too + dest.removeAttribute( jQuery.expando ); +} + +jQuery.buildFragment = function( args, nodes, scripts ) { + var fragment, cacheable, cacheresults, + doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); + + // Only cache "small" (1/2 KB) HTML strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && + args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { + + cacheable = true; + + cacheresults = jQuery.fragments[ args[0] ]; + if ( cacheresults && cacheresults !== 1 ) { + fragment = cacheresults; + } + } + + if ( !fragment ) { + fragment = doc.createDocumentFragment(); + jQuery.clean( args, doc, fragment, scripts ); + } + + if ( cacheable ) { + jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1; + } + + return { fragment: fragment, cacheable: cacheable }; +}; + +jQuery.fragments = {}; + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +}); + +function getAll( elem ) { + if ( "getElementsByTagName" in elem ) { + return elem.getElementsByTagName( "*" ); + + } else if ( "querySelectorAll" in elem ) { + return elem.querySelectorAll( "*" ); + + } else { + return []; + } +} + +// Used in clean, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( elem.type === "checkbox" || elem.type === "radio" ) { + elem.defaultChecked = elem.checked; + } +} +// Finds all inputs and passes them to fixDefaultChecked +function findInputs( elem ) { + if ( jQuery.nodeName( elem, "input" ) ) { + fixDefaultChecked( elem ); + } else if ( elem.getElementsByTagName ) { + jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked ); + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var clone = elem.cloneNode(true), + srcElements, + destElements, + i; + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + // IE copies events bound via attachEvent when using cloneNode. + // Calling detachEvent on the clone will also remove the events + // from the original. In order to get around this, we use some + // proprietary methods to clear the events. Thanks to MooTools + // guys for this hotness. + + cloneFixAttributes( elem, clone ); + + // Using Sizzle here is crazy slow, so we use getElementsByTagName + // instead + srcElements = getAll( elem ); + destElements = getAll( clone ); + + // Weird iteration because IE will replace the length property + // with an element if you are cloning the body and one of the + // elements on the page has a name or id of "length" + for ( i = 0; srcElements[i]; ++i ) { + cloneFixAttributes( srcElements[i], destElements[i] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + cloneCopyEvent( elem, clone ); + + if ( deepDataAndEvents ) { + srcElements = getAll( elem ); + destElements = getAll( clone ); + + for ( i = 0; srcElements[i]; ++i ) { + cloneCopyEvent( srcElements[i], destElements[i] ); + } + } + } + + // Return the cloned set + return clone; + }, + + clean: function( elems, context, fragment, scripts ) { + var checkScriptType; + + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) { + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + } + + var ret = [], j; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( typeof elem === "number" ) { + elem += ""; + } + + if ( !elem ) { + continue; + } + + // Convert html string into DOM nodes + if ( typeof elem === "string" ) { + if ( !rhtml.test( elem ) ) { + elem = context.createTextNode( elem ); + } else { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(rxhtmlTag, "<$1></$2>"); + + // Trim whitespace, otherwise indexOf won't work as expected + var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), + wrap = wrapMap[ tag ] || wrapMap._default, + depth = wrap[0], + div = context.createElement("div"); + + // Go to html and back, then peel off extra wrappers + div.innerHTML = wrap[1] + elem + wrap[2]; + + // Move to the right depth + while ( depth-- ) { + div = div.lastChild; + } + + // Remove IE's autoinserted <tbody> from table fragments + if ( !jQuery.support.tbody ) { + + // String was a <table>, *may* have spurious <tbody> + var hasBody = rtbody.test(elem), + tbody = tag === "table" && !hasBody ? + div.firstChild && div.firstChild.childNodes : + + // String was a bare <thead> or <tfoot> + wrap[1] === "<table>" && !hasBody ? + div.childNodes : + []; + + for ( j = tbody.length - 1; j >= 0 ; --j ) { + if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { + tbody[ j ].parentNode.removeChild( tbody[ j ] ); + } + } + } + + // IE completely kills leading whitespace when innerHTML is used + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); + } + + elem = div.childNodes; + } + } + + // Resets defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + var len; + if ( !jQuery.support.appendChecked ) { + if ( elem[0] && typeof (len = elem.length) === "number" ) { + for ( j = 0; j < len; j++ ) { + findInputs( elem[j] ); + } + } else { + findInputs( elem ); + } + } + + if ( elem.nodeType ) { + ret.push( elem ); + } else { + ret = jQuery.merge( ret, elem ); + } + } + + if ( fragment ) { + checkScriptType = function( elem ) { + return !elem.type || rscriptType.test( elem.type ); + }; + for ( i = 0; ret[i]; i++ ) { + if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { + scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); + + } else { + if ( ret[i].nodeType === 1 ) { + var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType ); + + ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); + } + fragment.appendChild( ret[i] ); + } + } + } + + return ret; + }, + + cleanData: function( elems ) { + var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special, + deleteExpando = jQuery.support.deleteExpando; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + continue; + } + + id = elem[ jQuery.expando ]; + + if ( id ) { + data = cache[ id ] && cache[ id ][ internalKey ]; + + if ( data && data.events ) { + for ( var type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + + // Null the DOM reference to avoid IE6/7/8 leak (#7054) + if ( data.handle ) { + data.handle.elem = null; + } + } + + if ( deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + delete cache[ id ]; + } + } + } +}); + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + + + + +var ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity=([^)]*)/, + rdashAlpha = /-([a-z])/ig, + // fixed for IE9, see #8346 + rupper = /([A-Z]|^ms)/g, + rnumpx = /^-?\d+(?:px)?$/i, + rnum = /^-?\d/, + rrelNum = /^[+\-]=/, + rrelNumFilter = /[^+\-\.\de]+/g, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssWidth = [ "Left", "Right" ], + cssHeight = [ "Top", "Bottom" ], + curCSS, + + getComputedStyle, + currentStyle, + + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn.css = function( name, value ) { + // Setting 'undefined' is a no-op + if ( arguments.length === 2 && value === undefined ) { + return this; + } + + return jQuery.access( this, name, value, true, function( elem, name, value ) { + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }); +}; + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity", "opacity" ); + return ret === "" ? "1" : ret; + + } else { + return elem.style.opacity; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "zIndex": true, + "fontWeight": true, + "opacity": true, + "zoom": true, + "lineHeight": true, + "widows": true, + "orphans": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, origName = jQuery.camelCase( name ), + style = elem.style, hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Make sure that NaN and null values aren't set. See: #7116 + if ( type === "number" && isNaN( value ) || value == null ) { + return; + } + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && rrelNum.test( value ) ) { + value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) ); + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra ) { + var ret, hooks; + + // Make sure that we're working with the right name + name = jQuery.camelCase( name ); + hooks = jQuery.cssHooks[ name ]; + name = jQuery.cssProps[ name ] || name; + + // cssFloat needs a special treatment + if ( name === "cssFloat" ) { + name = "float"; + } + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name ); + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + }, + + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + } +}); + +// DEPRECATED, Use jQuery.css() instead +jQuery.curCSS = jQuery.css; + +jQuery.each(["height", "width"], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + var val; + + if ( computed ) { + if ( elem.offsetWidth !== 0 ) { + val = getWH( elem, name, extra ); + + } else { + jQuery.swap( elem, cssShow, function() { + val = getWH( elem, name, extra ); + }); + } + + if ( val <= 0 ) { + val = curCSS( elem, name, name ); + + if ( val === "0px" && currentStyle ) { + val = currentStyle( elem, name, name ); + } + + if ( val != null ) { + // Should return "auto" instead of 0, use 0 for + // temporary backwards-compat + return val === "" || val === "auto" ? "0px" : val; + } + } + + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + + // Should return "auto" instead of 0, use 0 for + // temporary backwards-compat + return val === "" || val === "auto" ? "0px" : val; + } + + return typeof val === "string" ? val : val + "px"; + } + }, + + set: function( elem, value ) { + if ( rnumpx.test( value ) ) { + // ignore negative width and height values #1599 + value = parseFloat(value); + + if ( value >= 0 ) { + return value + "px"; + } + + } else { + return value; + } + } + }; +}); + +if ( !jQuery.support.opacity ) { + jQuery.cssHooks.opacity = { + get: function( elem, computed ) { + // IE uses filters for opacity + return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? + ( parseFloat( RegExp.$1 ) / 100 ) + "" : + computed ? "1" : ""; + }, + + set: function( elem, value ) { + var style = elem.style, + currentStyle = elem.currentStyle; + + // IE has trouble with opacity if it does not have layout + // Force it by setting the zoom level + style.zoom = 1; + + // Set the alpha filter to set the opacity + var opacity = jQuery.isNaN( value ) ? + "" : + "alpha(opacity=" + value * 100 + ")", + filter = currentStyle && currentStyle.filter || style.filter || ""; + + style.filter = ralpha.test( filter ) ? + filter.replace( ralpha, opacity ) : + filter + " " + opacity; + } + }; +} + +jQuery(function() { + // This hook cannot be added until DOM ready because the support test + // for it is not run until after DOM ready + if ( !jQuery.support.reliableMarginRight ) { + jQuery.cssHooks.marginRight = { + get: function( elem, computed ) { + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + // Work around by temporarily setting element display to inline-block + var ret; + jQuery.swap( elem, { "display": "inline-block" }, function() { + if ( computed ) { + ret = curCSS( elem, "margin-right", "marginRight" ); + } else { + ret = elem.style.marginRight; + } + }); + return ret; + } + }; + } +}); + +if ( document.defaultView && document.defaultView.getComputedStyle ) { + getComputedStyle = function( elem, name ) { + var ret, defaultView, computedStyle; + + name = name.replace( rupper, "-$1" ).toLowerCase(); + + if ( !(defaultView = elem.ownerDocument.defaultView) ) { + return undefined; + } + + if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) { + ret = computedStyle.getPropertyValue( name ); + if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { + ret = jQuery.style( elem, name ); + } + } + + return ret; + }; +} + +if ( document.documentElement.currentStyle ) { + currentStyle = function( elem, name ) { + var left, + ret = elem.currentStyle && elem.currentStyle[ name ], + rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ], + style = elem.style; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !rnumpx.test( ret ) && rnum.test( ret ) ) { + // Remember the original values + left = style.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + elem.runtimeStyle.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : (ret || 0); + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + elem.runtimeStyle.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +curCSS = getComputedStyle || currentStyle; + +function getWH( elem, name, extra ) { + var which = name === "width" ? cssWidth : cssHeight, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight; + + if ( extra === "border" ) { + return val; + } + + jQuery.each( which, function() { + if ( !extra ) { + val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0; + } + + if ( extra === "margin" ) { + val += parseFloat(jQuery.css( elem, "margin" + this )) || 0; + + } else { + val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0; + } + }); + + return val; +} + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.hidden = function( elem ) { + var width = elem.offsetWidth, + height = elem.offsetHeight; + + return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none"); + }; + + jQuery.expr.filters.visible = function( elem ) { + return !jQuery.expr.filters.hidden( elem ); + }; +} + + + + +var r20 = /%20/g, + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rhash = /#.*$/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL + rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + rquery = /\?/, + rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, + rselectTextarea = /^(?:select|textarea)/i, + rspacesAjax = /\s+/, + rts = /([?&])_=[^&]*/, + rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/, + + // Keep a copy of the old load method + _load = jQuery.fn.load, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Document location + ajaxLocation, + + // Document location segments + ajaxLocParts; + +// #8138, IE may throw an exception when accessing +// a field from window.location if document.domain has been set +try { + ajaxLocation = location.href; +} catch( e ) { + // Use the href attribute of an A element + // since IE will modify it given document.location + ajaxLocation = document.createElement( "a" ); + ajaxLocation.href = ""; + ajaxLocation = ajaxLocation.href; +} + +// Segment location into parts +ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + if ( jQuery.isFunction( func ) ) { + var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), + i = 0, + length = dataTypes.length, + dataType, + list, + placeBefore; + + // For each dataType in the dataTypeExpression + for(; i < length; i++ ) { + dataType = dataTypes[ i ]; + // We control if we're asked to add before + // any existing element + placeBefore = /^\+/.test( dataType ); + if ( placeBefore ) { + dataType = dataType.substr( 1 ) || "*"; + } + list = structure[ dataType ] = structure[ dataType ] || []; + // then we add to the structure accordingly + list[ placeBefore ? "unshift" : "push" ]( func ); + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, + dataType /* internal */, inspected /* internal */ ) { + + dataType = dataType || options.dataTypes[ 0 ]; + inspected = inspected || {}; + + inspected[ dataType ] = true; + + var list = structure[ dataType ], + i = 0, + length = list ? list.length : 0, + executeOnly = ( structure === prefilters ), + selection; + + for(; i < length && ( executeOnly || !selection ); i++ ) { + selection = list[ i ]( options, originalOptions, jqXHR ); + // If we got redirected to another dataType + // we try there if executing only and not done already + if ( typeof selection === "string" ) { + if ( !executeOnly || inspected[ selection ] ) { + selection = undefined; + } else { + options.dataTypes.unshift( selection ); + selection = inspectPrefiltersOrTransports( + structure, options, originalOptions, jqXHR, selection, inspected ); + } + } + } + // If we're only executing or nothing was selected + // we try the catchall dataType if not done already + if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { + selection = inspectPrefiltersOrTransports( + structure, options, originalOptions, jqXHR, "*", inspected ); + } + // unnecessary when only executing (prefilters) + // but it'll be ignored by the caller in that case + return selection; +} + +jQuery.fn.extend({ + load: function( url, params, callback ) { + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + + // Don't do a request if no elements are being requested + } else if ( !this.length ) { + return this; + } + + var off = url.indexOf( " " ); + if ( off >= 0 ) { + var selector = url.slice( off, url.length ); + url = url.slice( 0, off ); + } + + // Default to a GET request + var type = "GET"; + + // If the second parameter was provided + if ( params ) { + // If it's a function + if ( jQuery.isFunction( params ) ) { + // We assume that it's the callback + callback = params; + params = undefined; + + // Otherwise, build a param string + } else if ( typeof params === "object" ) { + params = jQuery.param( params, jQuery.ajaxSettings.traditional ); + type = "POST"; + } + } + + var self = this; + + // Request the remote document + jQuery.ajax({ + url: url, + type: type, + dataType: "html", + data: params, + // Complete callback (responseText is used internally) + complete: function( jqXHR, status, responseText ) { + // Store the response as specified by the jqXHR object + responseText = jqXHR.responseText; + // If successful, inject the HTML into all the matched elements + if ( jqXHR.isResolved() ) { + // #4825: Get the actual response in case + // a dataFilter is present in ajaxSettings + jqXHR.done(function( r ) { + responseText = r; + }); + // See if a selector was specified + self.html( selector ? + // Create a dummy div to hold the results + jQuery("<div>") + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(responseText.replace(rscript, "")) + + // Locate the specified elements + .find(selector) : + + // If not, just inject the full result + responseText ); + } + + if ( callback ) { + self.each( callback, [ responseText, status, jqXHR ] ); + } + } + }); + + return this; + }, + + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + + serializeArray: function() { + return this.map(function(){ + return this.elements ? jQuery.makeArray( this.elements ) : this; + }) + .filter(function(){ + return this.name && !this.disabled && + ( this.checked || rselectTextarea.test( this.nodeName ) || + rinput.test( this.type ) ); + }) + .map(function( i, elem ){ + var val = jQuery( this ).val(); + + return val == null ? + null : + jQuery.isArray( val ) ? + jQuery.map( val, function( val, i ){ + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }) : + { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }).get(); + } +}); + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ + jQuery.fn[ o ] = function( f ){ + return this.bind( o, f ); + }; +}); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + type: method, + url: url, + data: data, + success: callback, + dataType: type + }); + }; +}); + +jQuery.extend({ + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function ( target, settings ) { + if ( !settings ) { + // Only one parameter, we extend ajaxSettings + settings = target; + target = jQuery.extend( true, jQuery.ajaxSettings, settings ); + } else { + // target was provided, we extend into it + jQuery.extend( true, target, jQuery.ajaxSettings, settings ); + } + // Flatten fields we don't want deep extended + for( var field in { context: 1, url: 1 } ) { + if ( field in settings ) { + target[ field ] = settings[ field ]; + } else if( field in jQuery.ajaxSettings ) { + target[ field ] = jQuery.ajaxSettings[ field ]; + } + } + return target; + }, + + ajaxSettings: { + url: ajaxLocation, + isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), + global: true, + type: "GET", + contentType: "application/x-www-form-urlencoded", + processData: true, + async: true, + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + traditional: false, + headers: {}, + */ + + accepts: { + xml: "application/xml, text/xml", + html: "text/html", + text: "text/plain", + json: "application/json, text/javascript", + "*": "*/*" + }, + + contents: { + xml: /xml/, + html: /html/, + json: /json/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText" + }, + + // List of data converters + // 1) key format is "source_type destination_type" (a single space in-between) + // 2) the catchall symbol "*" can be used for source_type + converters: { + + // Convert anything to text + "* text": window.String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": jQuery.parseJSON, + + // Parse text as xml + "text xml": jQuery.parseXML + } + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + // Callbacks context + callbackContext = s.context || s, + // Context for global events + // It's the callbackContext if one was provided in the options + // and if it's a DOM node or a jQuery collection + globalEventContext = callbackContext !== s && + ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? + jQuery( callbackContext ) : jQuery.event, + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery._Deferred(), + // Status-dependent callbacks + statusCode = s.statusCode || {}, + // ifModified key + ifModifiedKey, + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + // Response headers + responseHeadersString, + responseHeaders, + // transport + transport, + // timeout handle + timeoutTimer, + // Cross-domain detection vars + parts, + // The jqXHR state + state = 0, + // To know if global events are to be dispatched + fireGlobals, + // Loop variable + i, + // Fake xhr + jqXHR = { + + readyState: 0, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( !state ) { + var lname = name.toLowerCase(); + name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Raw string + getAllResponseHeaders: function() { + return state === 2 ? responseHeadersString : null; + }, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( state === 2 ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match === undefined ? null : match; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( !state ) { + s.mimeType = type; + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + statusText = statusText || "abort"; + if ( transport ) { + transport.abort( statusText ); + } + done( 0, statusText ); + return this; + } + }; + + // Callback for when everything is done + // It is defined here because jslint complains if it is declared + // at the end of the function (which would be more logical and readable) + function done( status, statusText, responses, headers ) { + + // Called once + if ( state === 2 ) { + return; + } + + // State is "done" now + state = 2; + + // Clear timeout if it exists + if ( timeoutTimer ) { + clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status ? 4 : 0; + + var isSuccess, + success, + error, + response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined, + lastModified, + etag; + + // If successful, handle type chaining + if ( status >= 200 && status < 300 || status === 304 ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + + if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) { + jQuery.lastModified[ ifModifiedKey ] = lastModified; + } + if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) { + jQuery.etag[ ifModifiedKey ] = etag; + } + } + + // If not modified + if ( status === 304 ) { + + statusText = "notmodified"; + isSuccess = true; + + // If we have data + } else { + + try { + success = ajaxConvert( s, response ); + statusText = "success"; + isSuccess = true; + } catch(e) { + // We have a parsererror + statusText = "parsererror"; + error = e; + } + } + } else { + // We extract error from statusText + // then normalize statusText and status for non-aborts + error = statusText; + if( !statusText || status ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = statusText; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] ); + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + // Attach deferreds + deferred.promise( jqXHR ); + jqXHR.success = jqXHR.done; + jqXHR.error = jqXHR.fail; + jqXHR.complete = completeDeferred.done; + + // Status-dependent callbacks + jqXHR.statusCode = function( map ) { + if ( map ) { + var tmp; + if ( state < 2 ) { + for( tmp in map ) { + statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; + } + } else { + tmp = map[ jqXHR.status ]; + jqXHR.then( tmp, tmp ); + } + } + return this; + }; + + // Remove hash character (#7531: and string promotion) + // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) + // We also use the url parameter if available + s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); + + // Extract dataTypes list + s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); + + // Determine if a cross-domain request is in order + if ( s.crossDomain == null ) { + parts = rurl.exec( s.url.toLowerCase() ); + s.crossDomain = !!( parts && + ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) + ); + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefiler, stop there + if ( state === 2 ) { + return false; + } + + // We can fire global events as of now if asked to + fireGlobals = s.global; + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // If data is available, append data to url + if ( s.data ) { + s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; + } + + // Get ifModifiedKey before adding the anti-cache parameter + ifModifiedKey = s.url; + + // Add anti-cache in url if needed + if ( s.cache === false ) { + + var ts = jQuery.now(), + // try replacing _= if it is there + ret = s.url.replace( rts, "$1_=" + ts ); + + // if nothing was replaced, add timestamp to the end + s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + ifModifiedKey = ifModifiedKey || s.url; + if ( jQuery.lastModified[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); + } + if ( jQuery.etag[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); + } + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? + s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { + // Abort if not done already + jqXHR.abort(); + return false; + + } + + // Install callbacks on deferreds + for ( i in { success: 1, error: 1, complete: 1 } ) { + jqXHR[ i ]( s[ i ] ); + } + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = setTimeout( function(){ + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + state = 1; + transport.send( requestHeaders, done ); + } catch (e) { + // Propagate exception as error if not done + if ( status < 2 ) { + done( -1, e ); + // Simply rethrow otherwise + } else { + jQuery.error( e ); + } + } + } + + return jqXHR; + }, + + // Serialize an array of form elements or a set of + // key/values into a query string + param: function( a, traditional ) { + var s = [], + add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction( value ) ? value() : value; + s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + }); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( var prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ).replace( r20, "+" ); + } +}); + +function buildParams( prefix, obj, traditional, add ) { + if ( jQuery.isArray( obj ) ) { + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + // If array item is non-scalar (array or object), encode its + // numeric index to resolve deserialization ambiguity issues. + // Note that rack (as of 1.0.0) can't currently deserialize + // nested arrays properly, and attempting to do so may cause + // a server error. Possible fixes are to modify rack's + // deserialization algorithm or to provide an option or flag + // to force array serialization to be shallow. + buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add ); + } + }); + + } else if ( !traditional && obj != null && typeof obj === "object" ) { + // Serialize object item. + for ( var name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + // Serialize scalar item. + add( prefix, obj ); + } +} + +// This is still on the jQuery object... for now +// Want to move this to jQuery.ajax some day +jQuery.extend({ + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {} + +}); + +/* Handles responses to an ajax request: + * - sets all responseXXX fields accordingly + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var contents = s.contents, + dataTypes = s.dataTypes, + responseFields = s.responseFields, + ct, + type, + finalDataType, + firstDataType; + + // Fill responseXXX fields + for( type in responseFields ) { + if ( type in responses ) { + jqXHR[ responseFields[type] ] = responses[ type ]; + } + } + + // Remove auto dataType and get content-type in the process + while( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "content-type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +// Chain conversions given the request and the original response +function ajaxConvert( s, response ) { + + // Apply the dataFilter if provided + if ( s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + var dataTypes = s.dataTypes, + converters = {}, + i, + key, + length = dataTypes.length, + tmp, + // Current and previous dataTypes + current = dataTypes[ 0 ], + prev, + // Conversion expression + conversion, + // Conversion function + conv, + // Conversion functions (transitive conversion) + conv1, + conv2; + + // For each dataType in the chain + for( i = 1; i < length; i++ ) { + + // Create converters map + // with lowercased keys + if ( i === 1 ) { + for( key in s.converters ) { + if( typeof key === "string" ) { + converters[ key.toLowerCase() ] = s.converters[ key ]; + } + } + } + + // Get the dataTypes + prev = current; + current = dataTypes[ i ]; + + // If current is auto dataType, update it to prev + if( current === "*" ) { + current = prev; + // If no auto and dataTypes are actually different + } else if ( prev !== "*" && prev !== current ) { + + // Get the converter + conversion = prev + " " + current; + conv = converters[ conversion ] || converters[ "* " + current ]; + + // If there is no direct converter, search transitively + if ( !conv ) { + conv2 = undefined; + for( conv1 in converters ) { + tmp = conv1.split( " " ); + if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) { + conv2 = converters[ tmp[1] + " " + current ]; + if ( conv2 ) { + conv1 = converters[ conv1 ]; + if ( conv1 === true ) { + conv = conv2; + } else if ( conv2 === true ) { + conv = conv1; + } + break; + } + } + } + } + // If we found no converter, dispatch an error + if ( !( conv || conv2 ) ) { + jQuery.error( "No conversion from " + conversion.replace(" "," to ") ); + } + // If found converter is not an equivalence + if ( conv !== true ) { + // Convert with 1 or 2 converters accordingly + response = conv ? conv( response ) : conv2( conv1(response) ); + } + } + } + return response; +} + + + + +var jsc = jQuery.now(), + jsre = /(\=)\?(&|$)|\?\?/i; + +// Default jsonp settings +jQuery.ajaxSetup({ + jsonp: "callback", + jsonpCallback: function() { + return jQuery.expando + "_" + ( jsc++ ); + } +}); + +// Detect, normalize options and install callbacks for jsonp requests +jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { + + var inspectData = s.contentType === "application/x-www-form-urlencoded" && + ( typeof s.data === "string" ); + + if ( s.dataTypes[ 0 ] === "jsonp" || + s.jsonp !== false && ( jsre.test( s.url ) || + inspectData && jsre.test( s.data ) ) ) { + + var responseContainer, + jsonpCallback = s.jsonpCallback = + jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback, + previous = window[ jsonpCallback ], + url = s.url, + data = s.data, + replace = "$1" + jsonpCallback + "$2"; + + if ( s.jsonp !== false ) { + url = url.replace( jsre, replace ); + if ( s.url === url ) { + if ( inspectData ) { + data = data.replace( jsre, replace ); + } + if ( s.data === data ) { + // Add callback manually + url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback; + } + } + } + + s.url = url; + s.data = data; + + // Install callback + window[ jsonpCallback ] = function( response ) { + responseContainer = [ response ]; + }; + + // Clean-up function + jqXHR.always(function() { + // Set callback back to previous value + window[ jsonpCallback ] = previous; + // Call if it was a function and we have a response + if ( responseContainer && jQuery.isFunction( previous ) ) { + window[ jsonpCallback ]( responseContainer[ 0 ] ); + } + }); + + // Use data converter to retrieve json after script execution + s.converters["script json"] = function() { + if ( !responseContainer ) { + jQuery.error( jsonpCallback + " was not called" ); + } + return responseContainer[ 0 ]; + }; + + // force json dataType + s.dataTypes[ 0 ] = "json"; + + // Delegate to script + return "script"; + } +}); + + + + +// Install script dataType +jQuery.ajaxSetup({ + accepts: { + script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /javascript|ecmascript/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +}); + +// Handle cache's special case and global +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + s.global = false; + } +}); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function(s) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + + var script, + head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement; + + return { + + send: function( _, callback ) { + + script = document.createElement( "script" ); + + script.async = "async"; + + if ( s.scriptCharset ) { + script.charset = s.scriptCharset; + } + + script.src = s.url; + + // Attach handlers for all browsers + script.onload = script.onreadystatechange = function( _, isAbort ) { + + if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { + + // Handle memory leak in IE + script.onload = script.onreadystatechange = null; + + // Remove the script + if ( head && script.parentNode ) { + head.removeChild( script ); + } + + // Dereference the script + script = undefined; + + // Callback if not abort + if ( !isAbort ) { + callback( 200, "success" ); + } + } + }; + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709 and #4378). + head.insertBefore( script, head.firstChild ); + }, + + abort: function() { + if ( script ) { + script.onload( 0, 1 ); + } + } + }; + } +}); + + + + +var // #5280: Internet Explorer will keep connections alive if we don't abort on unload + xhrOnUnloadAbort = window.ActiveXObject ? function() { + // Abort all pending requests + for ( var key in xhrCallbacks ) { + xhrCallbacks[ key ]( 0, 1 ); + } + } : false, + xhrId = 0, + xhrCallbacks; + +// Functions to create xhrs +function createStandardXHR() { + try { + return new window.XMLHttpRequest(); + } catch( e ) {} +} + +function createActiveXHR() { + try { + return new window.ActiveXObject( "Microsoft.XMLHTTP" ); + } catch( e ) {} +} + +// Create the request object +// (This is still attached to ajaxSettings for backward compatibility) +jQuery.ajaxSettings.xhr = window.ActiveXObject ? + /* Microsoft failed to properly + * implement the XMLHttpRequest in IE7 (can't request local files), + * so we use the ActiveXObject when it is available + * Additionally XMLHttpRequest can be disabled in IE7/IE8 so + * we need a fallback. + */ + function() { + return !this.isLocal && createStandardXHR() || createActiveXHR(); + } : + // For all other browsers, use the standard XMLHttpRequest object + createStandardXHR; + +// Determine support properties +(function( xhr ) { + jQuery.extend( jQuery.support, { + ajax: !!xhr, + cors: !!xhr && ( "withCredentials" in xhr ) + }); +})( jQuery.ajaxSettings.xhr() ); + +// Create transport if the browser can provide an xhr +if ( jQuery.support.ajax ) { + + jQuery.ajaxTransport(function( s ) { + // Cross domain only allowed if supported through XMLHttpRequest + if ( !s.crossDomain || jQuery.support.cors ) { + + var callback; + + return { + send: function( headers, complete ) { + + // Get a new xhr + var xhr = s.xhr(), + handle, + i; + + // Open the socket + // Passing null username, generates a login popup on Opera (#2865) + if ( s.username ) { + xhr.open( s.type, s.url, s.async, s.username, s.password ); + } else { + xhr.open( s.type, s.url, s.async ); + } + + // Apply custom fields if provided + if ( s.xhrFields ) { + for ( i in s.xhrFields ) { + xhr[ i ] = s.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( s.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( s.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !s.crossDomain && !headers["X-Requested-With"] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Need an extra try/catch for cross domain requests in Firefox 3 + try { + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + } catch( _ ) {} + + // Do send the request + // This may raise an exception which is actually + // handled in jQuery.ajax (so no try/catch here) + xhr.send( ( s.hasContent && s.data ) || null ); + + // Listener + callback = function( _, isAbort ) { + + var status, + statusText, + responseHeaders, + responses, + xml; + + // Firefox throws exceptions when accessing properties + // of an xhr when a network error occured + // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) + try { + + // Was never called and is aborted or complete + if ( callback && ( isAbort || xhr.readyState === 4 ) ) { + + // Only called once + callback = undefined; + + // Do not keep as active anymore + if ( handle ) { + xhr.onreadystatechange = jQuery.noop; + if ( xhrOnUnloadAbort ) { + delete xhrCallbacks[ handle ]; + } + } + + // If it's an abort + if ( isAbort ) { + // Abort it manually if needed + if ( xhr.readyState !== 4 ) { + xhr.abort(); + } + } else { + status = xhr.status; + responseHeaders = xhr.getAllResponseHeaders(); + responses = {}; + xml = xhr.responseXML; + + // Construct response list + if ( xml && xml.documentElement /* #4958 */ ) { + responses.xml = xml; + } + responses.text = xhr.responseText; + + // Firefox throws an exception when accessing + // statusText for faulty cross-domain requests + try { + statusText = xhr.statusText; + } catch( e ) { + // We normalize with Webkit giving an empty statusText + statusText = ""; + } + + // Filter status for non standard behaviors + + // If the request is local and we have data: assume a success + // (success with no data won't get notified, that's the best we + // can do given current implementations) + if ( !status && s.isLocal && !s.crossDomain ) { + status = responses.text ? 200 : 404; + // IE - #1450: sometimes returns 1223 when it should be 204 + } else if ( status === 1223 ) { + status = 204; + } + } + } + } catch( firefoxAccessException ) { + if ( !isAbort ) { + complete( -1, firefoxAccessException ); + } + } + + // Call complete if needed + if ( responses ) { + complete( status, statusText, responses, responseHeaders ); + } + }; + + // if we're in sync mode or it's in cache + // and has been retrieved directly (IE6 & IE7) + // we need to manually fire the callback + if ( !s.async || xhr.readyState === 4 ) { + callback(); + } else { + handle = ++xhrId; + if ( xhrOnUnloadAbort ) { + // Create the active xhrs callbacks list if needed + // and attach the unload handler + if ( !xhrCallbacks ) { + xhrCallbacks = {}; + jQuery( window ).unload( xhrOnUnloadAbort ); + } + // Add to list of active xhrs callbacks + xhrCallbacks[ handle ] = callback; + } + xhr.onreadystatechange = callback; + } + }, + + abort: function() { + if ( callback ) { + callback(0,1); + } + } + }; + } + }); +} + + + + +var elemdisplay = {}, + iframe, iframeDoc, + rfxtypes = /^(?:toggle|show|hide)$/, + rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i, + timerId, + fxAttrs = [ + // height animations + [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], + // width animations + [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], + // opacity animations + [ "opacity" ] + ], + fxNow, + requestAnimationFrame = window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame; + +jQuery.fn.extend({ + show: function( speed, easing, callback ) { + var elem, display; + + if ( speed || speed === 0 ) { + return this.animate( genFx("show", 3), speed, easing, callback); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + elem = this[i]; + + if ( elem.style ) { + display = elem.style.display; + + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !jQuery._data(elem, "olddisplay") && display === "none" ) { + display = elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( display === "" && jQuery.css( elem, "display" ) === "none" ) { + jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName)); + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + elem = this[i]; + + if ( elem.style ) { + display = elem.style.display; + + if ( display === "" || display === "none" ) { + elem.style.display = jQuery._data(elem, "olddisplay") || ""; + } + } + } + + return this; + } + }, + + hide: function( speed, easing, callback ) { + if ( speed || speed === 0 ) { + return this.animate( genFx("hide", 3), speed, easing, callback); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + if ( this[i].style ) { + var display = jQuery.css( this[i], "display" ); + + if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) { + jQuery._data( this[i], "olddisplay", display ); + } + } + } + + // Set the display of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + if ( this[i].style ) { + this[i].style.display = "none"; + } + } + + return this; + } + }, + + // Save the old toggle function + _toggle: jQuery.fn.toggle, + + toggle: function( fn, fn2, callback ) { + var bool = typeof fn === "boolean"; + + if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { + this._toggle.apply( this, arguments ); + + } else if ( fn == null || bool ) { + this.each(function() { + var state = bool ? fn : jQuery(this).is(":hidden"); + jQuery(this)[ state ? "show" : "hide" ](); + }); + + } else { + this.animate(genFx("toggle", 3), fn, fn2, callback); + } + + return this; + }, + + fadeTo: function( speed, to, easing, callback ) { + return this.filter(":hidden").css("opacity", 0).show().end() + .animate({opacity: to}, speed, easing, callback); + }, + + animate: function( prop, speed, easing, callback ) { + var optall = jQuery.speed(speed, easing, callback); + + if ( jQuery.isEmptyObject( prop ) ) { + return this.each( optall.complete, [ false ] ); + } + + // Do not change referenced properties as per-property easing will be lost + prop = jQuery.extend( {}, prop ); + + return this[ optall.queue === false ? "each" : "queue" ](function() { + // XXX 'this' does not always have a nodeName when running the + // test suite + + if ( optall.queue === false ) { + jQuery._mark( this ); + } + + var opt = jQuery.extend( {}, optall ), + isElement = this.nodeType === 1, + hidden = isElement && jQuery(this).is(":hidden"), + name, val, p, + display, e, + parts, start, end, unit; + + // will store per property easing and be used to determine when an animation is complete + opt.animatedProperties = {}; + + for ( p in prop ) { + + // property name normalization + name = jQuery.camelCase( p ); + if ( p !== name ) { + prop[ name ] = prop[ p ]; + delete prop[ p ]; + } + + val = prop[ name ]; + + // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default) + if ( jQuery.isArray( val ) ) { + opt.animatedProperties[ name ] = val[ 1 ]; + val = prop[ name ] = val[ 0 ]; + } else { + opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing'; + } + + if ( val === "hide" && hidden || val === "show" && !hidden ) { + return opt.complete.call( this ); + } + + if ( isElement && ( name === "height" || name === "width" ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE does not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height + // animated + if ( jQuery.css( this, "display" ) === "inline" && + jQuery.css( this, "float" ) === "none" ) { + if ( !jQuery.support.inlineBlockNeedsLayout ) { + this.style.display = "inline-block"; + + } else { + display = defaultDisplay( this.nodeName ); + + // inline-level elements accept inline-block; + // block-level elements need to be inline with layout + if ( display === "inline" ) { + this.style.display = "inline-block"; + + } else { + this.style.display = "inline"; + this.style.zoom = 1; + } + } + } + } + } + + if ( opt.overflow != null ) { + this.style.overflow = "hidden"; + } + + for ( p in prop ) { + e = new jQuery.fx( this, opt, p ); + val = prop[ p ]; + + if ( rfxtypes.test(val) ) { + e[ val === "toggle" ? hidden ? "show" : "hide" : val ](); + + } else { + parts = rfxnum.exec( val ); + start = e.cur(); + + if ( parts ) { + end = parseFloat( parts[2] ); + unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" ); + + // We need to compute starting value + if ( unit !== "px" ) { + jQuery.style( this, p, (end || 1) + unit); + start = ((end || 1) / e.cur()) * start; + jQuery.style( this, p, start + unit); + } + + // If a +=/-= token was provided, we're doing a relative animation + if ( parts[1] ) { + end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start; + } + + e.custom( start, end, unit ); + + } else { + e.custom( start, val, "" ); + } + } + } + + // For JS strict compliance + return true; + }); + }, + + stop: function( clearQueue, gotoEnd ) { + if ( clearQueue ) { + this.queue([]); + } + + this.each(function() { + var timers = jQuery.timers, + i = timers.length; + // clear marker counters if we know they won't be + if ( !gotoEnd ) { + jQuery._unmark( true, this ); + } + while ( i-- ) { + if ( timers[i].elem === this ) { + if (gotoEnd) { + // force the next step to be the last + timers[i](true); + } + + timers.splice(i, 1); + } + } + }); + + // start the next in the queue if the last step wasn't forced + if ( !gotoEnd ) { + this.dequeue(); + } + + return this; + } + +}); + +// Animations created synchronously will run synchronously +function createFxNow() { + setTimeout( clearFxNow, 0 ); + return ( fxNow = jQuery.now() ); +} + +function clearFxNow() { + fxNow = undefined; +} + +// Generate parameters to create a standard animation +function genFx( type, num ) { + var obj = {}; + + jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() { + obj[ this ] = type; + }); + + return obj; +} + +// Generate shortcuts for custom animations +jQuery.each({ + slideDown: genFx("show", 1), + slideUp: genFx("hide", 1), + slideToggle: genFx("toggle", 1), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +}); + +jQuery.extend({ + speed: function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction(easing) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default; + + // Queueing + opt.old = opt.complete; + opt.complete = function( noUnmark ) { + if ( opt.queue !== false ) { + jQuery.dequeue( this ); + } else if ( noUnmark !== false ) { + jQuery._unmark( this ); + } + + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + }; + + return opt; + }, + + easing: { + linear: function( p, n, firstNum, diff ) { + return firstNum + diff * p; + }, + swing: function( p, n, firstNum, diff ) { + return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; + } + }, + + timers: [], + + fx: function( elem, options, prop ) { + this.options = options; + this.elem = elem; + this.prop = prop; + + options.orig = options.orig || {}; + } + +}); + +jQuery.fx.prototype = { + // Simple function for setting a style value + update: function() { + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); + }, + + // Get the current size + cur: function() { + if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) { + return this.elem[ this.prop ]; + } + + var parsed, + r = jQuery.css( this.elem, this.prop ); + // Empty strings, null, undefined and "auto" are converted to 0, + // complex values such as "rotate(1rad)" are returned as is, + // simple values such as "10px" are parsed to Float. + return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed; + }, + + // Start an animation from one number to another + custom: function( from, to, unit ) { + var self = this, + fx = jQuery.fx, + raf; + + this.startTime = fxNow || createFxNow(); + this.start = from; + this.end = to; + this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" ); + this.now = this.start; + this.pos = this.state = 0; + + function t( gotoEnd ) { + return self.step(gotoEnd); + } + + t.elem = this.elem; + + if ( t() && jQuery.timers.push(t) && !timerId ) { + // Use requestAnimationFrame instead of setInterval if available + if ( requestAnimationFrame ) { + timerId = 1; + raf = function() { + // When timerId gets set to null at any point, this stops + if ( timerId ) { + requestAnimationFrame( raf ); + fx.tick(); + } + }; + requestAnimationFrame( raf ); + } else { + timerId = setInterval( fx.tick, fx.interval ); + } + } + }, + + // Simple 'show' function + show: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); + this.options.show = true; + + // Begin the animation + // Make sure that we start at a small width/height to avoid any + // flash of content + this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur()); + + // Start by showing the element + jQuery( this.elem ).show(); + }, + + // Simple 'hide' function + hide: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); + this.options.hide = true; + + // Begin the animation + this.custom(this.cur(), 0); + }, + + // Each step of an animation + step: function( gotoEnd ) { + var t = fxNow || createFxNow(), + done = true, + elem = this.elem, + options = this.options, + i, n; + + if ( gotoEnd || t >= options.duration + this.startTime ) { + this.now = this.end; + this.pos = this.state = 1; + this.update(); + + options.animatedProperties[ this.prop ] = true; + + for ( i in options.animatedProperties ) { + if ( options.animatedProperties[i] !== true ) { + done = false; + } + } + + if ( done ) { + // Reset the overflow + if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) { + + jQuery.each( [ "", "X", "Y" ], function (index, value) { + elem.style[ "overflow" + value ] = options.overflow[index]; + }); + } + + // Hide the element if the "hide" operation was done + if ( options.hide ) { + jQuery(elem).hide(); + } + + // Reset the properties, if the item has been hidden or shown + if ( options.hide || options.show ) { + for ( var p in options.animatedProperties ) { + jQuery.style( elem, p, options.orig[p] ); + } + } + + // Execute the complete function + options.complete.call( elem ); + } + + return false; + + } else { + // classical easing cannot be used with an Infinity duration + if ( options.duration == Infinity ) { + this.now = t; + } else { + n = t - this.startTime; + this.state = n / options.duration; + + // Perform the easing function, defaults to swing + this.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration ); + this.now = this.start + ((this.end - this.start) * this.pos); + } + // Perform the next step of the animation + this.update(); + } + + return true; + } +}; + +jQuery.extend( jQuery.fx, { + tick: function() { + for ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) { + if ( !timers[i]() ) { + timers.splice(i--, 1); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + }, + + interval: 13, + + stop: function() { + clearInterval( timerId ); + timerId = null; + }, + + speeds: { + slow: 600, + fast: 200, + // Default speed + _default: 400 + }, + + step: { + opacity: function( fx ) { + jQuery.style( fx.elem, "opacity", fx.now ); + }, + + _default: function( fx ) { + if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) { + fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit; + } else { + fx.elem[ fx.prop ] = fx.now; + } + } + } +}); + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.animated = function( elem ) { + return jQuery.grep(jQuery.timers, function( fn ) { + return elem === fn.elem; + }).length; + }; +} + +// Try to restore the default display value of an element +function defaultDisplay( nodeName ) { + + if ( !elemdisplay[ nodeName ] ) { + + var elem = jQuery( "<" + nodeName + ">" ).appendTo( "body" ), + display = elem.css( "display" ); + + elem.remove(); + + // If the simple way fails, + // get element's real default display by attaching it to a temp iframe + if ( display === "none" || display === "" ) { + // No iframe to use yet, so create it + if ( !iframe ) { + iframe = document.createElement( "iframe" ); + iframe.frameBorder = iframe.width = iframe.height = 0; + } + + document.body.appendChild( iframe ); + + // Create a cacheable copy of the iframe document on first call. + // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake html + // document to it, Webkit & Firefox won't allow reusing the iframe document + if ( !iframeDoc || !iframe.createElement ) { + iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document; + iframeDoc.write( "<!doctype><html><body></body></html>" ); + } + + elem = iframeDoc.createElement( nodeName ); + + iframeDoc.body.appendChild( elem ); + + display = jQuery.css( elem, "display" ); + + document.body.removeChild( iframe ); + } + + // Store the correct default display + elemdisplay[ nodeName ] = display; + } + + return elemdisplay[ nodeName ]; +} + + + + +var rtable = /^t(?:able|d|h)$/i, + rroot = /^(?:body|html)$/i; + +if ( "getBoundingClientRect" in document.documentElement ) { + jQuery.fn.offset = function( options ) { + var elem = this[0], box; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + try { + box = elem.getBoundingClientRect(); + } catch(e) {} + + var doc = elem.ownerDocument, + docElem = doc.documentElement; + + // Make sure we're not dealing with a disconnected DOM node + if ( !box || !jQuery.contains( docElem, elem ) ) { + return box ? { top: box.top, left: box.left } : { top: 0, left: 0 }; + } + + var body = doc.body, + win = getWindow(doc), + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop, + scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft, + top = box.top + scrollTop - clientTop, + left = box.left + scrollLeft - clientLeft; + + return { top: top, left: left }; + }; + +} else { + jQuery.fn.offset = function( options ) { + var elem = this[0]; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + jQuery.offset.initialize(); + + var computedStyle, + offsetParent = elem.offsetParent, + prevOffsetParent = elem, + doc = elem.ownerDocument, + docElem = doc.documentElement, + body = doc.body, + defaultView = doc.defaultView, + prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle, + top = elem.offsetTop, + left = elem.offsetLeft; + + while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { + if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { + break; + } + + computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle; + top -= elem.scrollTop; + left -= elem.scrollLeft; + + if ( elem === offsetParent ) { + top += elem.offsetTop; + left += elem.offsetLeft; + + if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevOffsetParent = offsetParent; + offsetParent = elem.offsetParent; + } + + if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevComputedStyle = computedStyle; + } + + if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) { + top += body.offsetTop; + left += body.offsetLeft; + } + + if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { + top += Math.max( docElem.scrollTop, body.scrollTop ); + left += Math.max( docElem.scrollLeft, body.scrollLeft ); + } + + return { top: top, left: left }; + }; +} + +jQuery.offset = { + initialize: function() { + var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0, + html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>"; + + jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } ); + + container.innerHTML = html; + body.insertBefore( container, body.firstChild ); + innerDiv = container.firstChild; + checkDiv = innerDiv.firstChild; + td = innerDiv.nextSibling.firstChild.firstChild; + + this.doesNotAddBorder = (checkDiv.offsetTop !== 5); + this.doesAddBorderForTableAndCells = (td.offsetTop === 5); + + checkDiv.style.position = "fixed"; + checkDiv.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15); + checkDiv.style.position = checkDiv.style.top = ""; + + innerDiv.style.overflow = "hidden"; + innerDiv.style.position = "relative"; + + this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5); + + this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); + + body.removeChild( container ); + jQuery.offset.initialize = jQuery.noop; + }, + + bodyOffset: function( body ) { + var top = body.offsetTop, + left = body.offsetLeft; + + jQuery.offset.initialize(); + + if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) { + top += parseFloat( jQuery.css(body, "marginTop") ) || 0; + left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; + } + + return { top: top, left: left }; + }, + + setOffset: function( elem, options, i ) { + var position = jQuery.css( elem, "position" ); + + // set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + var curElem = jQuery( elem ), + curOffset = curElem.offset(), + curCSSTop = jQuery.css( elem, "top" ), + curCSSLeft = jQuery.css( elem, "left" ), + calculatePosition = (position === "absolute" || position === "fixed") && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1, + props = {}, curPosition = {}, curTop, curLeft; + + // need to be able to calculate position if either top or left is auto and position is either absolute or fixed + if ( calculatePosition ) { + curPosition = curElem.position(); + curTop = curPosition.top; + curLeft = curPosition.left; + } else { + curTop = parseFloat( curCSSTop ) || 0; + curLeft = parseFloat( curCSSLeft ) || 0; + } + + if ( jQuery.isFunction( options ) ) { + options = options.call( elem, i, curOffset ); + } + + if (options.top != null) { + props.top = (options.top - curOffset.top) + curTop; + } + if (options.left != null) { + props.left = (options.left - curOffset.left) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + } +}; + + +jQuery.fn.extend({ + position: function() { + if ( !this[0] ) { + return null; + } + + var elem = this[0], + + // Get *real* offsetParent + offsetParent = this.offsetParent(), + + // Get correct offsets + offset = this.offset(), + parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + + // Subtract element margins + // note: when an element has margin: auto the offsetLeft and marginLeft + // are the same in Safari causing offset.left to incorrectly be 0 + offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; + offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; + + // Add offsetParent borders + parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; + parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; + + // Subtract the two offsets + return { + top: offset.top - parentOffset.top, + left: offset.left - parentOffset.left + }; + }, + + offsetParent: function() { + return this.map(function() { + var offsetParent = this.offsetParent || document.body; + while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent; + }); + } +}); + + +// Create scrollLeft and scrollTop methods +jQuery.each( ["Left", "Top"], function( i, name ) { + var method = "scroll" + name; + + jQuery.fn[ method ] = function( val ) { + var elem, win; + + if ( val === undefined ) { + elem = this[ 0 ]; + + if ( !elem ) { + return null; + } + + win = getWindow( elem ); + + // Return the scroll offset + return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + + // Set the scroll offset + return this.each(function() { + win = getWindow( this ); + + if ( win ) { + win.scrollTo( + !i ? val : jQuery( win ).scrollLeft(), + i ? val : jQuery( win ).scrollTop() + ); + + } else { + this[ method ] = val; + } + }); + }; +}); + +function getWindow( elem ) { + return jQuery.isWindow( elem ) ? + elem : + elem.nodeType === 9 ? + elem.defaultView || elem.parentWindow : + false; +} + + + + +// Create innerHeight, innerWidth, outerHeight and outerWidth methods +jQuery.each([ "Height", "Width" ], function( i, name ) { + + var type = name.toLowerCase(); + + // innerHeight and innerWidth + jQuery.fn["inner" + name] = function() { + return this[0] ? + parseFloat( jQuery.css( this[0], type, "padding" ) ) : + null; + }; + + // outerHeight and outerWidth + jQuery.fn["outer" + name] = function( margin ) { + return this[0] ? + parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) : + null; + }; + + jQuery.fn[ type ] = function( size ) { + // Get window width or height + var elem = this[0]; + if ( !elem ) { + return size == null ? null : this; + } + + if ( jQuery.isFunction( size ) ) { + return this.each(function( i ) { + var self = jQuery( this ); + self[ type ]( size.call( this, i, self[ type ]() ) ); + }); + } + + if ( jQuery.isWindow( elem ) ) { + // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode + // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat + var docElemProp = elem.document.documentElement[ "client" + name ]; + return elem.document.compatMode === "CSS1Compat" && docElemProp || + elem.document.body[ "client" + name ] || docElemProp; + + // Get document width or height + } else if ( elem.nodeType === 9 ) { + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + return Math.max( + elem.documentElement["client" + name], + elem.body["scroll" + name], elem.documentElement["scroll" + name], + elem.body["offset" + name], elem.documentElement["offset" + name] + ); + + // Get or set width or height on the element + } else if ( size === undefined ) { + var orig = jQuery.css( elem, type ), + ret = parseFloat( orig ); + + return jQuery.isNaN( ret ) ? orig : ret; + + // Set the width or height on the element (default to pixels if value is unitless) + } else { + return this.css( type, typeof size === "string" ? size : size + "px" ); + } + }; + +}); + + +window.jQuery = window.$ = jQuery; +})(window); diff --git a/phpgwapi/js/jquery/jqplot/jquery.min.js b/phpgwapi/js/jquery/jqplot/jquery.min.js new file mode 100644 index 0000000000..b2ac1747f3 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/jquery.min.js @@ -0,0 +1,18 @@ +/*! + * jQuery JavaScript Library v1.6.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu May 12 15:04:36 2011 -0400 + */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!cj[a]){var b=f("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),c.body.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write("<!doctype><html><body></body></html>");b=cl.createElement(a),cl.body.appendChild(b),d=f.css(b,"display"),c.body.removeChild(ck)}cj[a]=d}return cj[a]}function cu(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function ct(){cq=b}function cs(){setTimeout(ct,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bF.test(a)?d(a,e):b_(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bU,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bQ),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bD(a,b,c){var d=b==="width"?bx:by,e=b==="width"?a.offsetWidth:a.offsetHeight;if(c==="border")return e;f.each(d,function(){c||(e-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?e+=parseFloat(f.css(a,"margin"+this))||0:e-=parseFloat(f.css(a,"border"+this+"Width"))||0});return e}function bn(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bm(a){f.nodeName(a,"input")?bl(a):a.getElementsByTagName&&f.grep(a.getElementsByTagName("input"),bl)}function bl(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bk(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bj(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bi(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bh(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function X(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(S.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function W(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function O(a,b){return(a&&a!=="*"?a+".":"")+b.replace(A,"`").replace(B,"&")}function N(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(y,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function L(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function F(){return!0}function E(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function H(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(H,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=d.userAgent,x,y,z,A=Object.prototype.toString,B=Object.prototype.hasOwnProperty,C=Array.prototype.push,D=Array.prototype.slice,E=String.prototype.trim,F=Array.prototype.indexOf,G={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.1",length:0,size:function(){return this.length},toArray:function(){return D.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?C.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(D.apply(this,arguments),"slice",D.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:C,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;y.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!y){y=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",z,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",z),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&H()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):G[A.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!B.call(a,"constructor")&&!B.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||B.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:E?function(a){return a==null?"":E.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?C.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(F)return F.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=D.call(arguments,2),g=function(){return a.apply(c,f.concat(D.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){G["[object "+b+"]"]=b.toLowerCase()}),x=e.uaMatch(w),x.browser&&(e.browser[x.browser]=!0,e.browser.version=x.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?z=function(){c.removeEventListener("DOMContentLoaded",z,!1),e.ready()}:c.attachEvent&&(z=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",z),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g](h)}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};f=c.createElement("select"),g=f.appendChild(c.createElement("option")),h=a.getElementsByTagName("input")[0],j={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},h.checked=!0,j.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,j.optDisabled=!g.disabled;try{delete a.test}catch(s){j.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function b(){j.noCloneEvent=!1,a.detachEvent("onclick",b)}),a.cloneNode(!0).fireEvent("onclick")),h=c.createElement("input"),h.value="t",h.setAttribute("type","radio"),j.radioValue=h.value==="t",h.setAttribute("checked","checked"),a.appendChild(h),k=c.createDocumentFragment(),k.appendChild(a.firstChild),j.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",l=c.createElement("body"),m={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};for(q in m)l.style[q]=m[q];l.appendChild(a),b.insertBefore(l,b.firstChild),j.appendChecked=h.checked,j.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,j.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",j.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",n=a.getElementsByTagName("td"),r=n[0].offsetHeight===0,n[0].style.display="",n[1].style.display="none",j.reliableHiddenOffsets=r&&n[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(i=c.createElement("div"),i.style.width="0",i.style.marginRight="0",a.appendChild(i),j.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(i,null)||{marginRight:0}).marginRight,10)||0)===0),l.innerHTML="",b.removeChild(l);if(a.attachEvent)for(q in{submit:1,change:1,focusin:1})p="on"+q,r=p in a,r||(a.setAttribute(p,"return;"),r=typeof a[p]=="function"),j[q+"Bubbles"]=r;return j}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u=/\:/,v,w;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.addClass(a.call(this,b,c.attr("class")||""))});if(a&&typeof a=="string"){var b=(a||"").split(o);for(var c=0,d=this.length;c<d;c++){var e=this[c];if(e.nodeType===1)if(!e.className)e.className=a;else{var g=" "+e.className+" ",h=e.className;for(var i=0,j=b.length;i<j;i++)g.indexOf(" "+b[i]+" ")<0&&(h+=" "+b[i]);e.className=f.trim(h)}}}return this},removeClass:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.removeClass(a.call(this,b,c.attr("class")))});if(a&&typeof a=="string"||a===b){var c=(a||"").split(o);for(var d=0,e=this.length;d<e;d++){var g=this[d];if(g.nodeType===1&&g.className)if(a){var h=(" "+g.className+" ").replace(n," ");for(var i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){var d=f(this);d.toggleClass(a.call(this,c,d.attr("class"),b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;return(e.value||"").replace(p,"")}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);c=j&&f.attrFix[c]||c,i=f.attrHooks[c],i||(!t.test(c)||typeof d!="boolean"&&d!==b&&d.toLowerCase()!==c.toLowerCase()?v&&(f.nodeName(a,"form")||u.test(c))&&(i=v):i=w);if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j)return i.get(a,c);h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);c=i&&f.propFix[c]||c,h=f.propHooks[c];return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return a[f.propFix[c]||c]?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=b),a.setAttribute(c,c.toLowerCase()));return c}},f.attrHooks.value={get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return a.value},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=Object.prototype.hasOwnProperty,y=/\.(.*)$/,z=/^(?:textarea|input|select)$/i,A=/\./g,B=/ /g,C=/[^\w\s.|`]/g,D=function(a){return a.replace(C,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=E;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=E);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),D).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem +)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,O(a.origType,a.selector),f.extend({},a,{handler:N,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,O(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?F:E):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=F;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=F;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=F,this.stopPropagation()},isDefaultPrevented:E,isPropagationStopped:E,isImmediatePropagationStopped:E};var G=function(a){var b=a.relatedTarget;a.type=a.data;try{if(b&&b!==c&&!b.parentNode)return;while(b&&b!==this)b=b.parentNode;b!==this&&f.event.handle.apply(this,arguments)}catch(d){}},H=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?H:G,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?H:G)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&f(b).closest("form").length&&L("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&L("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var I,J=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},K=function(c){var d=c.target,e,g;if(!!z.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=J(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:K,beforedeactivate:K,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&K.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&K.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",J(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in I)f.event.add(this,c+".specialChange",I[c]);return z.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return z.test(this.nodeName)}},I=f.event.special.change.filters,I.focus=I.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var M={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||E,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=y.exec(h),k="",j&&(k=j[0],h=h.replace(y,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,M[h]?(a.push(M[h]+k),h=h+k):h=(M[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+O(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+O(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var P=/Until$/,Q=/^(?:parents|prevUntil|prevAll)/,R=/,/,S=/^.[^:#\[\.,]*$/,T=Array.prototype.slice,U=f.expr.match.POS,V={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(X(this,a,!1),"not",a)},filter:function(a){return this.pushStack(X(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=U.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=U.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(W(c[0])||W(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=T.call(arguments);P.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!V[a]?f.unique(e):e,(this.length>1||R.test(d))&&Q.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var Y=/ jQuery\d+="(?:\d+|null)"/g,Z=/^\s+/,$=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,_=/<([\w:]+)/,ba=/<tbody/i,bb=/<|&#?\w+;/,bc=/<(?:script|object|embed|option|style)/i,bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Y,""):null;if(typeof a=="string"&&!bc.test(a)&&(f.support.leadingWhitespace||!Z.test(a))&&!bg[(_.exec(a)||["",""])[1].toLowerCase()]){a=a.replace($,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bh(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bn)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i=b&&b[0]?b[0].ownerDocument||b[0]:c;a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!bc.test(a[0])&&(f.support.checkClone||!bd.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bj(a,d),e=bk(a),g=bk(d);for(h=0;e[h];++h)bj(e[h],g[h])}if(b){bi(a,d);if(c){e=bk(a),g=bk(d);for(h=0;e[h];++h)bi(e[h],g[h])}}return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument|| +b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!bb.test(k))k=b.createTextNode(k);else{k=k.replace($,"<$1></$2>");var l=(_.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=ba.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Z.test(k)&&o.insertBefore(b.createTextNode(Z.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bm(k[i]);else bm(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bo=/alpha\([^)]*\)/i,bp=/opacity=([^)]*)/,bq=/-([a-z])/ig,br=/([A-Z]|^ms)/g,bs=/^-?\d+(?:px)?$/i,bt=/^-?\d/,bu=/^[+\-]=/,bv=/[^+\-\.\de]+/g,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB,bC=function(a,b){return b.toUpperCase()};f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0,widows:!0,orphans:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d;if(h==="number"&&isNaN(d)||d==null)return;h==="string"&&bu.test(d)&&(d=+d.replace(bv,"")+parseFloat(f.css(a,c))),h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bq,bC)}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){a.offsetWidth!==0?e=bD(a,b,d):f.swap(a,bw,function(){e=bD(a,b,d)});if(e<=0){e=bz(a,b,b),e==="0px"&&bB&&(e=bB(a,b,b));if(e!=null)return e===""||e==="auto"?"0px":e}if(e<0||e==null){e=a.style[b];return e===""||e==="auto"?"0px":e}return typeof e=="string"?e:e+"px"}},set:function(a,b){if(!bs.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bp.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bo.test(g)?g.replace(bo,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,c){var d,e,g;c=c.replace(br,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bs.test(d)&&bt.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bE=/%20/g,bF=/\[\]$/,bG=/\r?\n/g,bH=/#.*$/,bI=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bJ=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bK=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bL=/^(?:GET|HEAD)$/,bM=/^\/\//,bN=/\?/,bO=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bP=/^(?:select|textarea)/i,bQ=/\s+/,bR=/([?&])_=[^&]*/,bS=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bT=f.fn.load,bU={},bV={},bW,bX;try{bW=e.href}catch(bY){bW=c.createElement("a"),bW.href="",bW=bW.href}bX=bS.exec(bW.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bT)return bT.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bO,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bP.test(this.nodeName)||bJ.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bG,"\r\n")}}):{name:b.name,value:c.replace(bG,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bW,isLocal:bK.test(bX[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bZ(bU),ajaxTransport:bZ(bV),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?ca(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=cb(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bI.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bH,"").replace(bM,bX[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bQ),d.crossDomain==null&&(r=bS.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bX[1]&&r[2]==bX[2]&&(r[3]||(r[1]==="http:"?80:443))==(bX[3]||(bX[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bU,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bL.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bN.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bR,"$1_="+x);d.url=y+(y===d.url?(bN.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bV,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bE,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq,cr=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cv(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cm.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=cn.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this),f.isFunction(d.old)&&d.old.call(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function h(a){return d.step(a)}var d=this,e=f.fx,g;this.startTime=cq||cs(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,h.elem=this.elem,h()&&f.timers.push(h)&&!co&&(cr?(co=1,g=function(){co&&(cr(g),e.tick())},cr(g)):co=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cq||cs(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){return this[0]?parseFloat(f.css(this[0],d,"padding")):null},f.fn["outer"+c]=function(a){return this[0]?parseFloat(f.css(this[0],d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/optionsTutorial.txt b/phpgwapi/js/jquery/jqplot/optionsTutorial.txt new file mode 100644 index 0000000000..3e68825e4d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/optionsTutorial.txt @@ -0,0 +1,239 @@ +Title: Options Tutorial + +This document will help you understand how jqPlot's options +relate to the API documentation and the jqPlot object +itself. For a listing of options available to jqPlot, +see <jqPlot Options> in the jqPlotOptions.txt file. + +The key to effectively using jqPlot is understanding jqPlot's +options. The online documentation is API documentation. While +it explains what attributes and methods various objects posses, +it doesn't explain how to use or set those attributes through +options. This tutorial will help explain that. + +Lets assume you are creating a plot +like this: + +> chart = $.jqplot('chart', dataSeries, optionsObj); + +First, note that you shouldn't try to directly set attributes on the +"chart" object (like chart.grid.shadow) after your call to $.jqplot(). +At best this won't do anything **(see below). You should pass options in via +the "optionsObj". + +the optionsObj really represents the plot object (jqPlot object, not +to be confused with the $.jqplot function which will create a jqPlot +object). Attributes you specify on that object will be merged with +attributes in the jqPlot object. The axes, legend, series, etc. are +attributes on the jqPlot object. The jqPlot/optionsObj object looks +something like (only some attributes shown): + +> jqPlot-| +> |-seriesColors +> |-textColor +> |-fontFamily +> |-fontSize +> |-stackSeries +> |-series(Array)-| +> | |-Series1-| +> | | |-lineWidth +> | | |-shadow +> | | |-showLine +> | | |-showMarker +> | | |-color +> | |-Series2... +> | |-... +> | |-SeriesN +> | +> |-grid(Object)-| +> | |-drawGridLines +> | |-background +> | |-borderColor +> | |-borderWidth +> | |-shadow +> | +> |-title(Object)-| +> | |-text +> | |-show +> | |-fontFamily +> | |-fontSize +> | |-textAlign +> | |-textColor +> | +> |-axes(Object)-| +> | |-xais-| +> | | |-min +> | | |-max +> | | |-numberTicks +> | | |-showTicks +> | | |-showTickMarks +> | | |-pad +> | +> | ... and so on + +The optionsObj should follow the same construction as if it were a +jqPlot object (with some exceptions/shortcuts I'll mention in a +moment). So generally, when you see something like +"this.drawGridLines" in the grid properties in the docs, just replace +"this" with "grid" in your options object. So it becomes +optionsObj.grid.drawGridLines. Do likewise with the other objects in +the plot, replacing "this", with the respective attribute on the plot +like "legend" or "title". Series and Axes are handled a little +different, because series is an array and axes has 4 distinct children +"xaxis", "yaxis", "x2axis" and "y2axis". + +So, to remove the shadow from the grid and change the grid border size +you would do: + +> optionObj = {grid:{shadow:false, borderWidth:9.0}}; + +To do the same as above but also make all the text in the plot red you +would do: + +> optionObj = { +> textColor:"#ff0000", +> grid:{shadow:false, borderWidth:9.0} +> } + +Here is a more deeply nested example. Say you want to specify a min +and max on your y axis and use a specific color for your second +series. That would look like: + +> optionsObj = { +> axes:{yaxis:{min:5, max:230}}, +> series:[{},{color:"#33ff66"}] +> } + +Note that series options are an array in order of the series data you +sent in to your plot. To get to the second series, you have to put an +object (even if empty) in place of the first series. + +There is a handy shortcut to assign options to all axes or all series +at one go. Use axesDefaults and seriesDefaults. So, if you wanted +both x and y axes to start at 0 and you wanted all series to not show +markers, you could do: + +> optionsObj = {axesDefaults:{min:0}, seriesDefaults:{showMarker:false}} + +Another shortcut is for the plot title. Normally, you would assign +options to the title as an object. If you specify a title option as a +string, it will assign that to the title.text property automatically. +So these two are equivalent: + +> optionsObj = {title:{text:"My Plot"}} + +and + +> optionsObj = {title:"My Plot"} + +Where things need more explaination is with renderers, plugins and +their options. Briefly, what's renderer, what's a plugin. + +A renderer is an object that is used to draw something and gets +attached to an existing object in the plot in order to draw it. A +plugin does more than just provide drawing functionality to an +object. It will do more like calculate a trend line, change the +cursor, provide event driven functionality, etc. I consider renderers +plugins, but plugins don't have to be renderers. + +So, how do you use renderers, plugins, and specify their options? +Some common renderes are for bar charts and category axes. If you +want to render your series as a bar chart with each set of bars +showing up in a category on the x axis, you do: + +> optionsObj = { +> seriesDefaults:{renderer:$.jqplot.BarRenderer}, +> axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}} +> } + +This replaces the default renderer used for all series in the plot +with a bar renderer and the x axis default renderer (but not any other +axis) with a category renderer. + +Now, how would I assign options to those renderers? The renderer's +attributes may not be present in the pre-existing jqPlot object, they +may be specific to the renderer. This is done through the +"rendererOptions" option on the appropriate object. So, if I wanted my +bars to be 25 pixels wide, I would do: + + +> optionsObj = { +> seriesDefaults:{ +> renderer:$.jqplot.BarRenderer}, +> rendererOptions:{ +> barWidth:25 +> }, +> axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}} +> } + +Again, this is using the "seriesDefaults" option, which will apply +options to all series in the plot. You could do the same on any +particular series in the plot through the "series" options array. + +Plugins are free to add their own options. For example, the +highlighter plugin has it's own set of options that are unique to it. +As a result, it responds to options placed in the "highlighter" +attribute of your options object. So, if I wanted to change the +highlighter tooltip to fade in and out slowly and be positioned +directly above the point I'm highlighting: + +> optionsObj = { +> highlighter:{tooltipFadeSpeed:'slow', tooltipLocation:'n'} +> } + +Other plugins, like dragable and trendlines, add their options in with +the series. This is because both of those plugins can have different +options for different series in the plot. So, if you wanted to specify the +color of the dragable and constrain it to drag only on the x axis as well +as specify the color of the trend line you could do: + +> series:[{ +> dragable: { +> color: '#ff3366', +> constrainTo: 'x' +> }, +> trendline: { +> color: '#cccccc' +> } +> }] + +This would apply those options to the first series only. If you had 2 series +and wanted to turn off dragging and trend lines on the second series, you could do: + +> series:[{ +> dragable: { +> color: '#ff3366', +> constrainTo: 'x' +> }, +> trendline: { +> color: '#cccccc' +> } +> }, { +> isDragable: false, +> trendline:{ +> show: false +> } +> }] + +Note, series dragability is turned off with the "isDragable" option directly on +the series itself, not with a suboption of "dragable". This may be improved +in the future. + +I hope this is helpful. +A few key points to remember: + +- When you see "this" in the api docs, you generally replace it with +the name of the object (in lowercase) you are looking at in your +options object. +- seriesDefaults and axesDefaults are convenient shortcuts. +- to assign options to a renderer, generally use the "rendererOptions" +- plugins may add their own options attribute, like "highlighter" or +"cursor". + +** Note: you can set attributes after the plot is created (like +plot.grid.shadow = false), but you'll have to issue the appropriate +calls to possibly reinitialize and redraw the plot. jqPlot can +definitely handle this to change the plot after creation (this is how +the dragable plugin updates the plot data and the trend line plugin +recomputes itself when data changes). This hasn't been documented +yet, however. \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.BezierCurveRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.BezierCurveRenderer.js new file mode 100644 index 0000000000..a1d29666b9 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.BezierCurveRenderer.js @@ -0,0 +1,312 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + // Class: $.jqplot.BezierCurveRenderer.js + // Renderer which draws lines as stacked bezier curves. + // Data for the line will not be specified as an array of + // [x, y] data point values, but as a an array of [start piont, bezier curve] + // So, the line is specified as: [[xstart, ystart], [cp1x, cp1y, cp2x, cp2y, xend, yend]]. + $.jqplot.BezierCurveRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.BezierCurveRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.BezierCurveRenderer.prototype.constructor = $.jqplot.BezierCurveRenderer; + + + // Method: setGridData + // converts the user data values to grid coordinates and stores them + // in the gridData array. + // Called with scope of a series. + $.jqplot.BezierCurveRenderer.prototype.setGridData = function(plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + // this._plotData should be same as this.data + var data = this.data; + this.gridData = []; + this._prevGridData = []; + // if seriesIndex = 0, fill to x axis. + // if seriesIndex > 0, fill to previous series data. + var idx = this.index; + if (data.length == 2) { + if (idx == 0) { + this.gridData = [ + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], + [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), + xp.call(this._xaxis, data[1][2]), yp.call(this._yaxis, data[1][3]), + xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, data[1][5])], + [xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, this._yaxis.min)], + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, this._yaxis.min)] + ]; + } + else { + var psd = plot.series[idx-1].data; + this.gridData = [ + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], + [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), + xp.call(this._xaxis, data[1][2]), yp.call(this._yaxis, data[1][3]), + xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, data[1][5])], + [xp.call(this._xaxis, psd[1][4]), yp.call(this._yaxis, psd[1][5])], + [xp.call(this._xaxis, psd[1][2]), yp.call(this._yaxis, psd[1][3]), + xp.call(this._xaxis, psd[1][0]), yp.call(this._yaxis, psd[1][1]), + xp.call(this._xaxis, psd[0][0]), yp.call(this._yaxis, psd[0][1])] + ]; + } + } + else { + if (idx == 0) { + this.gridData = [ + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], + [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), + xp.call(this._xaxis, data[2][0]), yp.call(this._yaxis, data[2][1]), + xp.call(this._xaxis, data[3][0]), yp.call(this._yaxis, data[3][1])], + [xp.call(this._xaxis, data[3][1]), yp.call(this._yaxis, this._yaxis.min)], + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, this._yaxis.min)] + ]; + } + else { + var psd = plot.series[idx-1].data; + this.gridData = [ + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], + [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), + xp.call(this._xaxis, data[2][0]), yp.call(this._yaxis, data[2][1]), + xp.call(this._xaxis, data[3][0]), yp.call(this._yaxis, data[3][1])], + [xp.call(this._xaxis, psd[3][0]), yp.call(this._yaxis, psd[3][1])], + [xp.call(this._xaxis, psd[2][0]), yp.call(this._yaxis, psd[2][1]), + xp.call(this._xaxis, psd[1][0]), yp.call(this._yaxis, psd[1][1]), + xp.call(this._xaxis, psd[0][0]), yp.call(this._yaxis, psd[0][1])] + ]; + } + } + }; + + // Method: makeGridData + // converts any arbitrary data values to grid coordinates and + // returns them. This method exists so that plugins can use a series' + // linerenderer to generate grid data points without overwriting the + // grid data associated with that series. + // Called with scope of a series. + $.jqplot.BezierCurveRenderer.prototype.makeGridData = function(data, plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var gd = []; + var pgd = []; + // if seriesIndex = 0, fill to x axis. + // if seriesIndex > 0, fill to previous series data. + var idx = this.index; + if (data.length == 2) { + if (idx == 0) { + gd = [ + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], + [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), + xp.call(this._xaxis, data[1][2]), yp.call(this._yaxis, data[1][3]), + xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, data[1][5])], + [xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, this._yaxis.min)], + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, this._yaxis.min)] + ]; + } + else { + var psd = plot.series[idx-1].data; + gd = [ + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], + [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), + xp.call(this._xaxis, data[1][2]), yp.call(this._yaxis, data[1][3]), + xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, data[1][5])], + [xp.call(this._xaxis, psd[1][4]), yp.call(this._yaxis, psd[1][5])], + [xp.call(this._xaxis, psd[1][2]), yp.call(this._yaxis, psd[1][3]), + xp.call(this._xaxis, psd[1][0]), yp.call(this._yaxis, psd[1][1]), + xp.call(this._xaxis, psd[0][0]), yp.call(this._yaxis, psd[0][1])] + ]; + } + } + else { + if (idx == 0) { + gd = [ + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], + [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), + xp.call(this._xaxis, data[2][0]), yp.call(this._yaxis, data[2][1]), + xp.call(this._xaxis, data[3][0]), yp.call(this._yaxis, data[3][1])], + [xp.call(this._xaxis, data[3][1]), yp.call(this._yaxis, this._yaxis.min)], + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, this._yaxis.min)] + ]; + } + else { + var psd = plot.series[idx-1].data; + gd = [ + [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], + [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), + xp.call(this._xaxis, data[2][0]), yp.call(this._yaxis, data[2][1]), + xp.call(this._xaxis, data[3][0]), yp.call(this._yaxis, data[3][1])], + [xp.call(this._xaxis, psd[3][0]), yp.call(this._yaxis, psd[3][1])], + [xp.call(this._xaxis, psd[2][0]), yp.call(this._yaxis, psd[2][1]), + xp.call(this._xaxis, psd[1][0]), yp.call(this._yaxis, psd[1][1]), + xp.call(this._xaxis, psd[0][0]), yp.call(this._yaxis, psd[0][1])] + ]; + } + } + return gd; + }; + + + // called within scope of series. + $.jqplot.BezierCurveRenderer.prototype.draw = function(ctx, gd, options) { + var i; + ctx.save(); + if (gd.length) { + if (this.showLine) { + ctx.save(); + var opts = (options != null) ? options : {}; + ctx.fillStyle = opts.fillStyle || this.color; + ctx.beginPath(); + ctx.moveTo(gd[0][0], gd[0][1]); + ctx.bezierCurveTo(gd[1][0], gd[1][1], gd[1][2], gd[1][3], gd[1][4], gd[1][5]); + ctx.lineTo(gd[2][0], gd[2][1]); + if (gd[3].length == 2) { + ctx.lineTo(gd[3][0], gd[3][1]); + } + else { + ctx.bezierCurveTo(gd[3][0], gd[3][1], gd[3][2], gd[3][3], gd[3][4], gd[3][5]); + } + ctx.closePath(); + ctx.fill(); + ctx.restore(); + } + } + + ctx.restore(); + }; + + $.jqplot.BezierCurveRenderer.prototype.drawShadow = function(ctx, gd, options) { + // This is a no-op, shadows drawn with lines. + }; + + $.jqplot.BezierAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + }; + + $.jqplot.BezierAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.BezierAxisRenderer.prototype.constructor = $.jqplot.BezierAxisRenderer; + + + // Axes on a plot with Bezier Curves + $.jqplot.BezierAxisRenderer.prototype.init = function(options){ + $.extend(true, this, options); + var db = this._dataBounds; + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + var d = s.data; + if (d.length == 4) { + for (var j=0; j<d.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + if (d[j][0] < db.min || db.min == null) { + db.min = d[j][0]; + } + if (d[j][0] > db.max || db.max == null) { + db.max = d[j][0]; + } + } + else { + if (d[j][1] < db.min || db.min == null) { + db.min = d[j][1]; + } + if (d[j][1] > db.max || db.max == null) { + db.max = d[j][1]; + } + } + } + } + else { + if (this.name == 'xaxis' || this.name == 'x2axis') { + if (d[0][0] < db.min || db.min == null) { + db.min = d[0][0]; + } + if (d[0][0] > db.max || db.max == null) { + db.max = d[0][0]; + } + for (var j=0; j<5; j+=2) { + if (d[1][j] < db.min || db.min == null) { + db.min = d[1][j]; + } + if (d[1][j] > db.max || db.max == null) { + db.max = d[1][j]; + } + } + } + else { + if (d[0][1] < db.min || db.min == null) { + db.min = d[0][1]; + } + if (d[0][1] > db.max || db.max == null) { + db.max = d[0][1]; + } + for (var j=1; j<6; j+=2) { + if (d[1][j] < db.min || db.min == null) { + db.min = d[1][j]; + } + if (d[1][j] > db.max || db.max == null) { + db.max = d[1][j]; + } + } + } + } + } + }; + + // setup default renderers for axes and legend so user doesn't have to + // called with scope of plot + function preInit(target, data, options) { + options = options || {}; + options.axesDefaults = $.extend(true, {pad:0}, options.axesDefaults); + options.legend = $.extend(true, {placement:'outside'}, options.legend); + // only set these if there is a pie series + var setopts = false; + if (options.seriesDefaults.renderer == $.jqplot.BezierCurveRenderer) { + setopts = true; + } + else if (options.series) { + for (var i=0; i < options.series.length; i++) { + if (options.series[i].renderer == $.jqplot.BezierCurveRenderer) { + setopts = true; + } + } + } + + if (setopts) { + options.axesDefaults.renderer = $.jqplot.BezierAxisRenderer; + } + } + + $.jqplot.preInitHooks.push(preInit); + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.BezierCurveRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.BezierCurveRenderer.min.js new file mode 100644 index 0000000000..246b747952 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.BezierCurveRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(b){b.jqplot.BezierCurveRenderer=function(){b.jqplot.LineRenderer.call(this)};b.jqplot.BezierCurveRenderer.prototype=new b.jqplot.LineRenderer();b.jqplot.BezierCurveRenderer.prototype.constructor=b.jqplot.BezierCurveRenderer;b.jqplot.BezierCurveRenderer.prototype.setGridData=function(h){var e=this._xaxis.series_u2p;var g=this._yaxis.series_u2p;var f=this.data;this.gridData=[];this._prevGridData=[];var d=this.index;if(f.length==2){if(d==0){this.gridData=[[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,f[0][1])],[e.call(this._xaxis,f[1][0]),g.call(this._yaxis,f[1][1]),e.call(this._xaxis,f[1][2]),g.call(this._yaxis,f[1][3]),e.call(this._xaxis,f[1][4]),g.call(this._yaxis,f[1][5])],[e.call(this._xaxis,f[1][4]),g.call(this._yaxis,this._yaxis.min)],[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,this._yaxis.min)]]}else{var c=h.series[d-1].data;this.gridData=[[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,f[0][1])],[e.call(this._xaxis,f[1][0]),g.call(this._yaxis,f[1][1]),e.call(this._xaxis,f[1][2]),g.call(this._yaxis,f[1][3]),e.call(this._xaxis,f[1][4]),g.call(this._yaxis,f[1][5])],[e.call(this._xaxis,c[1][4]),g.call(this._yaxis,c[1][5])],[e.call(this._xaxis,c[1][2]),g.call(this._yaxis,c[1][3]),e.call(this._xaxis,c[1][0]),g.call(this._yaxis,c[1][1]),e.call(this._xaxis,c[0][0]),g.call(this._yaxis,c[0][1])]]}}else{if(d==0){this.gridData=[[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,f[0][1])],[e.call(this._xaxis,f[1][0]),g.call(this._yaxis,f[1][1]),e.call(this._xaxis,f[2][0]),g.call(this._yaxis,f[2][1]),e.call(this._xaxis,f[3][0]),g.call(this._yaxis,f[3][1])],[e.call(this._xaxis,f[3][1]),g.call(this._yaxis,this._yaxis.min)],[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,this._yaxis.min)]]}else{var c=h.series[d-1].data;this.gridData=[[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,f[0][1])],[e.call(this._xaxis,f[1][0]),g.call(this._yaxis,f[1][1]),e.call(this._xaxis,f[2][0]),g.call(this._yaxis,f[2][1]),e.call(this._xaxis,f[3][0]),g.call(this._yaxis,f[3][1])],[e.call(this._xaxis,c[3][0]),g.call(this._yaxis,c[3][1])],[e.call(this._xaxis,c[2][0]),g.call(this._yaxis,c[2][1]),e.call(this._xaxis,c[1][0]),g.call(this._yaxis,c[1][1]),e.call(this._xaxis,c[0][0]),g.call(this._yaxis,c[0][1])]]}}};b.jqplot.BezierCurveRenderer.prototype.makeGridData=function(g,i){var f=this._xaxis.series_u2p;var h=this._yaxis.series_u2p;var e=[];var j=[];var d=this.index;if(g.length==2){if(d==0){e=[[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,g[0][1])],[f.call(this._xaxis,g[1][0]),h.call(this._yaxis,g[1][1]),f.call(this._xaxis,g[1][2]),h.call(this._yaxis,g[1][3]),f.call(this._xaxis,g[1][4]),h.call(this._yaxis,g[1][5])],[f.call(this._xaxis,g[1][4]),h.call(this._yaxis,this._yaxis.min)],[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,this._yaxis.min)]]}else{var c=i.series[d-1].data;e=[[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,g[0][1])],[f.call(this._xaxis,g[1][0]),h.call(this._yaxis,g[1][1]),f.call(this._xaxis,g[1][2]),h.call(this._yaxis,g[1][3]),f.call(this._xaxis,g[1][4]),h.call(this._yaxis,g[1][5])],[f.call(this._xaxis,c[1][4]),h.call(this._yaxis,c[1][5])],[f.call(this._xaxis,c[1][2]),h.call(this._yaxis,c[1][3]),f.call(this._xaxis,c[1][0]),h.call(this._yaxis,c[1][1]),f.call(this._xaxis,c[0][0]),h.call(this._yaxis,c[0][1])]]}}else{if(d==0){e=[[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,g[0][1])],[f.call(this._xaxis,g[1][0]),h.call(this._yaxis,g[1][1]),f.call(this._xaxis,g[2][0]),h.call(this._yaxis,g[2][1]),f.call(this._xaxis,g[3][0]),h.call(this._yaxis,g[3][1])],[f.call(this._xaxis,g[3][1]),h.call(this._yaxis,this._yaxis.min)],[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,this._yaxis.min)]]}else{var c=i.series[d-1].data;e=[[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,g[0][1])],[f.call(this._xaxis,g[1][0]),h.call(this._yaxis,g[1][1]),f.call(this._xaxis,g[2][0]),h.call(this._yaxis,g[2][1]),f.call(this._xaxis,g[3][0]),h.call(this._yaxis,g[3][1])],[f.call(this._xaxis,c[3][0]),h.call(this._yaxis,c[3][1])],[f.call(this._xaxis,c[2][0]),h.call(this._yaxis,c[2][1]),f.call(this._xaxis,c[1][0]),h.call(this._yaxis,c[1][1]),f.call(this._xaxis,c[0][0]),h.call(this._yaxis,c[0][1])]]}}return e};b.jqplot.BezierCurveRenderer.prototype.draw=function(c,g,d){var e;c.save();if(g.length){if(this.showLine){c.save();var f=(d!=null)?d:{};c.fillStyle=f.fillStyle||this.color;c.beginPath();c.moveTo(g[0][0],g[0][1]);c.bezierCurveTo(g[1][0],g[1][1],g[1][2],g[1][3],g[1][4],g[1][5]);c.lineTo(g[2][0],g[2][1]);if(g[3].length==2){c.lineTo(g[3][0],g[3][1])}else{c.bezierCurveTo(g[3][0],g[3][1],g[3][2],g[3][3],g[3][4],g[3][5])}c.closePath();c.fill();c.restore()}}c.restore()};b.jqplot.BezierCurveRenderer.prototype.drawShadow=function(c,e,d){};b.jqplot.BezierAxisRenderer=function(){b.jqplot.LinearAxisRenderer.call(this)};b.jqplot.BezierAxisRenderer.prototype=new b.jqplot.LinearAxisRenderer();b.jqplot.BezierAxisRenderer.prototype.constructor=b.jqplot.BezierAxisRenderer;b.jqplot.BezierAxisRenderer.prototype.init=function(f){b.extend(true,this,f);var c=this._dataBounds;for(var g=0;g<this._series.length;g++){var h=this._series[g];var k=h.data;if(k.length==4){for(var e=0;e<k.length;e++){if(this.name=="xaxis"||this.name=="x2axis"){if(k[e][0]<c.min||c.min==null){c.min=k[e][0]}if(k[e][0]>c.max||c.max==null){c.max=k[e][0]}}else{if(k[e][1]<c.min||c.min==null){c.min=k[e][1]}if(k[e][1]>c.max||c.max==null){c.max=k[e][1]}}}}else{if(this.name=="xaxis"||this.name=="x2axis"){if(k[0][0]<c.min||c.min==null){c.min=k[0][0]}if(k[0][0]>c.max||c.max==null){c.max=k[0][0]}for(var e=0;e<5;e+=2){if(k[1][e]<c.min||c.min==null){c.min=k[1][e]}if(k[1][e]>c.max||c.max==null){c.max=k[1][e]}}}else{if(k[0][1]<c.min||c.min==null){c.min=k[0][1]}if(k[0][1]>c.max||c.max==null){c.max=k[0][1]}for(var e=1;e<6;e+=2){if(k[1][e]<c.min||c.min==null){c.min=k[1][e]}if(k[1][e]>c.max||c.max==null){c.max=k[1][e]}}}}}};function a(g,f,d){d=d||{};d.axesDefaults=b.extend(true,{pad:0},d.axesDefaults);d.legend=b.extend(true,{placement:"outside"},d.legend);var c=false;if(d.seriesDefaults.renderer==b.jqplot.BezierCurveRenderer){c=true}else{if(d.series){for(var e=0;e<d.series.length;e++){if(d.series[e].renderer==b.jqplot.BezierCurveRenderer){c=true}}}}if(c){d.axesDefaults.renderer=b.jqplot.BezierAxisRenderer}}b.jqplot.preInitHooks.push(a)})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.barRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.barRenderer.js new file mode 100644 index 0000000000..cac5e9e54b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.barRenderer.js @@ -0,0 +1,709 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + + // Class: $.jqplot.BarRenderer + // A plugin renderer for jqPlot to draw a bar plot. + // Draws series as a line. + + $.jqplot.BarRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.BarRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.BarRenderer.prototype.constructor = $.jqplot.BarRenderer; + + // called with scope of series. + $.jqplot.BarRenderer.prototype.init = function(options, plot) { + // Group: Properties + // + // prop: barPadding + // Number of pixels between adjacent bars at the same axis value. + this.barPadding = 8; + // prop: barMargin + // Number of pixels between groups of bars at adjacent axis values. + this.barMargin = 10; + // prop: barDirection + // 'vertical' = up and down bars, 'horizontal' = side to side bars + this.barDirection = 'vertical'; + // prop: barWidth + // Width of the bar in pixels (auto by devaul). null = calculated automatically. + this.barWidth = null; + // prop: shadowOffset + // offset of the shadow from the slice and offset of + // each succesive stroke of the shadow from the last. + this.shadowOffset = 2; + // prop: shadowDepth + // number of strokes to apply to the shadow, + // each stroke offset shadowOffset from the last. + this.shadowDepth = 5; + // prop: shadowAlpha + // transparency of the shadow (0 = transparent, 1 = opaque) + this.shadowAlpha = 0.08; + // prop: waterfall + // true to enable waterfall plot. + this.waterfall = false; + // prop: groups + // group bars into this many groups + this.groups = 1; + // prop: varyBarColor + // true to color each bar of a series separately rather than + // have every bar of a given series the same color. + // If used for non-stacked multiple series bar plots, user should + // specify a separate 'seriesColors' array for each series. + // Otherwise, each series will set their bars to the same color array. + // This option has no Effect for stacked bar charts and is disabled. + this.varyBarColor = false; + // prop: highlightMouseOver + // True to highlight slice when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on a slice. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over a slice. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColors + // an array of colors to use when highlighting a bar. + this.highlightColors = []; + this._type = 'bar'; + + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (options.highlightMouseDown && options.highlightMouseOver == null) { + options.highlightMouseOver = false; + } + + $.extend(true, this, options); + // fill is still needed to properly draw the legend. + // bars have to be filled. + this.fill = true; + + if (this.waterfall) { + this.fillToZero = false; + this.disableStack = true; + } + + if (this.barDirection == 'vertical' ) { + this._primaryAxis = '_xaxis'; + this._stackAxis = 'y'; + this.fillAxis = 'y'; + } + else { + this._primaryAxis = '_yaxis'; + this._stackAxis = 'x'; + this.fillAxis = 'x'; + } + // index of the currenty highlighted point, if any + this._highlightedPoint = null; + // total number of values for all bar series, total number of bar series, and position of this series + this._plotSeriesInfo = null; + // Array of actual data colors used for each data point. + this._dataColors = []; + this._barPoints = []; + + // set the shape renderer options + var opts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, strokeStyle:this.color, fillStyle:this.color, closePath:this.fill}; + this.renderer.shapeRenderer.init(opts); + // set the shadow renderer options + var sopts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, closePath:this.fill}; + this.renderer.shadowRenderer.init(sopts); + + plot.postInitHooks.addOnce(postInit); + plot.postDrawHooks.addOnce(postPlotDraw); + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + }; + + // called with scope of series + function barPreInit(target, data, seriesDefaults, options) { + if (this.rendererOptions.barDirection == 'horizontal') { + this._stackAxis = 'x'; + this._primaryAxis = '_yaxis'; + } + if (this.rendererOptions.waterfall == true) { + this._data = $.extend(true, [], this.data); + var sum = 0; + var pos = (!this.rendererOptions.barDirection || this.rendererOptions.barDirection == 'vertical') ? 1 : 0; + for(var i=0; i<this.data.length; i++) { + sum += this.data[i][pos]; + if (i>0) { + this.data[i][pos] += this.data[i-1][pos]; + } + } + this.data[this.data.length] = (pos == 1) ? [this.data.length+1, sum] : [sum, this.data.length+1]; + this._data[this._data.length] = (pos == 1) ? [this._data.length+1, sum] : [sum, this._data.length+1]; + } + if (this.rendererOptions.groups > 1) { + this.breakOnNull = true; + var l = this.data.length; + var skip = parseInt(l/this.rendererOptions.groups, 10); + var count = 0; + for (var i=skip; i<l; i+=skip) { + this.data.splice(i+count, 0, [null, null]); + count++; + } + for (i=0; i<this.data.length; i++) { + if (this._primaryAxis == '_xaxis') { + this.data[i][0] = i+1; + } + else { + this.data[i][1] = i+1; + } + } + } + } + + $.jqplot.preSeriesInitHooks.push(barPreInit); + + // needs to be called with scope of series, not renderer. + $.jqplot.BarRenderer.prototype.calcSeriesNumbers = function() { + var nvals = 0; + var nseries = 0; + var paxis = this[this._primaryAxis]; + var s, series, pos; + // loop through all series on this axis + for (var i=0; i < paxis._series.length; i++) { + series = paxis._series[i]; + if (series === this) { + pos = i; + } + // is the series rendered as a bar? + if (series.renderer.constructor == $.jqplot.BarRenderer) { + // gridData may not be computed yet, use data length insted + nvals += series.data.length; + nseries += 1; + } + } + // return total number of values for all bar series, total number of bar series, and position of this series + return [nvals, nseries, pos]; + }; + + $.jqplot.BarRenderer.prototype.setBarWidth = function() { + // need to know how many data values we have on the approprate axis and figure it out. + var i; + var nvals = 0; + var nseries = 0; + var paxis = this[this._primaryAxis]; + var s, series, pos; + var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this); + nvals = temp[0]; + nseries = temp[1]; + var nticks = paxis.numberTicks; + var nbins = (nticks-1)/2; + // so, now we have total number of axis values. + if (paxis.name == 'xaxis' || paxis.name == 'x2axis') { + if (this._stack) { + this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals * nseries - this.barMargin; + } + else { + this.barWidth = ((paxis._offsets.max - paxis._offsets.min)/nbins - this.barPadding * (nseries-1) - this.barMargin*2)/nseries; + // this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals - this.barPadding - this.barMargin/nseries; + } + } + else { + if (this._stack) { + this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals * nseries - this.barMargin; + } + else { + this.barWidth = ((paxis._offsets.min - paxis._offsets.max)/nbins - this.barPadding * (nseries-1) - this.barMargin*2)/nseries; + // this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals - this.barPadding - this.barMargin/nseries; + } + } + return [nvals, nseries]; + }; + + function computeHighlightColors (colors) { + var ret = []; + for (var i=0; i<colors.length; i++){ + var rgba = $.jqplot.getColorComponents(colors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + ret.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + } + return ret; + } + + $.jqplot.BarRenderer.prototype.draw = function(ctx, gridData, options) { + var i; + // Ughhh, have to make a copy of options b/c it may be modified later. + var opts = $.extend({}, options); + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var xaxis = this.xaxis; + var yaxis = this.yaxis; + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var pointx, pointy; + // clear out data colors. + this._dataColors = []; + this._barPoints = []; + + if (this.barWidth == null) { + this.renderer.setBarWidth.call(this); + } + + var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this); + var nvals = temp[0]; + var nseries = temp[1]; + var pos = temp[2]; + var points = []; + + if (this._stack) { + this._barNudge = 0; + } + else { + this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding); + } + if (showLine) { + var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors); + var positiveColors = new $.jqplot.ColorGenerator(this.seriesColors); + var negativeColor = negativeColors.get(this.index); + if (! this.useNegativeColors) { + negativeColor = opts.fillStyle; + } + var positiveColor = opts.fillStyle; + var base; + var xstart; + var ystart; + + if (this.barDirection == 'vertical') { + for (var i=0; i<gridData.length; i++) { + if (this.data[i][1] == null) { + continue; + } + points = []; + base = gridData[i][0] + this._barNudge; + ystart; + + // stacked + if (this._stack && this._prevGridData.length) { + ystart = this._prevGridData[i][1]; + } + // not stacked and first series in stack + else { + if (this.fillToZero) { + ystart = this._yaxis.series_u2p(0); + } + else if (this.waterfall && i > 0 && i < this.gridData.length-1) { + ystart = this.gridData[i-1][1]; + } + else if (this.waterfall && i == 0 && i < this.gridData.length-1) { + if (this._yaxis.min <= 0 && this._yaxis.max >= 0) { + ystart = this._yaxis.series_u2p(0); + } + else if (this._yaxis.min > 0) { + ystart = ctx.canvas.height; + } + else { + ystart = 0; + } + } + else if (this.waterfall && i == this.gridData.length - 1) { + if (this._yaxis.min <= 0 && this._yaxis.max >= 0) { + ystart = this._yaxis.series_u2p(0); + } + else if (this._yaxis.min > 0) { + ystart = ctx.canvas.height; + } + else { + ystart = 0; + } + } + else { + ystart = ctx.canvas.height; + } + } + if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) { + if (this.varyBarColor && !this._stack) { + if (this.useNegativeColors) { + opts.fillStyle = negativeColors.next(); + } + else { + opts.fillStyle = positiveColors.next(); + } + } + else { + opts.fillStyle = negativeColor; + } + } + else { + if (this.varyBarColor && !this._stack) { + opts.fillStyle = positiveColors.next(); + } + else { + opts.fillStyle = positiveColor; + } + } + + if (!this.fillToZero || this._plotData[i][1] >= 0) { + points.push([base-this.barWidth/2, ystart]); + points.push([base-this.barWidth/2, gridData[i][1]]); + points.push([base+this.barWidth/2, gridData[i][1]]); + points.push([base+this.barWidth/2, ystart]); + } + // for negative bars make sure points are always ordered clockwise + else { + points.push([base-this.barWidth/2, gridData[i][1]]); + points.push([base-this.barWidth/2, ystart]); + points.push([base+this.barWidth/2, ystart]); + points.push([base+this.barWidth/2, gridData[i][1]]); + } + this._barPoints.push(points); + // now draw the shadows if not stacked. + // for stacked plots, they are predrawn by drawShadow + if (shadow && !this._stack) { + var sopts = $.extend(true, {}, opts); + // need to get rid of fillStyle on shadow. + delete sopts.fillStyle; + this.renderer.shadowRenderer.draw(ctx, points, sopts); + } + var clr = opts.fillStyle || this.color; + this._dataColors.push(clr); + this.renderer.shapeRenderer.draw(ctx, points, opts); + } + } + + else if (this.barDirection == 'horizontal'){ + for (var i=0; i<gridData.length; i++) { + if (this.data[i][0] == null) { + continue; + } + points = []; + base = gridData[i][1] - this._barNudge; + xstart; + + if (this._stack && this._prevGridData.length) { + xstart = this._prevGridData[i][0]; + } + // not stacked and first series in stack + else { + if (this.fillToZero) { + xstart = this._xaxis.series_u2p(0); + } + else if (this.waterfall && i > 0 && i < this.gridData.length-1) { + xstart = this.gridData[i-1][1]; + } + else if (this.waterfall && i == 0 && i < this.gridData.length-1) { + if (this._xaxis.min <= 0 && this._xaxis.max >= 0) { + xstart = this._xaxis.series_u2p(0); + } + else if (this._xaxis.min > 0) { + xstart = 0; + } + else { + xstart = ctx.canvas.width; + } + } + else if (this.waterfall && i == this.gridData.length - 1) { + if (this._xaxis.min <= 0 && this._xaxis.max >= 0) { + xstart = this._xaxis.series_u2p(0); + } + else if (this._xaxis.min > 0) { + xstart = 0; + } + else { + xstart = ctx.canvas.width; + } + } + else { + xstart = 0; + } + } + if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) { + if (this.varyBarColor && !this._stack) { + if (this.useNegativeColors) { + opts.fillStyle = negativeColors.next(); + } + else { + opts.fillStyle = positiveColors.next(); + } + } + } + else { + if (this.varyBarColor && !this._stack) { + opts.fillStyle = positiveColors.next(); + } + else { + opts.fillStyle = positiveColor; + } + } + + points.push([xstart, base+this.barWidth/2]); + points.push([xstart, base-this.barWidth/2]); + points.push([gridData[i][0], base-this.barWidth/2]); + points.push([gridData[i][0], base+this.barWidth/2]); + this._barPoints.push(points); + // now draw the shadows if not stacked. + // for stacked plots, they are predrawn by drawShadow + if (shadow && !this._stack) { + var sopts = $.extend(true, {}, opts); + delete sopts.fillStyle; + this.renderer.shadowRenderer.draw(ctx, points, sopts); + } + var clr = opts.fillStyle || this.color; + this._dataColors.push(clr); + this.renderer.shapeRenderer.draw(ctx, points, opts); + } + } + } + + if (this.highlightColors.length == 0) { + this.highlightColors = computeHighlightColors(this._dataColors); + } + + else if (typeof(this.highlightColors) == 'string') { + var temp = this.highlightColors; + this.highlightColors = []; + for (var i=0; i<this._dataColors.length; i++) { + this.highlightColors.push(temp); + } + } + + }; + + + // for stacked plots, shadows will be pre drawn by drawShadow. + $.jqplot.BarRenderer.prototype.drawShadow = function(ctx, gridData, options) { + var i; + var opts = (options != undefined) ? options : {}; + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var xaxis = this.xaxis; + var yaxis = this.yaxis; + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var pointx, points, pointy, nvals, nseries, pos; + + if (this._stack && this.shadow) { + if (this.barWidth == null) { + this.renderer.setBarWidth.call(this); + } + + var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this); + nvals = temp[0]; + nseries = temp[1]; + pos = temp[2]; + + if (this._stack) { + this._barNudge = 0; + } + else { + this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding); + } + if (showLine) { + + if (this.barDirection == 'vertical') { + for (var i=0; i<gridData.length; i++) { + if (this.data[i][1] == null) { + continue; + } + points = []; + var base = gridData[i][0] + this._barNudge; + var ystart; + + if (this._stack && this._prevGridData.length) { + ystart = this._prevGridData[i][1]; + } + else { + if (this.fillToZero) { + ystart = this._yaxis.series_u2p(0); + } + else { + ystart = ctx.canvas.height; + } + } + + points.push([base-this.barWidth/2, ystart]); + points.push([base-this.barWidth/2, gridData[i][1]]); + points.push([base+this.barWidth/2, gridData[i][1]]); + points.push([base+this.barWidth/2, ystart]); + this.renderer.shadowRenderer.draw(ctx, points, opts); + } + } + + else if (this.barDirection == 'horizontal'){ + for (var i=0; i<gridData.length; i++) { + if (this.data[i][0] == null) { + continue; + } + points = []; + var base = gridData[i][1] - this._barNudge; + var xstart; + + if (this._stack && this._prevGridData.length) { + xstart = this._prevGridData[i][0]; + } + else { + xstart = 0; + } + + points.push([xstart, base+this.barWidth/2]); + points.push([gridData[i][0], base+this.barWidth/2]); + points.push([gridData[i][0], base-this.barWidth/2]); + points.push([xstart, base-this.barWidth/2]); + this.renderer.shadowRenderer.draw(ctx, points, opts); + } + } + } + + } + }; + + function postInit(target, data, options) { + for (var i=0; i<this.series.length; i++) { + if (this.series[i].renderer.constructor == $.jqplot.BarRenderer) { + // don't allow mouseover and mousedown at same time. + if (this.series[i].highlightMouseOver) { + this.series[i].highlightMouseDown = false; + } + } + } + this.target.bind('mouseout', {plot:this}, function (ev) { unhighlight(ev.data.plot); }); + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.barRenderer && this.plugins.barRenderer.highlightCanvas) { + + this.plugins.barRenderer.highlightCanvas.resetCanvas(); + this.plugins.barRenderer.highlightCanvas = null; + } + + this.plugins.barRenderer = {highlightedSeriesIndex:null}; + this.plugins.barRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + + this.eventCanvas._elem.before(this.plugins.barRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-barRenderer-highlight-canvas', this._plotDimensions, this)); + this.plugins.barRenderer.highlightCanvas.setContext(); + } + + function highlight (plot, sidx, pidx, points) { + var s = plot.series[sidx]; + var canvas = plot.plugins.barRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.barRenderer.highlightedSeriesIndex = sidx; + var opts = {fillStyle: s.highlightColors[pidx]}; + s.renderer.shapeRenderer.draw(canvas._ctx, points, opts); + canvas = null; + } + + function unhighlight (plot) { + var canvas = plot.plugins.barRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.barRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + canvas = null; + } + + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.barRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt = jQuery.Event('jqplotDataClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var idx = plot.plugins.barRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.barRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.barRenderer.min.js new file mode 100644 index 0000000000..4d5766c54c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.barRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(d){d.jqplot.BarRenderer=function(){d.jqplot.LineRenderer.call(this)};d.jqplot.BarRenderer.prototype=new d.jqplot.LineRenderer();d.jqplot.BarRenderer.prototype.constructor=d.jqplot.BarRenderer;d.jqplot.BarRenderer.prototype.init=function(n,p){this.barPadding=8;this.barMargin=10;this.barDirection="vertical";this.barWidth=null;this.shadowOffset=2;this.shadowDepth=5;this.shadowAlpha=0.08;this.waterfall=false;this.groups=1;this.varyBarColor=false;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this._type="bar";if(n.highlightMouseDown&&n.highlightMouseOver==null){n.highlightMouseOver=false}d.extend(true,this,n);this.fill=true;if(this.waterfall){this.fillToZero=false;this.disableStack=true}if(this.barDirection=="vertical"){this._primaryAxis="_xaxis";this._stackAxis="y";this.fillAxis="y"}else{this._primaryAxis="_yaxis";this._stackAxis="x";this.fillAxis="x"}this._highlightedPoint=null;this._plotSeriesInfo=null;this._dataColors=[];this._barPoints=[];var o={lineJoin:"miter",lineCap:"round",fill:true,isarc:false,strokeStyle:this.color,fillStyle:this.color,closePath:this.fill};this.renderer.shapeRenderer.init(o);var m={lineJoin:"miter",lineCap:"round",fill:true,isarc:false,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,closePath:this.fill};this.renderer.shadowRenderer.init(m);p.postInitHooks.addOnce(h);p.postDrawHooks.addOnce(i);p.eventListenerHooks.addOnce("jqplotMouseMove",b);p.eventListenerHooks.addOnce("jqplotMouseDown",a);p.eventListenerHooks.addOnce("jqplotMouseUp",k);p.eventListenerHooks.addOnce("jqplotClick",e);p.eventListenerHooks.addOnce("jqplotRightClick",l)};function g(s,o,n,v){if(this.rendererOptions.barDirection=="horizontal"){this._stackAxis="x";this._primaryAxis="_yaxis"}if(this.rendererOptions.waterfall==true){this._data=d.extend(true,[],this.data);var r=0;var t=(!this.rendererOptions.barDirection||this.rendererOptions.barDirection=="vertical")?1:0;for(var p=0;p<this.data.length;p++){r+=this.data[p][t];if(p>0){this.data[p][t]+=this.data[p-1][t]}}this.data[this.data.length]=(t==1)?[this.data.length+1,r]:[r,this.data.length+1];this._data[this._data.length]=(t==1)?[this._data.length+1,r]:[r,this._data.length+1]}if(this.rendererOptions.groups>1){this.breakOnNull=true;var m=this.data.length;var u=parseInt(m/this.rendererOptions.groups,10);var q=0;for(var p=u;p<m;p+=u){this.data.splice(p+q,0,[null,null]);q++}for(p=0;p<this.data.length;p++){if(this._primaryAxis=="_xaxis"){this.data[p][0]=p+1}else{this.data[p][1]=p+1}}}}d.jqplot.preSeriesInitHooks.push(g);d.jqplot.BarRenderer.prototype.calcSeriesNumbers=function(){var q=0;var r=0;var p=this[this._primaryAxis];var o,n,t;for(var m=0;m<p._series.length;m++){n=p._series[m];if(n===this){t=m}if(n.renderer.constructor==d.jqplot.BarRenderer){q+=n.data.length;r+=1}}return[q,r,t]};d.jqplot.BarRenderer.prototype.setBarWidth=function(){var p;var m=0;var n=0;var r=this[this._primaryAxis];var w,q,u;var v=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);m=v[0];n=v[1];var t=r.numberTicks;var o=(t-1)/2;if(r.name=="xaxis"||r.name=="x2axis"){if(this._stack){this.barWidth=(r._offsets.max-r._offsets.min)/m*n-this.barMargin}else{this.barWidth=((r._offsets.max-r._offsets.min)/o-this.barPadding*(n-1)-this.barMargin*2)/n}}else{if(this._stack){this.barWidth=(r._offsets.min-r._offsets.max)/m*n-this.barMargin}else{this.barWidth=((r._offsets.min-r._offsets.max)/o-this.barPadding*(n-1)-this.barMargin*2)/n}}return[m,n]};function f(n){var p=[];for(var r=0;r<n.length;r++){var q=d.jqplot.getColorComponents(n[r]);var m=[q[0],q[1],q[2]];var s=m[0]+m[1]+m[2];for(var o=0;o<3;o++){m[o]=(s>570)?m[o]*0.8:m[o]+0.3*(255-m[o]);m[o]=parseInt(m[o],10)}p.push("rgb("+m[0]+","+m[1]+","+m[2]+")")}return p}d.jqplot.BarRenderer.prototype.draw=function(D,J,p){var G;var z=d.extend({},p);var u=(z.shadow!=undefined)?z.shadow:this.shadow;var M=(z.showLine!=undefined)?z.showLine:this.showLine;var E=(z.fill!=undefined)?z.fill:this.fill;var o=this.xaxis;var H=this.yaxis;var x=this._xaxis.series_u2p;var I=this._yaxis.series_u2p;var C,B;this._dataColors=[];this._barPoints=[];if(this.barWidth==null){this.renderer.setBarWidth.call(this)}var L=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);var w=L[0];var v=L[1];var r=L[2];var F=[];if(this._stack){this._barNudge=0}else{this._barNudge=(-Math.abs(v/2-0.5)+r)*(this.barWidth+this.barPadding)}if(M){var t=new d.jqplot.ColorGenerator(this.negativeSeriesColors);var A=new d.jqplot.ColorGenerator(this.seriesColors);var K=t.get(this.index);if(!this.useNegativeColors){K=z.fillStyle}var s=z.fillStyle;var q;var N;var n;if(this.barDirection=="vertical"){for(var G=0;G<J.length;G++){if(this.data[G][1]==null){continue}F=[];q=J[G][0]+this._barNudge;n;if(this._stack&&this._prevGridData.length){n=this._prevGridData[G][1]}else{if(this.fillToZero){n=this._yaxis.series_u2p(0)}else{if(this.waterfall&&G>0&&G<this.gridData.length-1){n=this.gridData[G-1][1]}else{if(this.waterfall&&G==0&&G<this.gridData.length-1){if(this._yaxis.min<=0&&this._yaxis.max>=0){n=this._yaxis.series_u2p(0)}else{if(this._yaxis.min>0){n=D.canvas.height}else{n=0}}}else{if(this.waterfall&&G==this.gridData.length-1){if(this._yaxis.min<=0&&this._yaxis.max>=0){n=this._yaxis.series_u2p(0)}else{if(this._yaxis.min>0){n=D.canvas.height}else{n=0}}}else{n=D.canvas.height}}}}}if((this.fillToZero&&this._plotData[G][1]<0)||(this.waterfall&&this._data[G][1]<0)){if(this.varyBarColor&&!this._stack){if(this.useNegativeColors){z.fillStyle=t.next()}else{z.fillStyle=A.next()}}else{z.fillStyle=K}}else{if(this.varyBarColor&&!this._stack){z.fillStyle=A.next()}else{z.fillStyle=s}}if(!this.fillToZero||this._plotData[G][1]>=0){F.push([q-this.barWidth/2,n]);F.push([q-this.barWidth/2,J[G][1]]);F.push([q+this.barWidth/2,J[G][1]]);F.push([q+this.barWidth/2,n])}else{F.push([q-this.barWidth/2,J[G][1]]);F.push([q-this.barWidth/2,n]);F.push([q+this.barWidth/2,n]);F.push([q+this.barWidth/2,J[G][1]])}this._barPoints.push(F);if(u&&!this._stack){var y=d.extend(true,{},z);delete y.fillStyle;this.renderer.shadowRenderer.draw(D,F,y)}var m=z.fillStyle||this.color;this._dataColors.push(m);this.renderer.shapeRenderer.draw(D,F,z)}}else{if(this.barDirection=="horizontal"){for(var G=0;G<J.length;G++){if(this.data[G][0]==null){continue}F=[];q=J[G][1]-this._barNudge;N;if(this._stack&&this._prevGridData.length){N=this._prevGridData[G][0]}else{if(this.fillToZero){N=this._xaxis.series_u2p(0)}else{if(this.waterfall&&G>0&&G<this.gridData.length-1){N=this.gridData[G-1][1]}else{if(this.waterfall&&G==0&&G<this.gridData.length-1){if(this._xaxis.min<=0&&this._xaxis.max>=0){N=this._xaxis.series_u2p(0)}else{if(this._xaxis.min>0){N=0}else{N=D.canvas.width}}}else{if(this.waterfall&&G==this.gridData.length-1){if(this._xaxis.min<=0&&this._xaxis.max>=0){N=this._xaxis.series_u2p(0)}else{if(this._xaxis.min>0){N=0}else{N=D.canvas.width}}}else{N=0}}}}}if((this.fillToZero&&this._plotData[G][1]<0)||(this.waterfall&&this._data[G][1]<0)){if(this.varyBarColor&&!this._stack){if(this.useNegativeColors){z.fillStyle=t.next()}else{z.fillStyle=A.next()}}}else{if(this.varyBarColor&&!this._stack){z.fillStyle=A.next()}else{z.fillStyle=s}}F.push([N,q+this.barWidth/2]);F.push([N,q-this.barWidth/2]);F.push([J[G][0],q-this.barWidth/2]);F.push([J[G][0],q+this.barWidth/2]);this._barPoints.push(F);if(u&&!this._stack){var y=d.extend(true,{},z);delete y.fillStyle;this.renderer.shadowRenderer.draw(D,F,y)}var m=z.fillStyle||this.color;this._dataColors.push(m);this.renderer.shapeRenderer.draw(D,F,z)}}}}if(this.highlightColors.length==0){this.highlightColors=f(this._dataColors)}else{if(typeof(this.highlightColors)=="string"){var L=this.highlightColors;this.highlightColors=[];for(var G=0;G<this._dataColors.length;G++){this.highlightColors.push(L)}}}};d.jqplot.BarRenderer.prototype.drawShadow=function(y,E,o){var B;var v=(o!=undefined)?o:{};var r=(v.shadow!=undefined)?v.shadow:this.shadow;var G=(v.showLine!=undefined)?v.showLine:this.showLine;var z=(v.fill!=undefined)?v.fill:this.fill;var n=this.xaxis;var C=this.yaxis;var u=this._xaxis.series_u2p;var D=this._yaxis.series_u2p;var x,A,w,t,s,q;if(this._stack&&this.shadow){if(this.barWidth==null){this.renderer.setBarWidth.call(this)}var F=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);t=F[0];s=F[1];q=F[2];if(this._stack){this._barNudge=0}else{this._barNudge=(-Math.abs(s/2-0.5)+q)*(this.barWidth+this.barPadding)}if(G){if(this.barDirection=="vertical"){for(var B=0;B<E.length;B++){if(this.data[B][1]==null){continue}A=[];var p=E[B][0]+this._barNudge;var m;if(this._stack&&this._prevGridData.length){m=this._prevGridData[B][1]}else{if(this.fillToZero){m=this._yaxis.series_u2p(0)}else{m=y.canvas.height}}A.push([p-this.barWidth/2,m]);A.push([p-this.barWidth/2,E[B][1]]);A.push([p+this.barWidth/2,E[B][1]]);A.push([p+this.barWidth/2,m]);this.renderer.shadowRenderer.draw(y,A,v)}}else{if(this.barDirection=="horizontal"){for(var B=0;B<E.length;B++){if(this.data[B][0]==null){continue}A=[];var p=E[B][1]-this._barNudge;var H;if(this._stack&&this._prevGridData.length){H=this._prevGridData[B][0]}else{H=0}A.push([H,p+this.barWidth/2]);A.push([E[B][0],p+this.barWidth/2]);A.push([E[B][0],p-this.barWidth/2]);A.push([H,p-this.barWidth/2]);this.renderer.shadowRenderer.draw(y,A,v)}}}}}};function h(p,o,m){for(var n=0;n<this.series.length;n++){if(this.series[n].renderer.constructor==d.jqplot.BarRenderer){if(this.series[n].highlightMouseOver){this.series[n].highlightMouseDown=false}}}this.target.bind("mouseout",{plot:this},function(q){j(q.data.plot)})}function i(){if(this.plugins.barRenderer&&this.plugins.barRenderer.highlightCanvas){this.plugins.barRenderer.highlightCanvas.resetCanvas();this.plugins.barRenderer.highlightCanvas=null}this.plugins.barRenderer={highlightedSeriesIndex:null};this.plugins.barRenderer.highlightCanvas=new d.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.barRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-barRenderer-highlight-canvas",this._plotDimensions,this));this.plugins.barRenderer.highlightCanvas.setContext()}function c(t,r,p,o){var n=t.series[r];var m=t.plugins.barRenderer.highlightCanvas;m._ctx.clearRect(0,0,m._ctx.canvas.width,m._ctx.canvas.height);n._highlightedPoint=p;t.plugins.barRenderer.highlightedSeriesIndex=r;var q={fillStyle:n.highlightColors[p]};n.renderer.shapeRenderer.draw(m._ctx,o,q);m=null}function j(o){var m=o.plugins.barRenderer.highlightCanvas;m._ctx.clearRect(0,0,m._ctx.canvas.width,m._ctx.canvas.height);for(var n=0;n<o.series.length;n++){o.series[n]._highlightedPoint=null}o.plugins.barRenderer.highlightedSeriesIndex=null;o.target.trigger("jqplotDataUnhighlight");m=null}function b(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];var n=jQuery.Event("jqplotDataMouseOver");n.pageX=q.pageX;n.pageY=q.pageY;r.target.trigger(n,o);if(r.series[o[0]].highlightMouseOver&&!(o[0]==r.plugins.barRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){var m=jQuery.Event("jqplotDataHighlight");m.pageX=q.pageX;m.pageY=q.pageY;r.target.trigger(m,o);c(r,s.seriesIndex,s.pointIndex,s.points)}}else{if(s==null){j(r)}}}function a(p,o,s,r,q){if(r){var n=[r.seriesIndex,r.pointIndex,r.data];if(q.series[n[0]].highlightMouseDown&&!(n[0]==q.plugins.barRenderer.highlightedSeriesIndex&&n[1]==q.series[n[0]]._highlightedPoint)){var m=jQuery.Event("jqplotDataHighlight");m.pageX=p.pageX;m.pageY=p.pageY;q.target.trigger(m,n);c(q,r.seriesIndex,r.pointIndex,r.points)}}else{if(r==null){j(q)}}}function k(o,n,r,q,p){var m=p.plugins.barRenderer.highlightedSeriesIndex;if(m!=null&&p.series[m].highlightMouseDown){j(p)}}function e(p,o,s,r,q){if(r){var n=[r.seriesIndex,r.pointIndex,r.data];var m=jQuery.Event("jqplotDataClick");m.pageX=p.pageX;m.pageY=p.pageY;q.target.trigger(m,n)}}function l(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];var m=r.plugins.barRenderer.highlightedSeriesIndex;if(m!=null&&r.series[m].highlightMouseDown){j(r)}var n=jQuery.Event("jqplotDataRightClick");n.pageX=q.pageX;n.pageY=q.pageY;r.target.trigger(n,o)}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.blockRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.blockRenderer.js new file mode 100644 index 0000000000..ab2b515f17 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.blockRenderer.js @@ -0,0 +1,234 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.BlockRenderer + * Plugin renderer to draw a x-y block chart. A Block chart has data points displayed as + * colored squares with a text label inside. Data must be supplied in the form: + * + * > [[x1, y1, "label 1", {css}], [x2, y2, "label 2", {css}], ...] + * + * The label and css object are optional. If the label is ommitted, the + * box will collapse unless a css height and/or width is specified. + * + * The css object is an object specifying css properties + * such as: + * + * > {background:'#4f98a5', border:'3px solid gray', padding:'1px'} + * + * Note that css properties specified with the data point override defaults + * specified with the series. + * + */ + $.jqplot.BlockRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.BlockRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.BlockRenderer.prototype.constructor = $.jqplot.BlockRenderer; + + // called with scope of a series + $.jqplot.BlockRenderer.prototype.init = function(options) { + // Group: Properties + // + // prop: css + // default css styles that will be applied to all data blocks. + // these values will be overridden by css styles supplied with the + // individulal data points. + this.css = {padding:'2px', border:'1px solid #999', textAlign:'center'}; + // prop: escapeHtml + // true to escape html in the box label. + this.escapeHtml = false; + // prop: insertBreaks + // true to turn spaces in data block label into html breaks <br />. + this.insertBreaks = true; + // prop: varyBlockColors + // true to vary the color of each block in this series according to + // the seriesColors array. False to set each block to the color + // specified on this series. This has no effect if a css background color + // option is specified in the renderer css options. + this.varyBlockColors = false; + $.extend(true, this, options); + if (this.css.backgroundColor) { + this.color = this.css.backgroundColor; + } + else if (this.css.background) { + this.color = this.css.background; + } + else if (!this.varyBlockColors) { + this.css.background = this.color; + } + this.canvas = new $.jqplot.BlockCanvas(); + this.shadowCanvas = new $.jqplot.BlockCanvas(); + this.canvas._plotDimensions = this._plotDimensions; + this.shadowCanvas._plotDimensions = this._plotDimensions; + this._type = 'block'; + + // group: Methods + // + // Method: moveBlock + // Moves an individual block. More efficient than redrawing + // the whole series by calling plot.drawSeries(). + // Properties: + // idx - the 0 based index of the block or point in this series. + // x - the x coordinate in data units (value on x axis) to move the block to. + // y - the y coordinate in data units (value on the y axis) to move the block to. + // duration - optional parameter to create an animated movement. Can be a + // number (higher is slower animation) or 'fast', 'normal' or 'slow'. If not + // provided, the element is moved without any animation. + this.moveBlock = function (idx, x, y, duration) { + // update plotData, stackData, data and gridData + // x and y are in data coordinates. + var el = this.canvas._elem.children(':eq('+idx+')'); + this.data[idx][0] = x; + this.data[idx][1] = y; + this._plotData[idx][0] = x; + this._plotData[idx][1] = y; + this._stackData[idx][0] = x; + this._stackData[idx][1] = y; + this.gridData[idx][0] = this._xaxis.series_u2p(x); + this.gridData[idx][1] = this._yaxis.series_u2p(y); + var w = el.outerWidth(); + var h = el.outerHeight(); + var left = this.gridData[idx][0] - w/2 + 'px'; + var top = this.gridData[idx][1] - h/2 + 'px'; + if (duration) { + if (parseInt(duration, 10)) { + duration = parseInt(duration, 10); + } + el.animate({left:left, top:top}, duration); + } + else { + el.css({left:left, top:top}); + } + el = null; + }; + }; + + // called with scope of series + $.jqplot.BlockRenderer.prototype.draw = function (ctx, gd, options) { + if (this.plugins.pointLabels) { + this.plugins.pointLabels.show = false; + } + var i, el, d, gd, t, css, w, h, left, top; + var opts = (options != undefined) ? options : {}; + var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors); + this.canvas._elem.empty(); + for (i=0; i<this.gridData.length; i++) { + d = this.data[i]; + gd = this.gridData[i]; + t = ''; + css = {}; + if (typeof d[2] == 'string') { + t = d[2]; + } + else if (typeof d[2] == 'object') { + css = d[2]; + } + if (typeof d[3] == 'object') { + css = d[3]; + } + if (this.insertBreaks){ + t = t.replace(/ /g, '<br />'); + } + css = $.extend(true, {}, this.css, css); + // create a div + el = $('<div style="position:absolute;margin-left:auto;margin-right:auto;"></div>'); + this.canvas._elem.append(el); + // set text + this.escapeHtml ? el.text(t) : el.html(t); + // style it + // remove styles we don't want overridden. + delete css.position; + delete css.marginRight; + delete css.marginLeft; + if (!css.background && !css.backgroundColor && !css.backgroundImage){ + css.background = colorGenerator.next(); + } + el.css(css); + w = el.outerWidth(); + h = el.outerHeight(); + left = gd[0] - w/2 + 'px'; + top = gd[1] - h/2 + 'px'; + el.css({left:left, top:top}); + el = null; + } + }; + + $.jqplot.BlockCanvas = function() { + $.jqplot.ElemContainer.call(this); + this._ctx; + }; + + $.jqplot.BlockCanvas.prototype = new $.jqplot.ElemContainer(); + $.jqplot.BlockCanvas.prototype.constructor = $.jqplot.BlockCanvas; + + $.jqplot.BlockCanvas.prototype.createElement = function(offsets, clss, plotDimensions) { + this._offsets = offsets; + var klass = 'jqplot-blockCanvas'; + if (clss != undefined) { + klass = clss; + } + var elem; + // if this canvas already has a dom element, don't make a new one. + if (this._elem) { + elem = this._elem.get(0); + } + else { + elem = document.createElement('div'); + } + // if new plotDimensions supplied, use them. + if (plotDimensions != undefined) { + this._plotDimensions = plotDimensions; + } + + var w = this._plotDimensions.width - this._offsets.left - this._offsets.right + 'px'; + var h = this._plotDimensions.height - this._offsets.top - this._offsets.bottom + 'px'; + this._elem = $(elem); + this._elem.css({ position: 'absolute', width:w, height:h, left: this._offsets.left, top: this._offsets.top }); + + this._elem.addClass(klass); + return this._elem; + }; + + $.jqplot.BlockCanvas.prototype.setContext = function() { + this._ctx = { + canvas:{ + width:0, + height:0 + }, + clearRect:function(){return null;} + }; + return this._ctx; + }; + +})(jQuery); + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.blockRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.blockRenderer.min.js new file mode 100644 index 0000000000..62404280b9 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.blockRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.BlockRenderer=function(){a.jqplot.LineRenderer.call(this)};a.jqplot.BlockRenderer.prototype=new a.jqplot.LineRenderer();a.jqplot.BlockRenderer.prototype.constructor=a.jqplot.BlockRenderer;a.jqplot.BlockRenderer.prototype.init=function(b){this.css={padding:"2px",border:"1px solid #999",textAlign:"center"};this.escapeHtml=false;this.insertBreaks=true;this.varyBlockColors=false;a.extend(true,this,b);if(this.css.backgroundColor){this.color=this.css.backgroundColor}else{if(this.css.background){this.color=this.css.background}else{if(!this.varyBlockColors){this.css.background=this.color}}}this.canvas=new a.jqplot.BlockCanvas();this.shadowCanvas=new a.jqplot.BlockCanvas();this.canvas._plotDimensions=this._plotDimensions;this.shadowCanvas._plotDimensions=this._plotDimensions;this._type="block";this.moveBlock=function(l,j,i,e){var c=this.canvas._elem.children(":eq("+l+")");this.data[l][0]=j;this.data[l][1]=i;this._plotData[l][0]=j;this._plotData[l][1]=i;this._stackData[l][0]=j;this._stackData[l][1]=i;this.gridData[l][0]=this._xaxis.series_u2p(j);this.gridData[l][1]=this._yaxis.series_u2p(i);var k=c.outerWidth();var f=c.outerHeight();var d=this.gridData[l][0]-k/2+"px";var g=this.gridData[l][1]-f/2+"px";if(e){if(parseInt(e,10)){e=parseInt(e,10)}c.animate({left:d,top:g},e)}else{c.css({left:d,top:g})}c=null}};a.jqplot.BlockRenderer.prototype.draw=function(q,o,r){if(this.plugins.pointLabels){this.plugins.pointLabels.show=false}var f,c,l,o,p,k,n,g,e,m;var b=(r!=undefined)?r:{};var j=new a.jqplot.ColorGenerator(this.seriesColors);this.canvas._elem.empty();for(f=0;f<this.gridData.length;f++){l=this.data[f];o=this.gridData[f];p="";k={};if(typeof l[2]=="string"){p=l[2]}else{if(typeof l[2]=="object"){k=l[2]}}if(typeof l[3]=="object"){k=l[3]}if(this.insertBreaks){p=p.replace(/ /g,"<br />")}k=a.extend(true,{},this.css,k);c=a('<div style="position:absolute;margin-left:auto;margin-right:auto;"></div>');this.canvas._elem.append(c);this.escapeHtml?c.text(p):c.html(p);delete k.position;delete k.marginRight;delete k.marginLeft;if(!k.background&&!k.backgroundColor&&!k.backgroundImage){k.background=j.next()}c.css(k);n=c.outerWidth();g=c.outerHeight();e=o[0]-n/2+"px";m=o[1]-g/2+"px";c.css({left:e,top:m});c=null}};a.jqplot.BlockCanvas=function(){a.jqplot.ElemContainer.call(this);this._ctx};a.jqplot.BlockCanvas.prototype=new a.jqplot.ElemContainer();a.jqplot.BlockCanvas.prototype.constructor=a.jqplot.BlockCanvas;a.jqplot.BlockCanvas.prototype.createElement=function(i,e,c){this._offsets=i;var b="jqplot-blockCanvas";if(e!=undefined){b=e}var g;if(this._elem){g=this._elem.get(0)}else{g=document.createElement("div")}if(c!=undefined){this._plotDimensions=c}var d=this._plotDimensions.width-this._offsets.left-this._offsets.right+"px";var f=this._plotDimensions.height-this._offsets.top-this._offsets.bottom+"px";this._elem=a(g);this._elem.css({position:"absolute",width:d,height:f,left:this._offsets.left,top:this._offsets.top});this._elem.addClass(b);return this._elem};a.jqplot.BlockCanvas.prototype.setContext=function(){this._ctx={canvas:{width:0,height:0},clearRect:function(){return null}};return this._ctx}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.bubbleRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.bubbleRenderer.js new file mode 100644 index 0000000000..2d70ace224 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.bubbleRenderer.js @@ -0,0 +1,754 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + var arrayMax = function( array ){ + return Math.max.apply( Math, array ); + }; + var arrayMin = function( array ){ + return Math.min.apply( Math, array ); + }; + + /** + * Class: $.jqplot.BubbleRenderer + * Plugin renderer to draw a bubble chart. A Bubble chart has data points displayed as + * colored circles with an optional text label inside. To use + * the bubble renderer, you must include the bubble renderer like: + * + * > <script language="javascript" type="text/javascript" src="../src/plugins/jqplot.bubbleRenderer.js"></script> + * + * Data must be supplied in + * the form: + * + * > [[x1, y1, r1, <label or {label:'text', color:color}>], ...] + * + * where the label or options + * object is optional. + * + * Note that all bubble colors will be the same + * unless the "varyBubbleColors" option is set to true. Colors can be specified in the data array + * or in the seriesColors array option on the series. If no colors are defined, the default jqPlot + * series of 16 colors are used. Colors are automatically cycled around again if there are more + * bubbles than colors. + * + * Bubbles are autoscaled by default to fit within the chart area while maintaining + * relative sizes. If the "autoscaleBubbles" option is set to false, the r(adius) values + * in the data array a treated as literal pixel values for the radii of the bubbles. + * + * Properties are passed into the bubble renderer in the rendererOptions object of + * the series options like: + * + * > seriesDefaults: { + * > renderer: $.jqplot.BubbleRenderer, + * > rendererOptions: { + * > bubbleAlpha: 0.7, + * > varyBubbleColors: false + * > } + * > } + * + */ + $.jqplot.BubbleRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.BubbleRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.BubbleRenderer.prototype.constructor = $.jqplot.BubbleRenderer; + + // called with scope of a series + $.jqplot.BubbleRenderer.prototype.init = function(options, plot) { + // Group: Properties + // + // prop: varyBubbleColors + // True to vary the color of each bubble in this series according to + // the seriesColors array. False to set each bubble to the color + // specified on this series. This has no effect if a css background color + // option is specified in the renderer css options. + this.varyBubbleColors = true; + // prop: autoscaleBubbles + // True to scale the bubble radius based on plot size. + // False will use the radius value as provided as a raw pixel value for + // bubble radius. + this.autoscaleBubbles = true; + // prop: autoscaleMultiplier + // Multiplier the bubble size if autoscaleBubbles is true. + this.autoscaleMultiplier = 1.0; + // prop: autoscalePointsFactor + // Factor which decreases bubble size based on how many bubbles on on the chart. + // 0 means no adjustment for number of bubbles. Negative values will decrease + // size of bubbles as more bubbles are added. Values between 0 and -0.2 + // should work well. + this.autoscalePointsFactor = -0.07; + // prop: escapeHtml + // True to escape html in bubble label text. + this.escapeHtml = true; + // prop: highlightMouseOver + // True to highlight bubbles when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on a slice. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over a bubble. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColors + // An array of colors to use when highlighting a slice. Calculated automatically + // if not supplied. + this.highlightColors = []; + // prop: bubbleAlpha + // Alpha transparency to apply to all bubbles in this series. + this.bubbleAlpha = 1.0; + // prop: highlightAlpha + // Alpha transparency to apply when highlighting bubble. + // Set to value of bubbleAlpha by default. + this.highlightAlpha = null; + // prop: bubbleGradients + // True to color the bubbles with gradient fills instead of flat colors. + // NOT AVAILABLE IN IE due to lack of excanvas support for radial gradient fills. + // will be ignored in IE. + this.bubbleGradients = false; + // prop: showLabels + // True to show labels on bubbles (if any), false to not show. + this.showLabels = true; + // array of [point index, radius] which will be sorted in descending order to plot + // largest points below smaller points. + this.radii = []; + this.maxRadius = 0; + // index of the currenty highlighted point, if any + this._highlightedPoint = null; + // array of jQuery labels. + this.labels = []; + this.bubbleCanvases = []; + this._type = 'bubble'; + + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (options.highlightMouseDown && options.highlightMouseOver == null) { + options.highlightMouseOver = false; + } + + $.extend(true, this, options); + + if (this.highlightAlpha == null) { + this.highlightAlpha = this.bubbleAlpha; + if (this.bubbleGradients) { + this.highlightAlpha = 0.35; + } + } + + this.autoscaleMultiplier = this.autoscaleMultiplier * Math.pow(this.data.length, this.autoscalePointsFactor); + + // index of the currenty highlighted point, if any + this._highlightedPoint = null; + + // adjust the series colors for options colors passed in with data or for alpha. + // note, this can leave undefined holes in the seriesColors array. + var comps; + for (var i=0; i<this.data.length; i++) { + var color = null; + var d = this.data[i]; + this.maxRadius = Math.max(this.maxRadius, d[2]); + if (d[3]) { + if (typeof(d[3]) == 'object') { + color = d[3]['color']; + } + } + + if (color == null) { + if (this.seriesColors[i] != null) { + color = this.seriesColors[i]; + } + } + + if (color && this.bubbleAlpha < 1.0) { + comps = $.jqplot.getColorComponents(color); + color = 'rgba('+comps[0]+', '+comps[1]+', '+comps[2]+', '+this.bubbleAlpha+')'; + } + + if (color) { + this.seriesColors[i] = color; + } + } + + if (!this.varyBubbleColors) { + this.seriesColors = [this.color]; + } + + this.colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors); + + // set highlight colors if none provided + if (this.highlightColors.length == 0) { + for (var i=0; i<this.seriesColors.length; i++){ + var rgba = $.jqplot.getColorComponents(this.seriesColors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + this.highlightColors.push('rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+', '+this.highlightAlpha+')'); + } + } + + this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors); + + var sopts = {fill:true, isarc:true, angle:this.shadowAngle, alpha:this.shadowAlpha, closePath:true}; + + this.renderer.shadowRenderer.init(sopts); + + this.canvas = new $.jqplot.DivCanvas(); + this.canvas._plotDimensions = this._plotDimensions; + + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + plot.postDrawHooks.addOnce(postPlotDraw); + + }; + + + // converts the user data values to grid coordinates and stores them + // in the gridData array. + // Called with scope of a series. + $.jqplot.BubbleRenderer.prototype.setGridData = function(plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var data = this._plotData; + this.gridData = []; + var radii = []; + this.radii = []; + var dim = Math.min(plot._height, plot._width); + for (var i=0; i<this.data.length; i++) { + if (data[i] != null) { + this.gridData.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1]), data[i][2]]); + this.radii.push([i, data[i][2]]); + radii.push(data[i][2]); + } + } + var r, val, maxr = this.maxRadius = arrayMax(radii); + var l = this.gridData.length; + if (this.autoscaleBubbles) { + for (var i=0; i<l; i++) { + val = radii[i]/maxr; + r = this.autoscaleMultiplier * dim / 6; + this.gridData[i][2] = r * val; + } + } + + this.radii.sort(function(a, b) { return b[1] - a[1]; }); + }; + + // converts any arbitrary data values to grid coordinates and + // returns them. This method exists so that plugins can use a series' + // linerenderer to generate grid data points without overwriting the + // grid data associated with that series. + // Called with scope of a series. + $.jqplot.BubbleRenderer.prototype.makeGridData = function(data, plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var gd = []; + var radii = []; + this.radii = []; + var dim = Math.min(plot._height, plot._width); + for (var i=0; i<data.length; i++) { + if (data[i] != null) { + gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1]), data[i][2]]); + radii.push(data[i][2]); + this.radii.push([i, data[i][2]]); + } + } + var r, val, maxr = this.maxRadius = arrayMax(radii); + var l = this.gridData.length; + if (this.autoscaleBubbles) { + for (var i=0; i<l; i++) { + val = radii[i]/maxr; + r = this.autoscaleMultiplier * dim / 6; + gd[i][2] = r * val; + } + } + this.radii.sort(function(a, b) { return b[1] - a[1]; }); + return gd; + }; + + // called with scope of series + $.jqplot.BubbleRenderer.prototype.draw = function (ctx, gd, options) { + if (this.plugins.pointLabels) { + this.plugins.pointLabels.show = false; + } + var opts = (options != undefined) ? options : {}; + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + this.canvas._elem.empty(); + for (var i=0; i<this.radii.length; i++) { + var idx = this.radii[i][0]; + var t=null; + var color = null; + var el = null; + var tel = null; + var d = this.data[idx]; + var gd = this.gridData[idx]; + if (d[3]) { + if (typeof(d[3]) == 'object') { + t = d[3]['label']; + } + else if (typeof(d[3]) == 'string') { + t = d[3]; + } + } + + // color = (this.varyBubbleColors) ? this.colorGenerator.get(idx) : this.color; + color = this.colorGenerator.get(idx); + + // If we're drawing a shadow, expand the canvas dimensions to accomodate. + var canvasRadius = gd[2]; + var offset, depth; + if (this.shadow) { + offset = (0.7 + gd[2]/40).toFixed(1); + depth = 1 + Math.ceil(gd[2]/15); + canvasRadius += offset*depth; + } + this.bubbleCanvases[idx] = new $.jqplot.BubbleCanvas(); + this.canvas._elem.append(this.bubbleCanvases[idx].createElement(gd[0], gd[1], canvasRadius)); + this.bubbleCanvases[idx].setContext(); + var ctx = this.bubbleCanvases[idx]._ctx; + var x = ctx.canvas.width/2; + var y = ctx.canvas.height/2; + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [x, y, gd[2], 0, 2*Math.PI], {offset: offset, depth: depth}); + } + this.bubbleCanvases[idx].draw(gd[2], color, this.bubbleGradients, this.shadowAngle/180*Math.PI); + + // now draw label. + if (t && this.showLabels) { + tel = $('<div style="position:absolute;" class="jqplot-bubble-label"></div>'); + if (this.escapeHtml) { + tel.text(t); + } + else { + tel.html(t); + } + this.canvas._elem.append(tel); + var h = $(tel).outerHeight(); + var w = $(tel).outerWidth(); + var top = gd[1] - 0.5*h; + var left = gd[0] - 0.5*w; + tel.css({top: top, left: left}); + this.labels[idx] = $(tel); + } + } + }; + + + $.jqplot.DivCanvas = function() { + $.jqplot.ElemContainer.call(this); + this._ctx; + }; + + $.jqplot.DivCanvas.prototype = new $.jqplot.ElemContainer(); + $.jqplot.DivCanvas.prototype.constructor = $.jqplot.DivCanvas; + + $.jqplot.DivCanvas.prototype.createElement = function(offsets, clss, plotDimensions) { + this._offsets = offsets; + var klass = 'jqplot-DivCanvas'; + if (clss != undefined) { + klass = clss; + } + var elem; + // if this canvas already has a dom element, don't make a new one. + if (this._elem) { + elem = this._elem.get(0); + } + else { + elem = document.createElement('div'); + } + // if new plotDimensions supplied, use them. + if (plotDimensions != undefined) { + this._plotDimensions = plotDimensions; + } + + var w = this._plotDimensions.width - this._offsets.left - this._offsets.right + 'px'; + var h = this._plotDimensions.height - this._offsets.top - this._offsets.bottom + 'px'; + this._elem = $(elem); + this._elem.css({ position: 'absolute', width:w, height:h, left: this._offsets.left, top: this._offsets.top }); + + this._elem.addClass(klass); + return this._elem; + }; + + $.jqplot.DivCanvas.prototype.setContext = function() { + this._ctx = { + canvas:{ + width:0, + height:0 + }, + clearRect:function(){return null;} + }; + return this._ctx; + }; + + $.jqplot.BubbleCanvas = function() { + $.jqplot.ElemContainer.call(this); + this._ctx; + }; + + $.jqplot.BubbleCanvas.prototype = new $.jqplot.ElemContainer(); + $.jqplot.BubbleCanvas.prototype.constructor = $.jqplot.BubbleCanvas; + + // initialize with the x,y pont of bubble center and the bubble radius. + $.jqplot.BubbleCanvas.prototype.createElement = function(x, y, r) { + var klass = 'jqplot-bubble-point'; + + var elem; + // if this canvas already has a dom element, don't make a new one. + if (this._elem) { + elem = this._elem.get(0); + } + else { + elem = document.createElement('canvas'); + } + + elem.width = (r != null) ? 2*r : elem.width; + elem.height = (r != null) ? 2*r : elem.height; + this._elem = $(elem); + var l = (x != null && r != null) ? x - r : this._elem.css('left'); + var t = (y != null && r != null) ? y - r : this._elem.css('top'); + this._elem.css({ position: 'absolute', left: l, top: t }); + + this._elem.addClass(klass); + if ($.jqplot.use_excanvas) { + window.G_vmlCanvasManager.init_(document); + elem = window.G_vmlCanvasManager.initElement(elem); + } + + return this._elem; + }; + + $.jqplot.BubbleCanvas.prototype.draw = function(r, color, gradients, angle) { + var ctx = this._ctx; + // r = Math.floor(r*1.04); + // var x = Math.round(ctx.canvas.width/2); + // var y = Math.round(ctx.canvas.height/2); + var x = ctx.canvas.width/2; + var y = ctx.canvas.height/2; + ctx.save(); + if (gradients && !$.jqplot.use_excanvas) { + r = r*1.04; + var comps = $.jqplot.getColorComponents(color); + var colorinner = 'rgba('+Math.round(comps[0]+0.8*(255-comps[0]))+', '+Math.round(comps[1]+0.8*(255-comps[1]))+', '+Math.round(comps[2]+0.8*(255-comps[2]))+', '+comps[3]+')'; + var colorend = 'rgba('+comps[0]+', '+comps[1]+', '+comps[2]+', 0)'; + // var rinner = Math.round(0.35 * r); + // var xinner = Math.round(x - Math.cos(angle) * 0.33 * r); + // var yinner = Math.round(y - Math.sin(angle) * 0.33 * r); + var rinner = 0.35 * r; + var xinner = x - Math.cos(angle) * 0.33 * r; + var yinner = y - Math.sin(angle) * 0.33 * r; + var radgrad = ctx.createRadialGradient(xinner, yinner, rinner, x, y, r); + radgrad.addColorStop(0, colorinner); + radgrad.addColorStop(0.93, color); + radgrad.addColorStop(0.96, colorend); + radgrad.addColorStop(1, colorend); + // radgrad.addColorStop(.98, colorend); + ctx.fillStyle = radgrad; + ctx.fillRect(0,0, ctx.canvas.width, ctx.canvas.height); + } + else { + ctx.fillStyle = color; + ctx.strokeStyle = color; + ctx.lineWidth = 1; + ctx.beginPath(); + var ang = 2*Math.PI; + ctx.arc(x, y, r, 0, ang, 0); + ctx.closePath(); + ctx.fill(); + } + ctx.restore(); + }; + + $.jqplot.BubbleCanvas.prototype.setContext = function() { + this._ctx = this._elem.get(0).getContext("2d"); + return this._ctx; + }; + + $.jqplot.BubbleAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + }; + + $.jqplot.BubbleAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.BubbleAxisRenderer.prototype.constructor = $.jqplot.BubbleAxisRenderer; + + // called with scope of axis object. + $.jqplot.BubbleAxisRenderer.prototype.init = function(options){ + $.extend(true, this, options); + var db = this._dataBounds; + var minsidx = 0, + minpidx = 0, + maxsidx = 0, + maxpidx = 0, + maxr = 0, + minr = 0, + minMaxRadius = 0, + maxMaxRadius = 0, + maxMult = 0, + minMult = 0; + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + var d = s._plotData; + + for (var j=0; j<d.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + if (d[j][0] < db.min || db.min == null) { + db.min = d[j][0]; + minsidx=i; + minpidx=j; + minr = d[j][2]; + minMaxRadius = s.maxRadius; + minMult = s.autoscaleMultiplier; + } + if (d[j][0] > db.max || db.max == null) { + db.max = d[j][0]; + maxsidx=i; + maxpidx=j; + maxr = d[j][2]; + maxMaxRadius = s.maxRadius; + maxMult = s.autoscaleMultiplier; + } + } + else { + if (d[j][1] < db.min || db.min == null) { + db.min = d[j][1]; + minsidx=i; + minpidx=j; + minr = d[j][2]; + minMaxRadius = s.maxRadius; + minMult = s.autoscaleMultiplier; + } + if (d[j][1] > db.max || db.max == null) { + db.max = d[j][1]; + maxsidx=i; + maxpidx=j; + maxr = d[j][2]; + maxMaxRadius = s.maxRadius; + maxMult = s.autoscaleMultiplier; + } + } + } + } + + var minRatio = minr/minMaxRadius; + var maxRatio = maxr/maxMaxRadius; + + // need to estimate the effect of the radius on total axis span and adjust axis accordingly. + var span = db.max - db.min; + // var dim = (this.name == 'xaxis' || this.name == 'x2axis') ? this._plotDimensions.width : this._plotDimensions.height; + var dim = Math.min(this._plotDimensions.width, this._plotDimensions.height); + + var minfact = minRatio * minMult/3 * span; + var maxfact = maxRatio * maxMult/3 * span; + db.max += maxfact; + db.min -= minfact; + }; + + function highlight (plot, sidx, pidx) { + plot.plugins.bubbleRenderer.highlightLabelCanvas.empty(); + var s = plot.series[sidx]; + var canvas = plot.plugins.bubbleRenderer.highlightCanvas; + var ctx = canvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.bubbleRenderer.highlightedSeriesIndex = sidx; + + var color = s.highlightColorGenerator.get(pidx); + var x = s.gridData[pidx][0], + y = s.gridData[pidx][1], + r = s.gridData[pidx][2]; + ctx.save(); + ctx.fillStyle = color; + ctx.strokeStyle = color; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.arc(x, y, r, 0, 2*Math.PI, 0); + ctx.closePath(); + ctx.fill(); + ctx.restore(); + // bring label to front + if (s.labels[pidx]) { + plot.plugins.bubbleRenderer.highlightLabel = s.labels[pidx].clone(); + plot.plugins.bubbleRenderer.highlightLabel.appendTo(plot.plugins.bubbleRenderer.highlightLabelCanvas); + plot.plugins.bubbleRenderer.highlightLabel.addClass('jqplot-bubble-label-highlight'); + } + } + + function unhighlight (plot) { + var canvas = plot.plugins.bubbleRenderer.highlightCanvas; + var sidx = plot.plugins.bubbleRenderer.highlightedSeriesIndex; + plot.plugins.bubbleRenderer.highlightLabelCanvas.empty(); + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.bubbleRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + } + + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var si = neighbor.seriesIndex; + var pi = neighbor.pointIndex; + var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var si = neighbor.seriesIndex; + var pi = neighbor.pointIndex; + var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.bubbleRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var si = neighbor.seriesIndex; + var pi = neighbor.pointIndex; + var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]]; + var evt = jQuery.Event('jqplotDataClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var si = neighbor.seriesIndex; + var pi = neighbor.pointIndex; + var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]]; + var idx = plot.plugins.bubbleRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.bubbleRenderer && this.plugins.bubbleRenderer.highlightCanvas) { + this.plugins.bubbleRenderer.highlightCanvas.resetCanvas(); + this.plugins.bubbleRenderer.highlightCanvas = null; + } + + this.plugins.bubbleRenderer = {highlightedSeriesIndex:null}; + this.plugins.bubbleRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + this.plugins.bubbleRenderer.highlightLabel = null; + this.plugins.bubbleRenderer.highlightLabelCanvas = $('<div style="position:absolute;"></div>'); + var top = this._gridPadding.top; + var left = this._gridPadding.left; + var width = this._plotDimensions.width - this._gridPadding.left - this._gridPadding.right; + var height = this._plotDimensions.height - this._gridPadding.top - this._gridPadding.bottom; + this.plugins.bubbleRenderer.highlightLabelCanvas.css({top:top, left:left, width:width+'px', height:height+'px'}); + + this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-bubbleRenderer-highlight-canvas', this._plotDimensions, this)); + this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightLabelCanvas); + + var hctx = this.plugins.bubbleRenderer.highlightCanvas.setContext(); + } + + + // setup default renderers for axes and legend so user doesn't have to + // called with scope of plot + function preInit(target, data, options) { + options = options || {}; + options.axesDefaults = options.axesDefaults || {}; + options.seriesDefaults = options.seriesDefaults || {}; + // only set these if there is a Bubble series + var setopts = false; + if (options.seriesDefaults.renderer == $.jqplot.BubbleRenderer) { + setopts = true; + } + else if (options.series) { + for (var i=0; i < options.series.length; i++) { + if (options.series[i].renderer == $.jqplot.BubbleRenderer) { + setopts = true; + } + } + } + + if (setopts) { + options.axesDefaults.renderer = $.jqplot.BubbleAxisRenderer; + options.sortData = false; + } + } + + $.jqplot.preInitHooks.push(preInit); + +})(jQuery); + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.bubbleRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.bubbleRenderer.min.js new file mode 100644 index 0000000000..8f6c2a8db5 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.bubbleRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(f){var d=function(m){return Math.max.apply(Math,m)};var j=function(m){return Math.min.apply(Math,m)};f.jqplot.BubbleRenderer=function(){f.jqplot.LineRenderer.call(this)};f.jqplot.BubbleRenderer.prototype=new f.jqplot.LineRenderer();f.jqplot.BubbleRenderer.prototype.constructor=f.jqplot.BubbleRenderer;f.jqplot.BubbleRenderer.prototype.init=function(w,t){this.varyBubbleColors=true;this.autoscaleBubbles=true;this.autoscaleMultiplier=1;this.autoscalePointsFactor=-0.07;this.escapeHtml=true;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.bubbleAlpha=1;this.highlightAlpha=null;this.bubbleGradients=false;this.showLabels=true;this.radii=[];this.maxRadius=0;this._highlightedPoint=null;this.labels=[];this.bubbleCanvases=[];this._type="bubble";if(w.highlightMouseDown&&w.highlightMouseOver==null){w.highlightMouseOver=false}f.extend(true,this,w);if(this.highlightAlpha==null){this.highlightAlpha=this.bubbleAlpha;if(this.bubbleGradients){this.highlightAlpha=0.35}}this.autoscaleMultiplier=this.autoscaleMultiplier*Math.pow(this.data.length,this.autoscalePointsFactor);this._highlightedPoint=null;var n;for(var r=0;r<this.data.length;r++){var p=null;var v=this.data[r];this.maxRadius=Math.max(this.maxRadius,v[2]);if(v[3]){if(typeof(v[3])=="object"){p=v[3]["color"]}}if(p==null){if(this.seriesColors[r]!=null){p=this.seriesColors[r]}}if(p&&this.bubbleAlpha<1){n=f.jqplot.getColorComponents(p);p="rgba("+n[0]+", "+n[1]+", "+n[2]+", "+this.bubbleAlpha+")"}if(p){this.seriesColors[r]=p}}if(!this.varyBubbleColors){this.seriesColors=[this.color]}this.colorGenerator=new f.jqplot.ColorGenerator(this.seriesColors);if(this.highlightColors.length==0){for(var r=0;r<this.seriesColors.length;r++){var o=f.jqplot.getColorComponents(this.seriesColors[r]);var u=[o[0],o[1],o[2]];var s=u[0]+u[1]+u[2];for(var q=0;q<3;q++){u[q]=(s>570)?u[q]*0.8:u[q]+0.3*(255-u[q]);u[q]=parseInt(u[q],10)}this.highlightColors.push("rgba("+u[0]+","+u[1]+","+u[2]+", "+this.highlightAlpha+")")}}this.highlightColorGenerator=new f.jqplot.ColorGenerator(this.highlightColors);var m={fill:true,isarc:true,angle:this.shadowAngle,alpha:this.shadowAlpha,closePath:true};this.renderer.shadowRenderer.init(m);this.canvas=new f.jqplot.DivCanvas();this.canvas._plotDimensions=this._plotDimensions;t.eventListenerHooks.addOnce("jqplotMouseMove",a);t.eventListenerHooks.addOnce("jqplotMouseDown",b);t.eventListenerHooks.addOnce("jqplotMouseUp",k);t.eventListenerHooks.addOnce("jqplotClick",g);t.eventListenerHooks.addOnce("jqplotRightClick",l);t.postDrawHooks.addOnce(h)};f.jqplot.BubbleRenderer.prototype.setGridData=function(w){var q=this._xaxis.series_u2p;var m=this._yaxis.series_u2p;var t=this._plotData;this.gridData=[];var s=[];this.radii=[];var v=Math.min(w._height,w._width);for(var u=0;u<this.data.length;u++){if(t[u]!=null){this.gridData.push([q.call(this._xaxis,t[u][0]),m.call(this._yaxis,t[u][1]),t[u][2]]);this.radii.push([u,t[u][2]]);s.push(t[u][2])}}var n,o,x=this.maxRadius=d(s);var p=this.gridData.length;if(this.autoscaleBubbles){for(var u=0;u<p;u++){o=s[u]/x;n=this.autoscaleMultiplier*v/6;this.gridData[u][2]=n*o}}this.radii.sort(function(y,r){return r[1]-y[1]})};f.jqplot.BubbleRenderer.prototype.makeGridData=function(t,w){var q=this._xaxis.series_u2p;var n=this._yaxis.series_u2p;var x=[];var s=[];this.radii=[];var v=Math.min(w._height,w._width);for(var u=0;u<t.length;u++){if(t[u]!=null){x.push([q.call(this._xaxis,t[u][0]),n.call(this._yaxis,t[u][1]),t[u][2]]);s.push(t[u][2]);this.radii.push([u,t[u][2]])}}var m,o,y=this.maxRadius=d(s);var p=this.gridData.length;if(this.autoscaleBubbles){for(var u=0;u<p;u++){o=s[u]/y;m=this.autoscaleMultiplier*v/6;x[u][2]=m*o}}this.radii.sort(function(z,r){return r[1]-z[1]});return x};f.jqplot.BubbleRenderer.prototype.draw=function(D,J,n){if(this.plugins.pointLabels){this.plugins.pointLabels.show=false}var A=(n!=undefined)?n:{};var r=(A.shadow!=undefined)?A.shadow:this.shadow;this.canvas._elem.empty();for(var G=0;G<this.radii.length;G++){var C=this.radii[G][0];var z=null;var F=null;var m=null;var p=null;var I=this.data[C];var J=this.gridData[C];if(I[3]){if(typeof(I[3])=="object"){z=I[3]["label"]}else{if(typeof(I[3])=="string"){z=I[3]}}}F=this.colorGenerator.get(C);var E=J[2];var q,K;if(this.shadow){q=(0.7+J[2]/40).toFixed(1);K=1+Math.ceil(J[2]/15);E+=q*K}this.bubbleCanvases[C]=new f.jqplot.BubbleCanvas();this.canvas._elem.append(this.bubbleCanvases[C].createElement(J[0],J[1],E));this.bubbleCanvases[C].setContext();var D=this.bubbleCanvases[C]._ctx;var u=D.canvas.width/2;var s=D.canvas.height/2;if(this.shadow){this.renderer.shadowRenderer.draw(D,[u,s,J[2],0,2*Math.PI],{offset:q,depth:K})}this.bubbleCanvases[C].draw(J[2],F,this.bubbleGradients,this.shadowAngle/180*Math.PI);if(z&&this.showLabels){p=f('<div style="position:absolute;" class="jqplot-bubble-label"></div>');if(this.escapeHtml){p.text(z)}else{p.html(z)}this.canvas._elem.append(p);var H=f(p).outerHeight();var v=f(p).outerWidth();var B=J[1]-0.5*H;var o=J[0]-0.5*v;p.css({top:B,left:o});this.labels[C]=f(p)}}};f.jqplot.DivCanvas=function(){f.jqplot.ElemContainer.call(this);this._ctx};f.jqplot.DivCanvas.prototype=new f.jqplot.ElemContainer();f.jqplot.DivCanvas.prototype.constructor=f.jqplot.DivCanvas;f.jqplot.DivCanvas.prototype.createElement=function(s,p,n){this._offsets=s;var m="jqplot-DivCanvas";if(p!=undefined){m=p}var r;if(this._elem){r=this._elem.get(0)}else{r=document.createElement("div")}if(n!=undefined){this._plotDimensions=n}var o=this._plotDimensions.width-this._offsets.left-this._offsets.right+"px";var q=this._plotDimensions.height-this._offsets.top-this._offsets.bottom+"px";this._elem=f(r);this._elem.css({position:"absolute",width:o,height:q,left:this._offsets.left,top:this._offsets.top});this._elem.addClass(m);return this._elem};f.jqplot.DivCanvas.prototype.setContext=function(){this._ctx={canvas:{width:0,height:0},clearRect:function(){return null}};return this._ctx};f.jqplot.BubbleCanvas=function(){f.jqplot.ElemContainer.call(this);this._ctx};f.jqplot.BubbleCanvas.prototype=new f.jqplot.ElemContainer();f.jqplot.BubbleCanvas.prototype.constructor=f.jqplot.BubbleCanvas;f.jqplot.BubbleCanvas.prototype.createElement=function(n,u,s){var m="jqplot-bubble-point";var q;if(this._elem){q=this._elem.get(0)}else{q=document.createElement("canvas")}q.width=(s!=null)?2*s:q.width;q.height=(s!=null)?2*s:q.height;this._elem=f(q);var o=(n!=null&&s!=null)?n-s:this._elem.css("left");var p=(u!=null&&s!=null)?u-s:this._elem.css("top");this._elem.css({position:"absolute",left:o,top:p});this._elem.addClass(m);if(f.jqplot.use_excanvas){window.G_vmlCanvasManager.init_(document);q=window.G_vmlCanvasManager.initElement(q)}return this._elem};f.jqplot.BubbleCanvas.prototype.draw=function(m,s,v,p){var D=this._ctx;var B=D.canvas.width/2;var z=D.canvas.height/2;D.save();if(v&&!f.jqplot.use_excanvas){m=m*1.04;var o=f.jqplot.getColorComponents(s);var u="rgba("+Math.round(o[0]+0.8*(255-o[0]))+", "+Math.round(o[1]+0.8*(255-o[1]))+", "+Math.round(o[2]+0.8*(255-o[2]))+", "+o[3]+")";var t="rgba("+o[0]+", "+o[1]+", "+o[2]+", 0)";var C=0.35*m;var A=B-Math.cos(p)*0.33*m;var n=z-Math.sin(p)*0.33*m;var w=D.createRadialGradient(A,n,C,B,z,m);w.addColorStop(0,u);w.addColorStop(0.93,s);w.addColorStop(0.96,t);w.addColorStop(1,t);D.fillStyle=w;D.fillRect(0,0,D.canvas.width,D.canvas.height)}else{D.fillStyle=s;D.strokeStyle=s;D.lineWidth=1;D.beginPath();var q=2*Math.PI;D.arc(B,z,m,0,q,0);D.closePath();D.fill()}D.restore()};f.jqplot.BubbleCanvas.prototype.setContext=function(){this._ctx=this._elem.get(0).getContext("2d");return this._ctx};f.jqplot.BubbleAxisRenderer=function(){f.jqplot.LinearAxisRenderer.call(this)};f.jqplot.BubbleAxisRenderer.prototype=new f.jqplot.LinearAxisRenderer();f.jqplot.BubbleAxisRenderer.prototype.constructor=f.jqplot.BubbleAxisRenderer;f.jqplot.BubbleAxisRenderer.prototype.init=function(n){f.extend(true,this,n);var I=this._dataBounds;var H=0,v=0,m=0,y=0,q=0,r=0,D=0,t=0,F=0,z=0;for(var E=0;E<this._series.length;E++){var x=this._series[E];var G=x._plotData;for(var B=0;B<G.length;B++){if(this.name=="xaxis"||this.name=="x2axis"){if(G[B][0]<I.min||I.min==null){I.min=G[B][0];H=E;v=B;r=G[B][2];D=x.maxRadius;z=x.autoscaleMultiplier}if(G[B][0]>I.max||I.max==null){I.max=G[B][0];m=E;y=B;q=G[B][2];t=x.maxRadius;F=x.autoscaleMultiplier}}else{if(G[B][1]<I.min||I.min==null){I.min=G[B][1];H=E;v=B;r=G[B][2];D=x.maxRadius;z=x.autoscaleMultiplier}if(G[B][1]>I.max||I.max==null){I.max=G[B][1];m=E;y=B;q=G[B][2];t=x.maxRadius;F=x.autoscaleMultiplier}}}}var o=r/D;var w=q/t;var C=I.max-I.min;var A=Math.min(this._plotDimensions.width,this._plotDimensions.height);var p=o*z/3*C;var u=w*F/3*C;I.max+=u;I.min-=p};function e(p,v,q){p.plugins.bubbleRenderer.highlightLabelCanvas.empty();var z=p.series[v];var n=p.plugins.bubbleRenderer.highlightCanvas;var w=n._ctx;w.clearRect(0,0,w.canvas.width,w.canvas.height);z._highlightedPoint=q;p.plugins.bubbleRenderer.highlightedSeriesIndex=v;var o=z.highlightColorGenerator.get(q);var u=z.gridData[q][0],t=z.gridData[q][1],m=z.gridData[q][2];w.save();w.fillStyle=o;w.strokeStyle=o;w.lineWidth=1;w.beginPath();w.arc(u,t,m,0,2*Math.PI,0);w.closePath();w.fill();w.restore();if(z.labels[q]){p.plugins.bubbleRenderer.highlightLabel=z.labels[q].clone();p.plugins.bubbleRenderer.highlightLabel.appendTo(p.plugins.bubbleRenderer.highlightLabelCanvas);p.plugins.bubbleRenderer.highlightLabel.addClass("jqplot-bubble-label-highlight")}}function i(p){var m=p.plugins.bubbleRenderer.highlightCanvas;var o=p.plugins.bubbleRenderer.highlightedSeriesIndex;p.plugins.bubbleRenderer.highlightLabelCanvas.empty();m._ctx.clearRect(0,0,m._ctx.canvas.width,m._ctx.canvas.height);for(var n=0;n<p.series.length;n++){p.series[n]._highlightedPoint=null}p.plugins.bubbleRenderer.highlightedSeriesIndex=null;p.target.trigger("jqplotDataUnhighlight")}function a(s,p,m,v,r){if(v){var n=v.seriesIndex;var o=v.pointIndex;var q=[n,o,v.data,r.series[n].gridData[o][2]];var t=jQuery.Event("jqplotDataMouseOver");t.pageX=s.pageX;t.pageY=s.pageY;r.target.trigger(t,q);if(r.series[q[0]].highlightMouseOver&&!(q[0]==r.plugins.bubbleRenderer.highlightedSeriesIndex&&q[1]==r.series[q[0]]._highlightedPoint)){var u=jQuery.Event("jqplotDataHighlight");u.pageX=s.pageX;u.pageY=s.pageY;r.target.trigger(u,q);e(r,q[0],q[1])}}else{if(v==null){i(r)}}}function b(s,p,m,u,r){if(u){var n=u.seriesIndex;var o=u.pointIndex;var q=[n,o,u.data,r.series[n].gridData[o][2]];if(r.series[q[0]].highlightMouseDown&&!(q[0]==r.plugins.bubbleRenderer.highlightedSeriesIndex&&q[1]==r.series[q[0]]._highlightedPoint)){var t=jQuery.Event("jqplotDataHighlight");t.pageX=s.pageX;t.pageY=s.pageY;r.target.trigger(t,q);e(r,q[0],q[1])}}else{if(u==null){i(r)}}}function k(o,n,r,q,p){var m=p.plugins.bubbleRenderer.highlightedSeriesIndex;if(m!=null&&p.series[m].highlightMouseDown){i(p)}}function g(s,p,m,u,r){if(u){var n=u.seriesIndex;var o=u.pointIndex;var q=[n,o,u.data,r.series[n].gridData[o][2]];var t=jQuery.Event("jqplotDataClick");t.pageX=s.pageX;t.pageY=s.pageY;r.target.trigger(t,q)}}function l(s,p,m,v,r){if(v){var n=v.seriesIndex;var o=v.pointIndex;var q=[n,o,v.data,r.series[n].gridData[o][2]];var t=r.plugins.bubbleRenderer.highlightedSeriesIndex;if(t!=null&&r.series[t].highlightMouseDown){i(r)}var u=jQuery.Event("jqplotDataRightClick");u.pageX=s.pageX;u.pageY=s.pageY;r.target.trigger(u,q)}}function h(){if(this.plugins.bubbleRenderer&&this.plugins.bubbleRenderer.highlightCanvas){this.plugins.bubbleRenderer.highlightCanvas.resetCanvas();this.plugins.bubbleRenderer.highlightCanvas=null}this.plugins.bubbleRenderer={highlightedSeriesIndex:null};this.plugins.bubbleRenderer.highlightCanvas=new f.jqplot.GenericCanvas();this.plugins.bubbleRenderer.highlightLabel=null;this.plugins.bubbleRenderer.highlightLabelCanvas=f('<div style="position:absolute;"></div>');var q=this._gridPadding.top;var p=this._gridPadding.left;var n=this._plotDimensions.width-this._gridPadding.left-this._gridPadding.right;var m=this._plotDimensions.height-this._gridPadding.top-this._gridPadding.bottom;this.plugins.bubbleRenderer.highlightLabelCanvas.css({top:q,left:p,width:n+"px",height:m+"px"});this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-bubbleRenderer-highlight-canvas",this._plotDimensions,this));this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightLabelCanvas);var o=this.plugins.bubbleRenderer.highlightCanvas.setContext()}function c(q,p,n){n=n||{};n.axesDefaults=n.axesDefaults||{};n.seriesDefaults=n.seriesDefaults||{};var m=false;if(n.seriesDefaults.renderer==f.jqplot.BubbleRenderer){m=true}else{if(n.series){for(var o=0;o<n.series.length;o++){if(n.series[o].renderer==f.jqplot.BubbleRenderer){m=true}}}}if(m){n.axesDefaults.renderer=f.jqplot.BubbleAxisRenderer;n.sortData=false}}f.jqplot.preInitHooks.push(c)})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisLabelRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisLabelRenderer.js new file mode 100644 index 0000000000..8cb6e183f6 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisLabelRenderer.js @@ -0,0 +1,207 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.CanvasAxisLabelRenderer + * Renderer to draw axis labels with a canvas element to support advanced + * featrues such as rotated text. This renderer uses a separate rendering engine + * to draw the text on the canvas. Two modes of rendering the text are available. + * If the browser has native font support for canvas fonts (currently Mozila 3.5 + * and Safari 4), you can enable text rendering with the canvas fillText method. + * You do so by setting the "enableFontSupport" option to true. + * + * Browsers lacking native font support will have the text drawn on the canvas + * using the Hershey font metrics. Even if the "enableFontSupport" option is true + * non-supporting browsers will still render with the Hershey font. + * + */ + $.jqplot.CanvasAxisLabelRenderer = function(options) { + // Group: Properties + + // prop: angle + // angle of text, measured clockwise from x axis. + this.angle = 0; + // name of the axis associated with this tick + this.axis; + // prop: show + // wether or not to show the tick (mark and label). + this.show = true; + // prop: showLabel + // wether or not to show the label. + this.showLabel = true; + // prop: label + // label for the axis. + this.label = ''; + // prop: fontFamily + // CSS spec for the font-family css attribute. + // Applies only to browsers supporting native font rendering in the + // canvas tag. Currently Mozilla 3.5 and Safari 4. + this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'; + // prop: fontSize + // CSS spec for font size. + this.fontSize = '11pt'; + // prop: fontWeight + // CSS spec for fontWeight: normal, bold, bolder, lighter or a number 100 - 900 + this.fontWeight = 'normal'; + // prop: fontStretch + // Multiplier to condense or expand font width. + // Applies only to browsers which don't support canvas native font rendering. + this.fontStretch = 1.0; + // prop: textColor + // css spec for the color attribute. + this.textColor = '#666666'; + // prop: enableFontSupport + // true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+. + // If true, label will be drawn with canvas tag native support for fonts. + // If false, label will be drawn with Hershey font metrics. + this.enableFontSupport = true; + // prop: pt2px + // Point to pixel scaling factor, used for computing height of bounding box + // around a label. The labels text renderer has a default setting of 1.4, which + // should be suitable for most fonts. Leave as null to use default. If tops of + // letters appear clipped, increase this. If bounding box seems too big, decrease. + // This is an issue only with the native font renderering capabilities of Mozilla + // 3.5 and Safari 4 since they do not provide a method to determine the font height. + this.pt2px = null; + + this._elem; + this._ctx; + this._plotWidth; + this._plotHeight; + this._plotDimensions = {height:null, width:null}; + + $.extend(true, this, options); + + if (options.angle == null && this.axis != 'xaxis' && this.axis != 'x2axis') { + this.angle = -90; + } + + var ropts = {fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily}; + if (this.pt2px) { + ropts.pt2px = this.pt2px; + } + + if (this.enableFontSupport) { + + function support_canvas_text() { + return !!(document.createElement('canvas').getContext && typeof document.createElement('canvas').getContext('2d').fillText == 'function'); + } + + if (support_canvas_text()) { + this._textRenderer = new $.jqplot.CanvasFontRenderer(ropts); + } + + else { + this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); + } + } + else { + this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); + } + }; + + $.jqplot.CanvasAxisLabelRenderer.prototype.init = function(options) { + $.extend(true, this, options); + this._textRenderer.init({fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily}); + }; + + // return width along the x axis + // will check first to see if an element exists. + // if not, will return the computed text box width. + $.jqplot.CanvasAxisLabelRenderer.prototype.getWidth = function(ctx) { + if (this._elem) { + return this._elem.outerWidth(true); + } + else { + var tr = this._textRenderer; + var l = tr.getWidth(ctx); + var h = tr.getHeight(ctx); + var w = Math.abs(Math.sin(tr.angle)*h) + Math.abs(Math.cos(tr.angle)*l); + return w; + } + }; + + // return height along the y axis. + $.jqplot.CanvasAxisLabelRenderer.prototype.getHeight = function(ctx) { + if (this._elem) { + return this._elem.outerHeight(true); + } + else { + var tr = this._textRenderer; + var l = tr.getWidth(ctx); + var h = tr.getHeight(ctx); + var w = Math.abs(Math.cos(tr.angle)*h) + Math.abs(Math.sin(tr.angle)*l); + return w; + } + }; + + $.jqplot.CanvasAxisLabelRenderer.prototype.getAngleRad = function() { + var a = this.angle * Math.PI/180; + return a; + }; + + $.jqplot.CanvasAxisLabelRenderer.prototype.draw = function(ctx, plot) { + // Memory Leaks patch + if (this._elem) { + if ($.jqplot.use_excanvas) { + window.G_vmlCanvasManager.uninitElement(this._elem.get(0)); + } + + this._elem.emptyForce(); + this._elem = null; + } + + // create a canvas here, but can't draw on it untill it is appended + // to dom for IE compatability. + var elem = plot.canvasManager.getCanvas(); + + this._textRenderer.setText(this.label, ctx); + var w = this.getWidth(ctx); + var h = this.getHeight(ctx); + elem.width = w; + elem.height = h; + elem.style.width = w; + elem.style.height = h; + + elem = plot.canvasManager.initCanvas(elem); + + this._elem = $(elem); + this._elem.css({ position: 'absolute'}); + this._elem.addClass('jqplot-'+this.axis+'-label'); + + elem = null; + return this._elem; + }; + + $.jqplot.CanvasAxisLabelRenderer.prototype.pack = function() { + this._textRenderer.draw(this._elem.get(0).getContext("2d"), this.label); + }; + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisLabelRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisLabelRenderer.min.js new file mode 100644 index 0000000000..173cb3e7d4 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisLabelRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.CanvasAxisLabelRenderer=function(b){this.angle=0;this.axis;this.show=true;this.showLabel=true;this.label="";this.fontFamily='"Trebuchet MS", Arial, Helvetica, sans-serif';this.fontSize="11pt";this.fontWeight="normal";this.fontStretch=1;this.textColor="#666666";this.enableFontSupport=true;this.pt2px=null;this._elem;this._ctx;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null};a.extend(true,this,b);if(b.angle==null&&this.axis!="xaxis"&&this.axis!="x2axis"){this.angle=-90}var c={fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily};if(this.pt2px){c.pt2px=this.pt2px}if(this.enableFontSupport){function d(){return !!(document.createElement("canvas").getContext&&typeof document.createElement("canvas").getContext("2d").fillText=="function")}if(d()){this._textRenderer=new a.jqplot.CanvasFontRenderer(c)}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}};a.jqplot.CanvasAxisLabelRenderer.prototype.init=function(b){a.extend(true,this,b);this._textRenderer.init({fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily})};a.jqplot.CanvasAxisLabelRenderer.prototype.getWidth=function(d){if(this._elem){return this._elem.outerWidth(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.sin(f.angle)*e)+Math.abs(Math.cos(f.angle)*c);return b}};a.jqplot.CanvasAxisLabelRenderer.prototype.getHeight=function(d){if(this._elem){return this._elem.outerHeight(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.cos(f.angle)*e)+Math.abs(Math.sin(f.angle)*c);return b}};a.jqplot.CanvasAxisLabelRenderer.prototype.getAngleRad=function(){var b=this.angle*Math.PI/180;return b};a.jqplot.CanvasAxisLabelRenderer.prototype.draw=function(c,f){if(this._elem){if(a.jqplot.use_excanvas){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce();this._elem=null}var e=f.canvasManager.getCanvas();this._textRenderer.setText(this.label,c);var b=this.getWidth(c);var d=this.getHeight(c);e.width=b;e.height=d;e.style.width=b;e.style.height=d;e=f.canvasManager.initCanvas(e);this._elem=a(e);this._elem.css({position:"absolute"});this._elem.addClass("jqplot-"+this.axis+"-label");e=null;return this._elem};a.jqplot.CanvasAxisLabelRenderer.prototype.pack=function(){this._textRenderer.draw(this._elem.get(0).getContext("2d"),this.label)}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisTickRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisTickRenderer.js new file mode 100644 index 0000000000..92cb078c4b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisTickRenderer.js @@ -0,0 +1,247 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.CanvasAxisTickRenderer + * Renderer to draw axis ticks with a canvas element to support advanced + * featrues such as rotated text. This renderer uses a separate rendering engine + * to draw the text on the canvas. Two modes of rendering the text are available. + * If the browser has native font support for canvas fonts (currently Mozila 3.5 + * and Safari 4), you can enable text rendering with the canvas fillText method. + * You do so by setting the "enableFontSupport" option to true. + * + * Browsers lacking native font support will have the text drawn on the canvas + * using the Hershey font metrics. Even if the "enableFontSupport" option is true + * non-supporting browsers will still render with the Hershey font. + */ + $.jqplot.CanvasAxisTickRenderer = function(options) { + // Group: Properties + + // prop: mark + // tick mark on the axis. One of 'inside', 'outside', 'cross', '' or null. + this.mark = 'outside'; + // prop: showMark + // wether or not to show the mark on the axis. + this.showMark = true; + // prop: showGridline + // wether or not to draw the gridline on the grid at this tick. + this.showGridline = true; + // prop: isMinorTick + // if this is a minor tick. + this.isMinorTick = false; + // prop: angle + // angle of text, measured clockwise from x axis. + this.angle = 0; + // prop: markSize + // Length of the tick marks in pixels. For 'cross' style, length + // will be stoked above and below axis, so total length will be twice this. + this.markSize = 4; + // prop: show + // wether or not to show the tick (mark and label). + this.show = true; + // prop: showLabel + // wether or not to show the label. + this.showLabel = true; + // prop: labelPosition + // 'auto', 'start', 'middle' or 'end'. + // Whether tick label should be positioned so the start, middle, or end + // of the tick mark. + this.labelPosition = 'auto'; + this.label = ''; + this.value = null; + this._styles = {}; + // prop: formatter + // A class of a formatter for the tick text. + // The default $.jqplot.DefaultTickFormatter uses sprintf. + this.formatter = $.jqplot.DefaultTickFormatter; + // prop: formatString + // string passed to the formatter. + this.formatString = ''; + // prop: prefix + // String to prepend to the tick label. + // Prefix is prepended to the formatted tick label. + this.prefix = ''; + // prop: fontFamily + // css spec for the font-family css attribute. + this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'; + // prop: fontSize + // CSS spec for font size. + this.fontSize = '10pt'; + // prop: fontWeight + // CSS spec for fontWeight + this.fontWeight = 'normal'; + // prop: fontStretch + // Multiplier to condense or expand font width. + // Applies only to browsers which don't support canvas native font rendering. + this.fontStretch = 1.0; + // prop: textColor + // css spec for the color attribute. + this.textColor = '#666666'; + // prop: enableFontSupport + // true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+. + // If true, tick label will be drawn with canvas tag native support for fonts. + // If false, tick label will be drawn with Hershey font metrics. + this.enableFontSupport = true; + // prop: pt2px + // Point to pixel scaling factor, used for computing height of bounding box + // around a label. The labels text renderer has a default setting of 1.4, which + // should be suitable for most fonts. Leave as null to use default. If tops of + // letters appear clipped, increase this. If bounding box seems too big, decrease. + // This is an issue only with the native font renderering capabilities of Mozilla + // 3.5 and Safari 4 since they do not provide a method to determine the font height. + this.pt2px = null; + + this._elem; + this._ctx; + this._plotWidth; + this._plotHeight; + this._plotDimensions = {height:null, width:null}; + + $.extend(true, this, options); + + var ropts = {fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily}; + if (this.pt2px) { + ropts.pt2px = this.pt2px; + } + + if (this.enableFontSupport) { + + function support_canvas_text() { + return !!(document.createElement('canvas').getContext && typeof document.createElement('canvas').getContext('2d').fillText == 'function'); + } + + if (support_canvas_text()) { + this._textRenderer = new $.jqplot.CanvasFontRenderer(ropts); + } + + else { + this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); + } + } + else { + this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); + } + }; + + $.jqplot.CanvasAxisTickRenderer.prototype.init = function(options) { + $.extend(true, this, options); + this._textRenderer.init({fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily}); + }; + + // return width along the x axis + // will check first to see if an element exists. + // if not, will return the computed text box width. + $.jqplot.CanvasAxisTickRenderer.prototype.getWidth = function(ctx) { + if (this._elem) { + return this._elem.outerWidth(true); + } + else { + var tr = this._textRenderer; + var l = tr.getWidth(ctx); + var h = tr.getHeight(ctx); + var w = Math.abs(Math.sin(tr.angle)*h) + Math.abs(Math.cos(tr.angle)*l); + return w; + } + }; + + // return height along the y axis. + $.jqplot.CanvasAxisTickRenderer.prototype.getHeight = function(ctx) { + if (this._elem) { + return this._elem.outerHeight(true); + } + else { + var tr = this._textRenderer; + var l = tr.getWidth(ctx); + var h = tr.getHeight(ctx); + var w = Math.abs(Math.cos(tr.angle)*h) + Math.abs(Math.sin(tr.angle)*l); + return w; + } + }; + + $.jqplot.CanvasAxisTickRenderer.prototype.getAngleRad = function() { + var a = this.angle * Math.PI/180; + return a; + }; + + + $.jqplot.CanvasAxisTickRenderer.prototype.setTick = function(value, axisName, isMinor) { + this.value = value; + if (isMinor) { + this.isMinorTick = true; + } + return this; + }; + + $.jqplot.CanvasAxisTickRenderer.prototype.draw = function(ctx, plot) { + if (!this.label) { + this.label = this.prefix + this.formatter(this.formatString, this.value); + } + + // Memory Leaks patch + if (this._elem) { + if ($.jqplot.use_excanvas) { + window.G_vmlCanvasManager.uninitElement(this._elem.get(0)); + } + + this._elem.emptyForce(); + this._elem = null; + } + + // create a canvas here, but can't draw on it untill it is appended + // to dom for IE compatability. + + var elem = plot.canvasManager.getCanvas(); + + this._textRenderer.setText(this.label, ctx); + var w = this.getWidth(ctx); + var h = this.getHeight(ctx); + // canvases seem to need to have width and heigh attributes directly set. + elem.width = w; + elem.height = h; + elem.style.width = w; + elem.style.height = h; + elem.style.textAlign = 'left'; + elem.style.position = 'absolute'; + + elem = plot.canvasManager.initCanvas(elem); + + this._elem = $(elem); + this._elem.css(this._styles); + this._elem.addClass('jqplot-'+this.axis+'-tick'); + + elem = null; + return this._elem; + }; + + $.jqplot.CanvasAxisTickRenderer.prototype.pack = function() { + this._textRenderer.draw(this._elem.get(0).getContext("2d"), this.label); + }; + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js new file mode 100644 index 0000000000..7162b43378 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.CanvasAxisTickRenderer=function(b){this.mark="outside";this.showMark=true;this.showGridline=true;this.isMinorTick=false;this.angle=0;this.markSize=4;this.show=true;this.showLabel=true;this.labelPosition="auto";this.label="";this.value=null;this._styles={};this.formatter=a.jqplot.DefaultTickFormatter;this.formatString="";this.prefix="";this.fontFamily='"Trebuchet MS", Arial, Helvetica, sans-serif';this.fontSize="10pt";this.fontWeight="normal";this.fontStretch=1;this.textColor="#666666";this.enableFontSupport=true;this.pt2px=null;this._elem;this._ctx;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null};a.extend(true,this,b);var c={fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily};if(this.pt2px){c.pt2px=this.pt2px}if(this.enableFontSupport){function d(){return !!(document.createElement("canvas").getContext&&typeof document.createElement("canvas").getContext("2d").fillText=="function")}if(d()){this._textRenderer=new a.jqplot.CanvasFontRenderer(c)}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}};a.jqplot.CanvasAxisTickRenderer.prototype.init=function(b){a.extend(true,this,b);this._textRenderer.init({fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily})};a.jqplot.CanvasAxisTickRenderer.prototype.getWidth=function(d){if(this._elem){return this._elem.outerWidth(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.sin(f.angle)*e)+Math.abs(Math.cos(f.angle)*c);return b}};a.jqplot.CanvasAxisTickRenderer.prototype.getHeight=function(d){if(this._elem){return this._elem.outerHeight(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.cos(f.angle)*e)+Math.abs(Math.sin(f.angle)*c);return b}};a.jqplot.CanvasAxisTickRenderer.prototype.getAngleRad=function(){var b=this.angle*Math.PI/180;return b};a.jqplot.CanvasAxisTickRenderer.prototype.setTick=function(b,d,c){this.value=b;if(c){this.isMinorTick=true}return this};a.jqplot.CanvasAxisTickRenderer.prototype.draw=function(c,f){if(!this.label){this.label=this.prefix+this.formatter(this.formatString,this.value)}if(this._elem){if(a.jqplot.use_excanvas){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce();this._elem=null}var e=f.canvasManager.getCanvas();this._textRenderer.setText(this.label,c);var b=this.getWidth(c);var d=this.getHeight(c);e.width=b;e.height=d;e.style.width=b;e.style.height=d;e.style.textAlign="left";e.style.position="absolute";e=f.canvasManager.initCanvas(e);this._elem=a(e);this._elem.css(this._styles);this._elem.addClass("jqplot-"+this.axis+"-tick");e=null;return this._elem};a.jqplot.CanvasAxisTickRenderer.prototype.pack=function(){this._textRenderer.draw(this._elem.get(0).getContext("2d"),this.label)}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasOverlay.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasOverlay.js new file mode 100644 index 0000000000..b6301efde5 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasOverlay.js @@ -0,0 +1,705 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + // class: $.jqplot.CanvasOverlay + $.jqplot.CanvasOverlay = function(opts){ + var options = opts || {}; + this.options = { + show: $.jqplot.config.enablePlugins, + deferDraw: false + }; + // prop: objects + this.objects = []; + this.objectNames = []; + this.canvas = null; + this.markerRenderer = new $.jqplot.MarkerRenderer({style:'line'}); + this.markerRenderer.init(); + if (options.objects) { + var objs = options.objects, + obj; + for (var i=0; i<objs.length; i++) { + obj = objs[i]; + for (var n in obj) { + switch (n) { + case 'line': + this.addLine(obj[n]); + break; + case 'horizontalLine': + this.addHorizontalLine(obj[n]); + break; + case 'dashedHorizontalLine': + this.addDashedHorizontalLine(obj[n]); + break; + case 'verticalLine': + this.addVerticalLine(obj[n]); + break; + case 'dashedVerticalLine': + this.addDashedVerticalLine(obj[n]); + break; + default: + break; + } + } + } + } + $.extend(true, this.options, options); + }; + + // called with scope of a plot object + $.jqplot.CanvasOverlay.postPlotInit = function (target, data, opts) { + var options = opts || {}; + // add a canvasOverlay attribute to the plot + this.plugins.canvasOverlay = new $.jqplot.CanvasOverlay(options.canvasOverlay); + }; + + /** + * Class: Line + * A straight line. + */ + function Line(options) { + this.type = 'line'; + this.options = { + // prop: name + // Optional name for this overlay object. + // Can be later used to retrieve the object by name. + name: null, + // prop: show + // true to show (draw), false to not draw. + show: true, + // prop: lineWidth + // Width of the line. + lineWidth: 2, + // prop: lineCap + // Type of ending placed on the line ['round', 'butt', 'square'] + lineCap: 'round', + // prop: color + // color of the line + color: '#666666', + // prop: shadow + // wether or not to draw a shadow on the line + shadow: true, + // prop: shadowAngle + // Shadow angle in degrees + shadowAngle: 45, + // prop: shadowOffset + // Shadow offset from line in pixels + shadowOffset: 1, + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + shadowDepth: 3, + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + shadowAlpha: '0.07', + // prop: xaxis + // X axis to use for positioning/scaling the line. + xaxis: 'xaxis', + // prop: yaxis + // Y axis to use for positioning/scaling the line. + yaxis: 'yaxis', + // prop: start + // [x, y] coordinates for the start of the line. + start: [], + // prop: stop + // [x, y] coordinates for the end of the line. + stop: [] + }; + $.extend(true, this.options, options); + } + + /** + * Class: HorizontalLine + * A straight horizontal line. + */ + function HorizontalLine(options) { + this.type = 'horizontalLine'; + this.options = { + // prop: name + // Optional name for this overlay object. + // Can be later used to retrieve the object by name. + name: null, + // prop: show + // true to show (draw), false to not draw. + show: true, + // prop: lineWidth + // Width of the line. + lineWidth: 2, + // prop: lineCap + // Type of ending placed on the line ['round', 'butt', 'square'] + lineCap: 'round', + // prop: color + // color of the line + color: '#666666', + // prop: shadow + // wether or not to draw a shadow on the line + shadow: true, + // prop: shadowAngle + // Shadow angle in degrees + shadowAngle: 45, + // prop: shadowOffset + // Shadow offset from line in pixels + shadowOffset: 1, + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + shadowDepth: 3, + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + shadowAlpha: '0.07', + // prop: xaxis + // X axis to use for positioning/scaling the line. + xaxis: 'xaxis', + // prop: yaxis + // Y axis to use for positioning/scaling the line. + yaxis: 'yaxis', + // prop: y + // y value to position the line + y: null, + // prop: xmin + // x value for the start of the line, null to scale to axis min. + xmin: null, + // prop: xmax + // x value for the end of the line, null to scale to axis max. + xmax: null, + // prop xOffset + // offset ends of the line inside the grid. Number + xOffset: '6px', // number or string. Number interpreted as units, string as pixels. + xminOffset: null, + xmaxOffset: null + }; + $.extend(true, this.options, options); + } + + + /** + * Class: DashedHorizontalLine + * A straight dashed horizontal line. + */ + function DashedHorizontalLine(options) { + this.type = 'dashedHorizontalLine'; + this.options = { + // prop: name + // Optional name for this overlay object. + // Can be later used to retrieve the object by name. + name: null, + // prop: show + // true to show (draw), false to not draw. + show: true, + // prop: lineWidth + // Width of the line. + lineWidth: 2, + // prop: lineCap + // Type of ending placed on the line ['round', 'butt', 'square'] + lineCap: 'butt', + // prop: color + // color of the line + color: '#666666', + // prop: shadow + // wether or not to draw a shadow on the line + shadow: true, + // prop: shadowAngle + // Shadow angle in degrees + shadowAngle: 45, + // prop: shadowOffset + // Shadow offset from line in pixels + shadowOffset: 1, + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + shadowDepth: 3, + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + shadowAlpha: '0.07', + // prop: xaxis + // X axis to use for positioning/scaling the line. + xaxis: 'xaxis', + // prop: yaxis + // Y axis to use for positioning/scaling the line. + yaxis: 'yaxis', + y: null, + xmin: null, + xmax: null, + xOffset: '6px', // number or string. Number interpreted as units, string as pixels. + xminOffset: null, + xmaxOffset: null, + // prop: dashPattern + // Array of line, space settings in pixels. + // Default is 8 pixel of line, 8 pixel of space. + // Note, limit to a 2 element array b/c of bug with higher order arrays. + dashPattern: [8,8] + }; + $.extend(true, this.options, options); + } + + + /** + * Class: VerticalLine + * A straight vertical line. + */ + function VerticalLine(options) { + this.type = 'verticalLine'; + this.options = { + // prop: name + // Optional name for this overlay object. + // Can be later used to retrieve the object by name. + name: null, + // prop: show + // true to show (draw), false to not draw. + show: true, + // prop: lineWidth + // Width of the line. + lineWidth: 2, + // prop: lineCap + // Type of ending placed on the line ['round', 'butt', 'square'] + lineCap: 'round', + // prop: color + // color of the line + color: '#666666', + // prop: shadow + // wether or not to draw a shadow on the line + shadow: true, + // prop: shadowAngle + // Shadow angle in degrees + shadowAngle: 45, + // prop: shadowOffset + // Shadow offset from line in pixels + shadowOffset: 1, + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + shadowDepth: 3, + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + shadowAlpha: '0.07', + // prop: xaxis + // X axis to use for positioning/scaling the line. + xaxis: 'xaxis', + // prop: yaxis + // Y axis to use for positioning/scaling the line. + yaxis: 'yaxis', + x: null, + ymin: null, + ymax: null, + yOffset: '6px', // number or string. Number interpreted as units, string as pixels. + yminOffset: null, + ymaxOffset: null + }; + $.extend(true, this.options, options); + } + + + /** + * Class: DashedVerticalLine + * A straight dashed vertical line. + */ + function DashedVerticalLine(options) { + this.type = 'dashedVerticalLine'; + this.options = { + // prop: name + // Optional name for this overlay object. + // Can be later used to retrieve the object by name. + name: null, + // prop: show + // true to show (draw), false to not draw. + show: true, + // prop: lineWidth + // Width of the line. + lineWidth: 2, + // prop: lineCap + // Type of ending placed on the line ['round', 'butt', 'square'] + lineCap: 'butt', + // prop: color + // color of the line + color: '#666666', + // prop: shadow + // wether or not to draw a shadow on the line + shadow: true, + // prop: shadowAngle + // Shadow angle in degrees + shadowAngle: 45, + // prop: shadowOffset + // Shadow offset from line in pixels + shadowOffset: 1, + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + shadowDepth: 3, + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + shadowAlpha: '0.07', + // prop: xaxis + // X axis to use for positioning/scaling the line. + xaxis: 'xaxis', + // prop: yaxis + // Y axis to use for positioning/scaling the line. + yaxis: 'yaxis', + x: null, + ymin: null, + ymax: null, + yOffset: '6px', // number or string. Number interpreted as units, string as pixels. + yminOffset: null, + ymaxOffset: null, + // prop: dashPattern + // Array of line, space settings in pixels. + // Default is 8 pixel of line, 8 pixel of space. + // Note, limit to a 2 element array b/c of bug with higher order arrays. + dashPattern: [8,8] + }; + $.extend(true, this.options, options); + } + + $.jqplot.CanvasOverlay.prototype.addLine = function(opts) { + var line = new Line(opts); + this.objects.push(line); + this.objectNames.push(line.options.name); + }; + + $.jqplot.CanvasOverlay.prototype.addHorizontalLine = function(opts) { + var line = new HorizontalLine(opts); + this.objects.push(line); + this.objectNames.push(line.options.name); + }; + + $.jqplot.CanvasOverlay.prototype.addDashedHorizontalLine = function(opts) { + var line = new DashedHorizontalLine(opts); + this.objects.push(line); + this.objectNames.push(line.options.name); + }; + + $.jqplot.CanvasOverlay.prototype.addVerticalLine = function(opts) { + var line = new VerticalLine(opts); + this.objects.push(line); + this.objectNames.push(line.options.name); + }; + + $.jqplot.CanvasOverlay.prototype.addDashedVerticalLine = function(opts) { + var line = new DashedVerticalLine(opts); + this.objects.push(line); + this.objectNames.push(line.options.name); + }; + + $.jqplot.CanvasOverlay.prototype.removeObject = function(idx) { + // check if integer, remove by index + if ($.type(idx) == 'number') { + this.objects.splice(idx, 1); + this.objectNames.splice(idx, 1); + } + // if string, remove by name + else { + var id = $.inArray(idx, this.objectNames); + if (id != -1) { + this.objects.splice(id, 1); + this.objectNames.splice(id, 1); + } + } + }; + + $.jqplot.CanvasOverlay.prototype.getObject = function(idx) { + // check if integer, remove by index + if ($.type(idx) == 'number') { + return this.objects[idx]; + } + // if string, remove by name + else { + var id = $.inArray(idx, this.objectNames); + if (id != -1) { + return this.objects[id]; + } + } + }; + + // Set get as alias for getObject. + $.jqplot.CanvasOverlay.prototype.get = $.jqplot.CanvasOverlay.prototype.getObject; + + $.jqplot.CanvasOverlay.prototype.clear = function(plot) { + this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight()); + }; + + $.jqplot.CanvasOverlay.prototype.draw = function(plot) { + var obj, + objs = this.objects, + mr = this.markerRenderer, + start, + stop; + if (this.options.show) { + this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight()); + for (var k=0; k<objs.length; k++) { + obj = objs[k]; + var opts = $.extend(true, {}, obj.options); + if (obj.options.show) { + // style and shadow properties should be set before + // every draw of marker renderer. + mr.shadow = obj.options.shadow; + switch (obj.type) { + case 'line': + // style and shadow properties should be set before + // every draw of marker renderer. + mr.style = 'line'; + opts.closePath = false; + start = [plot.axes[obj.options.xaxis].series_u2p(obj.options.start[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.start[1])]; + stop = [plot.axes[obj.options.xaxis].series_u2p(obj.options.stop[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.stop[1])]; + mr.draw(start, stop, this.canvas._ctx, opts); + break; + case 'horizontalLine': + + // style and shadow properties should be set before + // every draw of marker renderer. + if (obj.options.y != null) { + mr.style = 'line'; + opts.closePath = false; + var xaxis = plot.axes[obj.options.xaxis], + xstart, + xstop, + y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y), + xminoff = obj.options.xminOffset || obj.options.xOffset, + xmaxoff = obj.options.xmaxOffset || obj.options.xOffset; + if (obj.options.xmin != null) { + xstart = xaxis.series_u2p(obj.options.xmin); + } + else if (xminoff != null) { + if ($.type(xminoff) == "number") { + xstart = xaxis.series_u2p(xaxis.min + xminoff); + } + else if ($.type(xminoff) == "string") { + xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff); + } + } + if (obj.options.xmax != null) { + xstop = xaxis.series_u2p(obj.options.xmax); + } + else if (xmaxoff != null) { + if ($.type(xmaxoff) == "number") { + xstop = xaxis.series_u2p(xaxis.max - xmaxoff); + } + else if ($.type(xmaxoff) == "string") { + xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff); + } + } + if (xstop != null && xstart != null) { + mr.draw([xstart, y], [xstop, y], this.canvas._ctx, opts); + } + } + break; + + case 'dashedHorizontalLine': + + var dashPat = obj.options.dashPattern; + var dashPatLen = 0; + for (var i=0; i<dashPat.length; i++) { + dashPatLen += dashPat[i]; + } + + // style and shadow properties should be set before + // every draw of marker renderer. + if (obj.options.y != null) { + mr.style = 'line'; + opts.closePath = false; + var xaxis = plot.axes[obj.options.xaxis], + xstart, + xstop, + y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y), + xminoff = obj.options.xminOffset || obj.options.xOffset, + xmaxoff = obj.options.xmaxOffset || obj.options.xOffset; + if (obj.options.xmin != null) { + xstart = xaxis.series_u2p(obj.options.xmin); + } + else if (xminoff != null) { + if ($.type(xminoff) == "number") { + xstart = xaxis.series_u2p(xaxis.min + xminoff); + } + else if ($.type(xminoff) == "string") { + xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff); + } + } + if (obj.options.xmax != null) { + xstop = xaxis.series_u2p(obj.options.xmax); + } + else if (xmaxoff != null) { + if ($.type(xmaxoff) == "number") { + xstop = xaxis.series_u2p(xaxis.max - xmaxoff); + } + else if ($.type(xmaxoff) == "string") { + xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff); + } + } + if (xstop != null && xstart != null) { + var numDash = Math.ceil((xstop - xstart)/dashPatLen); + var b=xstart, e; + for (var i=0; i<numDash; i++) { + for (var j=0; j<dashPat.length; j+=2) { + e = b+dashPat[j]; + mr.draw([b, y], [e, y], this.canvas._ctx, opts); + b += dashPat[j]; + if (j < dashPat.length-1) { + b += dashPat[j+1]; + } + } + } + } + } + break; + + case 'verticalLine': + + // style and shadow properties should be set before + // every draw of marker renderer. + if (obj.options.x != null) { + mr.style = 'line'; + opts.closePath = false; + var yaxis = plot.axes[obj.options.yaxis], + ystart, + ystop, + x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x), + yminoff = obj.options.yminOffset || obj.options.yOffset, + ymaxoff = obj.options.ymaxOffset || obj.options.yOffset; + if (obj.options.ymin != null) { + ystart = yaxis.series_u2p(obj.options.ymin); + } + else if (yminoff != null) { + if ($.type(yminoff) == "number") { + ystart = yaxis.series_u2p(yaxis.min - yminoff); + } + else if ($.type(yminoff) == "string") { + ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff); + } + } + if (obj.options.ymax != null) { + ystop = yaxis.series_u2p(obj.options.ymax); + } + else if (ymaxoff != null) { + if ($.type(ymaxoff) == "number") { + ystop = yaxis.series_u2p(yaxis.max + ymaxoff); + } + else if ($.type(ymaxoff) == "string") { + ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff); + } + } + if (ystop != null && ystart != null) { + mr.draw([x, ystart], [x, ystop], this.canvas._ctx, opts); + } + } + break; + + case 'dashedVerticalLine': + + var dashPat = obj.options.dashPattern; + var dashPatLen = 0; + for (var i=0; i<dashPat.length; i++) { + dashPatLen += dashPat[i]; + } + + // style and shadow properties should be set before + // every draw of marker renderer. + if (obj.options.x != null) { + mr.style = 'line'; + opts.closePath = false; + var yaxis = plot.axes[obj.options.yaxis], + ystart, + ystop, + x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x), + yminoff = obj.options.yminOffset || obj.options.yOffset, + ymaxoff = obj.options.ymaxOffset || obj.options.yOffset; + if (obj.options.ymin != null) { + ystart = yaxis.series_u2p(obj.options.ymin); + } + else if (yminoff != null) { + if ($.type(yminoff) == "number") { + ystart = yaxis.series_u2p(yaxis.min - yminoff); + } + else if ($.type(yminoff) == "string") { + ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff); + } + } + if (obj.options.ymax != null) { + ystop = yaxis.series_u2p(obj.options.ymax); + } + else if (ymaxoff != null) { + if ($.type(ymaxoff) == "number") { + ystop = yaxis.series_u2p(yaxis.max + ymaxoff); + } + else if ($.type(ymaxoff) == "string") { + ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff); + } + } + + + if (ystop != null && ystart != null) { + var numDash = Math.ceil((ystart - ystop)/dashPatLen); + var firstDashAdjust = ((numDash * dashPatLen) - (ystart - ystop))/2.0; + var b=ystart, e, bs, es; + for (var i=0; i<numDash; i++) { + for (var j=0; j<dashPat.length; j+=2) { + e = b - dashPat[j]; + if (e < ystop) { + e = ystop; + } + if (b < ystop) { + b = ystop; + } + // es = e; + // if (i == 0) { + // es += firstDashAdjust; + // } + mr.draw([x, b], [x, e], this.canvas._ctx, opts); + b -= dashPat[j]; + if (j < dashPat.length-1) { + b -= dashPat[j+1]; + } + } + } + } + } + break; + + default: + break; + } + } + } + } + }; + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + $.jqplot.CanvasOverlay.postPlotDraw = function() { + // Memory Leaks patch + if (this.plugins.canvasOverlay && this.plugins.canvasOverlay.highlightCanvas) { + this.plugins.canvasOverlay.highlightCanvas.resetCanvas(); + this.plugins.canvasOverlay.highlightCanvas = null; + } + this.plugins.canvasOverlay.canvas = new $.jqplot.GenericCanvas(); + + this.eventCanvas._elem.before(this.plugins.canvasOverlay.canvas.createElement(this._gridPadding, 'jqplot-overlayCanvas-canvas', this._plotDimensions, this)); + this.plugins.canvasOverlay.canvas.setContext(); + if (!this.plugins.canvasOverlay.deferDraw) { + this.plugins.canvasOverlay.draw(this); + } + }; + + $.jqplot.postInitHooks.push($.jqplot.CanvasOverlay.postPlotInit); + $.jqplot.postDrawHooks.push($.jqplot.CanvasOverlay.postPlotDraw); + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasOverlay.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasOverlay.min.js new file mode 100644 index 0000000000..183352bec1 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasOverlay.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(d){d.jqplot.CanvasOverlay=function(j){var g=j||{};this.options={show:d.jqplot.config.enablePlugins,deferDraw:false};this.objects=[];this.objectNames=[];this.canvas=null;this.markerRenderer=new d.jqplot.MarkerRenderer({style:"line"});this.markerRenderer.init();if(g.objects){var l=g.objects,k;for(var h=0;h<l.length;h++){k=l[h];for(var m in k){switch(m){case"line":this.addLine(k[m]);break;case"horizontalLine":this.addHorizontalLine(k[m]);break;case"dashedHorizontalLine":this.addDashedHorizontalLine(k[m]);break;case"verticalLine":this.addVerticalLine(k[m]);break;case"dashedVerticalLine":this.addDashedVerticalLine(k[m]);break;default:break}}}}d.extend(true,this.options,g)};d.jqplot.CanvasOverlay.postPlotInit=function(j,i,h){var g=h||{};this.plugins.canvasOverlay=new d.jqplot.CanvasOverlay(g.canvasOverlay)};function e(g){this.type="line";this.options={name:null,show:true,lineWidth:2,lineCap:"round",color:"#666666",shadow:true,shadowAngle:45,shadowOffset:1,shadowDepth:3,shadowAlpha:"0.07",xaxis:"xaxis",yaxis:"yaxis",start:[],stop:[]};d.extend(true,this.options,g)}function b(g){this.type="horizontalLine";this.options={name:null,show:true,lineWidth:2,lineCap:"round",color:"#666666",shadow:true,shadowAngle:45,shadowOffset:1,shadowDepth:3,shadowAlpha:"0.07",xaxis:"xaxis",yaxis:"yaxis",y:null,xmin:null,xmax:null,xOffset:"6px",xminOffset:null,xmaxOffset:null};d.extend(true,this.options,g)}function f(g){this.type="dashedHorizontalLine";this.options={name:null,show:true,lineWidth:2,lineCap:"butt",color:"#666666",shadow:true,shadowAngle:45,shadowOffset:1,shadowDepth:3,shadowAlpha:"0.07",xaxis:"xaxis",yaxis:"yaxis",y:null,xmin:null,xmax:null,xOffset:"6px",xminOffset:null,xmaxOffset:null,dashPattern:[8,8]};d.extend(true,this.options,g)}function a(g){this.type="verticalLine";this.options={name:null,show:true,lineWidth:2,lineCap:"round",color:"#666666",shadow:true,shadowAngle:45,shadowOffset:1,shadowDepth:3,shadowAlpha:"0.07",xaxis:"xaxis",yaxis:"yaxis",x:null,ymin:null,ymax:null,yOffset:"6px",yminOffset:null,ymaxOffset:null};d.extend(true,this.options,g)}function c(g){this.type="dashedVerticalLine";this.options={name:null,show:true,lineWidth:2,lineCap:"butt",color:"#666666",shadow:true,shadowAngle:45,shadowOffset:1,shadowDepth:3,shadowAlpha:"0.07",xaxis:"xaxis",yaxis:"yaxis",x:null,ymin:null,ymax:null,yOffset:"6px",yminOffset:null,ymaxOffset:null,dashPattern:[8,8]};d.extend(true,this.options,g)}d.jqplot.CanvasOverlay.prototype.addLine=function(h){var g=new e(h);this.objects.push(g);this.objectNames.push(g.options.name)};d.jqplot.CanvasOverlay.prototype.addHorizontalLine=function(h){var g=new b(h);this.objects.push(g);this.objectNames.push(g.options.name)};d.jqplot.CanvasOverlay.prototype.addDashedHorizontalLine=function(h){var g=new f(h);this.objects.push(g);this.objectNames.push(g.options.name)};d.jqplot.CanvasOverlay.prototype.addVerticalLine=function(h){var g=new a(h);this.objects.push(g);this.objectNames.push(g.options.name)};d.jqplot.CanvasOverlay.prototype.addDashedVerticalLine=function(h){var g=new c(h);this.objects.push(g);this.objectNames.push(g.options.name)};d.jqplot.CanvasOverlay.prototype.removeObject=function(g){if(d.type(g)=="number"){this.objects.splice(g,1);this.objectNames.splice(g,1)}else{var h=d.inArray(g,this.objectNames);if(h!=-1){this.objects.splice(h,1);this.objectNames.splice(h,1)}}};d.jqplot.CanvasOverlay.prototype.getObject=function(g){if(d.type(g)=="number"){return this.objects[g]}else{var h=d.inArray(g,this.objectNames);if(h!=-1){return this.objects[h]}}};d.jqplot.CanvasOverlay.prototype.get=d.jqplot.CanvasOverlay.prototype.getObject;d.jqplot.CanvasOverlay.prototype.clear=function(g){this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(),this.canvas.getHeight())};d.jqplot.CanvasOverlay.prototype.draw=function(G){var u,r=this.objects,B=this.markerRenderer,o,C;if(this.options.show){this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(),this.canvas.getHeight());for(var D=0;D<r.length;D++){u=r[D];var v=d.extend(true,{},u.options);if(u.options.show){B.shadow=u.options.shadow;switch(u.type){case"line":B.style="line";v.closePath=false;o=[G.axes[u.options.xaxis].series_u2p(u.options.start[0]),G.axes[u.options.yaxis].series_u2p(u.options.start[1])];C=[G.axes[u.options.xaxis].series_u2p(u.options.stop[0]),G.axes[u.options.yaxis].series_u2p(u.options.stop[1])];B.draw(o,C,this.canvas._ctx,v);break;case"horizontalLine":if(u.options.y!=null){B.style="line";v.closePath=false;var l=G.axes[u.options.xaxis],O,H,s=G.axes[u.options.yaxis].series_u2p(u.options.y),E=u.options.xminOffset||u.options.xOffset,p=u.options.xmaxOffset||u.options.xOffset;if(u.options.xmin!=null){O=l.series_u2p(u.options.xmin)}else{if(E!=null){if(d.type(E)=="number"){O=l.series_u2p(l.min+E)}else{if(d.type(E)=="string"){O=l.series_u2p(l.min)+parseFloat(E)}}}}if(u.options.xmax!=null){H=l.series_u2p(u.options.xmax)}else{if(p!=null){if(d.type(p)=="number"){H=l.series_u2p(l.max-p)}else{if(d.type(p)=="string"){H=l.series_u2p(l.max)-parseFloat(p)}}}}if(H!=null&&O!=null){B.draw([O,s],[H,s],this.canvas._ctx,v)}}break;case"dashedHorizontalLine":var h=u.options.dashPattern;var A=0;for(var I=0;I<h.length;I++){A+=h[I]}if(u.options.y!=null){B.style="line";v.closePath=false;var l=G.axes[u.options.xaxis],O,H,s=G.axes[u.options.yaxis].series_u2p(u.options.y),E=u.options.xminOffset||u.options.xOffset,p=u.options.xmaxOffset||u.options.xOffset;if(u.options.xmin!=null){O=l.series_u2p(u.options.xmin)}else{if(E!=null){if(d.type(E)=="number"){O=l.series_u2p(l.min+E)}else{if(d.type(E)=="string"){O=l.series_u2p(l.min)+parseFloat(E)}}}}if(u.options.xmax!=null){H=l.series_u2p(u.options.xmax)}else{if(p!=null){if(d.type(p)=="number"){H=l.series_u2p(l.max-p)}else{if(d.type(p)=="string"){H=l.series_u2p(l.max)-parseFloat(p)}}}}if(H!=null&&O!=null){var n=Math.ceil((H-O)/A);var M=O,K;for(var I=0;I<n;I++){for(var F=0;F<h.length;F+=2){K=M+h[F];B.draw([M,s],[K,s],this.canvas._ctx,v);M+=h[F];if(F<h.length-1){M+=h[F+1]}}}}}break;case"verticalLine":if(u.options.x!=null){B.style="line";v.closePath=false;var J=G.axes[u.options.yaxis],g,q,t=G.axes[u.options.xaxis].series_u2p(u.options.x),z=u.options.yminOffset||u.options.yOffset,m=u.options.ymaxOffset||u.options.yOffset;if(u.options.ymin!=null){g=J.series_u2p(u.options.ymin)}else{if(z!=null){if(d.type(z)=="number"){g=J.series_u2p(J.min-z)}else{if(d.type(z)=="string"){g=J.series_u2p(J.min)-parseFloat(z)}}}}if(u.options.ymax!=null){q=J.series_u2p(u.options.ymax)}else{if(m!=null){if(d.type(m)=="number"){q=J.series_u2p(J.max+m)}else{if(d.type(m)=="string"){q=J.series_u2p(J.max)+parseFloat(m)}}}}if(q!=null&&g!=null){B.draw([t,g],[t,q],this.canvas._ctx,v)}}break;case"dashedVerticalLine":var h=u.options.dashPattern;var A=0;for(var I=0;I<h.length;I++){A+=h[I]}if(u.options.x!=null){B.style="line";v.closePath=false;var J=G.axes[u.options.yaxis],g,q,t=G.axes[u.options.xaxis].series_u2p(u.options.x),z=u.options.yminOffset||u.options.yOffset,m=u.options.ymaxOffset||u.options.yOffset;if(u.options.ymin!=null){g=J.series_u2p(u.options.ymin)}else{if(z!=null){if(d.type(z)=="number"){g=J.series_u2p(J.min-z)}else{if(d.type(z)=="string"){g=J.series_u2p(J.min)-parseFloat(z)}}}}if(u.options.ymax!=null){q=J.series_u2p(u.options.ymax)}else{if(m!=null){if(d.type(m)=="number"){q=J.series_u2p(J.max+m)}else{if(d.type(m)=="string"){q=J.series_u2p(J.max)+parseFloat(m)}}}}if(q!=null&&g!=null){var n=Math.ceil((g-q)/A);var w=((n*A)-(g-q))/2;var M=g,K,L,N;for(var I=0;I<n;I++){for(var F=0;F<h.length;F+=2){K=M-h[F];if(K<q){K=q}if(M<q){M=q}B.draw([t,M],[t,K],this.canvas._ctx,v);M-=h[F];if(F<h.length-1){M-=h[F+1]}}}}}break;default:break}}}}};d.jqplot.CanvasOverlay.postPlotDraw=function(){if(this.plugins.canvasOverlay&&this.plugins.canvasOverlay.highlightCanvas){this.plugins.canvasOverlay.highlightCanvas.resetCanvas();this.plugins.canvasOverlay.highlightCanvas=null}this.plugins.canvasOverlay.canvas=new d.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.canvasOverlay.canvas.createElement(this._gridPadding,"jqplot-overlayCanvas-canvas",this._plotDimensions,this));this.plugins.canvasOverlay.canvas.setContext();if(!this.plugins.canvasOverlay.deferDraw){this.plugins.canvasOverlay.draw(this)}};d.jqplot.postInitHooks.push(d.jqplot.CanvasOverlay.postPlotInit);d.jqplot.postDrawHooks.push(d.jqplot.CanvasOverlay.postPlotDraw)})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasTextRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasTextRenderer.js new file mode 100644 index 0000000000..c6c520bec5 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasTextRenderer.js @@ -0,0 +1,420 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + // This code is a modified version of the canvastext.js code, copyright below: + // + // This code is released to the public domain by Jim Studt, 2007. + // He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/ + // + $.jqplot.CanvasTextRenderer = function(options){ + this.fontStyle = 'normal'; // normal, italic, oblique [not implemented] + this.fontVariant = 'normal'; // normal, small caps [not implemented] + this.fontWeight = 'normal'; // normal, bold, bolder, lighter, 100 - 900 + this.fontSize = '10px'; + this.fontFamily = 'sans-serif'; + this.fontStretch = 1.0; + this.fillStyle = '#666666'; + this.angle = 0; + this.textAlign = 'start'; + this.textBaseline = 'alphabetic'; + this.text; + this.width; + this.height; + this.pt2px = 1.28; + + $.extend(true, this, options); + this.normalizedFontSize = this.normalizeFontSize(this.fontSize); + this.setHeight(); + }; + + $.jqplot.CanvasTextRenderer.prototype.init = function(options) { + $.extend(true, this, options); + this.normalizedFontSize = this.normalizeFontSize(this.fontSize); + this.setHeight(); + }; + + // convert css spec into point size + // returns float + $.jqplot.CanvasTextRenderer.prototype.normalizeFontSize = function(sz) { + sz = String(sz); + var n = parseFloat(sz); + if (sz.indexOf('px') > -1) { + return n/this.pt2px; + } + else if (sz.indexOf('pt') > -1) { + return n; + } + else if (sz.indexOf('em') > -1) { + return n*12; + } + else if (sz.indexOf('%') > -1) { + return n*12/100; + } + // default to pixels; + else { + return n/this.pt2px; + } + }; + + + $.jqplot.CanvasTextRenderer.prototype.fontWeight2Float = function(w) { + // w = normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 + // return values adjusted for Hershey font. + if (Number(w)) { + return w/400; + } + else { + switch (w) { + case 'normal': + return 1; + break; + case 'bold': + return 1.75; + break; + case 'bolder': + return 2.25; + break; + case 'lighter': + return 0.75; + break; + default: + return 1; + break; + } + } + }; + + $.jqplot.CanvasTextRenderer.prototype.getText = function() { + return this.text; + }; + + $.jqplot.CanvasTextRenderer.prototype.setText = function(t, ctx) { + this.text = t; + this.setWidth(ctx); + return this; + }; + + $.jqplot.CanvasTextRenderer.prototype.getWidth = function(ctx) { + return this.width; + }; + + $.jqplot.CanvasTextRenderer.prototype.setWidth = function(ctx, w) { + if (!w) { + this.width = this.measure(ctx, this.text); + } + else { + this.width = w; + } + return this; + }; + + // return height in pixels. + $.jqplot.CanvasTextRenderer.prototype.getHeight = function(ctx) { + return this.height; + }; + + // w - height in pt + // set heigh in px + $.jqplot.CanvasTextRenderer.prototype.setHeight = function(w) { + if (!w) { + //height = this.fontSize /0.75; + this.height = this.normalizedFontSize * this.pt2px; + } + else { + this.height = w; + } + return this; + }; + + $.jqplot.CanvasTextRenderer.prototype.letter = function (ch) + { + return this.letters[ch]; + }; + + $.jqplot.CanvasTextRenderer.prototype.ascent = function() + { + return this.normalizedFontSize; + }; + + $.jqplot.CanvasTextRenderer.prototype.descent = function() + { + return 7.0*this.normalizedFontSize/25.0; + }; + + $.jqplot.CanvasTextRenderer.prototype.measure = function(ctx, str) + { + var total = 0; + var len = str.length; + + for (var i = 0; i < len; i++) { + var c = this.letter(str.charAt(i)); + if (c) { + total += c.width * this.normalizedFontSize / 25.0 * this.fontStretch; + } + } + return total; + }; + + $.jqplot.CanvasTextRenderer.prototype.draw = function(ctx,str) + { + var x = 0; + // leave room at bottom for descenders. + var y = this.height*0.72; + var total = 0; + var len = str.length; + var mag = this.normalizedFontSize / 25.0; + + ctx.save(); + var tx, ty; + + // 1st quadrant + if ((-Math.PI/2 <= this.angle && this.angle <= 0) || (Math.PI*3/2 <= this.angle && this.angle <= Math.PI*2)) { + tx = 0; + ty = -Math.sin(this.angle) * this.width; + } + // 4th quadrant + else if ((0 < this.angle && this.angle <= Math.PI/2) || (-Math.PI*2 <= this.angle && this.angle <= -Math.PI*3/2)) { + tx = Math.sin(this.angle) * this.height; + ty = 0; + } + // 2nd quadrant + else if ((-Math.PI < this.angle && this.angle < -Math.PI/2) || (Math.PI <= this.angle && this.angle <= Math.PI*3/2)) { + tx = -Math.cos(this.angle) * this.width; + ty = -Math.sin(this.angle) * this.width - Math.cos(this.angle) * this.height; + } + // 3rd quadrant + else if ((-Math.PI*3/2 < this.angle && this.angle < Math.PI) || (Math.PI/2 < this.angle && this.angle < Math.PI)) { + tx = Math.sin(this.angle) * this.height - Math.cos(this.angle)*this.width; + ty = -Math.cos(this.angle) * this.height; + } + + ctx.strokeStyle = this.fillStyle; + ctx.fillStyle = this.fillStyle; + ctx.translate(tx, ty); + ctx.rotate(this.angle); + ctx.lineCap = "round"; + // multiplier was 2.0 + var fact = (this.normalizedFontSize > 30) ? 2.0 : 2 + (30 - this.normalizedFontSize)/20; + ctx.lineWidth = fact * mag * this.fontWeight2Float(this.fontWeight); + + for ( var i = 0; i < len; i++) { + var c = this.letter( str.charAt(i)); + if ( !c) { + continue; + } + + ctx.beginPath(); + + var penUp = 1; + var needStroke = 0; + for ( var j = 0; j < c.points.length; j++) { + var a = c.points[j]; + if ( a[0] == -1 && a[1] == -1) { + penUp = 1; + continue; + } + if ( penUp) { + ctx.moveTo( x + a[0]*mag*this.fontStretch, y - a[1]*mag); + penUp = false; + } else { + ctx.lineTo( x + a[0]*mag*this.fontStretch, y - a[1]*mag); + } + } + ctx.stroke(); + x += c.width*mag*this.fontStretch; + } + ctx.restore(); + return total; + }; + + $.jqplot.CanvasTextRenderer.prototype.letters = { + ' ': { width: 16, points: [] }, + '!': { width: 10, points: [[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] }, + '"': { width: 16, points: [[4,21],[4,14],[-1,-1],[12,21],[12,14]] }, + '#': { width: 21, points: [[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]] }, + '$': { width: 20, points: [[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] }, + '%': { width: 24, points: [[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]] }, + '&': { width: 26, points: [[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]] }, + '\'': { width: 10, points: [[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]] }, + '(': { width: 14, points: [[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]] }, + ')': { width: 14, points: [[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]] }, + '*': { width: 16, points: [[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]] }, + '+': { width: 26, points: [[13,18],[13,0],[-1,-1],[4,9],[22,9]] }, + ',': { width: 10, points: [[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] }, + '-': { width: 18, points: [[6,9],[12,9]] }, + '.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] }, + '/': { width: 22, points: [[20,25],[2,-7]] }, + '0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] }, + '1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] }, + '2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] }, + '3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] }, + '4': { width: 20, points: [[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]] }, + '5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] }, + '6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] }, + '7': { width: 20, points: [[17,21],[7,0],[-1,-1],[3,21],[17,21]] }, + '8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] }, + '9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] }, + ':': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] }, + ';': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] }, + '<': { width: 24, points: [[20,18],[4,9],[20,0]] }, + '=': { width: 26, points: [[4,12],[22,12],[-1,-1],[4,6],[22,6]] }, + '>': { width: 24, points: [[4,18],[20,9],[4,0]] }, + '?': { width: 18, points: [[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]] }, + '@': { width: 27, points: [[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]] }, + 'A': { width: 18, points: [[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]] }, + 'B': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]] }, + 'C': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]] }, + 'D': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]] }, + 'E': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]] }, + 'F': { width: 18, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]] }, + 'G': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]] }, + 'H': { width: 22, points: [[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]] }, + 'I': { width: 8, points: [[4,21],[4,0]] }, + 'J': { width: 16, points: [[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]] }, + 'K': { width: 21, points: [[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]] }, + 'L': { width: 17, points: [[4,21],[4,0],[-1,-1],[4,0],[16,0]] }, + 'M': { width: 24, points: [[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]] }, + 'N': { width: 22, points: [[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]] }, + 'O': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]] }, + 'P': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]] }, + 'Q': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]] }, + 'R': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]] }, + 'S': { width: 20, points: [[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] }, + 'T': { width: 16, points: [[8,21],[8,0],[-1,-1],[1,21],[15,21]] }, + 'U': { width: 22, points: [[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]] }, + 'V': { width: 18, points: [[1,21],[9,0],[-1,-1],[17,21],[9,0]] }, + 'W': { width: 24, points: [[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]] }, + 'X': { width: 20, points: [[3,21],[17,0],[-1,-1],[17,21],[3,0]] }, + 'Y': { width: 18, points: [[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]] }, + 'Z': { width: 20, points: [[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]] }, + '[': { width: 14, points: [[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]] }, + '\\': { width: 14, points: [[0,21],[14,-3]] }, + ']': { width: 14, points: [[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]] }, + '^': { width: 16, points: [[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]] }, + '_': { width: 16, points: [[0,-2],[16,-2]] }, + '`': { width: 10, points: [[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]] }, + 'a': { width: 19, points: [[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'b': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] }, + 'c': { width: 18, points: [[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'd': { width: 19, points: [[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'e': { width: 18, points: [[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'f': { width: 12, points: [[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]] }, + 'g': { width: 19, points: [[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'h': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] }, + 'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]] }, + 'j': { width: 10, points: [[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]] }, + 'k': { width: 17, points: [[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]] }, + 'l': { width: 8, points: [[4,21],[4,0]] }, + 'm': { width: 30, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]] }, + 'n': { width: 19, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] }, + 'o': { width: 19, points: [[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]] }, + 'p': { width: 19, points: [[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] }, + 'q': { width: 19, points: [[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'r': { width: 13, points: [[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]] }, + 's': { width: 17, points: [[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]] }, + 't': { width: 12, points: [[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]] }, + 'u': { width: 19, points: [[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]] }, + 'v': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0]] }, + 'w': { width: 22, points: [[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]] }, + 'x': { width: 17, points: [[3,14],[14,0],[-1,-1],[14,14],[3,0]] }, + 'y': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]] }, + 'z': { width: 17, points: [[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]] }, + '{': { width: 14, points: [[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]] }, + '|': { width: 8, points: [[4,25],[4,-7]] }, + '}': { width: 14, points: [[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]] }, + '~': { width: 24, points: [[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]] } + }; + + $.jqplot.CanvasFontRenderer = function(options) { + options = options || {}; + if (!options.pt2px) { + options.pt2px = 1.5; + } + $.jqplot.CanvasTextRenderer.call(this, options); + }; + + $.jqplot.CanvasFontRenderer.prototype = new $.jqplot.CanvasTextRenderer({}); + $.jqplot.CanvasFontRenderer.prototype.constructor = $.jqplot.CanvasFontRenderer; + + $.jqplot.CanvasFontRenderer.prototype.measure = function(ctx, str) + { + // var fstyle = this.fontStyle+' '+this.fontVariant+' '+this.fontWeight+' '+this.fontSize+' '+this.fontFamily; + var fstyle = this.fontSize+' '+this.fontFamily; + ctx.save(); + ctx.font = fstyle; + var w = ctx.measureText(str).width; + ctx.restore(); + return w; + }; + + $.jqplot.CanvasFontRenderer.prototype.draw = function(ctx, str) + { + var x = 0; + // leave room at bottom for descenders. + var y = this.height*0.72; + //var y = 12; + + ctx.save(); + var tx, ty; + + // 1st quadrant + if ((-Math.PI/2 <= this.angle && this.angle <= 0) || (Math.PI*3/2 <= this.angle && this.angle <= Math.PI*2)) { + tx = 0; + ty = -Math.sin(this.angle) * this.width; + } + // 4th quadrant + else if ((0 < this.angle && this.angle <= Math.PI/2) || (-Math.PI*2 <= this.angle && this.angle <= -Math.PI*3/2)) { + tx = Math.sin(this.angle) * this.height; + ty = 0; + } + // 2nd quadrant + else if ((-Math.PI < this.angle && this.angle < -Math.PI/2) || (Math.PI <= this.angle && this.angle <= Math.PI*3/2)) { + tx = -Math.cos(this.angle) * this.width; + ty = -Math.sin(this.angle) * this.width - Math.cos(this.angle) * this.height; + } + // 3rd quadrant + else if ((-Math.PI*3/2 < this.angle && this.angle < Math.PI) || (Math.PI/2 < this.angle && this.angle < Math.PI)) { + tx = Math.sin(this.angle) * this.height - Math.cos(this.angle)*this.width; + ty = -Math.cos(this.angle) * this.height; + } + ctx.strokeStyle = this.fillStyle; + ctx.fillStyle = this.fillStyle; + // var fstyle = this.fontStyle+' '+this.fontVariant+' '+this.fontWeight+' '+this.fontSize+' '+this.fontFamily; + var fstyle = this.fontSize+' '+this.fontFamily; + ctx.font = fstyle; + ctx.translate(tx, ty); + ctx.rotate(this.angle); + ctx.fillText(str, x, y); + // ctx.strokeText(str, x, y); + + ctx.restore(); + }; + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasTextRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasTextRenderer.min.js new file mode 100644 index 0000000000..ad34469a1e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.canvasTextRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.CanvasTextRenderer=function(b){this.fontStyle="normal";this.fontVariant="normal";this.fontWeight="normal";this.fontSize="10px";this.fontFamily="sans-serif";this.fontStretch=1;this.fillStyle="#666666";this.angle=0;this.textAlign="start";this.textBaseline="alphabetic";this.text;this.width;this.height;this.pt2px=1.28;a.extend(true,this,b);this.normalizedFontSize=this.normalizeFontSize(this.fontSize);this.setHeight()};a.jqplot.CanvasTextRenderer.prototype.init=function(b){a.extend(true,this,b);this.normalizedFontSize=this.normalizeFontSize(this.fontSize);this.setHeight()};a.jqplot.CanvasTextRenderer.prototype.normalizeFontSize=function(b){b=String(b);var c=parseFloat(b);if(b.indexOf("px")>-1){return c/this.pt2px}else{if(b.indexOf("pt")>-1){return c}else{if(b.indexOf("em")>-1){return c*12}else{if(b.indexOf("%")>-1){return c*12/100}else{return c/this.pt2px}}}}};a.jqplot.CanvasTextRenderer.prototype.fontWeight2Float=function(b){if(Number(b)){return b/400}else{switch(b){case"normal":return 1;break;case"bold":return 1.75;break;case"bolder":return 2.25;break;case"lighter":return 0.75;break;default:return 1;break}}};a.jqplot.CanvasTextRenderer.prototype.getText=function(){return this.text};a.jqplot.CanvasTextRenderer.prototype.setText=function(c,b){this.text=c;this.setWidth(b);return this};a.jqplot.CanvasTextRenderer.prototype.getWidth=function(b){return this.width};a.jqplot.CanvasTextRenderer.prototype.setWidth=function(c,b){if(!b){this.width=this.measure(c,this.text)}else{this.width=b}return this};a.jqplot.CanvasTextRenderer.prototype.getHeight=function(b){return this.height};a.jqplot.CanvasTextRenderer.prototype.setHeight=function(b){if(!b){this.height=this.normalizedFontSize*this.pt2px}else{this.height=b}return this};a.jqplot.CanvasTextRenderer.prototype.letter=function(b){return this.letters[b]};a.jqplot.CanvasTextRenderer.prototype.ascent=function(){return this.normalizedFontSize};a.jqplot.CanvasTextRenderer.prototype.descent=function(){return 7*this.normalizedFontSize/25};a.jqplot.CanvasTextRenderer.prototype.measure=function(d,g){var f=0;var b=g.length;for(var e=0;e<b;e++){var h=this.letter(g.charAt(e));if(h){f+=h.width*this.normalizedFontSize/25*this.fontStretch}}return f};a.jqplot.CanvasTextRenderer.prototype.draw=function(s,n){var r=0;var o=this.height*0.72;var p=0;var l=n.length;var k=this.normalizedFontSize/25;s.save();var h,f;if((-Math.PI/2<=this.angle&&this.angle<=0)||(Math.PI*3/2<=this.angle&&this.angle<=Math.PI*2)){h=0;f=-Math.sin(this.angle)*this.width}else{if((0<this.angle&&this.angle<=Math.PI/2)||(-Math.PI*2<=this.angle&&this.angle<=-Math.PI*3/2)){h=Math.sin(this.angle)*this.height;f=0}else{if((-Math.PI<this.angle&&this.angle<-Math.PI/2)||(Math.PI<=this.angle&&this.angle<=Math.PI*3/2)){h=-Math.cos(this.angle)*this.width;f=-Math.sin(this.angle)*this.width-Math.cos(this.angle)*this.height}else{if((-Math.PI*3/2<this.angle&&this.angle<Math.PI)||(Math.PI/2<this.angle&&this.angle<Math.PI)){h=Math.sin(this.angle)*this.height-Math.cos(this.angle)*this.width;f=-Math.cos(this.angle)*this.height}}}}s.strokeStyle=this.fillStyle;s.fillStyle=this.fillStyle;s.translate(h,f);s.rotate(this.angle);s.lineCap="round";var t=(this.normalizedFontSize>30)?2:2+(30-this.normalizedFontSize)/20;s.lineWidth=t*k*this.fontWeight2Float(this.fontWeight);for(var g=0;g<l;g++){var m=this.letter(n.charAt(g));if(!m){continue}s.beginPath();var e=1;var b=0;for(var d=0;d<m.points.length;d++){var q=m.points[d];if(q[0]==-1&&q[1]==-1){e=1;continue}if(e){s.moveTo(r+q[0]*k*this.fontStretch,o-q[1]*k);e=false}else{s.lineTo(r+q[0]*k*this.fontStretch,o-q[1]*k)}}s.stroke();r+=m.width*k*this.fontStretch}s.restore();return p};a.jqplot.CanvasTextRenderer.prototype.letters={" ":{width:16,points:[]},"!":{width:10,points:[[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]]},'"':{width:16,points:[[4,21],[4,14],[-1,-1],[12,21],[12,14]]},"#":{width:21,points:[[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]]},"$":{width:20,points:[[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},"%":{width:24,points:[[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]]},"&":{width:26,points:[[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]]},"'":{width:10,points:[[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]]},"(":{width:14,points:[[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]]},")":{width:14,points:[[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]]},"*":{width:16,points:[[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]]},"+":{width:26,points:[[13,18],[13,0],[-1,-1],[4,9],[22,9]]},",":{width:10,points:[[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]]},"-":{width:18,points:[[6,9],[12,9]]},".":{width:10,points:[[5,2],[4,1],[5,0],[6,1],[5,2]]},"/":{width:22,points:[[20,25],[2,-7]]},"0":{width:20,points:[[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]]},"1":{width:20,points:[[6,17],[8,18],[11,21],[11,0]]},"2":{width:20,points:[[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]]},"3":{width:20,points:[[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]]},"4":{width:20,points:[[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]]},"5":{width:20,points:[[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]]},"6":{width:20,points:[[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]]},"7":{width:20,points:[[17,21],[7,0],[-1,-1],[3,21],[17,21]]},"8":{width:20,points:[[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]]},"9":{width:20,points:[[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]]},":":{width:10,points:[[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]]},";":{width:10,points:[[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]]},"<":{width:24,points:[[20,18],[4,9],[20,0]]},"=":{width:26,points:[[4,12],[22,12],[-1,-1],[4,6],[22,6]]},">":{width:24,points:[[4,18],[20,9],[4,0]]},"?":{width:18,points:[[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]]},"@":{width:27,points:[[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]]},A:{width:18,points:[[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]]},B:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]]},C:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]]},D:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]]},E:{width:19,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]]},F:{width:18,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]]},G:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]]},H:{width:22,points:[[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]]},I:{width:8,points:[[4,21],[4,0]]},J:{width:16,points:[[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]]},K:{width:21,points:[[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]]},L:{width:17,points:[[4,21],[4,0],[-1,-1],[4,0],[16,0]]},M:{width:24,points:[[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]]},N:{width:22,points:[[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]]},O:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]]},P:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]]},Q:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]]},R:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]]},S:{width:20,points:[[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},T:{width:16,points:[[8,21],[8,0],[-1,-1],[1,21],[15,21]]},U:{width:22,points:[[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]]},V:{width:18,points:[[1,21],[9,0],[-1,-1],[17,21],[9,0]]},W:{width:24,points:[[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]]},X:{width:20,points:[[3,21],[17,0],[-1,-1],[17,21],[3,0]]},Y:{width:18,points:[[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]]},Z:{width:20,points:[[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]]},"[":{width:14,points:[[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]]},"\\":{width:14,points:[[0,21],[14,-3]]},"]":{width:14,points:[[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]]},"^":{width:16,points:[[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]]},_:{width:16,points:[[0,-2],[16,-2]]},"`":{width:10,points:[[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]]},a:{width:19,points:[[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},b:{width:19,points:[[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},c:{width:18,points:[[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},d:{width:19,points:[[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},e:{width:18,points:[[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},f:{width:12,points:[[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]]},g:{width:19,points:[[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},h:{width:19,points:[[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},i:{width:8,points:[[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]]},j:{width:10,points:[[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]]},k:{width:17,points:[[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]]},l:{width:8,points:[[4,21],[4,0]]},m:{width:30,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]]},n:{width:19,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},o:{width:19,points:[[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]]},p:{width:19,points:[[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},q:{width:19,points:[[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},r:{width:13,points:[[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]]},s:{width:17,points:[[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]]},t:{width:12,points:[[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]]},u:{width:19,points:[[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]]},v:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0]]},w:{width:22,points:[[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]]},x:{width:17,points:[[3,14],[14,0],[-1,-1],[14,14],[3,0]]},y:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]]},z:{width:17,points:[[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]]},"{":{width:14,points:[[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]]},"|":{width:8,points:[[4,25],[4,-7]]},"}":{width:14,points:[[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]]},"~":{width:24,points:[[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]]}};a.jqplot.CanvasFontRenderer=function(b){b=b||{};if(!b.pt2px){b.pt2px=1.5}a.jqplot.CanvasTextRenderer.call(this,b)};a.jqplot.CanvasFontRenderer.prototype=new a.jqplot.CanvasTextRenderer({});a.jqplot.CanvasFontRenderer.prototype.constructor=a.jqplot.CanvasFontRenderer;a.jqplot.CanvasFontRenderer.prototype.measure=function(c,e){var d=this.fontSize+" "+this.fontFamily;c.save();c.font=d;var b=c.measureText(e).width;c.restore();return b};a.jqplot.CanvasFontRenderer.prototype.draw=function(e,g){var c=0;var h=this.height*0.72;e.save();var d,b;if((-Math.PI/2<=this.angle&&this.angle<=0)||(Math.PI*3/2<=this.angle&&this.angle<=Math.PI*2)){d=0;b=-Math.sin(this.angle)*this.width}else{if((0<this.angle&&this.angle<=Math.PI/2)||(-Math.PI*2<=this.angle&&this.angle<=-Math.PI*3/2)){d=Math.sin(this.angle)*this.height;b=0}else{if((-Math.PI<this.angle&&this.angle<-Math.PI/2)||(Math.PI<=this.angle&&this.angle<=Math.PI*3/2)){d=-Math.cos(this.angle)*this.width;b=-Math.sin(this.angle)*this.width-Math.cos(this.angle)*this.height}else{if((-Math.PI*3/2<this.angle&&this.angle<Math.PI)||(Math.PI/2<this.angle&&this.angle<Math.PI)){d=Math.sin(this.angle)*this.height-Math.cos(this.angle)*this.width;b=-Math.cos(this.angle)*this.height}}}}e.strokeStyle=this.fillStyle;e.fillStyle=this.fillStyle;var f=this.fontSize+" "+this.fontFamily;e.font=f;e.translate(d,b);e.rotate(this.angle);e.fillText(g,c,h);e.restore()}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.categoryAxisRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.categoryAxisRenderer.js new file mode 100644 index 0000000000..fc5d07cce1 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.categoryAxisRenderer.js @@ -0,0 +1,636 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * class: $.jqplot.CategoryAxisRenderer + * A plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series. + * + * To use this renderer, include the plugin in your source + * > <script type="text/javascript" language="javascript" src="plugins/jqplot.categoryAxisRenderer.js"></script> + * + * and supply the appropriate options to your plot + * + * > {axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}}} + **/ + $.jqplot.CategoryAxisRenderer = function(options) { + $.jqplot.LinearAxisRenderer.call(this); + // prop: sortMergedLabels + // True to sort tick labels when labels are created by merging + // x axis values from multiple series. That is, say you have + // two series like: + // > line1 = [[2006, 4], [2008, 9], [2009, 16]]; + // > line2 = [[2006, 3], [2007, 7], [2008, 6]]; + // If no label array is specified, tick labels will be collected + // from the x values of the series. With sortMergedLabels + // set to true, tick labels will be: + // > [2006, 2007, 2008, 2009] + // With sortMergedLabels set to false, tick labels will be: + // > [2006, 2008, 2009, 2007] + // + // Note, this property is specified on the renderOptions for the + // axes when creating a plot: + // > axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer, rendererOptions:{sortMergedLabels:true}}} + this.sortMergedLabels = false; + }; + + $.jqplot.CategoryAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.CategoryAxisRenderer.prototype.constructor = $.jqplot.CategoryAxisRenderer; + + $.jqplot.CategoryAxisRenderer.prototype.init = function(options){ + this.groups = 1; + this.groupLabels = []; + this._groupLabels = []; + this._grouped = false; + this._barsPerGroup = null; + // prop: tickRenderer + // A class of a rendering engine for creating the ticks labels displayed on the plot, + // See <$.jqplot.AxisTickRenderer>. + // this.tickRenderer = $.jqplot.AxisTickRenderer; + // this.labelRenderer = $.jqplot.AxisLabelRenderer; + $.extend(true, this, {tickOptions:{formatString:'%d'}}, options); + var db = this._dataBounds; + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + if (s.groups) { + this.groups = s.groups; + } + var d = s.data; + + for (var j=0; j<d.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + if (d[j][0] < db.min || db.min == null) { + db.min = d[j][0]; + } + if (d[j][0] > db.max || db.max == null) { + db.max = d[j][0]; + } + } + else { + if (d[j][1] < db.min || db.min == null) { + db.min = d[j][1]; + } + if (d[j][1] > db.max || db.max == null) { + db.max = d[j][1]; + } + } + } + } + + if (this.groupLabels.length) { + this.groups = this.groupLabels.length; + } + }; + + + $.jqplot.CategoryAxisRenderer.prototype.createTicks = function() { + // we're are operating on an axis here + var ticks = this._ticks; + var userTicks = this.ticks; + var name = this.name; + // databounds were set on axis initialization. + var db = this._dataBounds; + var dim, interval; + var min, max; + var pos1, pos2; + var tt, i; + + // if we already have ticks, use them. + if (userTicks.length) { + // adjust with blanks if we have groups + if (this.groups > 1 && !this._grouped) { + var l = userTicks.length; + var skip = parseInt(l/this.groups, 10); + var count = 0; + for (var i=skip; i<l; i+=skip) { + userTicks.splice(i+count, 0, ' '); + count++; + } + this._grouped = true; + } + this.min = 0.5; + this.max = userTicks.length + 0.5; + var range = this.max - this.min; + this.numberTicks = 2*userTicks.length + 1; + for (i=0; i<userTicks.length; i++){ + tt = this.min + 2 * i * range / (this.numberTicks-1); + // need a marker before and after the tick + var t = new this.tickRenderer(this.tickOptions); + t.showLabel = false; + // t.showMark = true; + t.setTick(tt, this.name); + this._ticks.push(t); + var t = new this.tickRenderer(this.tickOptions); + t.label = userTicks[i]; + // t.showLabel = true; + t.showMark = false; + t.showGridline = false; + t.setTick(tt+0.5, this.name); + this._ticks.push(t); + } + // now add the last tick at the end + var t = new this.tickRenderer(this.tickOptions); + t.showLabel = false; + // t.showMark = true; + t.setTick(tt+1, this.name); + this._ticks.push(t); + } + + // we don't have any ticks yet, let's make some! + else { + if (name == 'xaxis' || name == 'x2axis') { + dim = this._plotDimensions.width; + } + else { + dim = this._plotDimensions.height; + } + + // if min, max and number of ticks specified, user can't specify interval. + if (this.min != null && this.max != null && this.numberTicks != null) { + this.tickInterval = null; + } + + // if max, min, and interval specified and interval won't fit, ignore interval. + if (this.min != null && this.max != null && this.tickInterval != null) { + if (parseInt((this.max-this.min)/this.tickInterval, 10) != (this.max-this.min)/this.tickInterval) { + this.tickInterval = null; + } + } + + // find out how many categories are in the lines and collect labels + var labels = []; + var numcats = 0; + var min = 0.5; + var max, val; + var isMerged = false; + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + for (var j=0; j<s.data.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + val = s.data[j][0]; + } + else { + val = s.data[j][1]; + } + if ($.inArray(val, labels) == -1) { + isMerged = true; + numcats += 1; + labels.push(val); + } + } + } + + if (isMerged && this.sortMergedLabels) { + labels.sort(function(a,b) { return a - b; }); + } + + // keep a reference to these tick labels to use for redrawing plot (see bug #57) + this.ticks = labels; + + // now bin the data values to the right lables. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + for (var j=0; j<s.data.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + val = s.data[j][0]; + } + else { + val = s.data[j][1]; + } + // for category axis, force the values into category bins. + // we should have the value in the label array now. + var idx = $.inArray(val, labels)+1; + if (this.name == 'xaxis' || this.name == 'x2axis') { + s.data[j][0] = idx; + } + else { + s.data[j][1] = idx; + } + } + } + + // adjust with blanks if we have groups + if (this.groups > 1 && !this._grouped) { + var l = labels.length; + var skip = parseInt(l/this.groups, 10); + var count = 0; + for (var i=skip; i<l; i+=skip+1) { + labels[i] = ' '; + } + this._grouped = true; + } + + max = numcats + 0.5; + if (this.numberTicks == null) { + this.numberTicks = 2*numcats + 1; + } + + var range = max - min; + this.min = min; + this.max = max; + var track = 0; + + // todo: adjust this so more ticks displayed. + var maxVisibleTicks = parseInt(3+dim/20, 10); + var skip = parseInt(numcats/maxVisibleTicks, 10); + + if (this.tickInterval == null) { + + this.tickInterval = range / (this.numberTicks-1); + + } + // if tickInterval is specified, we will ignore any computed maximum. + for (var i=0; i<this.numberTicks; i++){ + tt = this.min + i * this.tickInterval; + var t = new this.tickRenderer(this.tickOptions); + // if even tick, it isn't a category, it's a divider + if (i/2 == parseInt(i/2, 10)) { + t.showLabel = false; + t.showMark = true; + } + else { + if (skip>0 && track<skip) { + t.showLabel = false; + track += 1; + } + else { + t.showLabel = true; + track = 0; + } + t.label = t.formatter(t.formatString, labels[(i-1)/2]); + t.showMark = false; + t.showGridline = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + } + } + + }; + + // called with scope of axis + $.jqplot.CategoryAxisRenderer.prototype.draw = function(ctx, plot) { + if (this.show) { + // populate the axis label and value properties. + // createTicks is a method on the renderer, but + // call it within the scope of the axis. + this.renderer.createTicks.call(this); + // fill a div with axes labels in the right direction. + // Need to pregenerate each axis to get it's bounds and + // position it and the labels correctly on the plot. + var dim=0; + var temp; + // Added for theming. + if (this._elem) { + // this._elem.empty(); + // Memory Leaks patch + this._elem.emptyForce(); + } + + this._elem = this._elem || $('<div class="jqplot-axis jqplot-'+this.name+'" style="position:absolute;"></div>'); + + if (this.name == 'xaxis' || this.name == 'x2axis') { + this._elem.width(this._plotDimensions.width); + } + else { + this._elem.height(this._plotDimensions.height); + } + + // create a _label object. + this.labelOptions.axis = this.name; + this._label = new this.labelRenderer(this.labelOptions); + if (this._label.show) { + var elem = this._label.draw(ctx, plot); + elem.appendTo(this._elem); + } + + var t = this._ticks; + for (var i=0; i<t.length; i++) { + var tick = t[i]; + if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + var elem = tick.draw(ctx, plot); + elem.appendTo(this._elem); + } + } + + this._groupLabels = []; + // now make group labels + for (var i=0; i<this.groupLabels.length; i++) + { + var elem = $('<div style="position:absolute;" class="jqplot-'+this.name+'-groupLabel"></div>'); + elem.html(this.groupLabels[i]); + this._groupLabels.push(elem); + elem.appendTo(this._elem); + } + } + return this._elem; + }; + + // called with scope of axis + $.jqplot.CategoryAxisRenderer.prototype.set = function() { + var dim = 0; + var temp; + var w = 0; + var h = 0; + var lshow = (this._label == null) ? false : this._label.show; + if (this.show) { + var t = this._ticks; + for (var i=0; i<t.length; i++) { + var tick = t[i]; + if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + temp = tick._elem.outerHeight(true); + } + else { + temp = tick._elem.outerWidth(true); + } + if (temp > dim) { + dim = temp; + } + } + } + + var dim2 = 0; + for (var i=0; i<this._groupLabels.length; i++) { + var l = this._groupLabels[i]; + if (this.name == 'xaxis' || this.name == 'x2axis') { + temp = l.outerHeight(true); + } + else { + temp = l.outerWidth(true); + } + if (temp > dim2) { + dim2 = temp; + } + } + + if (lshow) { + w = this._label._elem.outerWidth(true); + h = this._label._elem.outerHeight(true); + } + if (this.name == 'xaxis') { + dim += dim2 + h; + this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'}); + } + else if (this.name == 'x2axis') { + dim += dim2 + h; + this._elem.css({'height':dim+'px', left:'0px', top:'0px'}); + } + else if (this.name == 'yaxis') { + dim += dim2 + w; + this._elem.css({'width':dim+'px', left:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + else { + dim += dim2 + w; + this._elem.css({'width':dim+'px', right:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + } + }; + + // called with scope of axis + $.jqplot.CategoryAxisRenderer.prototype.pack = function(pos, offsets) { + var ticks = this._ticks; + var max = this.max; + var min = this.min; + var offmax = offsets.max; + var offmin = offsets.min; + var lshow = (this._label == null) ? false : this._label.show; + var i; + + for (var p in pos) { + this._elem.css(p, pos[p]); + } + + this._offsets = offsets; + // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left. + var pixellength = offmax - offmin; + var unitlength = max - min; + + // point to unit and unit to point conversions references to Plot DOM element top left corner. + this.p2u = function(p){ + return (p - offmin) * unitlength / pixellength + min; + }; + + this.u2p = function(u){ + return (u - min) * pixellength / unitlength + offmin; + }; + + if (this.name == 'xaxis' || this.name == 'x2axis'){ + this.series_u2p = function(u){ + return (u - min) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + min; + }; + } + + else { + this.series_u2p = function(u){ + return (u - max) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + max; + }; + } + + if (this.show) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + for (i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'xaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + if (temp * t.angle < 0) { + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + } + // position at start + else { + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + } + break; + case 'end': + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + case 'start': + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + break; + case 'middle': + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + default: + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + } + } + else { + shim = -t.getWidth()/2; + } + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('left', val); + t.pack(); + } + } + + var labeledge=['bottom', 0]; + if (lshow) { + var w = this._label._elem.outerWidth(true); + this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px'); + if (this.name == 'xaxis') { + this._label._elem.css('bottom', '0px'); + labeledge = ['bottom', this._label._elem.outerHeight(true)]; + } + else { + this._label._elem.css('top', '0px'); + labeledge = ['top', this._label._elem.outerHeight(true)]; + } + this._label.pack(); + } + + // draw the group labels + var step = parseInt(this._ticks.length/this.groups, 10); + for (i=0; i<this._groupLabels.length; i++) { + var mid = 0; + var count = 0; + for (var j=i*step; j<=(i+1)*step; j++) { + if (this._ticks[j]._elem && this._ticks[j].label != " ") { + var t = this._ticks[j]._elem; + var p = t.position(); + mid += p.left + t.outerWidth(true)/2; + count++; + } + } + mid = mid/count; + this._groupLabels[i].css({'left':(mid - this._groupLabels[i].outerWidth(true)/2)}); + this._groupLabels[i].css(labeledge[0], labeledge[1]); + } + } + else { + for (i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'yaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + case 'end': + if (temp * t.angle < 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'start': + if (t.angle > 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'middle': + // if (t.angle > 0) { + // shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + // } + // else { + // shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + // } + shim = -t.getHeight()/2; + break; + default: + shim = -t.getHeight()/2; + break; + } + } + else { + shim = -t.getHeight()/2; + } + + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('top', val); + t.pack(); + } + } + + var labeledge=['left', 0]; + if (lshow) { + var h = this._label._elem.outerHeight(true); + this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px'); + if (this.name == 'yaxis') { + this._label._elem.css('left', '0px'); + labeledge = ['left', this._label._elem.outerWidth(true)]; + } + else { + this._label._elem.css('right', '0px'); + labeledge = ['right', this._label._elem.outerWidth(true)]; + } + this._label.pack(); + } + + // draw the group labels, position top here, do left after label position. + var step = parseInt(this._ticks.length/this.groups, 10); + for (i=0; i<this._groupLabels.length; i++) { + var mid = 0; + var count = 0; + for (var j=i*step; j<=(i+1)*step; j++) { + if (this._ticks[j]._elem && this._ticks[j].label != " ") { + var t = this._ticks[j]._elem; + var p = t.position(); + mid += p.top + t.outerHeight()/2; + count++; + } + } + mid = mid/count; + this._groupLabels[i].css({'top':mid - this._groupLabels[i].outerHeight()/2}); + this._groupLabels[i].css(labeledge[0], labeledge[1]); + + } + } + } + }; + + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.categoryAxisRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.categoryAxisRenderer.min.js new file mode 100644 index 0000000000..982d642fd6 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.categoryAxisRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.CategoryAxisRenderer=function(b){a.jqplot.LinearAxisRenderer.call(this);this.sortMergedLabels=false};a.jqplot.CategoryAxisRenderer.prototype=new a.jqplot.LinearAxisRenderer();a.jqplot.CategoryAxisRenderer.prototype.constructor=a.jqplot.CategoryAxisRenderer;a.jqplot.CategoryAxisRenderer.prototype.init=function(e){this.groups=1;this.groupLabels=[];this._groupLabels=[];this._grouped=false;this._barsPerGroup=null;a.extend(true,this,{tickOptions:{formatString:"%d"}},e);var b=this._dataBounds;for(var f=0;f<this._series.length;f++){var g=this._series[f];if(g.groups){this.groups=g.groups}var h=g.data;for(var c=0;c<h.length;c++){if(this.name=="xaxis"||this.name=="x2axis"){if(h[c][0]<b.min||b.min==null){b.min=h[c][0]}if(h[c][0]>b.max||b.max==null){b.max=h[c][0]}}else{if(h[c][1]<b.min||b.min==null){b.min=h[c][1]}if(h[c][1]>b.max||b.max==null){b.max=h[c][1]}}}}if(this.groupLabels.length){this.groups=this.groupLabels.length}};a.jqplot.CategoryAxisRenderer.prototype.createTicks=function(){var D=this._ticks;var z=this.ticks;var F=this.name;var C=this._dataBounds;var v,A;var q,w;var d,c;var b,x;if(z.length){if(this.groups>1&&!this._grouped){var r=z.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x<r;x+=p){z.splice(x+e,0," ");e++}this._grouped=true}this.min=0.5;this.max=z.length+0.5;var m=this.max-this.min;this.numberTicks=2*z.length+1;for(x=0;x<z.length;x++){b=this.min+2*x*m/(this.numberTicks-1);var h=new this.tickRenderer(this.tickOptions);h.showLabel=false;h.setTick(b,this.name);this._ticks.push(h);var h=new this.tickRenderer(this.tickOptions);h.label=z[x];h.showMark=false;h.showGridline=false;h.setTick(b+0.5,this.name);this._ticks.push(h)}var h=new this.tickRenderer(this.tickOptions);h.showLabel=false;h.setTick(b+1,this.name);this._ticks.push(h)}else{if(F=="xaxis"||F=="x2axis"){v=this._plotDimensions.width}else{v=this._plotDimensions.height}if(this.min!=null&&this.max!=null&&this.numberTicks!=null){this.tickInterval=null}if(this.min!=null&&this.max!=null&&this.tickInterval!=null){if(parseInt((this.max-this.min)/this.tickInterval,10)!=(this.max-this.min)/this.tickInterval){this.tickInterval=null}}var y=[];var B=0;var q=0.5;var w,E;var f=false;for(var x=0;x<this._series.length;x++){var k=this._series[x];for(var u=0;u<k.data.length;u++){if(this.name=="xaxis"||this.name=="x2axis"){E=k.data[u][0]}else{E=k.data[u][1]}if(a.inArray(E,y)==-1){f=true;B+=1;y.push(E)}}}if(f&&this.sortMergedLabels){y.sort(function(j,i){return j-i})}this.ticks=y;for(var x=0;x<this._series.length;x++){var k=this._series[x];for(var u=0;u<k.data.length;u++){if(this.name=="xaxis"||this.name=="x2axis"){E=k.data[u][0]}else{E=k.data[u][1]}var n=a.inArray(E,y)+1;if(this.name=="xaxis"||this.name=="x2axis"){k.data[u][0]=n}else{k.data[u][1]=n}}}if(this.groups>1&&!this._grouped){var r=y.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x<r;x+=p+1){y[x]=" "}this._grouped=true}w=B+0.5;if(this.numberTicks==null){this.numberTicks=2*B+1}var m=w-q;this.min=q;this.max=w;var o=0;var g=parseInt(3+v/20,10);var p=parseInt(B/g,10);if(this.tickInterval==null){this.tickInterval=m/(this.numberTicks-1)}for(var x=0;x<this.numberTicks;x++){b=this.min+x*this.tickInterval;var h=new this.tickRenderer(this.tickOptions);if(x/2==parseInt(x/2,10)){h.showLabel=false;h.showMark=true}else{if(p>0&&o<p){h.showLabel=false;o+=1}else{h.showLabel=true;o=0}h.label=h.formatter(h.formatString,y[(x-1)/2]);h.showMark=false;h.showGridline=false}h.setTick(b,this.name);this._ticks.push(h)}}};a.jqplot.CategoryAxisRenderer.prototype.draw=function(b,j){if(this.show){this.renderer.createTicks.call(this);var h=0;var c;if(this._elem){this._elem.emptyForce()}this._elem=this._elem||a('<div class="jqplot-axis jqplot-'+this.name+'" style="position:absolute;"></div>');if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){var g=this._label.draw(b,j);g.appendTo(this._elem)}var f=this._ticks;for(var e=0;e<f.length;e++){var d=f[e];if(d.showLabel&&(!d.isMinorTick||this.showMinorTicks)){var g=d.draw(b,j);g.appendTo(this._elem)}}this._groupLabels=[];for(var e=0;e<this.groupLabels.length;e++){var g=a('<div style="position:absolute;" class="jqplot-'+this.name+'-groupLabel"></div>');g.html(this.groupLabels[e]);this._groupLabels.push(g);g.appendTo(this._elem)}}return this._elem};a.jqplot.CategoryAxisRenderer.prototype.set=function(){var e=0;var m;var k=0;var f=0;var d=(this._label==null)?false:this._label.show;if(this.show){var n=this._ticks;for(var c=0;c<n.length;c++){var g=n[c];if(g.showLabel&&(!g.isMinorTick||this.showMinorTicks)){if(this.name=="xaxis"||this.name=="x2axis"){m=g._elem.outerHeight(true)}else{m=g._elem.outerWidth(true)}if(m>e){e=m}}}var j=0;for(var c=0;c<this._groupLabels.length;c++){var b=this._groupLabels[c];if(this.name=="xaxis"||this.name=="x2axis"){m=b.outerHeight(true)}else{m=b.outerWidth(true)}if(m>j){j=m}}if(d){k=this._label._elem.outerWidth(true);f=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){e+=j+k;this._elem.css({width:e+"px",left:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}else{e+=j+k;this._elem.css({width:e+"px",right:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}}}}};a.jqplot.CategoryAxisRenderer.prototype.pack=function(e,c){var C=this._ticks;var v=this.max;var s=this.min;var n=c.max;var l=c.min;var q=(this._label==null)?false:this._label.show;var x;for(var r in e){this._elem.css(r,e[r])}this._offsets=c;var g=n-l;var k=v-s;this.p2u=function(h){return(h-l)*k/g+s};this.u2p=function(h){return(h-s)*g/k+l};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(h-s)*g/k};this.series_p2u=function(h){return h*k/g+s}}else{this.series_u2p=function(h){return(h-v)*g/k};this.series_p2u=function(h){return h*k/g+v}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(x=0;x<C.length;x++){var o=C[x];if(o.show&&o.showLabel){var b;if(o.constructor==a.jqplot.CanvasAxisTickRenderer&&o.angle){var A=(this.name=="xaxis")?1:-1;switch(o.labelPosition){case"auto":if(A*o.angle<0){b=-o.getWidth()+o._textRenderer.height*Math.sin(-o._textRenderer.angle)/2}else{b=-o._textRenderer.height*Math.sin(o._textRenderer.angle)/2}break;case"end":b=-o.getWidth()+o._textRenderer.height*Math.sin(-o._textRenderer.angle)/2;break;case"start":b=-o._textRenderer.height*Math.sin(o._textRenderer.angle)/2;break;case"middle":b=-o.getWidth()/2+o._textRenderer.height*Math.sin(-o._textRenderer.angle)/2;break;default:b=-o.getWidth()/2+o._textRenderer.height*Math.sin(-o._textRenderer.angle)/2;break}}else{b=-o.getWidth()/2}var D=this.u2p(o.value)+b+"px";o._elem.css("left",D);o.pack()}}var z=["bottom",0];if(q){var m=this._label._elem.outerWidth(true);this._label._elem.css("left",l+g/2-m/2+"px");if(this.name=="xaxis"){this._label._elem.css("bottom","0px");z=["bottom",this._label._elem.outerHeight(true)]}else{this._label._elem.css("top","0px");z=["top",this._label._elem.outerHeight(true)]}this._label.pack()}var d=parseInt(this._ticks.length/this.groups,10);for(x=0;x<this._groupLabels.length;x++){var B=0;var f=0;for(var u=x*d;u<=(x+1)*d;u++){if(this._ticks[u]._elem&&this._ticks[u].label!=" "){var o=this._ticks[u]._elem;var r=o.position();B+=r.left+o.outerWidth(true)/2;f++}}B=B/f;this._groupLabels[x].css({left:(B-this._groupLabels[x].outerWidth(true)/2)});this._groupLabels[x].css(z[0],z[1])}}else{for(x=0;x<C.length;x++){var o=C[x];if(o.show&&o.showLabel){var b;if(o.constructor==a.jqplot.CanvasAxisTickRenderer&&o.angle){var A=(this.name=="yaxis")?1:-1;switch(o.labelPosition){case"auto":case"end":if(A*o.angle<0){b=-o._textRenderer.height*Math.cos(-o._textRenderer.angle)/2}else{b=-o.getHeight()+o._textRenderer.height*Math.cos(o._textRenderer.angle)/2}break;case"start":if(o.angle>0){b=-o._textRenderer.height*Math.cos(-o._textRenderer.angle)/2}else{b=-o.getHeight()+o._textRenderer.height*Math.cos(o._textRenderer.angle)/2}break;case"middle":b=-o.getHeight()/2;break;default:b=-o.getHeight()/2;break}}else{b=-o.getHeight()/2}var D=this.u2p(o.value)+b+"px";o._elem.css("top",D);o.pack()}}var z=["left",0];if(q){var y=this._label._elem.outerHeight(true);this._label._elem.css("top",n-g/2-y/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px");z=["left",this._label._elem.outerWidth(true)]}else{this._label._elem.css("right","0px");z=["right",this._label._elem.outerWidth(true)]}this._label.pack()}var d=parseInt(this._ticks.length/this.groups,10);for(x=0;x<this._groupLabels.length;x++){var B=0;var f=0;for(var u=x*d;u<=(x+1)*d;u++){if(this._ticks[u]._elem&&this._ticks[u].label!=" "){var o=this._ticks[u]._elem;var r=o.position();B+=r.top+o.outerHeight()/2;f++}}B=B/f;this._groupLabels[x].css({top:B-this._groupLabels[x].outerHeight()/2});this._groupLabels[x].css(z[0],z[1])}}}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.ciParser.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.ciParser.js new file mode 100644 index 0000000000..4e9ec8c7f2 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.ciParser.js @@ -0,0 +1,115 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.ciParser + * Data Renderer function which converts a custom JSON data object into jqPlot data format. + * Set this as a callable on the jqplot dataRenderer plot option: + * + * > plot = $.jqplot('mychart', [data], { dataRenderer: $.jqplot.ciParser, ... }); + * + * Where data is an object in JSON format or a JSON encoded string conforming to the + * City Index API spec. + * + * Note that calling the renderer function is handled internally by jqPlot. The + * user does not have to call the function. The parameters described below will + * automatically be passed to the ciParser function. + * + * Parameters: + * data - JSON encoded string or object. + * plot - reference to jqPlot Plot object. + * + * Returns: + * data array in jqPlot format. + * + */ + $.jqplot.ciParser = function (data, plot) { + var ret = [], + line, + temp, + i, j, k, kk; + + if (typeof(data) == "string") { + data = $.jqplot.JSON.parse(data, handleStrings); + } + + else if (typeof(data) == "object") { + for (k in data) { + for (i=0; i<data[k].length; i++) { + for (kk in data[k][i]) { + data[k][i][kk] = handleStrings(kk, data[k][i][kk]); + } + } + } + } + + else { + return null; + } + + // function handleStrings + // Checks any JSON encoded strings to see if they are + // encoded dates. If so, pull out the timestamp. + // Expects dates to be represented by js timestamps. + + function handleStrings(key, value) { + var a; + if (value != null) { + if (value.toString().indexOf('Date') >= 0) { + //here we will try to extract the ticks from the Date string in the "value" fields of JSON returned data + a = /^\/Date\((-?[0-9]+)\)\/$/.exec(value); + if (a) { + return parseInt(a[1], 10); + } + } + return value; + } + } + + for (var prop in data) { + line = []; + temp = data[prop]; + switch (prop) { + case "PriceTicks": + for (i=0; i<temp.length; i++) { + line.push([temp[i]['TickDate'], temp[i]['Price']]); + } + break; + case "PriceBars": + for (i=0; i<temp.length; i++) { + line.push([temp[i]['BarDate'], temp[i]['Open'], temp[i]['High'], temp[i]['Low'], temp[i]['Close']]); + } + break; + } + ret.push(line); + } + return ret; + }; +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.ciParser.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.ciParser.min.js new file mode 100644 index 0000000000..6227db2522 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.ciParser.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.ciParser=function(g,l){var m=[],o,n,h,f,e,c;if(typeof(g)=="string"){g=a.jqplot.JSON.parse(g,d)}else{if(typeof(g)=="object"){for(e in g){for(h=0;h<g[e].length;h++){for(c in g[e][h]){g[e][h][c]=d(c,g[e][h][c])}}}}else{return null}}function d(j,k){var i;if(k!=null){if(k.toString().indexOf("Date")>=0){i=/^\/Date\((-?[0-9]+)\)\/$/.exec(k);if(i){return parseInt(i[1],10)}}return k}}for(var b in g){o=[];n=g[b];switch(b){case"PriceTicks":for(h=0;h<n.length;h++){o.push([n[h]["TickDate"],n[h]["Price"]])}break;case"PriceBars":for(h=0;h<n.length;h++){o.push([n[h]["BarDate"],n[h]["Open"],n[h]["High"],n[h]["Low"],n[h]["Close"]])}break}m.push(o)}return m}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.cursor.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.cursor.js new file mode 100644 index 0000000000..78b8cab890 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.cursor.js @@ -0,0 +1,1051 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + + /** + * Class: $.jqplot.Cursor + * Plugin class representing the cursor as displayed on the plot. + */ + $.jqplot.Cursor = function(options) { + // Group: Properties + // + // prop: style + // CSS spec for cursor style + this.style = 'crosshair'; + this.previousCursor = 'auto'; + // prop: show + // wether to show the cursor or not. + this.show = $.jqplot.config.enablePlugins; + // prop: showTooltip + // show a cursor position tooltip. Location of the tooltip + // will be controlled by followMouse and tooltipLocation. + this.showTooltip = true; + // prop: followMouse + // Tooltip follows the mouse, it is not at a fixed location. + // Tooltip will show on the grid at the location given by + // tooltipLocation, offset from the grid edge by tooltipOffset. + this.followMouse = false; + // prop: tooltipLocation + // Where to position tooltip. If followMouse is true, this is + // relative to the cursor, otherwise, it is relative to the grid. + // One of 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw' + this.tooltipLocation = 'se'; + // prop: tooltipOffset + // Pixel offset of tooltip from the grid boudaries or cursor center. + this.tooltipOffset = 6; + // prop: showTooltipGridPosition + // show the grid pixel coordinates of the mouse. + this.showTooltipGridPosition = false; + // prop: showTooltipUnitPosition + // show the unit (data) coordinates of the mouse. + this.showTooltipUnitPosition = true; + // prop: showTooltipDataPosition + // Used with showVerticalLine to show intersecting data points in the tooltip. + this.showTooltipDataPosition = false; + // prop: tooltipFormatString + // sprintf format string for the tooltip. + // Uses Ash Searle's javascript sprintf implementation + // found here: http://hexmen.com/blog/2007/03/printf-sprintf/ + // See http://perldoc.perl.org/functions/sprintf.html for reference + // Note, if showTooltipDataPosition is true, the default tooltipFormatString + // will be set to the cursorLegendFormatString, not the default given here. + this.tooltipFormatString = '%.4P, %.4P'; + // prop: useAxesFormatters + // Use the x and y axes formatters to format the text in the tooltip. + this.useAxesFormatters = true; + // prop: tooltipAxisGroups + // Show position for the specified axes. + // This is an array like [['xaxis', 'yaxis'], ['xaxis', 'y2axis']] + // Default is to compute automatically for all visible axes. + this.tooltipAxisGroups = []; + // prop: zoom + // Enable plot zooming. + this.zoom = false; + // zoomProxy and zoomTarget properties are not directly set by user. + // They Will be set through call to zoomProxy method. + this.zoomProxy = false; + this.zoomTarget = false; + // prop: looseZoom + // Will expand zoom range to provide more rounded tick values. + // Works only with linear axes and date axes. + this.looseZoom = false; + // prop: clickReset + // Will reset plot zoom if single click on plot without drag. + this.clickReset = false; + // prop: dblClickReset + // Will reset plot zoom if double click on plot without drag. + this.dblClickReset = true; + // prop: showVerticalLine + // draw a vertical line across the plot which follows the cursor. + // When the line is near a data point, a special legend and/or tooltip can + // be updated with the data values. + this.showVerticalLine = false; + // prop: showHorizontalLine + // draw a horizontal line across the plot which follows the cursor. + this.showHorizontalLine = false; + // prop: constrainZoomTo + // 'none', 'x' or 'y' + this.constrainZoomTo = 'none'; + // // prop: autoscaleConstraint + // // when a constrained axis is specified, true will + // // auatoscale the adjacent axis. + // this.autoscaleConstraint = true; + this.shapeRenderer = new $.jqplot.ShapeRenderer(); + this._zoom = {start:[], end:[], started: false, zooming:false, isZoomed:false, axes:{start:{}, end:{}}, gridpos:{}, datapos:{}}; + this._tooltipElem; + this.zoomCanvas; + this.cursorCanvas; + // prop: intersectionThreshold + // pixel distance from data point or marker to consider cursor lines intersecting with point. + // If data point markers are not shown, this should be >= 1 or will often miss point intersections. + this.intersectionThreshold = 2; + // prop: showCursorLegend + // Replace the plot legend with an enhanced legend displaying intersection information. + this.showCursorLegend = false; + // prop: cursorLegendFormatString + // Format string used in the cursor legend. If showTooltipDataPosition is true, + // this will also be the default format string used by tooltipFormatString. + this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString; + // whether the cursor is over the grid or not. + this._oldHandlers = {onselectstart: null, ondrag: null, onmousedown: null}; + // prop: constrainOutsideZoom + // True to limit actual zoom area to edges of grid, even when zooming + // outside of plot area. That is, can't zoom out by mousing outside plot. + this.constrainOutsideZoom = true; + // prop: showTooltipOutsideZoom + // True will keep updating the tooltip when zooming of the grid. + this.showTooltipOutsideZoom = false; + // true if mouse is over grid, false if not. + this.onGrid = false; + $.extend(true, this, options); + }; + + $.jqplot.Cursor.cursorLegendFormatString = '%s x:%s, y:%s'; + + // called with scope of plot + $.jqplot.Cursor.init = function (target, data, opts){ + // add a cursor attribute to the plot + var options = opts || {}; + this.plugins.cursor = new $.jqplot.Cursor(options.cursor); + var c = this.plugins.cursor; + + if (c.show) { + $.jqplot.eventListenerHooks.push(['jqplotMouseEnter', handleMouseEnter]); + $.jqplot.eventListenerHooks.push(['jqplotMouseLeave', handleMouseLeave]); + $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMouseMove]); + + if (c.showCursorLegend) { + opts.legend = opts.legend || {}; + opts.legend.renderer = $.jqplot.CursorLegendRenderer; + opts.legend.formatString = this.plugins.cursor.cursorLegendFormatString; + opts.legend.show = true; + } + + if (c.zoom) { + $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleMouseDown]); + + if (c.clickReset) { + $.jqplot.eventListenerHooks.push(['jqplotClick', handleClick]); + } + + if (c.dblClickReset) { + $.jqplot.eventListenerHooks.push(['jqplotDblClick', handleDblClick]); + } + } + + this.resetZoom = function() { + var axes = this.axes; + if (!c.zoomProxy) { + for (var ax in axes) { + axes[ax].reset(); + axes[ax]._ticks = []; + // fake out tick creation algorithm to make sure original auto + // computed format string is used if _overrideFormatString is true + axes[ax]._autoFormatString = c._zoom.axes[ax].tickFormatString; + } + this.redraw(); + } + else { + var ctx = this.plugins.cursor.zoomCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx = null; + } + this.plugins.cursor._zoom.isZoomed = false; + this.target.trigger('jqplotResetZoom', [this, this.plugins.cursor]); + }; + + + if (c.showTooltipDataPosition) { + c.showTooltipUnitPosition = false; + c.showTooltipGridPosition = false; + if (options.cursor.tooltipFormatString == undefined) { + c.tooltipFormatString = $.jqplot.Cursor.cursorLegendFormatString; + } + } + } + }; + + // called with context of plot + $.jqplot.Cursor.postDraw = function() { + var c = this.plugins.cursor; + + // Memory Leaks patch + if (c.zoomCanvas) { + c.zoomCanvas.resetCanvas(); + c.zoomCanvas = null; + } + + if (c.cursorCanvas) { + c.cursorCanvas.resetCanvas(); + c.cursorCanvas = null; + } + + if (c._tooltipElem) { + c._tooltipElem.emptyForce(); + c._tooltipElem = null; + } + + + if (c.zoom) { + c.zoomCanvas = new $.jqplot.GenericCanvas(); + this.eventCanvas._elem.before(c.zoomCanvas.createElement(this._gridPadding, 'jqplot-zoom-canvas', this._plotDimensions, this)); + c.zoomCanvas.setContext(); + } + + var elem = document.createElement('div'); + c._tooltipElem = $(elem); + elem = null; + c._tooltipElem.addClass('jqplot-cursor-tooltip'); + c._tooltipElem.css({position:'absolute', display:'none'}); + + + if (c.zoomCanvas) { + c.zoomCanvas._elem.before(c._tooltipElem); + } + + else { + this.eventCanvas._elem.before(c._tooltipElem); + } + + if (c.showVerticalLine || c.showHorizontalLine) { + c.cursorCanvas = new $.jqplot.GenericCanvas(); + this.eventCanvas._elem.before(c.cursorCanvas.createElement(this._gridPadding, 'jqplot-cursor-canvas', this._plotDimensions, this)); + c.cursorCanvas.setContext(); + } + + // if we are showing the positions in unit coordinates, and no axes groups + // were specified, create a default set. + if (c.showTooltipUnitPosition){ + if (c.tooltipAxisGroups.length === 0) { + var series = this.series; + var s; + var temp = []; + for (var i=0; i<series.length; i++) { + s = series[i]; + var ax = s.xaxis+','+s.yaxis; + if ($.inArray(ax, temp) == -1) { + temp.push(ax); + } + } + for (var i=0; i<temp.length; i++) { + c.tooltipAxisGroups.push(temp[i].split(',')); + } + } + } + }; + + // Group: methods + // + // method: $.jqplot.Cursor.zoomProxy + // links targetPlot to controllerPlot so that plot zooming of + // targetPlot will be controlled by zooming on the controllerPlot. + // controllerPlot will not actually zoom, but acts as an + // overview plot. Note, the zoom options must be set to true for + // zoomProxy to work. + $.jqplot.Cursor.zoomProxy = function(targetPlot, controllerPlot) { + var tc = targetPlot.plugins.cursor; + var cc = controllerPlot.plugins.cursor; + tc.zoomTarget = true; + tc.zoom = true; + tc.style = 'auto'; + tc.dblClickReset = false; + cc.zoom = true; + cc.zoomProxy = true; + + controllerPlot.target.bind('jqplotZoom', plotZoom); + controllerPlot.target.bind('jqplotResetZoom', plotReset); + + function plotZoom(ev, gridpos, datapos, plot, cursor) { + tc.doZoom(gridpos, datapos, targetPlot, cursor); + } + + function plotReset(ev, plot, cursor) { + targetPlot.resetZoom(); + } + }; + + $.jqplot.Cursor.prototype.resetZoom = function(plot, cursor) { + var axes = plot.axes; + var cax = cursor._zoom.axes; + if (!plot.plugins.cursor.zoomProxy && cursor._zoom.isZoomed) { + for (var ax in axes) { + // axes[ax]._ticks = []; + // axes[ax].min = cax[ax].min; + // axes[ax].max = cax[ax].max; + // axes[ax].numberTicks = cax[ax].numberTicks; + // axes[ax].tickInterval = cax[ax].tickInterval; + // // for date axes + // axes[ax].daTickInterval = cax[ax].daTickInterval; + axes[ax].reset(); + axes[ax]._ticks = []; + // fake out tick creation algorithm to make sure original auto + // computed format string is used if _overrideFormatString is true + axes[ax]._autoFormatString = cax[ax].tickFormatString; + } + plot.redraw(); + cursor._zoom.isZoomed = false; + } + else { + var ctx = cursor.zoomCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx = null; + } + plot.target.trigger('jqplotResetZoom', [plot, cursor]); + }; + + $.jqplot.Cursor.resetZoom = function(plot) { + plot.resetZoom(); + }; + + $.jqplot.Cursor.prototype.doZoom = function (gridpos, datapos, plot, cursor) { + var c = cursor; + var axes = plot.axes; + var zaxes = c._zoom.axes; + var start = zaxes.start; + var end = zaxes.end; + var min, max, dp, span; + var ctx = plot.plugins.cursor.zoomCanvas._ctx; + // don't zoom if zoom area is too small (in pixels) + if ((c.constrainZoomTo == 'none' && Math.abs(gridpos.x - c._zoom.start[0]) > 6 && Math.abs(gridpos.y - c._zoom.start[1]) > 6) || (c.constrainZoomTo == 'x' && Math.abs(gridpos.x - c._zoom.start[0]) > 6) || (c.constrainZoomTo == 'y' && Math.abs(gridpos.y - c._zoom.start[1]) > 6)) { + if (!plot.plugins.cursor.zoomProxy) { + for (var ax in datapos) { + // make a copy of the original axes to revert back. + if (c._zoom.axes[ax] == undefined) { + c._zoom.axes[ax] = {}; + c._zoom.axes[ax].numberTicks = axes[ax].numberTicks; + c._zoom.axes[ax].tickInterval = axes[ax].tickInterval; + // for date axes... + c._zoom.axes[ax].daTickInterval = axes[ax].daTickInterval; + c._zoom.axes[ax].min = axes[ax].min; + c._zoom.axes[ax].max = axes[ax].max; + c._zoom.axes[ax].tickFormatString = (axes[ax].tickOptions != null) ? axes[ax].tickOptions.formatString : ''; + } + + + if ((c.constrainZoomTo == 'none') || (c.constrainZoomTo == 'x' && ax.charAt(0) == 'x') || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'y')) { + dp = datapos[ax]; + if (dp != null) { + var newmin, newmax; + if (dp > start[ax]) { + newmin = start[ax]; + newmax = dp; + } + else { + span = start[ax] - dp; + newmin = dp; + newmax = start[ax]; + } + + if (this.looseZoom && (axes[ax].renderer.constructor === $.jqplot.LinearAxisRenderer || axes[ax].renderer.constructor === $.jqplot.DateAxisRenderer)) { + var ret = $.jqplot.LinearTickGenerator(newmin, newmax); + axes[ax].min = ret[0]; + axes[ax].max = ret[1]; + axes[ax]._autoFormatString = ret[3]; + axes[ax].numberTicks = ret[2]; + axes[ax].tickInterval = ret[4]; + // for date axes... + axes[ax].daTickInterval = [ret[4]/1000, 'seconds']; + } + else { + axes[ax].min = newmin; + axes[ax].max = newmax; + axes[ax].tickInterval = null; + // for date axes... + axes[ax].daTickInterval = null; + } + + axes[ax]._ticks = []; + } + } + + // if ((c.constrainZoomTo == 'x' && ax.charAt(0) == 'y' && c.autoscaleConstraint) || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'x' && c.autoscaleConstraint)) { + // dp = datapos[ax]; + // if (dp != null) { + // axes[ax].max == null; + // axes[ax].min = null; + // } + // } + } + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + plot.redraw(); + c._zoom.isZoomed = true; + ctx = null; + } + plot.target.trigger('jqplotZoom', [gridpos, datapos, plot, cursor]); + } + }; + + $.jqplot.preInitHooks.push($.jqplot.Cursor.init); + $.jqplot.postDrawHooks.push($.jqplot.Cursor.postDraw); + + function updateTooltip(gridpos, datapos, plot) { + var c = plot.plugins.cursor; + var s = ''; + var addbr = false; + if (c.showTooltipGridPosition) { + s = gridpos.x+', '+gridpos.y; + addbr = true; + } + if (c.showTooltipUnitPosition) { + var g; + for (var i=0; i<c.tooltipAxisGroups.length; i++) { + g = c.tooltipAxisGroups[i]; + if (addbr) { + s += '<br />'; + } + if (c.useAxesFormatters) { + var xf = plot.axes[g[0]]._ticks[0].formatter; + var yf = plot.axes[g[1]]._ticks[0].formatter; + var xfstr = plot.axes[g[0]]._ticks[0].formatString; + var yfstr = plot.axes[g[1]]._ticks[0].formatString; + s += xf(xfstr, datapos[g[0]]) + ', '+ yf(yfstr, datapos[g[1]]); + } + else { + s += $.jqplot.sprintf(c.tooltipFormatString, datapos[g[0]], datapos[g[1]]); + } + addbr = true; + } + } + + if (c.showTooltipDataPosition) { + var series = plot.series; + var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y); + var addbr = false; + + for (var i = 0; i< series.length; i++) { + if (series[i].show) { + var idx = series[i].index; + var label = series[i].label.toString(); + var cellid = $.inArray(idx, ret.indices); + var sx = undefined; + var sy = undefined; + if (cellid != -1) { + var data = ret.data[cellid].data; + if (c.useAxesFormatters) { + var xf = series[i]._xaxis._ticks[0].formatter; + var yf = series[i]._yaxis._ticks[0].formatter; + var xfstr = series[i]._xaxis._ticks[0].formatString; + var yfstr = series[i]._yaxis._ticks[0].formatString; + sx = xf(xfstr, data[0]); + sy = yf(yfstr, data[1]); + } + else { + sx = data[0]; + sy = data[1]; + } + if (addbr) { + s += '<br />'; + } + s += $.jqplot.sprintf(c.tooltipFormatString, label, sx, sy); + addbr = true; + } + } + } + + } + c._tooltipElem.html(s); + } + + function moveLine(gridpos, plot) { + var c = plot.plugins.cursor; + var ctx = c.cursorCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + if (c.showVerticalLine) { + c.shapeRenderer.draw(ctx, [[gridpos.x, 0], [gridpos.x, ctx.canvas.height]]); + } + if (c.showHorizontalLine) { + c.shapeRenderer.draw(ctx, [[0, gridpos.y], [ctx.canvas.width, gridpos.y]]); + } + var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y); + if (c.showCursorLegend) { + var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label'); + for (var i=0; i<cells.length; i++) { + var idx = $(cells[i]).data('seriesIndex'); + var series = plot.series[idx]; + var label = series.label.toString(); + var cellid = $.inArray(idx, ret.indices); + var sx = undefined; + var sy = undefined; + if (cellid != -1) { + var data = ret.data[cellid].data; + if (c.useAxesFormatters) { + var xf = series._xaxis._ticks[0].formatter; + var yf = series._yaxis._ticks[0].formatter; + var xfstr = series._xaxis._ticks[0].formatString; + var yfstr = series._yaxis._ticks[0].formatString; + sx = xf(xfstr, data[0]); + sy = yf(yfstr, data[1]); + } + else { + sx = data[0]; + sy = data[1]; + } + } + if (plot.legend.escapeHtml) { + $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy)); + } + else { + $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy)); + } + } + } + ctx = null; + } + + function getIntersectingPoints(plot, x, y) { + var ret = {indices:[], data:[]}; + var s, i, d0, d, j, r, p; + var threshold; + var c = plot.plugins.cursor; + for (var i=0; i<plot.series.length; i++) { + s = plot.series[i]; + r = s.renderer; + if (s.show) { + threshold = c.intersectionThreshold; + if (s.showMarker) { + threshold += s.markerRenderer.size/2; + } + for (var j=0; j<s.gridData.length; j++) { + p = s.gridData[j]; + // check vertical line + if (c.showVerticalLine) { + if (Math.abs(x-p[0]) <= threshold) { + ret.indices.push(i); + ret.data.push({seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}); + } + } + } + } + } + return ret; + } + + function moveTooltip(gridpos, plot) { + var c = plot.plugins.cursor; + var elem = c._tooltipElem; + switch (c.tooltipLocation) { + case 'nw': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true); + break; + case 'n': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2; + var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true); + break; + case 'ne': + var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true); + break; + case 'e': + var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2; + break; + case 'se': + var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset; + break; + case 's': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2; + var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset; + break; + case 'sw': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset; + break; + case 'w': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2; + break; + default: + var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset; + break; + } + + elem.css('left', x); + elem.css('top', y); + elem = null; + } + + function positionTooltip(plot) { + // fake a grid for positioning + var grid = plot._gridPadding; + var c = plot.plugins.cursor; + var elem = c._tooltipElem; + switch (c.tooltipLocation) { + case 'nw': + var a = grid.left + c.tooltipOffset; + var b = grid.top + c.tooltipOffset; + elem.css('left', a); + elem.css('top', b); + break; + case 'n': + var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2; + var b = grid.top + c.tooltipOffset; + elem.css('left', a); + elem.css('top', b); + break; + case 'ne': + var a = grid.right + c.tooltipOffset; + var b = grid.top + c.tooltipOffset; + elem.css({right:a, top:b}); + break; + case 'e': + var a = grid.right + c.tooltipOffset; + var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2; + elem.css({right:a, top:b}); + break; + case 'se': + var a = grid.right + c.tooltipOffset; + var b = grid.bottom + c.tooltipOffset; + elem.css({right:a, bottom:b}); + break; + case 's': + var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2; + var b = grid.bottom + c.tooltipOffset; + elem.css({left:a, bottom:b}); + break; + case 'sw': + var a = grid.left + c.tooltipOffset; + var b = grid.bottom + c.tooltipOffset; + elem.css({left:a, bottom:b}); + break; + case 'w': + var a = grid.left + c.tooltipOffset; + var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2; + elem.css({left:a, top:b}); + break; + default: // same as 'se' + var a = grid.right - c.tooltipOffset; + var b = grid.bottom + c.tooltipOffset; + elem.css({right:a, bottom:b}); + break; + } + elem = null; + } + + function handleClick (ev, gridpos, datapos, neighbor, plot) { + ev.preventDefault(); + ev.stopImmediatePropagation(); + var c = plot.plugins.cursor; + if (c.clickReset) { + c.resetZoom(plot, c); + } + var sel = window.getSelection; + if (document.selection && document.selection.empty) + { + document.selection.empty(); + } + else if (sel && !sel().isCollapsed) { + sel().collapse(); + } + return false; + } + + function handleDblClick (ev, gridpos, datapos, neighbor, plot) { + ev.preventDefault(); + ev.stopImmediatePropagation(); + var c = plot.plugins.cursor; + if (c.dblClickReset) { + c.resetZoom(plot, c); + } + var sel = window.getSelection; + if (document.selection && document.selection.empty) + { + document.selection.empty(); + } + else if (sel && !sel().isCollapsed) { + sel().collapse(); + } + return false; + } + + function handleMouseLeave(ev, gridpos, datapos, neighbor, plot) { + var c = plot.plugins.cursor; + c.onGrid = false; + if (c.show) { + $(ev.target).css('cursor', c.previousCursor); + if (c.showTooltip && !(c._zoom.zooming && c.showTooltipOutsideZoom && !c.constrainOutsideZoom)) { + c._tooltipElem.hide(); + } + if (c.zoom) { + c._zoom.gridpos = gridpos; + c._zoom.datapos = datapos; + } + if (c.showVerticalLine || c.showHorizontalLine) { + var ctx = c.cursorCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx = null; + } + if (c.showCursorLegend) { + var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label'); + for (var i=0; i<cells.length; i++) { + var idx = $(cells[i]).data('seriesIndex'); + var series = plot.series[idx]; + var label = series.label.toString(); + if (plot.legend.escapeHtml) { + $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined)); + } + else { + $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined)); + } + + } + } + } + } + + function handleMouseEnter(ev, gridpos, datapos, neighbor, plot) { + var c = plot.plugins.cursor; + c.onGrid = true; + if (c.show) { + c.previousCursor = ev.target.style.cursor; + ev.target.style.cursor = c.style; + if (c.showTooltip) { + updateTooltip(gridpos, datapos, plot); + if (c.followMouse) { + moveTooltip(gridpos, plot); + } + else { + positionTooltip(plot); + } + c._tooltipElem.show(); + } + if (c.showVerticalLine || c.showHorizontalLine) { + moveLine(gridpos, plot); + } + } + + } + + function handleMouseMove(ev, gridpos, datapos, neighbor, plot) { + var c = plot.plugins.cursor; + if (c.show) { + if (c.showTooltip) { + updateTooltip(gridpos, datapos, plot); + if (c.followMouse) { + moveTooltip(gridpos, plot); + } + } + if (c.showVerticalLine || c.showHorizontalLine) { + moveLine(gridpos, plot); + } + } + } + + function getEventPosition(ev) { + var plot = ev.data.plot; + var go = plot.eventCanvas._elem.offset(); + var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top}; + var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null}; + var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis']; + var ax = plot.axes; + var n, axis; + for (n=11; n>0; n--) { + axis = an[n-1]; + if (ax[axis].show) { + dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]); + } + } + + return {offsets:go, gridPos:gridPos, dataPos:dataPos}; + } + + function handleZoomMove(ev) { + var plot = ev.data.plot; + var c = plot.plugins.cursor; + // don't do anything if not on grid. + if (c.show && c.zoom && c._zoom.started && !c.zoomTarget) { + var ctx = c.zoomCanvas._ctx; + var positions = getEventPosition(ev); + var gridpos = positions.gridPos; + var datapos = positions.dataPos; + c._zoom.gridpos = gridpos; + c._zoom.datapos = datapos; + c._zoom.zooming = true; + var xpos = gridpos.x; + var ypos = gridpos.y; + var height = ctx.canvas.height; + var width = ctx.canvas.width; + if (c.showTooltip && !c.onGrid && c.showTooltipOutsideZoom) { + updateTooltip(gridpos, datapos, plot); + if (c.followMouse) { + moveTooltip(gridpos, plot); + } + } + if (c.constrainZoomTo == 'x') { + c._zoom.end = [xpos, height]; + } + else if (c.constrainZoomTo == 'y') { + c._zoom.end = [width, ypos]; + } + else { + c._zoom.end = [xpos, ypos]; + } + var sel = window.getSelection; + if (document.selection && document.selection.empty) + { + document.selection.empty(); + } + else if (sel && !sel().isCollapsed) { + sel().collapse(); + } + drawZoomBox.call(c); + ctx = null; + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + var c = plot.plugins.cursor; + $(document).one('mouseup.jqplot_cursor', {plot:plot}, handleMouseUp); + var axes = plot.axes; + if (document.onselectstart != undefined) { + c._oldHandlers.onselectstart = document.onselectstart; + document.onselectstart = function () { return false; }; + } + if (document.ondrag != undefined) { + c._oldHandlers.ondrag = document.ondrag; + document.ondrag = function () { return false; }; + } + if (document.onmousedown != undefined) { + c._oldHandlers.onmousedown = document.onmousedown; + document.onmousedown = function () { return false; }; + } + if (c.zoom) { + if (!c.zoomProxy) { + var ctx = c.zoomCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx = null; + } + if (c.constrainZoomTo == 'x') { + c._zoom.start = [gridpos.x, 0]; + } + else if (c.constrainZoomTo == 'y') { + c._zoom.start = [0, gridpos.y]; + } + else { + c._zoom.start = [gridpos.x, gridpos.y]; + } + c._zoom.started = true; + for (var ax in datapos) { + // get zoom starting position. + c._zoom.axes.start[ax] = datapos[ax]; + } + $(document).bind('mousemove.jqplotCursor', {plot:plot}, handleZoomMove); + } + } + + function handleMouseUp(ev) { + var plot = ev.data.plot; + var c = plot.plugins.cursor; + if (c.zoom && c._zoom.zooming && !c.zoomTarget) { + var xpos = c._zoom.gridpos.x; + var ypos = c._zoom.gridpos.y; + var datapos = c._zoom.datapos; + var height = c.zoomCanvas._ctx.canvas.height; + var width = c.zoomCanvas._ctx.canvas.width; + var axes = plot.axes; + + if (c.constrainOutsideZoom && !c.onGrid) { + if (xpos < 0) { xpos = 0; } + else if (xpos > width) { xpos = width; } + if (ypos < 0) { ypos = 0; } + else if (ypos > height) { ypos = height; } + + for (var axis in datapos) { + if (datapos[axis]) { + if (axis.charAt(0) == 'x') { + datapos[axis] = axes[axis].series_p2u(xpos); + } + else { + datapos[axis] = axes[axis].series_p2u(ypos); + } + } + } + } + + if (c.constrainZoomTo == 'x') { + ypos = height; + } + else if (c.constrainZoomTo == 'y') { + xpos = width; + } + c._zoom.end = [xpos, ypos]; + c._zoom.gridpos = {x:xpos, y:ypos}; + + c.doZoom(c._zoom.gridpos, datapos, plot, c); + } + c._zoom.started = false; + c._zoom.zooming = false; + + $(document).unbind('mousemove.jqplotCursor', handleZoomMove); + + if (document.onselectstart != undefined && c._oldHandlers.onselectstart != null){ + document.onselectstart = c._oldHandlers.onselectstart; + c._oldHandlers.onselectstart = null; + } + if (document.ondrag != undefined && c._oldHandlers.ondrag != null){ + document.ondrag = c._oldHandlers.ondrag; + c._oldHandlers.ondrag = null; + } + if (document.onmousedown != undefined && c._oldHandlers.onmousedown != null){ + document.onmousedown = c._oldHandlers.onmousedown; + c._oldHandlers.onmousedown = null; + } + + } + + function drawZoomBox() { + var start = this._zoom.start; + var end = this._zoom.end; + var ctx = this.zoomCanvas._ctx; + var l, t, h, w; + if (end[0] > start[0]) { + l = start[0]; + w = end[0] - start[0]; + } + else { + l = end[0]; + w = start[0] - end[0]; + } + if (end[1] > start[1]) { + t = start[1]; + h = end[1] - start[1]; + } + else { + t = end[1]; + h = start[1] - end[1]; + } + ctx.fillStyle = 'rgba(0,0,0,0.2)'; + ctx.strokeStyle = '#999999'; + ctx.lineWidth = 1.0; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx.clearRect(l, t, w, h); + // IE won't show transparent fill rect, so stroke a rect also. + ctx.strokeRect(l,t,w,h); + ctx = null; + } + + $.jqplot.CursorLegendRenderer = function(options) { + $.jqplot.TableLegendRenderer.call(this, options); + this.formatString = '%s'; + }; + + $.jqplot.CursorLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); + $.jqplot.CursorLegendRenderer.prototype.constructor = $.jqplot.CursorLegendRenderer; + + // called in context of a Legend + $.jqplot.CursorLegendRenderer.prototype.draw = function() { + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + if (this.show) { + var series = this._series, s; + // make a table. one line label per row. + var elem = document.createElement('div'); + this._elem = $(elem); + elem = null; + this._elem.addClass('jqplot-legend jqplot-cursor-legend'); + this._elem.css('position', 'absolute'); + + var pad = false; + for (var i = 0; i< series.length; i++) { + s = series[i]; + if (s.show && s.showLabel) { + var lt = $.jqplot.sprintf(this.formatString, s.label.toString()); + if (lt) { + var color = s.color; + if (s._stack && !s.fill) { + color = ''; + } + addrow.call(this, lt, color, pad, i); + pad = true; + } + // let plugins add more rows to legend. Used by trend line plugin. + for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) { + var item = $.jqplot.addLegendRowHooks[j].call(this, s); + if (item) { + addrow.call(this, item.label, item.color, pad); + pad = true; + } + } + } + } + series = s = null; + delete series; + delete s; + } + + function addrow(label, color, pad, idx) { + var rs = (pad) ? this.rowSpacing : '0'; + var tr = $('<tr class="jqplot-legend jqplot-cursor-legend"></tr>').appendTo(this._elem); + tr.data('seriesIndex', idx); + $('<td class="jqplot-legend jqplot-cursor-legend-swatch" style="padding-top:'+rs+';">'+ + '<div style="border:1px solid #cccccc;padding:0.2em;">'+ + '<div class="jqplot-cursor-legend-swatch" style="background-color:'+color+';"></div>'+ + '</div></td>').appendTo(tr); + var td = $('<td class="jqplot-legend jqplot-cursor-legend-label" style="vertical-align:middle;padding-top:'+rs+';"></td>'); + td.appendTo(tr); + td.data('seriesIndex', idx); + if (this.escapeHtml) { + td.text(label); + } + else { + td.html(label); + } + tr = null; + td = null; + } + return this._elem; + }; + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.cursor.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.cursor.min.js new file mode 100644 index 0000000000..c79f72718e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.cursor.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(j){j.jqplot.Cursor=function(q){this.style="crosshair";this.previousCursor="auto";this.show=j.jqplot.config.enablePlugins;this.showTooltip=true;this.followMouse=false;this.tooltipLocation="se";this.tooltipOffset=6;this.showTooltipGridPosition=false;this.showTooltipUnitPosition=true;this.showTooltipDataPosition=false;this.tooltipFormatString="%.4P, %.4P";this.useAxesFormatters=true;this.tooltipAxisGroups=[];this.zoom=false;this.zoomProxy=false;this.zoomTarget=false;this.looseZoom=false;this.clickReset=false;this.dblClickReset=true;this.showVerticalLine=false;this.showHorizontalLine=false;this.constrainZoomTo="none";this.shapeRenderer=new j.jqplot.ShapeRenderer();this._zoom={start:[],end:[],started:false,zooming:false,isZoomed:false,axes:{start:{},end:{}},gridpos:{},datapos:{}};this._tooltipElem;this.zoomCanvas;this.cursorCanvas;this.intersectionThreshold=2;this.showCursorLegend=false;this.cursorLegendFormatString=j.jqplot.Cursor.cursorLegendFormatString;this._oldHandlers={onselectstart:null,ondrag:null,onmousedown:null};this.constrainOutsideZoom=true;this.showTooltipOutsideZoom=false;this.onGrid=false;j.extend(true,this,q)};j.jqplot.Cursor.cursorLegendFormatString="%s x:%s, y:%s";j.jqplot.Cursor.init=function(t,s,r){var q=r||{};this.plugins.cursor=new j.jqplot.Cursor(q.cursor);var u=this.plugins.cursor;if(u.show){j.jqplot.eventListenerHooks.push(["jqplotMouseEnter",b]);j.jqplot.eventListenerHooks.push(["jqplotMouseLeave",f]);j.jqplot.eventListenerHooks.push(["jqplotMouseMove",i]);if(u.showCursorLegend){r.legend=r.legend||{};r.legend.renderer=j.jqplot.CursorLegendRenderer;r.legend.formatString=this.plugins.cursor.cursorLegendFormatString;r.legend.show=true}if(u.zoom){j.jqplot.eventListenerHooks.push(["jqplotMouseDown",a]);if(u.clickReset){j.jqplot.eventListenerHooks.push(["jqplotClick",k])}if(u.dblClickReset){j.jqplot.eventListenerHooks.push(["jqplotDblClick",c])}}this.resetZoom=function(){var x=this.axes;if(!u.zoomProxy){for(var w in x){x[w].reset();x[w]._ticks=[];x[w]._autoFormatString=u._zoom.axes[w].tickFormatString}this.redraw()}else{var v=this.plugins.cursor.zoomCanvas._ctx;v.clearRect(0,0,v.canvas.width,v.canvas.height);v=null}this.plugins.cursor._zoom.isZoomed=false;this.target.trigger("jqplotResetZoom",[this,this.plugins.cursor])};if(u.showTooltipDataPosition){u.showTooltipUnitPosition=false;u.showTooltipGridPosition=false;if(q.cursor.tooltipFormatString==undefined){u.tooltipFormatString=j.jqplot.Cursor.cursorLegendFormatString}}}};j.jqplot.Cursor.postDraw=function(){var x=this.plugins.cursor;if(x.zoomCanvas){x.zoomCanvas.resetCanvas();x.zoomCanvas=null}if(x.cursorCanvas){x.cursorCanvas.resetCanvas();x.cursorCanvas=null}if(x._tooltipElem){x._tooltipElem.emptyForce();x._tooltipElem=null}if(x.zoom){x.zoomCanvas=new j.jqplot.GenericCanvas();this.eventCanvas._elem.before(x.zoomCanvas.createElement(this._gridPadding,"jqplot-zoom-canvas",this._plotDimensions,this));x.zoomCanvas.setContext()}var v=document.createElement("div");x._tooltipElem=j(v);v=null;x._tooltipElem.addClass("jqplot-cursor-tooltip");x._tooltipElem.css({position:"absolute",display:"none"});if(x.zoomCanvas){x.zoomCanvas._elem.before(x._tooltipElem)}else{this.eventCanvas._elem.before(x._tooltipElem)}if(x.showVerticalLine||x.showHorizontalLine){x.cursorCanvas=new j.jqplot.GenericCanvas();this.eventCanvas._elem.before(x.cursorCanvas.createElement(this._gridPadding,"jqplot-cursor-canvas",this._plotDimensions,this));x.cursorCanvas.setContext()}if(x.showTooltipUnitPosition){if(x.tooltipAxisGroups.length===0){var t=this.series;var u;var q=[];for(var r=0;r<t.length;r++){u=t[r];var w=u.xaxis+","+u.yaxis;if(j.inArray(w,q)==-1){q.push(w)}}for(var r=0;r<q.length;r++){x.tooltipAxisGroups.push(q[r].split(","))}}}};j.jqplot.Cursor.zoomProxy=function(v,r){var q=v.plugins.cursor;var u=r.plugins.cursor;q.zoomTarget=true;q.zoom=true;q.style="auto";q.dblClickReset=false;u.zoom=true;u.zoomProxy=true;r.target.bind("jqplotZoom",t);r.target.bind("jqplotResetZoom",s);function t(x,w,z,y,A){q.doZoom(w,z,v,A)}function s(w,x,y){v.resetZoom()}};j.jqplot.Cursor.prototype.resetZoom=function(u,v){var t=u.axes;var s=v._zoom.axes;if(!u.plugins.cursor.zoomProxy&&v._zoom.isZoomed){for(var r in t){t[r].reset();t[r]._ticks=[];t[r]._autoFormatString=s[r].tickFormatString}u.redraw();v._zoom.isZoomed=false}else{var q=v.zoomCanvas._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);q=null}u.target.trigger("jqplotResetZoom",[u,v])};j.jqplot.Cursor.resetZoom=function(q){q.resetZoom()};j.jqplot.Cursor.prototype.doZoom=function(F,s,B,t){var G=t;var E=B.axes;var q=G._zoom.axes;var v=q.start;var r=q.end;var A,D,y,C;var z=B.plugins.cursor.zoomCanvas._ctx;if((G.constrainZoomTo=="none"&&Math.abs(F.x-G._zoom.start[0])>6&&Math.abs(F.y-G._zoom.start[1])>6)||(G.constrainZoomTo=="x"&&Math.abs(F.x-G._zoom.start[0])>6)||(G.constrainZoomTo=="y"&&Math.abs(F.y-G._zoom.start[1])>6)){if(!B.plugins.cursor.zoomProxy){for(var x in s){if(G._zoom.axes[x]==undefined){G._zoom.axes[x]={};G._zoom.axes[x].numberTicks=E[x].numberTicks;G._zoom.axes[x].tickInterval=E[x].tickInterval;G._zoom.axes[x].daTickInterval=E[x].daTickInterval;G._zoom.axes[x].min=E[x].min;G._zoom.axes[x].max=E[x].max;G._zoom.axes[x].tickFormatString=(E[x].tickOptions!=null)?E[x].tickOptions.formatString:""}if((G.constrainZoomTo=="none")||(G.constrainZoomTo=="x"&&x.charAt(0)=="x")||(G.constrainZoomTo=="y"&&x.charAt(0)=="y")){y=s[x];if(y!=null){var u,w;if(y>v[x]){u=v[x];w=y}else{C=v[x]-y;u=y;w=v[x]}if(this.looseZoom&&(E[x].renderer.constructor===j.jqplot.LinearAxisRenderer||E[x].renderer.constructor===j.jqplot.DateAxisRenderer)){var H=j.jqplot.LinearTickGenerator(u,w);E[x].min=H[0];E[x].max=H[1];E[x]._autoFormatString=H[3];E[x].numberTicks=H[2];E[x].tickInterval=H[4];E[x].daTickInterval=[H[4]/1000,"seconds"]}else{E[x].min=u;E[x].max=w;E[x].tickInterval=null;E[x].daTickInterval=null}E[x]._ticks=[]}}}z.clearRect(0,0,z.canvas.width,z.canvas.height);B.redraw();G._zoom.isZoomed=true;z=null}B.target.trigger("jqplotZoom",[F,s,B,t])}};j.jqplot.preInitHooks.push(j.jqplot.Cursor.init);j.jqplot.postDrawHooks.push(j.jqplot.Cursor.postDraw);function e(E,r,B){var G=B.plugins.cursor;var w="";var K=false;if(G.showTooltipGridPosition){w=E.x+", "+E.y;K=true}if(G.showTooltipUnitPosition){var D;for(var C=0;C<G.tooltipAxisGroups.length;C++){D=G.tooltipAxisGroups[C];if(K){w+="<br />"}if(G.useAxesFormatters){var A=B.axes[D[0]]._ticks[0].formatter;var q=B.axes[D[1]]._ticks[0].formatter;var H=B.axes[D[0]]._ticks[0].formatString;var v=B.axes[D[1]]._ticks[0].formatString;w+=A(H,r[D[0]])+", "+q(v,r[D[1]])}else{w+=j.jqplot.sprintf(G.tooltipFormatString,r[D[0]],r[D[1]])}K=true}}if(G.showTooltipDataPosition){var u=B.series;var J=d(B,E.x,E.y);var K=false;for(var C=0;C<u.length;C++){if(u[C].show){var y=u[C].index;var t=u[C].label.toString();var F=j.inArray(y,J.indices);var z=undefined;var x=undefined;if(F!=-1){var I=J.data[F].data;if(G.useAxesFormatters){var A=u[C]._xaxis._ticks[0].formatter;var q=u[C]._yaxis._ticks[0].formatter;var H=u[C]._xaxis._ticks[0].formatString;var v=u[C]._yaxis._ticks[0].formatString;z=A(H,I[0]);x=q(v,I[1])}else{z=I[0];x=I[1]}if(K){w+="<br />"}w+=j.jqplot.sprintf(G.tooltipFormatString,t,z,x);K=true}}}}G._tooltipElem.html(w)}function g(C,A){var E=A.plugins.cursor;var z=E.cursorCanvas._ctx;z.clearRect(0,0,z.canvas.width,z.canvas.height);if(E.showVerticalLine){E.shapeRenderer.draw(z,[[C.x,0],[C.x,z.canvas.height]])}if(E.showHorizontalLine){E.shapeRenderer.draw(z,[[0,C.y],[z.canvas.width,C.y]])}var G=d(A,C.x,C.y);if(E.showCursorLegend){var r=j(A.targetId+" td.jqplot-cursor-legend-label");for(var B=0;B<r.length;B++){var v=j(r[B]).data("seriesIndex");var t=A.series[v];var s=t.label.toString();var D=j.inArray(v,G.indices);var x=undefined;var w=undefined;if(D!=-1){var H=G.data[D].data;if(E.useAxesFormatters){var y=t._xaxis._ticks[0].formatter;var q=t._yaxis._ticks[0].formatter;var F=t._xaxis._ticks[0].formatString;var u=t._yaxis._ticks[0].formatString;x=y(F,H[0]);w=q(u,H[1])}else{x=H[0];w=H[1]}}if(A.legend.escapeHtml){j(r[B]).text(j.jqplot.sprintf(E.cursorLegendFormatString,s,x,w))}else{j(r[B]).html(j.jqplot.sprintf(E.cursorLegendFormatString,s,x,w))}}}z=null}function d(A,F,E){var B={indices:[],data:[]};var G,w,u,C,v,q,t;var z;var D=A.plugins.cursor;for(var w=0;w<A.series.length;w++){G=A.series[w];q=G.renderer;if(G.show){z=D.intersectionThreshold;if(G.showMarker){z+=G.markerRenderer.size/2}for(var v=0;v<G.gridData.length;v++){t=G.gridData[v];if(D.showVerticalLine){if(Math.abs(F-t[0])<=z){B.indices.push(w);B.data.push({seriesIndex:w,pointIndex:v,gridData:t,data:G.data[v]})}}}}}return B}function n(r,t){var v=t.plugins.cursor;var s=v._tooltipElem;switch(v.tooltipLocation){case"nw":var q=r.x+t._gridPadding.left-s.outerWidth(true)-v.tooltipOffset;var u=r.y+t._gridPadding.top-v.tooltipOffset-s.outerHeight(true);break;case"n":var q=r.x+t._gridPadding.left-s.outerWidth(true)/2;var u=r.y+t._gridPadding.top-v.tooltipOffset-s.outerHeight(true);break;case"ne":var q=r.x+t._gridPadding.left+v.tooltipOffset;var u=r.y+t._gridPadding.top-v.tooltipOffset-s.outerHeight(true);break;case"e":var q=r.x+t._gridPadding.left+v.tooltipOffset;var u=r.y+t._gridPadding.top-s.outerHeight(true)/2;break;case"se":var q=r.x+t._gridPadding.left+v.tooltipOffset;var u=r.y+t._gridPadding.top+v.tooltipOffset;break;case"s":var q=r.x+t._gridPadding.left-s.outerWidth(true)/2;var u=r.y+t._gridPadding.top+v.tooltipOffset;break;case"sw":var q=r.x+t._gridPadding.left-s.outerWidth(true)-v.tooltipOffset;var u=r.y+t._gridPadding.top+v.tooltipOffset;break;case"w":var q=r.x+t._gridPadding.left-s.outerWidth(true)-v.tooltipOffset;var u=r.y+t._gridPadding.top-s.outerHeight(true)/2;break;default:var q=r.x+t._gridPadding.left+v.tooltipOffset;var u=r.y+t._gridPadding.top+v.tooltipOffset;break}s.css("left",q);s.css("top",u);s=null}function m(u){var s=u._gridPadding;var v=u.plugins.cursor;var t=v._tooltipElem;switch(v.tooltipLocation){case"nw":var r=s.left+v.tooltipOffset;var q=s.top+v.tooltipOffset;t.css("left",r);t.css("top",q);break;case"n":var r=(s.left+(u._plotDimensions.width-s.right))/2-t.outerWidth(true)/2;var q=s.top+v.tooltipOffset;t.css("left",r);t.css("top",q);break;case"ne":var r=s.right+v.tooltipOffset;var q=s.top+v.tooltipOffset;t.css({right:r,top:q});break;case"e":var r=s.right+v.tooltipOffset;var q=(s.top+(u._plotDimensions.height-s.bottom))/2-t.outerHeight(true)/2;t.css({right:r,top:q});break;case"se":var r=s.right+v.tooltipOffset;var q=s.bottom+v.tooltipOffset;t.css({right:r,bottom:q});break;case"s":var r=(s.left+(u._plotDimensions.width-s.right))/2-t.outerWidth(true)/2;var q=s.bottom+v.tooltipOffset;t.css({left:r,bottom:q});break;case"sw":var r=s.left+v.tooltipOffset;var q=s.bottom+v.tooltipOffset;t.css({left:r,bottom:q});break;case"w":var r=s.left+v.tooltipOffset;var q=(s.top+(u._plotDimensions.height-s.bottom))/2-t.outerHeight(true)/2;t.css({left:r,top:q});break;default:var r=s.right-v.tooltipOffset;var q=s.bottom+v.tooltipOffset;t.css({right:r,bottom:q});break}t=null}function k(r,q,v,u,t){r.preventDefault();r.stopImmediatePropagation();var w=t.plugins.cursor;if(w.clickReset){w.resetZoom(t,w)}var s=window.getSelection;if(document.selection&&document.selection.empty){document.selection.empty()}else{if(s&&!s().isCollapsed){s().collapse()}}return false}function c(r,q,v,u,t){r.preventDefault();r.stopImmediatePropagation();var w=t.plugins.cursor;if(w.dblClickReset){w.resetZoom(t,w)}var s=window.getSelection;if(document.selection&&document.selection.empty){document.selection.empty()}else{if(s&&!s().isCollapsed){s().collapse()}}return false}function f(w,t,q,z,u){var v=u.plugins.cursor;v.onGrid=false;if(v.show){j(w.target).css("cursor",v.previousCursor);if(v.showTooltip&&!(v._zoom.zooming&&v.showTooltipOutsideZoom&&!v.constrainOutsideZoom)){v._tooltipElem.hide()}if(v.zoom){v._zoom.gridpos=t;v._zoom.datapos=q}if(v.showVerticalLine||v.showHorizontalLine){var B=v.cursorCanvas._ctx;B.clearRect(0,0,B.canvas.width,B.canvas.height);B=null}if(v.showCursorLegend){var A=j(u.targetId+" td.jqplot-cursor-legend-label");for(var s=0;s<A.length;s++){var y=j(A[s]).data("seriesIndex");var r=u.series[y];var x=r.label.toString();if(u.legend.escapeHtml){j(A[s]).text(j.jqplot.sprintf(v.cursorLegendFormatString,x,undefined,undefined))}else{j(A[s]).html(j.jqplot.sprintf(v.cursorLegendFormatString,x,undefined,undefined))}}}}}function b(r,q,u,t,s){var v=s.plugins.cursor;v.onGrid=true;if(v.show){v.previousCursor=r.target.style.cursor;r.target.style.cursor=v.style;if(v.showTooltip){e(q,u,s);if(v.followMouse){n(q,s)}else{m(s)}v._tooltipElem.show()}if(v.showVerticalLine||v.showHorizontalLine){g(q,s)}}}function i(r,q,u,t,s){var v=s.plugins.cursor;if(v.show){if(v.showTooltip){e(q,u,s);if(v.followMouse){n(q,s)}}if(v.showVerticalLine||v.showHorizontalLine){g(q,s)}}}function o(y){var x=y.data.plot;var t=x.eventCanvas._elem.offset();var w={x:y.pageX-t.left,y:y.pageY-t.top};var u={xaxis:null,yaxis:null,x2axis:null,y2axis:null,y3axis:null,y4axis:null,y5axis:null,y6axis:null,y7axis:null,y8axis:null,y9axis:null};var v=["xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis"];var q=x.axes;var r,s;for(r=11;r>0;r--){s=v[r-1];if(q[s].show){u[s]=q[s].series_p2u(w[s.charAt(0)])}}return{offsets:t,gridPos:w,dataPos:u}}function h(z){var x=z.data.plot;var y=x.plugins.cursor;if(y.show&&y.zoom&&y._zoom.started&&!y.zoomTarget){var B=y.zoomCanvas._ctx;var v=o(z);var w=v.gridPos;var t=v.dataPos;y._zoom.gridpos=w;y._zoom.datapos=t;y._zoom.zooming=true;var u=w.x;var s=w.y;var A=B.canvas.height;var q=B.canvas.width;if(y.showTooltip&&!y.onGrid&&y.showTooltipOutsideZoom){e(w,t,x);if(y.followMouse){n(w,x)}}if(y.constrainZoomTo=="x"){y._zoom.end=[u,A]}else{if(y.constrainZoomTo=="y"){y._zoom.end=[q,s]}else{y._zoom.end=[u,s]}}var r=window.getSelection;if(document.selection&&document.selection.empty){document.selection.empty()}else{if(r&&!r().isCollapsed){r().collapse()}}l.call(y);B=null}}function a(w,s,r,x,t){var v=t.plugins.cursor;j(document).one("mouseup.jqplot_cursor",{plot:t},p);var u=t.axes;if(document.onselectstart!=undefined){v._oldHandlers.onselectstart=document.onselectstart;document.onselectstart=function(){return false}}if(document.ondrag!=undefined){v._oldHandlers.ondrag=document.ondrag;document.ondrag=function(){return false}}if(document.onmousedown!=undefined){v._oldHandlers.onmousedown=document.onmousedown;document.onmousedown=function(){return false}}if(v.zoom){if(!v.zoomProxy){var y=v.zoomCanvas._ctx;y.clearRect(0,0,y.canvas.width,y.canvas.height);y=null}if(v.constrainZoomTo=="x"){v._zoom.start=[s.x,0]}else{if(v.constrainZoomTo=="y"){v._zoom.start=[0,s.y]}else{v._zoom.start=[s.x,s.y]}}v._zoom.started=true;for(var q in r){v._zoom.axes.start[q]=r[q]}j(document).bind("mousemove.jqplotCursor",{plot:t},h)}}function p(y){var v=y.data.plot;var x=v.plugins.cursor;if(x.zoom&&x._zoom.zooming&&!x.zoomTarget){var u=x._zoom.gridpos.x;var r=x._zoom.gridpos.y;var t=x._zoom.datapos;var z=x.zoomCanvas._ctx.canvas.height;var q=x.zoomCanvas._ctx.canvas.width;var w=v.axes;if(x.constrainOutsideZoom&&!x.onGrid){if(u<0){u=0}else{if(u>q){u=q}}if(r<0){r=0}else{if(r>z){r=z}}for(var s in t){if(t[s]){if(s.charAt(0)=="x"){t[s]=w[s].series_p2u(u)}else{t[s]=w[s].series_p2u(r)}}}}if(x.constrainZoomTo=="x"){r=z}else{if(x.constrainZoomTo=="y"){u=q}}x._zoom.end=[u,r];x._zoom.gridpos={x:u,y:r};x.doZoom(x._zoom.gridpos,t,v,x)}x._zoom.started=false;x._zoom.zooming=false;j(document).unbind("mousemove.jqplotCursor",h);if(document.onselectstart!=undefined&&x._oldHandlers.onselectstart!=null){document.onselectstart=x._oldHandlers.onselectstart;x._oldHandlers.onselectstart=null}if(document.ondrag!=undefined&&x._oldHandlers.ondrag!=null){document.ondrag=x._oldHandlers.ondrag;x._oldHandlers.ondrag=null}if(document.onmousedown!=undefined&&x._oldHandlers.onmousedown!=null){document.onmousedown=x._oldHandlers.onmousedown;x._oldHandlers.onmousedown=null}}function l(){var y=this._zoom.start;var u=this._zoom.end;var s=this.zoomCanvas._ctx;var r,v,x,q;if(u[0]>y[0]){r=y[0];q=u[0]-y[0]}else{r=u[0];q=y[0]-u[0]}if(u[1]>y[1]){v=y[1];x=u[1]-y[1]}else{v=u[1];x=y[1]-u[1]}s.fillStyle="rgba(0,0,0,0.2)";s.strokeStyle="#999999";s.lineWidth=1;s.clearRect(0,0,s.canvas.width,s.canvas.height);s.fillRect(0,0,s.canvas.width,s.canvas.height);s.clearRect(r,v,q,x);s.strokeRect(r,v,q,x);s=null}j.jqplot.CursorLegendRenderer=function(q){j.jqplot.TableLegendRenderer.call(this,q);this.formatString="%s"};j.jqplot.CursorLegendRenderer.prototype=new j.jqplot.TableLegendRenderer();j.jqplot.CursorLegendRenderer.prototype.constructor=j.jqplot.CursorLegendRenderer;j.jqplot.CursorLegendRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}if(this.show){var w=this._series,A;var r=document.createElement("div");this._elem=j(r);r=null;this._elem.addClass("jqplot-legend jqplot-cursor-legend");this._elem.css("position","absolute");var q=false;for(var x=0;x<w.length;x++){A=w[x];if(A.show&&A.showLabel){var v=j.jqplot.sprintf(this.formatString,A.label.toString());if(v){var t=A.color;if(A._stack&&!A.fill){t=""}z.call(this,v,t,q,x);q=true}for(var u=0;u<j.jqplot.addLegendRowHooks.length;u++){var y=j.jqplot.addLegendRowHooks[u].call(this,A);if(y){z.call(this,y.label,y.color,q);q=true}}}}w=A=null;delete w;delete A}function z(D,C,F,s){var B=(F)?this.rowSpacing:"0";var E=j('<tr class="jqplot-legend jqplot-cursor-legend"></tr>').appendTo(this._elem);E.data("seriesIndex",s);j('<td class="jqplot-legend jqplot-cursor-legend-swatch" style="padding-top:'+B+';"><div style="border:1px solid #cccccc;padding:0.2em;"><div class="jqplot-cursor-legend-swatch" style="background-color:'+C+';"></div></div></td>').appendTo(E);var G=j('<td class="jqplot-legend jqplot-cursor-legend-label" style="vertical-align:middle;padding-top:'+B+';"></td>');G.appendTo(E);G.data("seriesIndex",s);if(this.escapeHtml){G.text(D)}else{G.html(D)}E=null;G=null}return this._elem}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.dateAxisRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.dateAxisRenderer.js new file mode 100644 index 0000000000..94a48c0d6e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.dateAxisRenderer.js @@ -0,0 +1,439 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.DateAxisRenderer + * A plugin for a jqPlot to render an axis as a series of date values. + * This renderer has no options beyond those supplied by the <Axis> class. + * It supplies it's own tick formatter, so the tickOptions.formatter option + * should not be overridden. + * + * Thanks to Ken Synder for his enhanced Date instance methods which are + * included with this code <http://kendsnyder.com/sandbox/date/>. + * + * To use this renderer, include the plugin in your source + * > <script type="text/javascript" language="javascript" src="plugins/jqplot.dateAxisRenderer.js"></script> + * + * and supply the appropriate options to your plot + * + * > {axes:{xaxis:{renderer:$.jqplot.DateAxisRenderer}}} + * + * Dates can be passed into the axis in almost any recognizable value and + * will be parsed. They will be rendered on the axis in the format + * specified by tickOptions.formatString. e.g. tickOptions.formatString = '%Y-%m-%d'. + * + * Accecptable format codes + * are: + * + * > Code Result Description + * > == Years == + * > %Y 2008 Four-digit year + * > %y 08 Two-digit year + * > == Months == + * > %m 09 Two-digit month + * > %#m 9 One or two-digit month + * > %B September Full month name + * > %b Sep Abbreviated month name + * > == Days == + * > %d 05 Two-digit day of month + * > %#d 5 One or two-digit day of month + * > %e 5 One or two-digit day of month + * > %A Sunday Full name of the day of the week + * > %a Sun Abbreviated name of the day of the week + * > %w 0 Number of the day of the week (0 = Sunday, 6 = Saturday) + * > %o th The ordinal suffix string following the day of the month + * > == Hours == + * > %H 23 Hours in 24-hour format (two digits) + * > %#H 3 Hours in 24-hour integer format (one or two digits) + * > %I 11 Hours in 12-hour format (two digits) + * > %#I 3 Hours in 12-hour integer format (one or two digits) + * > %p PM AM or PM + * > == Minutes == + * > %M 09 Minutes (two digits) + * > %#M 9 Minutes (one or two digits) + * > == Seconds == + * > %S 02 Seconds (two digits) + * > %#S 2 Seconds (one or two digits) + * > %s 1206567625723 Unix timestamp (Seconds past 1970-01-01 00:00:00) + * > == Milliseconds == + * > %N 008 Milliseconds (three digits) + * > %#N 8 Milliseconds (one to three digits) + * > == Timezone == + * > %O 360 difference in minutes between local time and GMT + * > %Z Mountain Standard Time Name of timezone as reported by browser + * > %G -06:00 Hours and minutes between GMT + * > == Shortcuts == + * > %F 2008-03-26 %Y-%m-%d + * > %T 05:06:30 %H:%M:%S + * > %X 05:06:30 %H:%M:%S + * > %x 03/26/08 %m/%d/%y + * > %D 03/26/08 %m/%d/%y + * > %#c Wed Mar 26 15:31:00 2008 %a %b %e %H:%M:%S %Y + * > %v 3-Sep-2008 %e-%b-%Y + * > %R 15:31 %H:%M + * > %r 3:31:00 PM %I:%M:%S %p + * > == Characters == + * > %n \n Newline + * > %t \t Tab + * > %% % Percent Symbol + */ + $.jqplot.DateAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + this.date = new $.jsDate(); + }; + + $.jqplot.DateAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.DateAxisRenderer.prototype.constructor = $.jqplot.DateAxisRenderer; + + $.jqplot.DateTickFormatter = function(format, val) { + if (!format) { + format = '%Y/%m/%d'; + } + return $.jsDate.strftime(val, format); + }; + + $.jqplot.DateAxisRenderer.prototype.init = function(options){ + // prop: tickRenderer + // A class of a rendering engine for creating the ticks labels displayed on the plot, + // See <$.jqplot.AxisTickRenderer>. + // this.tickRenderer = $.jqplot.AxisTickRenderer; + // this.labelRenderer = $.jqplot.AxisLabelRenderer; + this.tickOptions.formatter = $.jqplot.DateTickFormatter; + this.daTickInterval = null; + this._daTickInterval = null; + + $.extend(true, this, options); + + var db = this._dataBounds, + stats, + sum, + s, + d, + pd, + sd, + intv; + + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + for (var i=0; i<this._series.length; i++) { + stats = {intervals:[], frequencies:{}, sortedIntervals:[], min:null, max:null, mean:null}; + sum = 0; + s = this._series[i]; + d = s.data; + pd = s._plotData; + sd = s._stackData; + intv = 0; + + for (var j=0; j<d.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + d[j][0] = new $.jsDate(d[j][0]).getTime(); + pd[j][0] = new $.jsDate(d[j][0]).getTime(); + sd[j][0] = new $.jsDate(d[j][0]).getTime(); + if ((d[j][0] != null && d[j][0] < db.min) || db.min == null) { + db.min = d[j][0]; + } + if ((d[j][0] != null && d[j][0] > db.max) || db.max == null) { + db.max = d[j][0]; + } + if (j>0) { + intv = Math.abs(d[j][0] - d[j-1][0]); + stats.intervals.push(intv); + if (stats.frequencies.hasOwnProperty(intv)) { + stats.frequencies[intv] += 1; + } + else { + stats.frequencies[intv] = 1; + } + } + sum += intv; + + } + else { + d[j][1] = new $.jsDate(d[j][1]).getTime(); + pd[j][1] = new $.jsDate(d[j][1]).getTime(); + sd[j][1] = new $.jsDate(d[j][1]).getTime(); + if ((d[j][1] != null && d[j][1] < db.min) || db.min == null) { + db.min = d[j][1]; + } + if ((d[j][1] != null && d[j][1] > db.max) || db.max == null) { + db.max = d[j][1]; + } + if (j>0) { + intv = Math.abs(d[j][1] - d[j-1][1]); + stats.intervals.push(intv); + if (stats.frequencies.hasOwnProperty(intv)) { + stats.frequencies[intv] += 1; + } + else { + stats.frequencies[intv] = 1; + } + } + } + sum += intv; + } + + var tempf = 0, + tempn=0; + for (var n in stats.frequencies) { + stats.sortedIntervals.push({interval:n, frequency:stats.frequencies[n]}); + } + stats.sortedIntervals.sort(function(a, b){ + return b.frequency - a.frequency; + }); + + stats.min = $.jqplot.arrayMin(stats.intervals); + stats.max = $.jqplot.arrayMax(stats.intervals); + stats.mean = sum/d.length; + this._intervalStats.push(stats); + stats = sum = s = d = pd = sd = null; + } + db = null; + + }; + + // called with scope of an axis + $.jqplot.DateAxisRenderer.prototype.reset = function() { + this.min = this._min; + this.max = this._max; + this.tickInterval = this._tickInterval; + this.numberTicks = this._numberTicks; + this.daTickInterval = this._daTickInterval; + // this._ticks = this.__ticks; + }; + + $.jqplot.DateAxisRenderer.prototype.createTicks = function() { + // we're are operating on an axis here + var ticks = this._ticks; + var userTicks = this.ticks; + var name = this.name; + // databounds were set on axis initialization. + var db = this._dataBounds; + var iv = this._intervalStats; + var dim, interval; + var min, max; + var pos1, pos2; + var tt, i; + + // if we already have ticks, use them. + // ticks must be in order of increasing value. + + min = ((this.min != null) ? new $.jsDate(this.min).getTime() : db.min); + max = ((this.max != null) ? new $.jsDate(this.max).getTime() : db.max); + + var range = max - min; + + if (userTicks.length) { + // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed + for (i=0; i<userTicks.length; i++){ + var ut = userTicks[i]; + var t = new this.tickRenderer(this.tickOptions); + if (ut.constructor == Array) { + t.value = new $.jsDate(ut[0]).getTime(); + t.label = ut[1]; + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(t.value, this.name); + this._ticks.push(t); + } + + else { + t.value = new $.jsDate(ut).getTime(); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(t.value, this.name); + this._ticks.push(t); + } + } + this.numberTicks = userTicks.length; + this.min = this._ticks[0].value; + this.max = this._ticks[this.numberTicks-1].value; + this.daTickInterval = [(this.max - this.min) / (this.numberTicks - 1)/1000, 'seconds']; + } + + //////// + // We don't have any ticks yet, let's make some! + // Doing complete autoscaling, no user options specified + //////// + + else if (this.tickInterval == null && this.min == null && this.max == null && this.numberTicks == null) { + var ret = $.jqplot.LinearTickGenerator(min, max); + // calculate a padded max and min, points should be less than these + // so that they aren't too close to the edges of the plot. + // User can adjust how much padding is allowed with pad, padMin and PadMax options. + var tumin = min + range*(this.padMin - 1); + var tumax = max - range*(this.padMax - 1); + + if (min <=tumin || max >= tumax) { + tumin = min - range*(this.padMin - 1); + tumax = max + range*(this.padMax - 1); + ret = $.jqplot.LinearTickGenerator(tumin, tumax); + } + + this.min = ret[0]; + this.max = ret[1]; + this.numberTicks = ret[2]; + this.tickInterval = ret[4]; + this.daTickInterval = [this.tickInterval/1000, 'seconds']; + + for (var i=0; i<this.numberTicks; i++){ + var min = new $.jsDate(this.min); + tt = min.add(i*this.daTickInterval[0], this.daTickInterval[1]).getTime(); + var t = new this.tickRenderer(this.tickOptions); + // var t = new $.jqplot.AxisTickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + } + } + + //////// + // Some option(s) specified, work around that. + //////// + + else { + if (name == 'xaxis' || name == 'x2axis') { + dim = this._plotDimensions.width; + } + else { + dim = this._plotDimensions.height; + } + + // if min, max and number of ticks specified, user can't specify interval. + if (this.min != null && this.max != null && this.numberTicks != null) { + this.tickInterval = null; + } + + // if user specified a tick interval, convert to usable. + if (this.tickInterval != null) + { + // if interval is a number or can be converted to one, use it. + // Assume it is in SECONDS!!! + if (Number(this.tickInterval)) { + this.daTickInterval = [Number(this.tickInterval), 'seconds']; + } + // else, parse out something we can build from. + else if (typeof this.tickInterval == "string") { + var parts = this.tickInterval.split(' '); + if (parts.length == 1) { + this.daTickInterval = [1, parts[0]]; + } + else if (parts.length == 2) { + this.daTickInterval = [parts[0], parts[1]]; + } + } + } + + // if min and max are same, space them out a bit + if (min == max) { + var adj = 24*60*60*500; // 1/2 day + min -= adj; + max += adj; + } + + range = max - min; + + var optNumTicks = 2 + parseInt(Math.max(0, dim-100)/100, 10); + + + // Here try to set ticks based on data spacing. + // if (this.min == null && this.max == null && this.numberTicks == null && this.tickInterval == null) { + // // + // } + + + var rmin, rmax; + + rmin = (this.min != null) ? new $.jsDate(this.min).getTime() : min - range/2*(this.padMin - 1); + rmax = (this.max != null) ? new $.jsDate(this.max).getTime() : max + range/2*(this.padMax - 1); + this.min = rmin; + this.max = rmax; + range = this.max - this.min; + + if (this.numberTicks == null){ + // if tickInterval is specified by user, we will ignore computed maximum. + // max will be equal or greater to fit even # of ticks. + if (this.daTickInterval != null) { + var nc = new $.jsDate(this.max).diff(this.min, this.daTickInterval[1], true); + this.numberTicks = Math.ceil(nc/this.daTickInterval[0]) +1; + // this.max = new $.jsDate(this.min).add(this.numberTicks-1, this.daTickInterval[1]).getTime(); + this.max = new $.jsDate(this.min).add((this.numberTicks-1) * this.daTickInterval[0], this.daTickInterval[1]).getTime(); + } + else if (dim > 200) { + this.numberTicks = parseInt(3+(dim-200)/100, 10); + } + else { + this.numberTicks = 2; + } + } + + if (this.daTickInterval == null) { + this.daTickInterval = [range / (this.numberTicks-1)/1000, 'seconds']; + } + for (var i=0; i<this.numberTicks; i++){ + var min = new $.jsDate(this.min); + tt = min.add(i*this.daTickInterval[0], this.daTickInterval[1]).getTime(); + var t = new this.tickRenderer(this.tickOptions); + // var t = new $.jqplot.AxisTickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + } + } + + + if (this._daTickInterval == null) { + this._daTickInterval = this.daTickInterval; + } + }; + +})(jQuery); + diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.dateAxisRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.dateAxisRenderer.min.js new file mode 100644 index 0000000000..e60846a88e --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.dateAxisRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.DateAxisRenderer=function(){a.jqplot.LinearAxisRenderer.call(this);this.date=new a.jsDate()};a.jqplot.DateAxisRenderer.prototype=new a.jqplot.LinearAxisRenderer();a.jqplot.DateAxisRenderer.prototype.constructor=a.jqplot.DateAxisRenderer;a.jqplot.DateTickFormatter=function(b,c){if(!b){b="%Y/%m/%d"}return a.jsDate.strftime(c,b)};a.jqplot.DateAxisRenderer.prototype.init=function(t){this.tickOptions.formatter=a.jqplot.DateTickFormatter;this.daTickInterval=null;this._daTickInterval=null;a.extend(true,this,t);var q=this._dataBounds,g,k,r,l,o,m,b;for(var f=0;f<this._series.length;f++){g={intervals:[],frequencies:{},sortedIntervals:[],min:null,max:null,mean:null};k=0;r=this._series[f];l=r.data;o=r._plotData;m=r._stackData;b=0;for(var e=0;e<l.length;e++){if(this.name=="xaxis"||this.name=="x2axis"){l[e][0]=new a.jsDate(l[e][0]).getTime();o[e][0]=new a.jsDate(l[e][0]).getTime();m[e][0]=new a.jsDate(l[e][0]).getTime();if((l[e][0]!=null&&l[e][0]<q.min)||q.min==null){q.min=l[e][0]}if((l[e][0]!=null&&l[e][0]>q.max)||q.max==null){q.max=l[e][0]}if(e>0){b=Math.abs(l[e][0]-l[e-1][0]);g.intervals.push(b);if(g.frequencies.hasOwnProperty(b)){g.frequencies[b]+=1}else{g.frequencies[b]=1}}k+=b}else{l[e][1]=new a.jsDate(l[e][1]).getTime();o[e][1]=new a.jsDate(l[e][1]).getTime();m[e][1]=new a.jsDate(l[e][1]).getTime();if((l[e][1]!=null&&l[e][1]<q.min)||q.min==null){q.min=l[e][1]}if((l[e][1]!=null&&l[e][1]>q.max)||q.max==null){q.max=l[e][1]}if(e>0){b=Math.abs(l[e][1]-l[e-1][1]);g.intervals.push(b);if(g.frequencies.hasOwnProperty(b)){g.frequencies[b]+=1}else{g.frequencies[b]=1}}}k+=b}var p=0,h=0;for(var c in g.frequencies){g.sortedIntervals.push({interval:c,frequency:g.frequencies[c]})}g.sortedIntervals.sort(function(i,d){return d.frequency-i.frequency});g.min=a.jqplot.arrayMin(g.intervals);g.max=a.jqplot.arrayMax(g.intervals);g.mean=k/l.length;this._intervalStats.push(g);g=k=r=l=o=m=null}q=null};a.jqplot.DateAxisRenderer.prototype.reset=function(){this.min=this._min;this.max=this._max;this.tickInterval=this._tickInterval;this.numberTicks=this._numberTicks;this.daTickInterval=this._daTickInterval};a.jqplot.DateAxisRenderer.prototype.createTicks=function(){var z=this._ticks;var w=this.ticks;var B=this.name;var y=this._dataBounds;var e=this._intervalStats;var q,x;var o,s;var d,c;var b,u;o=((this.min!=null)?new a.jsDate(this.min).getTime():y.min);s=((this.max!=null)?new a.jsDate(this.max).getTime():y.max);var k=s-o;if(w.length){for(u=0;u<w.length;u++){var g=w[u];var j=new this.tickRenderer(this.tickOptions);if(g.constructor==Array){j.value=new a.jsDate(g[0]).getTime();j.label=g[1];if(!this.showTicks){j.showLabel=false;j.showMark=false}else{if(!this.showTickMarks){j.showMark=false}}j.setTick(j.value,this.name);this._ticks.push(j)}else{j.value=new a.jsDate(g).getTime();if(!this.showTicks){j.showLabel=false;j.showMark=false}else{if(!this.showTickMarks){j.showMark=false}}j.setTick(j.value,this.name);this._ticks.push(j)}}this.numberTicks=w.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value;this.daTickInterval=[(this.max-this.min)/(this.numberTicks-1)/1000,"seconds"]}else{if(this.tickInterval==null&&this.min==null&&this.max==null&&this.numberTicks==null){var A=a.jqplot.LinearTickGenerator(o,s);var n=o+k*(this.padMin-1);var r=s-k*(this.padMax-1);if(o<=n||s>=r){n=o-k*(this.padMin-1);r=s+k*(this.padMax-1);A=a.jqplot.LinearTickGenerator(n,r)}this.min=A[0];this.max=A[1];this.numberTicks=A[2];this.tickInterval=A[4];this.daTickInterval=[this.tickInterval/1000,"seconds"];for(var u=0;u<this.numberTicks;u++){var o=new a.jsDate(this.min);b=o.add(u*this.daTickInterval[0],this.daTickInterval[1]).getTime();var j=new this.tickRenderer(this.tickOptions);if(!this.showTicks){j.showLabel=false;j.showMark=false}else{if(!this.showTickMarks){j.showMark=false}}j.setTick(b,this.name);this._ticks.push(j)}}else{if(B=="xaxis"||B=="x2axis"){q=this._plotDimensions.width}else{q=this._plotDimensions.height}if(this.min!=null&&this.max!=null&&this.numberTicks!=null){this.tickInterval=null}if(this.tickInterval!=null){if(Number(this.tickInterval)){this.daTickInterval=[Number(this.tickInterval),"seconds"]}else{if(typeof this.tickInterval=="string"){var l=this.tickInterval.split(" ");if(l.length==1){this.daTickInterval=[1,l[0]]}else{if(l.length==2){this.daTickInterval=[l[0],l[1]]}}}}}if(o==s){var h=24*60*60*500;o-=h;s+=h}k=s-o;var v=2+parseInt(Math.max(0,q-100)/100,10);var m,p;m=(this.min!=null)?new a.jsDate(this.min).getTime():o-k/2*(this.padMin-1);p=(this.max!=null)?new a.jsDate(this.max).getTime():s+k/2*(this.padMax-1);this.min=m;this.max=p;k=this.max-this.min;if(this.numberTicks==null){if(this.daTickInterval!=null){var f=new a.jsDate(this.max).diff(this.min,this.daTickInterval[1],true);this.numberTicks=Math.ceil(f/this.daTickInterval[0])+1;this.max=new a.jsDate(this.min).add((this.numberTicks-1)*this.daTickInterval[0],this.daTickInterval[1]).getTime()}else{if(q>200){this.numberTicks=parseInt(3+(q-200)/100,10)}else{this.numberTicks=2}}}if(this.daTickInterval==null){this.daTickInterval=[k/(this.numberTicks-1)/1000,"seconds"]}for(var u=0;u<this.numberTicks;u++){var o=new a.jsDate(this.min);b=o.add(u*this.daTickInterval[0],this.daTickInterval[1]).getTime();var j=new this.tickRenderer(this.tickOptions);if(!this.showTicks){j.showLabel=false;j.showMark=false}else{if(!this.showTickMarks){j.showMark=false}}j.setTick(b,this.name);this._ticks.push(j)}}}if(this._daTickInterval==null){this._daTickInterval=this.daTickInterval}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.donutRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.donutRenderer.js new file mode 100644 index 0000000000..1003f94cbe --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.donutRenderer.js @@ -0,0 +1,910 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.DonutRenderer + * Plugin renderer to draw a donut chart. + * x values, if present, will be used as slice labels. + * y values give slice size. + * + * To use this renderer, you need to include the + * donut renderer plugin, for example: + * + * > <script type="text/javascript" src="plugins/jqplot.donutRenderer.js"></script> + * + * Properties described here are passed into the $.jqplot function + * as options on the series renderer. For example: + * + * > plot2 = $.jqplot('chart2', [s1, s2], { + * > seriesDefaults: { + * > renderer:$.jqplot.DonutRenderer, + * > rendererOptions:{ + * > sliceMargin: 2, + * > innerDiameter: 110, + * > startAngle: -90 + * > } + * > } + * > }); + * + * A donut plot will trigger events on the plot target + * according to user interaction. All events return the event object, + * the series index, the point (slice) index, and the point data for + * the appropriate slice. + * + * 'jqplotDataMouseOver' - triggered when user mouseing over a slice. + * 'jqplotDataHighlight' - triggered the first time user mouses over a slice, + * if highlighting is enabled. + * 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of + * a highlighted slice. + * 'jqplotDataClick' - triggered when the user clicks on a slice. + * 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if + * the "captureRightClick" option is set to true on the plot. + */ + $.jqplot.DonutRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.DonutRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.DonutRenderer.prototype.constructor = $.jqplot.DonutRenderer; + + // called with scope of a series + $.jqplot.DonutRenderer.prototype.init = function(options, plot) { + // Group: Properties + // + // prop: diameter + // Outer diameter of the donut, auto computed by default + this.diameter = null; + // prop: innerDiameter + // Inner diameter of the donut, auto calculated by default. + // If specified will override thickness value. + this.innerDiameter = null; + // prop: thickness + // thickness of the donut, auto computed by default + // Overridden by if innerDiameter is specified. + this.thickness = null; + // prop: padding + // padding between the donut and plot edges, legend, etc. + this.padding = 20; + // prop: sliceMargin + // angular spacing between donut slices in degrees. + this.sliceMargin = 0; + // prop: ringMargin + // pixel distance between rings, or multiple series in a donut plot. + // null will compute ringMargin based on sliceMargin. + this.ringMargin = null; + // prop: fill + // true or false, wether to fil the slices. + this.fill = true; + // prop: shadowOffset + // offset of the shadow from the slice and offset of + // each succesive stroke of the shadow from the last. + this.shadowOffset = 2; + // prop: shadowAlpha + // transparency of the shadow (0 = transparent, 1 = opaque) + this.shadowAlpha = 0.07; + // prop: shadowDepth + // number of strokes to apply to the shadow, + // each stroke offset shadowOffset from the last. + this.shadowDepth = 5; + // prop: highlightMouseOver + // True to highlight slice when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on a slice. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over a slice. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColors + // an array of colors to use when highlighting a slice. + this.highlightColors = []; + // prop: dataLabels + // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices. + // Defaults to percentage of each pie slice. + this.dataLabels = 'percent'; + // prop: showDataLabels + // true to show data labels on slices. + this.showDataLabels = false; + // prop: dataLabelFormatString + // Format string for data labels. If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage. + this.dataLabelFormatString = null; + // prop: dataLabelThreshold + // Threshhold in percentage (0 - 100) of pie area, below which no label will be displayed. + // This applies to all label types, not just to percentage labels. + this.dataLabelThreshold = 3; + // prop: dataLabelPositionFactor + // A Multiplier (0-1) of the pie radius which controls position of label on slice. + // Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie. + this.dataLabelPositionFactor = 0.4; + // prop: dataLabelNudge + // Number of pixels to slide the label away from (+) or toward (-) the center of the pie. + this.dataLabelNudge = 0; + // prop: startAngle + // Angle to start drawing donut in degrees. + // According to orientation of canvas coordinate system: + // 0 = on the positive x axis + // -90 = on the positive y axis. + // 90 = on the negaive y axis. + // 180 or - 180 = on the negative x axis. + this.startAngle = 0; + this.tickRenderer = $.jqplot.DonutTickRenderer; + // Used as check for conditions where donut shouldn't be drawn. + this._drawData = true; + this._type = 'donut'; + + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (options.highlightMouseDown && options.highlightMouseOver == null) { + options.highlightMouseOver = false; + } + + $.extend(true, this, options); + if (this.diameter != null) { + this.diameter = this.diameter - this.sliceMargin; + } + this._diameter = null; + this._innerDiameter = null; + this._radius = null; + this._innerRadius = null; + this._thickness = null; + // references to the previous series in the plot to properly calculate diameters + // and thicknesses of nested rings. + this._previousSeries = []; + this._numberSeries = 1; + // array of [start,end] angles arrays, one for each slice. In radians. + this._sliceAngles = []; + // index of the currenty highlighted point, if any + this._highlightedPoint = null; + + // set highlight colors if none provided + if (this.highlightColors.length == 0) { + for (var i=0; i<this.seriesColors.length; i++){ + var rgba = $.jqplot.getColorComponents(this.seriesColors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + } + } + + plot.postParseOptionsHooks.addOnce(postParseOptions); + plot.postInitHooks.addOnce(postInit); + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + plot.postDrawHooks.addOnce(postPlotDraw); + + + }; + + $.jqplot.DonutRenderer.prototype.setGridData = function(plot) { + // set gridData property. This will hold angle in radians of each data point. + var stack = []; + var td = []; + var sa = this.startAngle/180*Math.PI; + var tot = 0; + // don't know if we have any valid data yet, so set plot to not draw. + this._drawData = false; + for (var i=0; i<this.data.length; i++){ + if (this.data[i][1] != 0) { + // we have data, O.K. to draw. + this._drawData = true; + } + stack.push(this.data[i][1]); + td.push([this.data[i][0]]); + if (i>0) { + stack[i] += stack[i-1]; + } + tot += this.data[i][1]; + } + var fact = Math.PI*2/stack[stack.length - 1]; + + for (var i=0; i<stack.length; i++) { + td[i][1] = stack[i] * fact; + td[i][2] = this.data[i][1]/tot; + } + this.gridData = td; + }; + + $.jqplot.DonutRenderer.prototype.makeGridData = function(data, plot) { + var stack = []; + var td = []; + var tot = 0; + var sa = this.startAngle/180*Math.PI; + // don't know if we have any valid data yet, so set plot to not draw. + this._drawData = false; + for (var i=0; i<data.length; i++){ + if (this.data[i][1] != 0) { + // we have data, O.K. to draw. + this._drawData = true; + } + stack.push(data[i][1]); + td.push([data[i][0]]); + if (i>0) { + stack[i] += stack[i-1]; + } + tot += data[i][1]; + } + var fact = Math.PI*2/stack[stack.length - 1]; + + for (var i=0; i<stack.length; i++) { + td[i][1] = stack[i] * fact; + td[i][2] = data[i][1]/tot; + } + return td; + }; + + $.jqplot.DonutRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) { + var r = this._diameter / 2; + var ri = r - this._thickness; + var fill = this.fill; + // var lineWidth = this.lineWidth; + ctx.save(); + ctx.translate(this._center[0], this._center[1]); + // ctx.translate(this.sliceMargin*Math.cos((ang1+ang2)/2), this.sliceMargin*Math.sin((ang1+ang2)/2)); + + if (isShadow) { + for (var i=0; i<this.shadowDepth; i++) { + ctx.save(); + ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI)); + doDraw(); + } + } + + else { + doDraw(); + } + + function doDraw () { + // Fix for IE and Chrome that can't seem to draw circles correctly. + // ang2 should always be <= 2 pi since that is the way the data is converted. + if (ang2 > 6.282 + this.startAngle) { + ang2 = 6.282 + this.startAngle; + if (ang1 > ang2) { + ang1 = 6.281 + this.startAngle; + } + } + // Fix for IE, where it can't seem to handle 0 degree angles. Also avoids + // ugly line on unfilled donuts. + if (ang1 >= ang2) { + return; + } + ctx.beginPath(); + ctx.fillStyle = color; + ctx.strokeStyle = color; + // ctx.lineWidth = lineWidth; + ctx.arc(0, 0, r, ang1, ang2, false); + ctx.lineTo(ri*Math.cos(ang2), ri*Math.sin(ang2)); + ctx.arc(0,0, ri, ang2, ang1, true); + ctx.closePath(); + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + } + + if (isShadow) { + for (var i=0; i<this.shadowDepth; i++) { + ctx.restore(); + } + } + + ctx.restore(); + }; + + // called with scope of series + $.jqplot.DonutRenderer.prototype.draw = function (ctx, gd, options, plot) { + var i; + var opts = (options != undefined) ? options : {}; + // offset and direction of offset due to legend placement + var offx = 0; + var offy = 0; + var trans = 1; + // var colorGenerator = new this.colorGenerator(this.seriesColors); + if (options.legendInfo && options.legendInfo.placement == 'insideGrid') { + var li = options.legendInfo; + switch (li.location) { + case 'nw': + offx = li.width + li.xoffset; + break; + case 'w': + offx = li.width + li.xoffset; + break; + case 'sw': + offx = li.width + li.xoffset; + break; + case 'ne': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'e': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'se': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'n': + offy = li.height + li.yoffset; + break; + case 's': + offy = li.height + li.yoffset; + trans = -1; + break; + default: + break; + } + } + + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var cw = ctx.canvas.width; + var ch = ctx.canvas.height; + var w = cw - offx - 2 * this.padding; + var h = ch - offy - 2 * this.padding; + var mindim = Math.min(w,h); + var d = mindim; + var ringmargin = (this.ringMargin == null) ? this.sliceMargin * 2.0 : this.ringMargin; + + for (var i=0; i<this._previousSeries.length; i++) { + d -= 2.0 * this._previousSeries[i]._thickness + 2.0 * ringmargin; + } + this._diameter = this.diameter || d; + if (this.innerDiameter != null) { + var od = (this._numberSeries > 1 && this.index > 0) ? this._previousSeries[0]._diameter : this._diameter; + this._thickness = this.thickness || (od - this.innerDiameter - 2.0*ringmargin*this._numberSeries) / this._numberSeries/2.0; + } + else { + this._thickness = this.thickness || mindim / 2 / (this._numberSeries + 1) * 0.85; + } + + var r = this._radius = this._diameter/2; + this._innerRadius = this._radius - this._thickness; + var sa = this.startAngle / 180 * Math.PI; + this._center = [(cw - trans * offx)/2 + trans * offx, (ch - trans*offy)/2 + trans * offy]; + + if (this.shadow) { + var shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')'; + for (var i=0; i<gd.length; i++) { + var ang1 = (i == 0) ? sa : gd[i-1][1] + sa; + // Adjust ang1 and ang2 for sliceMargin + ang1 += this.sliceMargin/180*Math.PI; + this.renderer.drawSlice.call (this, ctx, ang1, gd[i][1]+sa, shadowColor, true); + } + + } + for (var i=0; i<gd.length; i++) { + var ang1 = (i == 0) ? sa : gd[i-1][1] + sa; + // Adjust ang1 and ang2 for sliceMargin + ang1 += this.sliceMargin/180*Math.PI; + var ang2 = gd[i][1] + sa; + this._sliceAngles.push([ang1, ang2]); + this.renderer.drawSlice.call (this, ctx, ang1, ang2, this.seriesColors[i], false); + + if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) { + var fstr, avgang = (ang1+ang2)/2, label; + + if (this.dataLabels == 'label') { + fstr = this.dataLabelFormatString || '%s'; + label = $.jqplot.sprintf(fstr, gd[i][0]); + } + else if (this.dataLabels == 'value') { + fstr = this.dataLabelFormatString || '%d'; + label = $.jqplot.sprintf(fstr, this.data[i][1]); + } + else if (this.dataLabels == 'percent') { + fstr = this.dataLabelFormatString || '%d%%'; + label = $.jqplot.sprintf(fstr, gd[i][2]*100); + } + else if (this.dataLabels.constructor == Array) { + fstr = this.dataLabelFormatString || '%s'; + label = $.jqplot.sprintf(fstr, this.dataLabels[i]); + } + + var fact = this._innerRadius + this._thickness * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge; + + var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left; + var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top; + + var labelelem = $('<span class="jqplot-donut-series jqplot-data-label" style="position:absolute;">' + label + '</span>').insertBefore(plot.eventCanvas._elem); + x -= labelelem.width()/2; + y -= labelelem.height()/2; + x = Math.round(x); + y = Math.round(y); + labelelem.css({left: x, top: y}); + } + } + + }; + + $.jqplot.DonutAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + }; + + $.jqplot.DonutAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.DonutAxisRenderer.prototype.constructor = $.jqplot.DonutAxisRenderer; + + + // There are no traditional axes on a donut chart. We just need to provide + // dummy objects with properties so the plot will render. + // called with scope of axis object. + $.jqplot.DonutAxisRenderer.prototype.init = function(options){ + // + this.tickRenderer = $.jqplot.DonutTickRenderer; + $.extend(true, this, options); + // I don't think I'm going to need _dataBounds here. + // have to go Axis scaling in a way to fit chart onto plot area + // and provide u2p and p2u functionality for mouse cursor, etc. + // for convienence set _dataBounds to 0 and 100 and + // set min/max to 0 and 100. + this._dataBounds = {min:0, max:100}; + this.min = 0; + this.max = 100; + this.showTicks = false; + this.ticks = []; + this.showMark = false; + this.show = false; + }; + + + + + $.jqplot.DonutLegendRenderer = function(){ + $.jqplot.TableLegendRenderer.call(this); + }; + + $.jqplot.DonutLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); + $.jqplot.DonutLegendRenderer.prototype.constructor = $.jqplot.DonutLegendRenderer; + + /** + * Class: $.jqplot.DonutLegendRenderer + * Legend Renderer specific to donut plots. Set by default + * when user creates a donut plot. + */ + $.jqplot.DonutLegendRenderer.prototype.init = function(options) { + // Group: Properties + // + // prop: numberRows + // Maximum number of rows in the legend. 0 or null for unlimited. + this.numberRows = null; + // prop: numberColumns + // Maximum number of columns in the legend. 0 or null for unlimited. + this.numberColumns = null; + $.extend(true, this, options); + }; + + // called with context of legend + $.jqplot.DonutLegendRenderer.prototype.draw = function() { + var legend = this; + if (this.show) { + var series = this._series; + var ss = 'position:absolute;'; + ss += (this.background) ? 'background:'+this.background+';' : ''; + ss += (this.border) ? 'border:'+this.border+';' : ''; + ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; + ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : ''; + ss += (this.textColor) ? 'color:'+this.textColor+';' : ''; + ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : ''; + ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : ''; + ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : ''; + ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : ''; + this._elem = $('<table class="jqplot-table-legend" style="'+ss+'"></table>'); + // Donut charts legends don't go by number of series, but by number of data points + // in the series. Refactor things here for that. + + var pad = false, + reverse = false, + nr, nc; + var s = series[0]; + var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors); + + if (s.show) { + var pd = s.data; + if (this.numberRows) { + nr = this.numberRows; + if (!this.numberColumns){ + nc = Math.ceil(pd.length/nr); + } + else{ + nc = this.numberColumns; + } + } + else if (this.numberColumns) { + nc = this.numberColumns; + nr = Math.ceil(pd.length/this.numberColumns); + } + else { + nr = pd.length; + nc = 1; + } + + var i, j, tr, td1, td2, lt, rs, color; + var idx = 0; + + for (i=0; i<nr; i++) { + if (reverse){ + tr = $('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem); + } + else{ + tr = $('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem); + } + for (j=0; j<nc; j++) { + if (idx < pd.length){ + lt = this.labels[idx] || pd[idx][0].toString(); + color = colorGenerator.next(); + if (!reverse){ + if (i>0){ + pad = true; + } + else{ + pad = false; + } + } + else{ + if (i == nr -1){ + pad = false; + } + else{ + pad = true; + } + } + rs = (pad) ? this.rowSpacing : '0'; + + td1 = $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+ + '<div><div class="jqplot-table-legend-swatch" style="border-color:'+color+';"></div>'+ + '</div></td>'); + td2 = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>'); + if (this.escapeHtml){ + td2.text(lt); + } + else { + td2.html(lt); + } + if (reverse) { + td2.prependTo(tr); + td1.prependTo(tr); + } + else { + td1.appendTo(tr); + td2.appendTo(tr); + } + pad = true; + } + idx++; + } + } + } + } + return this._elem; + }; + + // $.jqplot.DonutLegendRenderer.prototype.pack = function(offsets) { + // if (this.show) { + // // fake a grid for positioning + // var grid = {_top:offsets.top, _left:offsets.left, _right:offsets.right, _bottom:this._plotDimensions.height - offsets.bottom}; + // if (this.placement == 'insideGrid') { + // switch (this.location) { + // case 'nw': + // var a = grid._left + this.xoffset; + // var b = grid._top + this.yoffset; + // this._elem.css('left', a); + // this._elem.css('top', b); + // break; + // case 'n': + // var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + // var b = grid._top + this.yoffset; + // this._elem.css('left', a); + // this._elem.css('top', b); + // break; + // case 'ne': + // var a = offsets.right + this.xoffset; + // var b = grid._top + this.yoffset; + // this._elem.css({right:a, top:b}); + // break; + // case 'e': + // var a = offsets.right + this.xoffset; + // var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + // this._elem.css({right:a, top:b}); + // break; + // case 'se': + // var a = offsets.right + this.xoffset; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({right:a, bottom:b}); + // break; + // case 's': + // var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({left:a, bottom:b}); + // break; + // case 'sw': + // var a = grid._left + this.xoffset; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({left:a, bottom:b}); + // break; + // case 'w': + // var a = grid._left + this.xoffset; + // var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + // this._elem.css({left:a, top:b}); + // break; + // default: // same as 'se' + // var a = grid._right - this.xoffset; + // var b = grid._bottom + this.yoffset; + // this._elem.css({right:a, bottom:b}); + // break; + // } + // + // } + // else { + // switch (this.location) { + // case 'nw': + // var a = this._plotDimensions.width - grid._left + this.xoffset; + // var b = grid._top + this.yoffset; + // this._elem.css('right', a); + // this._elem.css('top', b); + // break; + // case 'n': + // var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + // var b = this._plotDimensions.height - grid._top + this.yoffset; + // this._elem.css('left', a); + // this._elem.css('bottom', b); + // break; + // case 'ne': + // var a = this._plotDimensions.width - offsets.right + this.xoffset; + // var b = grid._top + this.yoffset; + // this._elem.css({left:a, top:b}); + // break; + // case 'e': + // var a = this._plotDimensions.width - offsets.right + this.xoffset; + // var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + // this._elem.css({left:a, top:b}); + // break; + // case 'se': + // var a = this._plotDimensions.width - offsets.right + this.xoffset; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({left:a, bottom:b}); + // break; + // case 's': + // var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + // var b = this._plotDimensions.height - offsets.bottom + this.yoffset; + // this._elem.css({left:a, top:b}); + // break; + // case 'sw': + // var a = this._plotDimensions.width - grid._left + this.xoffset; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({right:a, bottom:b}); + // break; + // case 'w': + // var a = this._plotDimensions.width - grid._left + this.xoffset; + // var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + // this._elem.css({right:a, top:b}); + // break; + // default: // same as 'se' + // var a = grid._right - this.xoffset; + // var b = grid._bottom + this.yoffset; + // this._elem.css({right:a, bottom:b}); + // break; + // } + // } + // } + // }; + + // setup default renderers for axes and legend so user doesn't have to + // called with scope of plot + function preInit(target, data, options) { + options = options || {}; + options.axesDefaults = options.axesDefaults || {}; + options.legend = options.legend || {}; + options.seriesDefaults = options.seriesDefaults || {}; + // only set these if there is a donut series + var setopts = false; + if (options.seriesDefaults.renderer == $.jqplot.DonutRenderer) { + setopts = true; + } + else if (options.series) { + for (var i=0; i < options.series.length; i++) { + if (options.series[i].renderer == $.jqplot.DonutRenderer) { + setopts = true; + } + } + } + + if (setopts) { + options.axesDefaults.renderer = $.jqplot.DonutAxisRenderer; + options.legend.renderer = $.jqplot.DonutLegendRenderer; + options.legend.preDraw = true; + options.seriesDefaults.pointLabels = {show: false}; + } + } + + // called with scope of plot. + function postInit(target, data, options) { + // if multiple series, add a reference to the previous one so that + // donut rings can nest. + for (var i=1; i<this.series.length; i++) { + if (!this.series[i]._previousSeries.length){ + for (var j=0; j<i; j++) { + if (this.series[i].renderer.constructor == $.jqplot.DonutRenderer && this.series[j].renderer.constructor == $.jqplot.DonutRenderer) { + this.series[i]._previousSeries.push(this.series[j]); + } + } + } + } + for (i=0; i<this.series.length; i++) { + if (this.series[i].renderer.constructor == $.jqplot.DonutRenderer) { + this.series[i]._numberSeries = this.series.length; + // don't allow mouseover and mousedown at same time. + if (this.series[i].highlightMouseOver) { + this.series[i].highlightMouseDown = false; + } + } + } + this.target.bind('mouseout', {plot:this}, function (ev) { unhighlight(ev.data.plot); }); + } + + var postParseOptionsRun = false; + // called with scope of plot + function postParseOptions(options) { + for (var i=0; i<this.series.length; i++) { + this.series[i].seriesColors = this.seriesColors; + this.series[i].colorGenerator = this.colorGenerator; + } + } + + function highlight (plot, sidx, pidx) { + var s = plot.series[sidx]; + var canvas = plot.plugins.donutRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.donutRenderer.highlightedSeriesIndex = sidx; + s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColors[pidx], false); + } + + function unhighlight (plot) { + var canvas = plot.plugins.donutRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.donutRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + } + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.donutRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt = jQuery.Event('jqplotDataClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var idx = plot.plugins.donutRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.donutRenderer && this.plugins.donutRenderer.highlightCanvas) { + this.plugins.donutRenderer.highlightCanvas.resetCanvas(); + this.plugins.donutRenderer.highlightCanvas = null; + } + + this.plugins.donutRenderer = {highlightedSeriesIndex:null}; + this.plugins.donutRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + // do we have any data labels? if so, put highlight canvas before those + // Fix for broken jquery :first selector with canvas (VML) elements. + var labels = $(this.targetId+' .jqplot-data-label'); + if (labels.length) { + $(labels[0]).before(this.plugins.donutRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-donutRenderer-highlight-canvas', this._plotDimensions, this)); + } + // else put highlight canvas before event canvas. + else { + this.eventCanvas._elem.before(this.plugins.donutRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-donutRenderer-highlight-canvas', this._plotDimensions, this)); + } + var hctx = this.plugins.donutRenderer.highlightCanvas.setContext(); + } + + $.jqplot.preInitHooks.push(preInit); + + $.jqplot.DonutTickRenderer = function() { + $.jqplot.AxisTickRenderer.call(this); + }; + + $.jqplot.DonutTickRenderer.prototype = new $.jqplot.AxisTickRenderer(); + $.jqplot.DonutTickRenderer.prototype.constructor = $.jqplot.DonutTickRenderer; + +})(jQuery); + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.donutRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.donutRenderer.min.js new file mode 100644 index 0000000000..c9095f15be --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.donutRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(e){e.jqplot.DonutRenderer=function(){e.jqplot.LineRenderer.call(this)};e.jqplot.DonutRenderer.prototype=new e.jqplot.LineRenderer();e.jqplot.DonutRenderer.prototype.constructor=e.jqplot.DonutRenderer;e.jqplot.DonutRenderer.prototype.init=function(p,t){this.diameter=null;this.innerDiameter=null;this.thickness=null;this.padding=20;this.sliceMargin=0;this.ringMargin=null;this.fill=true;this.shadowOffset=2;this.shadowAlpha=0.07;this.shadowDepth=5;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.dataLabels="percent";this.showDataLabels=false;this.dataLabelFormatString=null;this.dataLabelThreshold=3;this.dataLabelPositionFactor=0.4;this.dataLabelNudge=0;this.startAngle=0;this.tickRenderer=e.jqplot.DonutTickRenderer;this._drawData=true;this._type="donut";if(p.highlightMouseDown&&p.highlightMouseOver==null){p.highlightMouseOver=false}e.extend(true,this,p);if(this.diameter!=null){this.diameter=this.diameter-this.sliceMargin}this._diameter=null;this._innerDiameter=null;this._radius=null;this._innerRadius=null;this._thickness=null;this._previousSeries=[];this._numberSeries=1;this._sliceAngles=[];this._highlightedPoint=null;if(this.highlightColors.length==0){for(var r=0;r<this.seriesColors.length;r++){var q=e.jqplot.getColorComponents(this.seriesColors[r]);var n=[q[0],q[1],q[2]];var s=n[0]+n[1]+n[2];for(var o=0;o<3;o++){n[o]=(s>570)?n[o]*0.8:n[o]+0.3*(255-n[o]);n[o]=parseInt(n[o],10)}this.highlightColors.push("rgb("+n[0]+","+n[1]+","+n[2]+")")}}t.postParseOptionsHooks.addOnce(l);t.postInitHooks.addOnce(g);t.eventListenerHooks.addOnce("jqplotMouseMove",b);t.eventListenerHooks.addOnce("jqplotMouseDown",a);t.eventListenerHooks.addOnce("jqplotMouseUp",j);t.eventListenerHooks.addOnce("jqplotClick",f);t.eventListenerHooks.addOnce("jqplotRightClick",m);t.postDrawHooks.addOnce(h)};e.jqplot.DonutRenderer.prototype.setGridData=function(s){var o=[];var t=[];var n=this.startAngle/180*Math.PI;var r=0;this._drawData=false;for(var q=0;q<this.data.length;q++){if(this.data[q][1]!=0){this._drawData=true}o.push(this.data[q][1]);t.push([this.data[q][0]]);if(q>0){o[q]+=o[q-1]}r+=this.data[q][1]}var p=Math.PI*2/o[o.length-1];for(var q=0;q<o.length;q++){t[q][1]=o[q]*p;t[q][2]=this.data[q][1]/r}this.gridData=t};e.jqplot.DonutRenderer.prototype.makeGridData=function(s,t){var o=[];var u=[];var r=0;var n=this.startAngle/180*Math.PI;this._drawData=false;for(var q=0;q<s.length;q++){if(this.data[q][1]!=0){this._drawData=true}o.push(s[q][1]);u.push([s[q][0]]);if(q>0){o[q]+=o[q-1]}r+=s[q][1]}var p=Math.PI*2/o[o.length-1];for(var q=0;q<o.length;q++){u[q][1]=o[q]*p;u[q][2]=s[q][1]/r}return u};e.jqplot.DonutRenderer.prototype.drawSlice=function(x,u,t,p,s){var n=this._diameter/2;var v=n-this._thickness;var w=this.fill;x.save();x.translate(this._center[0],this._center[1]);if(s){for(var q=0;q<this.shadowDepth;q++){x.save();x.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI),this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));o()}}else{o()}function o(){if(t>6.282+this.startAngle){t=6.282+this.startAngle;if(u>t){u=6.281+this.startAngle}}if(u>=t){return}x.beginPath();x.fillStyle=p;x.strokeStyle=p;x.arc(0,0,n,u,t,false);x.lineTo(v*Math.cos(t),v*Math.sin(t));x.arc(0,0,v,t,u,true);x.closePath();if(w){x.fill()}else{x.stroke()}}if(s){for(var q=0;q<this.shadowDepth;q++){x.restore()}}x.restore()};e.jqplot.DonutRenderer.prototype.draw=function(N,V,t,P){var Q;var J=(t!=undefined)?t:{};var q=0;var p=0;var u=1;if(t.legendInfo&&t.legendInfo.placement=="insideGrid"){var I=t.legendInfo;switch(I.location){case"nw":q=I.width+I.xoffset;break;case"w":q=I.width+I.xoffset;break;case"sw":q=I.width+I.xoffset;break;case"ne":q=I.width+I.xoffset;u=-1;break;case"e":q=I.width+I.xoffset;u=-1;break;case"se":q=I.width+I.xoffset;u=-1;break;case"n":p=I.height+I.yoffset;break;case"s":p=I.height+I.yoffset;u=-1;break;default:break}}var B=(J.shadow!=undefined)?J.shadow:this.shadow;var W=(J.showLine!=undefined)?J.showLine:this.showLine;var O=(J.fill!=undefined)?J.fill:this.fill;var s=N.canvas.width;var H=N.canvas.height;var G=s-q-2*this.padding;var R=H-p-2*this.padding;var v=Math.min(G,R);var T=v;var X=(this.ringMargin==null)?this.sliceMargin*2:this.ringMargin;for(var Q=0;Q<this._previousSeries.length;Q++){T-=2*this._previousSeries[Q]._thickness+2*X}this._diameter=this.diameter||T;if(this.innerDiameter!=null){var M=(this._numberSeries>1&&this.index>0)?this._previousSeries[0]._diameter:this._diameter;this._thickness=this.thickness||(M-this.innerDiameter-2*X*this._numberSeries)/this._numberSeries/2}else{this._thickness=this.thickness||v/2/(this._numberSeries+1)*0.85}var K=this._radius=this._diameter/2;this._innerRadius=this._radius-this._thickness;var o=this.startAngle/180*Math.PI;this._center=[(s-u*q)/2+u*q,(H-u*p)/2+u*p];if(this.shadow){var L="rgba(0,0,0,"+this.shadowAlpha+")";for(var Q=0;Q<V.length;Q++){var A=(Q==0)?o:V[Q-1][1]+o;A+=this.sliceMargin/180*Math.PI;this.renderer.drawSlice.call(this,N,A,V[Q][1]+o,L,true)}}for(var Q=0;Q<V.length;Q++){var A=(Q==0)?o:V[Q-1][1]+o;A+=this.sliceMargin/180*Math.PI;var z=V[Q][1]+o;this._sliceAngles.push([A,z]);this.renderer.drawSlice.call(this,N,A,z,this.seriesColors[Q],false);if(this.showDataLabels&&V[Q][2]*100>=this.dataLabelThreshold){var S,U=(A+z)/2,C;if(this.dataLabels=="label"){S=this.dataLabelFormatString||"%s";C=e.jqplot.sprintf(S,V[Q][0])}else{if(this.dataLabels=="value"){S=this.dataLabelFormatString||"%d";C=e.jqplot.sprintf(S,this.data[Q][1])}else{if(this.dataLabels=="percent"){S=this.dataLabelFormatString||"%d%%";C=e.jqplot.sprintf(S,V[Q][2]*100)}else{if(this.dataLabels.constructor==Array){S=this.dataLabelFormatString||"%s";C=e.jqplot.sprintf(S,this.dataLabels[Q])}}}}var n=this._innerRadius+this._thickness*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var F=this._center[0]+Math.cos(U)*n+this.canvas._offsets.left;var E=this._center[1]+Math.sin(U)*n+this.canvas._offsets.top;var D=e('<span class="jqplot-donut-series jqplot-data-label" style="position:absolute;">'+C+"</span>").insertBefore(P.eventCanvas._elem);F-=D.width()/2;E-=D.height()/2;F=Math.round(F);E=Math.round(E);D.css({left:F,top:E})}}};e.jqplot.DonutAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.DonutAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.DonutAxisRenderer.prototype.constructor=e.jqplot.DonutAxisRenderer;e.jqplot.DonutAxisRenderer.prototype.init=function(n){this.tickRenderer=e.jqplot.DonutTickRenderer;e.extend(true,this,n);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.DonutLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.DonutLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.DonutLegendRenderer.prototype.constructor=e.jqplot.DonutLegendRenderer;e.jqplot.DonutLegendRenderer.prototype.init=function(n){this.numberRows=null;this.numberColumns=null;e.extend(true,this,n)};e.jqplot.DonutLegendRenderer.prototype.draw=function(){var q=this;if(this.show){var y=this._series;var B="position:absolute;";B+=(this.background)?"background:"+this.background+";":"";B+=(this.border)?"border:"+this.border+";":"";B+=(this.fontSize)?"font-size:"+this.fontSize+";":"";B+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";B+=(this.textColor)?"color:"+this.textColor+";":"";B+=(this.marginTop!=null)?"margin-top:"+this.marginTop+";":"";B+=(this.marginBottom!=null)?"margin-bottom:"+this.marginBottom+";":"";B+=(this.marginLeft!=null)?"margin-left:"+this.marginLeft+";":"";B+=(this.marginRight!=null)?"margin-right:"+this.marginRight+";":"";this._elem=e('<table class="jqplot-table-legend" style="'+B+'"></table>');var F=false,x=false,n,v;var z=y[0];var o=new e.jqplot.ColorGenerator(z.seriesColors);if(z.show){var G=z.data;if(this.numberRows){n=this.numberRows;if(!this.numberColumns){v=Math.ceil(G.length/n)}else{v=this.numberColumns}}else{if(this.numberColumns){v=this.numberColumns;n=Math.ceil(G.length/this.numberColumns)}else{n=G.length;v=1}}var E,D,p,t,r,u,w,C;var A=0;for(E=0;E<n;E++){if(x){p=e('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem)}else{p=e('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem)}for(D=0;D<v;D++){if(A<G.length){u=this.labels[A]||G[A][0].toString();C=o.next();if(!x){if(E>0){F=true}else{F=false}}else{if(E==n-1){F=false}else{F=true}}w=(F)?this.rowSpacing:"0";t=e('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+w+';"><div><div class="jqplot-table-legend-swatch" style="border-color:'+C+';"></div></div></td>');r=e('<td class="jqplot-table-legend" style="padding-top:'+w+';"></td>');if(this.escapeHtml){r.text(u)}else{r.html(u)}if(x){r.prependTo(p);t.prependTo(p)}else{t.appendTo(p);r.appendTo(p)}F=true}A++}}}}return this._elem};function c(r,q,o){o=o||{};o.axesDefaults=o.axesDefaults||{};o.legend=o.legend||{};o.seriesDefaults=o.seriesDefaults||{};var n=false;if(o.seriesDefaults.renderer==e.jqplot.DonutRenderer){n=true}else{if(o.series){for(var p=0;p<o.series.length;p++){if(o.series[p].renderer==e.jqplot.DonutRenderer){n=true}}}}if(n){o.axesDefaults.renderer=e.jqplot.DonutAxisRenderer;o.legend.renderer=e.jqplot.DonutLegendRenderer;o.legend.preDraw=true;o.seriesDefaults.pointLabels={show:false}}}function g(r,q,o){for(var p=1;p<this.series.length;p++){if(!this.series[p]._previousSeries.length){for(var n=0;n<p;n++){if(this.series[p].renderer.constructor==e.jqplot.DonutRenderer&&this.series[n].renderer.constructor==e.jqplot.DonutRenderer){this.series[p]._previousSeries.push(this.series[n])}}}}for(p=0;p<this.series.length;p++){if(this.series[p].renderer.constructor==e.jqplot.DonutRenderer){this.series[p]._numberSeries=this.series.length;if(this.series[p].highlightMouseOver){this.series[p].highlightMouseDown=false}}}this.target.bind("mouseout",{plot:this},function(s){i(s.data.plot)})}var k=false;function l(n){for(var o=0;o<this.series.length;o++){this.series[o].seriesColors=this.seriesColors;this.series[o].colorGenerator=this.colorGenerator}}function d(r,q,p){var o=r.series[q];var n=r.plugins.donutRenderer.highlightCanvas;n._ctx.clearRect(0,0,n._ctx.canvas.width,n._ctx.canvas.height);o._highlightedPoint=p;r.plugins.donutRenderer.highlightedSeriesIndex=q;o.renderer.drawSlice.call(o,n._ctx,o._sliceAngles[p][0],o._sliceAngles[p][1],o.highlightColors[p],false)}function i(p){var n=p.plugins.donutRenderer.highlightCanvas;n._ctx.clearRect(0,0,n._ctx.canvas.width,n._ctx.canvas.height);for(var o=0;o<p.series.length;o++){p.series[o]._highlightedPoint=null}p.plugins.donutRenderer.highlightedSeriesIndex=null;p.target.trigger("jqplotDataUnhighlight")}function b(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];var o=jQuery.Event("jqplotDataMouseOver");o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p);if(s.series[p[0]].highlightMouseOver&&!(p[0]==s.plugins.donutRenderer.highlightedSeriesIndex&&p[1]==s.series[p[0]]._highlightedPoint)){var n=jQuery.Event("jqplotDataHighlight");n.pageX=r.pageX;n.pageY=r.pageY;s.target.trigger(n,p);d(s,p[0],p[1])}}else{if(t==null){i(s)}}}function a(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];if(r.series[o[0]].highlightMouseDown&&!(o[0]==r.plugins.donutRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){var n=jQuery.Event("jqplotDataHighlight");n.pageX=q.pageX;n.pageY=q.pageY;r.target.trigger(n,o);d(r,o[0],o[1])}}else{if(s==null){i(r)}}}function j(p,o,s,r,q){var n=q.plugins.donutRenderer.highlightedSeriesIndex;if(n!=null&&q.series[n].highlightMouseDown){i(q)}}function f(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];var n=jQuery.Event("jqplotDataClick");n.pageX=q.pageX;n.pageY=q.pageY;r.target.trigger(n,o)}}function m(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];var n=s.plugins.donutRenderer.highlightedSeriesIndex;if(n!=null&&s.series[n].highlightMouseDown){i(s)}var o=jQuery.Event("jqplotDataRightClick");o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p)}}function h(){if(this.plugins.donutRenderer&&this.plugins.donutRenderer.highlightCanvas){this.plugins.donutRenderer.highlightCanvas.resetCanvas();this.plugins.donutRenderer.highlightCanvas=null}this.plugins.donutRenderer={highlightedSeriesIndex:null};this.plugins.donutRenderer.highlightCanvas=new e.jqplot.GenericCanvas();var o=e(this.targetId+" .jqplot-data-label");if(o.length){e(o[0]).before(this.plugins.donutRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-donutRenderer-highlight-canvas",this._plotDimensions,this))}else{this.eventCanvas._elem.before(this.plugins.donutRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-donutRenderer-highlight-canvas",this._plotDimensions,this))}var n=this.plugins.donutRenderer.highlightCanvas.setContext()}e.jqplot.preInitHooks.push(c);e.jqplot.DonutTickRenderer=function(){e.jqplot.AxisTickRenderer.call(this)};e.jqplot.DonutTickRenderer.prototype=new e.jqplot.AxisTickRenderer();e.jqplot.DonutTickRenderer.prototype.constructor=e.jqplot.DonutTickRenderer})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.dragable.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.dragable.js new file mode 100644 index 0000000000..2a473d008f --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.dragable.js @@ -0,0 +1,224 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + + /** + * Class: $.jqplot.Dragable + * Plugin to make plotted points dragable by the user. + */ + $.jqplot.Dragable = function(options) { + // Group: Properties + this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false}); + this.shapeRenderer = new $.jqplot.ShapeRenderer(); + this.isDragging = false; + this.isOver = false; + this._ctx; + this._elem; + this._point; + this._gridData; + // prop: color + // CSS color spec for the dragged point (and adjacent line segment or bar). + this.color; + // prop: constrainTo + // Constrain dragging motion to an axis or to none. + // Allowable values are 'none', 'x', 'y' + this.constrainTo = 'none'; // 'x', 'y', or 'none'; + $.extend(true, this, options); + }; + + function DragCanvas() { + $.jqplot.GenericCanvas.call(this); + this.isDragging = false; + this.isOver = false; + this._neighbor; + this._cursors = []; + } + + DragCanvas.prototype = new $.jqplot.GenericCanvas(); + DragCanvas.prototype.constructor = DragCanvas; + + + // called within scope of series + $.jqplot.Dragable.parseOptions = function (defaults, opts) { + var options = opts || {}; + this.plugins.dragable = new $.jqplot.Dragable(options.dragable); + // since this function is called before series options are parsed, + // we can set this here and it will be overridden if needed. + this.isDragable = $.jqplot.config.enablePlugins; + }; + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + // add a new DragCanvas object to the plot plugins to handle drawing on this new canvas. + $.jqplot.Dragable.postPlotDraw = function() { + // Memory Leaks patch + if (this.plugins.dragable && this.plugins.dragable.highlightCanvas) { + this.plugins.dragable.highlightCanvas.resetCanvas(); + this.plugins.dragable.highlightCanvas = null; + } + + this.plugins.dragable = {previousCursor:'auto', isOver:false}; + this.plugins.dragable.dragCanvas = new DragCanvas(); + + this.eventCanvas._elem.before(this.plugins.dragable.dragCanvas.createElement(this._gridPadding, 'jqplot-dragable-canvas', this._plotDimensions, this)); + var dctx = this.plugins.dragable.dragCanvas.setContext(); + }; + + //$.jqplot.preInitHooks.push($.jqplot.Dragable.init); + $.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Dragable.parseOptions); + $.jqplot.postDrawHooks.push($.jqplot.Dragable.postPlotDraw); + $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]); + $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleDown]); + $.jqplot.eventListenerHooks.push(['jqplotMouseUp', handleUp]); + + + function initDragPoint(plot, neighbor) { + var s = plot.series[neighbor.seriesIndex]; + var drag = s.plugins.dragable; + + // first, init the mark renderer for the dragged point + var smr = s.markerRenderer; + var mr = drag.markerRenderer; + mr.style = smr.style; + mr.lineWidth = smr.lineWidth + 2.5; + mr.size = smr.size + 5; + if (!drag.color) { + var rgba = $.jqplot.getColorComponents(smr.color); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var alpha = (rgba[3] >= 0.6) ? rgba[3]*0.6 : rgba[3]*(2-rgba[3]); + drag.color = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+alpha+')'; + } + mr.color = drag.color; + mr.init(); + + var start = (neighbor.pointIndex > 0) ? neighbor.pointIndex - 1 : 0; + var end = neighbor.pointIndex+2; + drag._gridData = s.gridData.slice(start, end); + } + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (plot.plugins.dragable.dragCanvas.isDragging) { + var dc = plot.plugins.dragable.dragCanvas; + var dp = dc._neighbor; + var s = plot.series[dp.seriesIndex]; + var drag = s.plugins.dragable; + var gd = s.gridData; + + // compute the new grid position with any constraints. + var x = (drag.constrainTo == 'y') ? dp.gridData[0] : gridpos.x; + var y = (drag.constrainTo == 'x') ? dp.gridData[1] : gridpos.y; + + // compute data values for any listeners. + var xu = s._xaxis.series_p2u(x); + var yu = s._yaxis.series_p2u(y); + + // clear the canvas then redraw effect at new position. + var ctx = dc._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + + // adjust our gridData for the new mouse position + if (dp.pointIndex > 0) { + drag._gridData[1] = [x, y]; + } + else { + drag._gridData[0] = [x, y]; + } + plot.series[dp.seriesIndex].draw(dc._ctx, {gridData:drag._gridData, shadow:false, preventJqPlotSeriesDrawTrigger:true, color:drag.color, markerOptions:{color:drag.color, shadow:false}, trendline:{show:false}}); + plot.target.trigger('jqplotSeriesPointChange', [dp.seriesIndex, dp.pointIndex, [xu,yu], [x,y]]); + } + else if (neighbor != null) { + var series = plot.series[neighbor.seriesIndex]; + if (series.isDragable) { + var dc = plot.plugins.dragable.dragCanvas; + if (!dc.isOver) { + dc._cursors.push(ev.target.style.cursor); + ev.target.style.cursor = "pointer"; + } + dc.isOver = true; + } + } + else if (neighbor == null) { + var dc = plot.plugins.dragable.dragCanvas; + if (dc.isOver) { + ev.target.style.cursor = dc._cursors.pop(); + dc.isOver = false; + } + } + } + + function handleDown(ev, gridpos, datapos, neighbor, plot) { + var dc = plot.plugins.dragable.dragCanvas; + dc._cursors.push(ev.target.style.cursor); + if (neighbor != null) { + var s = plot.series[neighbor.seriesIndex]; + var drag = s.plugins.dragable; + if (s.isDragable && !dc.isDragging) { + dc._neighbor = neighbor; + dc.isDragging = true; + initDragPoint(plot, neighbor); + drag.markerRenderer.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], dc._ctx); + ev.target.style.cursor = "move"; + plot.target.trigger('jqplotDragStart', [neighbor.seriesIndex, neighbor.pointIndex, gridpos, datapos]); + } + } + // Just in case of a hickup, we'll clear the drag canvas and reset. + else { + var ctx = dc._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + dc.isDragging = false; + } + } + + function handleUp(ev, gridpos, datapos, neighbor, plot) { + if (plot.plugins.dragable.dragCanvas.isDragging) { + var dc = plot.plugins.dragable.dragCanvas; + // clear the canvas + var ctx = dc._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + dc.isDragging = false; + // redraw the series canvas at the new point. + var dp = dc._neighbor; + var s = plot.series[dp.seriesIndex]; + var drag = s.plugins.dragable; + // compute the new grid position with any constraints. + var x = (drag.constrainTo == 'y') ? dp.data[0] : datapos[s.xaxis]; + var y = (drag.constrainTo == 'x') ? dp.data[1] : datapos[s.yaxis]; + // var x = datapos[s.xaxis]; + // var y = datapos[s.yaxis]; + s.data[dp.pointIndex][0] = x; + s.data[dp.pointIndex][1] = y; + plot.drawSeries({preventJqPlotSeriesDrawTrigger:true}, dp.seriesIndex); + dc._neighbor = null; + ev.target.style.cursor = dc._cursors.pop(); + plot.target.trigger('jqplotDragStop', [gridpos, datapos]); + } + } +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.dragable.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.dragable.min.js new file mode 100644 index 0000000000..480d9a3379 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.dragable.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(d){d.jqplot.Dragable=function(g){this.markerRenderer=new d.jqplot.MarkerRenderer({shadow:false});this.shapeRenderer=new d.jqplot.ShapeRenderer();this.isDragging=false;this.isOver=false;this._ctx;this._elem;this._point;this._gridData;this.color;this.constrainTo="none";d.extend(true,this,g)};function b(){d.jqplot.GenericCanvas.call(this);this.isDragging=false;this.isOver=false;this._neighbor;this._cursors=[]}b.prototype=new d.jqplot.GenericCanvas();b.prototype.constructor=b;d.jqplot.Dragable.parseOptions=function(i,h){var g=h||{};this.plugins.dragable=new d.jqplot.Dragable(g.dragable);this.isDragable=d.jqplot.config.enablePlugins};d.jqplot.Dragable.postPlotDraw=function(){if(this.plugins.dragable&&this.plugins.dragable.highlightCanvas){this.plugins.dragable.highlightCanvas.resetCanvas();this.plugins.dragable.highlightCanvas=null}this.plugins.dragable={previousCursor:"auto",isOver:false};this.plugins.dragable.dragCanvas=new b();this.eventCanvas._elem.before(this.plugins.dragable.dragCanvas.createElement(this._gridPadding,"jqplot-dragable-canvas",this._plotDimensions,this));var g=this.plugins.dragable.dragCanvas.setContext()};d.jqplot.preParseSeriesOptionsHooks.push(d.jqplot.Dragable.parseOptions);d.jqplot.postDrawHooks.push(d.jqplot.Dragable.postPlotDraw);d.jqplot.eventListenerHooks.push(["jqplotMouseMove",e]);d.jqplot.eventListenerHooks.push(["jqplotMouseDown",c]);d.jqplot.eventListenerHooks.push(["jqplotMouseUp",a]);function f(n,p){var q=n.series[p.seriesIndex];var m=q.plugins.dragable;var h=q.markerRenderer;var i=m.markerRenderer;i.style=h.style;i.lineWidth=h.lineWidth+2.5;i.size=h.size+5;if(!m.color){var l=d.jqplot.getColorComponents(h.color);var o=[l[0],l[1],l[2]];var k=(l[3]>=0.6)?l[3]*0.6:l[3]*(2-l[3]);m.color="rgba("+o[0]+","+o[1]+","+o[2]+","+k+")"}i.color=m.color;i.init();var g=(p.pointIndex>0)?p.pointIndex-1:0;var j=p.pointIndex+2;m._gridData=q.gridData.slice(g,j)}function e(o,l,h,t,m){if(m.plugins.dragable.dragCanvas.isDragging){var u=m.plugins.dragable.dragCanvas;var i=u._neighbor;var w=m.series[i.seriesIndex];var k=w.plugins.dragable;var r=w.gridData;var p=(k.constrainTo=="y")?i.gridData[0]:l.x;var n=(k.constrainTo=="x")?i.gridData[1]:l.y;var g=w._xaxis.series_p2u(p);var q=w._yaxis.series_p2u(n);var v=u._ctx;v.clearRect(0,0,v.canvas.width,v.canvas.height);if(i.pointIndex>0){k._gridData[1]=[p,n]}else{k._gridData[0]=[p,n]}m.series[i.seriesIndex].draw(u._ctx,{gridData:k._gridData,shadow:false,preventJqPlotSeriesDrawTrigger:true,color:k.color,markerOptions:{color:k.color,shadow:false},trendline:{show:false}});m.target.trigger("jqplotSeriesPointChange",[i.seriesIndex,i.pointIndex,[g,q],[p,n]])}else{if(t!=null){var j=m.series[t.seriesIndex];if(j.isDragable){var u=m.plugins.dragable.dragCanvas;if(!u.isOver){u._cursors.push(o.target.style.cursor);o.target.style.cursor="pointer"}u.isOver=true}}else{if(t==null){var u=m.plugins.dragable.dragCanvas;if(u.isOver){o.target.style.cursor=u._cursors.pop();u.isOver=false}}}}}function c(k,i,g,l,j){var m=j.plugins.dragable.dragCanvas;m._cursors.push(k.target.style.cursor);if(l!=null){var o=j.series[l.seriesIndex];var h=o.plugins.dragable;if(o.isDragable&&!m.isDragging){m._neighbor=l;m.isDragging=true;f(j,l);h.markerRenderer.draw(o.gridData[l.pointIndex][0],o.gridData[l.pointIndex][1],m._ctx);k.target.style.cursor="move";j.target.trigger("jqplotDragStart",[l.seriesIndex,l.pointIndex,i,g])}}else{var n=m._ctx;n.clearRect(0,0,n.canvas.width,n.canvas.height);m.isDragging=false}}function a(m,j,g,o,k){if(k.plugins.dragable.dragCanvas.isDragging){var p=k.plugins.dragable.dragCanvas;var q=p._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);p.isDragging=false;var h=p._neighbor;var r=k.series[h.seriesIndex];var i=r.plugins.dragable;var n=(i.constrainTo=="y")?h.data[0]:g[r.xaxis];var l=(i.constrainTo=="x")?h.data[1]:g[r.yaxis];r.data[h.pointIndex][0]=n;r.data[h.pointIndex][1]=l;k.drawSeries({preventJqPlotSeriesDrawTrigger:true},h.seriesIndex);p._neighbor=null;m.target.style.cursor=p._cursors.pop();k.target.trigger("jqplotDragStop",[j,g])}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.enhancedLegendRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.enhancedLegendRenderer.js new file mode 100644 index 0000000000..fc06d2078b --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.enhancedLegendRenderer.js @@ -0,0 +1,199 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + // class $.jqplot.EnhancedLegendRenderer + // Legend renderer which can specify the number of rows and/or columns in the legend. + $.jqplot.EnhancedLegendRenderer = function(){ + $.jqplot.TableLegendRenderer.call(this); + }; + + $.jqplot.EnhancedLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); + $.jqplot.EnhancedLegendRenderer.prototype.constructor = $.jqplot.EnhancedLegendRenderer; + + // called with scope of legend. + $.jqplot.EnhancedLegendRenderer.prototype.init = function(options) { + // prop: numberRows + // Maximum number of rows in the legend. 0 or null for unlimited. + this.numberRows = null; + // prop: numberColumns + // Maximum number of columns in the legend. 0 or null for unlimited. + this.numberColumns = null; + // prop: seriesToggle + // false to not enable series on/off toggling on the legend. + // true or a fadein/fadeout speed (number of milliseconds or 'fast', 'normal', 'slow') + // to enable show/hide of series on click of legend item. + this.seriesToggle = 'normal'; + // prop: disableIEFading + // true to toggle series with a show/hide method only and not allow fading in/out. + // This is to overcome poor performance of fade in some versions of IE. + this.disableIEFading = true; + $.extend(true, this, options); + + if (this.seriesToggle) { + $.jqplot.postDrawHooks.push(postDraw); + } + }; + + // called with scope of legend + $.jqplot.EnhancedLegendRenderer.prototype.draw = function() { + var legend = this; + if (this.show) { + var series = this._series; + var s; + var ss = 'position:absolute;'; + ss += (this.background) ? 'background:'+this.background+';' : ''; + ss += (this.border) ? 'border:'+this.border+';' : ''; + ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; + ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : ''; + ss += (this.textColor) ? 'color:'+this.textColor+';' : ''; + ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : ''; + ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : ''; + ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : ''; + ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : ''; + this._elem = $('<table class="jqplot-table-legend" style="'+ss+'"></table>'); + if (this.seriesToggle) { + this._elem.css('z-index', '3'); + } + + var pad = false, + reverse = false, + nr, nc; + if (this.numberRows) { + nr = this.numberRows; + if (!this.numberColumns){ + nc = Math.ceil(series.length/nr); + } + else{ + nc = this.numberColumns; + } + } + else if (this.numberColumns) { + nc = this.numberColumns; + nr = Math.ceil(series.length/this.numberColumns); + } + else { + nr = series.length; + nc = 1; + } + + var i, j, tr, td1, td2, lt, rs; + var idx = 0; + // check to see if we need to reverse + for (i=series.length-1; i>=0; i--) { + if (series[i]._stack || series[i].renderer.constructor == $.jqplot.BezierCurveRenderer){ + reverse = true; + } + } + + for (i=0; i<nr; i++) { + if (reverse){ + tr = $('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem); + } + else{ + tr = $('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem); + } + for (j=0; j<nc; j++) { + if (idx < series.length && series[idx].show && series[idx].showLabel){ + s = series[idx]; + lt = this.labels[idx] || s.label.toString(); + if (lt) { + var color = s.color; + if (!reverse){ + if (i>0){ + pad = true; + } + else{ + pad = false; + } + } + else{ + if (i == nr -1){ + pad = false; + } + else{ + pad = true; + } + } + rs = (pad) ? this.rowSpacing : '0'; + + td1 = $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+ + '<div><div class="jqplot-table-legend-swatch" style="background-color:'+color+';border-color:'+color+';"></div>'+ + '</div></td>'); + td2 = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>'); + if (this.escapeHtml){ + td2.text(lt); + } + else { + td2.html(lt); + } + if (reverse) { + if (this.showLabels) {td2.prependTo(tr);} + if (this.showSwatches) {td1.prependTo(tr);} + } + else { + if (this.showSwatches) {td1.appendTo(tr);} + if (this.showLabels) {td2.appendTo(tr);} + } + + if (this.seriesToggle) { + var speed; + if (typeof(this.seriesToggle) == 'string' || typeof(this.seriesToggle) == 'number') { + if (!$.jqplot.use_excanvas || !this.disableIEFading) { + speed = this.seriesToggle; + } + } + if (this.showSwatches) { + td1.bind('click', {series:s, speed:speed}, s.toggleDisplay); + td1.addClass('jqplot-seriesToggle'); + } + if (this.showLabels) { + td2.bind('click', {series:s, speed:speed}, s.toggleDisplay); + td2.addClass('jqplot-seriesToggle'); + } + } + + pad = true; + } + } + idx++; + } + } + } + return this._elem; + }; + + // called with scope of plot. + var postDraw = function () { + if (this.legend.renderer.constructor == $.jqplot.EnhancedLegendRenderer && this.legend.seriesToggle){ + var e = this.legend._elem.detach(); + this.eventCanvas._elem.after(e); + } + }; +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.enhancedLegendRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.enhancedLegendRenderer.min.js new file mode 100644 index 0000000000..90d3376688 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.enhancedLegendRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(b){b.jqplot.EnhancedLegendRenderer=function(){b.jqplot.TableLegendRenderer.call(this)};b.jqplot.EnhancedLegendRenderer.prototype=new b.jqplot.TableLegendRenderer();b.jqplot.EnhancedLegendRenderer.prototype.constructor=b.jqplot.EnhancedLegendRenderer;b.jqplot.EnhancedLegendRenderer.prototype.init=function(c){this.numberRows=null;this.numberColumns=null;this.seriesToggle="normal";this.disableIEFading=true;b.extend(true,this,c);if(this.seriesToggle){b.jqplot.postDrawHooks.push(a)}};b.jqplot.EnhancedLegendRenderer.prototype.draw=function(){var e=this;if(this.show){var n=this._series;var o;var q="position:absolute;";q+=(this.background)?"background:"+this.background+";":"";q+=(this.border)?"border:"+this.border+";":"";q+=(this.fontSize)?"font-size:"+this.fontSize+";":"";q+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";q+=(this.textColor)?"color:"+this.textColor+";":"";q+=(this.marginTop!=null)?"margin-top:"+this.marginTop+";":"";q+=(this.marginBottom!=null)?"margin-bottom:"+this.marginBottom+";":"";q+=(this.marginLeft!=null)?"margin-left:"+this.marginLeft+";":"";q+=(this.marginRight!=null)?"margin-right:"+this.marginRight+";":"";this._elem=b('<table class="jqplot-table-legend" style="'+q+'"></table>');if(this.seriesToggle){this._elem.css("z-index","3")}var w=false,m=false,c,k;if(this.numberRows){c=this.numberRows;if(!this.numberColumns){k=Math.ceil(n.length/c)}else{k=this.numberColumns}}else{if(this.numberColumns){k=this.numberColumns;c=Math.ceil(n.length/this.numberColumns)}else{c=n.length;k=1}}var v,t,d,g,f,h,l;var p=0;for(v=n.length-1;v>=0;v--){if(n[v]._stack||n[v].renderer.constructor==b.jqplot.BezierCurveRenderer){m=true}}for(v=0;v<c;v++){if(m){d=b('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem)}else{d=b('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem)}for(t=0;t<k;t++){if(p<n.length&&n[p].show&&n[p].showLabel){o=n[p];h=this.labels[p]||o.label.toString();if(h){var r=o.color;if(!m){if(v>0){w=true}else{w=false}}else{if(v==c-1){w=false}else{w=true}}l=(w)?this.rowSpacing:"0";g=b('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+l+';"><div><div class="jqplot-table-legend-swatch" style="background-color:'+r+";border-color:"+r+';"></div></div></td>');f=b('<td class="jqplot-table-legend" style="padding-top:'+l+';"></td>');if(this.escapeHtml){f.text(h)}else{f.html(h)}if(m){if(this.showLabels){f.prependTo(d)}if(this.showSwatches){g.prependTo(d)}}else{if(this.showSwatches){g.appendTo(d)}if(this.showLabels){f.appendTo(d)}}if(this.seriesToggle){var u;if(typeof(this.seriesToggle)=="string"||typeof(this.seriesToggle)=="number"){if(!b.jqplot.use_excanvas||!this.disableIEFading){u=this.seriesToggle}}if(this.showSwatches){g.bind("click",{series:o,speed:u},o.toggleDisplay);g.addClass("jqplot-seriesToggle")}if(this.showLabels){f.bind("click",{series:o,speed:u},o.toggleDisplay);f.addClass("jqplot-seriesToggle")}}w=true}}p++}}}return this._elem};var a=function(){if(this.legend.renderer.constructor==b.jqplot.EnhancedLegendRenderer&&this.legend.seriesToggle){var c=this.legend._elem.detach();this.eventCanvas._elem.after(c)}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.funnelRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.funnelRenderer.js new file mode 100644 index 0000000000..e1cefd96cb --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.funnelRenderer.js @@ -0,0 +1,938 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.FunnelRenderer + * Plugin renderer to draw a funnel chart. + * x values, if present, will be used as labels. + * y values give area size. + * + * Funnel charts will draw a single series + * only. + * + * To use this renderer, you need to include the + * funnel renderer plugin, for example: + * + * > <script type="text/javascript" src="plugins/jqplot.funnelRenderer.js"></script> + * + * Properties described here are passed into the $.jqplot function + * as options on the series renderer. For example: + * + * > plot2 = $.jqplot('chart2', [s1, s2], { + * > seriesDefaults: { + * > renderer:$.jqplot.FunnelRenderer, + * > rendererOptions:{ + * > sectionMargin: 12, + * > widthRatio: 0.3 + * > } + * > } + * > }); + * + * IMPORTANT + * + * *The funnel renderer will reorder data in descending order* so the largest value in + * the data set is first and displayed on top of the funnel. Data will then + * be displayed in descending order down the funnel. The area of each funnel + * section will correspond to the value of each data point relative to the sum + * of all values. That is section area is proportional to section value divided by + * sum of all section values. + * + * If your data is not in descending order when passed into the plot, *it will be + * reordered* when stored in the series.data property. A copy of the unordered + * data is kept in the series._unorderedData property. + * + * A funnel plot will trigger events on the plot target + * according to user interaction. All events return the event object, + * the series index, the point (section) index, and the point data for + * the appropriate section. *Note* the point index will referr to the ordered + * data, not the original unordered data. + * + * 'jqplotDataMouseOver' - triggered when mousing over a section. + * 'jqplotDataHighlight' - triggered the first time user mouses over a section, + * if highlighting is enabled. + * 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of + * a highlighted section. + * 'jqplotDataClick' - triggered when the user clicks on a section. + * 'jqplotDataRightClick' - tiggered when the user right clicks on a section if + * the "captureRightClick" option is set to true on the plot. + */ + $.jqplot.FunnelRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.FunnelRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.FunnelRenderer.prototype.constructor = $.jqplot.FunnelRenderer; + + // called with scope of a series + $.jqplot.FunnelRenderer.prototype.init = function(options, plot) { + // Group: Properties + // + // prop: padding + // padding between the funnel and plot edges, legend, etc. + this.padding = {top: 20, right: 20, bottom: 20, left: 20}; + // prop: sectionMargin + // spacing between funnel sections in pixels. + this.sectionMargin = 6; + // prop: fill + // true or false, wether to fill the areas. + this.fill = true; + // prop: shadowOffset + // offset of the shadow from the area and offset of + // each succesive stroke of the shadow from the last. + this.shadowOffset = 2; + // prop: shadowAlpha + // transparency of the shadow (0 = transparent, 1 = opaque) + this.shadowAlpha = 0.07; + // prop: shadowDepth + // number of strokes to apply to the shadow, + // each stroke offset shadowOffset from the last. + this.shadowDepth = 5; + // prop: highlightMouseOver + // True to highlight area when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on a area. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over a area. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColors + // array of colors to use when highlighting an area. + this.highlightColors = []; + // prop: widthRatio + // The ratio of the width of the top of the funnel to the bottom. + // a ratio of 0 will make an upside down pyramid. + this.widthRatio = 0.2; + // prop: lineWidth + // width of line if areas are stroked and not filled. + this.lineWidth = 2; + // prop: dataLabels + // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices. + // Defaults to percentage of each pie slice. + this.dataLabels = 'percent'; + // prop: showDataLabels + // true to show data labels on slices. + this.showDataLabels = false; + // prop: dataLabelFormatString + // Format string for data labels. If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage. + this.dataLabelFormatString = null; + // prop: dataLabelThreshold + // Threshhold in percentage (0 - 100) of pie area, below which no label will be displayed. + // This applies to all label types, not just to percentage labels. + this.dataLabelThreshold = 3; + this._type = 'funnel'; + + this.tickRenderer = $.jqplot.FunnelTickRenderer; + + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (options.highlightMouseDown && options.highlightMouseOver == null) { + options.highlightMouseOver = false; + } + + $.extend(true, this, options); + + // index of the currenty highlighted point, if any + this._highlightedPoint = null; + + // lengths of bases, or horizontal sides of areas of trapezoid. + this._bases = []; + // total area + this._atot; + // areas of segments. + this._areas = []; + // vertical lengths of segments. + this._lengths = []; + // angle of the funnel to vertical. + this._angle; + this._dataIndices = []; + + // sort data + this._unorderedData = $.extend(true, [], this.data); + var idxs = $.extend(true, [], this.data); + for (var i=0; i<idxs.length; i++) { + idxs[i].push(i); + } + this.data.sort( function (a, b) { return b[1] - a[1]; } ); + idxs.sort( function (a, b) { return b[1] - a[1]; }); + for (var i=0; i<idxs.length; i++) { + this._dataIndices.push(idxs[i][2]); + } + + // set highlight colors if none provided + if (this.highlightColors.length == 0) { + for (var i=0; i<this.seriesColors.length; i++){ + var rgba = $.jqplot.getColorComponents(this.seriesColors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.4 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + } + } + + plot.postParseOptionsHooks.addOnce(postParseOptions); + plot.postInitHooks.addOnce(postInit); + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + plot.postDrawHooks.addOnce(postPlotDraw); + + }; + + // gridData will be of form [label, percentage of total] + $.jqplot.FunnelRenderer.prototype.setGridData = function(plot) { + // set gridData property. This will hold angle in radians of each data point. + var sum = 0; + var td = []; + for (var i=0; i<this.data.length; i++){ + sum += this.data[i][1]; + td.push([this.data[i][0], this.data[i][1]]); + } + + // normalize y values, so areas are proportional. + for (var i=0; i<td.length; i++) { + td[i][1] = td[i][1]/sum; + } + + this._bases = new Array(td.length + 1); + this._lengths = new Array(td.length); + + this.gridData = td; + }; + + $.jqplot.FunnelRenderer.prototype.makeGridData = function(data, plot) { + // set gridData property. This will hold angle in radians of each data point. + var sum = 0; + var td = []; + for (var i=0; i<this.data.length; i++){ + sum += this.data[i][1]; + td.push([this.data[i][0], this.data[i][1]]); + } + + // normalize y values, so areas are proportional. + for (var i=0; i<td.length; i++) { + td[i][1] = td[i][1]/sum; + } + + this._bases = new Array(td.length + 1); + this._lengths = new Array(td.length); + + return td; + }; + + $.jqplot.FunnelRenderer.prototype.drawSection = function (ctx, vertices, color, isShadow) { + var fill = this.fill; + var lineWidth = this.lineWidth; + ctx.save(); + + if (isShadow) { + for (var i=0; i<this.shadowDepth; i++) { + ctx.save(); + ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI)); + doDraw(); + } + } + + else { + doDraw(); + } + + function doDraw () { + ctx.beginPath(); + ctx.fillStyle = color; + ctx.strokeStyle = color; + ctx.lineWidth = lineWidth; + ctx.moveTo(vertices[0][0], vertices[0][1]); + for (var i=1; i<4; i++) { + ctx.lineTo(vertices[i][0], vertices[i][1]); + } + ctx.closePath(); + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + } + + if (isShadow) { + for (var i=0; i<this.shadowDepth; i++) { + ctx.restore(); + } + } + + ctx.restore(); + }; + + // called with scope of series + $.jqplot.FunnelRenderer.prototype.draw = function (ctx, gd, options, plot) { + var i; + var opts = (options != undefined) ? options : {}; + // offset and direction of offset due to legend placement + var offx = 0; + var offy = 0; + var trans = 1; + this._areas = []; + // var colorGenerator = new this.colorGenerator(this.seriesColors); + if (options.legendInfo && options.legendInfo.placement == 'insideGrid') { + var li = options.legendInfo; + switch (li.location) { + case 'nw': + offx = li.width + li.xoffset; + break; + case 'w': + offx = li.width + li.xoffset; + break; + case 'sw': + offx = li.width + li.xoffset; + break; + case 'ne': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'e': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'se': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'n': + offy = li.height + li.yoffset; + break; + case 's': + offy = li.height + li.yoffset; + trans = -1; + break; + default: + break; + } + } + + var loff = (trans==1) ? this.padding.left + offx : this.padding.left; + var toff = (trans==1) ? this.padding.top + offy : this.padding.top; + var roff = (trans==-1) ? this.padding.right + offx : this.padding.right; + var boff = (trans==-1) ? this.padding.bottom + offy : this.padding.bottom; + + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var cw = ctx.canvas.width; + var ch = ctx.canvas.height; + this._bases[0] = cw - loff - roff; + var ltot = this._length = ch - toff - boff; + + var hend = this._bases[0]*this.widthRatio; + this._atot = ltot/2 * (this._bases[0] + this._bases[0]*this.widthRatio); + + this._angle = Math.atan((this._bases[0] - hend)/2/ltot); + + for (i=0; i<gd.length; i++) { + this._areas.push(gd[i][1] * this._atot); + } + + + var guess, err, count, lsum=0; + var tolerance = 0.0001; + + for (i=0; i<this._areas.length; i++) { + guess = this._areas[i]/this._bases[i]; + err = 999999; + this._lengths[i] = guess; + count = 0; + while (err > this._lengths[i]*tolerance && count < 100) { + this._lengths[i] = this._areas[i]/(this._bases[i] - this._lengths[i] * Math.tan(this._angle)); + err = Math.abs(this._lengths[i] - guess); + this._bases[i+1] = this._bases[i] - (2*this._lengths[i]*Math.tan(this._angle)); + guess = this._lengths[i]; + count++; + } + lsum += this._lengths[i]; + } + + // figure out vertices of each section + this._vertices = new Array(gd.length); + + // these are 4 coners of entire trapezoid + var p0 = [loff, toff], + p1 = [loff+this._bases[0], toff], + p2 = [loff + (this._bases[0] - this._bases[this._bases.length-1])/2, toff + this._length], + p3 = [p2[0] + this._bases[this._bases.length-1], p2[1]]; + + // equations of right and left sides, returns x, y values given height of section (y value) + function findleft (l) { + var m = (p0[1] - p2[1])/(p0[0] - p2[0]); + var b = p0[1] - m*p0[0]; + var y = l + p0[1]; + + return [(y - b)/m, y]; + } + + function findright (l) { + var m = (p1[1] - p3[1])/(p1[0] - p3[0]); + var b = p1[1] - m*p1[0]; + var y = l + p1[1]; + + return [(y - b)/m, y]; + } + + var x = offx, y = offy; + var h=0, adj=0; + + for (i=0; i<gd.length; i++) { + this._vertices[i] = new Array(); + var v = this._vertices[i]; + var sm = this.sectionMargin; + if (i == 0) { + adj = 0; + } + if (i == 1) { + adj = sm/3; + } + else if (i > 0 && i < gd.length-1) { + adj = sm/2; + } + else if (i == gd.length -1) { + adj = 2*sm/3; + } + v.push(findleft(h+adj)); + v.push(findright(h+adj)); + h += this._lengths[i]; + if (i == 0) { + adj = -2*sm/3; + } + else if (i > 0 && i < gd.length-1) { + adj = -sm/2; + } + else if (i == gd.length - 1) { + adj = 0; + } + v.push(findright(h+adj)); + v.push(findleft(h+adj)); + + } + + if (this.shadow) { + var shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')'; + for (var i=0; i<gd.length; i++) { + this.renderer.drawSection.call (this, ctx, this._vertices[i], shadowColor, true); + } + + } + for (var i=0; i<gd.length; i++) { + var v = this._vertices[i]; + this.renderer.drawSection.call (this, ctx, v, this.seriesColors[i]); + + if (this.showDataLabels && gd[i][1]*100 >= this.dataLabelThreshold) { + var fstr, label; + + if (this.dataLabels == 'label') { + fstr = this.dataLabelFormatString || '%s'; + label = $.jqplot.sprintf(fstr, gd[i][0]); + } + else if (this.dataLabels == 'value') { + fstr = this.dataLabelFormatString || '%d'; + label = $.jqplot.sprintf(fstr, this.data[i][1]); + } + else if (this.dataLabels == 'percent') { + fstr = this.dataLabelFormatString || '%d%%'; + label = $.jqplot.sprintf(fstr, gd[i][1]*100); + } + else if (this.dataLabels.constructor == Array) { + fstr = this.dataLabelFormatString || '%s'; + label = $.jqplot.sprintf(fstr, this.dataLabels[this._dataIndices[i]]); + } + + var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge; + + var x = (v[0][0] + v[1][0])/2 + this.canvas._offsets.left; + var y = (v[1][1] + v[2][1])/2 + this.canvas._offsets.top; + + var labelelem = $('<span class="jqplot-funnel-series jqplot-data-label" style="position:absolute;">' + label + '</span>').insertBefore(plot.eventCanvas._elem); + x -= labelelem.width()/2; + y -= labelelem.height()/2; + x = Math.round(x); + y = Math.round(y); + labelelem.css({left: x, top: y}); + } + + } + + }; + + $.jqplot.FunnelAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + }; + + $.jqplot.FunnelAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.FunnelAxisRenderer.prototype.constructor = $.jqplot.FunnelAxisRenderer; + + + // There are no traditional axes on a funnel chart. We just need to provide + // dummy objects with properties so the plot will render. + // called with scope of axis object. + $.jqplot.FunnelAxisRenderer.prototype.init = function(options){ + // + this.tickRenderer = $.jqplot.FunnelTickRenderer; + $.extend(true, this, options); + // I don't think I'm going to need _dataBounds here. + // have to go Axis scaling in a way to fit chart onto plot area + // and provide u2p and p2u functionality for mouse cursor, etc. + // for convienence set _dataBounds to 0 and 100 and + // set min/max to 0 and 100. + this._dataBounds = {min:0, max:100}; + this.min = 0; + this.max = 100; + this.showTicks = false; + this.ticks = []; + this.showMark = false; + this.show = false; + }; + + + + /** + * Class: $.jqplot.FunnelLegendRenderer + * Legend Renderer specific to funnel plots. Set by default + * when the user creates a funnel plot. + */ + $.jqplot.FunnelLegendRenderer = function(){ + $.jqplot.TableLegendRenderer.call(this); + }; + + $.jqplot.FunnelLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); + $.jqplot.FunnelLegendRenderer.prototype.constructor = $.jqplot.FunnelLegendRenderer; + + $.jqplot.FunnelLegendRenderer.prototype.init = function(options) { + // Group: Properties + // + // prop: numberRows + // Maximum number of rows in the legend. 0 or null for unlimited. + this.numberRows = null; + // prop: numberColumns + // Maximum number of columns in the legend. 0 or null for unlimited. + this.numberColumns = null; + $.extend(true, this, options); + }; + + // called with context of legend + $.jqplot.FunnelLegendRenderer.prototype.draw = function() { + var legend = this; + if (this.show) { + var series = this._series; + var ss = 'position:absolute;'; + ss += (this.background) ? 'background:'+this.background+';' : ''; + ss += (this.border) ? 'border:'+this.border+';' : ''; + ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; + ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : ''; + ss += (this.textColor) ? 'color:'+this.textColor+';' : ''; + ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : ''; + ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : ''; + ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : ''; + ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : ''; + this._elem = $('<table class="jqplot-table-legend" style="'+ss+'"></table>'); + // Funnel charts legends don't go by number of series, but by number of data points + // in the series. Refactor things here for that. + + var pad = false, + reverse = false, + nr, nc; + var s = series[0]; + var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors); + + if (s.show) { + var pd = s.data; + if (this.numberRows) { + nr = this.numberRows; + if (!this.numberColumns){ + nc = Math.ceil(pd.length/nr); + } + else{ + nc = this.numberColumns; + } + } + else if (this.numberColumns) { + nc = this.numberColumns; + nr = Math.ceil(pd.length/this.numberColumns); + } + else { + nr = pd.length; + nc = 1; + } + + var i, j, tr, td1, td2, lt, rs, color; + var idx = 0; + + for (i=0; i<nr; i++) { + if (reverse){ + tr = $('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem); + } + else{ + tr = $('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem); + } + for (j=0; j<nc; j++) { + if (idx < pd.length){ + lt = this.labels[idx] || pd[idx][0].toString(); + color = colorGenerator.next(); + if (!reverse){ + if (i>0){ + pad = true; + } + else{ + pad = false; + } + } + else{ + if (i == nr -1){ + pad = false; + } + else{ + pad = true; + } + } + rs = (pad) ? this.rowSpacing : '0'; + + td1 = $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+ + '<div><div class="jqplot-table-legend-swatch" style="border-color:'+color+';"></div>'+ + '</div></td>'); + td2 = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>'); + if (this.escapeHtml){ + td2.text(lt); + } + else { + td2.html(lt); + } + if (reverse) { + td2.prependTo(tr); + td1.prependTo(tr); + } + else { + td1.appendTo(tr); + td2.appendTo(tr); + } + pad = true; + } + idx++; + } + } + } + } + return this._elem; + }; + + // $.jqplot.FunnelLegendRenderer.prototype.pack = function(offsets) { + // if (this.show) { + // // fake a grid for positioning + // var grid = {_top:offsets.top, _left:offsets.left, _right:offsets.right, _bottom:this._plotDimensions.height - offsets.bottom}; + // if (this.placement == 'insideGrid') { + // switch (this.location) { + // case 'nw': + // var a = grid._left + this.xoffset; + // var b = grid._top + this.yoffset; + // this._elem.css('left', a); + // this._elem.css('top', b); + // break; + // case 'n': + // var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + // var b = grid._top + this.yoffset; + // this._elem.css('left', a); + // this._elem.css('top', b); + // break; + // case 'ne': + // var a = offsets.right + this.xoffset; + // var b = grid._top + this.yoffset; + // this._elem.css({right:a, top:b}); + // break; + // case 'e': + // var a = offsets.right + this.xoffset; + // var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + // this._elem.css({right:a, top:b}); + // break; + // case 'se': + // var a = offsets.right + this.xoffset; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({right:a, bottom:b}); + // break; + // case 's': + // var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({left:a, bottom:b}); + // break; + // case 'sw': + // var a = grid._left + this.xoffset; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({left:a, bottom:b}); + // break; + // case 'w': + // var a = grid._left + this.xoffset; + // var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + // this._elem.css({left:a, top:b}); + // break; + // default: // same as 'se' + // var a = grid._right - this.xoffset; + // var b = grid._bottom + this.yoffset; + // this._elem.css({right:a, bottom:b}); + // break; + // } + // + // } + // else { + // switch (this.location) { + // case 'nw': + // var a = this._plotDimensions.width - grid._left + this.xoffset; + // var b = grid._top + this.yoffset; + // this._elem.css('right', a); + // this._elem.css('top', b); + // break; + // case 'n': + // var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + // var b = this._plotDimensions.height - grid._top + this.yoffset; + // this._elem.css('left', a); + // this._elem.css('bottom', b); + // break; + // case 'ne': + // var a = this._plotDimensions.width - offsets.right + this.xoffset; + // var b = grid._top + this.yoffset; + // this._elem.css({left:a, top:b}); + // break; + // case 'e': + // var a = this._plotDimensions.width - offsets.right + this.xoffset; + // var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + // this._elem.css({left:a, top:b}); + // break; + // case 'se': + // var a = this._plotDimensions.width - offsets.right + this.xoffset; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({left:a, bottom:b}); + // break; + // case 's': + // var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + // var b = this._plotDimensions.height - offsets.bottom + this.yoffset; + // this._elem.css({left:a, top:b}); + // break; + // case 'sw': + // var a = this._plotDimensions.width - grid._left + this.xoffset; + // var b = offsets.bottom + this.yoffset; + // this._elem.css({right:a, bottom:b}); + // break; + // case 'w': + // var a = this._plotDimensions.width - grid._left + this.xoffset; + // var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + // this._elem.css({right:a, top:b}); + // break; + // default: // same as 'se' + // var a = grid._right - this.xoffset; + // var b = grid._bottom + this.yoffset; + // this._elem.css({right:a, bottom:b}); + // break; + // } + // } + // } + // }; + + // setup default renderers for axes and legend so user doesn't have to + // called with scope of plot + function preInit(target, data, options) { + options = options || {}; + options.axesDefaults = options.axesDefaults || {}; + options.legend = options.legend || {}; + options.seriesDefaults = options.seriesDefaults || {}; + // only set these if there is a funnel series + var setopts = false; + if (options.seriesDefaults.renderer == $.jqplot.FunnelRenderer) { + setopts = true; + } + else if (options.series) { + for (var i=0; i < options.series.length; i++) { + if (options.series[i].renderer == $.jqplot.FunnelRenderer) { + setopts = true; + } + } + } + + if (setopts) { + options.axesDefaults.renderer = $.jqplot.FunnelAxisRenderer; + options.legend.renderer = $.jqplot.FunnelLegendRenderer; + options.legend.preDraw = true; + options.sortData = false; + options.seriesDefaults.pointLabels = {show: false}; + } + } + + function postInit(target, data, options) { + // if multiple series, add a reference to the previous one so that + // funnel rings can nest. + for (var i=0; i<this.series.length; i++) { + if (this.series[i].renderer.constructor == $.jqplot.FunnelRenderer) { + // don't allow mouseover and mousedown at same time. + if (this.series[i].highlightMouseOver) { + this.series[i].highlightMouseDown = false; + } + } + } + this.target.bind('mouseout', {plot:this}, function (ev) { unhighlight(ev.data.plot); }); + } + + // called with scope of plot + function postParseOptions(options) { + for (var i=0; i<this.series.length; i++) { + this.series[i].seriesColors = this.seriesColors; + this.series[i].colorGenerator = this.colorGenerator; + } + } + + function highlight (plot, sidx, pidx) { + var s = plot.series[sidx]; + var canvas = plot.plugins.funnelRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.funnelRenderer.highlightedSeriesIndex = sidx; + s.renderer.drawSection.call(s, canvas._ctx, s._vertices[pidx], s.highlightColors[pidx], false); + } + + function unhighlight (plot) { + var canvas = plot.plugins.funnelRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.funnelRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + } + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.funnelRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt = jQuery.Event('jqplotDataClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var idx = plot.plugins.funnelRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.funnelRenderer && this.plugins.funnelRenderer.highlightCanvas) { + this.plugins.funnelRenderer.highlightCanvas.resetCanvas(); + this.plugins.funnelRenderer.highlightCanvas = null; + } + + this.plugins.funnelRenderer = {}; + this.plugins.funnelRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + + // do we have any data labels? if so, put highlight canvas before those + var labels = $(this.targetId+' .jqplot-data-label'); + if (labels.length) { + $(labels[0]).before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-funnelRenderer-highlight-canvas', this._plotDimensions, this)); + } + // else put highlight canvas before event canvas. + else { + this.eventCanvas._elem.before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-funnelRenderer-highlight-canvas', this._plotDimensions, this)); + } + var hctx = this.plugins.funnelRenderer.highlightCanvas.setContext(); + } + + $.jqplot.preInitHooks.push(preInit); + + $.jqplot.FunnelTickRenderer = function() { + $.jqplot.AxisTickRenderer.call(this); + }; + + $.jqplot.FunnelTickRenderer.prototype = new $.jqplot.AxisTickRenderer(); + $.jqplot.FunnelTickRenderer.prototype.constructor = $.jqplot.FunnelTickRenderer; + +})(jQuery); + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.funnelRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.funnelRenderer.min.js new file mode 100644 index 0000000000..5ebb47bddc --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.funnelRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(e){e.jqplot.FunnelRenderer=function(){e.jqplot.LineRenderer.call(this)};e.jqplot.FunnelRenderer.prototype=new e.jqplot.LineRenderer();e.jqplot.FunnelRenderer.prototype.constructor=e.jqplot.FunnelRenderer;e.jqplot.FunnelRenderer.prototype.init=function(p,t){this.padding={top:20,right:20,bottom:20,left:20};this.sectionMargin=6;this.fill=true;this.shadowOffset=2;this.shadowAlpha=0.07;this.shadowDepth=5;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.widthRatio=0.2;this.lineWidth=2;this.dataLabels="percent";this.showDataLabels=false;this.dataLabelFormatString=null;this.dataLabelThreshold=3;this._type="funnel";this.tickRenderer=e.jqplot.FunnelTickRenderer;if(p.highlightMouseDown&&p.highlightMouseOver==null){p.highlightMouseOver=false}e.extend(true,this,p);this._highlightedPoint=null;this._bases=[];this._atot;this._areas=[];this._lengths=[];this._angle;this._dataIndices=[];this._unorderedData=e.extend(true,[],this.data);var o=e.extend(true,[],this.data);for(var r=0;r<o.length;r++){o[r].push(r)}this.data.sort(function(v,u){return u[1]-v[1]});o.sort(function(v,u){return u[1]-v[1]});for(var r=0;r<o.length;r++){this._dataIndices.push(o[r][2])}if(this.highlightColors.length==0){for(var r=0;r<this.seriesColors.length;r++){var q=e.jqplot.getColorComponents(this.seriesColors[r]);var m=[q[0],q[1],q[2]];var s=m[0]+m[1]+m[2];for(var n=0;n<3;n++){m[n]=(s>570)?m[n]*0.8:m[n]+0.4*(255-m[n]);m[n]=parseInt(m[n],10)}this.highlightColors.push("rgb("+m[0]+","+m[1]+","+m[2]+")")}}t.postParseOptionsHooks.addOnce(k);t.postInitHooks.addOnce(g);t.eventListenerHooks.addOnce("jqplotMouseMove",a);t.eventListenerHooks.addOnce("jqplotMouseDown",b);t.eventListenerHooks.addOnce("jqplotMouseUp",j);t.eventListenerHooks.addOnce("jqplotClick",f);t.eventListenerHooks.addOnce("jqplotRightClick",l);t.postDrawHooks.addOnce(h)};e.jqplot.FunnelRenderer.prototype.setGridData=function(o){var n=0;var p=[];for(var m=0;m<this.data.length;m++){n+=this.data[m][1];p.push([this.data[m][0],this.data[m][1]])}for(var m=0;m<p.length;m++){p[m][1]=p[m][1]/n}this._bases=new Array(p.length+1);this._lengths=new Array(p.length);this.gridData=p};e.jqplot.FunnelRenderer.prototype.makeGridData=function(o,p){var n=0;var q=[];for(var m=0;m<this.data.length;m++){n+=this.data[m][1];q.push([this.data[m][0],this.data[m][1]])}for(var m=0;m<q.length;m++){q[m][1]=q[m][1]/n}this._bases=new Array(q.length+1);this._lengths=new Array(q.length);return q};e.jqplot.FunnelRenderer.prototype.drawSection=function(n,p,o,s){var t=this.fill;var m=this.lineWidth;n.save();if(s){for(var r=0;r<this.shadowDepth;r++){n.save();n.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI),this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));q()}}else{q()}function q(){n.beginPath();n.fillStyle=o;n.strokeStyle=o;n.lineWidth=m;n.moveTo(p[0][0],p[0][1]);for(var u=1;u<4;u++){n.lineTo(p[u][0],p[u][1])}n.closePath();if(t){n.fill()}else{n.stroke()}}if(s){for(var r=0;r<this.shadowDepth;r++){n.restore()}}n.restore()};e.jqplot.FunnelRenderer.prototype.draw=function(G,B,J,p){var Y;var L=(J!=undefined)?J:{};var w=0;var u=0;var R=1;this._areas=[];if(J.legendInfo&&J.legendInfo.placement=="insideGrid"){var O=J.legendInfo;switch(O.location){case"nw":w=O.width+O.xoffset;break;case"w":w=O.width+O.xoffset;break;case"sw":w=O.width+O.xoffset;break;case"ne":w=O.width+O.xoffset;R=-1;break;case"e":w=O.width+O.xoffset;R=-1;break;case"se":w=O.width+O.xoffset;R=-1;break;case"n":u=O.height+O.yoffset;break;case"s":u=O.height+O.yoffset;R=-1;break;default:break}}var t=(R==1)?this.padding.left+w:this.padding.left;var F=(R==1)?this.padding.top+u:this.padding.top;var M=(R==-1)?this.padding.right+w:this.padding.right;var o=(R==-1)?this.padding.bottom+u:this.padding.bottom;var P=(L.shadow!=undefined)?L.shadow:this.shadow;var q=(L.showLine!=undefined)?L.showLine:this.showLine;var C=(L.fill!=undefined)?L.fill:this.fill;var H=G.canvas.width;var N=G.canvas.height;this._bases[0]=H-t-M;var I=this._length=N-F-o;var r=this._bases[0]*this.widthRatio;this._atot=I/2*(this._bases[0]+this._bases[0]*this.widthRatio);this._angle=Math.atan((this._bases[0]-r)/2/I);for(Y=0;Y<B.length;Y++){this._areas.push(B[Y][1]*this._atot)}var E,aa,W,Q=0;var n=0.0001;for(Y=0;Y<this._areas.length;Y++){E=this._areas[Y]/this._bases[Y];aa=999999;this._lengths[Y]=E;W=0;while(aa>this._lengths[Y]*n&&W<100){this._lengths[Y]=this._areas[Y]/(this._bases[Y]-this._lengths[Y]*Math.tan(this._angle));aa=Math.abs(this._lengths[Y]-E);this._bases[Y+1]=this._bases[Y]-(2*this._lengths[Y]*Math.tan(this._angle));E=this._lengths[Y];W++}Q+=this._lengths[Y]}this._vertices=new Array(B.length);var ae=[t,F],ad=[t+this._bases[0],F],ac=[t+(this._bases[0]-this._bases[this._bases.length-1])/2,F+this._length],ab=[ac[0]+this._bases[this._bases.length-1],ac[1]];function V(ag){var x=(ae[1]-ac[1])/(ae[0]-ac[0]);var v=ae[1]-x*ae[0];var ah=ag+ae[1];return[(ah-v)/x,ah]}function D(ag){var x=(ad[1]-ab[1])/(ad[0]-ab[0]);var v=ad[1]-x*ad[0];var ah=ag+ad[1];return[(ah-v)/x,ah]}var T=w,S=u;var Z=0,m=0;for(Y=0;Y<B.length;Y++){this._vertices[Y]=new Array();var U=this._vertices[Y];var A=this.sectionMargin;if(Y==0){m=0}if(Y==1){m=A/3}else{if(Y>0&&Y<B.length-1){m=A/2}else{if(Y==B.length-1){m=2*A/3}}}U.push(V(Z+m));U.push(D(Z+m));Z+=this._lengths[Y];if(Y==0){m=-2*A/3}else{if(Y>0&&Y<B.length-1){m=-A/2}else{if(Y==B.length-1){m=0}}}U.push(D(Z+m));U.push(V(Z+m))}if(this.shadow){var af="rgba(0,0,0,"+this.shadowAlpha+")";for(var Y=0;Y<B.length;Y++){this.renderer.drawSection.call(this,G,this._vertices[Y],af,true)}}for(var Y=0;Y<B.length;Y++){var U=this._vertices[Y];this.renderer.drawSection.call(this,G,U,this.seriesColors[Y]);if(this.showDataLabels&&B[Y][1]*100>=this.dataLabelThreshold){var K,X;if(this.dataLabels=="label"){K=this.dataLabelFormatString||"%s";X=e.jqplot.sprintf(K,B[Y][0])}else{if(this.dataLabels=="value"){K=this.dataLabelFormatString||"%d";X=e.jqplot.sprintf(K,this.data[Y][1])}else{if(this.dataLabels=="percent"){K=this.dataLabelFormatString||"%d%%";X=e.jqplot.sprintf(K,B[Y][1]*100)}else{if(this.dataLabels.constructor==Array){K=this.dataLabelFormatString||"%s";X=e.jqplot.sprintf(K,this.dataLabels[this._dataIndices[Y]])}}}}var s=(this._radius)*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var T=(U[0][0]+U[1][0])/2+this.canvas._offsets.left;var S=(U[1][1]+U[2][1])/2+this.canvas._offsets.top;var z=e('<span class="jqplot-funnel-series jqplot-data-label" style="position:absolute;">'+X+"</span>").insertBefore(p.eventCanvas._elem);T-=z.width()/2;S-=z.height()/2;T=Math.round(T);S=Math.round(S);z.css({left:T,top:S})}}};e.jqplot.FunnelAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.FunnelAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.FunnelAxisRenderer.prototype.constructor=e.jqplot.FunnelAxisRenderer;e.jqplot.FunnelAxisRenderer.prototype.init=function(m){this.tickRenderer=e.jqplot.FunnelTickRenderer;e.extend(true,this,m);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.FunnelLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.FunnelLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.FunnelLegendRenderer.prototype.constructor=e.jqplot.FunnelLegendRenderer;e.jqplot.FunnelLegendRenderer.prototype.init=function(m){this.numberRows=null;this.numberColumns=null;e.extend(true,this,m)};e.jqplot.FunnelLegendRenderer.prototype.draw=function(){var p=this;if(this.show){var x=this._series;var A="position:absolute;";A+=(this.background)?"background:"+this.background+";":"";A+=(this.border)?"border:"+this.border+";":"";A+=(this.fontSize)?"font-size:"+this.fontSize+";":"";A+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";A+=(this.textColor)?"color:"+this.textColor+";":"";A+=(this.marginTop!=null)?"margin-top:"+this.marginTop+";":"";A+=(this.marginBottom!=null)?"margin-bottom:"+this.marginBottom+";":"";A+=(this.marginLeft!=null)?"margin-left:"+this.marginLeft+";":"";A+=(this.marginRight!=null)?"margin-right:"+this.marginRight+";":"";this._elem=e('<table class="jqplot-table-legend" style="'+A+'"></table>');var E=false,w=false,m,u;var y=x[0];var n=new e.jqplot.ColorGenerator(y.seriesColors);if(y.show){var F=y.data;if(this.numberRows){m=this.numberRows;if(!this.numberColumns){u=Math.ceil(F.length/m)}else{u=this.numberColumns}}else{if(this.numberColumns){u=this.numberColumns;m=Math.ceil(F.length/this.numberColumns)}else{m=F.length;u=1}}var D,C,o,r,q,t,v,B;var z=0;for(D=0;D<m;D++){if(w){o=e('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem)}else{o=e('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem)}for(C=0;C<u;C++){if(z<F.length){t=this.labels[z]||F[z][0].toString();B=n.next();if(!w){if(D>0){E=true}else{E=false}}else{if(D==m-1){E=false}else{E=true}}v=(E)?this.rowSpacing:"0";r=e('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+v+';"><div><div class="jqplot-table-legend-swatch" style="border-color:'+B+';"></div></div></td>');q=e('<td class="jqplot-table-legend" style="padding-top:'+v+';"></td>');if(this.escapeHtml){q.text(t)}else{q.html(t)}if(w){q.prependTo(o);r.prependTo(o)}else{r.appendTo(o);q.appendTo(o)}E=true}z++}}}}return this._elem};function c(q,p,n){n=n||{};n.axesDefaults=n.axesDefaults||{};n.legend=n.legend||{};n.seriesDefaults=n.seriesDefaults||{};var m=false;if(n.seriesDefaults.renderer==e.jqplot.FunnelRenderer){m=true}else{if(n.series){for(var o=0;o<n.series.length;o++){if(n.series[o].renderer==e.jqplot.FunnelRenderer){m=true}}}}if(m){n.axesDefaults.renderer=e.jqplot.FunnelAxisRenderer;n.legend.renderer=e.jqplot.FunnelLegendRenderer;n.legend.preDraw=true;n.sortData=false;n.seriesDefaults.pointLabels={show:false}}}function g(p,o,m){for(var n=0;n<this.series.length;n++){if(this.series[n].renderer.constructor==e.jqplot.FunnelRenderer){if(this.series[n].highlightMouseOver){this.series[n].highlightMouseDown=false}}}this.target.bind("mouseout",{plot:this},function(q){i(q.data.plot)})}function k(m){for(var n=0;n<this.series.length;n++){this.series[n].seriesColors=this.seriesColors;this.series[n].colorGenerator=this.colorGenerator}}function d(q,p,o){var n=q.series[p];var m=q.plugins.funnelRenderer.highlightCanvas;m._ctx.clearRect(0,0,m._ctx.canvas.width,m._ctx.canvas.height);n._highlightedPoint=o;q.plugins.funnelRenderer.highlightedSeriesIndex=p;n.renderer.drawSection.call(n,m._ctx,n._vertices[o],n.highlightColors[o],false)}function i(o){var m=o.plugins.funnelRenderer.highlightCanvas;m._ctx.clearRect(0,0,m._ctx.canvas.width,m._ctx.canvas.height);for(var n=0;n<o.series.length;n++){o.series[n]._highlightedPoint=null}o.plugins.funnelRenderer.highlightedSeriesIndex=null;o.target.trigger("jqplotDataUnhighlight")}function a(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];var n=jQuery.Event("jqplotDataMouseOver");n.pageX=q.pageX;n.pageY=q.pageY;r.target.trigger(n,o);if(r.series[o[0]].highlightMouseOver&&!(o[0]==r.plugins.funnelRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){var m=jQuery.Event("jqplotDataHighlight");m.pageX=q.pageX;m.pageY=q.pageY;r.target.trigger(m,o);d(r,o[0],o[1])}}else{if(s==null){i(r)}}}function b(p,o,s,r,q){if(r){var n=[r.seriesIndex,r.pointIndex,r.data];if(q.series[n[0]].highlightMouseDown&&!(n[0]==q.plugins.funnelRenderer.highlightedSeriesIndex&&n[1]==q.series[n[0]]._highlightedPoint)){var m=jQuery.Event("jqplotDataHighlight");m.pageX=p.pageX;m.pageY=p.pageY;q.target.trigger(m,n);d(q,n[0],n[1])}}else{if(r==null){i(q)}}}function j(o,n,r,q,p){var m=p.plugins.funnelRenderer.highlightedSeriesIndex;if(m!=null&&p.series[m].highlightMouseDown){i(p)}}function f(p,o,s,r,q){if(r){var n=[r.seriesIndex,r.pointIndex,r.data];var m=jQuery.Event("jqplotDataClick");m.pageX=p.pageX;m.pageY=p.pageY;q.target.trigger(m,n)}}function l(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];var m=r.plugins.funnelRenderer.highlightedSeriesIndex;if(m!=null&&r.series[m].highlightMouseDown){i(r)}var n=jQuery.Event("jqplotDataRightClick");n.pageX=q.pageX;n.pageY=q.pageY;r.target.trigger(n,o)}}function h(){if(this.plugins.funnelRenderer&&this.plugins.funnelRenderer.highlightCanvas){this.plugins.funnelRenderer.highlightCanvas.resetCanvas();this.plugins.funnelRenderer.highlightCanvas=null}this.plugins.funnelRenderer={};this.plugins.funnelRenderer.highlightCanvas=new e.jqplot.GenericCanvas();var n=e(this.targetId+" .jqplot-data-label");if(n.length){e(n[0]).before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-funnelRenderer-highlight-canvas",this._plotDimensions,this))}else{this.eventCanvas._elem.before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-funnelRenderer-highlight-canvas",this._plotDimensions,this))}var m=this.plugins.funnelRenderer.highlightCanvas.setContext()}e.jqplot.preInitHooks.push(c);e.jqplot.FunnelTickRenderer=function(){e.jqplot.AxisTickRenderer.call(this)};e.jqplot.FunnelTickRenderer.prototype=new e.jqplot.AxisTickRenderer();e.jqplot.FunnelTickRenderer.prototype.constructor=e.jqplot.FunnelTickRenderer})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.highlighter.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.highlighter.js new file mode 100644 index 0000000000..48078eb88d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.highlighter.js @@ -0,0 +1,421 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]); + + /** + * Class: $.jqplot.Highlighter + * Plugin which will highlight data points when they are moused over. + * + * To use this plugin, include the js + * file in your source: + * + * > <script type="text/javascript" src="plugins/jqplot.highlighter.js"></script> + * + * A tooltip providing information about the data point is enabled by default. + * To disable the tooltip, set "showTooltip" to false. + * + * You can control what data is displayed in the tooltip with various + * options. The "tooltipAxes" option controls wether the x, y or both + * data values are displayed. + * + * Some chart types (e.g. hi-low-close) have more than one y value per + * data point. To display the additional values in the tooltip, set the + * "yvalues" option to the desired number of y values present (3 for a hlc chart). + * + * By default, data values will be formatted with the same formatting + * specifiers as used to format the axis ticks. A custom format code + * can be supplied with the tooltipFormatString option. This will apply + * to all values in the tooltip. + * + * For more complete control, the "formatString" option can be set. This + * Allows conplete control over tooltip formatting. Values are passed to + * the format string in an order determined by the "tooltipAxes" and "yvalues" + * options. So, if you have a hi-low-close chart and you just want to display + * the hi-low-close values in the tooltip, you could set a formatString like: + * + * > highlighter: { + * > tooltipAxes: 'y', + * > yvalues: 3, + * > formatString:'<table class="jqplot-highlighter"> + * > <tr><td>hi:</td><td>%s</td></tr> + * > <tr><td>low:</td><td>%s</td></tr> + * > <tr><td>close:</td><td>%s</td></tr></table>' + * > } + * + */ + $.jqplot.Highlighter = function(options) { + // Group: Properties + // + //prop: show + // true to show the highlight. + this.show = $.jqplot.config.enablePlugins; + // prop: markerRenderer + // Renderer used to draw the marker of the highlighted point. + // Renderer will assimilate attributes from the data point being highlighted, + // so no attributes need set on the renderer directly. + // Default is to turn off shadow drawing on the highlighted point. + this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false}); + // prop: showMarker + // true to show the marker + this.showMarker = true; + // prop: lineWidthAdjust + // Pixels to add to the lineWidth of the highlight. + this.lineWidthAdjust = 2.5; + // prop: sizeAdjust + // Pixels to add to the overall size of the highlight. + this.sizeAdjust = 5; + // prop: showTooltip + // Show a tooltip with data point values. + this.showTooltip = true; + // prop: tooltipLocation + // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw' + this.tooltipLocation = 'nw'; + // prop: fadeTooltip + // true = fade in/out tooltip, flase = show/hide tooltip + this.fadeTooltip = true; + // prop: tooltipFadeSpeed + // 'slow', 'def', 'fast', or number of milliseconds. + this.tooltipFadeSpeed = "fast"; + // prop: tooltipOffset + // Pixel offset of tooltip from the highlight. + this.tooltipOffset = 2; + // prop: tooltipAxes + // Which axes to display in tooltip, 'x', 'y' or 'both', 'xy' or 'yx' + // 'both' and 'xy' are equivalent, 'yx' reverses order of labels. + this.tooltipAxes = 'both'; + // prop; tooltipSeparator + // String to use to separate x and y axes in tooltip. + this.tooltipSeparator = ', '; + // prop; tooltipContentEditor + // Function used to edit/augment/replace the formatted tooltip contents. + // Called as str = tooltipContentEditor(str, seriesIndex, pointIndex) + // where str is the generated tooltip html and seriesIndex and pointIndex identify + // the data point being highlighted. Should return the html for the tooltip contents. + this.tooltipContentEditor = null; + // prop: useAxesFormatters + // Use the x and y axes formatters to format the text in the tooltip. + this.useAxesFormatters = true; + // prop: tooltipFormatString + // sprintf format string for the tooltip. + // Uses Ash Searle's javascript sprintf implementation + // found here: http://hexmen.com/blog/2007/03/printf-sprintf/ + // See http://perldoc.perl.org/functions/sprintf.html for reference. + // Additional "p" and "P" format specifiers added by Chris Leonello. + this.tooltipFormatString = '%.5P'; + // prop: formatString + // alternative to tooltipFormatString + // will format the whole tooltip text, populating with x, y values as + // indicated by tooltipAxes option. So, you could have a tooltip like: + // 'Date: %s, number of cats: %d' to format the whole tooltip at one go. + // If useAxesFormatters is true, values will be formatted according to + // Axes formatters and you can populate your tooltip string with + // %s placeholders. + this.formatString = null; + // prop: yvalues + // Number of y values to expect in the data point array. + // Typically this is 1. Certain plots, like OHLC, will + // have more y values in each data point array. + this.yvalues = 1; + // prop: bringSeriesToFront + // This option requires jQuery 1.4+ + // True to bring the series of the highlighted point to the front + // of other series. + this.bringSeriesToFront = false; + this._tooltipElem; + this.isHighlighting = false; + + $.extend(true, this, options); + }; + + var locations = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']; + var locationIndicies = {'nw':0, 'n':1, 'ne':2, 'e':3, 'se':4, 's':5, 'sw':6, 'w':7}; + var oppositeLocations = ['se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e']; + + // axis.renderer.tickrenderer.formatter + + // called with scope of plot + $.jqplot.Highlighter.init = function (target, data, opts){ + var options = opts || {}; + // add a highlighter attribute to the plot + this.plugins.highlighter = new $.jqplot.Highlighter(options.highlighter); + }; + + // called within scope of series + $.jqplot.Highlighter.parseOptions = function (defaults, options) { + // Add a showHighlight option to the series + // and set it to true by default. + this.showHighlight = true; + }; + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + $.jqplot.Highlighter.postPlotDraw = function() { + // Memory Leaks patch + if (this.plugins.highlighter && this.plugins.highlighter.highlightCanvas) { + this.plugins.highlighter.highlightCanvas.resetCanvas(); + this.plugins.highlighter.highlightCanvas = null; + } + + if (this.plugins.highlighter && this.plugins.highlighter._tooltipElem) { + this.plugins.highlighter._tooltipElem.emptyForce(); + this.plugins.highlighter._tooltipElem = null; + } + + this.plugins.highlighter.highlightCanvas = new $.jqplot.GenericCanvas(); + + this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding, 'jqplot-highlight-canvas', this._plotDimensions, this)); + this.plugins.highlighter.highlightCanvas.setContext(); + + var elem = document.createElement('div'); + this.plugins.highlighter._tooltipElem = $(elem); + elem = null; + this.plugins.highlighter._tooltipElem.addClass('jqplot-highlighter-tooltip'); + this.plugins.highlighter._tooltipElem.css({position:'absolute', display:'none'}); + + this.eventCanvas._elem.before(this.plugins.highlighter._tooltipElem); + }; + + $.jqplot.preInitHooks.push($.jqplot.Highlighter.init); + $.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Highlighter.parseOptions); + $.jqplot.postDrawHooks.push($.jqplot.Highlighter.postPlotDraw); + + function draw(plot, neighbor) { + var hl = plot.plugins.highlighter; + var s = plot.series[neighbor.seriesIndex]; + var smr = s.markerRenderer; + var mr = hl.markerRenderer; + mr.style = smr.style; + mr.lineWidth = smr.lineWidth + hl.lineWidthAdjust; + mr.size = smr.size + hl.sizeAdjust; + var rgba = $.jqplot.getColorComponents(smr.color); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var alpha = (rgba[3] >= 0.6) ? rgba[3]*0.6 : rgba[3]*(2-rgba[3]); + mr.color = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+alpha+')'; + mr.init(); + mr.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], hl.highlightCanvas._ctx); + } + + function showTooltip(plot, series, neighbor) { + // neighbor looks like: {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]} + // gridData should be x,y pixel coords on the grid. + // add the plot._gridPadding to that to get x,y in the target. + var hl = plot.plugins.highlighter; + var elem = hl._tooltipElem; + if (hl.useAxesFormatters) { + var xf = series._xaxis._ticks[0].formatter; + var yf = series._yaxis._ticks[0].formatter; + var xfstr = series._xaxis._ticks[0].formatString; + var yfstr = series._yaxis._ticks[0].formatString; + var str; + var xstr = xf(xfstr, neighbor.data[0]); + var ystrs = []; + for (var i=1; i<hl.yvalues+1; i++) { + ystrs.push(yf(yfstr, neighbor.data[i])); + } + if (hl.formatString) { + switch (hl.tooltipAxes) { + case 'both': + case 'xy': + ystrs.unshift(xstr); + ystrs.unshift(hl.formatString); + str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs); + break; + case 'yx': + ystrs.push(xstr); + ystrs.unshift(hl.formatString); + str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs); + break; + case 'x': + str = $.jqplot.sprintf.apply($.jqplot.sprintf, [hl.formatString, xstr]); + break; + case 'y': + ystrs.unshift(hl.formatString); + str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs); + break; + default: // same as xy + ystrs.unshift(xstr); + ystrs.unshift(hl.formatString); + str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs); + break; + } + } + else { + switch (hl.tooltipAxes) { + case 'both': + case 'xy': + str = xstr; + for (var i=0; i<ystrs.length; i++) { + str += hl.tooltipSeparator + ystrs[i]; + } + break; + case 'yx': + str = ''; + for (var i=0; i<ystrs.length; i++) { + str += ystrs[i] + hl.tooltipSeparator; + } + str += xstr; + break; + case 'x': + str = xstr; + break; + case 'y': + str = ystrs.join(hl.tooltipSeparator); + break; + default: // same as 'xy' + str = xstr; + for (var i=0; i<ystrs.length; i++) { + str += hl.tooltipSeparator + ystrs[i]; + } + break; + + } + } + } + else { + var str; + if (hl.tooltipAxes == 'both' || hl.tooltipAxes == 'xy') { + str = $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[0]) + hl.tooltipSeparator + $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[1]); + } + else if (hl.tooltipAxes == 'yx') { + str = $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[1]) + hl.tooltipSeparator + $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[0]); + } + else if (hl.tooltipAxes == 'x') { + str = $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[0]); + } + else if (hl.tooltipAxes == 'y') { + str = $.jqplot.sprintf(hl.tooltipFormatString, neighbor.data[1]); + } + } + if ($.isFunction(hl.tooltipContentEditor)) { + // args str, seriesIndex, pointIndex are essential so the hook can look up + // extra data for the point. + str = hl.tooltipContentEditor(str, neighbor.seriesIndex, neighbor.pointIndex, plot); + } + elem.html(str); + var gridpos = {x:neighbor.gridData[0], y:neighbor.gridData[1]}; + var ms = 0; + var fact = 0.707; + if (series.markerRenderer.show == true) { + ms = (series.markerRenderer.size + hl.sizeAdjust)/2; + } + + var loc = locations; + if (series.fillToZero && series.fill && neighbor.data[1] < 0) { + loc = oppositeLocations; + } + + switch (loc[locationIndicies[hl.tooltipLocation]]) { + case 'nw': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - hl.tooltipOffset - fact * ms; + var y = gridpos.y + plot._gridPadding.top - hl.tooltipOffset - elem.outerHeight(true) - fact * ms; + break; + case 'n': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2; + var y = gridpos.y + plot._gridPadding.top - hl.tooltipOffset - elem.outerHeight(true) - ms; + break; + case 'ne': + var x = gridpos.x + plot._gridPadding.left + hl.tooltipOffset + fact * ms; + var y = gridpos.y + plot._gridPadding.top - hl.tooltipOffset - elem.outerHeight(true) - fact * ms; + break; + case 'e': + var x = gridpos.x + plot._gridPadding.left + hl.tooltipOffset + ms; + var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2; + break; + case 'se': + var x = gridpos.x + plot._gridPadding.left + hl.tooltipOffset + fact * ms; + var y = gridpos.y + plot._gridPadding.top + hl.tooltipOffset + fact * ms; + break; + case 's': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2; + var y = gridpos.y + plot._gridPadding.top + hl.tooltipOffset + ms; + break; + case 'sw': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - hl.tooltipOffset - fact * ms; + var y = gridpos.y + plot._gridPadding.top + hl.tooltipOffset + fact * ms; + break; + case 'w': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - hl.tooltipOffset - ms; + var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2; + break; + default: // same as 'nw' + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - hl.tooltipOffset - fact * ms; + var y = gridpos.y + plot._gridPadding.top - hl.tooltipOffset - elem.outerHeight(true) - fact * ms; + break; + } + elem.css('left', x); + elem.css('top', y); + if (hl.fadeTooltip) { + // Fix for stacked up animations. Thnanks Trevor! + elem.stop(true,true).fadeIn(hl.tooltipFadeSpeed); + } + else { + elem.show(); + } + elem = null; + + } + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + var hl = plot.plugins.highlighter; + var c = plot.plugins.cursor; + if (hl.show) { + if (neighbor == null && hl.isHighlighting) { + var ctx = hl.highlightCanvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + if (hl.fadeTooltip) { + hl._tooltipElem.fadeOut(hl.tooltipFadeSpeed); + } + else { + hl._tooltipElem.hide(); + } + if (hl.bringSeriesToFront) { + plot.restorePreviousSeriesOrder(); + } + hl.isHighlighting = false; + ctx = null; + + } + else if (neighbor != null && plot.series[neighbor.seriesIndex].showHighlight && !hl.isHighlighting) { + hl.isHighlighting = true; + if (hl.showMarker) { + draw(plot, neighbor); + } + if (hl.showTooltip && (!c || !c._zoom.started)) { + showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor); + } + if (hl.bringSeriesToFront) { + plot.moveSeriesToFront(neighbor.seriesIndex); + } + } + } + } +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.highlighter.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.highlighter.min.js new file mode 100644 index 0000000000..04ad197b9c --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.highlighter.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(d){d.jqplot.eventListenerHooks.push(["jqplotMouseMove",f]);d.jqplot.Highlighter=function(h){this.show=d.jqplot.config.enablePlugins;this.markerRenderer=new d.jqplot.MarkerRenderer({shadow:false});this.showMarker=true;this.lineWidthAdjust=2.5;this.sizeAdjust=5;this.showTooltip=true;this.tooltipLocation="nw";this.fadeTooltip=true;this.tooltipFadeSpeed="fast";this.tooltipOffset=2;this.tooltipAxes="both";this.tooltipSeparator=", ";this.tooltipContentEditor=null;this.useAxesFormatters=true;this.tooltipFormatString="%.5P";this.formatString=null;this.yvalues=1;this.bringSeriesToFront=false;this._tooltipElem;this.isHighlighting=false;d.extend(true,this,h)};var b=["nw","n","ne","e","se","s","sw","w"];var e={nw:0,n:1,ne:2,e:3,se:4,s:5,sw:6,w:7};var c=["se","s","sw","w","nw","n","ne","e"];d.jqplot.Highlighter.init=function(k,j,i){var h=i||{};this.plugins.highlighter=new d.jqplot.Highlighter(h.highlighter)};d.jqplot.Highlighter.parseOptions=function(i,h){this.showHighlight=true};d.jqplot.Highlighter.postPlotDraw=function(){if(this.plugins.highlighter&&this.plugins.highlighter.highlightCanvas){this.plugins.highlighter.highlightCanvas.resetCanvas();this.plugins.highlighter.highlightCanvas=null}if(this.plugins.highlighter&&this.plugins.highlighter._tooltipElem){this.plugins.highlighter._tooltipElem.emptyForce();this.plugins.highlighter._tooltipElem=null}this.plugins.highlighter.highlightCanvas=new d.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding,"jqplot-highlight-canvas",this._plotDimensions,this));this.plugins.highlighter.highlightCanvas.setContext();var h=document.createElement("div");this.plugins.highlighter._tooltipElem=d(h);h=null;this.plugins.highlighter._tooltipElem.addClass("jqplot-highlighter-tooltip");this.plugins.highlighter._tooltipElem.css({position:"absolute",display:"none"});this.eventCanvas._elem.before(this.plugins.highlighter._tooltipElem)};d.jqplot.preInitHooks.push(d.jqplot.Highlighter.init);d.jqplot.preParseSeriesOptionsHooks.push(d.jqplot.Highlighter.parseOptions);d.jqplot.postDrawHooks.push(d.jqplot.Highlighter.postPlotDraw);function a(m,o){var j=m.plugins.highlighter;var p=m.series[o.seriesIndex];var h=p.markerRenderer;var i=j.markerRenderer;i.style=h.style;i.lineWidth=h.lineWidth+j.lineWidthAdjust;i.size=h.size+j.sizeAdjust;var l=d.jqplot.getColorComponents(h.color);var n=[l[0],l[1],l[2]];var k=(l[3]>=0.6)?l[3]*0.6:l[3]*(2-l[3]);i.color="rgba("+n[0]+","+n[1]+","+n[2]+","+k+")";i.init();i.draw(p.gridData[o.pointIndex][0],p.gridData[o.pointIndex][1],j.highlightCanvas._ctx)}function g(w,q,m){var k=w.plugins.highlighter;var B=k._tooltipElem;if(k.useAxesFormatters){var u=q._xaxis._ticks[0].formatter;var h=q._yaxis._ticks[0].formatter;var C=q._xaxis._ticks[0].formatString;var r=q._yaxis._ticks[0].formatString;var v;var s=u(C,m.data[0]);var l=[];for(var z=1;z<k.yvalues+1;z++){l.push(h(r,m.data[z]))}if(k.formatString){switch(k.tooltipAxes){case"both":case"xy":l.unshift(s);l.unshift(k.formatString);v=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;case"yx":l.push(s);l.unshift(k.formatString);v=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;case"x":v=d.jqplot.sprintf.apply(d.jqplot.sprintf,[k.formatString,s]);break;case"y":l.unshift(k.formatString);v=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;default:l.unshift(s);l.unshift(k.formatString);v=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break}}else{switch(k.tooltipAxes){case"both":case"xy":v=s;for(var z=0;z<l.length;z++){v+=k.tooltipSeparator+l[z]}break;case"yx":v="";for(var z=0;z<l.length;z++){v+=l[z]+k.tooltipSeparator}v+=s;break;case"x":v=s;break;case"y":v=l.join(k.tooltipSeparator);break;default:v=s;for(var z=0;z<l.length;z++){v+=k.tooltipSeparator+l[z]}break}}}else{var v;if(k.tooltipAxes=="both"||k.tooltipAxes=="xy"){v=d.jqplot.sprintf(k.tooltipFormatString,m.data[0])+k.tooltipSeparator+d.jqplot.sprintf(k.tooltipFormatString,m.data[1])}else{if(k.tooltipAxes=="yx"){v=d.jqplot.sprintf(k.tooltipFormatString,m.data[1])+k.tooltipSeparator+d.jqplot.sprintf(k.tooltipFormatString,m.data[0])}else{if(k.tooltipAxes=="x"){v=d.jqplot.sprintf(k.tooltipFormatString,m.data[0])}else{if(k.tooltipAxes=="y"){v=d.jqplot.sprintf(k.tooltipFormatString,m.data[1])}}}}}if(d.isFunction(k.tooltipContentEditor)){v=k.tooltipContentEditor(v,m.seriesIndex,m.pointIndex,w)}B.html(v);var A={x:m.gridData[0],y:m.gridData[1]};var t=0;var j=0.707;if(q.markerRenderer.show==true){t=(q.markerRenderer.size+k.sizeAdjust)/2}var o=b;if(q.fillToZero&&q.fill&&m.data[1]<0){o=c}switch(o[e[k.tooltipLocation]]){case"nw":var p=A.x+w._gridPadding.left-B.outerWidth(true)-k.tooltipOffset-j*t;var n=A.y+w._gridPadding.top-k.tooltipOffset-B.outerHeight(true)-j*t;break;case"n":var p=A.x+w._gridPadding.left-B.outerWidth(true)/2;var n=A.y+w._gridPadding.top-k.tooltipOffset-B.outerHeight(true)-t;break;case"ne":var p=A.x+w._gridPadding.left+k.tooltipOffset+j*t;var n=A.y+w._gridPadding.top-k.tooltipOffset-B.outerHeight(true)-j*t;break;case"e":var p=A.x+w._gridPadding.left+k.tooltipOffset+t;var n=A.y+w._gridPadding.top-B.outerHeight(true)/2;break;case"se":var p=A.x+w._gridPadding.left+k.tooltipOffset+j*t;var n=A.y+w._gridPadding.top+k.tooltipOffset+j*t;break;case"s":var p=A.x+w._gridPadding.left-B.outerWidth(true)/2;var n=A.y+w._gridPadding.top+k.tooltipOffset+t;break;case"sw":var p=A.x+w._gridPadding.left-B.outerWidth(true)-k.tooltipOffset-j*t;var n=A.y+w._gridPadding.top+k.tooltipOffset+j*t;break;case"w":var p=A.x+w._gridPadding.left-B.outerWidth(true)-k.tooltipOffset-t;var n=A.y+w._gridPadding.top-B.outerHeight(true)/2;break;default:var p=A.x+w._gridPadding.left-B.outerWidth(true)-k.tooltipOffset-j*t;var n=A.y+w._gridPadding.top-k.tooltipOffset-B.outerHeight(true)-j*t;break}B.css("left",p);B.css("top",n);if(k.fadeTooltip){B.stop(true,true).fadeIn(k.tooltipFadeSpeed)}else{B.show()}B=null}function f(k,j,n,m,l){var h=l.plugins.highlighter;var o=l.plugins.cursor;if(h.show){if(m==null&&h.isHighlighting){var i=h.highlightCanvas._ctx;i.clearRect(0,0,i.canvas.width,i.canvas.height);if(h.fadeTooltip){h._tooltipElem.fadeOut(h.tooltipFadeSpeed)}else{h._tooltipElem.hide()}if(h.bringSeriesToFront){l.restorePreviousSeriesOrder()}h.isHighlighting=false;i=null}else{if(m!=null&&l.series[m.seriesIndex].showHighlight&&!h.isHighlighting){h.isHighlighting=true;if(h.showMarker){a(l,m)}if(h.showTooltip&&(!o||!o._zoom.started)){g(l,l.series[m.seriesIndex],m)}if(h.bringSeriesToFront){l.moveSeriesToFront(m.seriesIndex)}}}}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.json2.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.json2.js new file mode 100644 index 0000000000..46fb942baa --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.json2.js @@ -0,0 +1,475 @@ +/* + 2010-11-01 Chris Leonello + + Slightly modified version of the original json2.js to put JSON + functions under the $.jqplot namespace. + + licensing and orignal comments follow: + + http://www.JSON.org/json2.js + 2010-08-25 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + $.jqplot.JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + $.jqplot.JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = $.jqplot.JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = $.jqplot.JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = $.jqplot.JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + $.jqplot.JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = $.jqplot.JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = $.jqplot.JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +(function($) { + + $.jqplot.JSON = window.JSON; + + if (!window.JSON) { + $.jqplot.JSON = {}; + } + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof $.jqplot.JSON.stringify !== 'function') { + $.jqplot.JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('$.jqplot.JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof $.jqplot.JSON.parse !== 'function') { + $.jqplot.JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('$.jqplot.JSON.parse'); + }; + } +})(jQuery); diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.json2.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.json2.min.js new file mode 100644 index 0000000000..8818f36523 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.json2.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($){$.jqplot.JSON=window.JSON;if(!window.JSON){$.jqplot.JSON={}}function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof $.jqplot.JSON.stringify!=="function"){$.jqplot.JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("$.jqplot.JSON.stringify")}return str("",{"":value})}}if(typeof $.jqplot.JSON.parse!=="function"){$.jqplot.JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("$.jqplot.JSON.parse")}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.logAxisRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.logAxisRenderer.js new file mode 100644 index 0000000000..1fd7adb7b7 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.logAxisRenderer.js @@ -0,0 +1,446 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * class: $.jqplot.LogAxisRenderer + * A plugin for a jqPlot to render a logarithmic axis. + * + * To use this renderer, include the plugin in your source + * > <script type="text/javascript" language="javascript" src="plugins/jqplot.logAxisRenderer.js"></script> + * + * and supply the appropriate options to your plot + * + * > {axes:{xaxis:{renderer:$.jqplot.LogAxisRenderer}}} + **/ + $.jqplot.LogAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + // prop: axisDefaults + // Default properties which will be applied directly to the series. + // + // Group: Properties + // + // Properties + // + /// base - the logarithmic base, commonly 2, 10 or Math.E + // tickDistribution - 'even' or 'power'. 'even' gives equal pixel + // spacing of the ticks on the plot. 'power' gives ticks in powers + // of 10. + this.axisDefaults = { + base : 10, + tickDistribution :'even' + }; + }; + + $.jqplot.LogAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.LogAxisRenderer.prototype.constructor = $.jqplot.LogAxisRenderer; + + $.jqplot.LogAxisRenderer.prototype.init = function(options) { + // prop: tickRenderer + // A class of a rendering engine for creating the ticks labels displayed on the plot, + // See <$.jqplot.AxisTickRenderer>. + // this.tickRenderer = $.jqplot.AxisTickRenderer; + // this.labelRenderer = $.jqplot.AxisLabelRenderer; + $.extend(true, this.renderer, options); + for (var d in this.renderer.axisDefaults) { + if (this[d] == null) { + this[d] = this.renderer.axisDefaults[d]; + } + } + var db = this._dataBounds; + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + var d = s.data; + + for (var j=0; j<d.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + if ((d[j][0] != null && d[j][0] < db.min) || db.min == null) { + db.min = d[j][0]; + } + if ((d[j][0] != null && d[j][0] > db.max) || db.max == null) { + db.max = d[j][0]; + } + } + else { + if ((d[j][1] != null && d[j][1] < db.min) || db.min == null) { + db.min = d[j][1]; + } + if ((d[j][1] != null && d[j][1] > db.max) || db.max == null) { + db.max = d[j][1]; + } + } + } + } + }; + + $.jqplot.LogAxisRenderer.prototype.createTicks = function() { + // we're are operating on an axis here + var ticks = this._ticks; + var userTicks = this.ticks; + var name = this.name; + var db = this._dataBounds; + var dim, interval; + var min, max; + var pos1, pos2; + var tt, i; + + // if we already have ticks, use them. + // ticks must be in order of increasing value. + if (userTicks.length) { + // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed + for (i=0; i<userTicks.length; i++){ + var ut = userTicks[i]; + var t = new this.tickRenderer(this.tickOptions); + if (ut.constructor == Array) { + t.value = ut[0]; + t.label = ut[1]; + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(ut[0], this.name); + this._ticks.push(t); + } + + else { + t.value = ut; + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(ut, this.name); + this._ticks.push(t); + } + } + this.numberTicks = userTicks.length; + this.min = this._ticks[0].value; + this.max = this._ticks[this.numberTicks-1].value; + } + + // we don't have any ticks yet, let's make some! + else { + if (name == 'xaxis' || name == 'x2axis') { + dim = this._plotDimensions.width; + } + else { + dim = this._plotDimensions.height; + } + + min = ((this.min != null) ? this.min : db.min); + max = ((this.max != null) ? this.max : db.max); + + // if min and max are same, space them out a bit + if (min == max) { + var adj = 0.05; + min = min*(1-adj); + max = max*(1+adj); + } + + // perform some checks + if (this.min != null && this.min <= 0) { + throw('log axis minimum must be greater than 0'); + } + if (this.max != null && this.max <= 0) { + throw('log axis maximum must be greater than 0'); + } + // if (this.pad >1.99) this.pad = 1.99; + var range = max - min; + var rmin, rmax; + + if (this.tickDistribution == 'even') { + rmin = (this.min != null) ? this.min : min - min*((this.padMin-1)/2); + rmax = (this.max != null) ? this.max : max + max*((this.padMax-1)/2); + this.min = rmin; + this.max = rmax; + range = this.max - this.min; + + if (this.numberTicks == null){ + if (dim > 100) { + this.numberTicks = parseInt(3+(dim-100)/75, 10); + } + else { + this.numberTicks = 2; + } + } + + var u = Math.pow(this.base, (1/(this.numberTicks-1)*Math.log(this.max/this.min)/Math.log(this.base))); + for (var i=0; i<this.numberTicks; i++){ + tt = this.min * Math.pow(u, i); + var t = new this.tickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + } + + } + + else if (this.tickDistribution == 'power'){ + // for power distribution, open up range to get a nice power of axis.renderer.base. + // power distribution won't respect the user's min/max settings. + rmin = Math.pow(this.base, Math.ceil(Math.log(min*(2-this.padMin))/Math.log(this.base))-1); + rmax = Math.pow(this.base, Math.floor(Math.log(max*this.padMax)/Math.log(this.base))+1); + this.min = rmin; + this.max = rmax; + range = this.max - this.min; + + var fittedTicks = 0; + var minorTicks = 0; + if (this.numberTicks == null){ + if (dim > 100) { + this.numberTicks = Math.round(Math.log(this.max/this.min)/Math.log(this.base) + 1); + if (this.numberTicks < 2) { + this.numberTicks = 2; + } + fittedTicks = parseInt(3+(dim-100)/75, 10); + } + else { + this.numberTicks = 2; + fittedTicks = 2; + } + // if we don't have enough ticks, add some intermediate ticks + // how many to have between major ticks. + if (this.numberTicks < fittedTicks-1) { + minorTicks = Math.floor(fittedTicks/this.numberTicks); + } + } + + for (var i=0; i<this.numberTicks; i++){ + tt = Math.pow(this.base, i - this.numberTicks + 1) * this.max; + var t = new this.tickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + + if (minorTicks && i<this.numberTicks-1) { + var tt1 = Math.pow(this.base, i - this.numberTicks + 2) * this.max; + var spread = tt1 - tt; + var interval = tt1 / (minorTicks+1); + for (var j=minorTicks-1; j>=0; j--) { + var val = tt1-interval*(j+1); + var t = new this.tickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(val, this.name); + this._ticks.push(t); + } + } + } + } + } + }; + + $.jqplot.LogAxisRenderer.prototype.pack = function(pos, offsets) { + var lb = parseInt(this.base, 10); + var ticks = this._ticks; + var trans = function (v) { return Math.log(v)/Math.log(lb); }; + var invtrans = function (v) { return Math.pow(Math.E, (Math.log(lb)*v)); }; + var max = trans(this.max); + var min = trans(this.min); + var offmax = offsets.max; + var offmin = offsets.min; + var lshow = (this._label == null) ? false : this._label.show; + + for (var p in pos) { + this._elem.css(p, pos[p]); + } + + this._offsets = offsets; + // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left. + var pixellength = offmax - offmin; + var unitlength = max - min; + + // point to unit and unit to point conversions references to Plot DOM element top left corner. + this.p2u = function(p){ + return invtrans((p - offmin) * unitlength / pixellength + min); + }; + + this.u2p = function(u){ + return (trans(u) - min) * pixellength / unitlength + offmin; + }; + + if (this.name == 'xaxis' || this.name == 'x2axis'){ + this.series_u2p = function(u){ + return (trans(u) - min) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return invtrans(p * unitlength / pixellength + min); + }; + } + // yaxis is max at top of canvas. + else { + this.series_u2p = function(u){ + return (trans(u) - max) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return invtrans(p * unitlength / pixellength + max); + }; + } + + if (this.show) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + for (var i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + switch (t.labelPosition) { + case 'auto': + // position at end + if (t.angle < 0) { + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + } + // position at start + else { + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + } + break; + case 'end': + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + case 'start': + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + break; + case 'middle': + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + default: + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + } + } + else { + shim = -t.getWidth()/2; + } + // var shim = t.getWidth()/2; + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('left', val); + t.pack(); + } + } + if (lshow) { + var w = this._label._elem.outerWidth(true); + this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px'); + if (this.name == 'xaxis') { + this._label._elem.css('bottom', '0px'); + } + else { + this._label._elem.css('top', '0px'); + } + this._label.pack(); + } + } + else { + for (var i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + switch (t.labelPosition) { + case 'auto': + // position at end + case 'end': + if (t.angle < 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'start': + if (t.angle > 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'middle': + // if (t.angle > 0) { + // shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + // } + // else { + // shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + // } + shim = -t.getHeight()/2; + break; + default: + shim = -t.getHeight()/2; + break; + } + } + else { + shim = -t.getHeight()/2; + } + + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('top', val); + t.pack(); + } + } + if (lshow) { + var h = this._label._elem.outerHeight(true); + this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px'); + if (this.name == 'yaxis') { + this._label._elem.css('left', '0px'); + } + else { + this._label._elem.css('right', '0px'); + } + this._label.pack(); + } + } + } + }; +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.logAxisRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.logAxisRenderer.min.js new file mode 100644 index 0000000000..227c2ca975 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.logAxisRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.LogAxisRenderer=function(){a.jqplot.LinearAxisRenderer.call(this);this.axisDefaults={base:10,tickDistribution:"even"}};a.jqplot.LogAxisRenderer.prototype=new a.jqplot.LinearAxisRenderer();a.jqplot.LogAxisRenderer.prototype.constructor=a.jqplot.LogAxisRenderer;a.jqplot.LogAxisRenderer.prototype.init=function(e){a.extend(true,this.renderer,e);for(var h in this.renderer.axisDefaults){if(this[h]==null){this[h]=this.renderer.axisDefaults[h]}}var b=this._dataBounds;for(var f=0;f<this._series.length;f++){var g=this._series[f];var h=g.data;for(var c=0;c<h.length;c++){if(this.name=="xaxis"||this.name=="x2axis"){if((h[c][0]!=null&&h[c][0]<b.min)||b.min==null){b.min=h[c][0]}if((h[c][0]!=null&&h[c][0]>b.max)||b.max==null){b.max=h[c][0]}}else{if((h[c][1]!=null&&h[c][1]<b.min)||b.min==null){b.min=h[c][1]}if((h[c][1]!=null&&h[c][1]>b.max)||b.max==null){b.max=h[c][1]}}}}};a.jqplot.LogAxisRenderer.prototype.createTicks=function(){var A=this._ticks;var x=this.ticks;var D=this.name;var z=this._dataBounds;var s,y;var o,v;var e,d;var b,w;if(x.length){for(w=0;w<x.length;w++){var f=x[w];var k=new this.tickRenderer(this.tickOptions);if(f.constructor==Array){k.value=f[0];k.label=f[1];if(!this.showTicks){k.showLabel=false;k.showMark=false}else{if(!this.showTickMarks){k.showMark=false}}k.setTick(f[0],this.name);this._ticks.push(k)}else{k.value=f;if(!this.showTicks){k.showLabel=false;k.showMark=false}else{if(!this.showTickMarks){k.showMark=false}}k.setTick(f,this.name);this._ticks.push(k)}}this.numberTicks=x.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value}else{if(D=="xaxis"||D=="x2axis"){s=this._plotDimensions.width}else{s=this._plotDimensions.height}o=((this.min!=null)?this.min:z.min);v=((this.max!=null)?this.max:z.max);if(o==v){var g=0.05;o=o*(1-g);v=v*(1+g)}if(this.min!=null&&this.min<=0){throw ("log axis minimum must be greater than 0")}if(this.max!=null&&this.max<=0){throw ("log axis maximum must be greater than 0")}var l=v-o;var n,r;if(this.tickDistribution=="even"){n=(this.min!=null)?this.min:o-o*((this.padMin-1)/2);r=(this.max!=null)?this.max:v+v*((this.padMax-1)/2);this.min=n;this.max=r;l=this.max-this.min;if(this.numberTicks==null){if(s>100){this.numberTicks=parseInt(3+(s-100)/75,10)}else{this.numberTicks=2}}var h=Math.pow(this.base,(1/(this.numberTicks-1)*Math.log(this.max/this.min)/Math.log(this.base)));for(var w=0;w<this.numberTicks;w++){b=this.min*Math.pow(h,w);var k=new this.tickRenderer(this.tickOptions);if(!this.showTicks){k.showLabel=false;k.showMark=false}else{if(!this.showTickMarks){k.showMark=false}}k.setTick(b,this.name);this._ticks.push(k)}}else{if(this.tickDistribution=="power"){n=Math.pow(this.base,Math.ceil(Math.log(o*(2-this.padMin))/Math.log(this.base))-1);r=Math.pow(this.base,Math.floor(Math.log(v*this.padMax)/Math.log(this.base))+1);this.min=n;this.max=r;l=this.max-this.min;var q=0;var c=0;if(this.numberTicks==null){if(s>100){this.numberTicks=Math.round(Math.log(this.max/this.min)/Math.log(this.base)+1);if(this.numberTicks<2){this.numberTicks=2}q=parseInt(3+(s-100)/75,10)}else{this.numberTicks=2;q=2}if(this.numberTicks<q-1){c=Math.floor(q/this.numberTicks)}}for(var w=0;w<this.numberTicks;w++){b=Math.pow(this.base,w-this.numberTicks+1)*this.max;var k=new this.tickRenderer(this.tickOptions);if(!this.showTicks){k.showLabel=false;k.showMark=false}else{if(!this.showTickMarks){k.showMark=false}}k.setTick(b,this.name);this._ticks.push(k);if(c&&w<this.numberTicks-1){var m=Math.pow(this.base,w-this.numberTicks+2)*this.max;var B=m-b;var y=m/(c+1);for(var p=c-1;p>=0;p--){var C=m-y*(p+1);var k=new this.tickRenderer(this.tickOptions);if(!this.showTicks){k.showLabel=false;k.showMark=false}else{if(!this.showTickMarks){k.showMark=false}}k.setTick(C,this.name);this._ticks.push(k)}}}}}}};a.jqplot.LogAxisRenderer.prototype.pack=function(f,e){var r=parseInt(this.base,10);var y=this._ticks;var d=function(h){return Math.log(h)/Math.log(r)};var b=function(h){return Math.pow(Math.E,(Math.log(r)*h))};var u=d(this.max);var s=d(this.min);var m=e.max;var k=e.min;var o=(this._label==null)?false:this._label.show;for(var q in f){this._elem.css(q,f[q])}this._offsets=e;var g=m-k;var j=u-s;this.p2u=function(h){return b((h-k)*j/g+s)};this.u2p=function(h){return(d(h)-s)*g/j+k};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(d(h)-s)*g/j};this.series_p2u=function(h){return b(h*j/g+s)}}else{this.series_u2p=function(h){return(d(h)-u)*g/j};this.series_p2u=function(h){return b(h*j/g+u)}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(var v=0;v<y.length;v++){var n=y[v];if(n.show&&n.showLabel){var c;if(n.constructor==a.jqplot.CanvasAxisTickRenderer&&n.angle){switch(n.labelPosition){case"auto":if(n.angle<0){c=-n.getWidth()+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2}else{c=-n._textRenderer.height*Math.sin(n._textRenderer.angle)/2}break;case"end":c=-n.getWidth()+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2;break;case"start":c=-n._textRenderer.height*Math.sin(n._textRenderer.angle)/2;break;case"middle":c=-n.getWidth()/2+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2;break;default:c=-n.getWidth()/2+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2;break}}else{c=-n.getWidth()/2}var z=this.u2p(n.value)+c+"px";n._elem.css("left",z);n.pack()}}if(o){var l=this._label._elem.outerWidth(true);this._label._elem.css("left",k+g/2-l/2+"px");if(this.name=="xaxis"){this._label._elem.css("bottom","0px")}else{this._label._elem.css("top","0px")}this._label.pack()}}else{for(var v=0;v<y.length;v++){var n=y[v];if(n.show&&n.showLabel){var c;if(n.constructor==a.jqplot.CanvasAxisTickRenderer&&n.angle){switch(n.labelPosition){case"auto":case"end":if(n.angle<0){c=-n._textRenderer.height*Math.cos(-n._textRenderer.angle)/2}else{c=-n.getHeight()+n._textRenderer.height*Math.cos(n._textRenderer.angle)/2}break;case"start":if(n.angle>0){c=-n._textRenderer.height*Math.cos(-n._textRenderer.angle)/2}else{c=-n.getHeight()+n._textRenderer.height*Math.cos(n._textRenderer.angle)/2}break;case"middle":c=-n.getHeight()/2;break;default:c=-n.getHeight()/2;break}}else{c=-n.getHeight()/2}var z=this.u2p(n.value)+c+"px";n._elem.css("top",z);n.pack()}}if(o){var x=this._label._elem.outerHeight(true);this._label._elem.css("top",m-g/2-x/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{this._label._elem.css("right","0px")}this._label.pack()}}}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoAxisRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoAxisRenderer.js new file mode 100644 index 0000000000..991ed87895 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoAxisRenderer.js @@ -0,0 +1,610 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + // class: $.jqplot.MekkoAxisRenderer + // An axis renderer for a Mekko chart. + // Should be used with a Mekko chart where the mekkoRenderer is used on the series. + // Displays the Y axis as a range from 0 to 1 (0 to 100%) and the x axis with a tick + // for each series scaled to the sum of all the y values. + $.jqplot.MekkoAxisRenderer = function() { + }; + + // called with scope of axis object. + $.jqplot.MekkoAxisRenderer.prototype.init = function(options){ + // prop: tickMode + // How to space the ticks on the axis. + // 'bar' will place a tick at the width of each bar. + // This is the default for the x axis. + // 'even' will place ticks at even intervals. This is + // the default for x2 axis and y axis. y axis cannot be changed. + this.tickMode; + // prop: barLabelRenderer + // renderer to use to draw labels under each bar. + this.barLabelRenderer = $.jqplot.AxisLabelRenderer; + // prop: barLabels + // array of labels to put under each bar. + this.barLabels = this.barLabels || []; + // prop: barLabelOptions + // options object to pass to the bar label renderer. + this.barLabelOptions = {}; + this.tickOptions = $.extend(true, {showGridline:false}, this.tickOptions); + this._barLabels = []; + $.extend(true, this, options); + if (this.name == 'yaxis') { + this.tickOptions.formatString = this.tickOptions.formatString || "%d\%"; + } + var db = this._dataBounds; + db.min = 0; + // for y axes, scale always go from 0 to 1 (0 to 100%) + if (this.name == 'yaxis' || this.name == 'y2axis') { + db.max = 100; + this.tickMode = 'even'; + } + // For x axes, scale goes from 0 to sum of all y values. + else if (this.name == 'xaxis'){ + this.tickMode = (this.tickMode == null) ? 'bar' : this.tickMode; + for (var i=0; i<this._series.length; i++) { + db.max += this._series[i]._sumy; + } + } + else if (this.name == 'x2axis'){ + this.tickMode = (this.tickMode == null) ? 'even' : this.tickMode; + for (var i=0; i<this._series.length; i++) { + db.max += this._series[i]._sumy; + } + } + }; + + // called with scope of axis + $.jqplot.MekkoAxisRenderer.prototype.draw = function(ctx) { + if (this.show) { + // populate the axis label and value properties. + // createTicks is a method on the renderer, but + // call it within the scope of the axis. + this.renderer.createTicks.call(this); + // fill a div with axes labels in the right direction. + // Need to pregenerate each axis to get it's bounds and + // position it and the labels correctly on the plot. + var dim=0; + var temp; + + var elem = document.createElement('div'); + this._elem = $(elem); + this._elem.addClass('jqplot-axis jqplot-'+this.name); + this._elem.css('position', 'absolute'); + elem = null; + + if (this.name == 'xaxis' || this.name == 'x2axis') { + this._elem.width(this._plotDimensions.width); + } + else { + this._elem.height(this._plotDimensions.height); + } + + // draw the axis label + // create a _label object. + this.labelOptions.axis = this.name; + this._label = new this.labelRenderer(this.labelOptions); + if (this._label.show) { + this._elem.append(this._label.draw(ctx)); + } + + var t, tick, elem; + if (this.showTicks) { + t = this._ticks; + for (var i=0; i<t.length; i++) { + tick = t[i]; + if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + this._elem.append(tick.draw(ctx)); + } + } + } + + // draw the series labels + for (i=0; i<this.barLabels.length; i++) { + this.barLabelOptions.axis = this.name; + this.barLabelOptions.label = this.barLabels[i]; + this._barLabels.push(new this.barLabelRenderer(this.barLabelOptions)); + if (this.tickMode != 'bar') { + this._barLabels[i].show = false; + } + if (this._barLabels[i].show) { + var elem = this._barLabels[i].draw(ctx); + elem.removeClass('jqplot-'+this.name+'-label'); + elem.addClass('jqplot-'+this.name+'-tick'); + elem.addClass('jqplot-mekko-barLabel'); + elem.appendTo(this._elem); + elem = null; + } + } + + } + return this._elem; + }; + + // called with scope of an axis + $.jqplot.MekkoAxisRenderer.prototype.reset = function() { + this.min = this._min; + this.max = this._max; + this.tickInterval = this._tickInterval; + this.numberTicks = this._numberTicks; + // this._ticks = this.__ticks; + }; + + // called with scope of axis + $.jqplot.MekkoAxisRenderer.prototype.set = function() { + var dim = 0; + var temp; + var w = 0; + var h = 0; + var lshow = (this._label == null) ? false : this._label.show; + if (this.show && this.showTicks) { + var t = this._ticks; + for (var i=0; i<t.length; i++) { + var tick = t[i]; + if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + temp = tick._elem.outerHeight(true); + } + else { + temp = tick._elem.outerWidth(true); + } + if (temp > dim) { + dim = temp; + } + } + } + + if (lshow) { + w = this._label._elem.outerWidth(true); + h = this._label._elem.outerHeight(true); + } + if (this.name == 'xaxis') { + dim = dim + h; + this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'}); + } + else if (this.name == 'x2axis') { + dim = dim + h; + this._elem.css({'height':dim+'px', left:'0px', top:'0px'}); + } + else if (this.name == 'yaxis') { + dim = dim + w; + this._elem.css({'width':dim+'px', left:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + else { + dim = dim + w; + this._elem.css({'width':dim+'px', right:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + } + }; + + // called with scope of axis + $.jqplot.MekkoAxisRenderer.prototype.createTicks = function() { + // we're are operating on an axis here + var ticks = this._ticks; + var userTicks = this.ticks; + var name = this.name; + // databounds were set on axis initialization. + var db = this._dataBounds; + var dim, interval; + var min, max; + var pos1, pos2; + var t, tt, i, j; + + // if we already have ticks, use them. + // ticks must be in order of increasing value. + + if (userTicks.length) { + // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed + for (i=0; i<userTicks.length; i++){ + var ut = userTicks[i]; + var t = new this.tickRenderer(this.tickOptions); + if (ut.constructor == Array) { + t.value = ut[0]; + t.label = ut[1]; + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(ut[0], this.name); + this._ticks.push(t); + } + + else { + t.value = ut; + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(ut, this.name); + this._ticks.push(t); + } + } + this.numberTicks = userTicks.length; + this.min = this._ticks[0].value; + this.max = this._ticks[this.numberTicks-1].value; + this.tickInterval = (this.max - this.min) / (this.numberTicks - 1); + } + + // we don't have any ticks yet, let's make some! + else { + if (name == 'xaxis' || name == 'x2axis') { + dim = this._plotDimensions.width; + } + else { + dim = this._plotDimensions.height; + } + + // if min, max and number of ticks specified, user can't specify interval. + if (this.min != null && this.max != null && this.numberTicks != null) { + this.tickInterval = null; + } + + min = (this.min != null) ? this.min : db.min; + max = (this.max != null) ? this.max : db.max; + + // if min and max are same, space them out a bit.+ + if (min == max) { + var adj = 0.05; + if (min > 0) { + adj = Math.max(Math.log(min)/Math.LN10, 0.05); + } + min -= adj; + max += adj; + } + + var range = max - min; + var rmin, rmax; + var temp, prev, curr; + var ynumticks = [3,5,6,11,21]; + + // yaxis divide ticks in nice intervals from 0 to 1. + if (this.name == 'yaxis' || this.name == 'y2axis') { + this.min = 0; + this.max = 100; + // user didn't specify number of ticks. + if (!this.numberTicks){ + if (this.tickInterval) { + this.numberTicks = 3 + Math.ceil(range / this.tickInterval); + } + else { + temp = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing); + for (i=0; i<ynumticks.length; i++) { + curr = temp/ynumticks[i]; + if (curr == 1) { + this.numberTicks = ynumticks[i]; + break; + } + else if (curr > 1) { + prev = curr; + continue; + } + else if (curr < 1) { + // was prev or is curr closer to one? + if (Math.abs(prev - 1) < Math.abs(curr - 1)) { + this.numberTicks = ynumticks[i-1]; + break; + } + else { + this.numberTicks = ynumticks[i]; + break; + } + } + else if (i == ynumticks.length -1) { + this.numberTicks = ynumticks[i]; + } + } + this.tickInterval = range / (this.numberTicks - 1); + } + } + + // user did specify number of ticks. + else { + this.tickInterval = range / (this.numberTicks - 1); + } + + for (var i=0; i<this.numberTicks; i++){ + tt = this.min + i * this.tickInterval; + t = new this.tickRenderer(this.tickOptions); + // var t = new $.jqplot.AxisTickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + } + } + + // for x axes, have number ot ticks equal to number of series and ticks placed + // at sum of y values for each series. + else if (this.tickMode == 'bar') { + this.min = 0; + this.numberTicks = this._series.length + 1; + t = new this.tickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(0, this.name); + this._ticks.push(t); + + temp = 0; + + for (i=1; i<this.numberTicks; i++){ + temp += this._series[i-1]._sumy; + t = new this.tickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(temp, this.name); + this._ticks.push(t); + } + this.max = this.max || temp; + + // if user specified a max and it is greater than sum, add a tick + if (this.max > temp) { + t = new this.tickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(this.max, this.name); + this._ticks.push(t); + + } + } + + else if (this.tickMode == 'even') { + this.min = 0; + this.max = this.max || db.max; + // get a desired number of ticks + var nt = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing); + range = this.max - this.min; + this.numberTicks = nt; + this.tickInterval = range / (this.numberTicks - 1); + + for (i=0; i<this.numberTicks; i++){ + tt = this.min + i * this.tickInterval; + t = new this.tickRenderer(this.tickOptions); + // var t = new $.jqplot.AxisTickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + } + + } + } + }; + + // called with scope of axis + $.jqplot.MekkoAxisRenderer.prototype.pack = function(pos, offsets) { + var ticks = this._ticks; + var max = this.max; + var min = this.min; + var offmax = offsets.max; + var offmin = offsets.min; + var lshow = (this._label == null) ? false : this._label.show; + + for (var p in pos) { + this._elem.css(p, pos[p]); + } + + this._offsets = offsets; + // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left. + var pixellength = offmax - offmin; + var unitlength = max - min; + + // point to unit and unit to point conversions references to Plot DOM element top left corner. + this.p2u = function(p){ + return (p - offmin) * unitlength / pixellength + min; + }; + + this.u2p = function(u){ + return (u - min) * pixellength / unitlength + offmin; + }; + + if (this.name == 'xaxis' || this.name == 'x2axis'){ + this.series_u2p = function(u){ + return (u - min) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + min; + }; + } + + else { + this.series_u2p = function(u){ + return (u - max) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + max; + }; + } + + if (this.show) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + for (var i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'xaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + if (temp * t.angle < 0) { + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + } + // position at start + else { + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + } + break; + case 'end': + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + case 'start': + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + break; + case 'middle': + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + default: + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + } + } + else { + shim = -t.getWidth()/2; + } + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('left', val); + t.pack(); + } + } + var w; + if (lshow) { + w = this._label._elem.outerWidth(true); + this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px'); + if (this.name == 'xaxis') { + this._label._elem.css('bottom', '0px'); + } + else { + this._label._elem.css('top', '0px'); + } + this._label.pack(); + } + // now show the labels under the bars. + var b, l, r; + for (var i=0; i<this.barLabels.length; i++) { + b = this._barLabels[i]; + if (b.show) { + w = b.getWidth(); + l = this._ticks[i].getLeft() + this._ticks[i].getWidth(); + r = this._ticks[i+1].getLeft(); + b._elem.css('left', (r+l-w)/2+'px'); + b._elem.css('top', this._ticks[i]._elem.css('top')); + b.pack(); + } + } + } + else { + for (var i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'yaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + case 'end': + if (temp * t.angle < 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'start': + if (t.angle > 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'middle': + shim = -t.getHeight()/2; + break; + default: + shim = -t.getHeight()/2; + break; + } + } + else { + shim = -t.getHeight()/2; + } + + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('top', val); + t.pack(); + } + } + if (lshow) { + var h = this._label._elem.outerHeight(true); + this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px'); + if (this.name == 'yaxis') { + this._label._elem.css('left', '0px'); + } + else { + this._label._elem.css('right', '0px'); + } + this._label.pack(); + } + } + } + }; +})(jQuery); diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoAxisRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoAxisRenderer.min.js new file mode 100644 index 0000000000..fe79d7ce4d --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoAxisRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.MekkoAxisRenderer=function(){};a.jqplot.MekkoAxisRenderer.prototype.init=function(c){this.tickMode;this.barLabelRenderer=a.jqplot.AxisLabelRenderer;this.barLabels=this.barLabels||[];this.barLabelOptions={};this.tickOptions=a.extend(true,{showGridline:false},this.tickOptions);this._barLabels=[];a.extend(true,this,c);if(this.name=="yaxis"){this.tickOptions.formatString=this.tickOptions.formatString||"%d%"}var b=this._dataBounds;b.min=0;if(this.name=="yaxis"||this.name=="y2axis"){b.max=100;this.tickMode="even"}else{if(this.name=="xaxis"){this.tickMode=(this.tickMode==null)?"bar":this.tickMode;for(var d=0;d<this._series.length;d++){b.max+=this._series[d]._sumy}}else{if(this.name=="x2axis"){this.tickMode=(this.tickMode==null)?"even":this.tickMode;for(var d=0;d<this._series.length;d++){b.max+=this._series[d]._sumy}}}}};a.jqplot.MekkoAxisRenderer.prototype.draw=function(b){if(this.show){this.renderer.createTicks.call(this);var h=0;var c;var g=document.createElement("div");this._elem=a(g);this._elem.addClass("jqplot-axis jqplot-"+this.name);this._elem.css("position","absolute");g=null;if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){this._elem.append(this._label.draw(b))}var f,e,g;if(this.showTicks){f=this._ticks;for(var d=0;d<f.length;d++){e=f[d];if(e.showLabel&&(!e.isMinorTick||this.showMinorTicks)){this._elem.append(e.draw(b))}}}for(d=0;d<this.barLabels.length;d++){this.barLabelOptions.axis=this.name;this.barLabelOptions.label=this.barLabels[d];this._barLabels.push(new this.barLabelRenderer(this.barLabelOptions));if(this.tickMode!="bar"){this._barLabels[d].show=false}if(this._barLabels[d].show){var g=this._barLabels[d].draw(b);g.removeClass("jqplot-"+this.name+"-label");g.addClass("jqplot-"+this.name+"-tick");g.addClass("jqplot-mekko-barLabel");g.appendTo(this._elem);g=null}}}return this._elem};a.jqplot.MekkoAxisRenderer.prototype.reset=function(){this.min=this._min;this.max=this._max;this.tickInterval=this._tickInterval;this.numberTicks=this._numberTicks};a.jqplot.MekkoAxisRenderer.prototype.set=function(){var k=0;var d;var c=0;var j=0;var b=(this._label==null)?false:this._label.show;if(this.show&&this.showTicks){var g=this._ticks;for(var f=0;f<g.length;f++){var e=g[f];if(e.showLabel&&(!e.isMinorTick||this.showMinorTicks)){if(this.name=="xaxis"||this.name=="x2axis"){d=e._elem.outerHeight(true)}else{d=e._elem.outerWidth(true)}if(d>k){k=d}}}if(b){c=this._label._elem.outerWidth(true);j=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){k=k+j;this._elem.css({height:k+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){k=k+j;this._elem.css({height:k+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){k=k+c;this._elem.css({width:k+"px",left:"0px",top:"0px"});if(b&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",c+"px")}}else{k=k+c;this._elem.css({width:k+"px",right:"0px",top:"0px"});if(b&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",c+"px")}}}}}};a.jqplot.MekkoAxisRenderer.prototype.createTicks=function(){var z=this._ticks;var w=this.ticks;var B=this.name;var y=this._dataBounds;var p,x;var n,r;var d,c;var h,b,s,q;if(w.length){for(s=0;s<w.length;s++){var e=w[s];var h=new this.tickRenderer(this.tickOptions);if(e.constructor==Array){h.value=e[0];h.label=e[1];if(!this.showTicks){h.showLabel=false;h.showMark=false}else{if(!this.showTickMarks){h.showMark=false}}h.setTick(e[0],this.name);this._ticks.push(h)}else{h.value=e;if(!this.showTicks){h.showLabel=false;h.showMark=false}else{if(!this.showTickMarks){h.showMark=false}}h.setTick(e,this.name);this._ticks.push(h)}}this.numberTicks=w.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value;this.tickInterval=(this.max-this.min)/(this.numberTicks-1)}else{if(B=="xaxis"||B=="x2axis"){p=this._plotDimensions.width}else{p=this._plotDimensions.height}if(this.min!=null&&this.max!=null&&this.numberTicks!=null){this.tickInterval=null}n=(this.min!=null)?this.min:y.min;r=(this.max!=null)?this.max:y.max;if(n==r){var g=0.05;if(n>0){g=Math.max(Math.log(n)/Math.LN10,0.05)}n-=g;r+=g}var k=r-n;var m,o;var v,l,u;var f=[3,5,6,11,21];if(this.name=="yaxis"||this.name=="y2axis"){this.min=0;this.max=100;if(!this.numberTicks){if(this.tickInterval){this.numberTicks=3+Math.ceil(k/this.tickInterval)}else{v=2+Math.ceil((p-(this.tickSpacing-1))/this.tickSpacing);for(s=0;s<f.length;s++){u=v/f[s];if(u==1){this.numberTicks=f[s];break}else{if(u>1){l=u;continue}else{if(u<1){if(Math.abs(l-1)<Math.abs(u-1)){this.numberTicks=f[s-1];break}else{this.numberTicks=f[s];break}}else{if(s==f.length-1){this.numberTicks=f[s]}}}}}this.tickInterval=k/(this.numberTicks-1)}}else{this.tickInterval=k/(this.numberTicks-1)}for(var s=0;s<this.numberTicks;s++){b=this.min+s*this.tickInterval;h=new this.tickRenderer(this.tickOptions);if(!this.showTicks){h.showLabel=false;h.showMark=false}else{if(!this.showTickMarks){h.showMark=false}}h.setTick(b,this.name);this._ticks.push(h)}}else{if(this.tickMode=="bar"){this.min=0;this.numberTicks=this._series.length+1;h=new this.tickRenderer(this.tickOptions);if(!this.showTicks){h.showLabel=false;h.showMark=false}else{if(!this.showTickMarks){h.showMark=false}}h.setTick(0,this.name);this._ticks.push(h);v=0;for(s=1;s<this.numberTicks;s++){v+=this._series[s-1]._sumy;h=new this.tickRenderer(this.tickOptions);if(!this.showTicks){h.showLabel=false;h.showMark=false}else{if(!this.showTickMarks){h.showMark=false}}h.setTick(v,this.name);this._ticks.push(h)}this.max=this.max||v;if(this.max>v){h=new this.tickRenderer(this.tickOptions);if(!this.showTicks){h.showLabel=false;h.showMark=false}else{if(!this.showTickMarks){h.showMark=false}}h.setTick(this.max,this.name);this._ticks.push(h)}}else{if(this.tickMode=="even"){this.min=0;this.max=this.max||y.max;var A=2+Math.ceil((p-(this.tickSpacing-1))/this.tickSpacing);k=this.max-this.min;this.numberTicks=A;this.tickInterval=k/(this.numberTicks-1);for(s=0;s<this.numberTicks;s++){b=this.min+s*this.tickInterval;h=new this.tickRenderer(this.tickOptions);if(!this.showTicks){h.showLabel=false;h.showMark=false}else{if(!this.showTickMarks){h.showMark=false}}h.setTick(b,this.name);this._ticks.push(h)}}}}}};a.jqplot.MekkoAxisRenderer.prototype.pack=function(e,d){var C=this._ticks;var x=this.max;var v=this.min;var m=d.max;var j=d.min;var o=(this._label==null)?false:this._label.show;for(var s in e){this._elem.css(s,e[s])}this._offsets=d;var f=m-j;var g=x-v;this.p2u=function(b){return(b-j)*g/f+v};this.u2p=function(b){return(b-v)*f/g+j};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(b){return(b-v)*f/g};this.series_p2u=function(b){return b*g/f+v}}else{this.series_u2p=function(b){return(b-x)*f/g};this.series_p2u=function(b){return b*g/f+x}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(var y=0;y<C.length;y++){var n=C[y];if(n.show&&n.showLabel){var c;if(n.constructor==a.jqplot.CanvasAxisTickRenderer&&n.angle){var A=(this.name=="xaxis")?1:-1;switch(n.labelPosition){case"auto":if(A*n.angle<0){c=-n.getWidth()+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2}else{c=-n._textRenderer.height*Math.sin(n._textRenderer.angle)/2}break;case"end":c=-n.getWidth()+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2;break;case"start":c=-n._textRenderer.height*Math.sin(n._textRenderer.angle)/2;break;case"middle":c=-n.getWidth()/2+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2;break;default:c=-n.getWidth()/2+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2;break}}else{c=-n.getWidth()/2}var D=this.u2p(n.value)+c+"px";n._elem.css("left",D);n.pack()}}var k;if(o){k=this._label._elem.outerWidth(true);this._label._elem.css("left",j+f/2-k/2+"px");if(this.name=="xaxis"){this._label._elem.css("bottom","0px")}else{this._label._elem.css("top","0px")}this._label.pack()}var B,u,q;for(var y=0;y<this.barLabels.length;y++){B=this._barLabels[y];if(B.show){k=B.getWidth();u=this._ticks[y].getLeft()+this._ticks[y].getWidth();q=this._ticks[y+1].getLeft();B._elem.css("left",(q+u-k)/2+"px");B._elem.css("top",this._ticks[y]._elem.css("top"));B.pack()}}}else{for(var y=0;y<C.length;y++){var n=C[y];if(n.show&&n.showLabel){var c;if(n.constructor==a.jqplot.CanvasAxisTickRenderer&&n.angle){var A=(this.name=="yaxis")?1:-1;switch(n.labelPosition){case"auto":case"end":if(A*n.angle<0){c=-n._textRenderer.height*Math.cos(-n._textRenderer.angle)/2}else{c=-n.getHeight()+n._textRenderer.height*Math.cos(n._textRenderer.angle)/2}break;case"start":if(n.angle>0){c=-n._textRenderer.height*Math.cos(-n._textRenderer.angle)/2}else{c=-n.getHeight()+n._textRenderer.height*Math.cos(n._textRenderer.angle)/2}break;case"middle":c=-n.getHeight()/2;break;default:c=-n.getHeight()/2;break}}else{c=-n.getHeight()/2}var D=this.u2p(n.value)+c+"px";n._elem.css("top",D);n.pack()}}if(o){var z=this._label._elem.outerHeight(true);this._label._elem.css("top",m-f/2-z/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{this._label._elem.css("right","0px")}this._label.pack()}}}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoRenderer.js new file mode 100644 index 0000000000..207f7061a7 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoRenderer.js @@ -0,0 +1,436 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.MekkoRenderer + * Draws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph. + * the <$.jqplot.MekkoAxisRenderer> should be used with mekko charts. The mekko renderer + * overrides the default legend renderer with it's own $.jqplot.MekkoLegendRenderer + * which allows more flexibility to specify number of rows and columns in the legend. + * + * Data is specified per bar in the chart. You can specify data as an array of y values, or as + * an array of [label, value] pairs. Note that labels are used only on the first series. + * Labels on subsequent series are ignored: + * + * > bar1 = [['shirts', 8],['hats', 14],['shoes', 6],['gloves', 16],['dolls', 12]]; + * > bar2 = [15,6,9,13,6]; + * > bar3 = [['grumpy',4],['sneezy',2],['happy',7],['sleepy',9],['doc',7]]; + * + * If you want to place labels for each bar under the axis, you use the barLabels option on + * the axes. The bar labels can be styled with the ".jqplot-mekko-barLabel" css class. + * + * > barLabels = ['Mickey Mouse', 'Donald Duck', 'Goofy']; + * > axes:{xaxis:{barLabels:barLabels}} + * + */ + + + $.jqplot.MekkoRenderer = function(){ + this.shapeRenderer = new $.jqplot.ShapeRenderer(); + // prop: borderColor + // color of the borders between areas on the chart + this.borderColor = null; + // prop: showBorders + // True to draw borders lines between areas on the chart. + // False will draw borders lines with the same color as the area. + this.showBorders = true; + }; + + // called with scope of series. + $.jqplot.MekkoRenderer.prototype.init = function(options, plot) { + this.fill = false; + this.fillRect = true; + this.strokeRect = true; + this.shadow = false; + // width of bar on x axis. + this._xwidth = 0; + this._xstart = 0; + $.extend(true, this.renderer, options); + // set the shape renderer options + var opts = {lineJoin:'miter', lineCap:'butt', isarc:false, fillRect:this.fillRect, strokeRect:this.strokeRect}; + this.renderer.shapeRenderer.init(opts); + plot.axes.x2axis._series.push(this); + this._type = 'mekko'; + }; + + // Method: setGridData + // converts the user data values to grid coordinates and stores them + // in the gridData array. Will convert user data into appropriate + // rectangles. + // Called with scope of a series. + $.jqplot.MekkoRenderer.prototype.setGridData = function(plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var data = this._plotData; + this.gridData = []; + // figure out width on x axis. + // this._xwidth = this._sumy / plot._sumy * this.canvas.getWidth(); + this._xwidth = xp(this._sumy) - xp(0); + if (this.index>0) { + this._xstart = plot.series[this.index-1]._xstart + plot.series[this.index-1]._xwidth; + } + var totheight = this.canvas.getHeight(); + var sumy = 0; + var cury; + var curheight; + for (var i=0; i<data.length; i++) { + if (data[i] != null) { + sumy += data[i][1]; + cury = totheight - (sumy / this._sumy * totheight); + curheight = data[i][1] / this._sumy * totheight; + this.gridData.push([this._xstart, cury, this._xwidth, curheight]); + } + } + }; + + // Method: makeGridData + // converts any arbitrary data values to grid coordinates and + // returns them. This method exists so that plugins can use a series' + // linerenderer to generate grid data points without overwriting the + // grid data associated with that series. + // Called with scope of a series. + $.jqplot.MekkoRenderer.prototype.makeGridData = function(data, plot) { + // recalculate the grid data + // figure out width on x axis. + var xp = this._xaxis.series_u2p; + var totheight = this.canvas.getHeight(); + var sumy = 0; + var cury; + var curheight; + var gd = []; + for (var i=0; i<data.length; i++) { + if (data[i] != null) { + sumy += data[i][1]; + cury = totheight - (sumy / this._sumy * totheight); + curheight = data[i][1] / this._sumy * totheight; + gd.push([this._xstart, cury, this._xwidth, curheight]); + } + } + return gd; + }; + + + // called within scope of series. + $.jqplot.MekkoRenderer.prototype.draw = function(ctx, gd, options) { + var i; + var opts = (options != undefined) ? options : {}; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors); + ctx.save(); + if (gd.length) { + if (showLine) { + for (i=0; i<gd.length; i++){ + opts.fillStyle = colorGenerator.next(); + if (this.renderer.showBorders) { + opts.strokeStyle = this.renderer.borderColor; + } + else { + opts.strokeStyle = opts.fillStyle; + } + this.renderer.shapeRenderer.draw(ctx, gd[i], opts); + } + } + } + + ctx.restore(); + }; + + $.jqplot.MekkoRenderer.prototype.drawShadow = function(ctx, gd, options) { + // This is a no-op, no shadows on mekko charts. + }; + + /** + * Class: $.jqplot.MekkoLegendRenderer + * Legend renderer used by mekko charts with options for + * controlling number or rows and columns as well as placement + * outside of plot area. + * + */ + $.jqplot.MekkoLegendRenderer = function(){ + // + }; + + $.jqplot.MekkoLegendRenderer.prototype.init = function(options) { + // prop: numberRows + // Maximum number of rows in the legend. 0 or null for unlimited. + this.numberRows = null; + // prop: numberColumns + // Maximum number of columns in the legend. 0 or null for unlimited. + this.numberColumns = null; + // this will override the placement option on the Legend object + this.placement = "outside"; + $.extend(true, this, options); + }; + + // called with scope of legend + $.jqplot.MekkoLegendRenderer.prototype.draw = function() { + var legend = this; + if (this.show) { + var series = this._series; + var ss = 'position:absolute;'; + ss += (this.background) ? 'background:'+this.background+';' : ''; + ss += (this.border) ? 'border:'+this.border+';' : ''; + ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; + ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : ''; + ss += (this.textColor) ? 'color:'+this.textColor+';' : ''; + this._elem = $('<table class="jqplot-table-legend" style="'+ss+'"></table>'); + // Mekko charts legends don't go by number of series, but by number of data points + // in the series. Refactor things here for that. + + var pad = false, + reverse = true, // mekko charts are always stacked, so reverse + nr, nc; + var s = series[0]; + var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors); + + if (s.show) { + var pd = s.data; + if (this.numberRows) { + nr = this.numberRows; + if (!this.numberColumns){ + nc = Math.ceil(pd.length/nr); + } + else{ + nc = this.numberColumns; + } + } + else if (this.numberColumns) { + nc = this.numberColumns; + nr = Math.ceil(pd.length/this.numberColumns); + } + else { + nr = pd.length; + nc = 1; + } + + var i, j, tr, td1, td2, lt, rs, color; + var idx = 0; + + for (i=0; i<nr; i++) { + if (reverse){ + tr = $('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem); + } + else{ + tr = $('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem); + } + for (j=0; j<nc; j++) { + if (idx < pd.length) { + lt = this.labels[idx] || pd[idx][0].toString(); + color = colorGenerator.next(); + if (!reverse){ + if (i>0){ + pad = true; + } + else{ + pad = false; + } + } + else{ + if (i == nr -1){ + pad = false; + } + else{ + pad = true; + } + } + rs = (pad) ? this.rowSpacing : '0'; + + td1 = $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+ + '<div><div class="jqplot-table-legend-swatch" style="border-color:'+color+';"></div>'+ + '</div></td>'); + td2 = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>'); + if (this.escapeHtml){ + td2.text(lt); + } + else { + td2.html(lt); + } + if (reverse) { + td2.prependTo(tr); + td1.prependTo(tr); + } + else { + td1.appendTo(tr); + td2.appendTo(tr); + } + pad = true; + } + idx++; + } + } + + tr = null; + td1 = null; + td2 = null; + } + } + return this._elem; + }; + + $.jqplot.MekkoLegendRenderer.prototype.pack = function(offsets) { + if (this.show) { + // fake a grid for positioning + var grid = {_top:offsets.top, _left:offsets.left, _right:offsets.right, _bottom:this._plotDimensions.height - offsets.bottom}; + if (this.placement == 'insideGrid') { + switch (this.location) { + case 'nw': + var a = grid._left + this.xoffset; + var b = grid._top + this.yoffset; + this._elem.css('left', a); + this._elem.css('top', b); + break; + case 'n': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = grid._top + this.yoffset; + this._elem.css('left', a); + this._elem.css('top', b); + break; + case 'ne': + var a = offsets.right + this.xoffset; + var b = grid._top + this.yoffset; + this._elem.css({right:a, top:b}); + break; + case 'e': + var a = offsets.right + this.xoffset; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({right:a, top:b}); + break; + case 'se': + var a = offsets.right + this.xoffset; + var b = offsets.bottom + this.yoffset; + this._elem.css({right:a, bottom:b}); + break; + case 's': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = offsets.bottom + this.yoffset; + this._elem.css({left:a, bottom:b}); + break; + case 'sw': + var a = grid._left + this.xoffset; + var b = offsets.bottom + this.yoffset; + this._elem.css({left:a, bottom:b}); + break; + case 'w': + var a = grid._left + this.xoffset; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({left:a, top:b}); + break; + default: // same as 'se' + var a = grid._right - this.xoffset; + var b = grid._bottom + this.yoffset; + this._elem.css({right:a, bottom:b}); + break; + } + + } + else { + switch (this.location) { + case 'nw': + var a = this._plotDimensions.width - grid._left + this.xoffset; + var b = grid._top + this.yoffset; + this._elem.css('right', a); + this._elem.css('top', b); + break; + case 'n': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = this._plotDimensions.height - grid._top + this.yoffset; + this._elem.css('left', a); + this._elem.css('bottom', b); + break; + case 'ne': + var a = this._plotDimensions.width - offsets.right + this.xoffset; + var b = grid._top + this.yoffset; + this._elem.css({left:a, top:b}); + break; + case 'e': + var a = this._plotDimensions.width - offsets.right + this.xoffset; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({left:a, top:b}); + break; + case 'se': + var a = this._plotDimensions.width - offsets.right + this.xoffset; + var b = offsets.bottom + this.yoffset; + this._elem.css({left:a, bottom:b}); + break; + case 's': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = this._plotDimensions.height - offsets.bottom + this.yoffset; + this._elem.css({left:a, top:b}); + break; + case 'sw': + var a = this._plotDimensions.width - grid._left + this.xoffset; + var b = offsets.bottom + this.yoffset; + this._elem.css({right:a, bottom:b}); + break; + case 'w': + var a = this._plotDimensions.width - grid._left + this.xoffset; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({right:a, top:b}); + break; + default: // same as 'se' + var a = grid._right - this.xoffset; + var b = grid._bottom + this.yoffset; + this._elem.css({right:a, bottom:b}); + break; + } + } + } + }; + + // setup default renderers for axes and legend so user doesn't have to + // called with scope of plot + function preInit(target, data, options) { + options = options || {}; + options.axesDefaults = options.axesDefaults || {}; + options.legend = options.legend || {}; + options.seriesDefaults = options.seriesDefaults || {}; + var setopts = false; + if (options.seriesDefaults.renderer == $.jqplot.MekkoRenderer) { + setopts = true; + } + else if (options.series) { + for (var i=0; i < options.series.length; i++) { + if (options.series[i].renderer == $.jqplot.MekkoRenderer) { + setopts = true; + } + } + } + + if (setopts) { + options.axesDefaults.renderer = $.jqplot.MekkoAxisRenderer; + options.legend.renderer = $.jqplot.MekkoLegendRenderer; + options.legend.preDraw = true; + } + } + + $.jqplot.preInitHooks.push(preInit); + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoRenderer.min.js new file mode 100644 index 0000000000..bb53e5f536 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.mekkoRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(b){b.jqplot.MekkoRenderer=function(){this.shapeRenderer=new b.jqplot.ShapeRenderer();this.borderColor=null;this.showBorders=true};b.jqplot.MekkoRenderer.prototype.init=function(c,e){this.fill=false;this.fillRect=true;this.strokeRect=true;this.shadow=false;this._xwidth=0;this._xstart=0;b.extend(true,this.renderer,c);var d={lineJoin:"miter",lineCap:"butt",isarc:false,fillRect:this.fillRect,strokeRect:this.strokeRect};this.renderer.shapeRenderer.init(d);e.axes.x2axis._series.push(this);this._type="mekko"};b.jqplot.MekkoRenderer.prototype.setGridData=function(h){var e=this._xaxis.series_u2p;var c=this._yaxis.series_u2p;var g=this._plotData;this.gridData=[];this._xwidth=e(this._sumy)-e(0);if(this.index>0){this._xstart=h.series[this.index-1]._xstart+h.series[this.index-1]._xwidth}var l=this.canvas.getHeight();var d=0;var k;var j;for(var f=0;f<g.length;f++){if(g[f]!=null){d+=g[f][1];k=l-(d/this._sumy*l);j=g[f][1]/this._sumy*l;this.gridData.push([this._xstart,k,this._xwidth,j])}}};b.jqplot.MekkoRenderer.prototype.makeGridData=function(f,g){var d=this._xaxis.series_u2p;var l=this.canvas.getHeight();var c=0;var j;var h;var k=[];for(var e=0;e<f.length;e++){if(f[e]!=null){c+=f[e][1];j=l-(c/this._sumy*l);h=f[e][1]/this._sumy*l;k.push([this._xstart,j,this._xwidth,h])}}return k};b.jqplot.MekkoRenderer.prototype.draw=function(c,h,d){var e;var g=(d!=undefined)?d:{};var f=(g.showLine!=undefined)?g.showLine:this.showLine;var j=new b.jqplot.ColorGenerator(this.seriesColors);c.save();if(h.length){if(f){for(e=0;e<h.length;e++){g.fillStyle=j.next();if(this.renderer.showBorders){g.strokeStyle=this.renderer.borderColor}else{g.strokeStyle=g.fillStyle}this.renderer.shapeRenderer.draw(c,h[e],g)}}}c.restore()};b.jqplot.MekkoRenderer.prototype.drawShadow=function(c,e,d){};b.jqplot.MekkoLegendRenderer=function(){};b.jqplot.MekkoLegendRenderer.prototype.init=function(c){this.numberRows=null;this.numberColumns=null;this.placement="outside";b.extend(true,this,c)};b.jqplot.MekkoLegendRenderer.prototype.draw=function(){var f=this;if(this.show){var o=this._series;var r="position:absolute;";r+=(this.background)?"background:"+this.background+";":"";r+=(this.border)?"border:"+this.border+";":"";r+=(this.fontSize)?"font-size:"+this.fontSize+";":"";r+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";r+=(this.textColor)?"color:"+this.textColor+";":"";this._elem=b('<table class="jqplot-table-legend" style="'+r+'"></table>');var w=false,n=true,c,l;var p=o[0];var d=new b.jqplot.ColorGenerator(p.seriesColors);if(p.show){var x=p.data;if(this.numberRows){c=this.numberRows;if(!this.numberColumns){l=Math.ceil(x.length/c)}else{l=this.numberColumns}}else{if(this.numberColumns){l=this.numberColumns;c=Math.ceil(x.length/this.numberColumns)}else{c=x.length;l=1}}var v,u,e,h,g,k,m,t;var q=0;for(v=0;v<c;v++){if(n){e=b('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem)}else{e=b('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem)}for(u=0;u<l;u++){if(q<x.length){k=this.labels[q]||x[q][0].toString();t=d.next();if(!n){if(v>0){w=true}else{w=false}}else{if(v==c-1){w=false}else{w=true}}m=(w)?this.rowSpacing:"0";h=b('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+m+';"><div><div class="jqplot-table-legend-swatch" style="border-color:'+t+';"></div></div></td>');g=b('<td class="jqplot-table-legend" style="padding-top:'+m+';"></td>');if(this.escapeHtml){g.text(k)}else{g.html(k)}if(n){g.prependTo(e);h.prependTo(e)}else{h.appendTo(e);g.appendTo(e)}w=true}q++}}e=null;h=null;g=null}}return this._elem};b.jqplot.MekkoLegendRenderer.prototype.pack=function(f){if(this.show){var e={_top:f.top,_left:f.left,_right:f.right,_bottom:this._plotDimensions.height-f.bottom};if(this.placement=="insideGrid"){switch(this.location){case"nw":var d=e._left+this.xoffset;var c=e._top+this.yoffset;this._elem.css("left",d);this._elem.css("top",c);break;case"n":var d=(f.left+(this._plotDimensions.width-f.right))/2-this.getWidth()/2;var c=e._top+this.yoffset;this._elem.css("left",d);this._elem.css("top",c);break;case"ne":var d=f.right+this.xoffset;var c=e._top+this.yoffset;this._elem.css({right:d,top:c});break;case"e":var d=f.right+this.xoffset;var c=(f.top+(this._plotDimensions.height-f.bottom))/2-this.getHeight()/2;this._elem.css({right:d,top:c});break;case"se":var d=f.right+this.xoffset;var c=f.bottom+this.yoffset;this._elem.css({right:d,bottom:c});break;case"s":var d=(f.left+(this._plotDimensions.width-f.right))/2-this.getWidth()/2;var c=f.bottom+this.yoffset;this._elem.css({left:d,bottom:c});break;case"sw":var d=e._left+this.xoffset;var c=f.bottom+this.yoffset;this._elem.css({left:d,bottom:c});break;case"w":var d=e._left+this.xoffset;var c=(f.top+(this._plotDimensions.height-f.bottom))/2-this.getHeight()/2;this._elem.css({left:d,top:c});break;default:var d=e._right-this.xoffset;var c=e._bottom+this.yoffset;this._elem.css({right:d,bottom:c});break}}else{switch(this.location){case"nw":var d=this._plotDimensions.width-e._left+this.xoffset;var c=e._top+this.yoffset;this._elem.css("right",d);this._elem.css("top",c);break;case"n":var d=(f.left+(this._plotDimensions.width-f.right))/2-this.getWidth()/2;var c=this._plotDimensions.height-e._top+this.yoffset;this._elem.css("left",d);this._elem.css("bottom",c);break;case"ne":var d=this._plotDimensions.width-f.right+this.xoffset;var c=e._top+this.yoffset;this._elem.css({left:d,top:c});break;case"e":var d=this._plotDimensions.width-f.right+this.xoffset;var c=(f.top+(this._plotDimensions.height-f.bottom))/2-this.getHeight()/2;this._elem.css({left:d,top:c});break;case"se":var d=this._plotDimensions.width-f.right+this.xoffset;var c=f.bottom+this.yoffset;this._elem.css({left:d,bottom:c});break;case"s":var d=(f.left+(this._plotDimensions.width-f.right))/2-this.getWidth()/2;var c=this._plotDimensions.height-f.bottom+this.yoffset;this._elem.css({left:d,top:c});break;case"sw":var d=this._plotDimensions.width-e._left+this.xoffset;var c=f.bottom+this.yoffset;this._elem.css({right:d,bottom:c});break;case"w":var d=this._plotDimensions.width-e._left+this.xoffset;var c=(f.top+(this._plotDimensions.height-f.bottom))/2-this.getHeight()/2;this._elem.css({right:d,top:c});break;default:var d=e._right-this.xoffset;var c=e._bottom+this.yoffset;this._elem.css({right:d,bottom:c});break}}}};function a(g,f,d){d=d||{};d.axesDefaults=d.axesDefaults||{};d.legend=d.legend||{};d.seriesDefaults=d.seriesDefaults||{};var c=false;if(d.seriesDefaults.renderer==b.jqplot.MekkoRenderer){c=true}else{if(d.series){for(var e=0;e<d.series.length;e++){if(d.series[e].renderer==b.jqplot.MekkoRenderer){c=true}}}}if(c){d.axesDefaults.renderer=b.jqplot.MekkoAxisRenderer;d.legend.renderer=b.jqplot.MekkoLegendRenderer;d.legend.preDraw=true}}b.jqplot.preInitHooks.push(a)})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.meterGaugeRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.meterGaugeRenderer.js new file mode 100644 index 0000000000..8f9b0cb134 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.meterGaugeRenderer.js @@ -0,0 +1,1033 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.MeterGaugeRenderer + * Plugin renderer to draw a meter gauge chart. + * + * Data consists of a single series with 1 data point to position the gauge needle. + * + * To use this renderer, you need to include the + * meter gauge renderer plugin, for example: + * + * > <script type="text/javascript" src="plugins/jqplot.meterGaugeRenderer.js"></script> + * + * Properties described here are passed into the $.jqplot function + * as options on the series renderer. For example: + * + * > plot0 = $.jqplot('chart0',[[18]],{ + * > title: 'Network Speed', + * > seriesDefaults: { + * > renderer: $.jqplot.MeterGaugeRenderer, + * > rendererOptions: { + * > label: 'MB/s' + * > } + * > } + * > }); + * + * A meterGauge plot does not support events. + */ + $.jqplot.MeterGaugeRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.MeterGaugeRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.MeterGaugeRenderer.prototype.constructor = $.jqplot.MeterGaugeRenderer; + + // called with scope of a series + $.jqplot.MeterGaugeRenderer.prototype.init = function(options) { + // Group: Properties + // + // prop: diameter + // Outer diameter of the meterGauge, auto computed by default + this.diameter = null; + // prop: padding + // padding between the meterGauge and plot edges, auto + // calculated by default. + this.padding = null; + // prop: shadowOffset + // offset of the shadow from the gauge ring and offset of + // each succesive stroke of the shadow from the last. + this.shadowOffset = 2; + // prop: shadowAlpha + // transparency of the shadow (0 = transparent, 1 = opaque) + this.shadowAlpha = 0.07; + // prop: shadowDepth + // number of strokes to apply to the shadow, + // each stroke offset shadowOffset from the last. + this.shadowDepth = 4; + // prop: background + // background color of the inside of the gauge. + this.background = "#efefef"; + // prop: ringColor + // color of the outer ring, hub, and needle of the gauge. + this.ringColor = "#BBC6D0"; + // needle color not implemented yet. + this.needleColor = "#C3D3E5"; + // prop: tickColor + // color of the tick marks around the gauge. + this.tickColor = "989898"; + // prop: ringWidth + // width of the ring around the gauge. Auto computed by default. + this.ringWidth = null; + // prop: min + // Minimum value on the gauge. Auto computed by default + this.min; + // prop: max + // Maximum value on the gauge. Auto computed by default + this.max; + // prop: ticks + // Array of tick values. Auto computed by default. + this.ticks = []; + // prop: showTicks + // true to show ticks around gauge. + this.showTicks = true; + // prop: showTickLabels + // true to show tick labels next to ticks. + this.showTickLabels = true; + // prop: label + // A gauge label like 'kph' or 'Volts' + this.label = null; + // prop: labelHeightAdjust + // Number of Pixels to offset the label up (-) or down (+) from its default position. + this.labelHeightAdjust = 0; + // prop: labelPosition + // Where to position the label, either 'inside' or 'bottom'. + this.labelPosition = 'inside'; + // prop: intervals + // Array of ranges to be drawn around the gauge. + // Array of form: + // > [value1, value2, ...] + // indicating the values for the first, second, ... intervals. + this.intervals = []; + // prop: intervalColors + // Array of colors to use for the intervals. + this.intervalColors = [ "#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"]; + // prop: intervalInnerRadius + // Radius of the inner circle of the interval ring. + this.intervalInnerRadius = null; + // prop: intervalOuterRadius + // Radius of the outer circle of the interval ring. + this.intervalOuterRadius = null; + this.tickRenderer = $.jqplot.MeterGaugeTickRenderer; + // ticks spaced every 1, 2, 2.5, 5, 10, 20, .1, .2, .25, .5, etc. + this.tickPositions = [1, 2, 2.5, 5, 10]; + // prop: tickSpacing + // Degrees between ticks. This is a target number, if + // incompatible span and ticks are supplied, a suitable + // spacing close to this value will be computed. + this.tickSpacing = 30; + this.numberMinorTicks = null; + // prop: hubRadius + // Radius of the hub at the bottom center of gauge which the needle attaches to. + // Auto computed by default + this.hubRadius = null; + // prop: tickPadding + // padding of the tick marks to the outer ring and the tick labels to marks. + // Auto computed by default. + this.tickPadding = null; + // prop: needleThickness + // Maximum thickness the needle. Auto computed by default. + this.needleThickness = null; + // prop: needlePad + // Padding between needle and inner edge of the ring when the needle is at the min or max gauge value. + this.needlePad = 6; + // prop: pegNeedle + // True will stop needle just below/above the min/max values if data is below/above min/max, + // as if the meter is "pegged". + this.pegNeedle = true; + this._type = 'meterGauge'; + + $.extend(true, this, options); + this.type = null; + this.numberTicks = null; + this.tickInterval = null; + // span, the sweep (in degrees) from min to max. This gauge is + // a semi-circle. + this.span = 180; + // get rid of this nonsense + // this.innerSpan = this.span; + if (this.type == 'circular') { + this.semiCircular = false; + } + else if (this.type != 'circular') { + this.semiCircular = true; + } + else { + this.semiCircular = (this.span <= 180) ? true : false; + } + this._tickPoints = []; + // reference to label element. + this._labelElm = null; + + // start the gauge at the beginning of the span + this.startAngle = (90 + (360 - this.span)/2) * Math.PI/180; + this.endAngle = (90 - (360 - this.span)/2) * Math.PI/180; + + this.setmin = !!(this.min == null); + this.setmax = !!(this.max == null); + + // if given intervals and is an array of values, create labels and colors. + if (this.intervals.length) { + if (this.intervals[0].length == null || this.intervals.length == 1) { + for (var i=0; i<this.intervals.length; i++) { + this.intervals[i] = [this.intervals[i], this.intervals[i], this.intervalColors[i]]; + } + } + else if (this.intervals[0].length == 2) { + for (i=0; i<this.intervals.length; i++) { + this.intervals[i] = [this.intervals[i][0], this.intervals[i][1], this.intervalColors[i]]; + } + } + } + + // compute min, max and ticks if not supplied: + if (this.ticks.length) { + if (this.ticks[0].length == null || this.ticks[0].length == 1) { + for (var i=0; i<this.ticks.length; i++) { + this.ticks[i] = [this.ticks[i], this.ticks[i]]; + } + } + this.min = (this.min == null) ? this.ticks[0][0] : this.min; + this.max = (this.max == null) ? this.ticks[this.ticks.length-1][0] : this.max; + this.setmin = false; + this.setmax = false; + this.numberTicks = this.ticks.length; + this.tickInterval = this.ticks[1][0] - this.ticks[0][0]; + this.tickFactor = Math.floor(parseFloat((Math.log(this.tickInterval)/Math.log(10)).toFixed(11))); + // use the first interal to calculate minor ticks; + this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor); + if (!this.numberMinorTicks) { + this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor-1); + } + if (!this.numberMinorTicks) { + this.numberMinorTicks = 1; + } + } + + else if (this.intervals.length) { + this.min = (this.min == null) ? 0 : this.min; + this.setmin = false; + if (this.max == null) { + if (this.intervals[this.intervals.length-1][0] >= this.data[0][1]) { + this.max = this.intervals[this.intervals.length-1][0]; + this.setmax = false; + } + } + else { + this.setmax = false; + } + } + + else { + // no ticks and no intervals supplied, put needle in middle + this.min = (this.min == null) ? 0 : this.min; + this.setmin = false; + if (this.max == null) { + this.max = this.data[0][1] * 1.25; + this.setmax = true; + } + else { + this.setmax = false; + } + } + }; + + $.jqplot.MeterGaugeRenderer.prototype.setGridData = function(plot) { + // set gridData property. This will hold angle in radians of each data point. + var stack = []; + var td = []; + var sa = this.startAngle; + for (var i=0; i<this.data.length; i++){ + stack.push(this.data[i][1]); + td.push([this.data[i][0]]); + if (i>0) { + stack[i] += stack[i-1]; + } + } + var fact = Math.PI*2/stack[stack.length - 1]; + + for (var i=0; i<stack.length; i++) { + td[i][1] = stack[i] * fact; + } + this.gridData = td; + }; + + $.jqplot.MeterGaugeRenderer.prototype.makeGridData = function(data, plot) { + var stack = []; + var td = []; + var sa = this.startAngle; + for (var i=0; i<data.length; i++){ + stack.push(data[i][1]); + td.push([data[i][0]]); + if (i>0) { + stack[i] += stack[i-1]; + } + } + var fact = Math.PI*2/stack[stack.length - 1]; + + for (var i=0; i<stack.length; i++) { + td[i][1] = stack[i] * fact; + } + return td; + }; + + + function getnmt(pos, interval, fact) { + var temp; + for (var i=pos.length-1; i>=0; i--) { + temp = interval/(pos[i] * Math.pow(10, fact)); + if (temp == 4 || temp == 5) { + return temp - 1; + } + } + return null; + } + + // called with scope of series + $.jqplot.MeterGaugeRenderer.prototype.draw = function (ctx, gd, options) { + var i; + var opts = (options != undefined) ? options : {}; + // offset and direction of offset due to legend placement + var offx = 0; + var offy = 0; + var trans = 1; + if (options.legendInfo && options.legendInfo.placement == 'inside') { + var li = options.legendInfo; + switch (li.location) { + case 'nw': + offx = li.width + li.xoffset; + break; + case 'w': + offx = li.width + li.xoffset; + break; + case 'sw': + offx = li.width + li.xoffset; + break; + case 'ne': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'e': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'se': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'n': + offy = li.height + li.yoffset; + break; + case 's': + offy = li.height + li.yoffset; + trans = -1; + break; + default: + break; + } + } + + + + // pre-draw so can get it's dimensions. + if (this.label) { + this._labelElem = $('<div class="jqplot-meterGauge-label" style="position:absolute;">'+this.label+'</div>'); + this.canvas._elem.after(this._labelElem); + } + + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var cw = ctx.canvas.width; + var ch = ctx.canvas.height; + if (this.padding == null) { + this.padding = Math.round(Math.min(cw, ch)/30); + } + var w = cw - offx - 2 * this.padding; + var h = ch - offy - 2 * this.padding; + if (this.labelPosition == 'bottom' && this.label) { + h -= this._labelElem.outerHeight(true); + } + var mindim = Math.min(w,h); + var d = mindim; + + if (!this.diameter) { + if (this.semiCircular) { + if ( w >= 2*h) { + if (!this.ringWidth) { + this.ringWidth = 2*h/35; + } + this.needleThickness = this.needleThickness || 2+Math.pow(this.ringWidth, 0.8); + this.innerPad = this.ringWidth/2 + this.needleThickness/2 + this.needlePad; + this.diameter = 2 * (h - 2*this.innerPad); + } + else { + if (!this.ringWidth) { + this.ringWidth = w/35; + } + this.needleThickness = this.needleThickness || 2+Math.pow(this.ringWidth, 0.8); + this.innerPad = this.ringWidth/2 + this.needleThickness/2 + this.needlePad; + this.diameter = w - 2*this.innerPad; + } + // center taking into account legend and over draw for gauge bottom below hub. + // this will be center of hub. + this._center = [(cw - trans * offx)/2 + trans * offx, (ch + trans*offy - this.padding - this.ringWidth - this.innerPad)]; + } + else { + if (!this.ringWidth) { + this.ringWidth = d/35; + } + this.needleThickness = this.needleThickness || 2+Math.pow(this.ringWidth, 0.8); + this.innerPad = 0; + this.diameter = d - this.ringWidth; + // center in middle of canvas taking into account legend. + // will be center of hub. + this._center = [(cw-trans*offx)/2 + trans * offx, (ch-trans*offy)/2 + trans * offy]; + } + } + + if (this._labelElem && this.labelPosition == 'bottom') { + this._center[1] -= this._labelElem.outerHeight(true); + } + + this._radius = this.diameter/2; + + this.tickSpacing = 6000/this.diameter; + + if (!this.hubRadius) { + this.hubRadius = this.diameter/18; + } + + this.shadowOffset = 0.5 + this.ringWidth/9; + this.shadowWidth = this.ringWidth*1; + + this.tickPadding = 3 + Math.pow(this.diameter/20, 0.7); + this.tickOuterRadius = this._radius - this.ringWidth/2 - this.tickPadding; + this.tickLength = (this.showTicks) ? this._radius/13 : 0; + + if (this.ticks.length == 0) { + // no ticks, lets make some. + var max = this.max, + min = this.min, + setmax = this.setmax, + setmin = this.setmin, + ti = (max - min) * this.tickSpacing / this.span; + var tf = Math.floor(parseFloat((Math.log(ti)/Math.log(10)).toFixed(11))); + var tp = (ti/Math.pow(10, tf)); + (tp > 2 && tp <= 2.5) ? tp = 2.5 : tp = Math.ceil(tp); + var t = this.tickPositions; + var tpindex, nt; + + for (i=0; i<t.length; i++) { + if (tp == t[i] || i && t[i-1] < tp && tp < t[i]) { + ti = t[i]*Math.pow(10, tf); + tpindex = i; + } + } + + for (i=0; i<t.length; i++) { + if (tp == t[i] || i && t[i-1] < tp && tp < t[i]) { + ti = t[i]*Math.pow(10, tf); + nt = Math.ceil((max - min) / ti); + } + } + + // both max and min are free + if (setmax && setmin) { + var tmin = (min > 0) ? min - min % ti : min - min % ti - ti; + if (!this.forceZero) { + var diff = Math.min(min - tmin, 0.8*ti); + var ntp = Math.floor(diff/t[tpindex]); + if (ntp > 1) { + tmin = tmin + t[tpindex] * (ntp-1); + if (parseInt(tmin, 10) != tmin && parseInt(tmin-t[tpindex], 10) == tmin-t[tpindex]) { + tmin = tmin - t[tpindex]; + } + } + } + if (min == tmin) { + min -= ti; + } + else { + // tmin should always be lower than dataMin + if (min - tmin > 0.23*ti) { + min = tmin; + } + else { + min = tmin -ti; + nt += 1; + } + } + nt += 1; + var tmax = min + (nt - 1) * ti; + if (max >= tmax) { + tmax += ti; + nt += 1; + } + // now tmax should always be mroe than dataMax + if (tmax - max < 0.23*ti) { + tmax += ti; + nt += 1; + } + this.max = max = tmax; + this.min = min; + + this.tickInterval = ti; + this.numberTicks = nt; + var it; + for (i=0; i<nt; i++) { + it = parseFloat((min+i*ti).toFixed(11)); + this.ticks.push([it, it]); + } + this.max = this.ticks[nt-1][1]; + + this.tickFactor = tf; + // determine number of minor ticks + + this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor); + + if (!this.numberMinorTicks) { + this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor-1); + } + } + // max is free, min is fixed + else if (setmax) { + var tmax = min + (nt - 1) * ti; + if (max >= tmax) { + max = tmax + ti; + nt += 1; + } + else { + max = tmax; + } + + this.tickInterval = this.tickInterval || ti; + this.numberTicks = this.numberTicks || nt; + var it; + for (i=0; i<this.numberTicks; i++) { + it = parseFloat((min+i*this.tickInterval).toFixed(11)); + this.ticks.push([it, it]); + } + this.max = this.ticks[this.numberTicks-1][1]; + + this.tickFactor = tf; + // determine number of minor ticks + this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor); + + if (!this.numberMinorTicks) { + this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor-1); + } + } + + // not setting max or min + if (!setmax && !setmin) { + var range = this.max - this.min; + tf = Math.floor(parseFloat((Math.log(range)/Math.log(10)).toFixed(11))) - 1; + var nticks = [5,6,4,7,3,8,9,10,2], res, numticks, nonSigDigits=0, sigRange; + // check to see how many zeros are at the end of the range + if (range > 1) { + var rstr = String(range); + if (rstr.search(/\./) == -1) { + var pos = rstr.search(/0+$/); + nonSigDigits = (pos > 0) ? rstr.length - pos - 1 : 0; + } + } + sigRange = range/Math.pow(10, nonSigDigits); + for (i=0; i<nticks.length; i++) { + res = sigRange/(nticks[i]-1); + if (res == parseInt(res, 10)) { + this.numberTicks = nticks[i]; + this.tickInterval = range/(this.numberTicks-1); + this.tickFactor = tf+1; + break; + } + } + var it; + for (i=0; i<this.numberTicks; i++) { + it = parseFloat((this.min+i*this.tickInterval).toFixed(11)); + this.ticks.push([it, it]); + } + // determine number of minor ticks + this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor); + + if (!this.numberMinorTicks) { + this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor-1); + } + + if (!this.numberMinorTicks) { + this.numberMinorTicks = 1; + var nums = [4, 5, 3, 6, 2]; + for (i=0; i<5; i++) { + var temp = this.tickInterval/nums[i]; + if (temp == parseInt(temp, 10)) { + this.numberMinorTicks = nums[i]-1; + break; + } + } + } + } + } + + + var r = this._radius, + sa = this.startAngle, + ea = this.endAngle, + pi = Math.PI, + hpi = Math.PI/2; + + if (this.semiCircular) { + var overAngle = Math.atan(this.innerPad/r), + outersa = this.outerStartAngle = sa - overAngle, + outerea = this.outerEndAngle = ea + overAngle, + hubsa = this.hubStartAngle = sa - Math.atan(this.innerPad/this.hubRadius*2), + hubea = this.hubEndAngle = ea + Math.atan(this.innerPad/this.hubRadius*2); + + ctx.save(); + + ctx.translate(this._center[0], this._center[1]); + ctx.lineJoin = "round"; + ctx.lineCap = "round"; + + // draw the innerbackground + ctx.save(); + ctx.beginPath(); + ctx.fillStyle = this.background; + ctx.arc(0, 0, r, outersa, outerea, false); + ctx.closePath(); + ctx.fill(); + ctx.restore(); + + // draw the shadow + // the outer ring. + var shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')'; + ctx.save(); + for (var i=0; i<this.shadowDepth; i++) { + ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI)); + ctx.beginPath(); + ctx.strokeStyle = shadowColor; + ctx.lineWidth = this.shadowWidth; + ctx.arc(0 ,0, r, outersa, outerea, false); + ctx.closePath(); + ctx.stroke(); + } + ctx.restore(); + + // the inner hub. + ctx.save(); + var tempd = parseInt((this.shadowDepth+1)/2, 10); + for (var i=0; i<tempd; i++) { + ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI)); + ctx.beginPath(); + ctx.fillStyle = shadowColor; + ctx.arc(0 ,0, this.hubRadius, hubsa, hubea, false); + ctx.closePath(); + ctx.fill(); + } + ctx.restore(); + + // draw the outer ring. + ctx.save(); + ctx.beginPath(); + ctx.strokeStyle = this.ringColor; + ctx.lineWidth = this.ringWidth; + ctx.arc(0 ,0, r, outersa, outerea, false); + ctx.closePath(); + ctx.stroke(); + ctx.restore(); + + // draw the hub + + ctx.save(); + ctx.beginPath(); + ctx.fillStyle = this.ringColor; + ctx.arc(0 ,0, this.hubRadius,hubsa, hubea, false); + ctx.closePath(); + ctx.fill(); + ctx.restore(); + + // draw the ticks + if (this.showTicks) { + ctx.save(); + var orad = this.tickOuterRadius, + tl = this.tickLength, + mtl = tl/2, + nmt = this.numberMinorTicks, + ts = this.span * Math.PI / 180 / (this.ticks.length-1), + mts = ts/(nmt + 1); + + for (i = 0; i<this.ticks.length; i++) { + ctx.beginPath(); + ctx.lineWidth = 1.5 + this.diameter/360; + ctx.strokeStyle = this.ringColor; + var wps = ts*i+sa; + ctx.moveTo(-orad * Math.cos(ts*i+sa), orad * Math.sin(ts*i+sa)); + ctx.lineTo(-(orad-tl) * Math.cos(ts*i+sa), (orad - tl) * Math.sin(ts*i+sa)); + this._tickPoints.push([(orad-tl) * Math.cos(ts*i+sa) + this._center[0] + this.canvas._offsets.left, (orad - tl) * Math.sin(ts*i+sa) + this._center[1] + this.canvas._offsets.top, ts*i+sa]); + ctx.stroke(); + ctx.lineWidth = 1.0 + this.diameter/440; + if (i<this.ticks.length-1) { + for (var j=1; j<=nmt; j++) { + ctx.beginPath(); + ctx.moveTo(-orad * Math.cos(ts*i+mts*j+sa), orad * Math.sin(ts*i+mts*j+sa)); + ctx.lineTo(-(orad-mtl) * Math.cos(ts*i+mts*j+sa), (orad-mtl) * Math.sin(ts*i+mts*j+sa)); + ctx.stroke(); + } + } + } + ctx.restore(); + } + + // draw the tick labels + if (this.showTickLabels) { + var elem, l, t, ew, eh, dim, maxdim=0; + var tp = this.tickPadding * (1 - 1/(this.diameter/80+1)); + for (i=0; i<this.ticks.length; i++) { + elem = $('<div class="jqplot-meterGauge-tick" style="position:absolute;">'+this.ticks[i][1]+'</div>'); + this.canvas._elem.after(elem); + ew = elem.outerWidth(true); + eh = elem.outerHeight(true); + l = this._tickPoints[i][0] - ew * (this._tickPoints[i][2]-Math.PI)/Math.PI - tp * Math.cos(this._tickPoints[i][2]); + t = this._tickPoints[i][1] - eh/2 + eh/2 * Math.pow(Math.abs((Math.sin(this._tickPoints[i][2]))), 0.5) + tp/3 * Math.pow(Math.abs((Math.sin(this._tickPoints[i][2]))), 0.5) ; + // t = this._tickPoints[i][1] - eh/2 - eh/2 * Math.sin(this._tickPoints[i][2]) - tp/2 * Math.sin(this._tickPoints[i][2]); + elem.css({left:l, top:t}); + dim = ew*Math.cos(this._tickPoints[i][2]) + eh*Math.sin(Math.PI/2+this._tickPoints[i][2]/2); + maxdim = (dim > maxdim) ? dim : maxdim; + } + } + + // draw the gauge label + if (this.label && this.labelPosition == 'inside') { + var l = this._center[0] + this.canvas._offsets.left; + var tp = this.tickPadding * (1 - 1/(this.diameter/80+1)); + var t = 0.5*(this._center[1] + this.canvas._offsets.top - this.hubRadius) + 0.5*(this._center[1] + this.canvas._offsets.top - this.tickOuterRadius + this.tickLength + tp) + this.labelHeightAdjust; + // this._labelElem = $('<div class="jqplot-meterGauge-label" style="position:absolute;">'+this.label+'</div>'); + // this.canvas._elem.after(this._labelElem); + l -= this._labelElem.outerWidth(true)/2; + t -= this._labelElem.outerHeight(true)/2; + this._labelElem.css({left:l, top:t}); + } + + else if (this.label && this.labelPosition == 'bottom') { + var l = this._center[0] + this.canvas._offsets.left - this._labelElem.outerWidth(true)/2; + var t = this._center[1] + this.canvas._offsets.top + this.innerPad + + this.ringWidth + this.padding + this.labelHeightAdjust; + this._labelElem.css({left:l, top:t}); + + } + + // draw the intervals + + ctx.save(); + var inner = this.intervalInnerRadius || this.hubRadius * 1.5; + if (this.intervalOuterRadius == null) { + if (this.showTickLabels) { + var outer = (this.tickOuterRadius - this.tickLength - this.tickPadding - this.diameter/8); + } + else { + var outer = (this.tickOuterRadius - this.tickLength - this.diameter/16); + } + } + else { + var outer = this.intervalOuterRadius; + } + var range = this.max - this.min; + var intrange = this.intervals[this.intervals.length-1] - this.min; + var start, end, span = this.span*Math.PI/180; + for (i=0; i<this.intervals.length; i++) { + start = (i == 0) ? sa : sa + (this.intervals[i-1][0] - this.min)*span/range; + if (start < 0) { + start = 0; + } + end = sa + (this.intervals[i][0] - this.min)*span/range; + if (end < 0) { + end = 0; + } + ctx.beginPath(); + ctx.fillStyle = this.intervals[i][2]; + ctx.arc(0, 0, inner, start, end, false); + ctx.lineTo(outer*Math.cos(end), outer*Math.sin(end)); + ctx.arc(0, 0, outer, end, start, true); + ctx.lineTo(inner*Math.cos(start), inner*Math.sin(start)); + ctx.closePath(); + ctx.fill(); + } + ctx.restore(); + + // draw the needle + var datapoint = this.data[0][1]; + var dataspan = this.max - this.min; + if (this.pegNeedle) { + if (this.data[0][1] > this.max + dataspan*3/this.span) { + datapoint = this.max + dataspan*3/this.span; + } + if (this.data[0][1] < this.min - dataspan*3/this.span) { + datapoint = this.min - dataspan*3/this.span; + } + } + var dataang = (datapoint - this.min)/dataspan * this.span * Math.PI/180 + this.startAngle; + + + ctx.save(); + ctx.beginPath(); + ctx.fillStyle = this.ringColor; + ctx.strokeStyle = this.ringColor; + this.needleLength = (this.tickOuterRadius - this.tickLength) * 0.85; + this.needleThickness = (this.needleThickness < 2) ? 2 : this.needleThickness; + var endwidth = this.needleThickness * 0.4; + + + var dl = this.needleLength/10; + var dt = (this.needleThickness - endwidth)/10; + var templ; + for (var i=0; i<10; i++) { + templ = this.needleThickness - i*dt; + ctx.moveTo(dl*i*Math.cos(dataang), dl*i*Math.sin(dataang)); + ctx.lineWidth = templ; + ctx.lineTo(dl*(i+1)*Math.cos(dataang), dl*(i+1)*Math.sin(dataang)); + ctx.stroke(); + } + + ctx.restore(); + } + else { + this._center = [(cw - trans * offx)/2 + trans * offx, (ch - trans*offy)/2 + trans * offy]; + } + }; + + $.jqplot.MeterGaugeAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + }; + + $.jqplot.MeterGaugeAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.MeterGaugeAxisRenderer.prototype.constructor = $.jqplot.MeterGaugeAxisRenderer; + + + // There are no traditional axes on a gauge chart. We just need to provide + // dummy objects with properties so the plot will render. + // called with scope of axis object. + $.jqplot.MeterGaugeAxisRenderer.prototype.init = function(options){ + // + this.tickRenderer = $.jqplot.MeterGaugeTickRenderer; + $.extend(true, this, options); + // I don't think I'm going to need _dataBounds here. + // have to go Axis scaling in a way to fit chart onto plot area + // and provide u2p and p2u functionality for mouse cursor, etc. + // for convienence set _dataBounds to 0 and 100 and + // set min/max to 0 and 100. + this._dataBounds = {min:0, max:100}; + this.min = 0; + this.max = 100; + this.showTicks = false; + this.ticks = []; + this.showMark = false; + this.show = false; + }; + + $.jqplot.MeterGaugeLegendRenderer = function(){ + $.jqplot.TableLegendRenderer.call(this); + }; + + $.jqplot.MeterGaugeLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); + $.jqplot.MeterGaugeLegendRenderer.prototype.constructor = $.jqplot.MeterGaugeLegendRenderer; + + /** + * Class: $.jqplot.MeterGaugeLegendRenderer + *Meter gauges don't typically have a legend, this overrides the default legend renderer. + */ + $.jqplot.MeterGaugeLegendRenderer.prototype.init = function(options) { + // Maximum number of rows in the legend. 0 or null for unlimited. + this.numberRows = null; + // Maximum number of columns in the legend. 0 or null for unlimited. + this.numberColumns = null; + $.extend(true, this, options); + }; + + // called with context of legend + $.jqplot.MeterGaugeLegendRenderer.prototype.draw = function() { + if (this.show) { + var series = this._series; + var ss = 'position:absolute;'; + ss += (this.background) ? 'background:'+this.background+';' : ''; + ss += (this.border) ? 'border:'+this.border+';' : ''; + ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; + ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : ''; + ss += (this.textColor) ? 'color:'+this.textColor+';' : ''; + ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : ''; + ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : ''; + ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : ''; + ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : ''; + this._elem = $('<table class="jqplot-table-legend" style="'+ss+'"></table>'); + // MeterGauge charts legends don't go by number of series, but by number of data points + // in the series. Refactor things here for that. + + var pad = false, + reverse = false, + nr, nc; + var s = series[0]; + + if (s.show) { + var pd = s.data; + if (this.numberRows) { + nr = this.numberRows; + if (!this.numberColumns){ + nc = Math.ceil(pd.length/nr); + } + else{ + nc = this.numberColumns; + } + } + else if (this.numberColumns) { + nc = this.numberColumns; + nr = Math.ceil(pd.length/this.numberColumns); + } + else { + nr = pd.length; + nc = 1; + } + + var i, j, tr, td1, td2, lt, rs, color; + var idx = 0; + + for (i=0; i<nr; i++) { + if (reverse){ + tr = $('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem); + } + else{ + tr = $('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem); + } + for (j=0; j<nc; j++) { + if (idx < pd.length){ + // debugger + lt = this.labels[idx] || pd[idx][0].toString(); + color = s.color; + if (!reverse){ + if (i>0){ + pad = true; + } + else{ + pad = false; + } + } + else{ + if (i == nr -1){ + pad = false; + } + else{ + pad = true; + } + } + rs = (pad) ? this.rowSpacing : '0'; + + td1 = $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+ + '<div><div class="jqplot-table-legend-swatch" style="border-color:'+color+';"></div>'+ + '</div></td>'); + td2 = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>'); + if (this.escapeHtml){ + td2.text(lt); + } + else { + td2.html(lt); + } + if (reverse) { + td2.prependTo(tr); + td1.prependTo(tr); + } + else { + td1.appendTo(tr); + td2.appendTo(tr); + } + pad = true; + } + idx++; + } + } + } + } + return this._elem; + }; + + + // setup default renderers for axes and legend so user doesn't have to + // called with scope of plot + function preInit(target, data, options) { + // debugger + options = options || {}; + options.axesDefaults = options.axesDefaults || {}; + options.legend = options.legend || {}; + options.seriesDefaults = options.seriesDefaults || {}; + options.grid = options.grid || {}; + options.gridPadding = options.gridPadding || {}; + + // only set these if there is a gauge series + var setopts = false; + if (options.seriesDefaults.renderer == $.jqplot.MeterGaugeRenderer) { + setopts = true; + } + else if (options.series) { + for (var i=0; i < options.series.length; i++) { + if (options.series[i].renderer == $.jqplot.MeterGaugeRenderer) { + setopts = true; + } + } + } + + if (setopts) { + options.axesDefaults.renderer = $.jqplot.MeterGaugeAxisRenderer; + options.legend.renderer = $.jqplot.MeterGaugeLegendRenderer; + options.legend.preDraw = true; + options.grid.background = options.grid.background || 'white'; + options.grid.drawGridlines = false; + options.grid.borderWidth = (options.grid.borderWidth != null) ? options.grid.borderWidth : 0; + options.grid.shadow = (options.grid.shadow != null) ? options.grid.shadow : false; + options.gridPadding.top = (options.gridPadding.top != null) ? options.gridPadding.top : 0; + options.gridPadding.bottom = (options.gridPadding.bottom != null) ? options.gridPadding.bottom : 0; + options.gridPadding.left = (options.gridPadding.left != null) ? options.gridPadding.left : 0; + options.gridPadding.right = (options.gridPadding.right != null) ? options.gridPadding.right : 0; + } + } + + // called with scope of plot + function postParseOptions(options) { + // + } + + $.jqplot.preInitHooks.push(preInit); + $.jqplot.postParseOptionsHooks.push(postParseOptions); + + $.jqplot.MeterGaugeTickRenderer = function() { + $.jqplot.AxisTickRenderer.call(this); + }; + + $.jqplot.MeterGaugeTickRenderer.prototype = new $.jqplot.AxisTickRenderer(); + $.jqplot.MeterGaugeTickRenderer.prototype.constructor = $.jqplot.MeterGaugeTickRenderer; + +})(jQuery); + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.meterGaugeRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.meterGaugeRenderer.min.js new file mode 100644 index 0000000000..ebd89cbf96 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.meterGaugeRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(c){c.jqplot.MeterGaugeRenderer=function(){c.jqplot.LineRenderer.call(this)};c.jqplot.MeterGaugeRenderer.prototype=new c.jqplot.LineRenderer();c.jqplot.MeterGaugeRenderer.prototype.constructor=c.jqplot.MeterGaugeRenderer;c.jqplot.MeterGaugeRenderer.prototype.init=function(e){this.diameter=null;this.padding=null;this.shadowOffset=2;this.shadowAlpha=0.07;this.shadowDepth=4;this.background="#efefef";this.ringColor="#BBC6D0";this.needleColor="#C3D3E5";this.tickColor="989898";this.ringWidth=null;this.min;this.max;this.ticks=[];this.showTicks=true;this.showTickLabels=true;this.label=null;this.labelHeightAdjust=0;this.labelPosition="inside";this.intervals=[];this.intervalColors=["#4bb2c5","#EAA228","#c5b47f","#579575","#839557","#958c12","#953579","#4b5de4","#d8b83f","#ff5800","#0085cc","#c747a3","#cddf54","#FBD178","#26B4E3","#bd70c7"];this.intervalInnerRadius=null;this.intervalOuterRadius=null;this.tickRenderer=c.jqplot.MeterGaugeTickRenderer;this.tickPositions=[1,2,2.5,5,10];this.tickSpacing=30;this.numberMinorTicks=null;this.hubRadius=null;this.tickPadding=null;this.needleThickness=null;this.needlePad=6;this.pegNeedle=true;this._type="meterGauge";c.extend(true,this,e);this.type=null;this.numberTicks=null;this.tickInterval=null;this.span=180;if(this.type=="circular"){this.semiCircular=false}else{if(this.type!="circular"){this.semiCircular=true}else{this.semiCircular=(this.span<=180)?true:false}}this._tickPoints=[];this._labelElm=null;this.startAngle=(90+(360-this.span)/2)*Math.PI/180;this.endAngle=(90-(360-this.span)/2)*Math.PI/180;this.setmin=!!(this.min==null);this.setmax=!!(this.max==null);if(this.intervals.length){if(this.intervals[0].length==null||this.intervals.length==1){for(var f=0;f<this.intervals.length;f++){this.intervals[f]=[this.intervals[f],this.intervals[f],this.intervalColors[f]]}}else{if(this.intervals[0].length==2){for(f=0;f<this.intervals.length;f++){this.intervals[f]=[this.intervals[f][0],this.intervals[f][1],this.intervalColors[f]]}}}}if(this.ticks.length){if(this.ticks[0].length==null||this.ticks[0].length==1){for(var f=0;f<this.ticks.length;f++){this.ticks[f]=[this.ticks[f],this.ticks[f]]}}this.min=(this.min==null)?this.ticks[0][0]:this.min;this.max=(this.max==null)?this.ticks[this.ticks.length-1][0]:this.max;this.setmin=false;this.setmax=false;this.numberTicks=this.ticks.length;this.tickInterval=this.ticks[1][0]-this.ticks[0][0];this.tickFactor=Math.floor(parseFloat((Math.log(this.tickInterval)/Math.log(10)).toFixed(11)));this.numberMinorTicks=b(this.tickPositions,this.tickInterval,this.tickFactor);if(!this.numberMinorTicks){this.numberMinorTicks=b(this.tickPositions,this.tickInterval,this.tickFactor-1)}if(!this.numberMinorTicks){this.numberMinorTicks=1}}else{if(this.intervals.length){this.min=(this.min==null)?0:this.min;this.setmin=false;if(this.max==null){if(this.intervals[this.intervals.length-1][0]>=this.data[0][1]){this.max=this.intervals[this.intervals.length-1][0];this.setmax=false}}else{this.setmax=false}}else{this.min=(this.min==null)?0:this.min;this.setmin=false;if(this.max==null){this.max=this.data[0][1]*1.25;this.setmax=true}else{this.setmax=false}}}};c.jqplot.MeterGaugeRenderer.prototype.setGridData=function(j){var f=[];var k=[];var e=this.startAngle;for(var h=0;h<this.data.length;h++){f.push(this.data[h][1]);k.push([this.data[h][0]]);if(h>0){f[h]+=f[h-1]}}var g=Math.PI*2/f[f.length-1];for(var h=0;h<f.length;h++){k[h][1]=f[h]*g}this.gridData=k};c.jqplot.MeterGaugeRenderer.prototype.makeGridData=function(j,k){var f=[];var l=[];var e=this.startAngle;for(var h=0;h<j.length;h++){f.push(j[h][1]);l.push([j[h][0]]);if(h>0){f[h]+=f[h-1]}}var g=Math.PI*2/f[f.length-1];for(var h=0;h<f.length;h++){l[h][1]=f[h]*g}return l};function b(j,f,g){var e;for(var h=j.length-1;h>=0;h--){e=f/(j[h]*Math.pow(10,g));if(e==4||e==5){return e-1}}return null}c.jqplot.MeterGaugeRenderer.prototype.draw=function(X,aC,ap){var aa;var aM=(ap!=undefined)?ap:{};var ai=0;var ah=0;var at=1;if(ap.legendInfo&&ap.legendInfo.placement=="inside"){var aI=ap.legendInfo;switch(aI.location){case"nw":ai=aI.width+aI.xoffset;break;case"w":ai=aI.width+aI.xoffset;break;case"sw":ai=aI.width+aI.xoffset;break;case"ne":ai=aI.width+aI.xoffset;at=-1;break;case"e":ai=aI.width+aI.xoffset;at=-1;break;case"se":ai=aI.width+aI.xoffset;at=-1;break;case"n":ah=aI.height+aI.yoffset;break;case"s":ah=aI.height+aI.yoffset;at=-1;break;default:break}}if(this.label){this._labelElem=c('<div class="jqplot-meterGauge-label" style="position:absolute;">'+this.label+"</div>");this.canvas._elem.after(this._labelElem)}var m=(aM.shadow!=undefined)?aM.shadow:this.shadow;var N=(aM.showLine!=undefined)?aM.showLine:this.showLine;var I=(aM.fill!=undefined)?aM.fill:this.fill;var K=X.canvas.width;var S=X.canvas.height;if(this.padding==null){this.padding=Math.round(Math.min(K,S)/30)}var Q=K-ai-2*this.padding;var ab=S-ah-2*this.padding;if(this.labelPosition=="bottom"&&this.label){ab-=this._labelElem.outerHeight(true)}var L=Math.min(Q,ab);var ad=L;if(!this.diameter){if(this.semiCircular){if(Q>=2*ab){if(!this.ringWidth){this.ringWidth=2*ab/35}this.needleThickness=this.needleThickness||2+Math.pow(this.ringWidth,0.8);this.innerPad=this.ringWidth/2+this.needleThickness/2+this.needlePad;this.diameter=2*(ab-2*this.innerPad)}else{if(!this.ringWidth){this.ringWidth=Q/35}this.needleThickness=this.needleThickness||2+Math.pow(this.ringWidth,0.8);this.innerPad=this.ringWidth/2+this.needleThickness/2+this.needlePad;this.diameter=Q-2*this.innerPad}this._center=[(K-at*ai)/2+at*ai,(S+at*ah-this.padding-this.ringWidth-this.innerPad)]}else{if(!this.ringWidth){this.ringWidth=ad/35}this.needleThickness=this.needleThickness||2+Math.pow(this.ringWidth,0.8);this.innerPad=0;this.diameter=ad-this.ringWidth;this._center=[(K-at*ai)/2+at*ai,(S-at*ah)/2+at*ah]}}if(this._labelElem&&this.labelPosition=="bottom"){this._center[1]-=this._labelElem.outerHeight(true)}this._radius=this.diameter/2;this.tickSpacing=6000/this.diameter;if(!this.hubRadius){this.hubRadius=this.diameter/18}this.shadowOffset=0.5+this.ringWidth/9;this.shadowWidth=this.ringWidth*1;this.tickPadding=3+Math.pow(this.diameter/20,0.7);this.tickOuterRadius=this._radius-this.ringWidth/2-this.tickPadding;this.tickLength=(this.showTicks)?this._radius/13:0;if(this.ticks.length==0){var A=this.max,aL=this.min,q=this.setmax,aG=this.setmin,au=(A-aL)*this.tickSpacing/this.span;var aw=Math.floor(parseFloat((Math.log(au)/Math.log(10)).toFixed(11)));var an=(au/Math.pow(10,aw));(an>2&&an<=2.5)?an=2.5:an=Math.ceil(an);var T=this.tickPositions;var aA,ak;for(aa=0;aa<T.length;aa++){if(an==T[aa]||aa&&T[aa-1]<an&&an<T[aa]){au=T[aa]*Math.pow(10,aw);aA=aa}}for(aa=0;aa<T.length;aa++){if(an==T[aa]||aa&&T[aa-1]<an&&an<T[aa]){au=T[aa]*Math.pow(10,aw);ak=Math.ceil((A-aL)/au)}}if(q&&aG){var aP=(aL>0)?aL-aL%au:aL-aL%au-au;if(!this.forceZero){var D=Math.min(aL-aP,0.8*au);var o=Math.floor(D/T[aA]);if(o>1){aP=aP+T[aA]*(o-1);if(parseInt(aP,10)!=aP&&parseInt(aP-T[aA],10)==aP-T[aA]){aP=aP-T[aA]}}}if(aL==aP){aL-=au}else{if(aL-aP>0.23*au){aL=aP}else{aL=aP-au;ak+=1}}ak+=1;var E=aL+(ak-1)*au;if(A>=E){E+=au;ak+=1}if(E-A<0.23*au){E+=au;ak+=1}this.max=A=E;this.min=aL;this.tickInterval=au;this.numberTicks=ak;var O;for(aa=0;aa<ak;aa++){O=parseFloat((aL+aa*au).toFixed(11));this.ticks.push([O,O])}this.max=this.ticks[ak-1][1];this.tickFactor=aw;this.numberMinorTicks=b(this.tickPositions,this.tickInterval,this.tickFactor);if(!this.numberMinorTicks){this.numberMinorTicks=b(this.tickPositions,this.tickInterval,this.tickFactor-1)}}else{if(q){var E=aL+(ak-1)*au;if(A>=E){A=E+au;ak+=1}else{A=E}this.tickInterval=this.tickInterval||au;this.numberTicks=this.numberTicks||ak;var O;for(aa=0;aa<this.numberTicks;aa++){O=parseFloat((aL+aa*this.tickInterval).toFixed(11));this.ticks.push([O,O])}this.max=this.ticks[this.numberTicks-1][1];this.tickFactor=aw;this.numberMinorTicks=b(this.tickPositions,this.tickInterval,this.tickFactor);if(!this.numberMinorTicks){this.numberMinorTicks=b(this.tickPositions,this.tickInterval,this.tickFactor-1)}}}if(!q&&!aG){var P=this.max-this.min;aw=Math.floor(parseFloat((Math.log(P)/Math.log(10)).toFixed(11)))-1;var aN=[5,6,4,7,3,8,9,10,2],V,C,av=0,M;if(P>1){var aJ=String(P);if(aJ.search(/\./)==-1){var aF=aJ.search(/0+$/);av=(aF>0)?aJ.length-aF-1:0}}M=P/Math.pow(10,av);for(aa=0;aa<aN.length;aa++){V=M/(aN[aa]-1);if(V==parseInt(V,10)){this.numberTicks=aN[aa];this.tickInterval=P/(this.numberTicks-1);this.tickFactor=aw+1;break}}var O;for(aa=0;aa<this.numberTicks;aa++){O=parseFloat((this.min+aa*this.tickInterval).toFixed(11));this.ticks.push([O,O])}this.numberMinorTicks=b(this.tickPositions,this.tickInterval,this.tickFactor);if(!this.numberMinorTicks){this.numberMinorTicks=b(this.tickPositions,this.tickInterval,this.tickFactor-1)}if(!this.numberMinorTicks){this.numberMinorTicks=1;var aH=[4,5,3,6,2];for(aa=0;aa<5;aa++){var ao=this.tickInterval/aH[aa];if(ao==parseInt(ao,10)){this.numberMinorTicks=aH[aa]-1;break}}}}}var U=this._radius,aE=this.startAngle,k=this.endAngle,H=Math.PI,e=Math.PI/2;if(this.semiCircular){var z=Math.atan(this.innerPad/U),ac=this.outerStartAngle=aE-z,aB=this.outerEndAngle=k+z,B=this.hubStartAngle=aE-Math.atan(this.innerPad/this.hubRadius*2),af=this.hubEndAngle=k+Math.atan(this.innerPad/this.hubRadius*2);X.save();X.translate(this._center[0],this._center[1]);X.lineJoin="round";X.lineCap="round";X.save();X.beginPath();X.fillStyle=this.background;X.arc(0,0,U,ac,aB,false);X.closePath();X.fill();X.restore();var aj="rgba(0,0,0,"+this.shadowAlpha+")";X.save();for(var aa=0;aa<this.shadowDepth;aa++){X.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI),this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));X.beginPath();X.strokeStyle=aj;X.lineWidth=this.shadowWidth;X.arc(0,0,U,ac,aB,false);X.closePath();X.stroke()}X.restore();X.save();var az=parseInt((this.shadowDepth+1)/2,10);for(var aa=0;aa<az;aa++){X.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI),this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));X.beginPath();X.fillStyle=aj;X.arc(0,0,this.hubRadius,B,af,false);X.closePath();X.fill()}X.restore();X.save();X.beginPath();X.strokeStyle=this.ringColor;X.lineWidth=this.ringWidth;X.arc(0,0,U,ac,aB,false);X.closePath();X.stroke();X.restore();X.save();X.beginPath();X.fillStyle=this.ringColor;X.arc(0,0,this.hubRadius,B,af,false);X.closePath();X.fill();X.restore();if(this.showTicks){X.save();var f=this.tickOuterRadius,aq=this.tickLength,v=aq/2,F=this.numberMinorTicks,am=this.span*Math.PI/180/(this.ticks.length-1),p=am/(F+1);for(aa=0;aa<this.ticks.length;aa++){X.beginPath();X.lineWidth=1.5+this.diameter/360;X.strokeStyle=this.ringColor;var ae=am*aa+aE;X.moveTo(-f*Math.cos(am*aa+aE),f*Math.sin(am*aa+aE));X.lineTo(-(f-aq)*Math.cos(am*aa+aE),(f-aq)*Math.sin(am*aa+aE));this._tickPoints.push([(f-aq)*Math.cos(am*aa+aE)+this._center[0]+this.canvas._offsets.left,(f-aq)*Math.sin(am*aa+aE)+this._center[1]+this.canvas._offsets.top,am*aa+aE]);X.stroke();X.lineWidth=1+this.diameter/440;if(aa<this.ticks.length-1){for(var Y=1;Y<=F;Y++){X.beginPath();X.moveTo(-f*Math.cos(am*aa+p*Y+aE),f*Math.sin(am*aa+p*Y+aE));X.lineTo(-(f-v)*Math.cos(am*aa+p*Y+aE),(f-v)*Math.sin(am*aa+p*Y+aE));X.stroke()}}}X.restore()}if(this.showTickLabels){var J,W,T,aO,g,G,n=0;var an=this.tickPadding*(1-1/(this.diameter/80+1));for(aa=0;aa<this.ticks.length;aa++){J=c('<div class="jqplot-meterGauge-tick" style="position:absolute;">'+this.ticks[aa][1]+"</div>");this.canvas._elem.after(J);aO=J.outerWidth(true);g=J.outerHeight(true);W=this._tickPoints[aa][0]-aO*(this._tickPoints[aa][2]-Math.PI)/Math.PI-an*Math.cos(this._tickPoints[aa][2]);T=this._tickPoints[aa][1]-g/2+g/2*Math.pow(Math.abs((Math.sin(this._tickPoints[aa][2]))),0.5)+an/3*Math.pow(Math.abs((Math.sin(this._tickPoints[aa][2]))),0.5);J.css({left:W,top:T});G=aO*Math.cos(this._tickPoints[aa][2])+g*Math.sin(Math.PI/2+this._tickPoints[aa][2]/2);n=(G>n)?G:n}}if(this.label&&this.labelPosition=="inside"){var W=this._center[0]+this.canvas._offsets.left;var an=this.tickPadding*(1-1/(this.diameter/80+1));var T=0.5*(this._center[1]+this.canvas._offsets.top-this.hubRadius)+0.5*(this._center[1]+this.canvas._offsets.top-this.tickOuterRadius+this.tickLength+an)+this.labelHeightAdjust;W-=this._labelElem.outerWidth(true)/2;T-=this._labelElem.outerHeight(true)/2;this._labelElem.css({left:W,top:T})}else{if(this.label&&this.labelPosition=="bottom"){var W=this._center[0]+this.canvas._offsets.left-this._labelElem.outerWidth(true)/2;var T=this._center[1]+this.canvas._offsets.top+this.innerPad+ +this.ringWidth+this.padding+this.labelHeightAdjust;this._labelElem.css({left:W,top:T})}}X.save();var ax=this.intervalInnerRadius||this.hubRadius*1.5;if(this.intervalOuterRadius==null){if(this.showTickLabels){var ag=(this.tickOuterRadius-this.tickLength-this.tickPadding-this.diameter/8)}else{var ag=(this.tickOuterRadius-this.tickLength-this.diameter/16)}}else{var ag=this.intervalOuterRadius}var P=this.max-this.min;var aD=this.intervals[this.intervals.length-1]-this.min;var y,Z,u=this.span*Math.PI/180;for(aa=0;aa<this.intervals.length;aa++){y=(aa==0)?aE:aE+(this.intervals[aa-1][0]-this.min)*u/P;if(y<0){y=0}Z=aE+(this.intervals[aa][0]-this.min)*u/P;if(Z<0){Z=0}X.beginPath();X.fillStyle=this.intervals[aa][2];X.arc(0,0,ax,y,Z,false);X.lineTo(ag*Math.cos(Z),ag*Math.sin(Z));X.arc(0,0,ag,Z,y,true);X.lineTo(ax*Math.cos(y),ax*Math.sin(y));X.closePath();X.fill()}X.restore();var ay=this.data[0][1];var R=this.max-this.min;if(this.pegNeedle){if(this.data[0][1]>this.max+R*3/this.span){ay=this.max+R*3/this.span}if(this.data[0][1]<this.min-R*3/this.span){ay=this.min-R*3/this.span}}var al=(ay-this.min)/R*this.span*Math.PI/180+this.startAngle;X.save();X.beginPath();X.fillStyle=this.ringColor;X.strokeStyle=this.ringColor;this.needleLength=(this.tickOuterRadius-this.tickLength)*0.85;this.needleThickness=(this.needleThickness<2)?2:this.needleThickness;var aK=this.needleThickness*0.4;var x=this.needleLength/10;var s=(this.needleThickness-aK)/10;var ar;for(var aa=0;aa<10;aa++){ar=this.needleThickness-aa*s;X.moveTo(x*aa*Math.cos(al),x*aa*Math.sin(al));X.lineWidth=ar;X.lineTo(x*(aa+1)*Math.cos(al),x*(aa+1)*Math.sin(al));X.stroke()}X.restore()}else{this._center=[(K-at*ai)/2+at*ai,(S-at*ah)/2+at*ah]}};c.jqplot.MeterGaugeAxisRenderer=function(){c.jqplot.LinearAxisRenderer.call(this)};c.jqplot.MeterGaugeAxisRenderer.prototype=new c.jqplot.LinearAxisRenderer();c.jqplot.MeterGaugeAxisRenderer.prototype.constructor=c.jqplot.MeterGaugeAxisRenderer;c.jqplot.MeterGaugeAxisRenderer.prototype.init=function(e){this.tickRenderer=c.jqplot.MeterGaugeTickRenderer;c.extend(true,this,e);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};c.jqplot.MeterGaugeLegendRenderer=function(){c.jqplot.TableLegendRenderer.call(this)};c.jqplot.MeterGaugeLegendRenderer.prototype=new c.jqplot.TableLegendRenderer();c.jqplot.MeterGaugeLegendRenderer.prototype.constructor=c.jqplot.MeterGaugeLegendRenderer;c.jqplot.MeterGaugeLegendRenderer.prototype.init=function(e){this.numberRows=null;this.numberColumns=null;c.extend(true,this,e)};c.jqplot.MeterGaugeLegendRenderer.prototype.draw=function(){if(this.show){var p=this._series;var x="position:absolute;";x+=(this.background)?"background:"+this.background+";":"";x+=(this.border)?"border:"+this.border+";":"";x+=(this.fontSize)?"font-size:"+this.fontSize+";":"";x+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";x+=(this.textColor)?"color:"+this.textColor+";":"";x+=(this.marginTop!=null)?"margin-top:"+this.marginTop+";":"";x+=(this.marginBottom!=null)?"margin-bottom:"+this.marginBottom+";":"";x+=(this.marginLeft!=null)?"margin-left:"+this.marginLeft+";":"";x+=(this.marginRight!=null)?"margin-right:"+this.marginRight+";":"";this._elem=c('<table class="jqplot-table-legend" style="'+x+'"></table>');var f=false,q=false,u,o;var w=p[0];if(w.show){var t=w.data;if(this.numberRows){u=this.numberRows;if(!this.numberColumns){o=Math.ceil(t.length/u)}else{o=this.numberColumns}}else{if(this.numberColumns){o=this.numberColumns;u=Math.ceil(t.length/this.numberColumns)}else{u=t.length;o=1}}var n,m,r,g,e,l,k,h;var v=0;for(n=0;n<u;n++){if(q){r=c('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem)}else{r=c('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem)}for(m=0;m<o;m++){if(v<t.length){l=this.labels[v]||t[v][0].toString();h=w.color;if(!q){if(n>0){f=true}else{f=false}}else{if(n==u-1){f=false}else{f=true}}k=(f)?this.rowSpacing:"0";g=c('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+k+';"><div><div class="jqplot-table-legend-swatch" style="border-color:'+h+';"></div></div></td>');e=c('<td class="jqplot-table-legend" style="padding-top:'+k+';"></td>');if(this.escapeHtml){e.text(l)}else{e.html(l)}if(q){e.prependTo(r);g.prependTo(r)}else{g.appendTo(r);e.appendTo(r)}f=true}v++}}}}return this._elem};function a(j,h,f){f=f||{};f.axesDefaults=f.axesDefaults||{};f.legend=f.legend||{};f.seriesDefaults=f.seriesDefaults||{};f.grid=f.grid||{};f.gridPadding=f.gridPadding||{};var e=false;if(f.seriesDefaults.renderer==c.jqplot.MeterGaugeRenderer){e=true}else{if(f.series){for(var g=0;g<f.series.length;g++){if(f.series[g].renderer==c.jqplot.MeterGaugeRenderer){e=true}}}}if(e){f.axesDefaults.renderer=c.jqplot.MeterGaugeAxisRenderer;f.legend.renderer=c.jqplot.MeterGaugeLegendRenderer;f.legend.preDraw=true;f.grid.background=f.grid.background||"white";f.grid.drawGridlines=false;f.grid.borderWidth=(f.grid.borderWidth!=null)?f.grid.borderWidth:0;f.grid.shadow=(f.grid.shadow!=null)?f.grid.shadow:false;f.gridPadding.top=(f.gridPadding.top!=null)?f.gridPadding.top:0;f.gridPadding.bottom=(f.gridPadding.bottom!=null)?f.gridPadding.bottom:0;f.gridPadding.left=(f.gridPadding.left!=null)?f.gridPadding.left:0;f.gridPadding.right=(f.gridPadding.right!=null)?f.gridPadding.right:0}}function d(e){}c.jqplot.preInitHooks.push(a);c.jqplot.postParseOptionsHooks.push(d);c.jqplot.MeterGaugeTickRenderer=function(){c.jqplot.AxisTickRenderer.call(this)};c.jqplot.MeterGaugeTickRenderer.prototype=new c.jqplot.AxisTickRenderer();c.jqplot.MeterGaugeTickRenderer.prototype.constructor=c.jqplot.MeterGaugeTickRenderer})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.ohlcRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.ohlcRenderer.js new file mode 100644 index 0000000000..41f963b313 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.ohlcRenderer.js @@ -0,0 +1,372 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.OHLCRenderer + * jqPlot Plugin to draw Open Hi Low Close, Candlestick and Hi Low Close charts. + * + * To use this plugin, include the renderer js file in + * your source: + * + * > <script type="text/javascript" src="plugins/jqplot.ohlcRenderer.js"></script> + * + * You will most likely want to use a date axis renderer + * for the x axis also, so include the date axis render js file also: + * + * > <script type="text/javascript" src="plugins/jqplot.dateAxisRenderer.js"></script> + * + * Then you set the renderer in the series options on your plot: + * + * > series: [{renderer:$.jqplot.OHLCRenderer}] + * + * For OHLC and candlestick charts, data should be specified + * like so: + * + * > dat = [['07/06/2009',138.7,139.68,135.18,135.4], ['06/29/2009',143.46,144.66,139.79,140.02], ...] + * + * If the data array has only 4 values per point instead of 5, + * the renderer will create a Hi Low Close chart instead. In that case, + * data should be supplied like: + * + * > dat = [['07/06/2009',139.68,135.18,135.4], ['06/29/2009',144.66,139.79,140.02], ...] + * + * To generate a candlestick chart instead of an OHLC chart, + * set the "candlestick" option to true: + * + * > series: [{renderer:$.jqplot.OHLCRenderer, rendererOptions:{candleStick:true}}], + * + */ + $.jqplot.OHLCRenderer = function(){ + // subclass line renderer to make use of some of it's methods. + $.jqplot.LineRenderer.call(this); + // prop: candleStick + // true to render chart as candleStick. + // Must have an open price, cannot be a hlc chart. + this.candleStick = false; + // prop: tickLength + // length of the line in pixels indicating open and close price. + // Default will auto calculate based on plot width and + // number of points displayed. + this.tickLength = 'auto'; + // prop: bodyWidth + // width of the candlestick body in pixels. Default will auto calculate + // based on plot width and number of candlesticks displayed. + this.bodyWidth = 'auto'; + // prop: openColor + // color of the open price tick mark. Default is series color. + this.openColor = null; + // prop: closeColor + // color of the close price tick mark. Default is series color. + this.closeColor = null; + // prop: wickColor + // color of the hi-lo line thorugh the candlestick body. + // Default is the series color. + this.wickColor = null; + // prop: fillUpBody + // true to render an "up" day (close price greater than open price) + // with a filled candlestick body. + this.fillUpBody = false; + // prop: fillDownBody + // true to render a "down" day (close price lower than open price) + // with a filled candlestick body. + this.fillDownBody = true; + // prop: upBodyColor + // Color of candlestick body of an "up" day. Default is series color. + this.upBodyColor = null; + // prop: downBodyColor + // Color of candlestick body on a "down" day. Default is series color. + this.downBodyColor = null; + // prop: hlc + // true if is a hi-low-close chart (no open price). + // This is determined automatically from the series data. + this.hlc = false; + // prop: lineWidth + // Width of the hi-low line and open/close ticks. + // Must be set in the rendererOptions for the series. + this.lineWidth = 1.5; + this._tickLength; + this._bodyWidth; + }; + + $.jqplot.OHLCRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.OHLCRenderer.prototype.constructor = $.jqplot.OHLCRenderer; + + // called with scope of series. + $.jqplot.OHLCRenderer.prototype.init = function(options) { + options = options || {}; + // lineWidth has to be set on the series, changes in renderer + // constructor have no effect. set the default here + // if no renderer option for lineWidth is specified. + this.lineWidth = options.lineWidth || 1.5; + $.jqplot.LineRenderer.prototype.init.call(this, options); + this._type = 'ohlc'; + // set the yaxis data bounds here to account for hi and low values + var db = this._yaxis._dataBounds; + var d = this._plotData; + // if data points have less than 5 values, force a hlc chart. + if (d[0].length < 5) { + this.renderer.hlc = true; + + for (var j=0; j<d.length; j++) { + if (d[j][2] < db.min || db.min == null) { + db.min = d[j][2]; + } + if (d[j][1] > db.max || db.max == null) { + db.max = d[j][1]; + } + } + } + else { + for (var j=0; j<d.length; j++) { + if (d[j][3] < db.min || db.min == null) { + db.min = d[j][3]; + } + if (d[j][2] > db.max || db.max == null) { + db.max = d[j][2]; + } + } + } + + }; + + // called within scope of series. + $.jqplot.OHLCRenderer.prototype.draw = function(ctx, gd, options) { + var d = this.data; + var xmin = this._xaxis.min; + var xmax = this._xaxis.max; + // index of last value below range of plot. + var xminidx = 0; + // index of first value above range of plot. + var xmaxidx = d.length; + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var i, prevColor, ops, b, h, w, a, points; + var o; + var r = this.renderer; + var opts = (options != undefined) ? options : {}; + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var fillAndStroke = (opts.fillAndStroke != undefined) ? opts.fillAndStroke : this.fillAndStroke; + r.bodyWidth = (opts.bodyWidth != undefined) ? opts.bodyWidth : r.bodyWidth; + r.tickLength = (opts.tickLength != undefined) ? opts.tickLength : r.tickLength; + ctx.save(); + if (this.show) { + var x, open, hi, low, close; + // need to get widths based on number of points shown, + // not on total number of points. Use the results + // to speed up drawing in next step. + for (var i=0; i<d.length; i++) { + if (d[i][0] < xmin) { + xminidx = i; + } + else if (d[i][0] < xmax) { + xmaxidx = i+1; + } + } + + var dwidth = this.gridData[xmaxidx-1][0] - this.gridData[xminidx][0]; + var nvisiblePoints = xmaxidx - xminidx; + try { + var dinterval = Math.abs(this._xaxis.series_u2p(parseInt(this._xaxis._intervalStats[0].sortedIntervals[0].interval)) - this._xaxis.series_u2p(0)); + } + + catch (e) { + var dinterval = dwidth / nvisiblePoints; + } + + if (r.candleStick) { + if (typeof(r.bodyWidth) == 'number') { + r._bodyWidth = r.bodyWidth; + } + else { + r._bodyWidth = Math.min(20, dinterval/1.75); + } + } + else { + if (typeof(r.tickLength) == 'number') { + r._tickLength = r.tickLength; + } + else { + r._tickLength = Math.min(10, dinterval/3.5); + } + } + + for (var i=xminidx; i<xmaxidx; i++) { + x = xp(d[i][0]); + if (r.hlc) { + open = null; + hi = yp(d[i][1]); + low = yp(d[i][2]); + close = yp(d[i][3]); + } + else { + open = yp(d[i][1]); + hi = yp(d[i][2]); + low = yp(d[i][3]); + close = yp(d[i][4]); + } + o = {}; + if (r.candleStick && !r.hlc) { + w = r._bodyWidth; + a = x - w/2; + // draw candle + // determine if candle up or down + // up, remember grid coordinates increase downward + if (close < open) { + // draw wick + if (r.wickColor) { + o.color = r.wickColor; + } + else if (r.downBodyColor) { + o.color = r.upBodyColor; + } + ops = $.extend(true, {}, opts, o); + r.shapeRenderer.draw(ctx, [[x, hi], [x, close]], ops); + r.shapeRenderer.draw(ctx, [[x, open], [x, low]], ops); + o = {}; + b = close; + h = open - close; + // if color specified, use it + if (r.fillUpBody) { + o.fillRect = true; + } + else { + o.strokeRect = true; + w = w - this.lineWidth; + a = x - w/2; + } + if (r.upBodyColor) { + o.color = r.upBodyColor; + o.fillStyle = r.upBodyColor; + } + points = [a, b, w, h]; + } + // down + else if (close > open) { + // draw wick + if (r.wickColor) { + o.color = r.wickColor; + } + else if (r.downBodyColor) { + o.color = r.downBodyColor; + } + ops = $.extend(true, {}, opts, o); + r.shapeRenderer.draw(ctx, [[x, hi], [x, open]], ops); + r.shapeRenderer.draw(ctx, [[x, close], [x, low]], ops); + + o = {}; + + b = open; + h = close - open; + // if color specified, use it + if (r.fillDownBody) { + o.fillRect = true; + } + else { + o.strokeRect = true; + w = w - this.lineWidth; + a = x - w/2; + } + if (r.downBodyColor) { + o.color = r.downBodyColor; + o.fillStyle = r.downBodyColor; + } + points = [a, b, w, h]; + } + // even, open = close + else { + // draw wick + if (r.wickColor) { + o.color = r.wickColor; + } + ops = $.extend(true, {}, opts, o); + r.shapeRenderer.draw(ctx, [[x, hi], [x, low]], ops); + o = {}; + o.fillRect = false; + o.strokeRect = false; + a = [x - w/2, open]; + b = [x + w/2, close]; + w = null; + h = null; + points = [a, b]; + } + ops = $.extend(true, {}, opts, o); + r.shapeRenderer.draw(ctx, points, ops); + } + else { + prevColor = opts.color; + if (r.openColor) { + opts.color = r.openColor; + } + // draw open tick + if (!r.hlc) { + r.shapeRenderer.draw(ctx, [[x-r._tickLength, open], [x, open]], opts); + } + opts.color = prevColor; + // draw wick + if (r.wickColor) { + opts.color = r.wickColor; + } + r.shapeRenderer.draw(ctx, [[x, hi], [x, low]], opts); + opts.color = prevColor; + // draw close tick + if (r.closeColor) { + opts.color = r.closeColor; + } + r.shapeRenderer.draw(ctx, [[x, close], [x+r._tickLength, close]], opts); + opts.color = prevColor; + } + } + } + + ctx.restore(); + }; + + $.jqplot.OHLCRenderer.prototype.drawShadow = function(ctx, gd, options) { + // This is a no-op, shadows drawn with lines. + }; + + // called with scope of plot. + $.jqplot.OHLCRenderer.checkOptions = function(target, data, options) { + // provide some sensible highlighter options by default + // These aren't good for hlc, only for ohlc or candlestick + if (!options.highlighter) { + options.highlighter = { + showMarker:false, + tooltipAxes: 'y', + yvalues: 4, + formatString:'<table class="jqplot-highlighter"><tr><td>date:</td><td>%s</td></tr><tr><td>open:</td><td>%s</td></tr><tr><td>hi:</td><td>%s</td></tr><tr><td>low:</td><td>%s</td></tr><tr><td>close:</td><td>%s</td></tr></table>' + }; + } + }; + + //$.jqplot.preInitHooks.push($.jqplot.OHLCRenderer.checkOptions); + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.ohlcRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.ohlcRenderer.min.js new file mode 100644 index 0000000000..97a265a310 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.ohlcRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(a){a.jqplot.OHLCRenderer=function(){a.jqplot.LineRenderer.call(this);this.candleStick=false;this.tickLength="auto";this.bodyWidth="auto";this.openColor=null;this.closeColor=null;this.wickColor=null;this.fillUpBody=false;this.fillDownBody=true;this.upBodyColor=null;this.downBodyColor=null;this.hlc=false;this.lineWidth=1.5;this._tickLength;this._bodyWidth};a.jqplot.OHLCRenderer.prototype=new a.jqplot.LineRenderer();a.jqplot.OHLCRenderer.prototype.constructor=a.jqplot.OHLCRenderer;a.jqplot.OHLCRenderer.prototype.init=function(e){e=e||{};this.lineWidth=e.lineWidth||1.5;a.jqplot.LineRenderer.prototype.init.call(this,e);this._type="ohlc";var b=this._yaxis._dataBounds;var f=this._plotData;if(f[0].length<5){this.renderer.hlc=true;for(var c=0;c<f.length;c++){if(f[c][2]<b.min||b.min==null){b.min=f[c][2]}if(f[c][1]>b.max||b.max==null){b.max=f[c][1]}}}else{for(var c=0;c<f.length;c++){if(f[c][3]<b.min||b.min==null){b.min=f[c][3]}if(f[c][2]>b.max||b.max==null){b.max=f[c][2]}}}};a.jqplot.OHLCRenderer.prototype.draw=function(A,N,j){var J=this.data;var v=this._xaxis.min;var z=this._xaxis.max;var l=0;var K=J.length;var p=this._xaxis.series_u2p;var G=this._yaxis.series_u2p;var D,E,f,M,F,n,O,C;var y;var u=this.renderer;var s=(j!=undefined)?j:{};var k=(s.shadow!=undefined)?s.shadow:this.shadow;var B=(s.fill!=undefined)?s.fill:this.fill;var c=(s.fillAndStroke!=undefined)?s.fillAndStroke:this.fillAndStroke;u.bodyWidth=(s.bodyWidth!=undefined)?s.bodyWidth:u.bodyWidth;u.tickLength=(s.tickLength!=undefined)?s.tickLength:u.tickLength;A.save();if(this.show){var m,q,g,Q,t;for(var D=0;D<J.length;D++){if(J[D][0]<v){l=D}else{if(J[D][0]<z){K=D+1}}}var I=this.gridData[K-1][0]-this.gridData[l][0];var L=K-l;try{var P=Math.abs(this._xaxis.series_u2p(parseInt(this._xaxis._intervalStats[0].sortedIntervals[0].interval))-this._xaxis.series_u2p(0))}catch(H){var P=I/L}if(u.candleStick){if(typeof(u.bodyWidth)=="number"){u._bodyWidth=u.bodyWidth}else{u._bodyWidth=Math.min(20,P/1.75)}}else{if(typeof(u.tickLength)=="number"){u._tickLength=u.tickLength}else{u._tickLength=Math.min(10,P/3.5)}}for(var D=l;D<K;D++){m=p(J[D][0]);if(u.hlc){q=null;g=G(J[D][1]);Q=G(J[D][2]);t=G(J[D][3])}else{q=G(J[D][1]);g=G(J[D][2]);Q=G(J[D][3]);t=G(J[D][4])}y={};if(u.candleStick&&!u.hlc){n=u._bodyWidth;O=m-n/2;if(t<q){if(u.wickColor){y.color=u.wickColor}else{if(u.downBodyColor){y.color=u.upBodyColor}}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,[[m,g],[m,t]],f);u.shapeRenderer.draw(A,[[m,q],[m,Q]],f);y={};M=t;F=q-t;if(u.fillUpBody){y.fillRect=true}else{y.strokeRect=true;n=n-this.lineWidth;O=m-n/2}if(u.upBodyColor){y.color=u.upBodyColor;y.fillStyle=u.upBodyColor}C=[O,M,n,F]}else{if(t>q){if(u.wickColor){y.color=u.wickColor}else{if(u.downBodyColor){y.color=u.downBodyColor}}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,[[m,g],[m,q]],f);u.shapeRenderer.draw(A,[[m,t],[m,Q]],f);y={};M=q;F=t-q;if(u.fillDownBody){y.fillRect=true}else{y.strokeRect=true;n=n-this.lineWidth;O=m-n/2}if(u.downBodyColor){y.color=u.downBodyColor;y.fillStyle=u.downBodyColor}C=[O,M,n,F]}else{if(u.wickColor){y.color=u.wickColor}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,[[m,g],[m,Q]],f);y={};y.fillRect=false;y.strokeRect=false;O=[m-n/2,q];M=[m+n/2,t];n=null;F=null;C=[O,M]}}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,C,f)}else{E=s.color;if(u.openColor){s.color=u.openColor}if(!u.hlc){u.shapeRenderer.draw(A,[[m-u._tickLength,q],[m,q]],s)}s.color=E;if(u.wickColor){s.color=u.wickColor}u.shapeRenderer.draw(A,[[m,g],[m,Q]],s);s.color=E;if(u.closeColor){s.color=u.closeColor}u.shapeRenderer.draw(A,[[m,t],[m+u._tickLength,t]],s);s.color=E}}}A.restore()};a.jqplot.OHLCRenderer.prototype.drawShadow=function(b,d,c){};a.jqplot.OHLCRenderer.checkOptions=function(d,c,b){if(!b.highlighter){b.highlighter={showMarker:false,tooltipAxes:"y",yvalues:4,formatString:'<table class="jqplot-highlighter"><tr><td>date:</td><td>%s</td></tr><tr><td>open:</td><td>%s</td></tr><tr><td>hi:</td><td>%s</td></tr><tr><td>low:</td><td>%s</td></tr><tr><td>close:</td><td>%s</td></tr></table>'}}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.pieRenderer.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.pieRenderer.js new file mode 100644 index 0000000000..4aa7340aac --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.pieRenderer.js @@ -0,0 +1,898 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.PieRenderer + * Plugin renderer to draw a pie chart. + * x values, if present, will be used as slice labels. + * y values give slice size. + * + * To use this renderer, you need to include the + * pie renderer plugin, for example: + * + * > <script type="text/javascript" src="plugins/jqplot.pieRenderer.js"></script> + * + * Properties described here are passed into the $.jqplot function + * as options on the series renderer. For example: + * + * > plot2 = $.jqplot('chart2', [s1, s2], { + * > seriesDefaults: { + * > renderer:$.jqplot.PieRenderer, + * > rendererOptions:{ + * > sliceMargin: 2, + * > startAngle: -90 + * > } + * > } + * > }); + * + * A pie plot will trigger events on the plot target + * according to user interaction. All events return the event object, + * the series index, the point (slice) index, and the point data for + * the appropriate slice. + * + * 'jqplotDataMouseOver' - triggered when user mouseing over a slice. + * 'jqplotDataHighlight' - triggered the first time user mouses over a slice, + * if highlighting is enabled. + * 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of + * a highlighted slice. + * 'jqplotDataClick' - triggered when the user clicks on a slice. + * 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if + * the "captureRightClick" option is set to true on the plot. + */ + $.jqplot.PieRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer; + + // called with scope of a series + $.jqplot.PieRenderer.prototype.init = function(options, plot) { + // Group: Properties + // + // prop: diameter + // Outer diameter of the pie, auto computed by default + this.diameter = null; + // prop: padding + // padding between the pie and plot edges, legend, etc. + this.padding = 20; + // prop: sliceMargin + // angular spacing between pie slices in degrees. + this.sliceMargin = 0; + // prop: fill + // true or false, wether to fil the slices. + this.fill = true; + // prop: shadowOffset + // offset of the shadow from the slice and offset of + // each succesive stroke of the shadow from the last. + this.shadowOffset = 2; + // prop: shadowAlpha + // transparency of the shadow (0 = transparent, 1 = opaque) + this.shadowAlpha = 0.07; + // prop: shadowDepth + // number of strokes to apply to the shadow, + // each stroke offset shadowOffset from the last. + this.shadowDepth = 5; + // prop: highlightMouseOver + // True to highlight slice when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on a slice. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over a slice. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColors + // an array of colors to use when highlighting a slice. + this.highlightColors = []; + // prop: dataLabels + // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices. + // Defaults to percentage of each pie slice. + this.dataLabels = 'percent'; + // prop: showDataLabels + // true to show data labels on slices. + this.showDataLabels = false; + // prop: dataLabelFormatString + // Format string for data labels. If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage. + this.dataLabelFormatString = null; + // prop: dataLabelThreshold + // Threshhold in percentage (0-100) of pie area, below which no label will be displayed. + // This applies to all label types, not just to percentage labels. + this.dataLabelThreshold = 3; + // prop: dataLabelPositionFactor + // A Multiplier (0-1) of the pie radius which controls position of label on slice. + // Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie. + this.dataLabelPositionFactor = 0.52; + // prop: dataLabelNudge + // Number of pixels to slide the label away from (+) or toward (-) the center of the pie. + this.dataLabelNudge = 2; + // prop: dataLabelCenterOn + // True to center the data label at its position. + // False to set the inside facing edge of the label at its position. + this.dataLabelCenterOn = true; + // prop: startAngle + // Angle to start drawing pie in degrees. + // According to orientation of canvas coordinate system: + // 0 = on the positive x axis + // -90 = on the positive y axis. + // 90 = on the negaive y axis. + // 180 or - 180 = on the negative x axis. + this.startAngle = 0; + this.tickRenderer = $.jqplot.PieTickRenderer; + // Used as check for conditions where pie shouldn't be drawn. + this._drawData = true; + this._type = 'pie'; + + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (options.highlightMouseDown && options.highlightMouseOver == null) { + options.highlightMouseOver = false; + } + + $.extend(true, this, options); + + if (this.sliceMargin < 0) { + this.sliceMargin = 0; + } + + this._diameter = null; + this._radius = null; + // array of [start,end] angles arrays, one for each slice. In radians. + this._sliceAngles = []; + // index of the currenty highlighted point, if any + this._highlightedPoint = null; + + // set highlight colors if none provided + if (this.highlightColors.length == 0) { + for (var i=0; i<this.seriesColors.length; i++){ + var rgba = $.jqplot.getColorComponents(this.seriesColors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + } + } + + this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors); + + plot.postParseOptionsHooks.addOnce(postParseOptions); + plot.postInitHooks.addOnce(postInit); + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + plot.postDrawHooks.addOnce(postPlotDraw); + }; + + $.jqplot.PieRenderer.prototype.setGridData = function(plot) { + // set gridData property. This will hold angle in radians of each data point. + var stack = []; + var td = []; + var sa = this.startAngle/180*Math.PI; + var tot = 0; + // don't know if we have any valid data yet, so set plot to not draw. + this._drawData = false; + for (var i=0; i<this.data.length; i++){ + if (this.data[i][1] != 0) { + // we have data, O.K. to draw. + this._drawData = true; + } + stack.push(this.data[i][1]); + td.push([this.data[i][0]]); + if (i>0) { + stack[i] += stack[i-1]; + } + tot += this.data[i][1]; + } + var fact = Math.PI*2/stack[stack.length - 1]; + + for (var i=0; i<stack.length; i++) { + td[i][1] = stack[i] * fact; + td[i][2] = this.data[i][1]/tot; + } + this.gridData = td; + }; + + $.jqplot.PieRenderer.prototype.makeGridData = function(data, plot) { + var stack = []; + var td = []; + var tot = 0; + var sa = this.startAngle/180*Math.PI; + // don't know if we have any valid data yet, so set plot to not draw. + this._drawData = false; + for (var i=0; i<data.length; i++){ + if (this.data[i][1] != 0) { + // we have data, O.K. to draw. + this._drawData = true; + } + stack.push(data[i][1]); + td.push([data[i][0]]); + if (i>0) { + stack[i] += stack[i-1]; + } + tot += data[i][1]; + } + var fact = Math.PI*2/stack[stack.length - 1]; + + for (var i=0; i<stack.length; i++) { + td[i][1] = stack[i] * fact; + td[i][2] = data[i][1]/tot; + } + return td; + }; + + function calcRadiusAdjustment(ang) { + return Math.sin((ang - (ang-Math.PI) / 8 / Math.PI )/2.0); + } + + function calcRPrime(ang1, ang2, sliceMargin, fill, lineWidth) { + var rprime = 0; + var ang = ang2 - ang1; + var absang = Math.abs(ang); + var sm = sliceMargin; + if (fill == false) { + sm += lineWidth; + } + + if (sm > 0 && absang > 0.01 && absang < 6.282) { + rprime = parseFloat(sm) / 2.0 / calcRadiusAdjustment(ang); + } + + return rprime; + } + + $.jqplot.PieRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) { + if (this._drawData) { + var r = this._radius; + var fill = this.fill; + var lineWidth = this.lineWidth; + var sm = this.sliceMargin; + if (this.fill == false) { + sm += this.lineWidth; + } + ctx.save(); + ctx.translate(this._center[0], this._center[1]); + + var rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth); + + var transx = rprime * Math.cos((ang1 + ang2) / 2.0); + var transy = rprime * Math.sin((ang1 + ang2) / 2.0); + + if ((ang2 - ang1) <= Math.PI) { + r -= rprime; + } + else { + r += rprime; + } + + ctx.translate(transx, transy); + + if (isShadow) { + for (var i=0, l=this.shadowDepth; i<l; i++) { + ctx.save(); + ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI)); + doDraw(r); + } + for (var i=0, l=this.shadowDepth; i<l; i++) { + ctx.restore(); + } + } + + else { + doDraw(r); + } + ctx.restore(); + } + + function doDraw (rad) { + // Fix for IE and Chrome that can't seem to draw circles correctly. + // ang2 should always be <= 2 pi since that is the way the data is converted. + // 2Pi = 6.2831853, Pi = 3.1415927 + if (ang2 > 6.282 + this.startAngle) { + ang2 = 6.282 + this.startAngle; + if (ang1 > ang2) { + ang1 = 6.281 + this.startAngle; + } + } + // Fix for IE, where it can't seem to handle 0 degree angles. Also avoids + // ugly line on unfilled pies. + if (ang1 >= ang2) { + return; + } + + ctx.beginPath(); + ctx.fillStyle = color; + ctx.strokeStyle = color; + ctx.lineWidth = lineWidth; + ctx.arc(0, 0, rad, ang1, ang2, false); + ctx.lineTo(0,0); + ctx.closePath(); + + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + } + }; + + // called with scope of series + $.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) { + var i; + var opts = (options != undefined) ? options : {}; + // offset and direction of offset due to legend placement + var offx = 0; + var offy = 0; + var trans = 1; + var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors); + if (options.legendInfo && options.legendInfo.placement == 'insideGrid') { + var li = options.legendInfo; + switch (li.location) { + case 'nw': + offx = li.width + li.xoffset; + break; + case 'w': + offx = li.width + li.xoffset; + break; + case 'sw': + offx = li.width + li.xoffset; + break; + case 'ne': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'e': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'se': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'n': + offy = li.height + li.yoffset; + break; + case 's': + offy = li.height + li.yoffset; + trans = -1; + break; + default: + break; + } + } + + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var cw = ctx.canvas.width; + var ch = ctx.canvas.height; + var w = cw - offx - 2 * this.padding; + var h = ch - offy - 2 * this.padding; + var mindim = Math.min(w,h); + var d = mindim; + + // Fixes issue #272. Thanks hugwijst! + // reset slice angles array. + this._sliceAngles = []; + + var sm = this.sliceMargin; + if (this.fill == false) { + sm += this.lineWidth; + } + + var rprime; + var maxrprime = 0; + + var ang, ang1, ang2, shadowColor; + var sa = this.startAngle / 180 * Math.PI; + + // have to pre-draw shadows, so loop throgh here and calculate some values also. + for (var i=0, l=gd.length; i<l; i++) { + ang1 = (i == 0) ? sa : gd[i-1][1] + sa; + ang2 = gd[i][1] + sa; + + this._sliceAngles.push([ang1, ang2]); + + rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth); + + if (Math.abs(ang2-ang1) > Math.PI) { + maxrprime = Math.max(rprime, maxrprime); + } + } + + if (this.diameter != null && this.diameter > 0) { + this._diameter = this.diameter - 2*maxrprime; + } + else { + this._diameter = d - 2*maxrprime; + } + + // Need to check for undersized pie. This can happen if + // plot area too small and legend is too big. + if (this._diameter < 6) { + $.jqplot.log('Diameter of pie too small, not rendering.'); + return; + } + + var r = this._radius = this._diameter/2; + + this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)]; + + if (this.shadow) { + for (var i=0, l=gd.length; i<l; i++) { + shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')'; + this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], shadowColor, true); + } + } + + for (var i=0; i<gd.length; i++) { + + this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], colorGenerator.next(), false); + + if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) { + var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label; + + if (this.dataLabels == 'label') { + fstr = this.dataLabelFormatString || '%s'; + label = $.jqplot.sprintf(fstr, gd[i][0]); + } + else if (this.dataLabels == 'value') { + fstr = this.dataLabelFormatString || '%d'; + label = $.jqplot.sprintf(fstr, this.data[i][1]); + } + else if (this.dataLabels == 'percent') { + fstr = this.dataLabelFormatString || '%d%%'; + label = $.jqplot.sprintf(fstr, gd[i][2]*100); + } + else if (this.dataLabels.constructor == Array) { + fstr = this.dataLabelFormatString || '%s'; + label = $.jqplot.sprintf(fstr, this.dataLabels[i]); + } + + var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge; + + var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left; + var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top; + + var labelelem = $('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">' + label + '</div>').insertBefore(plot.eventCanvas._elem); + if (this.dataLabelCenterOn) { + x -= labelelem.width()/2; + y -= labelelem.height()/2; + } + else { + x -= labelelem.width() * Math.sin(avgang/2); + y -= labelelem.height()/2; + } + x = Math.round(x); + y = Math.round(y); + labelelem.css({left: x, top: y}); + } + } + }; + + $.jqplot.PieAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + }; + + $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer; + + + // There are no traditional axes on a pie chart. We just need to provide + // dummy objects with properties so the plot will render. + // called with scope of axis object. + $.jqplot.PieAxisRenderer.prototype.init = function(options){ + // + this.tickRenderer = $.jqplot.PieTickRenderer; + $.extend(true, this, options); + // I don't think I'm going to need _dataBounds here. + // have to go Axis scaling in a way to fit chart onto plot area + // and provide u2p and p2u functionality for mouse cursor, etc. + // for convienence set _dataBounds to 0 and 100 and + // set min/max to 0 and 100. + this._dataBounds = {min:0, max:100}; + this.min = 0; + this.max = 100; + this.showTicks = false; + this.ticks = []; + this.showMark = false; + this.show = false; + }; + + + + + $.jqplot.PieLegendRenderer = function(){ + $.jqplot.TableLegendRenderer.call(this); + }; + + $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); + $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer; + + /** + * Class: $.jqplot.PieLegendRenderer + * Legend Renderer specific to pie plots. Set by default + * when user creates a pie plot. + */ + $.jqplot.PieLegendRenderer.prototype.init = function(options) { + // Group: Properties + // + // prop: numberRows + // Maximum number of rows in the legend. 0 or null for unlimited. + this.numberRows = null; + // prop: numberColumns + // Maximum number of columns in the legend. 0 or null for unlimited. + this.numberColumns = null; + $.extend(true, this, options); + }; + + // called with context of legend + $.jqplot.PieLegendRenderer.prototype.draw = function() { + var legend = this; + if (this.show) { + var series = this._series; + + + this._elem = $(document.createElement('table')); + this._elem.addClass('jqplot-table-legend'); + + var ss = {position:'absolute'}; + if (this.background) { + ss['background'] = this.background; + } + if (this.border) { + ss['border'] = this.border; + } + if (this.fontSize) { + ss['fontSize'] = this.fontSize; + } + if (this.fontFamily) { + ss['fontFamily'] = this.fontFamily; + } + if (this.textColor) { + ss['textColor'] = this.textColor; + } + if (this.marginTop != null) { + ss['marginTop'] = this.marginTop; + } + if (this.marginBottom != null) { + ss['marginBottom'] = this.marginBottom; + } + if (this.marginLeft != null) { + ss['marginLeft'] = this.marginLeft; + } + if (this.marginRight != null) { + ss['marginRight'] = this.marginRight; + } + + this._elem.css(ss); + + // Pie charts legends don't go by number of series, but by number of data points + // in the series. Refactor things here for that. + + var pad = false, + reverse = false, + nr, + nc; + var s = series[0]; + var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors); + + if (s.show) { + var pd = s.data; + if (this.numberRows) { + nr = this.numberRows; + if (!this.numberColumns){ + nc = Math.ceil(pd.length/nr); + } + else{ + nc = this.numberColumns; + } + } + else if (this.numberColumns) { + nc = this.numberColumns; + nr = Math.ceil(pd.length/this.numberColumns); + } + else { + nr = pd.length; + nc = 1; + } + + var i, j; + var tr, td1, td2; + var lt, rs, color; + var idx = 0; + var div0, div1; + + for (i=0; i<nr; i++) { + tr = $(document.createElement('tr')); + tr.addClass('jqplot-table-legend'); + + if (reverse){ + tr.prependTo(this._elem); + } + + else{ + tr.appendTo(this._elem); + } + + for (j=0; j<nc; j++) { + if (idx < pd.length){ + lt = this.labels[idx] || pd[idx][0].toString(); + color = colorGenerator.next(); + if (!reverse){ + if (i>0){ + pad = true; + } + else{ + pad = false; + } + } + else{ + if (i == nr -1){ + pad = false; + } + else{ + pad = true; + } + } + rs = (pad) ? this.rowSpacing : '0'; + + + + td1 = $(document.createElement('td')); + td1.addClass('jqplot-table-legend'); + td1.css({textAlign: 'center', paddingTop: rs}); + + div0 = $(document.createElement('div')); + div1 = $(document.createElement('div')); + div1.addClass('jqplot-table-legend-swatch'); + div1.css({backgroundColor: color, borderColor: color}); + td1.append(div0.append(div1)); + + td2 = $(document.createElement('td')); + td2.addClass('jqplot-table-legend'); + td2.css('paddingTop', rs); + + if (this.escapeHtml){ + td2.text(lt); + } + else { + td2.html(lt); + } + if (reverse) { + td2.prependTo(tr); + td1.prependTo(tr); + } + else { + td1.appendTo(tr); + td2.appendTo(tr); + } + pad = true; + } + idx++; + } + } + } + } + return this._elem; + }; + + $.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + plot.target.trigger('jqplotDataMouseOver', ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + plot.target.trigger('jqplotDataHighlight', ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + }; + + + // this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]); + + // setup default renderers for axes and legend so user doesn't have to + // called with scope of plot + function preInit(target, data, options) { + options = options || {}; + options.axesDefaults = options.axesDefaults || {}; + options.legend = options.legend || {}; + options.seriesDefaults = options.seriesDefaults || {}; + // only set these if there is a pie series + var setopts = false; + if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) { + setopts = true; + } + else if (options.series) { + for (var i=0; i < options.series.length; i++) { + if (options.series[i].renderer == $.jqplot.PieRenderer) { + setopts = true; + } + } + } + + if (setopts) { + options.axesDefaults.renderer = $.jqplot.PieAxisRenderer; + options.legend.renderer = $.jqplot.PieLegendRenderer; + options.legend.preDraw = true; + options.seriesDefaults.pointLabels = {show: false}; + } + } + + function postInit(target, data, options) { + for (var i=0; i<this.series.length; i++) { + if (this.series[i].renderer.constructor == $.jqplot.PieRenderer) { + // don't allow mouseover and mousedown at same time. + if (this.series[i].highlightMouseOver) { + this.series[i].highlightMouseDown = false; + } + } + } + this.target.bind('mouseout', {plot:this}, function (ev) { unhighlight(ev.data.plot); }); + } + + // called with scope of plot + function postParseOptions(options) { + for (var i=0; i<this.series.length; i++) { + this.series[i].seriesColors = this.seriesColors; + this.series[i].colorGenerator = this.colorGenerator; + } + } + + function highlight (plot, sidx, pidx) { + var s = plot.series[sidx]; + var canvas = plot.plugins.pieRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.pieRenderer.highlightedSeriesIndex = sidx; + s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColorGenerator.get(pidx), false); + } + + function unhighlight (plot) { + var canvas = plot.plugins.pieRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.pieRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + } + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.pieRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt = jQuery.Event('jqplotDataClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var idx = plot.plugins.pieRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.pieRenderer && this.plugins.pieRenderer.highlightCanvas) { + this.plugins.pieRenderer.highlightCanvas.resetCanvas(); + this.plugins.pieRenderer.highlightCanvas = null; + } + + this.plugins.pieRenderer = {highlightedSeriesIndex:null}; + this.plugins.pieRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + + // do we have any data labels? if so, put highlight canvas before those + var labels = $(this.targetId+' .jqplot-data-label'); + if (labels.length) { + $(labels[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this)); + } + // else put highlight canvas before event canvas. + else { + this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this)); + } + + var hctx = this.plugins.pieRenderer.highlightCanvas.setContext(); + } + + $.jqplot.preInitHooks.push(preInit); + + $.jqplot.PieTickRenderer = function() { + $.jqplot.AxisTickRenderer.call(this); + }; + + $.jqplot.PieTickRenderer.prototype = new $.jqplot.AxisTickRenderer(); + $.jqplot.PieTickRenderer.prototype.constructor = $.jqplot.PieTickRenderer; + +})(jQuery); + + \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.pieRenderer.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.pieRenderer.min.js new file mode 100644 index 0000000000..a324f808df --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.pieRenderer.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(e){e.jqplot.PieRenderer=function(){e.jqplot.LineRenderer.call(this)};e.jqplot.PieRenderer.prototype=new e.jqplot.LineRenderer();e.jqplot.PieRenderer.prototype.constructor=e.jqplot.PieRenderer;e.jqplot.PieRenderer.prototype.init=function(q,u){this.diameter=null;this.padding=20;this.sliceMargin=0;this.fill=true;this.shadowOffset=2;this.shadowAlpha=0.07;this.shadowDepth=5;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.dataLabels="percent";this.showDataLabels=false;this.dataLabelFormatString=null;this.dataLabelThreshold=3;this.dataLabelPositionFactor=0.52;this.dataLabelNudge=2;this.dataLabelCenterOn=true;this.startAngle=0;this.tickRenderer=e.jqplot.PieTickRenderer;this._drawData=true;this._type="pie";if(q.highlightMouseDown&&q.highlightMouseOver==null){q.highlightMouseOver=false}e.extend(true,this,q);if(this.sliceMargin<0){this.sliceMargin=0}this._diameter=null;this._radius=null;this._sliceAngles=[];this._highlightedPoint=null;if(this.highlightColors.length==0){for(var s=0;s<this.seriesColors.length;s++){var r=e.jqplot.getColorComponents(this.seriesColors[s]);var o=[r[0],r[1],r[2]];var t=o[0]+o[1]+o[2];for(var p=0;p<3;p++){o[p]=(t>570)?o[p]*0.8:o[p]+0.3*(255-o[p]);o[p]=parseInt(o[p],10)}this.highlightColors.push("rgb("+o[0]+","+o[1]+","+o[2]+")")}}this.highlightColorGenerator=new e.jqplot.ColorGenerator(this.highlightColors);u.postParseOptionsHooks.addOnce(m);u.postInitHooks.addOnce(g);u.eventListenerHooks.addOnce("jqplotMouseMove",b);u.eventListenerHooks.addOnce("jqplotMouseDown",a);u.eventListenerHooks.addOnce("jqplotMouseUp",l);u.eventListenerHooks.addOnce("jqplotClick",f);u.eventListenerHooks.addOnce("jqplotRightClick",n);u.postDrawHooks.addOnce(i)};e.jqplot.PieRenderer.prototype.setGridData=function(t){var p=[];var u=[];var o=this.startAngle/180*Math.PI;var s=0;this._drawData=false;for(var r=0;r<this.data.length;r++){if(this.data[r][1]!=0){this._drawData=true}p.push(this.data[r][1]);u.push([this.data[r][0]]);if(r>0){p[r]+=p[r-1]}s+=this.data[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r<p.length;r++){u[r][1]=p[r]*q;u[r][2]=this.data[r][1]/s}this.gridData=u};e.jqplot.PieRenderer.prototype.makeGridData=function(t,u){var p=[];var v=[];var s=0;var o=this.startAngle/180*Math.PI;this._drawData=false;for(var r=0;r<t.length;r++){if(this.data[r][1]!=0){this._drawData=true}p.push(t[r][1]);v.push([t[r][0]]);if(r>0){p[r]+=p[r-1]}s+=t[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r<p.length;r++){v[r][1]=p[r]*q;v[r][2]=t[r][1]/s}return v};function h(o){return Math.sin((o-(o-Math.PI)/8/Math.PI)/2)}function j(u,t,o,v,r){var w=0;var q=t-u;var s=Math.abs(q);var p=o;if(v==false){p+=r}if(p>0&&s>0.01&&s<6.282){w=parseFloat(p)/2/h(q)}return w}e.jqplot.PieRenderer.prototype.drawSlice=function(B,z,y,u,w){if(this._drawData){var p=this._radius;var A=this.fill;var x=this.lineWidth;var s=this.sliceMargin;if(this.fill==false){s+=this.lineWidth}B.save();B.translate(this._center[0],this._center[1]);var D=j(z,y,this.sliceMargin,this.fill,this.lineWidth);var o=D*Math.cos((z+y)/2);var C=D*Math.sin((z+y)/2);if((y-z)<=Math.PI){p-=D}else{p+=D}B.translate(o,C);if(w){for(var v=0,t=this.shadowDepth;v<t;v++){B.save();B.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI),this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));q(p)}for(var v=0,t=this.shadowDepth;v<t;v++){B.restore()}}else{q(p)}B.restore()}function q(r){if(y>6.282+this.startAngle){y=6.282+this.startAngle;if(z>y){z=6.281+this.startAngle}}if(z>=y){return}B.beginPath();B.fillStyle=u;B.strokeStyle=u;B.lineWidth=x;B.arc(0,0,r,z,y,false);B.lineTo(0,0);B.closePath();if(A){B.fill()}else{B.stroke()}}};e.jqplot.PieRenderer.prototype.draw=function(B,z,E,o){var W;var H=(E!=undefined)?E:{};var t=0;var s=0;var N=1;var L=new e.jqplot.ColorGenerator(this.seriesColors);if(E.legendInfo&&E.legendInfo.placement=="insideGrid"){var J=E.legendInfo;switch(J.location){case"nw":t=J.width+J.xoffset;break;case"w":t=J.width+J.xoffset;break;case"sw":t=J.width+J.xoffset;break;case"ne":t=J.width+J.xoffset;N=-1;break;case"e":t=J.width+J.xoffset;N=-1;break;case"se":t=J.width+J.xoffset;N=-1;break;case"n":s=J.height+J.yoffset;break;case"s":s=J.height+J.yoffset;N=-1;break;default:break}}var K=(H.shadow!=undefined)?H.shadow:this.shadow;var A=(H.fill!=undefined)?H.fill:this.fill;var C=B.canvas.width;var I=B.canvas.height;var Q=C-t-2*this.padding;var X=I-s-2*this.padding;var M=Math.min(Q,X);var Y=M;this._sliceAngles=[];var v=this.sliceMargin;if(this.fill==false){v+=this.lineWidth}var q;var G=0;var R,aa,Z,ab;var D=this.startAngle/180*Math.PI;for(var W=0,V=z.length;W<V;W++){aa=(W==0)?D:z[W-1][1]+D;Z=z[W][1]+D;this._sliceAngles.push([aa,Z]);q=j(aa,Z,this.sliceMargin,this.fill,this.lineWidth);if(Math.abs(Z-aa)>Math.PI){G=Math.max(q,G)}}if(this.diameter!=null&&this.diameter>0){this._diameter=this.diameter-2*G}else{this._diameter=Y-2*G}if(this._diameter<6){e.jqplot.log("Diameter of pie too small, not rendering.");return}var S=this._radius=this._diameter/2;this._center=[(C-N*t)/2+N*t+G*Math.cos(D),(I-N*s)/2+N*s+G*Math.sin(D)];if(this.shadow){for(var W=0,V=z.length;W<V;W++){ab="rgba(0,0,0,"+this.shadowAlpha+")";this.renderer.drawSlice.call(this,B,this._sliceAngles[W][0],this._sliceAngles[W][1],ab,true)}}for(var W=0;W<z.length;W++){this.renderer.drawSlice.call(this,B,this._sliceAngles[W][0],this._sliceAngles[W][1],L.next(),false);if(this.showDataLabels&&z[W][2]*100>=this.dataLabelThreshold){var F,U=(this._sliceAngles[W][0]+this._sliceAngles[W][1])/2,T;if(this.dataLabels=="label"){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,z[W][0])}else{if(this.dataLabels=="value"){F=this.dataLabelFormatString||"%d";T=e.jqplot.sprintf(F,this.data[W][1])}else{if(this.dataLabels=="percent"){F=this.dataLabelFormatString||"%d%%";T=e.jqplot.sprintf(F,z[W][2]*100)}else{if(this.dataLabels.constructor==Array){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,this.dataLabels[W])}}}}var p=(this._radius)*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var P=this._center[0]+Math.cos(U)*p+this.canvas._offsets.left;var O=this._center[1]+Math.sin(U)*p+this.canvas._offsets.top;var u=e('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">'+T+"</div>").insertBefore(o.eventCanvas._elem);if(this.dataLabelCenterOn){P-=u.width()/2;O-=u.height()/2}else{P-=u.width()*Math.sin(U/2);O-=u.height()/2}P=Math.round(P);O=Math.round(O);u.css({left:P,top:O})}}};e.jqplot.PieAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.PieAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.PieAxisRenderer.prototype.constructor=e.jqplot.PieAxisRenderer;e.jqplot.PieAxisRenderer.prototype.init=function(o){this.tickRenderer=e.jqplot.PieTickRenderer;e.extend(true,this,o);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.PieLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.PieLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.PieLegendRenderer.prototype.constructor=e.jqplot.PieLegendRenderer;e.jqplot.PieLegendRenderer.prototype.init=function(o){this.numberRows=null;this.numberColumns=null;e.extend(true,this,o)};e.jqplot.PieLegendRenderer.prototype.draw=function(){var r=this;if(this.show){var B=this._series;this._elem=e(document.createElement("table"));this._elem.addClass("jqplot-table-legend");var E={position:"absolute"};if(this.background){E.background=this.background}if(this.border){E.border=this.border}if(this.fontSize){E.fontSize=this.fontSize}if(this.fontFamily){E.fontFamily=this.fontFamily}if(this.textColor){E.textColor=this.textColor}if(this.marginTop!=null){E.marginTop=this.marginTop}if(this.marginBottom!=null){E.marginBottom=this.marginBottom}if(this.marginLeft!=null){E.marginLeft=this.marginLeft}if(this.marginRight!=null){E.marginRight=this.marginRight}this._elem.css(E);var I=false,A=false,o,y;var C=B[0];var p=new e.jqplot.ColorGenerator(C.seriesColors);if(C.show){var J=C.data;if(this.numberRows){o=this.numberRows;if(!this.numberColumns){y=Math.ceil(J.length/o)}else{y=this.numberColumns}}else{if(this.numberColumns){y=this.numberColumns;o=Math.ceil(J.length/this.numberColumns)}else{o=J.length;y=1}}var H,G;var q,w,v;var x,z,F;var D=0;var u,t;for(H=0;H<o;H++){q=e(document.createElement("tr"));q.addClass("jqplot-table-legend");if(A){q.prependTo(this._elem)}else{q.appendTo(this._elem)}for(G=0;G<y;G++){if(D<J.length){x=this.labels[D]||J[D][0].toString();F=p.next();if(!A){if(H>0){I=true}else{I=false}}else{if(H==o-1){I=false}else{I=true}}z=(I)?this.rowSpacing:"0";w=e(document.createElement("td"));w.addClass("jqplot-table-legend");w.css({textAlign:"center",paddingTop:z});u=e(document.createElement("div"));t=e(document.createElement("div"));t.addClass("jqplot-table-legend-swatch");t.css({backgroundColor:F,borderColor:F});w.append(u.append(t));v=e(document.createElement("td"));v.addClass("jqplot-table-legend");v.css("paddingTop",z);if(this.escapeHtml){v.text(x)}else{v.html(x)}if(A){v.prependTo(q);w.prependTo(q)}else{w.appendTo(q);v.appendTo(q)}I=true}D++}}}}return this._elem};e.jqplot.PieRenderer.prototype.handleMove=function(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];r.target.trigger("jqplotDataMouseOver",o);if(r.series[o[0]].highlightMouseOver&&!(o[0]==r.plugins.pieRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){r.target.trigger("jqplotDataHighlight",o);d(r,o[0],o[1])}}else{if(s==null){k(r)}}};function c(s,r,p){p=p||{};p.axesDefaults=p.axesDefaults||{};p.legend=p.legend||{};p.seriesDefaults=p.seriesDefaults||{};var o=false;if(p.seriesDefaults.renderer==e.jqplot.PieRenderer){o=true}else{if(p.series){for(var q=0;q<p.series.length;q++){if(p.series[q].renderer==e.jqplot.PieRenderer){o=true}}}}if(o){p.axesDefaults.renderer=e.jqplot.PieAxisRenderer;p.legend.renderer=e.jqplot.PieLegendRenderer;p.legend.preDraw=true;p.seriesDefaults.pointLabels={show:false}}}function g(r,q,o){for(var p=0;p<this.series.length;p++){if(this.series[p].renderer.constructor==e.jqplot.PieRenderer){if(this.series[p].highlightMouseOver){this.series[p].highlightMouseDown=false}}}this.target.bind("mouseout",{plot:this},function(s){k(s.data.plot)})}function m(o){for(var p=0;p<this.series.length;p++){this.series[p].seriesColors=this.seriesColors;this.series[p].colorGenerator=this.colorGenerator}}function d(t,r,q){var p=t.series[r];var o=t.plugins.pieRenderer.highlightCanvas;o._ctx.clearRect(0,0,o._ctx.canvas.width,o._ctx.canvas.height);p._highlightedPoint=q;t.plugins.pieRenderer.highlightedSeriesIndex=r;p.renderer.drawSlice.call(p,o._ctx,p._sliceAngles[q][0],p._sliceAngles[q][1],p.highlightColorGenerator.get(q),false)}function k(q){var o=q.plugins.pieRenderer.highlightCanvas;o._ctx.clearRect(0,0,o._ctx.canvas.width,o._ctx.canvas.height);for(var p=0;p<q.series.length;p++){q.series[p]._highlightedPoint=null}q.plugins.pieRenderer.highlightedSeriesIndex=null;q.target.trigger("jqplotDataUnhighlight")}function b(s,r,v,u,t){if(u){var q=[u.seriesIndex,u.pointIndex,u.data];var p=jQuery.Event("jqplotDataMouseOver");p.pageX=s.pageX;p.pageY=s.pageY;t.target.trigger(p,q);if(t.series[q[0]].highlightMouseOver&&!(q[0]==t.plugins.pieRenderer.highlightedSeriesIndex&&q[1]==t.series[q[0]]._highlightedPoint)){var o=jQuery.Event("jqplotDataHighlight");o.pageX=s.pageX;o.pageY=s.pageY;t.target.trigger(o,q);d(t,q[0],q[1])}}else{if(u==null){k(t)}}}function a(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];if(s.series[p[0]].highlightMouseDown&&!(p[0]==s.plugins.pieRenderer.highlightedSeriesIndex&&p[1]==s.series[p[0]]._highlightedPoint)){var o=jQuery.Event("jqplotDataHighlight");o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p);d(s,p[0],p[1])}}else{if(t==null){k(s)}}}function l(q,p,t,s,r){var o=r.plugins.pieRenderer.highlightedSeriesIndex;if(o!=null&&r.series[o].highlightMouseDown){k(r)}}function f(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];var o=jQuery.Event("jqplotDataClick");o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p)}}function n(s,r,v,u,t){if(u){var q=[u.seriesIndex,u.pointIndex,u.data];var o=t.plugins.pieRenderer.highlightedSeriesIndex;if(o!=null&&t.series[o].highlightMouseDown){k(t)}var p=jQuery.Event("jqplotDataRightClick");p.pageX=s.pageX;p.pageY=s.pageY;t.target.trigger(p,q)}}function i(){if(this.plugins.pieRenderer&&this.plugins.pieRenderer.highlightCanvas){this.plugins.pieRenderer.highlightCanvas.resetCanvas();this.plugins.pieRenderer.highlightCanvas=null}this.plugins.pieRenderer={highlightedSeriesIndex:null};this.plugins.pieRenderer.highlightCanvas=new e.jqplot.GenericCanvas();var p=e(this.targetId+" .jqplot-data-label");if(p.length){e(p[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-pieRenderer-highlight-canvas",this._plotDimensions,this))}else{this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-pieRenderer-highlight-canvas",this._plotDimensions,this))}var o=this.plugins.pieRenderer.highlightCanvas.setContext()}e.jqplot.preInitHooks.push(c);e.jqplot.PieTickRenderer=function(){e.jqplot.AxisTickRenderer.call(this)};e.jqplot.PieTickRenderer.prototype=new e.jqplot.AxisTickRenderer();e.jqplot.PieTickRenderer.prototype.constructor=e.jqplot.PieTickRenderer})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.pointLabels.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.pointLabels.js new file mode 100644 index 0000000000..1c93433f74 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.pointLabels.js @@ -0,0 +1,353 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + + /** + * Class: $.jqplot.PointLabels + * Plugin for putting labels at the data points. + * + * To use this plugin, include the js + * file in your source: + * + * > <script type="text/javascript" src="plugins/jqplot.pointLabels.js"></script> + * + * By default, the last value in the data ponit array in the data series is used + * for the label. For most series renderers, extra data can be added to the + * data point arrays and the last value will be used as the label. + * + * For instance, + * this series: + * + * > [[1,4], [3,5], [7,2]] + * + * Would, by default, use the y values in the labels. + * Extra data can be added to the series like so: + * + * > [[1,4,'mid'], [3 5,'hi'], [7,2,'low']] + * + * And now the point labels would be 'mid', 'low', and 'hi'. + * + * Options to the point labels and a custom labels array can be passed into the + * "pointLabels" option on the series option like so: + * + * > series:[{pointLabels:{ + * > labels:['mid', 'hi', 'low'], + * > location:'se', + * > ypadding: 12 + * > } + * > }] + * + * A custom labels array in the options takes precendence over any labels + * in the series data. If you have a custom labels array in the options, + * but still want to use values from the series array as labels, set the + * "labelsFromSeries" option to true. + * + * By default, html entities (<, >, etc.) are escaped in point labels. + * If you want to include actual html markup in the labels, + * set the "escapeHTML" option to false. + * + */ + $.jqplot.PointLabels = function(options) { + // Group: Properties + // + // prop: show + // show the labels or not. + this.show = $.jqplot.config.enablePlugins; + // prop: location + // compass location where to position the label around the point. + // 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw' + this.location = 'n'; + // prop: labelsFromSeries + // true to use labels within data point arrays. + this.labelsFromSeries = false; + // prop: seriesLabelIndex + // array index for location of labels within data point arrays. + // if null, will use the last element of the data point array. + this.seriesLabelIndex = null; + // prop: labels + // array of arrays of labels, one array for each series. + this.labels = []; + // actual labels that will get displayed. + // needed to preserve user specified labels in labels array. + this._labels = []; + // prop: stackedValue + // true to display value as stacked in a stacked plot. + // no effect if labels is specified. + this.stackedValue = false; + // prop: ypadding + // vertical padding in pixels between point and label + this.ypadding = 6; + // prop: xpadding + // horizontal padding in pixels between point and label + this.xpadding = 6; + // prop: escapeHTML + // true to escape html entities in the labels. + // If you want to include markup in the labels, set to false. + this.escapeHTML = true; + // prop: edgeTolerance + // Number of pixels that the label must be away from an axis + // boundary in order to be drawn. Negative values will allow overlap + // with the grid boundaries. + this.edgeTolerance = -5; + // prop: formatter + // A class of a formatter for the tick text. sprintf by default. + this.formatter = $.jqplot.DefaultTickFormatter; + // prop: formatString + // string passed to the formatter. + this.formatString = ''; + // prop: hideZeros + // true to not show a label for a value which is 0. + this.hideZeros = false; + this._elems = []; + + $.extend(true, this, options); + }; + + var locations = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']; + var locationIndicies = {'nw':0, 'n':1, 'ne':2, 'e':3, 'se':4, 's':5, 'sw':6, 'w':7}; + var oppositeLocations = ['se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e']; + + // called with scope of a series + $.jqplot.PointLabels.init = function (target, data, seriesDefaults, opts){ + var options = $.extend(true, {}, seriesDefaults, opts); + options.pointLabels = options.pointLabels || {}; + if (this.renderer.constructor == $.jqplot.BarRenderer && this.barDirection == 'horizontal' && !options.pointLabels.location) { + options.pointLabels.location = 'e'; + } + // add a pointLabels attribute to the series plugins + this.plugins.pointLabels = new $.jqplot.PointLabels(options.pointLabels); + this.plugins.pointLabels.setLabels.call(this); + }; + + // called with scope of series + $.jqplot.PointLabels.prototype.setLabels = function() { + var p = this.plugins.pointLabels; + var labelIdx; + if (p.seriesLabelIndex != null) { + labelIdx = p.seriesLabelIndex; + } + else if (this.renderer.constructor == $.jqplot.BarRenderer && this.barDirection == 'horizontal') { + labelIdx = 0; + } + else { + labelIdx = this._plotData[0].length -1; + } + p._labels = []; + if (p.labels.length == 0 || p.labelsFromSeries) { + if (p.stackedValue) { + if (this._plotData.length && this._plotData[0].length){ + // var idx = p.seriesLabelIndex || this._plotData[0].length -1; + for (var i=0; i<this._plotData.length; i++) { + p._labels.push(this._plotData[i][labelIdx]); + } + } + } + else { + var d = this._plotData; + if (this.renderer.constructor == $.jqplot.BarRenderer && this.waterfall) { + d = this._data; + } + if (d.length && d[0].length) { + // var idx = p.seriesLabelIndex || d[0].length -1; + for (var i=0; i<d.length; i++) { + p._labels.push(d[i][labelIdx]); + } + } + d = null; + } + } + else if (p.labels.length){ + p._labels = p.labels; + } + }; + + $.jqplot.PointLabels.prototype.xOffset = function(elem, location, padding) { + location = location || this.location; + padding = padding || this.xpadding; + var offset; + + switch (location) { + case 'nw': + offset = -elem.outerWidth(true) - this.xpadding; + break; + case 'n': + offset = -elem.outerWidth(true)/2; + break; + case 'ne': + offset = this.xpadding; + break; + case 'e': + offset = this.xpadding; + break; + case 'se': + offset = this.xpadding; + break; + case 's': + offset = -elem.outerWidth(true)/2; + break; + case 'sw': + offset = -elem.outerWidth(true) - this.xpadding; + break; + case 'w': + offset = -elem.outerWidth(true) - this.xpadding; + break; + default: // same as 'nw' + offset = -elem.outerWidth(true) - this.xpadding; + break; + } + return offset; + }; + + $.jqplot.PointLabels.prototype.yOffset = function(elem, location, padding) { + location = location || this.location; + padding = padding || this.xpadding; + var offset; + + switch (location) { + case 'nw': + offset = -elem.outerHeight(true) - this.ypadding; + break; + case 'n': + offset = -elem.outerHeight(true) - this.ypadding; + break; + case 'ne': + offset = -elem.outerHeight(true) - this.ypadding; + break; + case 'e': + offset = -elem.outerHeight(true)/2; + break; + case 'se': + offset = this.ypadding; + break; + case 's': + offset = this.ypadding; + break; + case 'sw': + offset = this.ypadding; + break; + case 'w': + offset = -elem.outerHeight(true)/2; + break; + default: // same as 'nw' + offset = -elem.outerHeight(true) - this.ypadding; + break; + } + return offset; + }; + + // called with scope of series + $.jqplot.PointLabels.draw = function (sctx, options) { + var p = this.plugins.pointLabels; + // set labels again in case they have changed. + p.setLabels.call(this); + // remove any previous labels + for (var i=0; i<p._elems.length; i++) { + // Memory Leaks patch + // p._elems[i].remove(); + p._elems[i].emptyForce(); + } + p._elems.splice(0, p._elems.length); + + if (p.show) { + var ax = '_'+this._stackAxis+'axis'; + + if (!p.formatString) { + p.formatString = this[ax]._ticks[0].formatString; + p.formatter = this[ax]._ticks[0].formatter; + } + + var pd = this._plotData; + var xax = this._xaxis; + var yax = this._yaxis; + var elem, helem; + + for (var i=0, l=p._labels.length; i < l; i++) { + var label = p._labels[i]; + + if (p.hideZeros && parseInt(p._labels[i], 10) == 0) { + label = ''; + } + + if (label != null) { + label = p.formatter(p.formatString, label); + } + + helem = document.createElement('div'); + p._elems[i] = $(helem); + + elem = p._elems[i]; + + + elem.addClass('jqplot-point-label jqplot-series-'+this.index+' jqplot-point-'+i); + elem.css('position', 'absolute'); + elem.insertAfter(sctx.canvas); + + if (p.escapeHTML) { + elem.text(label); + } + else { + elem.html(label); + } + var location = p.location; + if ((this.fillToZero && pd[i][1] < 0) || (this.waterfall && parseInt(label, 10)) < 0) { + location = oppositeLocations[locationIndicies[location]]; + } + var ell = xax.u2p(pd[i][0]) + p.xOffset(elem, location); + var elt = yax.u2p(pd[i][1]) + p.yOffset(elem, location); + if (this.renderer.constructor == $.jqplot.BarRenderer) { + if (this.barDirection == "vertical") { + ell += this._barNudge; + } + else { + elt -= this._barNudge; + } + } + elem.css('left', ell); + elem.css('top', elt); + var elr = ell + elem.width(); + var elb = elt + elem.height(); + var et = p.edgeTolerance; + var scl = $(sctx.canvas).position().left; + var sct = $(sctx.canvas).position().top; + var scr = sctx.canvas.width + scl; + var scb = sctx.canvas.height + sct; + // if label is outside of allowed area, remove it + if (ell - et < scl || elt - et < sct || elr + et > scr || elb + et > scb) { + elem.remove(); + } + elem = null; + helem = null; + } + } + }; + + $.jqplot.postSeriesInitHooks.push($.jqplot.PointLabels.init); + $.jqplot.postDrawSeriesHooks.push($.jqplot.PointLabels.draw); +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.pointLabels.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.pointLabels.min.js new file mode 100644 index 0000000000..86b3fd8c15 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.pointLabels.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(c){c.jqplot.PointLabels=function(e){this.show=c.jqplot.config.enablePlugins;this.location="n";this.labelsFromSeries=false;this.seriesLabelIndex=null;this.labels=[];this._labels=[];this.stackedValue=false;this.ypadding=6;this.xpadding=6;this.escapeHTML=true;this.edgeTolerance=-5;this.formatter=c.jqplot.DefaultTickFormatter;this.formatString="";this.hideZeros=false;this._elems=[];c.extend(true,this,e)};var a=["nw","n","ne","e","se","s","sw","w"];var d={nw:0,n:1,ne:2,e:3,se:4,s:5,sw:6,w:7};var b=["se","s","sw","w","nw","n","ne","e"];c.jqplot.PointLabels.init=function(i,h,f,g){var e=c.extend(true,{},f,g);e.pointLabels=e.pointLabels||{};if(this.renderer.constructor==c.jqplot.BarRenderer&&this.barDirection=="horizontal"&&!e.pointLabels.location){e.pointLabels.location="e"}this.plugins.pointLabels=new c.jqplot.PointLabels(e.pointLabels);this.plugins.pointLabels.setLabels.call(this)};c.jqplot.PointLabels.prototype.setLabels=function(){var f=this.plugins.pointLabels;var h;if(f.seriesLabelIndex!=null){h=f.seriesLabelIndex}else{if(this.renderer.constructor==c.jqplot.BarRenderer&&this.barDirection=="horizontal"){h=0}else{h=this._plotData[0].length-1}}f._labels=[];if(f.labels.length==0||f.labelsFromSeries){if(f.stackedValue){if(this._plotData.length&&this._plotData[0].length){for(var e=0;e<this._plotData.length;e++){f._labels.push(this._plotData[e][h])}}}else{var g=this._plotData;if(this.renderer.constructor==c.jqplot.BarRenderer&&this.waterfall){g=this._data}if(g.length&&g[0].length){for(var e=0;e<g.length;e++){f._labels.push(g[e][h])}}g=null}}else{if(f.labels.length){f._labels=f.labels}}};c.jqplot.PointLabels.prototype.xOffset=function(f,e,g){e=e||this.location;g=g||this.xpadding;var h;switch(e){case"nw":h=-f.outerWidth(true)-this.xpadding;break;case"n":h=-f.outerWidth(true)/2;break;case"ne":h=this.xpadding;break;case"e":h=this.xpadding;break;case"se":h=this.xpadding;break;case"s":h=-f.outerWidth(true)/2;break;case"sw":h=-f.outerWidth(true)-this.xpadding;break;case"w":h=-f.outerWidth(true)-this.xpadding;break;default:h=-f.outerWidth(true)-this.xpadding;break}return h};c.jqplot.PointLabels.prototype.yOffset=function(f,e,g){e=e||this.location;g=g||this.xpadding;var h;switch(e){case"nw":h=-f.outerHeight(true)-this.ypadding;break;case"n":h=-f.outerHeight(true)-this.ypadding;break;case"ne":h=-f.outerHeight(true)-this.ypadding;break;case"e":h=-f.outerHeight(true)/2;break;case"se":h=this.ypadding;break;case"s":h=this.ypadding;break;case"sw":h=this.ypadding;break;case"w":h=-f.outerHeight(true)/2;break;default:h=-f.outerHeight(true)-this.ypadding;break}return h};c.jqplot.PointLabels.draw=function(w,j){var t=this.plugins.pointLabels;t.setLabels.call(this);for(var v=0;v<t._elems.length;v++){t._elems[v].emptyForce()}t._elems.splice(0,t._elems.length);if(t.show){var r="_"+this._stackAxis+"axis";if(!t.formatString){t.formatString=this[r]._ticks[0].formatString;t.formatter=this[r]._ticks[0].formatter}var C=this._plotData;var z=this._xaxis;var q=this._yaxis;var y,f;for(var v=0,u=t._labels.length;v<u;v++){var o=t._labels[v];if(t.hideZeros&&parseInt(t._labels[v],10)==0){o=""}if(o!=null){o=t.formatter(t.formatString,o)}f=document.createElement("div");t._elems[v]=c(f);y=t._elems[v];y.addClass("jqplot-point-label jqplot-series-"+this.index+" jqplot-point-"+v);y.css("position","absolute");y.insertAfter(w.canvas);if(t.escapeHTML){y.text(o)}else{y.html(o)}var g=t.location;if((this.fillToZero&&C[v][1]<0)||(this.waterfall&&parseInt(o,10))<0){g=b[d[g]]}var n=z.u2p(C[v][0])+t.xOffset(y,g);var h=q.u2p(C[v][1])+t.yOffset(y,g);if(this.renderer.constructor==c.jqplot.BarRenderer){if(this.barDirection=="vertical"){n+=this._barNudge}else{h-=this._barNudge}}y.css("left",n);y.css("top",h);var k=n+y.width();var s=h+y.height();var B=t.edgeTolerance;var e=c(w.canvas).position().left;var x=c(w.canvas).position().top;var A=w.canvas.width+e;var m=w.canvas.height+x;if(n-B<e||h-B<x||k+B>A||s+B>m){y.remove()}y=null;f=null}}};c.jqplot.postSeriesInitHooks.push(c.jqplot.PointLabels.init);c.jqplot.postDrawSeriesHooks.push(c.jqplot.PointLabels.draw)})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.trendline.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.trendline.js new file mode 100644 index 0000000000..57c6ec5f85 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.trendline.js @@ -0,0 +1,220 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + + /** + * Class: $.jqplot.Trendline + * Plugin which will automatically compute and draw trendlines for plotted data. + */ + $.jqplot.Trendline = function() { + // Group: Properties + + // prop: show + // Wether or not to show the trend line. + this.show = $.jqplot.config.enablePlugins; + // prop: color + // CSS color spec for the trend line. + // By default this wil be the same color as the primary line. + this.color = '#666666'; + // prop: renderer + // Renderer to use to draw the trend line. + // The data series that is plotted may not be rendered as a line. + // Therefore, we use our own line renderer here to draw a trend line. + this.renderer = new $.jqplot.LineRenderer(); + // prop: rendererOptions + // Options to pass to the line renderer. + // By default, markers are not shown on trend lines. + this.rendererOptions = {marker:{show:false}}; + // prop: label + // Label for the trend line to use in the legend. + this.label = ''; + // prop: type + // Either 'exponential', 'exp', or 'linear'. + this.type = 'linear'; + // prop: shadow + // true or false, wether or not to show the shadow. + this.shadow = true; + // prop: markerRenderer + // Renderer to use to draw markers on the line. + // I think this is wrong. + this.markerRenderer = {show:false}; + // prop: lineWidth + // Width of the trend line. + this.lineWidth = 1.5; + // prop: shadowAngle + // Angle of the shadow on the trend line. + this.shadowAngle = 45; + // prop: shadowOffset + // pixel offset for each stroke of the shadow. + this.shadowOffset = 1.0; + // prop: shadowAlpha + // Alpha transparency of the shadow. + this.shadowAlpha = 0.07; + // prop: shadowDepth + // number of strokes to make of the shadow. + this.shadowDepth = 3; + this.isTrendline = true; + + }; + + $.jqplot.postSeriesInitHooks.push(parseTrendLineOptions); + $.jqplot.postDrawSeriesHooks.push(drawTrendline); + $.jqplot.addLegendRowHooks.push(addTrendlineLegend); + + // called witin scope of the legend object + // current series passed in + // must return null or an object {label:label, color:color} + function addTrendlineLegend(series) { + var lt = series.trendline.label.toString(); + var ret = null; + if (this.renderer.constructor != $.jqplot.PieRenderer && series.trendline.show && lt) { + ret = {label:lt, color:series.trendline.color}; + } + return ret; + } + + // called within scope of a series + function parseTrendLineOptions (target, data, seriesDefaults, options, plot) { + if (this.renderer.constructor == $.jqplot.LineRenderer) { + this.trendline = new $.jqplot.Trendline(); + options = options || {}; + $.extend(true, this.trendline, {color:this.color}, seriesDefaults.trendline, options.trendline); + this.trendline.renderer.init.call(this.trendline, null); + } + } + + // called within scope of series object + function drawTrendline(sctx, options) { + // if we have options, merge trendline options in with precedence + options = $.extend(true, {}, this.trendline, options); + + if (options.show && this.renderer.constructor != $.jqplot.PieRenderer) { + var fit; + // this.renderer.setGridData.call(this); + var data = options.data || this.data; + fit = fitData(data, this.trendline.type); + var gridData = options.gridData || this.renderer.makeGridData.call(this, fit.data); + this.trendline.renderer.draw.call(this.trendline, sctx, gridData, {showLine:true, shadow:this.trendline.shadow}); + } + } + + function regression(x, y, typ) { + var type = (typ == null) ? 'linear' : typ; + var N = x.length; + var slope; + var intercept; + var SX = 0; + var SY = 0; + var SXX = 0; + var SXY = 0; + var SYY = 0; + var Y = []; + var X = []; + + if (type == 'linear') { + X = x; + Y = y; + } + else if (type == 'exp' || type == 'exponential') { + for ( var i=0; i<y.length; i++) { + // ignore points <= 0, log undefined. + if (y[i] <= 0) { + N--; + } + else { + X.push(x[i]); + Y.push(Math.log(y[i])); + } + } + } + + for ( var i = 0; i < N; i++) { + SX = SX + X[i]; + SY = SY + Y[i]; + SXY = SXY + X[i]* Y[i]; + SXX = SXX + X[i]* X[i]; + SYY = SYY + Y[i]* Y[i]; + } + + slope = (N*SXY - SX*SY)/(N*SXX - SX*SX); + intercept = (SY - slope*SX)/N; + + return [slope, intercept]; + } + + function linearRegression(X,Y) { + var ret; + ret = regression(X,Y,'linear'); + return [ret[0],ret[1]]; + } + + function expRegression(X,Y) { + var ret; + var x = X; + var y = Y; + ret = regression(x, y,'exp'); + var base = Math.exp(ret[0]); + var coeff = Math.exp(ret[1]); + return [base, coeff]; + } + + function fitData(data, typ) { + var type = (typ == null) ? 'linear' : typ; + var ret; + var res; + var x = []; + var y = []; + var ypred = []; + + for (i=0; i<data.length; i++){ + if (data[i] != null && data[i][0] != null && data[i][1] != null) { + x.push(data[i][0]); + y.push(data[i][1]); + } + } + + if (type == 'linear') { + ret = linearRegression(x,y); + for ( var i=0; i<x.length; i++){ + res = ret[0]*x[i] + ret[1]; + ypred.push([x[i], res]); + } + } + else if (type == 'exp' || type == 'exponential') { + ret = expRegression(x,y); + for ( var i=0; i<x.length; i++){ + res = ret[1]*Math.pow(ret[0],x[i]); + ypred.push([x[i], res]); + } + } + return {data: ypred, slope: ret[0], intercept: ret[1]}; + } + +})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/plugins/jqplot.trendline.min.js b/phpgwapi/js/jquery/jqplot/plugins/jqplot.trendline.min.js new file mode 100644 index 0000000000..3cc53b3a16 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/plugins/jqplot.trendline.min.js @@ -0,0 +1,30 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.0b2_r792 + * + * Copyright (c) 2009-2011 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function(f){f.jqplot.Trendline=function(){this.show=f.jqplot.config.enablePlugins;this.color="#666666";this.renderer=new f.jqplot.LineRenderer();this.rendererOptions={marker:{show:false}};this.label="";this.type="linear";this.shadow=true;this.markerRenderer={show:false};this.lineWidth=1.5;this.shadowAngle=45;this.shadowOffset=1;this.shadowAlpha=0.07;this.shadowDepth=3;this.isTrendline=true};f.jqplot.postSeriesInitHooks.push(e);f.jqplot.postDrawSeriesHooks.push(g);f.jqplot.addLegendRowHooks.push(a);function a(k){var i=k.trendline.label.toString();var j=null;if(this.renderer.constructor!=f.jqplot.PieRenderer&&k.trendline.show&&i){j={label:i,color:k.trendline.color}}return j}function e(m,k,j,i,l){if(this.renderer.constructor==f.jqplot.LineRenderer){this.trendline=new f.jqplot.Trendline();i=i||{};f.extend(true,this.trendline,{color:this.color},j.trendline,i.trendline);this.trendline.renderer.init.call(this.trendline,null)}}function g(m,i){i=f.extend(true,{},this.trendline,i);if(i.show&&this.renderer.constructor!=f.jqplot.PieRenderer){var k;var l=i.data||this.data;k=c(l,this.trendline.type);var j=i.gridData||this.renderer.makeGridData.call(this,k.data);this.trendline.renderer.draw.call(this.trendline,m,j,{showLine:true,shadow:this.trendline.shadow})}}function b(w,v,n){var u=(n==null)?"linear":n;var s=w.length;var t;var z;var o=0;var m=0;var r=0;var q=0;var l=0;var j=[];var k=[];if(u=="linear"){k=w;j=v}else{if(u=="exp"||u=="exponential"){for(var p=0;p<v.length;p++){if(v[p]<=0){s--}else{k.push(w[p]);j.push(Math.log(v[p]))}}}}for(var p=0;p<s;p++){o=o+k[p];m=m+j[p];q=q+k[p]*j[p];r=r+k[p]*k[p];l=l+j[p]*j[p]}t=(s*q-o*m)/(s*r-o*o);z=(m-t*o)/s;return[t,z]}function h(k,j){var i;i=b(k,j,"linear");return[i[0],i[1]]}function d(o,m){var k;var i=o;var n=m;k=b(i,n,"exp");var l=Math.exp(k[0]);var j=Math.exp(k[1]);return[l,j]}function c(l,j){var p=(j==null)?"linear":j;var n;var o;var r=[];var q=[];var m=[];for(k=0;k<l.length;k++){if(l[k]!=null&&l[k][0]!=null&&l[k][1]!=null){r.push(l[k][0]);q.push(l[k][1])}}if(p=="linear"){n=h(r,q);for(var k=0;k<r.length;k++){o=n[0]*r[k]+n[1];m.push([r[k],o])}}else{if(p=="exp"||p=="exponential"){n=d(r,q);for(var k=0;k<r.length;k++){o=n[1]*Math.pow(n[0],r[k]);m.push([r[k],o])}}}return{data:m,slope:n[0],intercept:n[1]}}})(jQuery); \ No newline at end of file diff --git a/phpgwapi/js/jquery/jqplot/usage.txt b/phpgwapi/js/jquery/jqplot/usage.txt new file mode 100644 index 0000000000..de42d22f87 --- /dev/null +++ b/phpgwapi/js/jquery/jqplot/usage.txt @@ -0,0 +1,126 @@ +Title: jqPlot Usage + +Usage Documentation: + +Introduction: + +jqPlot is a jQuery plugin to generate pure client-side javascript charts in your web pages. + +The jqPlot home page is at <http://www.jqplot.com/>. + +The project page and downloads are at <http://www.bitbucket.org/cleonello/jqplot/>. + +Below are a few examples to demonstrate jqPlot usage. These plots are shown as static images. +Many more examples of dynamically rendered plots can be seen on the test and examples pages here: <../../tests/>. + +Include the Files: + +jqPlot requires jQuery (1.4+ required for certain features). jQuery 1.4.4 is included in the distribution. +To use jqPlot include jquery, the jqPlot jQuery plugin, jqPlot css file and optionally the excanvas +script for IE support in your web page. Note, excanvas is required only for IE versions below 9. IE 9 includes +native support for the canvas element and does not require excanvas: + +> <!--[if lt IE 9]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]--> +> <script language="javascript" type="text/javascript" src="jquery-1.4.4.min.js"></script> +> <script language="javascript" type="text/javascript" src="jquery.jqplot.min.js"></script> +> <link rel="stylesheet" type="text/css" href="jquery.jqplot.css" /> + +Add a plot container: + +Add a container (target) to your web page where you want your plot to show up. +Be sure to give your target a width and a height: + +> <div id="chartdiv" style="height:400px;width:300px; "></div> + +Create a plot: + +Then, create the actual plot by calling the +$.jqplot plugin with the id of your target and some data: + +> $.jqplot('chartdiv', [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]]); + +Which will produce a +chart like: + +(see images/basicline.png) + +Plot Options: + +You can customize the plot by passing options to the $.jqplot function. Options are described in +<jqPlot Options> in the jqPlotOptions.txt file. An example of options usage: + +> $.jqplot('chartdiv', [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]], +> { title:'Exponential Line', +> axes:{yaxis:{min:-10, max:240}}, +> series:[{color:'#5FAB78'}] +> }); + +Which will produce +a plot like: + +(see images/basicoptions.png) + +Using Plugins: + +You can use jqPlot plugins (that is, plugins to the jqPlot plugin) by including them in your html +after you include the jqPlot plugin. Here is how to include the log axis plugin: + +> <link rel="stylesheet" type="text/css" href="jquery.jqplot.css" /> +> <!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]--> +> <script language="javascript" type="text/javascript" src="jquery-1.4.4.min.js"></script> +> <script language="javascript" type="text/javascript" src="jquery.jqplot.min.js"></script> +> <script language="javascript" type="text/javascript" src="jqplot.logAxisRenderer.js"></script> + +Important note: For jqplot builds r529 and above (0.9.7r529 and higher), you must explicitly +enable plugins via either the { show: true } plugin option to the plot or by using +the $.jqplot.config.enablePlugins = true; config options set on the page before plot creation. +Only plugins that can be immediately active upon loading are affected. This includes +non-renderer plugins like cursor, dragable, highlighter, and trendline. + +Here is a the same $.jqplot call +but with a log y axis: + +> $.jqplot('chartdiv', [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]], +> { title:'Exponential Line', +> axes:{yaxis:{renderer: $.jqplot.LogAxisRenderer}}, +> series:[{color:'#5FAB78'}] +> }); + +Which produces +a plot like: + +(see images/basiclogaxis.png) + +You can further customize with options specific +to the log axis plugin: + +> $.jqplot('chartdiv', [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]], +> { title:'Exponential Line', +> axes:{yaxis:{renderer: $.jqplot.LogAxisRenderer, tickDistribution:'power'}}, +> series:[{color:'#5FAB78'}] +> }); + +Which makes a +plot like: + +(see images/basiclogoptions.png) + +For a full list of options, see <jqPlot Options> in the jqPlotOptions.txt file. + +You can add as many plugins as you wish. Order is generally not important. +Some plugins, like the highlighter plugin which highlights data points near the +mouse, don't need any extra options or setup to function. Highlighter does have +additional options which the user can set. + +Other plugins, the barRenderer for example, provide functionality the must be specified +in the chart options object. To render a series as a bar graph with the bar renderer, +you would first include the plugin after jqPlot: + +> <script language="javascript" type="text/javascript" src="plugins/jqplot.barRenderer.min.js"></script> + +Then you would create +a chart like: + +> $.jqplot('chartdiv', [[34.53, 56.32, 25.1, 18.6]], {series:[{renderer:$.jqplot.BarRenderer}]}); + +Here the default LineRenderer is replaced by a BarRenderer to generate a bar graph for the first (an only) series. \ No newline at end of file From 70e2684dd5fc26befac6bba35313457a2a05c0ad Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Wed, 10 Aug 2011 13:03:51 +0000 Subject: [PATCH 009/472] fixed catchable fatal error ($old hast to be array or null) and avoid reading old contact twice --- addressbook/inc/class.addressbook_bo.inc.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/addressbook/inc/class.addressbook_bo.inc.php b/addressbook/inc/class.addressbook_bo.inc.php index 95ed0468da..fa8ac40d8a 100755 --- a/addressbook/inc/class.addressbook_bo.inc.php +++ b/addressbook/inc/class.addressbook_bo.inc.php @@ -879,7 +879,10 @@ class addressbook_bo extends addressbook_so } // Get old record for tracking changes - $old = $this->data2db($this->read($contact['id'])); + if (!isset($old) && $isUpdate) + { + $old = $this->read($contact['id']); + } // IF THE OLD ENTRY IS A ACCOUNT, dont allow to change the owner/location // maybe we need that for id and account_id as well. if (is_array($old) && (!isset($old['owner']) || empty($old['owner']))) @@ -912,7 +915,7 @@ class addressbook_bo extends addressbook_so egw_link::notify_update('addressbook', $contact['id'], $contact); // Check for restore of deleted contact, restore held links - if($old['tid'] == addressbook_so::DELETED_TYPE && $contact['tid'] != addressbook_so::DELETED_TYPE) + if($old && $old['tid'] == addressbook_so::DELETED_TYPE && $contact['tid'] != addressbook_so::DELETED_TYPE) { egw_link::restore('addressbook', $contact['id']); } @@ -920,7 +923,7 @@ class addressbook_bo extends addressbook_so // Record change history for sql - doesn't work for LDAP accounts if(!$contact['account_id'] || $contact['account_id'] && $this->account_repository == 'sql') { $deleted = ($old['tid'] == addressbook_so::DELETED_TYPE || $contact['tid'] == addressbook_so::DELETED_TYPE); - $this->tracking->track($to_write, $old, null, $deleted); + $this->tracking->track($to_write, $old ? $old : null, null, $deleted); } } From 858279ad84b3b7981eed05911c6dd41b38c4585d Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Wed, 10 Aug 2011 14:24:30 +0000 Subject: [PATCH 010/472] * eSync/Addressbook: new preference to force sorting on device, eg. for use with Windows Mobile, which use "own sorting" set in addressbook otherwise --- .../inc/class.addressbook_activesync.inc.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/addressbook/inc/class.addressbook_activesync.inc.php b/addressbook/inc/class.addressbook_activesync.inc.php index 2c67e03dda..ae99da7520 100644 --- a/addressbook/inc/class.addressbook_activesync.inc.php +++ b/addressbook/inc/class.addressbook_activesync.inc.php @@ -381,6 +381,13 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug $message->$key = ('"'.$emailname.'"'." <$contact[$attr]>"); } break; + case 'n_fileas': + if ($GLOBALS['egw_info']['user']['preferences']['activesync']['addressbook-force-fileas']) + { + $message->$key = $this->addressbook->fileas($contact,$GLOBALS['egw_info']['user']['preferences']['activesync']['addressbook-force-fileas']); + break; + } + // fall through default: if (!empty($contact[$attr])) $message->$key = $contact[$attr]; } @@ -533,6 +540,12 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug $contact[$attr] = $message->$key; } break; + case 'n_fileas': // only change fileas, if not forced on the client + if (!$GLOBALS['egw_info']['user']['preferences']['activesync']['addressbook-force-fileas']) + { + $contact[$attr] = $message->$key; + } + break; case 'title': // as ol jobtitle mapping changed in egw from role to title, do NOT overwrite title with value of role if ($id && $message->$key == $contact['role']) break; // fall throught @@ -740,6 +753,8 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug $addressbooks = $addressbook_bo->get_addressbooks(EGW_ACL_READ); unset($addressbooks[$user]); // personal addressbook is allways synced unset($addressbooks[$user.'p']);// private addressbook uses ID self::PRIVATE_AB + + $fileas_options = array('0' => lang('use addressbooks "own sorting" attribute'))+$addressbook_bo->fileas_options(); } if ($GLOBALS['egw_info']['user']['preferences']['addressbook']['private_addressbook']) { @@ -785,6 +800,17 @@ class addressbook_activesync implements activesync_plugin_write, activesync_plug 'admin' => false, 'default' => '0', ); + + $settings['addressbook-force-fileas'] = array( + 'type' => 'select', + 'label' => 'Force sorting on device to', + 'name' => 'addressbook-force-fileas', + 'help' => 'Some devices (eg. Windows Mobil, but not iOS) sort by addressbooks "own sorting" attribute, which might not be what you want on the device. With this setting you can force the device to use a different sorting for all contacts, without changing it in addressbook.', + 'values' => $fileas_options, + 'xmlrpc' => true, + 'admin' => false, + 'default' => '0', + ); return $settings; } } From 68c7a5550eb324add4ae6efa26d1325a81cf1a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Wed, 10 Aug 2011 14:36:31 +0000 Subject: [PATCH 011/472] - Styled button a little bit - Added test for textbox - Added baseWidget and inputWidget classes - Implemented attribute system - Implemented statustext as a test for the attribute system - Ported csv_split function to JS - Implemented system for the legacy options - Added function for iterating over the widget tree --- etemplate/js/et2_baseWidget.js | 118 +++++++ etemplate/js/et2_box.js | 37 ++ etemplate/js/et2_button.js | 23 +- etemplate/js/et2_common.js | 319 ++++++++++++++++-- etemplate/js/et2_description.js | 80 ++++- etemplate/js/et2_grid.js | 22 +- etemplate/js/et2_inheritance.js | 142 +++++++- etemplate/js/et2_inputWidget.js | 94 ++++++ etemplate/js/et2_tabs.js | 178 ++++++++++ etemplate/js/et2_template.js | 18 + etemplate/js/et2_textbox.js | 59 +++- etemplate/js/et2_widget.js | 255 +++++++++----- etemplate/js/et2_xml.js | 8 + etemplate/js/lib/tooltip.js | 180 ++++++++++ etemplate/js/test/et2_test_description.xet | 8 + etemplate/js/test/et2_test_grid.xet | 9 +- etemplate/js/test/et2_test_tabbox.xet | 18 + etemplate/js/test/et2_test_textbox.xet | 13 + etemplate/js/test/et2_test_timesheet_edit.xet | 2 +- etemplate/js/test/gfx/gradient01.png | Bin 0 -> 249 bytes etemplate/js/test/gfx/gradient01.svg | 85 +++++ etemplate/js/test/gfx/gradient02.png | Bin 0 -> 246 bytes etemplate/js/test/gfx/gradient02.svg | 90 +++++ etemplate/js/test/test_xml.html | 86 +++++ 24 files changed, 1685 insertions(+), 159 deletions(-) create mode 100644 etemplate/js/et2_baseWidget.js create mode 100644 etemplate/js/et2_box.js create mode 100644 etemplate/js/et2_inputWidget.js create mode 100644 etemplate/js/et2_tabs.js create mode 100644 etemplate/js/lib/tooltip.js create mode 100644 etemplate/js/test/et2_test_description.xet create mode 100644 etemplate/js/test/et2_test_tabbox.xet create mode 100644 etemplate/js/test/et2_test_textbox.xet create mode 100644 etemplate/js/test/gfx/gradient01.png create mode 100644 etemplate/js/test/gfx/gradient01.svg create mode 100644 etemplate/js/test/gfx/gradient02.png create mode 100644 etemplate/js/test/gfx/gradient02.svg diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js new file mode 100644 index 0000000000..21f0769864 --- /dev/null +++ b/etemplate/js/et2_baseWidget.js @@ -0,0 +1,118 @@ +/** + * eGroupWare eTemplate2 - JS Widget base class + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id: et2_widget.js 36021 2011-08-07 13:43:46Z igel457 $ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + lib/tooltip.js; + et2_widget; +*/ + +/** + * Class which manages the DOM node itself. The simpleWidget class is derrived + * from et2_DOMWidget and implements the getDOMNode function. A setDOMNode + * function is provided, which attatches the given node to the DOM if possible. + */ +var et2_baseWidget = et2_DOMWidget.extend({ + + attributes: { + "statustext": { + "name": "Tooltip", + "type": "string", + "description": "Tooltip which is shown for this element" + } + }, + + init: function() { + this._super.apply(this, arguments); + + this.node = null; + this.statustext = ""; + + this._tooltipElem = null; + }, + + detatchFromDOM: function() { + // Detach this node from the tooltip node + if (this._tooltipElem) + { + egw_global_tooltip.unbindFromElement(this._tooltipElem); + this._tooltipElem = null; + } + + this._super.apply(this, arguments); + }, + + attachToDOM: function() { + this._super.apply(this,arguments); + + // Update the statustext + this.set_statustext(this.statustext); + }, + + setDOMNode: function(_node) { + if (_node != this.node) + { + // Deatch the old node from the DOM + this.detatchFromDOM(); + + // Set the new DOM-Node + this.node = _node; + + // Attatch the DOM-Node to the tree + return this.attachToDOM(); + } + + return false; + }, + + getDOMNode: function() { + return this.node; + }, + + getTooltipElement: function() { + return this.getDOMNode(); + }, + + set_statustext: function(_value) { + // Don't execute the code below, if no tooltip will be attached/detached + if (_value == "" && !this._tooltipElem) + { + return; + } + + this.statustext = _value; + + //Get the domnode the tooltip should be attached to + var elem = $j(this.getTooltipElement()); + + if (elem) + { + //If a tooltip is already attached to the element, remove it first + if (this._tooltipElem) + { + egw_global_tooltip.unbindFromElement(this._tooltipElem); + this._tooltipElem = null; + } + + if (_value && _value != '') + { + egw_global_tooltip.bindToElement(elem, _value); + this._tooltipElem = elem; + } + } + } + +}); + + diff --git a/etemplate/js/et2_box.js b/etemplate/js/et2_box.js new file mode 100644 index 0000000000..289e490a2e --- /dev/null +++ b/etemplate/js/et2_box.js @@ -0,0 +1,37 @@ +/** + * eGroupWare eTemplate2 - JS Box object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + et2_baseWidget; +*/ + +/** + * Class which implements the hbox and vbox tag + */ +var et2_box = et2_baseWidget.extend({ + + init: function(_parent, _type) { + this._super.apply(this, arguments); + + this.div = $j(document.createElement("div")) + .addClass("et2_" + _type); + + this.setDOMNode(this.div[0]); + } + +}); + +et2_register_widget(et2_box, ["hbox", "vbox"]); + diff --git a/etemplate/js/et2_button.js b/etemplate/js/et2_button.js index 27d534fac3..92310ae216 100644 --- a/etemplate/js/et2_button.js +++ b/etemplate/js/et2_button.js @@ -14,20 +14,31 @@ /*egw:uses jquery.jquery; - et2_widget; + et2_baseWidget; */ /** * Class which implements the "button" XET-Tag */ -var et2_button = et2_DOMWidget.extend({ +var et2_button = et2_baseWidget.extend({ + + attributes: { + "label": { + "name": "caption", + "type": "string", + "description": "Label of the button" + } + }, init: function(_parent) { + this._super.apply(this, arguments); + + this.label = ""; + this.btn = $j(document.createElement("button")) .addClass("et2_button"); - this._super.apply(this, arguments); - this.label = ""; + this.setDOMNode(this.btn[0]); }, set_label: function(_value) { @@ -37,10 +48,6 @@ var et2_button = et2_DOMWidget.extend({ this.btn.text(_value); } - }, - - getDOMNode: function() { - return this.btn[0]; } }); diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index 0152b47aae..51a19119c2 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -10,27 +10,6 @@ * @version $Id$ */ -function et2_debug(_level, _msg) -{ - if (typeof console != "undefined") - { - if (_level == "log" && typeof console.log == "function") - { - console.log(_msg); - } - - if (_level == "warn" && typeof console.warn == "function") - { - console.warn(_msg); - } - - if (_level == "error" && typeof console.error == "function") - { - console.error(_msg); - } - } -} - /** * IE Fix for array.indexOf */ @@ -46,4 +25,302 @@ if (typeof Array.prototype.indexOf == "undefined") }; } +/** + * ET2_DEBUGLEVEL specifies which messages are printed to the console. Decrease + * the value of ET2_DEBUGLEVEL to get less messages. + */ +var ET2_DEBUGLEVEL = 0; + +function et2_debug(_level, _msg) +{ + if (typeof console != "undefined") + { + if (_level == "log" && ET2_DEBUGLEVEL >= 4 && + typeof console.log == "function") + { + console.log(_msg); + } + + if (_level == "info" && ET2_DEBUGLEVEL >= 3 && + typeof console.info == "function") + { + console.info(_msg); + } + + if (_level == "warn" && ET2_DEBUGLEVEL >= 2 && + typeof console.warn == "function") + { + console.warn(_msg); + } + + if (_level == "error" && ET2_DEBUGLEVEL >= 1 && + typeof console.error == "function") + { + console.error(_msg); + } + } +} + +/** + * Array with all types supported by the et2_checkType function. + */ +var et2_validTypes = ["boolean", "string", "float", "integer", "any"]; + +/** + * Object whith default values for the above types. Do not specify array or + * objects inside the et2_typeDefaults object, as this instance will be shared + * between all users of it. + */ +var et2_typeDefaults = { + "boolean": false, + "string": "", + "float": 0.0, + "integer": 0, + "any": null +}; + +/** + * Checks whether the given value is of the given type. Strings are converted + * into the corresponding type. The (converted) value is returned. All supported + * types are listed in the et2_validTypes array. + */ +function et2_checkType(_val, _type) +{ + function _err() { + throw("'" + _val + "' is not of specified _type '" + _type + "'"); + } + + // If the type is "any" simply return the value again + if (_type == "any") + { + return _val; + } + + // If the type is boolean, check whether the given value is exactly true or + // false. Otherwise check whether the value is the string "true" or "false". + if (_type == "boolean") + { + if (_val === true || _val === false) + { + return _val; + } + + var lcv = _val.toLowerCase(); + if (lcv === "true" || lcv === "false" || lcv === "") + { + return _val === "true"; + } + + _err(); + } + + // Check whether the given value is of the type "string" + if (_type == "string") + { + if (typeof _val == "string") + { + return _val; + } + + _err(); + } + + // Check whether the value is already a number, otherwise try to convert it + // to one. + if (_type == "float") + { + if (typeof _val == "number") + { + return _val; + } + + if (!isNaN(_val)) + { + return parseFloat(_val); + } + + _err(); + } + + // Check whether the value is an integer by comparing the result of + // parseInt(_val) to the value itself. + if (_type == "integer") + { + if (parseInt(_val) == _val) + { + return parseInt(_val); + } + + _err(); + } + + // We should never come here + throw("Invalid type identifier supplied."); +} + +/** + * Validates the given attribute with the given id. The validation checks for + * the existance of a human name, a description, a type and a default value. + * If the human name defaults to the given id, the description defaults to an + * empty string, the type defaults to any and the default to the corresponding + * type default. + */ +function et2_validateAttrib(_id, _attrib) +{ + // Default ignore to false. + if (typeof _attrib["ignore"] == "undefined") + { + _attrib["ignore"] = false + } + + // Break if "ignore" is set to true. + if (_attrib.ignore) + { + return; + } + + if (typeof _attrib["name"] == "undefined") + { + _attrib["name"] = _id; + et2_debug("log", "Human name ('name'-Field) for attribute '" + + _id + "' has not been supplied, set to '" + _id + "'"); + } + + if (typeof _attrib["description"] == "undefined") + { + _attrib["description"] = ""; + et2_debug("log", "Description for attribute '" + + _id + "' has not been supplied"); + } + + if (typeof _attrib["type"] == "undefined") + { + _attrib["type"] = "any"; + } + else + { + if (et2_validTypes.indexOf(_attrib["type"]) < 0) + { + et2_debug("error", "Invalid type for attribute '" + _id + + "' supplied."); + } + } + + // Set the defaults + if (typeof _attrib["default"] == "undefined") + { + _attrib["default"] = et2_typeDefaults[_attrib["type"]]; + } +} + +/** + * Equivalent to the PHP array_values function + */ +function et2_arrayValues(_arr) +{ + var result = []; + for (var key in _arr) + { + if (parseInt(key) == key) + { + result.push(_arr[key]); + } + } + + return result; +} + +/** + * Equivalent to the PHP substr function, partly take from phpjs, licensed under + * the GPL. + */ +function et2_substr (str, start, len) { + var end = str.length; + + if (start < 0) + { + start += end; + } + end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start); + + return start >= str.length || start < 0 || start > end ? "" : str.slice(start, end); +} + +/** + * Split a $delimiter-separated options string, which can contain parts with + * delimiters enclosed in $enclosure. Ported from class.boetemplate.inc.php + * + * Examples: + * - et2_csvSplit('"1,2,3",2,3') === array('1,2,3','2','3') + * - et2_csvSplit('1,2,3',2) === array('1','2,3') + * - et2_csvSplit('"1,2,3",2,3',2) === array('1,2,3','2,3') + * - et2_csvSplit('"a""b,c",d') === array('a"b,c','d') // to escape enclosures double them! + * + * @param string _str + * @param int _num=null in how many parts to split maximal, parts over this + * number end up (unseparated) in the last part + * @param string _delimiter=',' + * @param string _enclosure='"' + * @return array + */ +function et2_csvSplit(_str, _num, _delimiter, _enclosure) +{ + // Default the parameters + if (typeof _num == "undefined") + { + _num == null; + } + + if (typeof _delimiter == "undefined") + { + _delimiter = ","; + } + + if (typeof _enclosure == "undefined") + { + _enclosure = '"'; + } + + // If the _enclosure string does not occur in the string, simply use the + // split function + if (_str.indexOf(_enclosure) == -1) + { + return _num === null ? _str.split(_delimiter) : + _str.split(_delimiter, _num); + } + + // Split the string at the delimiter and join it again, when a enclosure is + // found at the beginning/end of a part + var parts = _str.split(_delimiter); + for (var n = 0; typeof parts[n] != "undefined"; n++) + { + var part = parts[n]; + + if (part.charAt(0) === _enclosure) + { + var m = n; + while (typeof parts[m + 1] != "undefined" && parts[n].substr(-1) !== _enclosure) + { + parts[n] += _delimiter + parts[++m]; + delete(parts[m]); + } + parts[n] = et2_substr(parts[n].replace( + new RegExp(_enclosure + _enclosure, 'g'), _enclosure), 1 , -1); + n = m; + } + } + + // Rebuild the array index + parts = et2_arrayValues(parts); + + // Limit the parts to the given number + if (_num !== null && _num > 0 && _num < parts.length && parts.length > 0) + { + parts[_num - 1] = parts.slice(_num - 1, parts.length).join(_delimiter); + parts = parts.slice(0, _num); + } + + return parts; +} + diff --git a/etemplate/js/et2_description.js b/etemplate/js/et2_description.js index 1ff3dd7bb1..883175afab 100644 --- a/etemplate/js/et2_description.js +++ b/etemplate/js/et2_description.js @@ -14,24 +14,82 @@ /*egw:uses jquery.jquery; - et2_widget; + et2_baseWidget; */ /** * Class which implements the "description" XET-Tag */ -var et2_description = et2_DOMWidget.extend({ +var et2_description = et2_baseWidget.extend({ + + attributes: { + "value": { + "name": "Caption", + "type": "string", + "description": "Displayed text" + }, + + /** + * Options converted from the "options"-attribute. + */ + "font_style": { + "name": "Font Style", + "type": "string", + "description": "Style may be a compositum of \"b\" and \"i\" which " + + " renders the text bold and/or italic." + }, + "href": { + "name": "Link Target", + "type": "string", + "description": "Link URL, empty if you don't wan't to display a link." + }, + "activate_links": { + "name": "Replace URLs", + "type": "boolean", + "default": false, + "description": "If set, URLs in the text are automatically replaced " + + "by links" + }, + "label_for": { + "name": "Label for widget", + "type": "string", + "description": "Marks the text as label for the given widget." + }, + "extra_link_target": { + "name": "Link target", + "type": "string", + "default": "_self", + "description": "Link target descriptor" + }, + "extra_link_popup": { + "name": "Popup", + "type": "string", + "description": "???" + }, + "extra_link_title": { + "name": "Link Title", + "type": "string", + "description": "Link title which is displayed on mouse over." + } + }, + + legacyOptions: ["font_style", "href", "activate_links", "label_for", + "extra_link_target", "extra_link_popup", "extra_link_title"], init: function(_parent) { + this._super.apply(this, arguments); + + this.value = ""; + this.font_style = ""; + this.span = $j(document.createElement("span")) .addClass("et2_label"); - this._super.apply(this, arguments); - this.value = ""; + this.setDOMNode(this.span[0]); }, - set_value: function(_value) { - if (_value != this.value) + set_value: function(_value, _force) { + if (_value != this.value || _force) { this.value = _value; @@ -39,8 +97,14 @@ var et2_description = et2_DOMWidget.extend({ } }, - getDOMNode: function() { - return this.span[0]; + set_font_style: function(_value) { + if (_value != this.font_style) + { + this.font_style = _value; + + this.span.toggleClass("et2_bold", _value.indexOf("b") >= 0); + this.span.toggleClass("et2_italic", _value.indexOf("i") >= 0); + } } }); diff --git a/etemplate/js/et2_grid.js b/etemplate/js/et2_grid.js index 1521d1df93..b129126fe4 100644 --- a/etemplate/js/et2_grid.js +++ b/etemplate/js/et2_grid.js @@ -98,12 +98,6 @@ var et2_grid = et2_DOMWidget.extend({ }; }, - _readAttrWithDefault: function(_node, _name, _default) { - var val = _node.getAttribute(_name); - - return (val === null) ? _default : val; - }, - _getCell: function(_cells, _x, _y) { if ((0 <= _y) && (_y < _cells.length)) { @@ -132,10 +126,10 @@ var et2_grid = et2_DOMWidget.extend({ var colDataEntry = this._getColDataEntry(); if (nodeName == "column") { - colDataEntry["width"] = this._readAttrWithDefault(node, "width", "auto"); - colDataEntry["class"] = this._readAttrWithDefault(node, "class", ""); - colDataEntry["align"] = this._readAttrWithDefault(node, "align", ""); - colDataEntry["span"] = this._readAttrWithDefault(node, "span", "1"); + colDataEntry["width"] = et2_readAttrWithDefault(node, "width", "auto"); + colDataEntry["class"] = et2_readAttrWithDefault(node, "class", ""); + colDataEntry["align"] = et2_readAttrWithDefault(node, "align", ""); + colDataEntry["span"] = et2_readAttrWithDefault(node, "span", "1"); } else { @@ -149,10 +143,10 @@ var et2_grid = et2_DOMWidget.extend({ var rowDataEntry = this._getRowDataEntry(); if (nodeName == "row") { - rowDataEntry["height"] = this._readAttrWithDefault(node, "height", "auto"); - rowDataEntry["class"] = this._readAttrWithDefault(node, "class", ""); - rowDataEntry["valign"] = this._readAttrWithDefault(node, "valign", ""); - rowDataEntry["span"] = this._readAttrWithDefault(node, "span", "1"); + rowDataEntry["height"] = et2_readAttrWithDefault(node, "height", "auto"); + rowDataEntry["class"] = et2_readAttrWithDefault(node, "class", ""); + rowDataEntry["valign"] = et2_readAttrWithDefault(node, "valign", ""); + rowDataEntry["span"] = et2_readAttrWithDefault(node, "span", "1"); } else { diff --git a/etemplate/js/et2_inheritance.js b/etemplate/js/et2_inheritance.js index 377c7c0fbb..9233805d4a 100644 --- a/etemplate/js/et2_inheritance.js +++ b/etemplate/js/et2_inheritance.js @@ -12,6 +12,10 @@ "use strict"; +/*egw:uses + et2_common; +*/ + /** * Usage of the JS inheritance system * ---------------------------------- @@ -84,10 +88,10 @@ }; /** - * The addInterfaceStuff function adds all interface functions the class has + * The addInterfaceFunctions function adds all interface functions the class has * to implement to the class prototype. */ - function addInterfaceStuff(prototype, interfaces) + function addInterfaceFunctions(prototype, interfaces) { // Remember all interface functions in the prototype var ifaces = ((typeof prototype["_ifacefuncs"] == "undefined") ? [] : @@ -107,7 +111,7 @@ } else { - throw("Interfaces must be instanceof Interface!"); + throw("Interfaces must be instance of Interface!"); } } @@ -144,6 +148,118 @@ } }; + function addAttributeFunctions(prototype, _super) + { + var attributes = prototype.attributes; + + // Add the old attributes to the new ones. If the attributes already + // exist, they are merged. + for (var key in _super.attributes) + { + var attrib = _super.attributes[key]; + + if (typeof attributes[key] == "undefined") + { + // In the case that the old attribute has no equivalent in the + // new class, simply create a reference to the old one. + attributes[key] = attrib; + } + else + { + // Otherwise merge the two attribute descriptors. + for (var key2 in attrib) + { + if (typeof attributes[key][key2] == "undefined") + { + attributes[key][key2] = attrib[key2]; + } + } + } + } + + // Validate the attributes + for (var key in attributes) + { + et2_validateAttrib(key, attributes[key]); + } + + /** + * The initAttributes function sets the attributes to their default + * values. The attributes are not overwritten, which means, that the + * default is only set, if either a setter exists or this[propName] does + * not exist yet. + */ + prototype.initAttributes = function() { + for (var key in this.attributes) + { + if (!this.attributes[key].ignore) + { + this.setAttribute(key, this.attributes[key]["default"], + false); + } + } + + this._attrsInitialized = true; + } + + /** + * The setAttribute function sets the attribute with the given name to + * the given value. _override defines, whether this[_name] will be set, + * if this key already exists. _override defaults to true. A warning + * is issued if the attribute does not exist. + */ + prototype.setAttribute = function(_name, _value, _override) { + if (typeof this.attributes[_name] != "undefined") + { + if (!this.attributes[_name].ignore) + { + if (typeof _override == "undefined") + { + _override = true; + } + + var val = et2_checkType(_value, this.attributes[_name].type); + + if (typeof this["set_" + _name] == "function") + { + this["set_" + _name](val); + } + else if (_override || typeof this[_name] == "undefined") + { + this[_name] = val; + } + } + } + else + { + et2_debug("warn", "Attribute '" + _name + "' does not exist!"); + } + } + + /** + * Returns the value of the given attribute. If the property does not + * exist, an error message is issued. + */ + prototype.getAttribute = function(_name) { + if (typeof this.attributes[_name] != "undefined" && + !this.attributes[_name].ignore) + { + if (typeof this["get_" + _name] == "function") + { + return this["get_" + _name](); + } + else + { + return this[_name]; + } + } + else + { + et2_error("error", "Attribute '" + _name + "' does not exist!"); + } + } + }; + function classExtend(interfaces, prop) { if (typeof prop == "undefined") @@ -158,6 +274,11 @@ interfaces = [interfaces]; } + if (typeof prop.attributes == "undefined") + { + prop.attributes = {}; + } + var _super = this.prototype; // Instantiate a base class (but only create the instance, @@ -199,7 +320,11 @@ // Add the interface functions and the "implements" function to the // prototype - addInterfaceStuff(prototype, interfaces); + addInterfaceFunctions(prototype, interfaces); + + // Merge the attributes and create the functions corresponding to the + // attributes + addAttributeFunctions(prototype, _super); // The dummy class constructor function Class() { @@ -221,6 +346,12 @@ { this.init.apply(this, arguments); } + + // Initialize the attributes + if (typeof this._attrsInitialized == "undefined") + { + this.initAttributes(); + } } } @@ -243,5 +374,8 @@ // is an array which defines a set of interfaces the object has to // implement. An interface is simply an object with named functions. Class.extend = classExtend; + + // The base class has no attributes + Class.attributes = {}; }).call(window); diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js new file mode 100644 index 0000000000..7c37e69039 --- /dev/null +++ b/etemplate/js/et2_inputWidget.js @@ -0,0 +1,94 @@ +/** + * eGroupWare eTemplate2 - JS Widget base class + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id: et2_widget.js 36021 2011-08-07 13:43:46Z igel457 $ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + et2_baseWidget; +*/ + +/** + * Interface for all widgets which support returning a value + */ +var et2_IInput = new Interface({ + /** + * getValue has to return the value of the input widget + */ + getValue: function() {}, + + /** + * Is dirty returns true if the value of the widget has changed since it + * was loaded. + */ + isDirty: function() {}, + + /** + * Causes the dirty flag to be reseted. + */ + resetDirty: function() {} +}); + +/** + * et2_inputWidget derrives from et2_simpleWidget and implements the IInput + * interface. When derriving from this class, call setDOMNode with an input + * DOMNode. + */ +var et2_inputWidget = et2_simpleWidget.extend(et2_IInput, { + + attributes: { + "value": { + "name": "Value", + "description": "The value of the widget", + "type": "string", + "default": "" + } + }, + + init: function() { + this._super.apply(this, arguments); + + this._oldValue = ""; + }, + + set_value: function(_value) { + this._oldValue = _value; + + if (this.node) + { + $j(this.node).val(_value); + } + }, + + get_value: function() { + return this.getValue(); + }, + + getValue: function() { + if (this.node) + { + return $j(this.node).val(); + } + + return this._oldValue; + }, + + isDirty: function() { + return this._oldValue != this.getValue(); + }, + + resetDirty: function() { + this._oldValue = this.getValue(); + } + +}); + diff --git a/etemplate/js/et2_tabs.js b/etemplate/js/et2_tabs.js new file mode 100644 index 0000000000..29e3b572bd --- /dev/null +++ b/etemplate/js/et2_tabs.js @@ -0,0 +1,178 @@ +/** + * eGroupWare eTemplate2 - JS Tabs object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + et2_widget; +*/ + +/** + * Class which implements the tabbox-tag + */ +var et2_tabbox = et2_DOMWidget.extend({ + + init: function(_parent, _type) { + // Create the outer tabbox container + this.container = $j(document.createElement("div")) + .addClass("et2_tabbox"); + + // Create the upper container for the tab flags + var cntr = $j(document.createElement("div")) + .addClass("et2_flags") + .appendTo(this.container); + + this.flagContainer = $j(document.createElement("span")) + .addClass("et2_tabflagcntr") + .appendTo(cntr); + + $j(document.createElement("span")) + .addClass("et2_tabspacer") + .appendTo(cntr); + + // Create the lower tab container + this.tabContainer = $j(document.createElement("div")) + .addClass("et2_tabs") + .appendTo(this.container); + + this._super.apply(this, arguments); + + this.tabData = []; + }, + + destroy: function(_parent, _type) { + + this._super.apply(this, arguments); + + this.container = null; + this.flagContainer = null; + this.tabData = []; + }, + + _readTabs: function(tabData, tabs) { + et2_filteredNodeIterator(tabs, function(node, nodeName) { + if (nodeName == "tab") + { + tabData.push({ + "label": et2_readAttrWithDefault(node, "label", "Tab"), + "widget": null, + "contentDiv": null, + "flagDiv": null + }); + } + else + { + throw("Error while parsing: Invalid tag '" + nodeName + + "' in tabs tag"); + } + }, this); + }, + + _readTabPanels: function(tabData, tabpanels) { + var i = 0; + et2_filteredNodeIterator(tabpanels, function(node, nodeName) { + if (i < tabData.length) + { + // Create the widget corresponding to the given node + tabData[i].widget = this.createElementFromNode(node, + nodeName); + } + else + { + throw("Error while reading tabpanels tag, too many widgets!"); + } + i++; + }, this); + }, + + loadFromXML: function(_node) { + // Get the tabs and tabpanels tags + var tabsElems = et2_directChildrenByTagName(_node, "tabs"); + var tabpanelsElems = et2_directChildrenByTagName(_node, "tabpanels"); + + if (tabsElems.length == 1 && tabpanelsElems.length == 1) + { + var tabs = tabsElems[0]; + var tabpanels = tabpanelsElems[0]; + + var tabData = []; + + // Parse the "tabs" tag + this._readTabs(tabData, tabs); + + // Read and create the widgets defined in the "tabpanels" + this._readTabPanels(tabData, tabpanels); + + // Create the tab DOM-Nodes + this.createTabs(tabData) + } + else + { + throw("Error while parsing tabbox, none or multiple tabs or tabpanels tags!"); + } + }, + + createTabs: function(tabData) { + this.tabData = tabData; + + this.tabContainer.empty(); + this.flagContainer.empty(); + + for (var i = 0; i < this.tabData.length; i++) + { + // Add a spacer to the flag container + $j(document.createElement("span")) + .addClass("et2_flagspacer") + .text("-") + .appendTo(this.flagContainer); + + var entry = this.tabData[i]; + + entry.flagDiv = $j(document.createElement("span")) + .addClass("et2_tabflag") + .text(entry.label) + .appendTo(this.flagContainer); + + entry.contentDiv = $j(document.createElement("div")) + .addClass("et2_tabcntr") + .hide() + .appendTo(this.tabContainer); + + // Let the widget appear on its corresponding page + entry.widget.onSetParent(); + } + }, + + getDOMNode: function(_sender) { + if (_sender == this) + { + return this.container[0]; + } + else + { + for (var i = 0; i < this.tabData.length; i++) + { + if (this.tabData[i].widget == _sender) + { + return this.tabData[i].contentDiv[0]; + } + } + + return null; + } + } + +}); + +et2_register_widget(et2_tabbox, ["tabbox"]); + diff --git a/etemplate/js/et2_template.js b/etemplate/js/et2_template.js index 0a9e5df4fa..a4ad2e270f 100644 --- a/etemplate/js/et2_template.js +++ b/etemplate/js/et2_template.js @@ -26,6 +26,23 @@ */ var et2_template = et2_DOMWidget.extend({ + attributes: { + "template": { + }, + "group": { + }, + "version": { + "name": "Version", + "type": "string", + "description": "Version of the template" + }, + "lang": { + "name": "Language", + "type": "string", + "description": "Language the template is written in" + } + }, + /** * Initializes this template widget as a simple container. */ @@ -34,6 +51,7 @@ var et2_template = et2_DOMWidget.extend({ this.isProxied = false; this.div = document.createElement("div"); + this.id = ""; this._super.apply(this, arguments); }, diff --git a/etemplate/js/et2_textbox.js b/etemplate/js/et2_textbox.js index 9c5e2765bc..14a083e2d6 100644 --- a/etemplate/js/et2_textbox.js +++ b/etemplate/js/et2_textbox.js @@ -14,33 +14,56 @@ /*egw:uses jquery.jquery; - et2_widget; + et2_inputWidget; */ /** * Class which implements the "textbox" XET-Tag */ -var et2_textbox = et2_DOMWidget.extend({ +var et2_textbox = et2_baseWidget.extend({ - init: function(_parent) { - this.input = $j(document.createElement("input")) - .addClass("et2_input"); - - this._super.apply(this, arguments); - this.label = ""; - }, - - set_value: function(_value) { - if (_value != this.value) - { - this.label = _value; - - this.input.attr("value", _value); + attributes: { + "multiline": { + "name": "multiline", + "type": "boolean", + "default": false, + "description": "If true, the textbox is a multiline edit field." } }, - getDOMNode: function() { - return this.input[0]; + init: function(_parent) { + this._super.apply(this, arguments); + + this.input = null; + + this.createInputWidget(); + }, + + createInputWidget: function() { + if (this.multiline) + { + this.input = $j(document.createElement("textarea")); + } + else + { + this.input = $j(document.createElement("input")); + } + + this.input.addClass("et2_textbox"); + + this.setDOMNode(this.input[0]); + }, + + set_multiline: function(_value) { + if (_value != this.multiline) + { + this.multiline = _value; + + this.createInputWidget(); + + // Write all settings again + this.update(); + } } }); diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 1c2771c1ce..84d2fc42c9 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -14,6 +14,7 @@ /*egw:uses jquery.jquery; + lib/tooltip.js; et2_xml; et2_common; et2_inheritance; @@ -53,6 +54,26 @@ function et2_register_widget(_constructor, _types) */ var et2_widget = Class.extend({ + attributes: { + "id": { + "name": "ID", + "type": "string", + "description": "Unique identifier of the widget" + }, + + /** + * Ignore the "span" property by default - it is read by the grid and + * other widgets. + */ + "span": { + "ignore": true + } + }, + + // Set the legacyOptions array to the names of the properties the "options" + // attribute defines. + legacyOptions: [], + /** * The init function is the constructor of the widget. When deriving new * classes from the widget base class, always call this constructor unless @@ -82,7 +103,6 @@ var et2_widget = Class.extend({ } this._children = []; - this.id = ""; this.type = _type; // The supported widget classes array defines a whitelist for all widget @@ -148,12 +168,12 @@ var et2_widget = Class.extend({ _obj._children[i].clone(this, _obj._children[i].type); } - // Copy all properties for which a setter function exists - for (var key in _obj) + // Copy all properties + for (var key in _obj.attributes) { - if (key != "id" && typeof this["set_" + key] == "function") + if (!_obj.attributes[key].ignore && key != "id") { - this["set_" + key](_obj[key]); + this.setAttribute(key, _obj.getAttribute(key)); } } }, @@ -265,6 +285,31 @@ var et2_widget = Class.extend({ return null; }, + /** + * Function which allows iterating over the complete widget tree. + * + * @param _callback is the function which should be called for each widget + * @param _context is the context in which the function should be executed + * @param _type is an optional parameter which specifies a class/interface + * the elements have to be instanceOf. + */ + iterateOver: function(_callback, _context, _type) { + if (typeof _type == "undefined") + { + _type = et2_widget; + } + + if (this.instanceOf(_type)) + { + _callback.call(_context, this); + } + + for (var i = 0; i < this._children.length; i++) + { + this._children[i].iterateOver(_callback, _context, _type); + } + }, + isOfSupportedWidgetClass: function(_obj) { for (var i = 0; i < this.supportedWidgetClasses.length; i++) @@ -336,12 +381,19 @@ var et2_widget = Class.extend({ loadAttributes: function(_attrs) { for (var i = 0; i < _attrs.length; i++) { - var attr = _attrs[i]; - - // Check whether a setter exists for the given attribute - if (typeof this["set_" + attr.name] == "function" && attr.name.charAt(0) != "_") + if (_attrs[i].name == "options") { - this["set_" + attr.name](attr.value); + // Parse the legacy options + var splitted = et2_csvSplit(_attrs[i].value); + + for (var i = 0; i < splitted.length && i < this.legacyOptions.length; i++) + { + this.setAttribute(this.legacyOptions[i], splitted[i]); + } + } + else + { + this.setAttribute(_attrs[i].name, _attrs[i].value); } } }, @@ -357,13 +409,14 @@ var et2_widget = Class.extend({ * update function of all child nodes. */ update: function() { + // Go through every property of this object and check whether a // corresponding setter function exists. If yes, it is called. - for (var key in this) + for (var key in this.attributes) { - if (typeof this["set_" + key] == "function" && key.charAt(0) != "_") + if (!this.attributes[key].ignore && key != "id") { - this["set_" + key](this[key]); + this.setAttribute(key, this.getAttribute(key)); } } @@ -372,19 +425,8 @@ var et2_widget = Class.extend({ { this._children[i].update(); } - }, - - get_id: function() { - return this.id; - }, - - set_id: function(_value) { - this.id = _value; - }, - - get_type: function() { - return this.type; } + }); /** @@ -392,7 +434,13 @@ var et2_widget = Class.extend({ */ var et2_IDOMNode = new Interface({ /** - * Returns the DOM-Node of the current widget. + * Returns the DOM-Node of the current widget. The return value has to be + * a plain DOM node. If you want to return an jQuery object as you receive + * it with + * + * obj = $j(node); + * + * simply return obj[0]; * * @param _sender The _sender parameter defines which widget is asking for * the DOMNode.depending on that, the widget may return different nodes. @@ -417,19 +465,32 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { */ init: function(_parent, _type) { this.parentNode = null; - this.visible = true; + + this._attachSet = { + "node": null, + "parent": null + }; // Call the inherited constructor this._super.apply(this, arguments); }, + /** + * Detatches the node from the DOM and clears all references to the parent + * node or the dom node of this widget. + */ destroy: function() { this.detatchFromDOM(); + this.parentNode = null; + this._attachSet = {}; this._super(); }, + /** + * Automatically tries to attach this node to the parent widget. + */ onSetParent: function() { // Check whether the parent implements the et2_IDOMNode interface. If // yes, grab the DOM node and create our own. @@ -438,16 +499,53 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { } }, + /** + * Detaches the widget from the DOM tree, if it had been attached to the + * DOM-Tree using the attachToDOM method. + */ detatchFromDOM: function() { - if (this.parentNode) + + if (this._attachSet.node && this._attachSet.parent) { - var node = this.getDOMNode(this); - if (node) - { - this.parentNode.removeChild(node); - this.parentNode = null; - } + // Remove the current node from the parent node + this._attachSet.parent.removeChild(this._attachSet.node); + + // Reset the "attachSet" + this._attachSet = { + "node": null, + "parent": null + }; + + return true; } + + return false; + }, + + /** + * Attaches the widget to the DOM tree. Fails if the widget is already + * attached to the tree or no parent node or no node for this widget is + * defined. + */ + attachToDOM: function() { + // Attach the DOM node of this widget (if existing) to the new parent + var node = this.getDOMNode(this); + if (node && this.parentNode && + (node != this._attachSet.node || + this.parentNode != this._attachSet.parent)) + { + this.parentNode.appendChild(node); + + // Store the currently attached nodes + this._attachSet = { + "node": node, + "parent": this.parentNode + }; + + return true; + } + + return false; }, /** @@ -462,51 +560,77 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { this.parentNode = _node; - // Attach the DOM node of this widget (if existing) to the new parent - var node = this.getDOMNode(this); - if (node && this.parentNode) - { - this.parentNode.appendChild(node); - } + // And attatch the element to the DOM tree + this.attachToDOM(); } }, + /** + * Returns the parent node. + */ getParentDOMNode: function() { return this.parentNode; }, + /** + * Sets the id of the DOM-Node. + */ set_id: function(_value) { - this._super(_value); + + this.id = _value; var node = this.getDOMNode(this); if (node) { - node.setAttribute("id", _value); + if (_value != "") + { + node.setAttribute("id", _value); + } + else + { + node.removeAttribute("id"); + } } } }); /** - * Container object for not-yet supported widgets + * Common container object */ -var et2_placeholder = et2_DOMWidget.extend({ +var et2_container = et2_simpleWidget.extend({ init: function() { - // Create the placeholder div - this.placeDiv = $j(document.createElement("span")) - .addClass("et2_placeholder"); + this._super.apply(this, arguments); + + this.setDOMNode(document.createElement("div")); + } + +}); + + +/** + * Container object for not-yet supported widgets + */ +var et2_placeholder = et2_baseWidget.extend({ + + init: function() { + this._super.apply(this, arguments); // The attrNodes object will hold the DOM nodes which represent the // values of this object this.attrNodes = {}; - this._super.apply(this, arguments); + // Create the placeholder div + this.placeDiv = $j(document.createElement("span")) + .addClass("et2_placeholder"); var headerNode = $j(document.createElement("span")) .text(this.type) - .addClass("et2_caption"); - $j(this.placeDiv).append(headerNode); + .addClass("et2_caption") + .appendTo(this.placeDiv); + + this.setDOMNode(this.placeDiv[0]); }, loadAttributes: function(_attrs) { @@ -523,37 +647,6 @@ var et2_placeholder = et2_DOMWidget.extend({ this.attrNodes[attr.name].text(attr.name + "=" + attr.value); } - }, - - getDOMNode: function() { - return this.placeDiv[0]; } - }); -/** - * Common container object - */ -var et2_container = et2_DOMWidget.extend({ - - init: function() { - this.div = document.createElement("div"); - - this._super.apply(this, arguments); - }, - - getDOMNode: function() { - return this.div; - } - -}); - -/** - * Interface for all widgets which support returning a value - */ - -var et2_IValue = new Interface({ - getValue: function() {} -}); - - diff --git a/etemplate/js/et2_xml.js b/etemplate/js/et2_xml.js index cc95e3bd13..656306c622 100644 --- a/etemplate/js/et2_xml.js +++ b/etemplate/js/et2_xml.js @@ -114,3 +114,11 @@ function et2_filteredNodeIterator(_node, _callback, _context) } } +function et2_readAttrWithDefault(_node, _name, _default) +{ + var val = _node.getAttribute(_name); + + return (val === null) ? _default : val; +} + + diff --git a/etemplate/js/lib/tooltip.js b/etemplate/js/lib/tooltip.js new file mode 100644 index 0000000000..8c810f7948 --- /dev/null +++ b/etemplate/js/lib/tooltip.js @@ -0,0 +1,180 @@ +/** + * eGroupware2 UI - Tooltip JS + * + * This javascript file contains the JavaScript code for the etemplate2 tooltip + * + * @link http://www.egroupware.org + * @author Andreas Stoeckel (as@stylite.de) + * @version $Id: tooltip.js 31497 2010-07-22 09:50:11Z igel457 $ + */ + +/* Tooltip handling */ +function egw_tooltip() +{ + this.tooltip_div = null; + this.current_elem = null; + this.time_delta = 100; + this.show_delta = 0; + this.show_delay = 800; + this.x = 0; + this.y = 0; +} + +egw_tooltip.prototype.bindToElement = function(_elem, _text) +{ + if (_text != '') + { + var self = this; + _elem.bind('mouseenter.tooltip', function(e) { + if (_elem != self.current_elem) + { + //Prepare the tooltip + self._prepare(_text); + + self.current_elem = _elem; + self.show_delta = 0; + self.x = e.clientX; + self.y = e.clientY; + + window.setTimeout(function() {self.showHintTimeout();}, self.time_delta); + } + + return false; + }); + + _elem.bind('mouseleave.tooltip', function() { + self.current_elem = null; + self.show_delta = 0; + //self.hide(); + if (self.tooltip_div) + { + self.tooltip_div.fadeOut(100); + } + }); + + _elem.bind('mousemove.tooltip', function(e) { + //Calculate the distance the mouse took since the last call of mousemove + var dx = self.x - e.clientX; + var dy = self.y - e.clientY; + var movedist = Math.sqrt(dx * dx + dy * dy); + + //Block appereance of the tooltip on fast movements (with small movedistances) + if (movedist > 2) + self.show_delta = 0; + + self.x = e.clientX; + self.y = e.clientY; + }); + } +} + +egw_tooltip.prototype.unbindFromElement = function(_elem) +{ + _elem.unbind('mouseenter.tooltip'); + _elem.unbind('mouseleave.tooltip'); + _elem.unbind('mousemove.tooltip'); +} + +egw_tooltip.prototype.showHintTimeout = function() +{ + if (this.current_elem != null) + { + this.show_delta += this.time_delta; + if (this.show_delta < this.show_delay) + { + //Repeat the call of timeout + var self = this; + window.setTimeout(function() {self.showHintTimeout();}, this.time_delta); + } + else + { + this.show_delta = 0; + this.show(); + } + } +} + +egw_tooltip.prototype._prepare = function(_text) +{ + var self = this; + + //Remove the old tooltip + if (this.tooltip_div) + this.hide(); + + //Generate the tooltip div, set it's text and append it to the body tag + this.tooltip_div = $j(document.createElement('div')); + this.tooltip_div.hide(); + this.tooltip_div.append(_text); + this.tooltip_div.addClass("egw_tooltip"); + $j('body').append(this.tooltip_div); + + //The tooltip should automatically hide when the mouse comes over it + this.tooltip_div.mouseenter(function() { + self.hide(); + }); +} + +egw_tooltip.prototype.show = function() +{ + if (this.tooltip_div) + { + //Calculate the cursor_rectangle - this is a space the tooltip might + //not overlap with + var cursor_rect = { + left: (this.x - 8), + top: (this.y - 8), + right: (this.x + 8), + bottom: (this.y + 8) + }; + + //Calculate how much space is left on each side of the rectangle + var window_width = $j(document).width(); + var window_height = $j(document).height(); + var space_left = { + left: (cursor_rect.left), + top: (cursor_rect.top), + right: (window_width - cursor_rect.right), + bottom: (window_height - cursor_rect.bottom) + }; + + //Get the width and the height of the tooltip + var tooltip_width = this.tooltip_div.width(); + if (tooltip_width > 300) tooltip_width = 300; + var tooltip_height = this.tooltip_div.height(); + + + if (space_left.right < tooltip_width) { + this.tooltip_div.css('left', cursor_rect.left - tooltip_width); + } else if (space_left.left >= tooltip_width) { + this.tooltip_div.css('left', cursor_rect.right); + } else { + this.tooltip_div.css('left', cursor_rect.right); + this.tooltip_div.css('max-width', space_left.right); + } + + if (space_left.bottom < tooltip_height) { + this.tooltip_div.css('top', cursor_rect.top - tooltip_height); + } else if (space_left.top >= tooltip_height) { + this.tooltip_div.css('top', cursor_rect.bottom); + } else { + this.tooltip_div.css('top', cursor_rect.bottom); + this.tooltip_div.css('max-height', space_left.bottom); + } + + this.tooltip_div.fadeIn(100); + } +} + +egw_tooltip.prototype.hide = function() +{ + if (this.tooltip_div) + { + this.tooltip_div.remove(); + this.tooltip_div = null; + } +} + +//A reference to the current tooltip object +window.egw_global_tooltip = new egw_tooltip(); + diff --git a/etemplate/js/test/et2_test_description.xet b/etemplate/js/test/et2_test_description.xet new file mode 100644 index 0000000000..e5775712ef --- /dev/null +++ b/etemplate/js/test/et2_test_description.xet @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<overlay> + <vbox> + <description value="This is only a test" options="bi" /> + <description value="This is only a test" font_style="italic" statustext="This is only an italic label!"/> + </vbox> +</overlay> + diff --git a/etemplate/js/test/et2_test_grid.xet b/etemplate/js/test/et2_test_grid.xet index fa4b2d6b2d..2db9ab63a5 100644 --- a/etemplate/js/test/et2_test_grid.xet +++ b/etemplate/js/test/et2_test_grid.xet @@ -25,15 +25,16 @@ <columns> <column> <label value="Northwest"/> - <label value="Northeast"/> + <label value="Southwest"/> </column> <label value="Equator"/> <column> + <label value="Northeast"/> <label value="Southwest"/> - <label value="Southeast"/> </column> </columns> + <rows> <row/> <row/> @@ -121,12 +122,12 @@ <columns> <column> <label value="Northwest"/> - <label value="Northeast"/> + <label value="Southwest"/> </column> <label value="Equator"/> <column> + <label value="Northeast"/> <label value="Southwest"/> - <label value="Southeast"/> </column> </columns> diff --git a/etemplate/js/test/et2_test_tabbox.xet b/etemplate/js/test/et2_test_tabbox.xet new file mode 100644 index 0000000000..aa310f721b --- /dev/null +++ b/etemplate/js/test/et2_test_tabbox.xet @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<overlay> + <tabbox> + <tabs> + <tab label="Test1" /> + <tab label="Test2" /> + <tab label="Test3" /> + <tab label="Test4" /> + </tabs> + <tabpanels> + <label value="This is the content of tab 1"/> + <label value="This is the content of tab 2"/> + <label value="This is the content of tab 3"/> + <label value="This is the content of tab 4"/> + </tabpanels> + </tabbox> +</overlay> + diff --git a/etemplate/js/test/et2_test_textbox.xet b/etemplate/js/test/et2_test_textbox.xet new file mode 100644 index 0000000000..663b17f518 --- /dev/null +++ b/etemplate/js/test/et2_test_textbox.xet @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<overlay> + <textbox value="This is a single line textbox." statustext="Write something here!"/> + <textbox multiline="true" value="This is a multi line textbox."/> + + <template id="testbox"> + <textbox value="This is a single line textbox." statustext="And something else here!"/> + <textbox multiline="true" value="This is a multi line textbox."/> + </template> + + <template id="testbox"/> +</overlay> + diff --git a/etemplate/js/test/et2_test_timesheet_edit.xet b/etemplate/js/test/et2_test_timesheet_edit.xet index fbfcd2c9ad..f8c403e638 100644 --- a/etemplate/js/test/et2_test_timesheet_edit.xet +++ b/etemplate/js/test/et2_test_timesheet_edit.xet @@ -145,7 +145,7 @@ </grid> </row> <row class="row" disabled="@ts_viewtype"> - <description value="Unitprice" options=",,ts_unitprice"/> + <description value="Unitprice" options=",,,ts_unitprice"/> <grid> <columns> <column disabled="@pm_integration=none"/> diff --git a/etemplate/js/test/gfx/gradient01.png b/etemplate/js/test/gfx/gradient01.png new file mode 100644 index 0000000000000000000000000000000000000000..111cd7fbf3a2d20bfa29232ce39c27659053ec3f GIT binary patch literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^3P9Yz!3HF=(z2z16icy_X9x!n)NrJ90QsB+9+AaB z_18g|(Me-=1yE43#5JNMI6tkVJh3R1p}f3YFEcN@I61K(RWH9NefB#WkV$2pE{-7; zbKc&%$jP9<;TqVTmj5QFN4zBFKy$%=nY(+nEsS@{0M$Xk1I`1hRxy9DU2wVK2P*?Z z2m`|cCI$vk28I<33=Tj6Ee3`FMurBU<6%-Rj351hqDY{@;sMjbUB3MWj<V$-VNX{- Jmvv4FO#lsnK3)I- literal 0 HcmV?d00001 diff --git a/etemplate/js/test/gfx/gradient01.svg b/etemplate/js/test/gfx/gradient01.svg new file mode 100644 index 0000000000..8ffdc2bb0c --- /dev/null +++ b/etemplate/js/test/gfx/gradient01.svg @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="32" + height="128" + id="svg2" + version="1.1" + inkscape:version="0.48.0 r9654" + sodipodi:docname="Neues Dokument 1"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3755"> + <stop + style="stop-color:#ffffff;stop-opacity:0.52499998;" + offset="0" + id="stop3757" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop3759" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3755" + id="linearGradient3761" + x1="15.357142" + y1="948.78522" + x2="15.357142" + y2="1021.8951" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.979899" + inkscape:cx="88.135153" + inkscape:cy="46.311537" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1600" + inkscape:window-height="823" + inkscape:window-x="0" + inkscape:window-y="24" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-924.36218)"> + <rect + style="color:#000000;fill:url(#linearGradient3761);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.50000000000000000;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="rect2985" + width="32" + height="128" + x="0" + y="924.36218" /> + </g> +</svg> diff --git a/etemplate/js/test/gfx/gradient02.png b/etemplate/js/test/gfx/gradient02.png new file mode 100644 index 0000000000000000000000000000000000000000..8ea5aed2d197666f760138464c746719078a5ef2 GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^3P9Yz!3HF=(z2z16icy_X9x!n)NrJ90QsB+9+AaB z_18g|(Me-=1yE43#5JNMI6tkVJh3R1p}f3YFEcN@I61K(RWH9NefB#WkV(a!E{-7; zbKc%M$jhL>!C+|mZog4qq1`Da6P54D=g(+8Uvirfs0;z>816`YWKFo<@P~<kL5qPQ zfRUjA=++Phh6O+YQ3i$;3=9seNK!!#|2%<w7?{8;cW(!)=!#I6K#-89tDnm{r-UW| DY%@DA literal 0 HcmV?d00001 diff --git a/etemplate/js/test/gfx/gradient02.svg b/etemplate/js/test/gfx/gradient02.svg new file mode 100644 index 0000000000..61ae2bbbc9 --- /dev/null +++ b/etemplate/js/test/gfx/gradient02.svg @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="32" + height="128" + id="svg2" + version="1.1" + inkscape:version="0.48.0 r9654" + sodipodi:docname="gradient02.svg" + inkscape:export-filename="/home/andreas/source/egroupware/trunk/egroupware/etemplate/js/test/gfx/gradient02.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3755"> + <stop + style="stop-color:#ffffff;stop-opacity:0.52499998;" + offset="0" + id="stop3757" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop3759" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3755" + id="linearGradient3761" + x1="15.357142" + y1="948.78522" + x2="15.357142" + y2="1021.8951" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-32,-1976.7244)" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.979899" + inkscape:cx="88.135153" + inkscape:cy="46.311537" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1600" + inkscape:window-height="823" + inkscape:window-x="0" + inkscape:window-y="24" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-924.36218)"> + <rect + style="color:#000000;fill:url(#linearGradient3761);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="rect2985" + width="32" + height="128" + x="-32" + y="-1052.3622" + transform="scale(-1,-1)" /> + </g> +</svg> diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 4a849d78ac..804ca50b8f 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -11,7 +11,10 @@ <script src="../et2_description.js"></script> <script src="../et2_grid.js"></script> <script src="../et2_button.js"></script> + <script src="../et2_box.js"></script> <script src="../et2_textbox.js"></script> + <!--<script src="../et2_tabs.js"></script>--> + <script src="../lib/tooltip.js"></script> <style type="text/css"> body { font-family: Lucida Grande, sans-serif; @@ -75,6 +78,86 @@ color: #101050; font-size: 10pt; } + + button.et2_button { + background-color: #E0E0E0; + background-image: url(gfx/gradient01.png); + background-position: center; + background-repeat: repeat-x; + + border: 1px solid silver; + color: #101010; + cursor: pointer; + margin: 5px; + padding: 3px; + text-align: center; + + font-size: 9pt; + + text-shadow: 1px 1px #E0E0E0; + } + + button.et2_button:hover { + color: #050505; + border: 1px solid gray; + background-color: #D0D0EE; + } + + button.et2_button:active { + background-image: url(gfx/gradient02.png); + background-color: #D0D0E0; + } + + button.et2_button:focus { + border: 1px solid #2c3d6f; + color: #202d52; + outline: none; + } + + div.et2_hbox { + display: inline; + } + + .et2_tabflag { + display: inline-block; + margin-right: 5px; + height: 20px; + padding: 5px; + cursor: pointer; + border-width: 1px 1px 0 1px; + border-style: solid; + border-color: silver; + } + + .et2_tabflag.active { + border-bottom: 1px solid white; + } + + .et2_textbox { + resize: none; + } + + .et2_bold { + font-weight: bold; + } + + .et2_italic { + font-style: italic; + } + + .et2_vbox div, .et2_vbox span { + display: block; + } + + .egw_tooltip + { + position: fixed; + border: 1px solid #897f51; + padding: 3px; + background-color: #FDF9DB; + max-width: 300px; + color: black; + } </style> </head> <body> @@ -84,6 +167,9 @@ <a href="#" onclick="open_xet('et2_test_timesheet_edit.xet');">Timesheet edit dialog</a> <a href="#" onclick="open_xet('et2_test_template.xet');">Template proxy test</a> <a href="#" onclick="open_xet('et2_test_grid.xet');">Grid test</a> + <a href="#" onclick="open_xet('et2_test_tabbox.xet');">Tabs test</a> + <a href="#" onclick="open_xet('et2_test_textbox.xet');">Textbox test</a> + <a href="#" onclick="open_xet('et2_test_description.xet');">Description test</a> </div> <div class="header">ETemplate2 container:</div> <div id="container"></div> From 510c482eef7edd3443c03ee90b484138e6725681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Wed, 10 Aug 2011 14:39:35 +0000 Subject: [PATCH 012/472] Fixed some dependencies --- etemplate/js/et2_baseWidget.js | 55 +++++++++++++++++++++++++++++++++ etemplate/js/et2_inputWidget.js | 2 +- etemplate/js/et2_widget.js | 54 -------------------------------- etemplate/js/test/test_xml.html | 2 ++ 4 files changed, 58 insertions(+), 55 deletions(-) diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js index 21f0769864..5f633719ec 100644 --- a/etemplate/js/et2_baseWidget.js +++ b/etemplate/js/et2_baseWidget.js @@ -115,4 +115,59 @@ var et2_baseWidget = et2_DOMWidget.extend({ }); +/** + * Simple container object + */ +var et2_container = et2_baseWidget.extend({ + + init: function() { + this._super.apply(this, arguments); + + this.setDOMNode(document.createElement("div")); + } + +}); + +/** + * Container object for not-yet supported widgets + */ +var et2_placeholder = et2_baseWidget.extend({ + + init: function() { + this._super.apply(this, arguments); + + // The attrNodes object will hold the DOM nodes which represent the + // values of this object + this.attrNodes = {}; + + // Create the placeholder div + this.placeDiv = $j(document.createElement("span")) + .addClass("et2_placeholder"); + + var headerNode = $j(document.createElement("span")) + .text(this.type) + .addClass("et2_caption") + .appendTo(this.placeDiv); + + this.setDOMNode(this.placeDiv[0]); + }, + + loadAttributes: function(_attrs) { + for (var i = 0; i < _attrs.length; i++) + { + var attr = _attrs[i]; + + if (typeof this.attrNodes[attr.name] == "undefined") + { + this.attrNodes[attr.name] = $j(document.createElement("span")) + .addClass("et2_attr"); + this.placeDiv.append(this.attrNodes[attr.name]); + } + + this.attrNodes[attr.name].text(attr.name + "=" + attr.value); + } + } +}); + + diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 7c37e69039..6b2d541431 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -43,7 +43,7 @@ var et2_IInput = new Interface({ * interface. When derriving from this class, call setDOMNode with an input * DOMNode. */ -var et2_inputWidget = et2_simpleWidget.extend(et2_IInput, { +var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { attributes: { "value": { diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 84d2fc42c9..3426fc1a79 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -595,58 +595,4 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { }); -/** - * Common container object - */ -var et2_container = et2_simpleWidget.extend({ - - init: function() { - this._super.apply(this, arguments); - - this.setDOMNode(document.createElement("div")); - } - -}); - - -/** - * Container object for not-yet supported widgets - */ -var et2_placeholder = et2_baseWidget.extend({ - - init: function() { - this._super.apply(this, arguments); - - // The attrNodes object will hold the DOM nodes which represent the - // values of this object - this.attrNodes = {}; - - // Create the placeholder div - this.placeDiv = $j(document.createElement("span")) - .addClass("et2_placeholder"); - - var headerNode = $j(document.createElement("span")) - .text(this.type) - .addClass("et2_caption") - .appendTo(this.placeDiv); - - this.setDOMNode(this.placeDiv[0]); - }, - - loadAttributes: function(_attrs) { - for (var i = 0; i < _attrs.length; i++) - { - var attr = _attrs[i]; - - if (typeof this.attrNodes[attr.name] == "undefined") - { - this.attrNodes[attr.name] = $j(document.createElement("span")) - .addClass("et2_attr"); - this.placeDiv.append(this.attrNodes[attr.name]); - } - - this.attrNodes[attr.name].text(attr.name + "=" + attr.value); - } - } -}); diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 804ca50b8f..d274130069 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -7,6 +7,8 @@ <script src="../et2_inheritance.js"></script> <script src="../et2_common.js"></script> <script src="../et2_widget.js"></script> + <script src="../et2_baseWidget.js"></script> + <script src="../et2_inputWidget.js"></script> <script src="../et2_template.js"></script> <script src="../et2_description.js"></script> <script src="../et2_grid.js"></script> From 67b05dc93cbb48c0672d9bdc1ff39500bef0c44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Wed, 10 Aug 2011 15:15:51 +0000 Subject: [PATCH 013/472] Accidently derrived et2_textbox from et2_baseWidget --- etemplate/js/et2_textbox.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etemplate/js/et2_textbox.js b/etemplate/js/et2_textbox.js index 14a083e2d6..6227716a00 100644 --- a/etemplate/js/et2_textbox.js +++ b/etemplate/js/et2_textbox.js @@ -20,7 +20,7 @@ /** * Class which implements the "textbox" XET-Tag */ -var et2_textbox = et2_baseWidget.extend({ +var et2_textbox = et2_inputWidget.extend({ attributes: { "multiline": { From 4f2eeaafe120f3b1c39f75043e125c43bb9a1dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Wed, 10 Aug 2011 16:23:02 +0000 Subject: [PATCH 014/472] Fixed problem with id not being copied when cloning an template rewrote a part of the attribute merging system - now not only references of the attribute descriptors are copied between the instances. --- etemplate/js/et2_common.js | 8 ++++- etemplate/js/et2_inheritance.js | 58 +++++++++++++++++++++------------ etemplate/js/et2_inputWidget.js | 2 +- etemplate/js/et2_template.js | 8 +++++ etemplate/js/et2_textbox.js | 1 + etemplate/js/et2_widget.js | 9 ++--- 6 files changed, 60 insertions(+), 26 deletions(-) diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index 51a19119c2..b85c64524b 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -29,7 +29,7 @@ if (typeof Array.prototype.indexOf == "undefined") * ET2_DEBUGLEVEL specifies which messages are printed to the console. Decrease * the value of ET2_DEBUGLEVEL to get less messages. */ -var ET2_DEBUGLEVEL = 0; +var ET2_DEBUGLEVEL = 4; function et2_debug(_level, _msg) { @@ -158,6 +158,12 @@ function et2_checkType(_val, _type) throw("Invalid type identifier supplied."); } +/** + * If et2_no_init is set as default value, the initAttributes function will not + * try to initialize the attribute with the default value. + */ +var et2_no_init = new Object(); + /** * Validates the given attribute with the given id. The validation checks for * the existance of a human name, a description, a type and a default value. diff --git a/etemplate/js/et2_inheritance.js b/etemplate/js/et2_inheritance.js index 9233805d4a..fd970e3865 100644 --- a/etemplate/js/et2_inheritance.js +++ b/etemplate/js/et2_inheritance.js @@ -150,31 +150,47 @@ function addAttributeFunctions(prototype, _super) { - var attributes = prototype.attributes; + function _copyMerge(_new, _old) + { + var result = {}; + + // Copy the new object + if (typeof _new != "undefined") + { + for (var key in _new) + { + result[key] = _new[key]; + } + } + + // Merge the old object + for (var key in _old) + { + if (typeof result[key] == "undefined") + { + result[key] = _old[key]; + } + } + + return result; + } + + var attributes = {}; + + // Copy the old attributes + for (var key in prototype.attributes) + { + attributes[key] = _copyMerge({}, prototype.attributes[key]); + } // Add the old attributes to the new ones. If the attributes already // exist, they are merged. for (var key in _super.attributes) { - var attrib = _super.attributes[key]; + var _old = _super.attributes[key]; + var _new = {}; - if (typeof attributes[key] == "undefined") - { - // In the case that the old attribute has no equivalent in the - // new class, simply create a reference to the old one. - attributes[key] = attrib; - } - else - { - // Otherwise merge the two attribute descriptors. - for (var key2 in attrib) - { - if (typeof attributes[key][key2] == "undefined") - { - attributes[key][key2] = attrib[key2]; - } - } - } + attributes[key] = _copyMerge(attributes[key], _old); } // Validate the attributes @@ -183,6 +199,8 @@ et2_validateAttrib(key, attributes[key]); } + prototype.attributes = attributes; + /** * The initAttributes function sets the attributes to their default * values. The attributes are not overwritten, which means, that the @@ -192,7 +210,7 @@ prototype.initAttributes = function() { for (var key in this.attributes) { - if (!this.attributes[key].ignore) + if (!this.attributes[key].ignore && this.attributes[key]["default"] !== et2_no_init) { this.setAttribute(key, this.attributes[key]["default"], false); diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 6b2d541431..14260f50b0 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -50,7 +50,7 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { "name": "Value", "description": "The value of the widget", "type": "string", - "default": "" + "default": et2_no_init } }, diff --git a/etemplate/js/et2_template.js b/etemplate/js/et2_template.js index a4ad2e270f..a9c25a9dd9 100644 --- a/etemplate/js/et2_template.js +++ b/etemplate/js/et2_template.js @@ -115,10 +115,18 @@ var et2_template = et2_DOMWidget.extend({ // isProxied property to true tmpl.makeProxied(); + // Do not copy the id when cloning as this leads to infinit + // recursion + tmpl.attributes["id"].ignore = true; + // Create a clone of the template and add it as child of this // template (done by passing "this" to the clone function) this.proxiedTemplate = tmpl.clone(this); + // Reset the "ignore" flag and manually copy the id + tmpl.attributes["id"].ignore = false; + this.proxiedTemplate.id = tmpl.id; + // Disallow adding any new node to this template this.supportedWidgetClasses = []; diff --git a/etemplate/js/et2_textbox.js b/etemplate/js/et2_textbox.js index 6227716a00..6d22417e07 100644 --- a/etemplate/js/et2_textbox.js +++ b/etemplate/js/et2_textbox.js @@ -35,6 +35,7 @@ var et2_textbox = et2_inputWidget.extend({ this._super.apply(this, arguments); this.input = null; + this.id = ""; this.createInputWidget(); }, diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 3426fc1a79..3a26511694 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -58,7 +58,7 @@ var et2_widget = Class.extend({ "id": { "name": "ID", "type": "string", - "description": "Unique identifier of the widget" + "description": "Unique identifier of the widget", }, /** @@ -92,6 +92,8 @@ var et2_widget = Class.extend({ _type = "widget"; } + this.id = ""; + // Copy the parent parameter and add this widget to its parent children // list. this._parent = _parent; @@ -161,7 +163,6 @@ var et2_widget = Class.extend({ }, assign: function(_obj) { - // Create a clone of all child elements of the given object for (var i = 0; i < _obj._children.length; i++) { @@ -171,7 +172,7 @@ var et2_widget = Class.extend({ // Copy all properties for (var key in _obj.attributes) { - if (!_obj.attributes[key].ignore && key != "id") + if (!_obj.attributes[key].ignore) { this.setAttribute(key, _obj.getAttribute(key)); } @@ -414,7 +415,7 @@ var et2_widget = Class.extend({ // corresponding setter function exists. If yes, it is called. for (var key in this.attributes) { - if (!this.attributes[key].ignore && key != "id") + if (!this.attributes[key].ignore) { this.setAttribute(key, this.getAttribute(key)); } From 9ea38d694bb6ad7db858e6bce81757212f1611fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Wed, 10 Aug 2011 17:44:22 +0000 Subject: [PATCH 015/472] Added very basic implementation for reading the content array --- etemplate/js/et2_contentArrayMgr.js | 44 +++++++++ etemplate/js/et2_inputWidget.js | 14 +++ etemplate/js/et2_widget.js | 20 +++- .../js/test/et2_test_timesheet_edit.json | 95 +++++++++++++++++++ etemplate/js/test/test_xml.html | 20 +++- 5 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 etemplate/js/et2_contentArrayMgr.js create mode 100644 etemplate/js/test/et2_test_timesheet_edit.json diff --git a/etemplate/js/et2_contentArrayMgr.js b/etemplate/js/et2_contentArrayMgr.js new file mode 100644 index 0000000000..20ce93fd95 --- /dev/null +++ b/etemplate/js/et2_contentArrayMgr.js @@ -0,0 +1,44 @@ +/** + * eGroupWare eTemplate2 - JS content array manager + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +"use strict"; + +function et2_contentArrayMgr(_data, _parentMgr) +{ + if (typeof _parentMgr == "undefined") + { + _parentMgr = null; + } + + // Copy the parent manager which is needed to access relative data when + // being in a relative perspective of the manager + this.parentMgr = _parentMgr; + + // Hold a reference to the data + this.data = _data; +} + +et2_contentArrayMgr.prototype.getValueForID = function(_id) +{ + if (typeof this.data[_id] != "undefined") + { + return this.data[_id]; + } + + return null; +} + +et2_contentArrayMgr.prototype.openPerspective = function(_rootId) +{ + return new et2_contentArrayMgr(this._data[_rootId], this); +} + diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 14260f50b0..03e1c91ccd 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -69,6 +69,20 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { } }, + set_id: function(_value) { + this._super.apply(this, arguments); + + var mgr = this.getContentMgr(); + if (_value != '' && mgr != null) + { + var val = mgr.getValueForID(this.id); + if (val !== null) + { + this.set_value(val); + } + } + }, + get_value: function() { return this.getValue(); }, diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 3a26511694..bf6fa41d20 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -58,7 +58,7 @@ var et2_widget = Class.extend({ "id": { "name": "ID", "type": "string", - "description": "Unique identifier of the widget", + "description": "Unique identifier of the widget" }, /** @@ -93,6 +93,7 @@ var et2_widget = Class.extend({ } this.id = ""; + this._mgr = null; // Copy the parent parameter and add this widget to its parent children // list. @@ -426,6 +427,23 @@ var et2_widget = Class.extend({ { this._children[i].update(); } + }, + + setContentMgr: function(_mgr) { + this._mgr = _mgr; + }, + + getContentMgr: function() { + if (this._mgr != null) + { + return this._mgr; + } + else if (this._parent) + { + return this._parent.getContentMgr(); + } + + return null; } }); diff --git a/etemplate/js/test/et2_test_timesheet_edit.json b/etemplate/js/test/et2_test_timesheet_edit.json new file mode 100644 index 0000000000..1c1762df3e --- /dev/null +++ b/etemplate/js/test/et2_test_timesheet_edit.json @@ -0,0 +1,95 @@ +var timesheet_data = { + "content":{ + "ts_id":"1", + "ts_project":null, + "ts_title":"Test geschrieben", + "ts_description":null, + "ts_start":1307030400, + "ts_duration":"150", + "ts_quantity":"2.5", + "ts_unitprice":null, + "cat_id":null, + "ts_owner":"5", + "ts_modified":1307039479, + "ts_modifier":"5", + "pl_id":null, + "ts_status":null, + "user_timezone_read":"Europe/Berlin", + "msg":null, + "view":false, + "tabs":null, + "link_to":{ + "to_id":"1", + "to_app":"timesheet" + }, + "js":"<script>\u000a\u000a</script>\u000a", + "ts_quantity_blur":2.5, + "start_time":"18:00", + "pm_integration":null, + "no_ts_status":true, + "all_pm_ids":[], + "history":{ + "id":"1", + "app":"timesheet", + "status-widgets":{ + "ts_status":[], + "ts_modifier":"select-account", + "cat_id":"select-cat" + } + }, + "ts_title_blur":null + }, + "sel_options":{ + "status":{ + "ts_project":"Project", + "ts_title":"Title", + "cat_id":"Category", + "ts_description":"Description", + "ts_start":"Start", + "ts_duration":"Duration", + "ts_quantity":"Quantity", + "ts_unitprice":"Unitprice", + "ts_owner":"Owner", + "ts_modifier":"Modifier", + "ts_status":"Status", + "pm_id":"Projectid", + "customfields":"Custom fields" + }, + "ts_owner":{ + "5":"User, admin" + }, + "ts_status":[] + }, + "readonlys":{ + "button[delete]":false, + "button[edit]":true, + "button[save]":false, + "button[save_new]":false, + "button[apply]":false, + "ts_owner":true, + "tabs":{ + "customfields":true + } + }, + "preserv":{ + "ts_id":"1", + "ts_project":null, + "ts_title":"Test geschrieben", + "ts_description":null, + "ts_start":1307030400, + "ts_duration":"150", + "ts_quantity":"2.5", + "ts_unitprice":null, + "cat_id":null, + "ts_owner":"5", + "ts_modified":1307039479, + "ts_modifier":"5", + "pl_id":null, + "ts_status":null, + "user_timezone_read":"Europe/Berlin", + "view":false, + "referer":"timesheet.timesheet_ui.index", + "ts_title_blur":null + } +} + diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index d274130069..c499baaffd 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -15,8 +15,12 @@ <script src="../et2_button.js"></script> <script src="../et2_box.js"></script> <script src="../et2_textbox.js"></script> + <script src="../et2_contentArrayMgr.js"></script> <!--<script src="../et2_tabs.js"></script>--> <script src="../lib/tooltip.js"></script> + + <script src="et2_test_timesheet_edit.json"></script> + <style type="text/css"> body { font-family: Lucida Grande, sans-serif; @@ -166,7 +170,7 @@ <h1>EGroupware ETemplate2 Test</h1> <div class="header">Choose one of the following tests:</div> <div id="linklist"> - <a href="#" onclick="open_xet('et2_test_timesheet_edit.xet');">Timesheet edit dialog</a> + <a href="#" onclick="open_xet('et2_test_timesheet_edit.xet', timesheet_data.content);">Timesheet edit dialog</a> <a href="#" onclick="open_xet('et2_test_template.xet');">Template proxy test</a> <a href="#" onclick="open_xet('et2_test_grid.xet');">Grid test</a> <a href="#" onclick="open_xet('et2_test_tabbox.xet');">Tabs test</a> @@ -174,13 +178,21 @@ <a href="#" onclick="open_xet('et2_test_description.xet');">Description test</a> </div> <div class="header">ETemplate2 container:</div> + <div id="time"></div> <div id="container"></div> <script> var container = null; - function open_xet(file) { + function open_xet(file, content) { + if (typeof content == "undefined") + { + content = {}; + } + et2_loadXMLFromURL(file, function(_xmldoc) { + var t1 = (new Date).getTime(); + if (container != null) { container.destroy(); @@ -189,7 +201,11 @@ container = new et2_container(null); container.setParentDOMNode(document.getElementById("container")); + container.setContentMgr(new et2_contentArrayMgr(content)); container.loadFromXML(_xmldoc); + + var t2 = (new Date).getTime(); + $j("#time").text("Building the template took " + (t2 - t1) + "ms"); }); } </script> From 0b6954fb4479b911f642fe1181a6f3987f1c9ffe Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 10 Aug 2011 21:44:25 +0000 Subject: [PATCH 016/472] Handle lists inside tables in odt --- etemplate/templates/default/openoffice.xslt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/etemplate/templates/default/openoffice.xslt b/etemplate/templates/default/openoffice.xslt index 300355f3e7..147631eedf 100644 --- a/etemplate/templates/default/openoffice.xslt +++ b/etemplate/templates/default/openoffice.xslt @@ -44,9 +44,7 @@ </style:style> <xsl:copy-of select="$custom-styles" /> <xsl:call-template name="extract-styles" /> - </xsl:copy> <!-- Pre-made styles from http://fisheye.liip.ch/browse/PUB/fluxcms/branches/matrix/inc/bx/editors/ooo/html2odt.xsl?r=9331 --> - <office:styles> <style:style style:name="Pol" style:family="paragraph" style:parent-style-name="Standard" style:list-style-name="LO"> <style:text-properties style:text-position="0% 100%"/> </style:style> @@ -140,7 +138,7 @@ <style:text-properties style:font-name="StarSymbol"/> </text:list-level-style-bullet> </text:list-style> - </office:styles> + </xsl:copy> </xsl:template> <!-- Generate custom styles based on the span styles --> @@ -199,7 +197,7 @@ <xsl:variable name="font-size" select="substring-after(text(),'font-size:')" /> <!-- Approximate conversion that seems to work --> <xsl:variable name="size" select="ceiling(number(translate($font-size,translate($font-size,'0123456789',''),'')))"/> - <style:text-properties fo:font-size="{$size}pt" fo:font-size-asian="{$size}pt"/> + <style:text-properties fo:font-size="{$size}pt"/> </xsl:when> <xsl:when test="starts-with(.,'font-family:')"> @@ -223,13 +221,13 @@ <text:span text:style-name="Tunderline"><xsl:apply-templates/></text:span> </xsl:template> - <xsl:template match="ul[parent::office:text]"> + <xsl:template match="ul[ancestor::office:text]"> <text:list text:style-name="LU"> <xsl:apply-templates/> </text:list> </xsl:template> - <xsl:template match="ol[parent::office:text]"> + <xsl:template match="ol[ancestor::office:text]"> <text:list text:style-name="LO"> <xsl:apply-templates/> </text:list> From 9c82896a7b91f33ceaacce515b4ebfaa62fa630c Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 11 Aug 2011 07:23:29 +0000 Subject: [PATCH 017/472] quietened PHP Warning: in_array() expects parameter 2 to be array, boolean given on line 855 --- phpgwapi/inc/class.egw_vfs.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpgwapi/inc/class.egw_vfs.inc.php b/phpgwapi/inc/class.egw_vfs.inc.php index 3efe67e482..2992c433b1 100644 --- a/phpgwapi/inc/class.egw_vfs.inc.php +++ b/phpgwapi/inc/class.egw_vfs.inc.php @@ -852,7 +852,7 @@ class egw_vfs extends vfs_stream_wrapper // check if there's a group access and we have the right membership if (($stat['mode'] & ($check << 3)) == ($check << 3) && $stat['gid']) { - if (in_array(-abs($stat['gid']), $GLOBALS['egw']->accounts->memberships(self::$user, true))) + if (($memberships = $GLOBALS['egw']->accounts->memberships(self::$user, true)) && in_array(-abs($stat['gid']), $memberships)) { //error_log(__METHOD__."(path=$path||stat[name]={$stat['name']},stat[mode]=".sprintf('%o',$stat['mode']).",$check) access via group rights!"); return true; From 4f54abdda219df6afe1a40e19f3f55b8c74f546c Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 11 Aug 2011 07:31:47 +0000 Subject: [PATCH 018/472] quietened PHP Warning: array_keys() expects parameter 1 to be array, null given on line 106 --- phpgwapi/inc/class.hooks.inc.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpgwapi/inc/class.hooks.inc.php b/phpgwapi/inc/class.hooks.inc.php index a1cefdf673..bd47372322 100644 --- a/phpgwapi/inc/class.hooks.inc.php +++ b/phpgwapi/inc/class.hooks.inc.php @@ -43,7 +43,7 @@ class hooks var $table = 'egw_hooks'; /** * Hooks by location and appname - * + * * @var array $location => $app => $file */ var $locations; @@ -78,7 +78,7 @@ class hooks /** * Executes all the hooks (the user has rights to) for a given location - * + * * If no $order given, hooks are executed in the order of the applications! * * @param string|array $args location-name as string or array with keys location and @@ -103,7 +103,7 @@ class hooks if (!$no_permission_check) { // on install of a new egroupware both hook-apps and user apps may be empty/not set - $apps = array_intersect((array)$apps,(array)array_keys($GLOBALS['egw_info']['user']['apps'])); + $apps = array_intersect((array)$apps,array_keys((array)$GLOBALS['egw_info']['user']['apps'])); } if ($order) { @@ -254,9 +254,9 @@ class hooks // some apps have setup_info for more then themselfs (eg. phpgwapi for groupdav) foreach($setup_info as $appname => $data) { - if ($data['hooks']) + if ($data['hooks']) { - if ($hdata[$appname]) + if ($hdata[$appname]) { $hdata[$appname]['hooks'] = array_merge($hdata[$appname]['hooks'],$data['hooks']); } From 378526a648b7ba47fc630858c37a92e9fd6c42d0 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 11 Aug 2011 07:41:18 +0000 Subject: [PATCH 019/472] quietend PHP Warning: explode() expects parameter 2 to be string, array given on line 313 --- calendar/inc/class.calendar_uiforms.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calendar/inc/class.calendar_uiforms.inc.php b/calendar/inc/class.calendar_uiforms.inc.php index 033f5ad661..025bdf80ea 100644 --- a/calendar/inc/class.calendar_uiforms.inc.php +++ b/calendar/inc/class.calendar_uiforms.inc.php @@ -310,7 +310,7 @@ class calendar_uiforms extends calendar_ui break; case 'resource': - if (is_array($data) && isset($data['current']) ) + if (is_array($data)) // if $data['current'] is NOT set --> $app=='' { list($app,$id) = explode(':',$data['current']); } From d2a87d2de4c35a9a2507a06d2883300e2c0d32a7 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 11 Aug 2011 08:41:13 +0000 Subject: [PATCH 020/472] fixed Warning: DateTime::modify(): Failed to parse time string (1234.5 second) at position 7 (s): The timezone could not be found in the database, caused by second fraction --- calendar/inc/class.calendar_ical.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php index f2c811bd39..4e3c753ead 100644 --- a/calendar/inc/class.calendar_ical.inc.php +++ b/calendar/inc/class.calendar_ical.inc.php @@ -629,7 +629,7 @@ class calendar_ical extends calendar_boupdate else { $length = ($event['end'] - $event['start']) / 2; - $rrule['UNTIL']->modify($length . ' second'); + $rrule['UNTIL']->modify((int)$length . ' second'); } if (!$tzid || $version != '1.0') From 7a6b105dc3432331ae3b331302e62ebb9a360353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Thu, 11 Aug 2011 13:53:35 +0000 Subject: [PATCH 021/472] Moved et2_DOMWidget to its own file, added getInputNode function to et2_inputWidget --- etemplate/js/et2_DOMWidget.js | 185 ++++++++++++++++++++++++++++++++ etemplate/js/et2_baseWidget.js | 2 +- etemplate/js/et2_inheritance.js | 1 + etemplate/js/et2_inputWidget.js | 14 ++- etemplate/js/et2_widget.js | 168 ----------------------------- etemplate/js/test/test_xml.html | 5 +- 6 files changed, 200 insertions(+), 175 deletions(-) create mode 100644 etemplate/js/et2_DOMWidget.js diff --git a/etemplate/js/et2_DOMWidget.js b/etemplate/js/et2_DOMWidget.js new file mode 100644 index 0000000000..e7eaa515ba --- /dev/null +++ b/etemplate/js/et2_DOMWidget.js @@ -0,0 +1,185 @@ +/** + * eGroupWare eTemplate2 - JS DOM Widget class + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + et2_widget; +*/ + +/** + * Interface for all widget classes, which are based on a DOM node. + */ +var et2_IDOMNode = new Interface({ + /** + * Returns the DOM-Node of the current widget. The return value has to be + * a plain DOM node. If you want to return an jQuery object as you receive + * it with + * + * obj = $j(node); + * + * simply return obj[0]; + * + * @param _sender The _sender parameter defines which widget is asking for + * the DOMNode. Depending on that, the widget may return different nodes. + * This is used in the grid. Normally the _sender parameter can be omitted + * in most implementations of the getDOMNode function. + * However, you should always define the _sender parameter when calling + * getDOMNode! + */ + getDOMNode: function(_sender) {} +}); + +/** + * Abstract widget class which can be inserted into the DOM. All widget classes + * deriving from this class have to care about implementing the "getDOMNode" + * function which has to return the DOM-Node. + */ +var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { + + /** + * When the DOMWidget is initialized, it grabs the DOM-Node of the parent + * object (if available) and passes it to its own "createDOMNode" function + */ + init: function(_parent, _type) { + this.parentNode = null; + + this._attachSet = { + "node": null, + "parent": null + }; + + // Call the inherited constructor + this._super.apply(this, arguments); + }, + + /** + * Detatches the node from the DOM and clears all references to the parent + * node or the dom node of this widget. + */ + destroy: function() { + + this.detatchFromDOM(); + this.parentNode = null; + this._attachSet = {}; + + this._super(); + }, + + /** + * Automatically tries to attach this node to the parent widget. + */ + onSetParent: function() { + // Check whether the parent implements the et2_IDOMNode interface. If + // yes, grab the DOM node and create our own. + if (this._parent && this._parent.implements(et2_IDOMNode)) { + this.setParentDOMNode(this._parent.getDOMNode(this)); + } + }, + + /** + * Detaches the widget from the DOM tree, if it had been attached to the + * DOM-Tree using the attachToDOM method. + */ + detatchFromDOM: function() { + + if (this._attachSet.node && this._attachSet.parent) + { + // Remove the current node from the parent node + this._attachSet.parent.removeChild(this._attachSet.node); + + // Reset the "attachSet" + this._attachSet = { + "node": null, + "parent": null + }; + + return true; + } + + return false; + }, + + /** + * Attaches the widget to the DOM tree. Fails if the widget is already + * attached to the tree or no parent node or no node for this widget is + * defined. + */ + attachToDOM: function() { + // Attach the DOM node of this widget (if existing) to the new parent + var node = this.getDOMNode(this); + if (node && this.parentNode && + (node != this._attachSet.node || + this.parentNode != this._attachSet.parent)) + { + this.parentNode.appendChild(node); + + // Store the currently attached nodes + this._attachSet = { + "node": node, + "parent": this.parentNode + }; + + return true; + } + + return false; + }, + + /** + * Set the parent DOM node of this element. If another parent node is already + * set, this widget removes itself from the DOM tree + */ + setParentDOMNode: function(_node) { + if (_node != this.parentNode) + { + // Detatch this element from the DOM tree + this.detatchFromDOM(); + + this.parentNode = _node; + + // And attatch the element to the DOM tree + this.attachToDOM(); + } + }, + + /** + * Returns the parent node. + */ + getParentDOMNode: function() { + return this.parentNode; + }, + + /** + * Sets the id of the DOM-Node. + */ + set_id: function(_value) { + + this.id = _value; + + var node = this.getDOMNode(this); + if (node) + { + if (_value != "") + { + node.setAttribute("id", _value); + } + else + { + node.removeAttribute("id"); + } + } + } + +}); + + diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js index 5f633719ec..43409be5ff 100644 --- a/etemplate/js/et2_baseWidget.js +++ b/etemplate/js/et2_baseWidget.js @@ -15,7 +15,7 @@ /*egw:uses jquery.jquery; lib/tooltip.js; - et2_widget; + et2_DOMWidget; */ /** diff --git a/etemplate/js/et2_inheritance.js b/etemplate/js/et2_inheritance.js index fd970e3865..048d1219fd 100644 --- a/etemplate/js/et2_inheritance.js +++ b/etemplate/js/et2_inheritance.js @@ -395,5 +395,6 @@ // The base class has no attributes Class.attributes = {}; + }).call(window); diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 03e1c91ccd..ec71aa8f37 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -63,9 +63,10 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { set_value: function(_value) { this._oldValue = _value; - if (this.node) + var node = this.getInputNode(); + if (node) { - $j(this.node).val(_value); + $j(node).val(_value); } }, @@ -87,10 +88,15 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { return this.getValue(); }, + getInputNode: function() { + return this.node; + }, + getValue: function() { - if (this.node) + var node = this.getInputNode(); + if (node) { - return $j(this.node).val(); + return $j(node).val(); } return this._oldValue; diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index bf6fa41d20..f8969e8ef3 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -13,8 +13,6 @@ "use strict"; /*egw:uses - jquery.jquery; - lib/tooltip.js; et2_xml; et2_common; et2_inheritance; @@ -448,170 +446,4 @@ var et2_widget = Class.extend({ }); -/** - * Interface for all widget classes, which are based on a DOM node. - */ -var et2_IDOMNode = new Interface({ - /** - * Returns the DOM-Node of the current widget. The return value has to be - * a plain DOM node. If you want to return an jQuery object as you receive - * it with - * - * obj = $j(node); - * - * simply return obj[0]; - * - * @param _sender The _sender parameter defines which widget is asking for - * the DOMNode.depending on that, the widget may return different nodes. - * This is used in the grid. Normally the _sender parameter can be omitted - * in most implementations of the getDOMNode function. - * However, you should always define the _sender parameter when calling - * getDOMNode! - */ - getDOMNode: function(_sender) {} -}); - -/** - * Abstract widget class which can be inserted into the DOM. All widget classes - * deriving from this class have to care about implementing the "getDOMNode" - * function which has to return the DOM-Node. - */ -var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { - - /** - * When the DOMWidget is initialized, it grabs the DOM-Node of the parent - * object (if available) and passes it to its own "createDOMNode" function - */ - init: function(_parent, _type) { - this.parentNode = null; - - this._attachSet = { - "node": null, - "parent": null - }; - - // Call the inherited constructor - this._super.apply(this, arguments); - }, - - /** - * Detatches the node from the DOM and clears all references to the parent - * node or the dom node of this widget. - */ - destroy: function() { - - this.detatchFromDOM(); - this.parentNode = null; - this._attachSet = {}; - - this._super(); - }, - - /** - * Automatically tries to attach this node to the parent widget. - */ - onSetParent: function() { - // Check whether the parent implements the et2_IDOMNode interface. If - // yes, grab the DOM node and create our own. - if (this._parent && this._parent.implements(et2_IDOMNode)) { - this.setParentDOMNode(this._parent.getDOMNode(this)); - } - }, - - /** - * Detaches the widget from the DOM tree, if it had been attached to the - * DOM-Tree using the attachToDOM method. - */ - detatchFromDOM: function() { - - if (this._attachSet.node && this._attachSet.parent) - { - // Remove the current node from the parent node - this._attachSet.parent.removeChild(this._attachSet.node); - - // Reset the "attachSet" - this._attachSet = { - "node": null, - "parent": null - }; - - return true; - } - - return false; - }, - - /** - * Attaches the widget to the DOM tree. Fails if the widget is already - * attached to the tree or no parent node or no node for this widget is - * defined. - */ - attachToDOM: function() { - // Attach the DOM node of this widget (if existing) to the new parent - var node = this.getDOMNode(this); - if (node && this.parentNode && - (node != this._attachSet.node || - this.parentNode != this._attachSet.parent)) - { - this.parentNode.appendChild(node); - - // Store the currently attached nodes - this._attachSet = { - "node": node, - "parent": this.parentNode - }; - - return true; - } - - return false; - }, - - /** - * Set the parent DOM node of this element. If another parent node is already - * set, this widget removes itself from the DOM tree - */ - setParentDOMNode: function(_node) { - if (_node != this.parentNode) - { - // Detatch this element from the DOM tree - this.detatchFromDOM(); - - this.parentNode = _node; - - // And attatch the element to the DOM tree - this.attachToDOM(); - } - }, - - /** - * Returns the parent node. - */ - getParentDOMNode: function() { - return this.parentNode; - }, - - /** - * Sets the id of the DOM-Node. - */ - set_id: function(_value) { - - this.id = _value; - - var node = this.getDOMNode(this); - if (node) - { - if (_value != "") - { - node.setAttribute("id", _value); - } - else - { - node.removeAttribute("id"); - } - } - } - -}); - diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index c499baaffd..902aa27392 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -7,6 +7,7 @@ <script src="../et2_inheritance.js"></script> <script src="../et2_common.js"></script> <script src="../et2_widget.js"></script> + <script src="../et2_DOMWidget.js"></script> <script src="../et2_baseWidget.js"></script> <script src="../et2_inputWidget.js"></script> <script src="../et2_template.js"></script> @@ -191,14 +192,14 @@ et2_loadXMLFromURL(file, function(_xmldoc) { - var t1 = (new Date).getTime(); - if (container != null) { container.destroy(); container = null; } + var t1 = (new Date).getTime(); + container = new et2_container(null); container.setParentDOMNode(document.getElementById("container")); container.setContentMgr(new et2_contentArrayMgr(content)); From 0fc000c955eb4554cc1b3465a872e6dee6cefeb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Thu, 11 Aug 2011 13:54:20 +0000 Subject: [PATCH 022/472] Added some documentation for the JS inheritance system and the base widget classes --- etemplate/doc/et2/documentation.pdf | Bin 0 -> 189140 bytes etemplate/doc/et2/documentation.tex | 343 ++++++++++++++++++ etemplate/doc/et2/media/class_structure.pdf | Bin 0 -> 57355 bytes etemplate/doc/et2/media/class_structure.svg | 158 ++++++++ etemplate/doc/et2/media/class_structure.zargo | Bin 0 -> 7075 bytes 5 files changed, 501 insertions(+) create mode 100644 etemplate/doc/et2/documentation.pdf create mode 100644 etemplate/doc/et2/documentation.tex create mode 100644 etemplate/doc/et2/media/class_structure.pdf create mode 100644 etemplate/doc/et2/media/class_structure.svg create mode 100644 etemplate/doc/et2/media/class_structure.zargo diff --git a/etemplate/doc/et2/documentation.pdf b/etemplate/doc/et2/documentation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e06280242d58096dbc085703cf3665bfe99f584b GIT binary patch literal 189140 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≪hN!fSHB8Z-b^ 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�Han>uXu@r%qqodH2U7@fv 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 literal 0 HcmV?d00001 diff --git a/etemplate/doc/et2/documentation.tex b/etemplate/doc/et2/documentation.tex new file mode 100644 index 0000000000..5a737cf6d7 --- /dev/null +++ b/etemplate/doc/et2/documentation.tex @@ -0,0 +1,343 @@ +\documentclass[10pt,a4paper]{report} +\usepackage[utf8x]{inputenc} +\usepackage{ucs} +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{graphicx} +\usepackage[english]{babel} + +\usepackage{parskip} +\setlength{\parindent}{0cm} +\setlength{\marginparwidth}{2.5cm} +\setlength{\marginparsep}{0.5cm} + +\usepackage{fancyhdr} +\pagestyle{fancy} +\fancyhead{} +\fancyhead[C]{\small{\textsc{ETemplate2 JavaScript Documentation}}} +\renewcommand{\headrulewidth}{0pt} + + +\title{ETemplate2 JavaScript Documentation} + +\begin{document} + +\chapter*{ETemplate2 JavaScript Documentation} + +\section*{Abstract} + +In contrast to our last approach, the new \textit{ETemplate2}-System renders the ETemplate templates completely on the client. When a template should be displayed, the URL to the template definition XET file, plus the initial content array is sent to the client. The client downloads the XET file (most of the time it will come from the browser cache), parses and renders it and sets the values of the widget according to the ones defined in the content array. + +\section*{JS Inheritance System} +Instead of using the jQuery-Class system as we did before, a new inheritance system has been introduced (see \textit{et2\_inheritance.js}). It features: +\begin{itemize} + \item Basic class inheritance + \item Support for interfaces + \item Support for attributes +\end{itemize} + +\subsection*{Basic inheritance} + +To create a class write +\begin{verbatim} +var MyClass = Class.extend([interfaces, ] functions/attributes); +\end{verbatim} +where ``interfaces'' is a single interface or an array of interfaces (see below) and functions/attributes an object containing the functions the class implements. You can extend \textit{MyClass} again by writing +\begin{verbatim} +var MyOtherClass = MyClass.extend([interfaces, ] + functions/attributes); +\end{verbatim} +The \textit{extend} function only extends the prototype and is only run once, when the JS file is intially parsed. Creating classes using the inheritance system introduces nearly no additional speed impact. + +\subsection*{Defining functions} + +\paragraph{Simple functions:} +To define a function simply add it to the functions object: +\begin{verbatim} +var MyClass = Class.extend({ + myFunction: function(_param) { + console.log("myFunction has been " + + "called with param", param); + } +}); +\end{verbatim} + +\paragraph{Override functions:} +To override functions in another class write: +\begin{verbatim} +var MyOtherClass = MyClass.extend({ + myFunction: function(_param1, _param2) { + // If this._super is not found inside + // the function, the code overhead for + // overriding functions is not created + this._super(_param1); + + console.log("And _param2 is ", _param2); + } +}); +\end{verbatim} + +\paragraph{Constructor and destructor:} +The constructor function is named ``\textit{init}''. It underlies the same overriding-mechanism as all other functions. When overriding the init function it is the best (as it probably is with all other functions too) to call the inherited super function with +\begin{verbatim} +this._super.apply(this, arguments); +\end{verbatim} +The destructor is not really part of the inheritance system but used inside the widget system. The destructor is named ``\textit{destroy}'' and should \textsc{always} be written in order to free all references to other objects, delete all DOM-Nodes and unbind all event handers. When deriving from some higher-level widget classes it will be enough to override the ``detatchFromDOM'' method and sometimes even to do nothing (see below). + + +\subsection*{Interfaces} + +\paragraph{Using interfaces:} +Interfaces can be used to check whether a class implements a certain set of functions. You can create an interface declaration by writing something like: +\begin{verbatim} +var IBreathingObject = new Interface({ + breath: function() {} +}); +\end{verbatim} +The construct with the empty function is only to make the interface declaration look syntactically pleasing, other objects are not allowed inside the interface declaration. + +To make a class extending a interface simply write +\begin{verbatim} +var MyClass = new Class.extend([IBreathingObject, ...], { + [...] +}); +\end{verbatim} +or in the case of only one interface +\begin{verbatim} +var MyClass = Class.extend(IBreathingObject, { + [...] +}); +\end{verbatim} +If a class does not implement all functions declared in the interface, it is marked as \textit{abstract} and an attempt on creating it will throw an exception. + +\paragraph{Extended type check:} +You can check whether a class/object derrives from a certain interface by using the \textit{implements} function (\textit{implements} does \textsc{not} check whether the functions are really implemented, just whether the class/object has been defined with that interface. + +Example: +\begin{verbatim} +var MyClass = Class.extend(IBreathingObject, { + [...] +}); + +MyClass.prototype.implements(IBreathingObject); // true + +var obj = new MyClass(); +obj.implements(IBreathingObject); // true +\end{verbatim} + +\textit{Implements} only checks for interfaces - if you want to check whether an object is instance of another class or implements a certain interface, you can use the \textit{instanceOf} function. In the above example: +\begin{verbatim} +obj.instanceOf(Class); // true +obj.instanceOf(MyClass); // true; +obj.instanceOf(IBreathingObject); // true +\end{verbatim} + + +\subsection*{Attributes} + +\paragraph{Basic usage:} +Attributes are used to declare a certain set of variables, getters and setters which are automatically used when (de-)serializing the object. Additionally the attributes can be used to add some documentation and type safety to the classes. To define attributes, simply add an ``attribute''-object to your class definition: +\begin{verbatim} +var MyClass = Class.extend({ + attributes: { + "color": { + "name": "Color", + "type": "string", + "default": "red", + "description": "This is just an example" + } + } +}); +\end{verbatim} + +\paragraph{Default attribute values:} +When the object is created, after the "init" functions have been called, the default value of the attribute will be set, without overriding existing object-variables which have the same name as the attribute. If no default is given, the default value defaults to an default value defined for the given type. The type defaults to ``any'' which means, that no type-check is done (see Table \ref{tbl:attr_types}). If you do not wish the default value to be automatically set, set the default value to the ``et2\_no\_default'' object. + +\begin{table} + \begin{center} + \begin{tabular}{r | l l} + & \textbf{default value} & \textbf{special conversions} \\ + \hline + string & \texttt{""} & \\ + integer & \texttt{0} & strings are parsed to ints \\ + floats & \texttt{0.0} & strings are parsed to floats \\ + boolean & \texttt{false} & the strings \texttt{"false"}, \texttt{"true"}, and \texttt{""} \\ + any & \texttt{null} & \\ + \end{tabular} + \end{center} + \label{tbl:attr_types} + \caption{Overview over all available attribute types, their standard default values and special conversions} +\end{table} + +\paragraph{Setters and getters:} +You can manually \textit{set} an attribute by calling the function +\begin{verbatim} +obj.setAttribute(name, value); +\end{verbatim} +\texttt{setAttribute} checks for the existance of the attribute with the given name and typechecks the given value. When setting an attribute, the code checks, whether a setter function named ``\texttt{set\_[name]}'' is found. If yes, the function is called with the given value as parameter. If the function does not exist, the following code is executed +\begin{verbatim} +obj[name] = value; +\end{verbatim} + +You can manually \textit{get} an attribute by calling the function +\begin{verbatim} +obj.getAttribute(name); +\end{verbatim} +Just like the \texttt{setAttribute} function, \texttt{getAttribute} searches for a getter function named ``\texttt{get\_[name]}'' first and simply returns \texttt{obj[name]} if the getter function is not found. + +\paragraph{Ignoring attributes:} +Sometimes you may want the \texttt{setAttribute} function to simply ignore a certain attribute - in ETemplate2 for example, the \textit{span} attribute is ignored, as it is read by the grid class. To mark an attribute as ``ignored'' simply add: +\begin{verbatim} +"ignore": true +\end{verbatim} +to the attribute definition. Setting an attribute to be ignored can also be done at runtime - but this only effects objects of exactly the same class, as attribute definitions are copied between prototypes and not referenced. + +\paragraph{Attribute inheritance:} +All classes automatically inherit the attributes of their parent class. You can change the attribute definition for a new class by simply defining a new entry for it. The entry can also be partial. So in our above example, we could simply change the color-attribute to be an integer value, as e.g. the new class directly uses the binary-representation of the color: +\begin{verbatim} +var MyOtherClass = MyClass.extend({ + attributes: { + "color": { + "type": "integer" + } + } +}); +\end{verbatim} + +\paragraph{JS Dependencies:} +The JS dependency management is done on the server-side by EGW, so it cannot be used or tested when using the standalone test method (see below). However, you can mark dependencies by using the +\begin{verbatim} +/*egw:uses + jquery.jquery; + et2_baseWidget; +*/ +\end{verbatim} +syntax. Note that this comment has to start in the first 16 lines. More information on that topic can be found in the preamble of + +\begin{center}\texttt{class.egw\_include\_mgr.inc.php}\end{center} + +in phpgwapi. + + +\section*{ETemplate2 class structure} + +\subsection*{Overview} +The following UML class diagram (see figure \ref{fig:uml}) gives an overview over the \textit{ETemplate2} class structure. Basically the widgets form a tree and when loading the XET-file, the widget objects are automatically created according to the XML-Tag. Widget classes can be registered using the +\begin{verbatim} +et2_register_widget(class_prototype, array_of_tagnames); +\end{verbatim} +function. + +\begin{figure} + \begin{center} + \includegraphics[scale=0.6]{class_structure.pdf} + \end{center} + \caption{Overview over the ETemplate2 JavaScript side class structure. The blue classes are the ones you normally derrive other classes from.} + \label{fig:uml} +\end{figure} + +\subsection*{et2\_widget} + +\paragraph{Overview:} +\textit{et2\_widget} is the base widget class. It spans the widget tree and introduces features for managing the child widgets, like adding and destryoing them. The constructor takes to parameters, the parent and the actual tag name the widget was created for. The tag name is stored in the ``type'' object-variable. The widget automatically adds itself to the parent children list and removes itself from the list when it is destroyed. + +\paragraph{XML-Handling:} +\textit{et2\_widget} has three important functions for XML handling: +\begin{verbatim} +et2_widget::loadFromXML(_node) +\end{verbatim} +Reads the attributes for this widget from the given XML-DOM-Node. All child widgets are created and the LoadFromXML-function is recursively called for them. + +\begin{verbatim} +et2_widget::loadAttributes(_attrs) +\end{verbatim} +Is called by \texttt{LoadFromXML} with the XML-DOM-Attributes object. The base implementation simply calls the ``\texttt{setAttribute}'' function for every attribute found. + +\begin{verbatim} +et2_widget::loadContent(_text) +\end{verbatim} +Is called whenever \texttt{loadFromXML} finds a text-node inside the XML data. The base implementation does nothing when reaching a text node. + +\paragraph{Cloning widgets:} +\textit{et2\_widget} introduces a mechanism which can be used to clone widgets and to assign the attributes of other widgets to them. The clone function +\begin{verbatim} +et2_widget::clone(_parent); +\end{verbatim} +takes the parent widget the cloned widget should be added to. + +\paragraph{Updating the widget:} +\textit{et2\_widget} has a function called \texttt{update} which reads all attributes and setts them again. +\begin{verbatim} +et2_widget::update() +\end{verbatim} +This function is e.g. important if you replace the DOM-Node of a widget (see below) and want to call all attribute setters. The \texttt{upate} function does that automatically. + +\subsection*{et2\_IDOMNode interface} +The \textit{et2\_IDOMNode} interface declares the +\begin{verbatim} +et2_IDOMNode::getDOMNode(_sender) +\end{verbatim} +function, which has to be implemented by all widgets which have a representation in the HTML-DOM-Tree. \texttt{getDOMNode} should return the DOM-Node of the current widget. The return value has to be a plain DOM node, not a jQuery object. The \texttt{\_sender} parameter defines which widget is asking for the DOMNode. Depending on that, the widget may return different nodes. This is used in the grid or the tab. Normally the \_sender parameter can be omitted in most implementations of the getDOMNode function. However, you should always provide the \texttt{\_sender} parameter when calling \texttt{getDOMNode}! + +\subsection*{et2\_DOMWidget} +The \textit{et2\_DOMWidget} class is derrived from \textit{et2\_IDOMNode} and \textit{et2\_widget} without implementing the \texttt{getDOMNode} funcition. It introduces an mechanism which automatically inserts the DOM-Node of this widget into the DOM-Node of the parent widget (if the parent widget implements \textit{et2\_IDOMWidget}. The two functions +\begin{verbatim} +et2_DOMWidget::attachToDOM() +et2_DOMWidget::detatchFromDOM() +\end{verbatim} +have to be extended by any class which derrives from \textit{et2\_DOMwidget} and attaches event-handlers to the DOM. All event handlers have to be detached in the \texttt{detatchFromDOM} function and (re-)attached in the \texttt{attachToDOM} function. See the \textit{et2\_baseWidget} statustext-code for an example. The \textit{et2\_DOMWidget} also automatically sets the \textit{id} property of its DOM-Node. + +Directly derrive a widget from the \textit{et2\_DOMWidget} class, if you have to return different DOM-Nodes depending on the widget which asked for the DOM-Node and therefore need an own implementation of the \texttt{getDOMNode} function. + +\subsection*{et2\_baseWidget} +\textit{et2\_baseWidget}, derrived from \textit{et2\_DOMWidget} is in most cases the best choice whe implementing an widget. It introduces the function +\begin{verbatim} +et2_DOMWidget::setDOMNode(_node) +\end{verbatim} +and implements \texttt{getDOMNode}. Calling \texttt{setDOMNode} detatches the current node from the DOM-Tree and attaches the given node. Very basic widgets only have to call \texttt{setDOMNode} once in the constructor. Widgets which can change their underlying DOM-Node can call \texttt{setDOMNode} e.g. from setter functions. Remember that you have to reapply all changes you've made to the DOM-Node, so probably you'll have to call \texttt{update()} after having set the new DOM-Node. + +\subsection*{et2\_IInput Interface} +\textit{et2\_IInput} is the base interface for all widgets which can return a value. The three functions, which have to be implemented are rather self-explanatory: +\begin{verbatim} +et2_IInput::getValue() +et2_IInput::isDirty() +et2_IInput::resetDirty() +\end{verbatim} + +\subsection*{et2\_inputWidget} +The \textit{et2\_inputWidget} derrives from \textit{et2\_baseWidget} and \textit{et2\_IInput}. This class automatically reads its content from the content-array when its id is set (behaviour might be changed). It has a function +\begin{verbatim} +et2_inputWidget::getInputWidget() +\end{verbatim} +which as a default returns the DOM-Node of the widget. In more complicated widgets where the base DOM-Node is not equally to the input-DOM-Node you can override this function. + +The setters and getters for the value attribute of the widget utilize the jQuery ``\texttt{val()}'' function for the DOM-Node returned by +\begin{verbatim} +et2_inputWidget::getInputWidget() +\end{verbatim} + +In some complicated cases it might be better not to derrive directly from \texttt{et2\_inputWidget} but from \texttt{et2\_baseWidget} or even \texttt{et\_DOMWidget} and simply implement \texttt{et2\_IInput}. + +\section*{Conventions and testing} + +New widgets should be in their own JS-File named like the widget. They can by easily tested by including the JS-File in \texttt{test\_xml.html} found in the ``test'' folder. You can simply add new tests using the same scheme as with the existing tests. + +Please \textsc{always} test, whether your widget also works properly if it is wrapped in a template, as this causes the widget to be cloned, which creates a completely different situation in comparison to reading the widget directly from XML. A test XET-File for this may look like that: +\begin{verbatim} +<overlay> + <!-- Test without template --> + <mywidget/> + + <!-- Test with template --> + <template id="test"> + <mywidget/> + </template> + <!-- Reference the template above --> + <template id="test"/> +</overlay> +\end{verbatim} + +There are also many more or less helpfull debug messages in the code. You can regulate the amout of messages by setting the \texttt{ET2\_DEBUGLEVEL} variable in \textit{et2\_common.js}. + +\end{document} \ No newline at end of file diff --git a/etemplate/doc/et2/media/class_structure.pdf b/etemplate/doc/et2/media/class_structure.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d38521ce98fc57e9ac879b3439a0ff68002496a5 GIT binary patch literal 57355 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 b@RzQxZsu^ezZeP#@$m5CFfz)kE8zS;W;ts5 literal 0 HcmV?d00001 diff --git a/etemplate/doc/et2/media/class_structure.svg b/etemplate/doc/et2/media/class_structure.svg new file mode 100644 index 0000000000..5e2587f559 --- /dev/null +++ b/etemplate/doc/et2/media/class_structure.svg @@ -0,0 +1,158 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg height="911" version="1.1" width="602" xmlns="http://www.w3.org/2000/svg"> +<rect fill="#c8c8ff" height="67" stroke="#c8c8ff" stroke-width="1" width="78" x="49" y="14"/> +<rect fill="none" height="67" stroke="#000000" stroke-width="1" width="78" x="49" y="14"/> +<text font-family="Dialog" font-size="12" x="54" y="27"> +et2_widget</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="78" x="49" y="37"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="78" x="49" y="58"/> +<rect fill="#c8c8ff" height="85" stroke="#c8c8ff" stroke-width="1" width="108" x="33" y="222"/> +<rect fill="none" height="85" stroke="#000000" stroke-width="1" width="108" x="33" y="222"/> +<text font-family="Dialog" font-size="12" font-style="italic" x="38" y="235"> +et2_DOMWidget</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="108" x="33" y="245"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="108" x="33" y="275"/> +<rect fill="#ffffff" height="67" stroke="#ffffff" stroke-width="1" width="150" x="297" y="22"/> +<rect fill="none" height="67" stroke="#000000" stroke-width="1" width="150" x="297" y="22"/> +<text font-family="Dialog" font-size="12" x="321" y="54"> +et2_IDOMWidget</text> +<text font-family="Dialog" font-size="12" x="324" y="36"> +<<interface>></text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="150" x="297" y="64"/> +<text font-family="Dialog" font-size="12" x="301" y="78"> +getDOMNode(_sender)</text> +<polyline fill="none" points="93,222 93,81" stroke="#000000" stroke-width="1"/> +<polygon fill="#ffffff" points="93,81 100,93 86,93" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="93,81 100,93 86,93" stroke="#000000" stroke-width="1"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="141" x2="144" y1="222" y2="219"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="148" x2="152" y1="216" y2="213"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="156" x2="160" y1="210" y2="206"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="163" x2="167" y1="203" y2="200"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="171" x2="175" y1="197" y2="193"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="179" x2="182" y1="190" y2="187"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="186" x2="190" y1="184" y2="180"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="194" x2="198" y1="177" y2="174"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="201" x2="205" y1="171" y2="167"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="209" x2="213" y1="164" y2="161"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="217" x2="220" y1="158" y2="154"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="224" x2="228" y1="151" y2="148"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="232" x2="236" y1="145" y2="141"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="239" x2="243" y1="138" y2="135"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="247" x2="251" y1="132" y2="128"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="255" x2="258" y1="125" y2="122"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="262" x2="266" y1="119" y2="115"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="270" x2="274" y1="112" y2="109"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="277" x2="281" y1="106" y2="102"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="285" x2="289" y1="99" y2="96"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="293" x2="297" y1="93" y2="89"/> +<polygon fill="#ffffff" points="297,89 292,102 283,91" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="297,89 292,102 283,91" stroke="#000000" stroke-width="1"/> +<text font-family="Dialog" font-size="12" x="149" y="134"> +<<realize>></text> +<rect fill="#c8c8ff" height="93" stroke="#c8c8ff" stroke-width="1" width="137" x="25" y="390"/> +<rect fill="none" height="93" stroke="#000000" stroke-width="1" width="137" x="25" y="390"/> +<text font-family="Dialog" font-size="12" x="43" y="403"> +et2_baseWidget</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="137" x="25" y="413"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="137" x="25" y="438"/> +<text font-family="Dialog" font-size="12" x="29" y="452"> +getDOMNode()</text> +<text font-family="Dialog" font-size="12" x="29" y="468"> +setDOMNode(_node)</text> +<polyline fill="none" points="89,390 89,307" stroke="#000000" stroke-width="1"/> +<polygon fill="#ffffff" points="89,307 96,319 82,319" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="89,307 96,319 82,319" stroke="#000000" stroke-width="1"/> +<rect fill="#ffffff" height="99" stroke="#ffffff" stroke-width="1" width="105" x="289" y="630"/> +<rect fill="none" height="99" stroke="#000000" stroke-width="1" width="105" x="289" y="630"/> +<text font-family="Dialog" font-size="12" x="310" y="662"> +et2_IInput</text> +<text font-family="Dialog" font-size="12" x="293" y="644"> +<<interface>></text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="105" x="289" y="672"/> +<text font-family="Dialog" font-size="12" x="293" y="686"> +getValue()</text> +<text font-family="Dialog" font-size="12" x="293" y="702"> +isDirty()</text> +<text font-family="Dialog" font-size="12" x="293" y="718"> +resetDirty()</text> +<rect fill="#c8c8ff" height="106" stroke="#c8c8ff" stroke-width="1" width="112" x="33" y="742"/> +<rect fill="none" height="106" stroke="#000000" stroke-width="1" width="112" x="33" y="742"/> +<text font-family="Dialog" font-size="12" x="38" y="755"> +et2_inputWidget</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="112" x="33" y="765"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="112" x="33" y="788"/> +<text font-family="Dialog" font-size="12" x="37" y="802"> +getValue()</text> +<text font-family="Dialog" font-size="12" x="37" y="818"> +isDirty()</text> +<text font-family="Dialog" font-size="12" x="37" y="834"> +resetDirty()</text> +<polyline fill="none" points="89,742 89,483" stroke="#000000" stroke-width="1"/> +<polygon fill="#ffffff" points="89,483 96,495 82,495" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="89,483 96,495 82,495" stroke="#000000" stroke-width="1"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="145" x2="150" y1="742" y2="742"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="155" x2="160" y1="742" y2="741"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="165" x2="170" y1="741" y2="740"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="175" x2="180" y1="740" y2="739"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="185" x2="190" y1="739" y2="738"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="195" x2="200" y1="738" y2="738"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="205" x2="210" y1="737" y2="737"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="215" x2="220" y1="736" y2="736"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="225" x2="230" y1="735" y2="735"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="235" x2="240" y1="734" y2="734"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="245" x2="250" y1="733" y2="733"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="255" x2="260" y1="733" y2="732"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="265" x2="270" y1="732" y2="731"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="275" x2="280" y1="731" y2="730"/> +<line fill="#000000" stroke="#000000" stroke-width="1" x1="285" x2="289" y1="730" y2="729"/> +<polygon fill="#ffffff" points="289,729 277,737 276,723" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="289,729 277,737 276,723" stroke="#000000" stroke-width="1"/> +<text font-family="Dialog" font-size="12" x="175" y="724"> +<<realize>></text> +<rect fill="#ffffff" height="67" stroke="#ffffff" stroke-width="1" width="66" x="345" y="310"/> +<rect fill="none" height="67" stroke="#000000" stroke-width="1" width="66" x="345" y="310"/> +<text font-family="Dialog" font-size="12" x="352" y="323"> +et2_grid</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="66" x="345" y="333"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="66" x="345" y="354"/> +<rect fill="#ffffff" height="67" stroke="#ffffff" stroke-width="1" width="80" x="465" y="310"/> +<rect fill="none" height="67" stroke="#000000" stroke-width="1" width="80" x="465" y="310"/> +<text font-family="Dialog" font-size="12" x="470" y="323"> +et2_tabbox</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="80" x="465" y="333"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="80" x="465" y="354"/> +<polyline fill="none" points="505,310 505,278 141,278" stroke="#000000" stroke-width="1"/> +<polygon fill="#ffffff" points="141,278 153,271 153,285" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="141,278 153,271 153,285" stroke="#000000" stroke-width="1"/> +<rect fill="#ffffff" height="67" stroke="#ffffff" stroke-width="1" width="107" x="481" y="518"/> +<rect fill="none" height="67" stroke="#000000" stroke-width="1" width="107" x="481" y="518"/> +<text font-family="Dialog" font-size="12" x="486" y="531"> +et2_description</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="107" x="481" y="541"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="107" x="481" y="562"/> +<polyline fill="none" points="529,518 529,462 162,462" stroke="#000000" stroke-width="1"/> +<polygon fill="#ffffff" points="162,462 174,455 174,469" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="162,462 174,455 174,469" stroke="#000000" stroke-width="1"/> +<rect fill="#ffffff" height="67" stroke="#ffffff" stroke-width="1" width="83" x="369" y="830"/> +<rect fill="none" height="67" stroke="#000000" stroke-width="1" width="83" x="369" y="830"/> +<text font-family="Dialog" font-size="12" x="374" y="843"> +et2_textbox</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="83" x="369" y="853"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="83" x="369" y="874"/> +<polyline fill="none" points="409,830 409,798 145,798" stroke="#000000" stroke-width="1"/> +<polygon fill="#ffffff" points="145,798 157,791 157,805" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="145,798 157,791 157,805" stroke="#000000" stroke-width="1"/> +<polyline fill="none" points="385,310 385,278 141,278" stroke="#000000" stroke-width="1"/> +<polygon fill="#ffffff" points="141,278 153,271 153,285" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="141,278 153,271 153,285" stroke="#000000" stroke-width="1"/> +<rect fill="#ffffff" height="67" stroke="#ffffff" stroke-width="1" width="79" x="345" y="518"/> +<rect fill="none" height="67" stroke="#000000" stroke-width="1" width="79" x="345" y="518"/> +<text font-family="Dialog" font-size="12" x="350" y="531"> +et2_button</text> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="79" x="345" y="541"/> +<rect fill="#000000" height="1" stroke="#000000" stroke-width="1" width="79" x="345" y="562"/> +<polyline fill="none" points="385,518 385,462 162,462" stroke="#000000" stroke-width="1"/> +<polygon fill="#ffffff" points="162,462 174,455 174,469" stroke="#ffffff" stroke-width="1"/> +<polygon fill="none" points="162,462 174,455 174,469" stroke="#000000" stroke-width="1"/> +</svg> diff --git a/etemplate/doc/et2/media/class_structure.zargo b/etemplate/doc/et2/media/class_structure.zargo new file mode 100644 index 0000000000000000000000000000000000000000..acfcbea79fc8b2c4799438de57df8fbffa7cefe5 GIT binary patch literal 7075 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 literal 0 HcmV?d00001 From 74498fd3204e1bd1d0e5b3a21947c63bc8c2ec8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Thu, 11 Aug 2011 13:54:46 +0000 Subject: [PATCH 023/472] fixed path in tex file --- etemplate/doc/et2/documentation.pdf | Bin 189140 -> 189402 bytes etemplate/doc/et2/documentation.tex | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/etemplate/doc/et2/documentation.pdf b/etemplate/doc/et2/documentation.pdf index e06280242d58096dbc085703cf3665bfe99f584b..739e642e097d0db7f1045a1a06d068f086b50b99 100644 GIT binary patch delta 24405 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 BNa6qh delta 24226 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 diff --git a/etemplate/doc/et2/documentation.tex b/etemplate/doc/et2/documentation.tex index 5a737cf6d7..4ac8e59881 100644 --- a/etemplate/doc/et2/documentation.tex +++ b/etemplate/doc/et2/documentation.tex @@ -231,7 +231,7 @@ function. \begin{figure} \begin{center} - \includegraphics[scale=0.6]{class_structure.pdf} + \includegraphics[scale=0.6]{media/class_structure.pdf} \end{center} \caption{Overview over the ETemplate2 JavaScript side class structure. The blue classes are the ones you normally derrive other classes from.} \label{fig:uml} From 2a95927fc8d7549d45d1ae07b18264fd4adef8d0 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 11 Aug 2011 19:04:40 +0000 Subject: [PATCH 024/472] added update from 1.8.002 --- phpgwapi/setup/tables_update.inc.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/phpgwapi/setup/tables_update.inc.php b/phpgwapi/setup/tables_update.inc.php index 618c6b1da0..a0d38b4ebf 100644 --- a/phpgwapi/setup/tables_update.inc.php +++ b/phpgwapi/setup/tables_update.inc.php @@ -28,6 +28,10 @@ function phpgwapi_upgrade1_8_001() { return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.9.001'; } +function phpgwapi_upgrade1_8_002() +{ + return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.9.001'; +} /** * Add index to improve import of contacts using a custom field as primary key From b9bb6280e3be56fc3bb0b9d8771f7c516386779a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Fri, 12 Aug 2011 12:15:44 +0000 Subject: [PATCH 025/472] Added getValues() function to the base widget which creates an associative 'array' with all form values. --- etemplate/js/et2_grid.js | 32 +++++++++++++++++++++--- etemplate/js/et2_inputWidget.js | 4 ++- etemplate/js/et2_template.js | 13 ++++++++++ etemplate/js/et2_widget.js | 34 ++++++++++++++++++++++++++ etemplate/js/test/et2_test_textbox.xet | 8 +++--- 5 files changed, 82 insertions(+), 9 deletions(-) diff --git a/etemplate/js/et2_grid.js b/etemplate/js/et2_grid.js index b129126fe4..9d4fde9005 100644 --- a/etemplate/js/et2_grid.js +++ b/etemplate/js/et2_grid.js @@ -440,6 +440,9 @@ var et2_grid = et2_DOMWidget.extend({ assign: function(_obj) { if (_obj instanceof et2_grid) { + // Remember all widgets which have already been instanciated + var instances = []; + // Copy the cells array of the other grid and clone the widgets // inside of it var cells = new Array(_obj.cells.length); @@ -451,10 +454,32 @@ var et2_grid = et2_DOMWidget.extend({ for (var x = 0; x < _obj.cells[y].length; x++) { var srcCell = _obj.cells[y][x]; + + var widget = null; + if (srcCell.widget) + { + // Search for the widget inside the instances array + for (var i = 0; i < instances.length; i++) + { + if (instances[i].srcWidget == srcCell.widget) + { + widget = instances[i].widget; + break; + } + } + + if (widget == null) + { + widget = srcCell.widget.clone(this, srcCell.widget.type); + instances.push({ + "widget": widget, + "srcWidget": srcCell.widget + }); + } + } + cells[y][x] = { - "widget": (srcCell.widget ? - srcCell.widget.clone(this, srcCell.widget.type) : - null), + "widget": widget, "td": null, "colSpan": srcCell.colSpan, "rowSpan": srcCell.rowSpan @@ -464,7 +489,6 @@ var et2_grid = et2_DOMWidget.extend({ // Create the table this.createTableFromCells(cells); - } else { diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index ec71aa8f37..00553f9f02 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -96,7 +96,9 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { var node = this.getInputNode(); if (node) { - return $j(node).val(); + var val = $j(node).val(); + + return val; } return this._oldValue; diff --git a/etemplate/js/et2_template.js b/etemplate/js/et2_template.js index a9c25a9dd9..357689a795 100644 --- a/etemplate/js/et2_template.js +++ b/etemplate/js/et2_template.js @@ -142,6 +142,19 @@ var et2_template = et2_DOMWidget.extend({ getDOMNode: function(_fromProxy) { return this.div; + }, + + getValues: function(_target) { + if (this.proxiedTemplate) + { + return this.proxiedTemplate.getValues(_target); + } + else if (!this.isProxied) + { + return this._super(_target); + } + + return _target; } }); diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index f8969e8ef3..8156c4385d 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -442,6 +442,40 @@ var et2_widget = Class.extend({ } return null; + }, + + /** + * Fetches all input element values and returns them in an associative + * array. Widgets which introduce namespacing can use the internal _target + * parameter to add another layer. + * + * @param _target is used internally and should no be supplied. + */ + getValues: function(_target) { + if (typeof _target == "undefined") + { + _target = {}; + } + + // Add the value of this element to the result object + if (this.implements(et2_IInput)) + { + if (typeof _target[this.id] != "undefined") + { + et2_debug("error", "Overwriting value of '" + this.id + + "', id exists twice!"); + } + + _target[this.id] = this.getValue(); + } + + // Store the values of the children in the target array + for (var i = 0; i < this._children.length; i++) + { + this._children[i].getValues(_target); + } + + return _target; } }); diff --git a/etemplate/js/test/et2_test_textbox.xet b/etemplate/js/test/et2_test_textbox.xet index 663b17f518..c9e73a7c6f 100644 --- a/etemplate/js/test/et2_test_textbox.xet +++ b/etemplate/js/test/et2_test_textbox.xet @@ -1,11 +1,11 @@ <?xml version="1.0"?> <overlay> - <textbox value="This is a single line textbox." statustext="Write something here!"/> - <textbox multiline="true" value="This is a multi line textbox."/> + <textbox id="test1" value="This is a single line textbox." statustext="Write something here!"/> + <textbox id="test2" multiline="true" value="This is a multi line textbox."/> <template id="testbox"> - <textbox value="This is a single line textbox." statustext="And something else here!"/> - <textbox multiline="true" value="This is a multi line textbox."/> + <textbox id="test3" value="This is a single line textbox." statustext="And something else here!"/> + <textbox id="test4" multiline="true" value="This is a multi line textbox."/> </template> <template id="testbox"/> From 89230b86cf2bf04fd0d1d706015a8d572a331f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Fri, 12 Aug 2011 15:26:08 +0000 Subject: [PATCH 026/472] Added functions to expand names and a basic implementation for 'disabled' --- etemplate/js/et2_DOMWidget.js | 27 ++++ etemplate/js/et2_contentArrayMgr.js | 170 +++++++++++++++++++- etemplate/js/et2_inputWidget.js | 17 +- etemplate/js/et2_widget.js | 24 ++- etemplate/js/test/et2_test_expressions.json | 4 + etemplate/js/test/et2_test_expressions.xet | 6 + etemplate/js/test/test_xml.html | 2 + 7 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 etemplate/js/test/et2_test_expressions.json create mode 100644 etemplate/js/test/et2_test_expressions.xet diff --git a/etemplate/js/et2_DOMWidget.js b/etemplate/js/et2_DOMWidget.js index e7eaa515ba..5071719d0e 100644 --- a/etemplate/js/et2_DOMWidget.js +++ b/etemplate/js/et2_DOMWidget.js @@ -46,6 +46,15 @@ var et2_IDOMNode = new Interface({ */ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { + attributes: { + "disabled": { + "name": "Visible", + "type": "boolean", + "description": "Defines whether this widget is visible.", + "default": false + } + }, + /** * When the DOMWidget is initialized, it grabs the DOM-Node of the parent * object (if available) and passes it to its own "createDOMNode" function @@ -58,6 +67,8 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { "parent": null }; + this.disabled = false; + // Call the inherited constructor this._super.apply(this, arguments); }, @@ -178,6 +189,22 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { node.removeAttribute("id"); } } + }, + + set_disabled: function(_value) { + if (this.node) + { + this.diabled = _value; + + if (_value) + { + $j(this.node).hide(); + } + else + { + $j(this.node).show(); + } + } } }); diff --git a/etemplate/js/et2_contentArrayMgr.js b/etemplate/js/et2_contentArrayMgr.js index 20ce93fd95..e6cb50759d 100644 --- a/etemplate/js/et2_contentArrayMgr.js +++ b/etemplate/js/et2_contentArrayMgr.js @@ -24,7 +24,33 @@ function et2_contentArrayMgr(_data, _parentMgr) this.parentMgr = _parentMgr; // Hold a reference to the data + if (typeof _data == "undefined" || !_data) + { + et2_debug("error", "Invalid data passed to content array manager!"); + _data = {}; + } + this.data = _data; + + // Holds information about the current perspective + this.perspectiveData = { + "key": null, + "col": 0, + "row": 0 + } +} + +/** + * Returns the root content array manager object + */ +et2_contentArrayMgr.prototype.getRoot = function() +{ + if (this.parentMgr != null) + { + return this.parentMgr.getRoot(); + } + + return this; } et2_contentArrayMgr.prototype.getValueForID = function(_id) @@ -37,8 +63,148 @@ et2_contentArrayMgr.prototype.getValueForID = function(_id) return null; } -et2_contentArrayMgr.prototype.openPerspective = function(_rootId) +/** + * Get array entry is the equivalent to the boetemplate get_array function. + * It returns a reference to the (sub) array with the given key. This also works + * for keys using the ETemplate referencing scheme like a[b][c] + * + * @param _key is the string index, may contain sub-indices like a[b] + * @param _referenceInto if true none-existing sub-arrays/-indices get created + * to be returned as reference, else false is returned. Defaults to false + * @param _skipEmpty returns false if _key is not present in this content array. + * Defaults to false. + */ +et2_contentArrayMgr.prototype.getEntry = function(_key, _referenceInto, + _skipEmpty) { - return new et2_contentArrayMgr(this._data[_rootId], this); + if (typeof _referenceInto == "undefined") + { + _referenceInto = false; + } + + if (typeof _skipEmpty == "undefined") + { + _skipEmpty = false; + } + + // Parse the given key by removing the "]"-chars and splitting at "[" + var indexes = _key.replace(/]/g,'').split('['); + + var entry = this.data; + for (var i = 0; i < indexes.length; i++) + { + // Abort if the current entry is not an object (associative array) and + // we should descend further into it. + var isObject = entry instanceof Object; + if (!isObject && !_referenceInto) + { + return false; + } + + // Check whether the entry actually exists + var idx = indexes[i]; + if (_skipEmpty && (!isObject || typeof entry[idx] == "undefined")) + { + return false; + } + + entry = entry[idx]; + } + + return entry; +} + +/** + * Equivaltent to the boetemplate::expand_name function. + * + * Expands variables inside the given identifier to their values inside the + * content array. + */ +et2_contentArrayMgr.prototype.expandName = function(_ident) +{ + // Check whether the identifier refers to an index in the content array + var is_index_in_content = _ident.charAt(0) == '@'; + + // Check whether "$" occurs in the given identifier + var pos_var = _ident.indexOf('$'); + if (pos_var >= 0) + { + // TODO + } + + if (is_index_in_content) + { + // If an additional "@" is specified, this means that we have to return + // the entry from the root element + if (_ident.charAt(1) == '@') + { + _ident = this.getRoot().getEntry(_ident.substr(2)); + } + + _ident = this.getEntry(_ident.substr(1)); + } + + return _ident; +} + +et2_contentArrayMgr.prototype.parseBoolExpression = function(_expression) +{ + // If the first char of the expression is a '!' this means, that the value + // is to be negated. + if (_expression.charAt(0) == '!') + { + return !this.parseBoolExpression(_expression.substr(1)); + } + + // Split the expression at a possible "=" + var parts = _expression.split('='); + + // Expand the first value + var val = this.expandName(parts[0]); + + // If a second expression existed, test that one + if (typeof parts[1] != "undefined") + { + // Expand the second value + var checkVal = this.expandName(parts[1]); + + // Values starting with / are treated as regular expression. It is + // checked whether the first value matches the regular expression + if (checkVal.charAt(0) == '/') + { + return (new RegExp(checkVal.substr(1, checkVal.length - 2))) + .match(val) ? true : false; + } + + // Otherwise check for simple equality + return val == checkVal; + } + + return val != '' && (typeof val != "string" || val.toLowerCase() != "false"); +} + +et2_contentArrayMgr.prototype.openPerspective = function(_root, _col, _row) +{ + // Get the root node + var root = typeof _root == "string" ? this.data[_root] : + (_root == null ? this.data : _root); + + // Create a new content array manager with the given root + var mgr = new et2_contentArrayMgr(root, this); + + // Set the root key + if (typeof _root == "string") + { + mgr.perspectiveData.key == _root; + } + + // Set the _col and _row parameter + if (typeof _col != "undefined" && typeof _row != "undefined") + { + mgr.perspectiveData.col = _col; + mgr.perspectiveData.row = _row; + } + + return mgr; } diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 00553f9f02..aa11b061af 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -71,8 +71,23 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { }, set_id: function(_value) { - this._super.apply(this, arguments); + this.id = _value; + // Set the id of the input node + var node = this.getInputNode(); + if (node) + { + if (_value != "") + { + node.setAttribute("id", _value); + } + else + { + node.removeAttribute("id"); + } + } + + // Set the value for this element var mgr = this.getContentMgr(); if (_value != '' && mgr != null) { diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 8156c4385d..efd1fab72f 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -381,6 +381,7 @@ var et2_widget = Class.extend({ loadAttributes: function(_attrs) { for (var i = 0; i < _attrs.length; i++) { + // Special handling for the legacy options if (_attrs[i].name == "options") { // Parse the legacy options @@ -393,7 +394,28 @@ var et2_widget = Class.extend({ } else { - this.setAttribute(_attrs[i].name, _attrs[i].value); + var attrName = _attrs[i].name; + var attrValue = _attrs[i].value; + + if (typeof this.attributes[attrName] != "undefined") + { + var attr = this.attributes[attrName]; + + // If the attribute is marked as boolean, parse the + // expression as bool expression. + if (attr.type == "boolean") + { + attrValue = this.getContentMgr() + .parseBoolExpression(attrValue); + } + else + { + attrValue = this.getContentMgr().expandName(attrValue); + } + } + + // Set the attribute + this.setAttribute(attrName, attrValue); } } }, diff --git a/etemplate/js/test/et2_test_expressions.json b/etemplate/js/test/et2_test_expressions.json new file mode 100644 index 0000000000..fcdf1b47c7 --- /dev/null +++ b/etemplate/js/test/et2_test_expressions.json @@ -0,0 +1,4 @@ +var expression_test_data = { + "display_text": "true" +}; + diff --git a/etemplate/js/test/et2_test_expressions.xet b/etemplate/js/test/et2_test_expressions.xet new file mode 100644 index 0000000000..eb796e1a03 --- /dev/null +++ b/etemplate/js/test/et2_test_expressions.xet @@ -0,0 +1,6 @@ +<?xml version="1.0"?> +<overlay> + <template id="test"> + <description disabled="!@display_text" value="Dies ist nur ein test!" /> + </template> +</overlay> diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 902aa27392..b8bd833604 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -21,6 +21,7 @@ <script src="../lib/tooltip.js"></script> <script src="et2_test_timesheet_edit.json"></script> + <script src="et2_test_expressions.json"></script> <style type="text/css"> body { @@ -177,6 +178,7 @@ <a href="#" onclick="open_xet('et2_test_tabbox.xet');">Tabs test</a> <a href="#" onclick="open_xet('et2_test_textbox.xet');">Textbox test</a> <a href="#" onclick="open_xet('et2_test_description.xet');">Description test</a> + <a href="#" onclick="open_xet('et2_test_expressions.xet', expression_test_data);">Expression test</a> </div> <div class="header">ETemplate2 container:</div> <div id="time"></div> From 8a420df72139d543620d279fd878073dc8fc4541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Fri, 12 Aug 2011 15:35:27 +0000 Subject: [PATCH 027/472] Moved basic functions of 'Class' from the 'add*Functions' functions to Class.prototype --- etemplate/js/et2_inheritance.js | 214 ++++++++++++++++---------------- 1 file changed, 110 insertions(+), 104 deletions(-) diff --git a/etemplate/js/et2_inheritance.js b/etemplate/js/et2_inheritance.js index 048d1219fd..9e40a275af 100644 --- a/etemplate/js/et2_inheritance.js +++ b/etemplate/js/et2_inheritance.js @@ -119,33 +119,6 @@ { prototype["_ifacefuncs"].push(ifaces[i]); } - - // The implements function can be used to check whether the object - // implements the given interface. - prototype["implements"] = function(_iface) { - for (var key in _iface) - { - if (this._ifacefuncs.indexOf(key) < 0) - { - return false; - } - } - return true; - } - - // The instanceOf function can be used to check for both - classes and - // interfaces. Please don't change the case of this function as this - // affects IE and Opera support. - prototype["instanceOf"] = function(_obj) { - if (_obj instanceof Interface) - { - return this.implements(_obj); - } - else - { - return this instanceof _obj; - } - } }; function addAttributeFunctions(prototype, _super) @@ -200,82 +173,6 @@ } prototype.attributes = attributes; - - /** - * The initAttributes function sets the attributes to their default - * values. The attributes are not overwritten, which means, that the - * default is only set, if either a setter exists or this[propName] does - * not exist yet. - */ - prototype.initAttributes = function() { - for (var key in this.attributes) - { - if (!this.attributes[key].ignore && this.attributes[key]["default"] !== et2_no_init) - { - this.setAttribute(key, this.attributes[key]["default"], - false); - } - } - - this._attrsInitialized = true; - } - - /** - * The setAttribute function sets the attribute with the given name to - * the given value. _override defines, whether this[_name] will be set, - * if this key already exists. _override defaults to true. A warning - * is issued if the attribute does not exist. - */ - prototype.setAttribute = function(_name, _value, _override) { - if (typeof this.attributes[_name] != "undefined") - { - if (!this.attributes[_name].ignore) - { - if (typeof _override == "undefined") - { - _override = true; - } - - var val = et2_checkType(_value, this.attributes[_name].type); - - if (typeof this["set_" + _name] == "function") - { - this["set_" + _name](val); - } - else if (_override || typeof this[_name] == "undefined") - { - this[_name] = val; - } - } - } - else - { - et2_debug("warn", "Attribute '" + _name + "' does not exist!"); - } - } - - /** - * Returns the value of the given attribute. If the property does not - * exist, an error message is issued. - */ - prototype.getAttribute = function(_name) { - if (typeof this.attributes[_name] != "undefined" && - !this.attributes[_name].ignore) - { - if (typeof this["get_" + _name] == "function") - { - return this["get_" + _name](); - } - else - { - return this[_name]; - } - } - else - { - et2_error("error", "Attribute '" + _name + "' does not exist!"); - } - } }; function classExtend(interfaces, prop) { @@ -394,7 +291,116 @@ Class.extend = classExtend; // The base class has no attributes - Class.attributes = {}; + Class.prototype.attributes = {}; + + // Add the basic functions + + /** + * Returns the value of the given attribute. If the property does not + * exist, an error message is issued. + */ + Class.prototype.getAttribute = function(_name) { + if (typeof this.attributes[_name] != "undefined" && + !this.attributes[_name].ignore) + { + if (typeof this["get_" + _name] == "function") + { + return this["get_" + _name](); + } + else + { + return this[_name]; + } + } + else + { + et2_error("error", "Attribute '" + _name + "' does not exist!"); + } + } + + /** + * The setAttribute function sets the attribute with the given name to + * the given value. _override defines, whether this[_name] will be set, + * if this key already exists. _override defaults to true. A warning + * is issued if the attribute does not exist. + */ + Class.prototype.setAttribute = function(_name, _value, _override) { + if (typeof this.attributes[_name] != "undefined") + { + if (!this.attributes[_name].ignore) + { + if (typeof _override == "undefined") + { + _override = true; + } + + var val = et2_checkType(_value, this.attributes[_name].type); + + if (typeof this["set_" + _name] == "function") + { + this["set_" + _name](val); + } + else if (_override || typeof this[_name] == "undefined") + { + this[_name] = val; + } + } + } + else + { + et2_debug("warn", "Attribute '" + _name + "' does not exist!"); + } + } + + /** + * The initAttributes function sets the attributes to their default + * values. The attributes are not overwritten, which means, that the + * default is only set, if either a setter exists or this[propName] does + * not exist yet. + */ + Class.prototype.initAttributes = function() { + for (var key in this.attributes) + { + if (!this.attributes[key].ignore && this.attributes[key]["default"] !== et2_no_init) + { + this.setAttribute(key, this.attributes[key]["default"], + false); + } + } + + this._attrsInitialized = true; + } + + /** + * The implements function can be used to check whether the object + * implements the given interface. + */ + Class.prototype.implements = function(_iface) { + for (var key in _iface) + { + if (this._ifacefuncs.indexOf(key) < 0) + { + return false; + } + } + return true; + } + + /** + * The instanceOf function can be used to check for both - classes and + * interfaces. Please don't change the case of this function as this + * affects IE and Opera support. + */ + Class.prototype.instanceOf = function(_obj) { + if (_obj instanceof Interface) + { + return this.implements(_obj); + } + else + { + return this instanceof _obj; + } + } }).call(window); From 2fc29718f1922de1d53c4cfdadc85ff39039b81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Fri, 12 Aug 2011 16:29:24 +0000 Subject: [PATCH 028/472] Added correct handling of namespaces --- etemplate/js/et2_baseWidget.js | 2 -- etemplate/js/et2_box.js | 7 ++++ etemplate/js/et2_contentArrayMgr.js | 12 +++++-- etemplate/js/et2_grid.js | 13 +++++++ etemplate/js/et2_template.js | 3 ++ etemplate/js/et2_widget.js | 39 ++++++++++++++++++++- etemplate/js/test/et2_test_expressions.json | 5 ++- 7 files changed, 74 insertions(+), 7 deletions(-) diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js index 43409be5ff..19ed9ff89e 100644 --- a/etemplate/js/et2_baseWidget.js +++ b/etemplate/js/et2_baseWidget.js @@ -169,5 +169,3 @@ var et2_placeholder = et2_baseWidget.extend({ } }); - - diff --git a/etemplate/js/et2_box.js b/etemplate/js/et2_box.js index 289e490a2e..2f9f385106 100644 --- a/etemplate/js/et2_box.js +++ b/etemplate/js/et2_box.js @@ -29,6 +29,13 @@ var et2_box = et2_baseWidget.extend({ .addClass("et2_" + _type); this.setDOMNode(this.div[0]); + }, + + set_id: function(_value) { + this._super.apply(this, arguments); + + // Check whether a namespace exists for this element + this.checkCreateNamespace(); } }); diff --git a/etemplate/js/et2_contentArrayMgr.js b/etemplate/js/et2_contentArrayMgr.js index e6cb50759d..fd615e0970 100644 --- a/etemplate/js/et2_contentArrayMgr.js +++ b/etemplate/js/et2_contentArrayMgr.js @@ -34,6 +34,7 @@ function et2_contentArrayMgr(_data, _parentMgr) // Holds information about the current perspective this.perspectiveData = { + "owner": null, "key": null, "col": 0, "row": 0 @@ -140,8 +141,10 @@ et2_contentArrayMgr.prototype.expandName = function(_ident) { _ident = this.getRoot().getEntry(_ident.substr(2)); } - - _ident = this.getEntry(_ident.substr(1)); + else + { + _ident = this.getEntry(_ident.substr(1)); + } } return _ident; @@ -183,7 +186,7 @@ et2_contentArrayMgr.prototype.parseBoolExpression = function(_expression) return val != '' && (typeof val != "string" || val.toLowerCase() != "false"); } -et2_contentArrayMgr.prototype.openPerspective = function(_root, _col, _row) +et2_contentArrayMgr.prototype.openPerspective = function(_owner, _root, _col, _row) { // Get the root node var root = typeof _root == "string" ? this.data[_root] : @@ -192,6 +195,9 @@ et2_contentArrayMgr.prototype.openPerspective = function(_root, _col, _row) // Create a new content array manager with the given root var mgr = new et2_contentArrayMgr(root, this); + // Set the owner + mgr.perspectiveData.owner = _owner; + // Set the root key if (typeof _root == "string") { diff --git a/etemplate/js/et2_grid.js b/etemplate/js/et2_grid.js index 9d4fde9005..20a81eb982 100644 --- a/etemplate/js/et2_grid.js +++ b/etemplate/js/et2_grid.js @@ -489,6 +489,12 @@ var et2_grid = et2_DOMWidget.extend({ // Create the table this.createTableFromCells(cells); + + // Copy a reference to the content array manager + if (_obj._mgr) + { + this._mgr = _obj._mgr; + } } else { @@ -514,6 +520,13 @@ var et2_grid = et2_DOMWidget.extend({ } return null; + }, + + set_id: function(_value) { + this._super.apply(this, arguments); + + // Check whether a namespace exists for this element + this.checkCreateNamespace(); } }); diff --git a/etemplate/js/et2_template.js b/etemplate/js/et2_template.js index 357689a795..3d47e7e960 100644 --- a/etemplate/js/et2_template.js +++ b/etemplate/js/et2_template.js @@ -136,6 +136,9 @@ var et2_template = et2_DOMWidget.extend({ else { this._super(_value); + + // Check whether a namespace exists for this element + this.checkCreateNamespace(); } } }, diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index efd1fab72f..8351a5870d 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -136,6 +136,7 @@ var et2_widget = Class.extend({ // Delete all references to other objects this._children = []; this._parent = null; + this._mgr = null; this.onSetParent(); }, @@ -176,6 +177,12 @@ var et2_widget = Class.extend({ this.setAttribute(key, _obj.getAttribute(key)); } } + + // Copy a reference to the content array manager + if (_obj._mgr) + { + this._mgr = _obj._mgr; + } }, /** @@ -498,8 +505,38 @@ var et2_widget = Class.extend({ } return _target; - } + }, + /** + * Checks whether a namespace exists for this element in the content array. + * If yes, an own perspective of the content array is created. If not, the + * parent content manager is used. + */ + checkCreateNamespace: function() { + // Get the content manager + var mgr = this.getContentMgr(); + + // Get the original content manager if we have already created a + // perspective for this node + if (this._mgr != null && this._mgr.perspectiveData.owner == this) + { + mgr = mgr.parentMgr; + } + + // Check whether the manager has a namespace for the id of this object + if (mgr.getEntry(this.id) instanceof Object) + { + // The content manager has a own node for this object, so create + // an own perspective. + this._mgr = mgr.openPerspective(this, this.id); + } + else + { + // The current content manager does not have an own namespace for + // this element, so use the content manager of the parent. + this._mgr = null; + } + } }); diff --git a/etemplate/js/test/et2_test_expressions.json b/etemplate/js/test/et2_test_expressions.json index fcdf1b47c7..373d549874 100644 --- a/etemplate/js/test/et2_test_expressions.json +++ b/etemplate/js/test/et2_test_expressions.json @@ -1,4 +1,7 @@ var expression_test_data = { - "display_text": "true" + "test": { + "display_text": "true" + }, + "display_text": "false" }; From 0c71ee3931cce143f9181269712f23fdf350df41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Fri, 12 Aug 2011 17:02:21 +0000 Subject: [PATCH 029/472] Added correct handling of namespaces for the getValues function --- etemplate/js/et2_box.js | 2 +- etemplate/js/et2_contentArrayMgr.js | 28 ++++++++++- etemplate/js/et2_widget.js | 56 ++++++++++++++------- etemplate/js/test/et2_test_expressions.json | 6 ++- etemplate/js/test/et2_test_expressions.xet | 6 ++- 5 files changed, 74 insertions(+), 24 deletions(-) diff --git a/etemplate/js/et2_box.js b/etemplate/js/et2_box.js index 2f9f385106..2e849d9f47 100644 --- a/etemplate/js/et2_box.js +++ b/etemplate/js/et2_box.js @@ -40,5 +40,5 @@ var et2_box = et2_baseWidget.extend({ }); -et2_register_widget(et2_box, ["hbox", "vbox"]); +et2_register_widget(et2_box, ["hbox", "vbox", "box"]); diff --git a/etemplate/js/et2_contentArrayMgr.js b/etemplate/js/et2_contentArrayMgr.js index fd615e0970..ded34ada3c 100644 --- a/etemplate/js/et2_contentArrayMgr.js +++ b/etemplate/js/et2_contentArrayMgr.js @@ -64,6 +64,32 @@ et2_contentArrayMgr.prototype.getValueForID = function(_id) return null; } +/** + * Returns the path to this content array manager perspective as an array + * containing the key values + * + * @param _path is used internally, do not supply it manually. + */ +et2_contentArrayMgr.prototype.getPath = function(_path) +{ + if (typeof _path == "undefined") + { + _path = []; + } + + if (this.perspectiveData.key != null) + { + _path.push(this.perspectiveData.key); + } + + if (this.parentMgr != null) + { + this.parentMgr.getPath(_path); + } + + return _path; +} + /** * Get array entry is the equivalent to the boetemplate get_array function. * It returns a reference to the (sub) array with the given key. This also works @@ -201,7 +227,7 @@ et2_contentArrayMgr.prototype.openPerspective = function(_owner, _root, _col, _r // Set the root key if (typeof _root == "string") { - mgr.perspectiveData.key == _root; + mgr.perspectiveData.key = _root; } // Set the _col and _row parameter diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 8351a5870d..2980e997d7 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -477,34 +477,52 @@ var et2_widget = Class.extend({ * Fetches all input element values and returns them in an associative * array. Widgets which introduce namespacing can use the internal _target * parameter to add another layer. - * - * @param _target is used internally and should no be supplied. */ - getValues: function(_target) { - if (typeof _target == "undefined") - { - _target = {}; - } + getValues: function() { + var result = {}; - // Add the value of this element to the result object - if (this.implements(et2_IInput)) - { - if (typeof _target[this.id] != "undefined") + // Iterate over the widget tree + this.iterateOver(function(_widget) { + + // Get the path to the node we have to store the value at + var path = _widget.getContentMgr().getPath(); + + // Set the _target variable to that node + var _target = result; + for (var i = 0; i < path.length; i++) + { + // Create a new object for not-existing path nodes + if (typeof _target[path[i]] == "undefined") + { + _target[path[i]] = {}; + } + + // Check whether the path node is really an object + if (_target[path[i]] instanceof Object) + { + _target = _target[path[i]]; + } + else + { + et2_debug("error", "ID collision while writing at path " + + "node '" + path[i] + "'"); + } + } + + // Check whether the entry is really undefined + if (typeof _target[_widget.id] != "undefined") { et2_debug("error", "Overwriting value of '" + this.id + "', id exists twice!"); } - _target[this.id] = this.getValue(); - } + // Store the value of the widget and reset its dirty flag, + _target[_widget.id] = _widget.getValue(); + _widget.resetDirty(); - // Store the values of the children in the target array - for (var i = 0; i < this._children.length; i++) - { - this._children[i].getValues(_target); - } + }, this, et2_IInput); - return _target; + return result; }, /** diff --git a/etemplate/js/test/et2_test_expressions.json b/etemplate/js/test/et2_test_expressions.json index 373d549874..55cbb8a2b6 100644 --- a/etemplate/js/test/et2_test_expressions.json +++ b/etemplate/js/test/et2_test_expressions.json @@ -1,7 +1,9 @@ var expression_test_data = { "test": { - "display_text": "true" + "display_text": "true", + "textbox": "And this is the inner textbox." }, - "display_text": "false" + "display_text": "false", + "textbox": "This is the outer textbox." }; diff --git a/etemplate/js/test/et2_test_expressions.xet b/etemplate/js/test/et2_test_expressions.xet index eb796e1a03..28f38df615 100644 --- a/etemplate/js/test/et2_test_expressions.xet +++ b/etemplate/js/test/et2_test_expressions.xet @@ -1,6 +1,10 @@ <?xml version="1.0"?> <overlay> <template id="test"> - <description disabled="!@display_text" value="Dies ist nur ein test!" /> + <vbox> + <description disabled="!@display_text" value="Dies ist nur ein test!" /> + <textbox id="textbox" /> + </vbox> </template> + <textbox id="textbox" /> </overlay> From 358fbf6d9ec1a1c3a260bea521d74f3d4f03c556 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Sat, 13 Aug 2011 16:51:35 +0000 Subject: [PATCH 030/472] first try to call new etemplate2 stuff from server-side, just replace etemplate with etemplate_new, eg. in timesheet_ui::edit() --- etemplate/inc/class.etemplate_new.inc.php | 372 ++++++++++++++++++++++ etemplate/js/test/test.css | 147 +++++++++ etemplate/js/test/test_xml.html | 146 +-------- 3 files changed, 520 insertions(+), 145 deletions(-) create mode 100644 etemplate/inc/class.etemplate_new.inc.php create mode 100644 etemplate/js/test/test.css diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php new file mode 100644 index 0000000000..e93356f38b --- /dev/null +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -0,0 +1,372 @@ +<?php +/** + * EGroupware - eTemplate serverside + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Ralf Becker <RalfBecker@outdoor-training.de> + * @copyright 2002-11 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +/** + * New eTemplate serverside contains: + * - main server methods like read, exec + * - + * + * @ToDo supported customized templates stored in DB, currently we only support xet files stored in filesystem + */ +class etemplate_new +{ + /** + * Are we running as sitemgr module or not + * + * @public boolean + */ + public $sitemgr=false; + + /** + * constructor of etemplate class, reads an eTemplate if $name is given + * + * @param string $name of etemplate or array with name and other keys + * @param string|array $load_via with keys of other etemplate to load in order to get $name + */ + function __construct($name='',$load_via='') + { + $this->sitemgr = isset($GLOBALS['Common_BO']) && is_object($GLOBALS['Common_BO']); + + if ($name) $this->read($name,$template='default',$lang='default',$group=0,$version='',$load_via); + } + + /** + * Abstracts a html-location-header call + * + * In other UI's than html this needs to call the methode, defined by menuaction or + * open a browser-window for any other links. + * + * @param string|array $params url or array with get-params incl. menuaction + */ + static function location($params='') + { + egw::redirect_link(is_array($params) ? '/index.php' : $params, + is_array($params) ? $params : ''); + } + + /** + * Generates a Dialog from an eTemplate - abstract the UI-layer + * + * This is the only function an application should use, all other are INTERNAL and + * do NOT abstract the UI-layer, because they return HTML. + * Generates a webpage with a form from the template and puts process_exec in the + * form as submit-url to call process_show for the template before it + * ExecuteMethod's the given $method of the caller. + * + * @param string $method Methode (e.g. 'etemplate.editor.edit') to be called if form is submitted + * @param array $content with content to fill the input-fields of template, eg. the text-field + * with name 'name' gets its content from $content['name'] + * @param $sel_options array or arrays with the options for each select-field, keys are the + * field-names, eg. array('name' => array(1 => 'one',2 => 'two')) set the + * options for field 'name'. ($content['options-name'] is possible too !!!) + * @param array $readonlys with field-names as keys for fields with should be readonly + * (eg. to implement ACL grants on field-level or to remove buttons not applicable) + * @param array $preserv with vars which should be transported to the $method-call (eg. an id) array('id' => $id) sets $_POST['id'] for the $method-call + * @param int $output_mode + * 0 = echo incl. navbar + * 1 = return html + * -1 = first time return html, after use 0 (echo html incl. navbar), eg. for home + * 2 = echo without navbar (eg. for popups) + * 3 = return eGW independent html site + * @param string $ignore_validation if not empty regular expression for validation-errors to ignore + * @param array $changes change made in the last call if looping, only used internaly by process_exec + * @return string html for $output_mode == 1, else nothing + */ + function exec($method,$content,$sel_options='',$readonlys='',$preserv='',$output_mode=0,$ignore_validation='',$changes='') + { + if (!$this->rel_path) throw new egw_exception_assertion_failed('No (valid) template read!'); + +/* if (self::$response) // call is within an ajax event / form submit + { + + } + else // first call +*/ { + egw_framework::validate_file('.','et2_xml','etemplate'); + egw_framework::validate_file('.','et2_baseWidget','etemplate'); + egw_framework::validate_file('.','et2_contentArrayMgr','etemplate'); + egw_framework::includeCSS('/etemplate/js/test/test.css'); + common::egw_header(); + if ($output_mode != 2) + { + parse_navbar(); + } + echo ' + <div id="container"></div> + <script> + var container = null; + + function open_xet(file, content) { + et2_loadXMLFromURL(file, + function(_xmldoc) { + if (container != null) + { + container.destroy(); + container = null; + } + + container = new et2_container(null); + container.setParentDOMNode(document.getElementById("container")); + container.setContentMgr(new et2_contentArrayMgr(content)); + container.loadFromXML(_xmldoc); + }); + } + open_xet("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode(array( + 'content' => $content, + 'sel_options' => $sel_options, + 'readonlys' => $readonlys, + 'modifications' => $this->modifications, + 'validation_errros' => self::$validation_errors, + )).'); + </script> +'; + common::egw_footer(); + } + } + + /** + * Path of template relative to EGW_SERVER_ROOT + * + * @var string + */ + public $rel_path; + + /** + * Reads an eTemplate from filesystem or DB (not yet supported) + * + * @param string $name name of the eTemplate or array with the values for all keys + * @param string $template template-set, '' loads the prefered template of the user, 'default' loads the default one '' in the db + * @param string $lang language, '' loads the pref. lang of the user, 'default' loads the default one '' in the db + * @param int $group id of the (primary) group of the user or 0 for none, not used at the moment !!! + * @param string $version version of the eTemplate + * @param mixed $load_via name/array of keys of etemplate to load in order to get $name (only as second try!) + * @return boolean True if a fitting template is found, else False + * + * @ToDo supported customized templates stored in DB + */ + public function read($name,$template='default',$lang='default',$group=0,$version='',$load_via='') + { + list($app, $tpl_name) = explode('.', $name, 2); + + $this->rel_path = '/'.$app.'/templates/'.$template.'/'.$tpl_name.'.xet'; + if (!file_exists(EGW_SERVER_ROOT.$this->rel_path) && $template !== 'default') + { + $this->rel_path = '/'.$app.'/templates/default/'.$tpl_name.'.xet'; + } + if (!file_exists(EGW_SERVER_ROOT.$this->rel_path)) + { + $this->rel_path = null; + error_log(__METHOD__."('$name',...,'$load_via') returning FALSE"); + return false; + } + error_log(__METHOD__."('$name',...,'$load_via') this->rel_path=$this->rel_path returning FALSE"); + return true; + } + + /** + * Validation errors from process_show and the extensions, should be set via etemplate::set_validation_error + * + * @public array form_name => message pairs + */ + static protected $validation_errors = array(); + + /** + * Sets a validation error, to be displayed in the next exec + * + * @param string $name (complete) name of the widget causing the error + * @param string $error error-message already translated + * @param string $cname=null set it to '', if the name is already a form-name, defaults to self::$name_vars + */ + static function set_validation_error($name,$error,$cname=null) + { + if (is_null($cname)) $cname = self::$name_vars; + //echo "<p>etemplate::set_validation_error('$name','$error','$cname');</p>\n"; + if ($cname) $name = self::form_name($cname,$name); + + if (self::$validation_errors[$name]) + { + self::$validation_errors[$name] .= ', '; + } + self::$validation_errors[$name] .= $error; + } + + /** + * Check if we have not ignored validation errors + * + * @param string $ignore_validation='' if not empty regular expression for validation-errors to ignore + * @param string $cname=null name-prefix, which need to be ignored, default self::$name_vars + * @return boolean true if there are not ignored validation errors, false otherwise + */ + function validation_errors($ignore_validation='',$cname=null) + { + if (is_null($cname)) $cname = self::$name_vars; + //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') validation_error="; _debug_array(self::$validation_errors); + if (!$ignore_validation) return count(self::$validation_errors) > 0; + + foreach(self::$validation_errors as $name => $error) + { + if ($cname) $name = preg_replace('/^'.$cname.'\[([^\]]+)\](.*)$/','\\1\\2',$name); + + // treat $ignoare_validation only as regular expression, if it starts with a slash + if ($ignore_validation[0] == '/' && !preg_match($ignore_validation,$name) || + $ignore_validation[0] != '/' && $ignore_validation != $name) + { + //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') name='$name' ($error) not ignored!!!</p>\n"; + return true; + } + //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') name='$name' ($error) ignored</p>\n"; + } + return false; + } + + /** + * Modifications on the instancated template + * + * Get collected here to be send to the server + */ + protected $modifications = array(); + + /** + * Returns reference to an attribute in a named cell + * + * Currently we always return a reference to an not set value, unless it was set before. + * We do not return a reference to the actual cell, as it get's contructed on client-side! + * + * @param string $name cell-name + * @param string $attr attribute-name + * @return mixed reference to attribute, usually NULL + */ + function &get_cell_attribute($name,$attr) + { + error_log(__METHOD__."('$name', '$attr')"); + + return $this->modifications[$name][$attr]; + } + + /** + * set an attribute in a named cell if val is not NULL else return the attribute + * + * @param string $name cell-name + * @param string $attr attribute-name + * @param mixed $val if not NULL sets attribute else returns it + * @return mixed number of changed cells or False, if none changed + */ + function &set_cell_attribute($name,$attr,$val) + { + error_log(__METHOD__."('$name', '$attr', ".array2string($val).')'); + + $attr =& $this->get_cell_attribute($name, $attr); + if (!is_null($val)) $attr = $val; + + return $attr; + } + + /** + * disables all cells with name == $name + * + * @param sting $name cell-name + * @param boolean $disabled=true disable or enable a cell, default true=disable + * @return mixed number of changed cells or False, if none changed + */ + function disable_cells($name,$disabled=True) + { + return $this->set_cell_attribute($name,'disabled',$disabled); + } + + /** + * set one or more attibutes for row $n + * + * @param int $n numerical row-number starting with 1 (!) + * @param string $height percent or pixel or '' for no height + * @param string $class name of css class (without the leading '.') or '' for no class + * @param string $valign alignment (top,middle,bottom) or '' for none + * @param boolean $disabled True or expression or False to disable or enable the row (Only the number 0 means dont change the attribute !!!) + * @param string $path='/0' default is the first widget in the tree of children + * @return false if $path is no grid or array(height,class,valign,disabled) otherwise + */ + function set_row_attributes($n,$height=0,$class=0,$valign=0,$disabled=0,$path='/0') + { + throw new egw_exception_assertion_failed('Not yet implemented!'); + + $grid =& $this->get_widget_by_path($path); + if (is_null($grid) || $grid['type'] != 'grid') return false; + $grid_attr =& $grid['data'][0]; + + list($old_height,$old_disabled) = explode(',',$grid_attr["h$n"]); + $disabled = $disabled !== 0 ? $disabled : $old_disabled; + $grid_attr["h$n"] = ($height !== 0 ? $height : $old_height). + ($disabled ? ','.$disabled : ''); + list($old_class,$old_valign) = explode(',',$grid_attr["c$n"]); + $valign = $valign !== 0 ? $valign : $old_valign; + $grid_attr["c$n"] = ($class !== 0 ? $class : $old_class). + ($valign ? ','.$valign : ''); + + list($height,$disabled) = explode(',',$grid_attr["h$n"]); + list($class,$valign) = explode(',',$grid_attr["c$n"]); + return array($height,$class,$valign,$disabled); + } + + /** + * disables row $n + * + * @param int $n numerical row-number starting with 1 (!) + * @param boolean $enable=false can be used to re-enable a row if set to True + * @param string $path='/0' default is the first widget in the tree of children + */ + function disable_row($n,$enable=False,$path='/0') + { + $this->set_row_attributes($n,0,0,0,!$enable,$path); + } + + /** + * set one or more attibutes for column $c + * + * @param int|string $c numerical column-number starting with 0 (!), or the char-code starting with 'A' + * @param string $width percent or pixel or '' for no height + * @param mixed $disabled=0 True or expression or False to disable or enable the column (Only the number 0 means dont change the attribute !!!) + * @param string $path='/0' default is the first widget in the tree of children + * @return false if $path specifies no grid or array(width,disabled) otherwise + */ + function set_column_attributes($c,$width=0,$disabled=0,$path='/0') + { + throw new egw_exception_assertion_failed('Not yet implemented!'); + + if (is_numeric($c)) + { + $c = $this->num2chrs($c); + } + $grid =& $this->get_widget_by_path($path); + if (is_null($grid) || $grid['type'] != 'grid') return false; + $grid_attr =& $grid['data'][0]; + + list($old_width,$old_disabled) = explode(',',$grid_attr[$c]); + $disabled = $disabled !== 0 ? $disabled : $old_disabled; + $grid_attr[$c] = ($width !== 0 ? $width : $old_width). + ($disabled ? ','.$disabled : ''); + + //echo "set_column_attributes('$c',,'$path'): ".$grid_attr[$c]."</p>\n"; _debug_array($grid_attr); + return explode(',',$grid_attr[$c]); + } + + /** + * disables column $c + * + * @param int|string $c numerical column-number starting with 0 (!), or the char-code starting with 'A' + * @param boolean $enable can be used to re-enable a column if set to True + * @param string $path='/0' default is the first widget in the tree of children + */ + function disable_column($c,$enable=False,$path='/0') + { + $this->set_column_attributes($c,0,!$enable,$path); + } +} diff --git a/etemplate/js/test/test.css b/etemplate/js/test/test.css new file mode 100644 index 0000000000..89ba4c8753 --- /dev/null +++ b/etemplate/js/test/test.css @@ -0,0 +1,147 @@ +/** + * Styles for etemplate2 tests + * + * @version: $Id$ + */ +body { + font-family: Lucida Grande, sans-serif; + font-size: 10pt; +} + +#linklist a { + color: blue; + display: block; +} + +#linklist a:visited { + color: blue; +} + +#linklist a:hover { + color: #5050FF; +} + +#container { + margin: 10px; + border: 1px solid gray; + padding: 10px; +} + +.header { + color: #111; + margin: 30px 0 5px 0; + border-bottom: 1px solid #111; +} + +.et2_placeholder { + display: inline-block; + border: 1px solid cornflowerblue; + background-color: #FCFCFC; + padding: 3px; + margin: 1px; +} + +.et2_placeholder .et2_caption { + display: block; + font-size: 8pt; + margin: 0 0 5px 0; + font-weight: bold; + color: #2E2E2E; + text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0; +} + +.et2_placeholder .et2_attr { + display: block; + font-size: 8pt; + color: #3030A0; + margin: 2px 0 2px 0; +} + +.et2_grid td { + border: 1px dashed silver; +} + +.et2_label { + color: #101050; + font-size: 10pt; +} + +button.et2_button { + background-color: #E0E0E0; + background-image: url(gfx/gradient01.png); + background-position: center; + background-repeat: repeat-x; + + border: 1px solid silver; + color: #101010; + cursor: pointer; + margin: 5px; + padding: 3px; + text-align: center; + + font-size: 9pt; + + text-shadow: 1px 1px #E0E0E0; +} + +button.et2_button:hover { + color: #050505; + border: 1px solid gray; + background-color: #D0D0EE; +} + +button.et2_button:active { + background-image: url(gfx/gradient02.png); + background-color: #D0D0E0; +} + +button.et2_button:focus { + border: 1px solid #2c3d6f; + color: #202d52; + outline: none; +} + +div.et2_hbox { + display: inline; +} + +.et2_tabflag { + display: inline-block; + margin-right: 5px; + height: 20px; + padding: 5px; + cursor: pointer; + border-width: 1px 1px 0 1px; + border-style: solid; + border-color: silver; +} + +.et2_tabflag.active { + border-bottom: 1px solid white; +} + +.et2_textbox { + resize: none; +} + +.et2_bold { + font-weight: bold; +} + +.et2_italic { + font-style: italic; +} + +.et2_vbox div, .et2_vbox span { + display: block; +} + +.egw_tooltip +{ + position: fixed; + border: 1px solid #897f51; + padding: 3px; + background-color: #FDF9DB; + max-width: 300px; + color: black; +} diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index b8bd833604..f8733ff58b 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -22,151 +22,7 @@ <script src="et2_test_timesheet_edit.json"></script> <script src="et2_test_expressions.json"></script> - - <style type="text/css"> - body { - font-family: Lucida Grande, sans-serif; - font-size: 10pt; - } - - #linklist a { - color: blue; - display: block; - } - - #linklist a:visited { - color: blue; - } - - #linklist a:hover { - color: #5050FF; - } - - #container { - margin: 10px; - border: 1px solid gray; - padding: 10px; - } - - .header { - color: #111; - margin: 30px 0 5px 0; - border-bottom: 1px solid #111; - } - - .et2_placeholder { - display: inline-block; - border: 1px solid cornflowerblue; - background-color: #FCFCFC; - padding: 3px; - margin: 1px; - } - - .et2_placeholder .et2_caption { - display: block; - font-size: 8pt; - margin: 0 0 5px 0; - font-weight: bold; - color: #2E2E2E; - text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0; - } - - .et2_placeholder .et2_attr { - display: block; - font-size: 8pt; - color: #3030A0; - margin: 2px 0 2px 0; - } - - .et2_grid td { - border: 1px dashed silver; - } - - .et2_label { - color: #101050; - font-size: 10pt; - } - - button.et2_button { - background-color: #E0E0E0; - background-image: url(gfx/gradient01.png); - background-position: center; - background-repeat: repeat-x; - - border: 1px solid silver; - color: #101010; - cursor: pointer; - margin: 5px; - padding: 3px; - text-align: center; - - font-size: 9pt; - - text-shadow: 1px 1px #E0E0E0; - } - - button.et2_button:hover { - color: #050505; - border: 1px solid gray; - background-color: #D0D0EE; - } - - button.et2_button:active { - background-image: url(gfx/gradient02.png); - background-color: #D0D0E0; - } - - button.et2_button:focus { - border: 1px solid #2c3d6f; - color: #202d52; - outline: none; - } - - div.et2_hbox { - display: inline; - } - - .et2_tabflag { - display: inline-block; - margin-right: 5px; - height: 20px; - padding: 5px; - cursor: pointer; - border-width: 1px 1px 0 1px; - border-style: solid; - border-color: silver; - } - - .et2_tabflag.active { - border-bottom: 1px solid white; - } - - .et2_textbox { - resize: none; - } - - .et2_bold { - font-weight: bold; - } - - .et2_italic { - font-style: italic; - } - - .et2_vbox div, .et2_vbox span { - display: block; - } - - .egw_tooltip - { - position: fixed; - border: 1px solid #897f51; - padding: 3px; - background-color: #FDF9DB; - max-width: 300px; - color: black; - } - </style> + <link rel="StyleSheet" type="text/css" href="./test.css" /> </head> <body> <h1>EGroupware ETemplate2 Test</h1> From 9657dd6c1c8460ae59417f2843ed1d060c996e51 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Sat, 13 Aug 2011 17:34:22 +0000 Subject: [PATCH 031/472] fixed not working dependency --- etemplate/js/et2_baseWidget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js index 19ed9ff89e..02489b3f29 100644 --- a/etemplate/js/et2_baseWidget.js +++ b/etemplate/js/et2_baseWidget.js @@ -14,7 +14,7 @@ /*egw:uses jquery.jquery; - lib/tooltip.js; + lib/tooltip; et2_DOMWidget; */ From 0a410a1e057ed0d32c3be7fbf7c8fa519a5bd3cf Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Sat, 13 Aug 2011 17:34:59 +0000 Subject: [PATCH 032/472] seems all widget have to be explicitly loaded, to be used ... --- etemplate/inc/class.etemplate_new.inc.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index e93356f38b..4e4eacade1 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -95,6 +95,15 @@ class etemplate_new egw_framework::validate_file('.','et2_xml','etemplate'); egw_framework::validate_file('.','et2_baseWidget','etemplate'); egw_framework::validate_file('.','et2_contentArrayMgr','etemplate'); + + // it seems all widget have to be explicitly loaded, to be used ... + foreach(scandir(EGW_SERVER_ROOT.'/etemplate/js') as $file) + { + if (preg_match('/^(et2_.*)\.js$/',$file,$matches)) + { + egw_framework::validate_file('.',$matches[1],'etemplate'); + } + } egw_framework::includeCSS('/etemplate/js/test/test.css'); common::egw_header(); if ($output_mode != 2) @@ -169,7 +178,7 @@ class etemplate_new error_log(__METHOD__."('$name',...,'$load_via') returning FALSE"); return false; } - error_log(__METHOD__."('$name',...,'$load_via') this->rel_path=$this->rel_path returning FALSE"); + //error_log(__METHOD__."('$name',...,'$load_via') this->rel_path=$this->rel_path returning TRUE"); return true; } From a28295db5801ee722ddddc4aec0ddf5b2fdb5063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 08:34:21 +0000 Subject: [PATCH 033/472] Added et2_all.js which contains references to all widgets and can be included by egw to load the complete etemplate2 js module, fixed problem in 'et2_DOMWidget::set_disabled', interpreting 'type' attribute like the node name when creating the wigdets from XML --- etemplate/doc/et2/documentation.pdf | Bin 189402 -> 189139 bytes etemplate/doc/et2/documentation.tex | 2 +- etemplate/inc/class.etemplate_new.inc.php | 12 +----------- etemplate/js/et2_DOMWidget.js | 7 ++++--- etemplate/js/et2_widget.js | 17 +++++++++++++++++ 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/etemplate/doc/et2/documentation.pdf b/etemplate/doc/et2/documentation.pdf index 739e642e097d0db7f1045a1a06d068f086b50b99..95179a0634470c419cc1992e142bc7158ae907a3 100644 GIT binary patch delta 21621 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 b+J}$KT_1V6THDZ`aH0@US}<5aQ<3&xPZ9qI delta 21847 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 L@bfEaDFgli(s($* diff --git a/etemplate/doc/et2/documentation.tex b/etemplate/doc/et2/documentation.tex index 4ac8e59881..9898836612 100644 --- a/etemplate/doc/et2/documentation.tex +++ b/etemplate/doc/et2/documentation.tex @@ -281,7 +281,7 @@ et2_IDOMNode::getDOMNode(_sender) function, which has to be implemented by all widgets which have a representation in the HTML-DOM-Tree. \texttt{getDOMNode} should return the DOM-Node of the current widget. The return value has to be a plain DOM node, not a jQuery object. The \texttt{\_sender} parameter defines which widget is asking for the DOMNode. Depending on that, the widget may return different nodes. This is used in the grid or the tab. Normally the \_sender parameter can be omitted in most implementations of the getDOMNode function. However, you should always provide the \texttt{\_sender} parameter when calling \texttt{getDOMNode}! \subsection*{et2\_DOMWidget} -The \textit{et2\_DOMWidget} class is derrived from \textit{et2\_IDOMNode} and \textit{et2\_widget} without implementing the \texttt{getDOMNode} funcition. It introduces an mechanism which automatically inserts the DOM-Node of this widget into the DOM-Node of the parent widget (if the parent widget implements \textit{et2\_IDOMWidget}. The two functions +The \textit{et2\_DOMWidget} class is derrived from \textit{et2\_IDOMNode} and \textit{et2\_widget} without implementing the \texttt{getDOMNode} funcition. It introduces an mechanism which automatically inserts the DOM-Node of this widget into the DOM-Node of the parent widget (if the parent widget implements \textit{et2\_IDOMNode}. The two functions \begin{verbatim} et2_DOMWidget::attachToDOM() et2_DOMWidget::detatchFromDOM() diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index 4e4eacade1..d01af18174 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -92,18 +92,8 @@ class etemplate_new } else // first call */ { - egw_framework::validate_file('.','et2_xml','etemplate'); - egw_framework::validate_file('.','et2_baseWidget','etemplate'); - egw_framework::validate_file('.','et2_contentArrayMgr','etemplate'); + egw_framework::validate_file('.','et2_all','etemplate'); - // it seems all widget have to be explicitly loaded, to be used ... - foreach(scandir(EGW_SERVER_ROOT.'/etemplate/js') as $file) - { - if (preg_match('/^(et2_.*)\.js$/',$file,$matches)) - { - egw_framework::validate_file('.',$matches[1],'etemplate'); - } - } egw_framework::includeCSS('/etemplate/js/test/test.css'); common::egw_header(); if ($output_mode != 2) diff --git a/etemplate/js/et2_DOMWidget.js b/etemplate/js/et2_DOMWidget.js index 5071719d0e..aad70b65a4 100644 --- a/etemplate/js/et2_DOMWidget.js +++ b/etemplate/js/et2_DOMWidget.js @@ -192,17 +192,18 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { }, set_disabled: function(_value) { - if (this.node) + var node = this.getDOMNode(); + if (node) { this.diabled = _value; if (_value) { - $j(this.node).hide(); + $j(node).hide(); } else { - $j(this.node).show(); + $j(node).show(); } } } diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 2980e997d7..4c96208145 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -16,6 +16,7 @@ et2_xml; et2_common; et2_inheritance; + et2_contentArrayMgr; */ /** @@ -65,6 +66,14 @@ var et2_widget = Class.extend({ */ "span": { "ignore": true + }, + + /** + * Ignore the "type" tag - it is read by the "createElementFromNode" + * function and passed as second parameter of the widget constructor + */ + "type": { + "ignore": true } }, @@ -330,6 +339,14 @@ var et2_widget = Class.extend({ }, createElementFromNode: function(_node, _nodeName) { + + // Check whether the type attribute exists - if yes pass it instead of + // the nodeName + if (_node.getAttribute("type")) + { + _nodeName = _node.getAttribute("type"); + } + if (typeof _nodeName == "undefined") { _nodeName = _node.nodeName.toLowerCase(); From bb4aab785450803b06554016d4591bfa95ab451f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 08:42:07 +0000 Subject: [PATCH 034/472] Fixed two dependencies --- etemplate/js/et2_grid.js | 2 +- etemplate/js/et2_template.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/etemplate/js/et2_grid.js b/etemplate/js/et2_grid.js index 20a81eb982..aaa5843d5f 100644 --- a/etemplate/js/et2_grid.js +++ b/etemplate/js/et2_grid.js @@ -14,7 +14,7 @@ /*egw:uses jquery.jquery; - et2_widget; + et2_DOMWidget; et2_xml; */ diff --git a/etemplate/js/et2_template.js b/etemplate/js/et2_template.js index 3d47e7e960..29d479fa60 100644 --- a/etemplate/js/et2_template.js +++ b/etemplate/js/et2_template.js @@ -13,7 +13,8 @@ "use strict"; /*egw:uses - et2_widget; + et2_xml; + et2_DOMWidget; */ /** From 27d1173d2fee549899aa7eabe09c9a21738318a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 08:46:40 +0000 Subject: [PATCH 035/472] Fixed bug in timesheet_ui edit.xet: Options not set properly --- timesheet/templates/default/edit.xet | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/timesheet/templates/default/edit.xet b/timesheet/templates/default/edit.xet index 3398134fd1..5f9337c77a 100644 --- a/timesheet/templates/default/edit.xet +++ b/timesheet/templates/default/edit.xet @@ -145,7 +145,7 @@ </grid> </row> <row class="row" disabled="@ts_viewtype"> - <description value="Unitprice" options=",,ts_unitprice"/> + <description value="Unitprice" options=",,,ts_unitprice"/> <grid> <columns> <column disabled="@pm_integration=none"/> @@ -207,4 +207,4 @@ .fullWidth textarea { widht: 100%; } </styles> </template> -</overlay> \ No newline at end of file +</overlay> From 26ce82186c9426622176c6e2d798efc557d443c4 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Mon, 15 Aug 2011 09:15:01 +0000 Subject: [PATCH 036/472] also updated template in database, after Andreas change of the xet file --- timesheet/setup/etemplates.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/timesheet/setup/etemplates.inc.php b/timesheet/setup/etemplates.inc.php index 158402b9f6..ffccc76ca4 100644 --- a/timesheet/setup/etemplates.inc.php +++ b/timesheet/setup/etemplates.inc.php @@ -2,7 +2,7 @@ /** * EGroupware - eTemplates for Application timesheet * http://www.egroupware.org - * generated by soetemplate::dump4setup() 2011-08-04 18:39 + * generated by soetemplate::dump4setup() 2011-08-15 11:13 * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package timesheet @@ -21,7 +21,7 @@ $templ_data[] = array('name' => 'timesheet.customstatus','template' => '','lang' $templ_data[] = array('name' => 'timesheet.customstatus.cats','template' => '','lang' => '','group' => '0','version' => '1.7.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:3:{s:1:"D";s:3:"30%";s:2:"c1";s:7:"row,top";s:1:"A";s:3:"100";}i:1;a:4:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Status";}s:1:"B";a:8:{s:4:"type";s:4:"grid";s:4:"size";s:17:"100%,280,,,,,auto";s:4:"span";s:3:"all";s:4:"name";s:6:"statis";s:4:"data";a:3:{i:0;a:3:{s:2:"c1";s:2:"th";s:1:"B";s:2:"5%";s:2:"c2";s:3:"row";}i:1;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"Name";}s:1:"B";a:2:{s:4:"type";s:5:"label";s:5:"label";s:7:"Actions";}}i:2;a:2:{s:1:"A";a:4:{s:4:"type";s:4:"text";s:4:"size";s:6:"80,150";s:4:"blur";s:18:"--> enter new name";s:4:"name";s:12:"${row}[name]";}s:1:"B";a:7:{s:4:"type";s:6:"button";s:4:"size";s:6:"delete";s:5:"label";s:6:"Delete";s:5:"align";s:6:"center";s:4:"name";s:21:"delete[$row_cont[id]]";s:4:"help";s:18:"Delete this status";s:7:"onclick";s:37:"return confirm(\'Delete this status\');";}}}s:4:"rows";i:2;s:4:"cols";i:2;s:7:"options";a:3:{i:0;s:4:"100%";i:1;s:3:"280";i:6;s:4:"auto";}}s:1:"C";a:1:{s:4:"type";s:5:"label";}s:1:"D";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:1;s:4:"cols";i:4;s:4:"size";s:17:"100%,300,,,,,auto";s:7:"options";a:3:{i:0;s:4:"100%";i:1;s:3:"300";i:6;s:4:"auto";}}}','size' => '100%,300,,,,,auto','style' => '','modified' => '1236867741',); -$templ_data[] = array('name' => 'timesheet.edit','template' => '','lang' => '','group' => '0','version' => '1.9.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:8:{i:0;a:8:{s:1:"A";s:3:"100";s:2:"h1";s:6:",!@msg";s:2:"c2";s:2:"th";s:2:"h2";s:2:"28";s:2:"c3";s:3:"row";s:2:"c4";s:3:"row";s:2:"h4";s:13:",@ts_viewtype";s:2:"h6";s:14:",!@ts_modified";}i:1;a:2:{s:1:"A";a:5:{s:4:"span";s:13:"all,redItalic";s:7:"no_lang";s:1:"1";s:5:"align";s:6:"center";s:4:"name";s:3:"msg";s:4:"type";s:5:"label";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:3:{s:4:"size";s:11:",,,ts_owner";s:4:"type";s:5:"label";s:5:"label";s:4:"User";}s:1:"B";a:4:{s:4:"span";s:3:"all";s:7:"no_lang";s:1:"1";s:4:"name";s:8:"ts_owner";s:4:"type";s:6:"select";}}i:3;a:2:{s:1:"A";a:3:{s:4:"size";s:13:",,,ts_project";s:4:"type";s:5:"label";s:5:"label";s:7:"Project";}s:1:"B";a:5:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:2:{s:2:"h1";s:21:",@pm_integration=none";s:2:"h2";s:21:",@pm_integration=full";}i:1;a:1:{s:1:"A";a:6:{s:4:"span";s:13:"all,fullWidth";s:8:"onchange";s:1:"1";s:4:"name";s:5:"pm_id";s:4:"size";s:4:"None";s:4:"type";s:21:"projectmanager-select";s:4:"help";s:16:"Select a project";}}i:2;a:1:{s:1:"A";a:5:{s:4:"blur";s:16:"@ts_project_blur";s:4:"size";s:5:"65,80";s:4:"name";s:10:"ts_project";s:4:"type";s:4:"text";s:4:"span";s:10:",fullWidth";}}}s:4:"cols";i:1;s:4:"rows";i:2;s:4:"size";s:7:",,,,1,1";}}i:4;a:2:{s:1:"A";a:3:{s:4:"size";s:14:",,ts_unitprice";s:4:"type";s:5:"label";s:5:"label";s:9:"Unitprice";}s:1:"B";a:4:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:1:{s:1:"A";s:21:",@pm_integration=none";}i:1;a:2:{s:1:"A";a:4:{s:8:"onchange";s:209:"this.form[\'exec[ts_unitprice]\'].value=this.options[this.selectedIndex].text.lastIndexOf(\'(\') < 0 ? \'\' : this.options[this.selectedIndex].text.slice(this.options[this.selectedIndex].text.lastIndexOf(\'(\')+1,-1);";s:4:"name";s:5:"pl_id";s:4:"size";s:4:"None";s:4:"type";s:24:"projectmanager-pricelist";}s:1:"B";a:4:{s:4:"type";s:5:"float";s:4:"span";s:3:"all";s:4:"name";s:12:"ts_unitprice";s:4:"size";s:1:",";}}}s:4:"cols";i:2;s:4:"rows";i:1;}}i:5;a:2:{s:1:"A";a:5:{s:4:"span";s:3:"all";s:4:"name";s:45:"tabs=general|notes|links|customfields|history";s:4:"type";s:3:"tab";s:5:"label";s:41:"General|Notes|Links|Custom Fields|History";s:4:"help";s:4:"||||";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:6;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:13:"Last modified";}s:1:"B";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:3:{s:8:"readonly";s:4:"true";s:4:"name";s:11:"ts_modified";s:4:"type";s:9:"date-time";}i:2;a:4:{s:4:"type";s:14:"select-account";s:5:"label";s:2:"by";s:8:"readonly";s:4:"true";s:4:"name";s:11:"ts_modifier";}}}i:7;a:2:{s:1:"A";a:6:{s:4:"span";s:1:"2";s:6:"orient";s:1:"0";s:4:"size";s:1:"2";s:4:"type";s:4:"hbox";i:1;a:8:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"6";i:1;a:4:{s:5:"label";s:4:"Edit";s:4:"name";s:12:"button[edit]";s:4:"type";s:6:"button";s:4:"help";s:15:"Edit this entry";}i:2;a:4:{s:5:"label";s:10:"Save & New";s:4:"name";s:16:"button[save_new]";s:4:"type";s:6:"button";s:4:"help";s:34:"Saves this entry and add a new one";}i:3;a:4:{s:5:"label";s:4:"Save";s:4:"name";s:12:"button[save]";s:4:"type";s:6:"button";s:4:"help";s:22:"Saves the changes made";}i:4;a:4:{s:5:"label";s:5:"Apply";s:4:"name";s:13:"button[apply]";s:4:"type";s:6:"button";s:4:"help";s:24:"Applies the changes made";}i:5;a:5:{s:5:"label";s:6:"Cancel";s:7:"onclick";s:15:"window.close();";s:4:"name";s:14:"button[cancel]";s:4:"type";s:6:"button";s:4:"help";s:44:"closes the window without saving the changes";}i:6;a:2:{s:4:"name";s:2:"js";s:4:"type";s:4:"html";}}i:2;a:6:{s:5:"label";s:6:"Delete";s:5:"align";s:5:"right";s:7:"onclick";s:36:"return confirm(\'Delete this entry\');";s:4:"name";s:14:"button[delete]";s:4:"type";s:6:"button";s:4:"help";s:17:"Delete this entry";}}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"cols";i:2;s:4:"rows";i:7;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '.fullWidth select { widht: 100%; } +$templ_data[] = array('name' => 'timesheet.edit','template' => '','lang' => '','group' => '0','version' => '1.9.001','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:8:{i:0;a:8:{s:1:"A";s:3:"100";s:2:"h1";s:6:",!@msg";s:2:"c2";s:2:"th";s:2:"h2";s:2:"28";s:2:"c3";s:3:"row";s:2:"c4";s:3:"row";s:2:"h4";s:13:",@ts_viewtype";s:2:"h6";s:14:",!@ts_modified";}i:1;a:2:{s:1:"A";a:5:{s:4:"span";s:13:"all,redItalic";s:7:"no_lang";s:1:"1";s:5:"align";s:6:"center";s:4:"name";s:3:"msg";s:4:"type";s:5:"label";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:2;a:2:{s:1:"A";a:3:{s:4:"size";s:11:",,,ts_owner";s:4:"type";s:5:"label";s:5:"label";s:4:"User";}s:1:"B";a:4:{s:4:"span";s:3:"all";s:7:"no_lang";s:1:"1";s:4:"name";s:8:"ts_owner";s:4:"type";s:6:"select";}}i:3;a:2:{s:1:"A";a:3:{s:4:"size";s:13:",,,ts_project";s:4:"type";s:5:"label";s:5:"label";s:7:"Project";}s:1:"B";a:5:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:2:{s:2:"h1";s:21:",@pm_integration=none";s:2:"h2";s:21:",@pm_integration=full";}i:1;a:1:{s:1:"A";a:6:{s:4:"span";s:13:"all,fullWidth";s:8:"onchange";s:1:"1";s:4:"name";s:5:"pm_id";s:4:"size";s:4:"None";s:4:"type";s:21:"projectmanager-select";s:4:"help";s:16:"Select a project";}}i:2;a:1:{s:1:"A";a:5:{s:4:"blur";s:16:"@ts_project_blur";s:4:"size";s:5:"65,80";s:4:"name";s:10:"ts_project";s:4:"type";s:4:"text";s:4:"span";s:10:",fullWidth";}}}s:4:"cols";i:1;s:4:"rows";i:2;s:4:"size";s:7:",,,,1,1";}}i:4;a:2:{s:1:"A";a:3:{s:4:"size";s:15:",,,ts_unitprice";s:4:"type";s:5:"label";s:5:"label";s:9:"Unitprice";}s:1:"B";a:4:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:1:{s:1:"A";s:21:",@pm_integration=none";}i:1;a:2:{s:1:"A";a:4:{s:8:"onchange";s:209:"this.form[\'exec[ts_unitprice]\'].value=this.options[this.selectedIndex].text.lastIndexOf(\'(\') < 0 ? \'\' : this.options[this.selectedIndex].text.slice(this.options[this.selectedIndex].text.lastIndexOf(\'(\')+1,-1);";s:4:"name";s:5:"pl_id";s:4:"size";s:4:"None";s:4:"type";s:24:"projectmanager-pricelist";}s:1:"B";a:4:{s:4:"type";s:5:"float";s:4:"span";s:3:"all";s:4:"name";s:12:"ts_unitprice";s:4:"size";s:1:",";}}}s:4:"cols";i:2;s:4:"rows";i:1;}}i:5;a:2:{s:1:"A";a:5:{s:4:"span";s:3:"all";s:4:"name";s:45:"tabs=general|notes|links|customfields|history";s:4:"type";s:3:"tab";s:5:"label";s:41:"General|Notes|Links|Custom Fields|History";s:4:"help";s:4:"||||";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}i:6;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:13:"Last modified";}s:1:"B";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:3:{s:8:"readonly";s:4:"true";s:4:"name";s:11:"ts_modified";s:4:"type";s:9:"date-time";}i:2;a:4:{s:4:"type";s:14:"select-account";s:5:"label";s:2:"by";s:8:"readonly";s:4:"true";s:4:"name";s:11:"ts_modifier";}}}i:7;a:2:{s:1:"A";a:6:{s:4:"span";s:1:"2";s:6:"orient";s:1:"0";s:4:"size";s:1:"2";s:4:"type";s:4:"hbox";i:1;a:8:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"6";i:1;a:4:{s:5:"label";s:4:"Edit";s:4:"name";s:12:"button[edit]";s:4:"type";s:6:"button";s:4:"help";s:15:"Edit this entry";}i:2;a:4:{s:5:"label";s:10:"Save & New";s:4:"name";s:16:"button[save_new]";s:4:"type";s:6:"button";s:4:"help";s:34:"Saves this entry and add a new one";}i:3;a:4:{s:5:"label";s:4:"Save";s:4:"name";s:12:"button[save]";s:4:"type";s:6:"button";s:4:"help";s:22:"Saves the changes made";}i:4;a:4:{s:5:"label";s:5:"Apply";s:4:"name";s:13:"button[apply]";s:4:"type";s:6:"button";s:4:"help";s:24:"Applies the changes made";}i:5;a:5:{s:5:"label";s:6:"Cancel";s:7:"onclick";s:15:"window.close();";s:4:"name";s:14:"button[cancel]";s:4:"type";s:6:"button";s:4:"help";s:44:"closes the window without saving the changes";}i:6;a:2:{s:4:"name";s:2:"js";s:4:"type";s:4:"html";}}i:2;a:6:{s:5:"label";s:6:"Delete";s:5:"align";s:5:"right";s:7:"onclick";s:36:"return confirm(\'Delete this entry\');";s:4:"name";s:14:"button[delete]";s:4:"type";s:6:"button";s:4:"help";s:17:"Delete this entry";}}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"cols";i:2;s:4:"rows";i:7;s:4:"size";s:4:"100%";s:7:"options";a:1:{i:0;s:4:"100%";}}}','size' => '100%','style' => '.fullWidth select { widht: 100%; } .fullWidth input { widht: 100%; } .fullWidth textarea { widht: 100%; }','modified' => '1311158552',); From 29c16431adbdb5780c3656a7290d09aa17b30b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 09:24:32 +0000 Subject: [PATCH 037/472] Added new attribute type 'js', which cares about converting given JS code to a function --- etemplate/js/et2_button.js | 24 +++++++++++++++++++++++- etemplate/js/et2_common.js | 26 +++++++++++++++++++++++++- etemplate/js/et2_textbox.js | 2 +- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/etemplate/js/et2_button.js b/etemplate/js/et2_button.js index 92310ae216..4148371810 100644 --- a/etemplate/js/et2_button.js +++ b/etemplate/js/et2_button.js @@ -27,6 +27,12 @@ var et2_button = et2_baseWidget.extend({ "name": "caption", "type": "string", "description": "Label of the button" + }, + + "onclick": { + "name": "onclick", + "type": "js", + "description": "JS code which gets executed when the button is clicked" } }, @@ -36,11 +42,27 @@ var et2_button = et2_baseWidget.extend({ this.label = ""; this.btn = $j(document.createElement("button")) - .addClass("et2_button"); + .addClass("et2_button") + .click(this, function(e) {e.data.buttonClick()}); this.setDOMNode(this.btn[0]); }, + buttonClick: function() { + // Execute the JS code connected to the event handler + if (this.onclick != null) + { + if (!this.onclick()) + return false; + } + + // Fetch the form data + var formData = this.getRoot().getValues(); + + // Submit it! + console.log(formData); + }, + set_label: function(_value) { if (_value != this.value) { diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index b85c64524b..65a5af23f5 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -64,7 +64,7 @@ function et2_debug(_level, _msg) /** * Array with all types supported by the et2_checkType function. */ -var et2_validTypes = ["boolean", "string", "float", "integer", "any"]; +var et2_validTypes = ["boolean", "string", "float", "integer", "any", "js"]; /** * Object whith default values for the above types. Do not specify array or @@ -74,6 +74,7 @@ var et2_validTypes = ["boolean", "string", "float", "integer", "any"]; var et2_typeDefaults = { "boolean": false, "string": "", + "js": null, "float": 0.0, "integer": 0, "any": null @@ -114,6 +115,29 @@ function et2_checkType(_val, _type) _err(); } + if (_type == "js") + { + // Handle the default case + if (_val === null) + { + return null; + } + + // Create a new function containing the code + if (typeof _val == "string") + { + if (_val !== "") + { + // TODO: Parse JS code properly + return new Function(_val); + } + + return null; + } + + _err(); + } + // Check whether the given value is of the type "string" if (_type == "string") { diff --git a/etemplate/js/et2_textbox.js b/etemplate/js/et2_textbox.js index 6d22417e07..fcf36ac85a 100644 --- a/etemplate/js/et2_textbox.js +++ b/etemplate/js/et2_textbox.js @@ -69,5 +69,5 @@ var et2_textbox = et2_inputWidget.extend({ }); -et2_register_widget(et2_textbox, ["textbox"]); +et2_register_widget(et2_textbox, ["textbox", "int", "float"]); From f9914e069c193a36f59e5bcbf3c9fcffdba1225d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 10:04:37 +0000 Subject: [PATCH 038/472] Fixed problem with getValues iterating over widgets which are in proxied templates --- etemplate/js/et2_template.js | 13 ++----------- etemplate/js/et2_widget.js | 28 ++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/etemplate/js/et2_template.js b/etemplate/js/et2_template.js index 29d479fa60..9ade66ce3b 100644 --- a/etemplate/js/et2_template.js +++ b/etemplate/js/et2_template.js @@ -148,17 +148,8 @@ var et2_template = et2_DOMWidget.extend({ return this.div; }, - getValues: function(_target) { - if (this.proxiedTemplate) - { - return this.proxiedTemplate.getValues(_target); - } - else if (!this.isProxied) - { - return this._super(_target); - } - - return _target; + isInTree: function() { + return this._super(!this.isProxied); } }); diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 4c96208145..33ff1dbbd7 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -315,7 +315,7 @@ var et2_widget = Class.extend({ _type = et2_widget; } - if (this.instanceOf(_type)) + if (this.isInTree() && this.instanceOf(_type)) { _callback.call(_context, this); } @@ -326,6 +326,30 @@ var et2_widget = Class.extend({ } }, + /** + * Returns true if the widget currently resides in the visible part of the + * widget tree. E.g. Templates which have been cloned are not in the visible + * part of the widget tree. + * + * @param _vis can be used by widgets overwriting this function - simply + * write + * return this._super(inTree); + * when calling this function the _vis parameter does not have to be supplied. + */ + isInTree: function(_vis) { + if (typeof _vis == "undefined") + { + _vis = true; + } + + if (this._parent) + { + return _vis && this._parent.isInTree(); + } + + return _vis; + }, + isOfSupportedWidgetClass: function(_obj) { for (var i = 0; i < this.supportedWidgetClasses.length; i++) @@ -529,7 +553,7 @@ var et2_widget = Class.extend({ // Check whether the entry is really undefined if (typeof _target[_widget.id] != "undefined") { - et2_debug("error", "Overwriting value of '" + this.id + + et2_debug("error", "Overwriting value of '" + _widget.id + "', id exists twice!"); } From be34748b32c4bd4a0aaa49ece8c4e43fa5dc3765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 11:13:22 +0000 Subject: [PATCH 039/472] Added et2_all.js --- etemplate/js/et2_all.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 etemplate/js/et2_all.js diff --git a/etemplate/js/et2_all.js b/etemplate/js/et2_all.js new file mode 100644 index 0000000000..d92b72adfd --- /dev/null +++ b/etemplate/js/et2_all.js @@ -0,0 +1,27 @@ +/** + * eGroupWare eTemplate2 - JS file which contains the complete et2 module + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +/** + * Only include the actual widget class files here, all other dependencies are + * included in those files. + */ + +/*egw:uses + et2_template; + et2_grid; + et2_box; +// et2_tabs; + et2_button; + et2_description; + et2_textbox; +*/ + From 8c9fd0f636bf9743ad84b2877a03c7db4fe18dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 12:34:00 +0000 Subject: [PATCH 040/472] Implemented usage of mutliple array-manager objects (the object which cares about proper namespacing etc.) for each supplied data manager part (like 'content', 'readonlys' etc.), renamed et2_contentArrayMgr.js to et2_arrayMgr.js, renamed et2_all.js to etemplate2.js and added an top-level object which cares about loading the template, creating the array managers etc. --- etemplate/inc/class.etemplate_new.inc.php | 22 +-- etemplate/js/et2_all.js | 27 ---- ...et2_contentArrayMgr.js => et2_arrayMgr.js} | 18 +-- etemplate/js/et2_common.js | 14 ++ etemplate/js/et2_inputWidget.js | 2 +- etemplate/js/et2_widget.js | 134 ++++++++++++------ etemplate/js/etemplate2.js | 97 +++++++++++++ etemplate/js/test/et2_test_expressions.json | 14 +- etemplate/js/test/et2_test_expressions.xet | 2 +- .../js/test/et2_test_timesheet_edit.json | 20 --- etemplate/js/test/test_xml.html | 35 ++--- 11 files changed, 231 insertions(+), 154 deletions(-) delete mode 100644 etemplate/js/et2_all.js rename etemplate/js/{et2_contentArrayMgr.js => et2_arrayMgr.js} (90%) create mode 100644 etemplate/js/etemplate2.js diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index d01af18174..71391a9905 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -92,7 +92,7 @@ class etemplate_new } else // first call */ { - egw_framework::validate_file('.','et2_all','etemplate'); + egw_framework::validate_file('.','etemplate2','etemplate'); egw_framework::includeCSS('/etemplate/js/test/test.css'); common::egw_header(); @@ -103,24 +103,8 @@ class etemplate_new echo ' <div id="container"></div> <script> - var container = null; - - function open_xet(file, content) { - et2_loadXMLFromURL(file, - function(_xmldoc) { - if (container != null) - { - container.destroy(); - container = null; - } - - container = new et2_container(null); - container.setParentDOMNode(document.getElementById("container")); - container.setContentMgr(new et2_contentArrayMgr(content)); - container.loadFromXML(_xmldoc); - }); - } - open_xet("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode(array( + var et2 = new etemplate2(document.getElementById("container"), ""); + et2.load("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode(array( 'content' => $content, 'sel_options' => $sel_options, 'readonlys' => $readonlys, diff --git a/etemplate/js/et2_all.js b/etemplate/js/et2_all.js deleted file mode 100644 index d92b72adfd..0000000000 --- a/etemplate/js/et2_all.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * eGroupWare eTemplate2 - JS file which contains the complete et2 module - * - * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License - * @package etemplate - * @subpackage api - * @link http://www.egroupware.org - * @author Andreas Stöckel - * @copyright Stylite 2011 - * @version $Id$ - */ - -/** - * Only include the actual widget class files here, all other dependencies are - * included in those files. - */ - -/*egw:uses - et2_template; - et2_grid; - et2_box; -// et2_tabs; - et2_button; - et2_description; - et2_textbox; -*/ - diff --git a/etemplate/js/et2_contentArrayMgr.js b/etemplate/js/et2_arrayMgr.js similarity index 90% rename from etemplate/js/et2_contentArrayMgr.js rename to etemplate/js/et2_arrayMgr.js index ded34ada3c..a3004352be 100644 --- a/etemplate/js/et2_contentArrayMgr.js +++ b/etemplate/js/et2_arrayMgr.js @@ -12,7 +12,7 @@ "use strict"; -function et2_contentArrayMgr(_data, _parentMgr) +function et2_arrayMgr(_data, _parentMgr) { if (typeof _parentMgr == "undefined") { @@ -44,7 +44,7 @@ function et2_contentArrayMgr(_data, _parentMgr) /** * Returns the root content array manager object */ -et2_contentArrayMgr.prototype.getRoot = function() +et2_arrayMgr.prototype.getRoot = function() { if (this.parentMgr != null) { @@ -54,7 +54,7 @@ et2_contentArrayMgr.prototype.getRoot = function() return this; } -et2_contentArrayMgr.prototype.getValueForID = function(_id) +et2_arrayMgr.prototype.getValueForID = function(_id) { if (typeof this.data[_id] != "undefined") { @@ -70,7 +70,7 @@ et2_contentArrayMgr.prototype.getValueForID = function(_id) * * @param _path is used internally, do not supply it manually. */ -et2_contentArrayMgr.prototype.getPath = function(_path) +et2_arrayMgr.prototype.getPath = function(_path) { if (typeof _path == "undefined") { @@ -101,7 +101,7 @@ et2_contentArrayMgr.prototype.getPath = function(_path) * @param _skipEmpty returns false if _key is not present in this content array. * Defaults to false. */ -et2_contentArrayMgr.prototype.getEntry = function(_key, _referenceInto, +et2_arrayMgr.prototype.getEntry = function(_key, _referenceInto, _skipEmpty) { if (typeof _referenceInto == "undefined") @@ -147,7 +147,7 @@ et2_contentArrayMgr.prototype.getEntry = function(_key, _referenceInto, * Expands variables inside the given identifier to their values inside the * content array. */ -et2_contentArrayMgr.prototype.expandName = function(_ident) +et2_arrayMgr.prototype.expandName = function(_ident) { // Check whether the identifier refers to an index in the content array var is_index_in_content = _ident.charAt(0) == '@'; @@ -176,7 +176,7 @@ et2_contentArrayMgr.prototype.expandName = function(_ident) return _ident; } -et2_contentArrayMgr.prototype.parseBoolExpression = function(_expression) +et2_arrayMgr.prototype.parseBoolExpression = function(_expression) { // If the first char of the expression is a '!' this means, that the value // is to be negated. @@ -212,14 +212,14 @@ et2_contentArrayMgr.prototype.parseBoolExpression = function(_expression) return val != '' && (typeof val != "string" || val.toLowerCase() != "false"); } -et2_contentArrayMgr.prototype.openPerspective = function(_owner, _root, _col, _row) +et2_arrayMgr.prototype.openPerspective = function(_owner, _root, _col, _row) { // Get the root node var root = typeof _root == "string" ? this.data[_root] : (_root == null ? this.data : _root); // Create a new content array manager with the given root - var mgr = new et2_contentArrayMgr(root, this); + var mgr = new et2_arrayMgr(root, this); // Set the owner mgr.perspectiveData.owner = _owner; diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index 65a5af23f5..35627732f0 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -353,4 +353,18 @@ function et2_csvSplit(_str, _num, _delimiter, _enclosure) return parts; } +/** + * Creates a copy of the given object (non recursive) + */ +function et2_cloneObject(_obj) +{ + var result = {}; + + for (var key in _obj) + { + result[key] = _obj[key]; + } + + return result; +} diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index aa11b061af..4664bf2068 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -88,7 +88,7 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { } // Set the value for this element - var mgr = this.getContentMgr(); + var mgr = this.getArrayMgr("content"); if (_value != '' && mgr != null) { var val = mgr.getValueForID(this.id); diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 33ff1dbbd7..5da9c81b13 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -16,7 +16,7 @@ et2_xml; et2_common; et2_inheritance; - et2_contentArrayMgr; + et2_arrayMgr; */ /** @@ -100,7 +100,7 @@ var et2_widget = Class.extend({ } this.id = ""; - this._mgr = null; + this._mgrs = {}; // Copy the parent parameter and add this widget to its parent children // list. @@ -145,7 +145,7 @@ var et2_widget = Class.extend({ // Delete all references to other objects this._children = []; this._parent = null; - this._mgr = null; + this._mgrs = {}; this.onSetParent(); }, @@ -188,10 +188,7 @@ var et2_widget = Class.extend({ } // Copy a reference to the content array manager - if (_obj._mgr) - { - this._mgr = _obj._mgr; - } + this.setArrayMgrs(_obj.mgrs); }, /** @@ -453,12 +450,12 @@ var et2_widget = Class.extend({ // expression as bool expression. if (attr.type == "boolean") { - attrValue = this.getContentMgr() + attrValue = this.getArrayMgr("content") .parseBoolExpression(attrValue); } else { - attrValue = this.getContentMgr().expandName(attrValue); + attrValue = this.getArrayMgr("content").expandName(attrValue); } } @@ -497,23 +494,6 @@ var et2_widget = Class.extend({ } }, - setContentMgr: function(_mgr) { - this._mgr = _mgr; - }, - - getContentMgr: function() { - if (this._mgr != null) - { - return this._mgr; - } - else if (this._parent) - { - return this._parent.getContentMgr(); - } - - return null; - }, - /** * Fetches all input element values and returns them in an associative * array. Widgets which introduce namespacing can use the internal _target @@ -566,6 +546,67 @@ var et2_widget = Class.extend({ return result; }, + /** + * Sets all array manager objects - this function can be used to set the + * root array managers of the container object. + */ + setArrayMgrs: function(_mgrs) { + this._mgrs = et2_cloneObject(_mgrs); + }, + + /** + * Returns an associative array containing the top-most array managers. + * + * @param _mgrs is used internally and should not be supplied. + */ + getArrayMgrs: function(_mgrs) { + if (typeof _mgrs == "undefined") + { + _mgrs = {}; + } + + // Add all managers of this object to the result, if they have not already + // been set in the result + for (var key in this._mgrs) + { + if (typeof _mgrs[key] == "undefined") + { + _mgrs[key] = this._mgrs[key]; + } + } + + // Recursively applies this function to the parent widget + if (this._parent) + { + this._parent.getArrayMgrs(_mgrs); + } + + return _mgrs; + }, + + /** + * Sets the array manager for the given part + */ + setArrayMgr: function(_part, _mgr) { + this._mgrs[_part] = _mgr; + }, + + /** + * Returns the array manager object for the given part + */ + getArrayMgr: function(_part) { + if (typeof this._mgrs[_part] != "undefined") + { + return this._mgrs[_part]; + } + else if (this._parent) + { + return this._parent.getArrayMgr(_part); + } + + return null; + }, + /** * Checks whether a namespace exists for this element in the content array. * If yes, an own perspective of the content array is created. If not, the @@ -573,27 +614,32 @@ var et2_widget = Class.extend({ */ checkCreateNamespace: function() { // Get the content manager - var mgr = this.getContentMgr(); + var mgrs = this.getArrayMgrs(); - // Get the original content manager if we have already created a - // perspective for this node - if (this._mgr != null && this._mgr.perspectiveData.owner == this) + for (var key in mgrs) { - mgr = mgr.parentMgr; - } + var mgr = mgrs[key]; - // Check whether the manager has a namespace for the id of this object - if (mgr.getEntry(this.id) instanceof Object) - { - // The content manager has a own node for this object, so create - // an own perspective. - this._mgr = mgr.openPerspective(this, this.id); - } - else - { - // The current content manager does not have an own namespace for - // this element, so use the content manager of the parent. - this._mgr = null; + // Get the original content manager if we have already created a + // perspective for this node + if (typeof this._mgrs[key] != "undefined" && mgr.perspectiveData.owner == this) + { + mgr = mgr.parentMgr; + } + + // Check whether the manager has a namespace for the id of this object + if (mgr.getEntry(this.id) instanceof Object) + { + // The content manager has an own node for this object, so + // create an own perspective. + this._mgrs[key] = mgr.openPerspective(this, this.id); + } + else + { + // The current content manager does not have an own namespace for + // this element, so use the content manager of the parent. + delete(this._mgrs[key]); + } } } }); diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js new file mode 100644 index 0000000000..ef7975d42d --- /dev/null +++ b/etemplate/js/etemplate2.js @@ -0,0 +1,97 @@ +/** + * eGroupWare eTemplate2 - JS file which contains the complete et2 module + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +/*egw:uses + // Include all widget classes here + et2_template; + et2_grid; + et2_box; + et2_button; + et2_description; + et2_textbox; + + // Requirements for the etemplate2 object + et2_xml; + et2_arrayMgr; +*/ + +/** + * The etemplate2 class manages a certain etemplate2 instance. + * + * @param _container is the DOM-Node into which the DOM-Nodes of this instance + * should be inserted + * @param _submitURL is the URL to which the form data should be submitted. + */ +function etemplate2(_container, _submitURL) +{ + // Copy the given parameters + this.DOMContainer = _container; + this.submitURL = _submitURL; + + // Preset the object variable + this.widgetContainer = null; +} + +/** + * Clears the current instance. + */ +etemplate2.prototype.clear = function() +{ + if (this.widgetContainer != null) + { + this.widgetContainer.destroy(); + this.widgetContainer = null; + } +} + +/** + * Creates an associative array containing the data array managers for each part + * of the associative data array. A part is something like "content", "readonlys" + * or "sel_options". + */ +etemplate2.prototype._createArrayManagers = function(_data) +{ + var result = {}; + + // Create an array manager object for each part of the _data array. + for (var key in _data) + { + result[key] = new et2_arrayMgr(_data[key]); + } + + return result; +} + +/** + * Loads the template from the given URL and sets the data object + */ +etemplate2.prototype.load = function(_url, _data) +{ + // Asynchronously load the XET file (code below is executed ahead of the + // code in the callback function) + et2_loadXMLFromURL(_url, function(_xmldoc) { + this.widgetContainer.loadFromXML(_xmldoc); + }, this); + + // Clear any existing instance + this.clear(); + + // Create the basic widget container and attach it to the DOM + this.widgetContainer = new et2_container(null); + this.widgetContainer.setParentDOMNode(this.DOMContainer); + + // Split the given data into array manager objects and pass those to the + // widget container + this.widgetContainer.setArrayMgrs(this._createArrayManagers(_data)); +} + + diff --git a/etemplate/js/test/et2_test_expressions.json b/etemplate/js/test/et2_test_expressions.json index 55cbb8a2b6..1f854e19ce 100644 --- a/etemplate/js/test/et2_test_expressions.json +++ b/etemplate/js/test/et2_test_expressions.json @@ -1,9 +1,11 @@ var expression_test_data = { - "test": { - "display_text": "true", - "textbox": "And this is the inner textbox." - }, - "display_text": "false", - "textbox": "This is the outer textbox." + "content": { + "test": { + "display_text": "true", + "textbox": "And this is the inner textbox." + }, + "display_text": "false", + "textbox": "This is the outer textbox." + } }; diff --git a/etemplate/js/test/et2_test_expressions.xet b/etemplate/js/test/et2_test_expressions.xet index 28f38df615..39255a728a 100644 --- a/etemplate/js/test/et2_test_expressions.xet +++ b/etemplate/js/test/et2_test_expressions.xet @@ -2,7 +2,7 @@ <overlay> <template id="test"> <vbox> - <description disabled="!@display_text" value="Dies ist nur ein test!" /> + <description disabled="!@@display_text" value="Dies ist nur ein test!" /> <textbox id="textbox" /> </vbox> </template> diff --git a/etemplate/js/test/et2_test_timesheet_edit.json b/etemplate/js/test/et2_test_timesheet_edit.json index 1c1762df3e..b938f6e34b 100644 --- a/etemplate/js/test/et2_test_timesheet_edit.json +++ b/etemplate/js/test/et2_test_timesheet_edit.json @@ -70,26 +70,6 @@ var timesheet_data = { "tabs":{ "customfields":true } - }, - "preserv":{ - "ts_id":"1", - "ts_project":null, - "ts_title":"Test geschrieben", - "ts_description":null, - "ts_start":1307030400, - "ts_duration":"150", - "ts_quantity":"2.5", - "ts_unitprice":null, - "cat_id":null, - "ts_owner":"5", - "ts_modified":1307039479, - "ts_modifier":"5", - "pl_id":null, - "ts_status":null, - "user_timezone_read":"Europe/Berlin", - "view":false, - "referer":"timesheet.timesheet_ui.index", - "ts_title_blur":null } } diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index f8733ff58b..96adcd2ef5 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -6,6 +6,7 @@ <script src="../et2_xml.js"></script> <script src="../et2_inheritance.js"></script> <script src="../et2_common.js"></script> + <script src="../et2_arrayMgr.js"></script> <script src="../et2_widget.js"></script> <script src="../et2_DOMWidget.js"></script> <script src="../et2_baseWidget.js"></script> @@ -16,7 +17,9 @@ <script src="../et2_button.js"></script> <script src="../et2_box.js"></script> <script src="../et2_textbox.js"></script> - <script src="../et2_contentArrayMgr.js"></script> + + <script src="../etemplate2.js"></script> + <!--<script src="../et2_tabs.js"></script>--> <script src="../lib/tooltip.js"></script> @@ -28,7 +31,7 @@ <h1>EGroupware ETemplate2 Test</h1> <div class="header">Choose one of the following tests:</div> <div id="linklist"> - <a href="#" onclick="open_xet('et2_test_timesheet_edit.xet', timesheet_data.content);">Timesheet edit dialog</a> + <a href="#" onclick="open_xet('et2_test_timesheet_edit.xet', timesheet_data);">Timesheet edit dialog</a> <a href="#" onclick="open_xet('et2_test_template.xet');">Template proxy test</a> <a href="#" onclick="open_xet('et2_test_grid.xet');">Grid test</a> <a href="#" onclick="open_xet('et2_test_tabbox.xet');">Tabs test</a> @@ -40,33 +43,11 @@ <div id="time"></div> <div id="container"></div> <script> - var container = null; + var et2 = new etemplate2(document.getElementById("container"), ""); function open_xet(file, content) { - if (typeof content == "undefined") - { - content = {}; - } - - et2_loadXMLFromURL(file, - function(_xmldoc) { - if (container != null) - { - container.destroy(); - container = null; - } - - var t1 = (new Date).getTime(); - - container = new et2_container(null); - container.setParentDOMNode(document.getElementById("container")); - container.setContentMgr(new et2_contentArrayMgr(content)); - container.loadFromXML(_xmldoc); - - var t2 = (new Date).getTime(); - $j("#time").text("Building the template took " + (t2 - t1) + "ms"); - }); - } + et2.load(file, content); + } </script> </body> </html> From fd21e247a1c081389e60d03e44d228a23b94076c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 12:46:27 +0000 Subject: [PATCH 041/472] etemplate2 object now creates not passed entries in the data array --- etemplate/js/etemplate2.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index ef7975d42d..4b18c73094 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -60,6 +60,22 @@ etemplate2.prototype.clear = function() */ etemplate2.prototype._createArrayManagers = function(_data) { + if (typeof _data == "undefined") + { + _data = {}; + } + + // Create all neccessary _data entries + var neededEntries = ["content", "readonlys", "validation_errors"]; + for (var i = 0; i < neededEntries.length; i++) + { + if (typeof _data[neededEntries[i]] == "undefined") + { + et2_debug("info", "Created not passed entry '" + neededEntries[i] + "' in data array."); + _data[neededEntries[i]] = {}; + } + } + var result = {}; // Create an array manager object for each part of the _data array. From c999373490d4301178f3b0054f418d4a5f0dd984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 14:26:37 +0000 Subject: [PATCH 042/472] Added possibility for egw_json plugins to be executed in the context of the creator of the request object --- phpgwapi/js/egw_json.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/phpgwapi/js/egw_json.js b/phpgwapi/js/egw_json.js index 1467ad7511..ff9353f3b3 100644 --- a/phpgwapi/js/egw_json.js +++ b/phpgwapi/js/egw_json.js @@ -9,6 +9,11 @@ * @version $Id$ */ +/*egw:uses + jsapi.jsapi; // Contains some helper functions + jquery.jquery; // Used for the ajax requests +*/ + /* The egw_json_request is the javaScript side implementation of class.egw_json.inc.php.*/ function _egw_json_escape_string(input) @@ -164,12 +169,19 @@ function egw_json_register_plugin(_callback, _context) /** * Function used internally to pass a response to all registered plugins */ -function _egw_json_plugin_handle(_type, _response) { +function _egw_json_plugin_handle(_type, _response, _context) { for (var i = 0; i < _egw_json_plugins.length; i++) { try { var plugin = _egw_json_plugins[i]; - if (plugin.callback.call(plugin.context, _type, _response)) { + + var context = plugin.context; + if (!plugin.context && typeof _context != "undefined") + { + context = _context; + } + + if (plugin.callback.call(context, _type, _response)) { return true; } } catch (e) { @@ -532,7 +544,7 @@ egw_json_request.prototype.handleResponse = function(data, textStatus, XMLHttpRe } //Try to handle the json response with all registered plugins - hasResponse |= _egw_json_plugin_handle(data.response[i].type, res); + hasResponse |= _egw_json_plugin_handle(data.response[i].type, res, this.context); } catch(e) { this.jsonError('Internal JSON handler error', e); } From 7800cfc5d455bd5437a4de563db0a3d1d67fdd41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 14:29:58 +0000 Subject: [PATCH 043/472] Implemented et2_IInput interface for et2_button in order to transfer the id of the clicked button back to the server, implemented etemplate2.submit function, implemented egw_json et2_load response type to load a new template with new data. --- etemplate/inc/class.etemplate_new.inc.php | 21 +++++++- etemplate/js/et2_button.js | 28 ++++++++--- etemplate/js/et2_widget.js | 34 +++++++++++-- etemplate/js/etemplate2.js | 59 ++++++++++++++++++++++- 4 files changed, 130 insertions(+), 12 deletions(-) diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index 71391a9905..a825d8b3f4 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -103,7 +103,7 @@ class etemplate_new echo ' <div id="container"></div> <script> - var et2 = new etemplate2(document.getElementById("container"), ""); + var et2 = new etemplate2(document.getElementById("container"), "etemplate_new::ajax_process_content"); et2.load("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode(array( 'content' => $content, 'sel_options' => $sel_options, @@ -117,6 +117,25 @@ class etemplate_new } } + /** + * Process via Ajax submitted content + */ + static public function ajax_process_content(array $content) + { + error_log(__METHOD__."(".print_r($content, true).")"); + + $response = egw_json_response::get(); + $response->generic("et2_load", array( + "url" => $GLOBALS['egw_info']['server']['webserver_url']."/etemplate/js/test/et2_test_expressions.xet", + "data" => array( + "content" => array( + "display_text" => "", + "textbox" => "Hello world!" + ) + ) + )); + } + /** * Path of template relative to EGW_SERVER_ROOT * diff --git a/etemplate/js/et2_button.js b/etemplate/js/et2_button.js index 4148371810..796f8db6bb 100644 --- a/etemplate/js/et2_button.js +++ b/etemplate/js/et2_button.js @@ -14,13 +14,14 @@ /*egw:uses jquery.jquery; + et2_inputWidget; et2_baseWidget; */ /** * Class which implements the "button" XET-Tag */ -var et2_button = et2_baseWidget.extend({ +var et2_button = et2_baseWidget.extend(et2_IInput, { attributes: { "label": { @@ -40,6 +41,7 @@ var et2_button = et2_baseWidget.extend({ this._super.apply(this, arguments); this.label = ""; + this.clicked = false; this.btn = $j(document.createElement("button")) .addClass("et2_button") @@ -56,11 +58,10 @@ var et2_button = et2_baseWidget.extend({ return false; } - // Fetch the form data - var formData = this.getRoot().getValues(); - - // Submit it! - console.log(formData); + // Submit the form + this.clicked = true; + this.getInstanceManager().submit(); + this.clicked = false; }, set_label: function(_value) { @@ -70,6 +71,21 @@ var et2_button = et2_baseWidget.extend({ this.btn.text(_value); } + }, + + isDirty: function() { + return true; + }, + + resetDirty: function() { + }, + + getValue: function() { + if (this.clicked) + { + return true; + } + return null; } }); diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 5da9c81b13..0900ca121a 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -101,6 +101,7 @@ var et2_widget = Class.extend({ this.id = ""; this._mgrs = {}; + this._inst = null; // Copy the parent parameter and add this widget to its parent children // list. @@ -506,7 +507,7 @@ var et2_widget = Class.extend({ this.iterateOver(function(_widget) { // Get the path to the node we have to store the value at - var path = _widget.getContentMgr().getPath(); + var path = _widget.getArrayMgr("content").getPath(); // Set the _target variable to that node var _target = result; @@ -537,8 +538,12 @@ var et2_widget = Class.extend({ "', id exists twice!"); } - // Store the value of the widget and reset its dirty flag, - _target[_widget.id] = _widget.getValue(); + // Store the value of the widget and reset its dirty flag + var value = _widget.getValue(); + if (value !== null) + { + _target[_widget.id] = value; + } _widget.resetDirty(); }, this, et2_IInput); @@ -641,6 +646,29 @@ var et2_widget = Class.extend({ delete(this._mgrs[key]); } } + }, + + /** + * Sets the instance manager object (of type etemplate2, see etemplate2.js) + */ + setInstanceManager: function(_inst) { + this._inst = _inst; + }, + + /** + * Returns the instance manager + */ + getInstanceManager: function() { + if (this._inst != null) + { + return this._inst; + } + else if (this._parent) + { + return this._parent.getInstanceManager(); + } + + return null; } }); diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 4b18c73094..efcb17c4c9 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -31,11 +31,16 @@ * should be inserted * @param _submitURL is the URL to which the form data should be submitted. */ -function etemplate2(_container, _submitURL) +function etemplate2(_container, _menuaction) { + if (typeof _menuaction == "undefined") + { + _menuaction = "etemplate_new::ajax_process_content"; + } + // Copy the given parameters this.DOMContainer = _container; - this.submitURL = _submitURL; + this.menuaction = _menuaction; // Preset the object variable this.widgetContainer = null; @@ -103,6 +108,7 @@ etemplate2.prototype.load = function(_url, _data) // Create the basic widget container and attach it to the DOM this.widgetContainer = new et2_container(null); + this.widgetContainer.setInstanceManager(this); this.widgetContainer.setParentDOMNode(this.DOMContainer); // Split the given data into array manager objects and pass those to the @@ -110,4 +116,53 @@ etemplate2.prototype.load = function(_url, _data) this.widgetContainer.setArrayMgrs(this._createArrayManagers(_data)); } +etemplate2.prototype.submit = function() +{ + // Get the form values + var values = this.widgetContainer.getValues(); + + // Create the request object + if (typeof egw_json_request != "undefined") + { + var request = new egw_json_request(this.menuaction, [values], this); + request.sendRequest(true); + } + else + { + console.log(values); + } +} + +/** + * Function which handles the EGW JSON et2_load response + */ +function etemplate2_handle_response(_type, _response) +{ + if (_type == "et2_load") + { + // Check the parameters + var data = _response.data; + if (typeof data.url == "string" && data.data instanceof Object) + { + this.load(data.url, data.data); + return true; + } + + throw("Error while parsing et2_load response"); + } + + return false; +} + +// Register the egw_json result object +if (typeof egw_json_register_plugin != "undefined") +{ + // Calls etemplate2_handle_response in the context of the object which + // requested the response from the server + egw_json_register_plugin(etemplate2_handle_response, null); +} +else +{ + et2_debug("info", "EGW JSON Plugin could not be registered, running ET2 standalone."); +} From 8207a325aaa0d8c97a547fa58745e506c407a51f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 14:52:45 +0000 Subject: [PATCH 044/472] Moved loading of data-array attributes to the new 'loadingFinished' function --- etemplate/inc/class.etemplate_new.inc.php | 2 +- etemplate/js/et2_inputWidget.js | 29 +++++++++++++---------- etemplate/js/et2_widget.js | 11 +++++++++ etemplate/js/etemplate2.js | 2 +- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index a825d8b3f4..d8f0ea314c 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -109,7 +109,7 @@ class etemplate_new 'sel_options' => $sel_options, 'readonlys' => $readonlys, 'modifications' => $this->modifications, - 'validation_errros' => self::$validation_errors, + 'validation_errors' => self::$validation_errors, )).'); </script> '; diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 4664bf2068..dbd18e5669 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -60,6 +60,21 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { this._oldValue = ""; }, + loadingFinished: function() { + this._super.call(this, arguments); + + if (this.id != "") + { + // Set the value for this element + var contentMgr = this.getArrayMgr("content"); + var val = contentMgr.getValueForID(this.id); + if (val !== null) + { + this.set_value(val); + } + } + }, + set_value: function(_value) { this._oldValue = _value; @@ -73,7 +88,8 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { set_id: function(_value) { this.id = _value; - // Set the id of the input node + // Set the id of the _input_ node (in contrast to the default + // implementation, which sets the base node) var node = this.getInputNode(); if (node) { @@ -86,17 +102,6 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { node.removeAttribute("id"); } } - - // Set the value for this element - var mgr = this.getArrayMgr("content"); - if (_value != '' && mgr != null) - { - var val = mgr.getValueForID(this.id); - if (val !== null) - { - this.set_value(val); - } - } }, get_value: function() { diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 0900ca121a..f0b6f9d4d4 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -383,6 +383,9 @@ var et2_widget = Class.extend({ var widget = new constructor(this, _nodeName) widget.loadFromXML(_node); + // Call the "loadFinished" function of the widget + widget.loadingFinished(); + return widget; }, @@ -472,6 +475,14 @@ var et2_widget = Class.extend({ loadContent: function(_content) { }, + /** + * Called when loading of the widget from XML node is finished. This + * function can be used to load the data from the data arrays (content, + * readonlys, sel_options etc.) + */ + loadingFinished: function() { + }, + /** * Calls the setter of each property with its current value, calls the * update function of all child nodes. diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index efcb17c4c9..b3f7de3e3d 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -71,7 +71,7 @@ etemplate2.prototype._createArrayManagers = function(_data) } // Create all neccessary _data entries - var neededEntries = ["content", "readonlys", "validation_errors"]; + var neededEntries = ["content", "sel_options", "readonlys", "modifications", "validation_errors"]; for (var i = 0; i < neededEntries.length; i++) { if (typeof _data[neededEntries[i]] == "undefined") From 3bdca867e7853ef25853362e6bcb10c12bdb31ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Mon, 15 Aug 2011 16:03:53 +0000 Subject: [PATCH 045/472] et2_debug is now capable of taking any count of arguments as the console.* functions do, improved 'Attribute does not exist' message, fixed memory leak in grid (inherited destructor was not called) --- etemplate/js/et2_button.js | 13 ++++++++++++- etemplate/js/et2_common.js | 17 ++++++++++++----- etemplate/js/et2_grid.js | 2 ++ etemplate/js/et2_inheritance.js | 4 ++-- etemplate/js/et2_widget.js | 2 +- etemplate/js/etemplate2.js | 2 +- etemplate/js/lib/tooltip.js | 6 ++++++ etemplate/js/test/et2_test_textbox.xet | 6 ++++-- 8 files changed, 40 insertions(+), 12 deletions(-) diff --git a/etemplate/js/et2_button.js b/etemplate/js/et2_button.js index 796f8db6bb..2f5de7a5be 100644 --- a/etemplate/js/et2_button.js +++ b/etemplate/js/et2_button.js @@ -73,8 +73,16 @@ var et2_button = et2_baseWidget.extend(et2_IInput, { } }, + + /** + * Implementation of the et2_IInput interface + */ + + /** + * Always return false as a button is never dirty + */ isDirty: function() { - return true; + return false; }, resetDirty: function() { @@ -85,6 +93,9 @@ var et2_button = et2_baseWidget.extend(et2_IInput, { { return true; } + + // If "null" is returned, the result is not added to the submitted + // array. return null; } diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index 35627732f0..dd4ebc4ec9 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -31,32 +31,39 @@ if (typeof Array.prototype.indexOf == "undefined") */ var ET2_DEBUGLEVEL = 4; -function et2_debug(_level, _msg) +function et2_debug(_level) { if (typeof console != "undefined") { + // Get the passed parameters and remove the first entry + var args = []; + for (var i = 1; i < arguments.length; i++) + { + args.push(arguments[i]); + } + if (_level == "log" && ET2_DEBUGLEVEL >= 4 && typeof console.log == "function") { - console.log(_msg); + console.log.apply(console, args); } if (_level == "info" && ET2_DEBUGLEVEL >= 3 && typeof console.info == "function") { - console.info(_msg); + console.info.apply(console, args); } if (_level == "warn" && ET2_DEBUGLEVEL >= 2 && typeof console.warn == "function") { - console.warn(_msg); + console.warn.apply(console, args); } if (_level == "error" && ET2_DEBUGLEVEL >= 1 && typeof console.error == "function") { - console.error(_msg); + console.error.apply(console, args); } } } diff --git a/etemplate/js/et2_grid.js b/etemplate/js/et2_grid.js index aaa5843d5f..a1c89e7fea 100644 --- a/etemplate/js/et2_grid.js +++ b/etemplate/js/et2_grid.js @@ -43,6 +43,8 @@ var et2_grid = et2_DOMWidget.extend({ }, destroy: function() { + this._super.call(this, arguments); + // Delete all references to cells or widgets this.cells = null; this.managementArray = null; diff --git a/etemplate/js/et2_inheritance.js b/etemplate/js/et2_inheritance.js index 9e40a275af..e122b23878 100644 --- a/etemplate/js/et2_inheritance.js +++ b/etemplate/js/et2_inheritance.js @@ -314,7 +314,7 @@ } else { - et2_error("error", "Attribute '" + _name + "' does not exist!"); + et2_error("error", this, "Attribute '" + _name + "' does not exist!"); } } @@ -348,7 +348,7 @@ } else { - et2_debug("warn", "Attribute '" + _name + "' does not exist!"); + et2_debug("warn", this, "Attribute '" + _name + "' does not exist!"); } } diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index f0b6f9d4d4..7ec9895a9d 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -545,7 +545,7 @@ var et2_widget = Class.extend({ // Check whether the entry is really undefined if (typeof _target[_widget.id] != "undefined") { - et2_debug("error", "Overwriting value of '" + _widget.id + + et2_debug("error", _widget, "Overwriting value of '" + _widget.id + "', id exists twice!"); } diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index b3f7de3e3d..63826057e7 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -76,7 +76,7 @@ etemplate2.prototype._createArrayManagers = function(_data) { if (typeof _data[neededEntries[i]] == "undefined") { - et2_debug("info", "Created not passed entry '" + neededEntries[i] + "' in data array."); + et2_debug("log", "Created not passed entry '" + neededEntries[i] + "' in data array."); _data[neededEntries[i]] = {}; } } diff --git a/etemplate/js/lib/tooltip.js b/etemplate/js/lib/tooltip.js index 8c810f7948..60521dbfcb 100644 --- a/etemplate/js/lib/tooltip.js +++ b/etemplate/js/lib/tooltip.js @@ -70,6 +70,12 @@ egw_tooltip.prototype.bindToElement = function(_elem, _text) egw_tooltip.prototype.unbindFromElement = function(_elem) { + if (this.current_elem == _elem) + { + this.hide(); + this.current_elem = null; + } + _elem.unbind('mouseenter.tooltip'); _elem.unbind('mouseleave.tooltip'); _elem.unbind('mousemove.tooltip'); diff --git a/etemplate/js/test/et2_test_textbox.xet b/etemplate/js/test/et2_test_textbox.xet index c9e73a7c6f..fcfee62023 100644 --- a/etemplate/js/test/et2_test_textbox.xet +++ b/etemplate/js/test/et2_test_textbox.xet @@ -1,13 +1,15 @@ <?xml version="1.0"?> <overlay> - <textbox id="test1" value="This is a single line textbox." statustext="Write something here!"/> + <textbox id="test1" value="This is a single line textbox."/> <textbox id="test2" multiline="true" value="This is a multi line textbox."/> <template id="testbox"> - <textbox id="test3" value="This is a single line textbox." statustext="And something else here!"/> + <textbox id="test3" value="This is a single line textbox."/> <textbox id="test4" multiline="true" value="This is a multi line textbox."/> </template> <template id="testbox"/> + + <button label="test" onclick="open_xet('et2_test_textbox.xet');" statustext="button"/> </overlay> From b176cb9256c8cb52277cbf1e63ea55c5db140504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans-J=C3=BCrgen=20Tappe?= <hj.tappe@web.de> Date: Mon, 15 Aug 2011 16:25:08 +0000 Subject: [PATCH 046/472] - Allow sitemgr blocks to be moved between pages, categories and websitewide (previously only moving from a page up to the cat, then up globally was possible). - Allow options within a select to be formatted through the standard html::select_option() function --- phpgwapi/inc/class.html.inc.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/phpgwapi/inc/class.html.inc.php b/phpgwapi/inc/class.html.inc.php index 5a25532776..d64466a159 100644 --- a/phpgwapi/inc/class.html.inc.php +++ b/phpgwapi/inc/class.html.inc.php @@ -471,9 +471,10 @@ class html * @param string $label label * @param mixed $selected value or array of values of options to mark as selected * @param boolean $no_lang NOT running the label through lang(), default false=use lang() + * @param string $extra extra text, e.g.: style="", default: '' * @return string html */ - static function select_option($value,$label,$selected,$no_lang=0,$title='') + static function select_option($value,$label,$selected,$no_lang=0,$title='',$extra='') { // the following compares strict as strings, to archive: '0' == 0 != '' // the first non-strict search via array_search, is for performance reasons, to not always search the whole array with php @@ -486,7 +487,8 @@ class html } } return '<option value="'.self::htmlspecialchars($value).'"'.($found ? ' selected="selected"' : '') . - ($title ? ' title="'.self::htmlspecialchars($no_lang ? $title : lang($title)).'"' : '') . '>'. + ($title ? ' title="'.self::htmlspecialchars($no_lang ? $title : lang($title)).'"' : '') . + ($extra ? ' ' . $extra : '') . '>'. self::htmlspecialchars($no_lang || $label == '' ? $label : lang($label)) . "</option>\n"; } From 4fe9d951a8f87ecc30d4ed571f771f001201a9ee Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Mon, 15 Aug 2011 18:54:13 +0000 Subject: [PATCH 047/472] Fix typo --- etemplate/js/et2_common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index dd4ebc4ec9..15bf011d77 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -305,7 +305,7 @@ function et2_csvSplit(_str, _num, _delimiter, _enclosure) // Default the parameters if (typeof _num == "undefined") { - _num == null; + _num = null; } if (typeof _delimiter == "undefined") From 8996f45e9ec198ac4c216eb0d3438a9ccf02698f Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Tue, 16 Aug 2011 10:20:40 +0000 Subject: [PATCH 048/472] * Calendar: not using freebusy rights for searching calendar, as it would allow to probe for event contents - optimised private event filter for searching to not query private grants (again) from database --- calendar/inc/class.calendar_bo.inc.php | 20 ++++++++++++++++---- calendar/inc/class.calendar_so.inc.php | 10 ++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php index bb1f10cfdc..1958142a2f 100644 --- a/calendar/inc/class.calendar_bo.inc.php +++ b/calendar/inc/class.calendar_bo.inc.php @@ -313,9 +313,10 @@ class calendar_bo * @param int|array $_users * @param boolean $no_enum_groups=true * @param boolean $ignore_acl=false + * @param boolean $use_freebusy=true should freebusy rights are taken into account, default true, can be set to false eg. for a search * @return array of user-ids */ - private function resolve_users($_users, $no_enum_groups=true, $ignore_acl=false) + private function resolve_users($_users, $no_enum_groups=true, $ignore_acl=false, $use_freebusy=true) { if (!is_array($_users)) { @@ -326,7 +327,7 @@ class calendar_bo foreach($_users as $user) { $user = trim($user); - if ($params['ignore_acl'] || $this->check_perms(EGW_ACL_READ|EGW_ACL_READ_FOR_PARTICIPANTS|EGW_ACL_FREEBUSY,0,$user)) + if ($ignore_acl || $this->check_perms(EGW_ACL_READ|EGW_ACL_READ_FOR_PARTICIPANTS|($use_freebusy?EGW_ACL_FREEBUSY:0),0,$user)) { if ($user && !in_array($user,$users)) // already added? { @@ -352,7 +353,7 @@ class calendar_bo { // use only members which gave the user a read-grant if (!in_array($member['account_id'],$users) && - ($params['ignore_acl'] || $this->check_perms(EGW_ACL_READ|EGW_ACL_FREEBUSY,0,$member['account_id']))) + ($params['ignore_acl'] || $this->check_perms(EGW_ACL_READ|($use_freebusy?EGW_ACL_FREEBUSY:0),0,$member['account_id']))) { $users[] = $member['account_id']; } @@ -428,7 +429,18 @@ class calendar_bo $params['users'] = $params['query'] ? array_keys($this->grants) : $this->user; } // resolve users to add memberships for users and members for groups - $users = $this->resolve_users($params['users'], $params['filter'] == 'no-enum-groups', $params['ignore_acl']); + // for search, do NOT use freebusy rights, as it would allow to probe the content of event entries + $users = $this->resolve_users($params['users'], $params['filter'] == 'no-enum-groups', $params['ignore_acl'], empty($params['query'])); + + // supply so with private_grants, to not query them again from the database + if (!empty($params['query'])) + { + $params['private_grants'] = array(); + foreach($this->grants as $user => $rights) + { + if ($rights & EGW_ACL_PRIVATE) $params['private_grants'][] = $user; + } + } // replace (by so not understood filter 'no-enum-groups' with 'default' filter if ($params['filter'] == 'no-enum-groups') diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php index d4c840f8b0..11390c0cf0 100644 --- a/calendar/inc/class.calendar_so.inc.php +++ b/calendar/inc/class.calendar_so.inc.php @@ -404,10 +404,12 @@ class calendar_so $where[] = '('.implode(' OR ',$to_or).')'; // Searching - restrict private to own or private grant - $private_grants = $GLOBALS['egw']->acl->get_ids_for_location($GLOBALS['egw_info']['user']['account_id'], EGW_ACL_PRIVATE, 'calendar'); - $private_filter = '(cal_public=1 OR cal_owner = ' . $GLOBALS['egw_info']['user']['account_id']; - if($private_grants) $private_filter .= ' OR cal_public=0 AND cal_owner IN (' . implode(',',$private_grants) . ')'; - $private_filter .= ')'; + if (!isset($params['private_grants'])) + { + $params['private_grants'] = $GLOBALS['egw']->acl->get_ids_for_location($GLOBALS['egw_info']['user']['account_id'], EGW_ACL_PRIVATE, 'calendar'); + $params['private_grants'][] = $GLOBALS['egw_info']['user']['account_id']; // db query does NOT return current user + } + $private_filter = '(cal_public=1 OR cal_public=0 AND '.$this->db->expression($this->cal_table, array('cal_owner' => $params['private_grants'])) . ')'; $where[] = $private_filter; } if (!empty($params['sql_filter']) && is_string($params['sql_filter'])) From 697a1131715ea993be0d44097968042c8b85bce5 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Tue, 16 Aug 2011 11:44:33 +0000 Subject: [PATCH 049/472] url need to run throught htmlspecialchars too (like every attribute in html markup), eg. "x®_id=" fails otherwise --- phpgwapi/inc/class.html.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpgwapi/inc/class.html.inc.php b/phpgwapi/inc/class.html.inc.php index d64466a159..31dd57de1d 100644 --- a/phpgwapi/inc/class.html.inc.php +++ b/phpgwapi/inc/class.html.inc.php @@ -1061,7 +1061,7 @@ class html $url = self::link($url,$vars); } //echo "<p>html::a_href('".htmlspecialchars($content)."','$url',".print_r($vars,True).") = ".self::link($url,$vars)."</p>"; - return '<a href="'.$url.'" '.$options.'>'.$content.'</a>'; + return '<a href="'.htmlspecialchars($url).'" '.$options.'>'.$content.'</a>'; } /** From 41787c36f3a4eb4593c9632d69045bd68fe9f7bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Tue, 16 Aug 2011 12:31:18 +0000 Subject: [PATCH 050/472] - Reading readonly properties - Added system for readonlys: Readonly is passed in constructor as third parameter. If a widget class is registerd with "[type]_ro" (see et2_textbox for example) this one is created - Added new 'valueWidget' base class which introduces the 'value' attribute and implements auto loading from the content array - Implemented readonly attribute for buttons and textboxes --- etemplate/js/et2_arrayMgr.js | 452 ++++++++++-------- etemplate/js/et2_button.js | 16 +- etemplate/js/et2_common.js | 5 + etemplate/js/et2_description.js | 18 +- etemplate/js/et2_grid.js | 2 + etemplate/js/et2_inheritance.js | 2 +- etemplate/js/et2_inputWidget.js | 28 +- etemplate/js/et2_textbox.js | 35 ++ etemplate/js/et2_valueWidget.js | 50 ++ etemplate/js/et2_widget.js | 28 +- etemplate/js/etemplate2.js | 8 +- etemplate/js/test/et2_test_expressions.json | 3 + etemplate/js/test/et2_test_expressions.xet | 2 +- .../js/test/et2_test_timesheet_edit.json | 5 +- etemplate/js/test/test_xml.html | 1 + 15 files changed, 398 insertions(+), 257 deletions(-) create mode 100644 etemplate/js/et2_valueWidget.js diff --git a/etemplate/js/et2_arrayMgr.js b/etemplate/js/et2_arrayMgr.js index a3004352be..6882b62f8f 100644 --- a/etemplate/js/et2_arrayMgr.js +++ b/etemplate/js/et2_arrayMgr.js @@ -10,233 +10,277 @@ * @version $Id$ */ +/*egw:uses + et2_inheritance; +*/ + "use strict"; -function et2_arrayMgr(_data, _parentMgr) -{ - if (typeof _parentMgr == "undefined") - { - _parentMgr = null; - } +var et2_arrayMgr = Class.extend({ - // Copy the parent manager which is needed to access relative data when - // being in a relative perspective of the manager - this.parentMgr = _parentMgr; + splitIds: true, - // Hold a reference to the data - if (typeof _data == "undefined" || !_data) - { - et2_debug("error", "Invalid data passed to content array manager!"); - _data = {}; - } - - this.data = _data; - - // Holds information about the current perspective - this.perspectiveData = { - "owner": null, - "key": null, - "col": 0, - "row": 0 - } -} - -/** - * Returns the root content array manager object - */ -et2_arrayMgr.prototype.getRoot = function() -{ - if (this.parentMgr != null) - { - return this.parentMgr.getRoot(); - } - - return this; -} - -et2_arrayMgr.prototype.getValueForID = function(_id) -{ - if (typeof this.data[_id] != "undefined") - { - return this.data[_id]; - } - - return null; -} - -/** - * Returns the path to this content array manager perspective as an array - * containing the key values - * - * @param _path is used internally, do not supply it manually. - */ -et2_arrayMgr.prototype.getPath = function(_path) -{ - if (typeof _path == "undefined") - { - _path = []; - } - - if (this.perspectiveData.key != null) - { - _path.push(this.perspectiveData.key); - } - - if (this.parentMgr != null) - { - this.parentMgr.getPath(_path); - } - - return _path; -} - -/** - * Get array entry is the equivalent to the boetemplate get_array function. - * It returns a reference to the (sub) array with the given key. This also works - * for keys using the ETemplate referencing scheme like a[b][c] - * - * @param _key is the string index, may contain sub-indices like a[b] - * @param _referenceInto if true none-existing sub-arrays/-indices get created - * to be returned as reference, else false is returned. Defaults to false - * @param _skipEmpty returns false if _key is not present in this content array. - * Defaults to false. - */ -et2_arrayMgr.prototype.getEntry = function(_key, _referenceInto, - _skipEmpty) -{ - if (typeof _referenceInto == "undefined") - { - _referenceInto = false; - } - - if (typeof _skipEmpty == "undefined") - { - _skipEmpty = false; - } - - // Parse the given key by removing the "]"-chars and splitting at "[" - var indexes = _key.replace(/]/g,'').split('['); - - var entry = this.data; - for (var i = 0; i < indexes.length; i++) - { - // Abort if the current entry is not an object (associative array) and - // we should descend further into it. - var isObject = entry instanceof Object; - if (!isObject && !_referenceInto) + init: function(_data, _parentMgr) { + if (typeof _parentMgr == "undefined") { - return false; + _parentMgr = null; } - // Check whether the entry actually exists - var idx = indexes[i]; - if (_skipEmpty && (!isObject || typeof entry[idx] == "undefined")) + // Copy the parent manager which is needed to access relative data when + // being in a relative perspective of the manager + this.parentMgr = _parentMgr; + + // Hold a reference to the data + if (typeof _data == "undefined" || !_data) { - return false; + et2_debug("error", "Invalid data passed to content array manager!"); + _data = {}; } - entry = entry[idx]; - } + this.data = _data; - return entry; -} - -/** - * Equivaltent to the boetemplate::expand_name function. - * - * Expands variables inside the given identifier to their values inside the - * content array. - */ -et2_arrayMgr.prototype.expandName = function(_ident) -{ - // Check whether the identifier refers to an index in the content array - var is_index_in_content = _ident.charAt(0) == '@'; - - // Check whether "$" occurs in the given identifier - var pos_var = _ident.indexOf('$'); - if (pos_var >= 0) - { - // TODO - } - - if (is_index_in_content) - { - // If an additional "@" is specified, this means that we have to return - // the entry from the root element - if (_ident.charAt(1) == '@') - { - _ident = this.getRoot().getEntry(_ident.substr(2)); + // Holds information about the current perspective + this.perspectiveData = { + "owner": null, + "key": null, + "col": 0, + "row": 0 } - else + }, + + /** + * Returns the root content array manager object + */ + getRoot : function() { + if (this.parentMgr != null) { - _ident = this.getEntry(_ident.substr(1)); - } - } - - return _ident; -} - -et2_arrayMgr.prototype.parseBoolExpression = function(_expression) -{ - // If the first char of the expression is a '!' this means, that the value - // is to be negated. - if (_expression.charAt(0) == '!') - { - return !this.parseBoolExpression(_expression.substr(1)); - } - - // Split the expression at a possible "=" - var parts = _expression.split('='); - - // Expand the first value - var val = this.expandName(parts[0]); - - // If a second expression existed, test that one - if (typeof parts[1] != "undefined") - { - // Expand the second value - var checkVal = this.expandName(parts[1]); - - // Values starting with / are treated as regular expression. It is - // checked whether the first value matches the regular expression - if (checkVal.charAt(0) == '/') - { - return (new RegExp(checkVal.substr(1, checkVal.length - 2))) - .match(val) ? true : false; + return this.parentMgr.getRoot(); } - // Otherwise check for simple equality - return val == checkVal; - } + return this; + }, - return val != '' && (typeof val != "string" || val.toLowerCase() != "false"); -} + getValueForID : function(_id) { + if (typeof this.data[_id] != "undefined") + { + return this.data[_id]; + } -et2_arrayMgr.prototype.openPerspective = function(_owner, _root, _col, _row) -{ - // Get the root node - var root = typeof _root == "string" ? this.data[_root] : - (_root == null ? this.data : _root); + return null; + }, - // Create a new content array manager with the given root - var mgr = new et2_arrayMgr(root, this); + /** + * Returns the path to this content array manager perspective as an array + * containing the key values + * + * @param _path is used internally, do not supply it manually. + */ + getPath : function(_path) { + if (typeof _path == "undefined") + { + _path = []; + } - // Set the owner - mgr.perspectiveData.owner = _owner; + if (this.perspectiveData.key != null) + { + _path.push(this.perspectiveData.key); + } - // Set the root key - if (typeof _root == "string") + if (this.parentMgr != null) + { + this.parentMgr.getPath(_path); + } + + return _path; + }, + + /** + * Get array entry is the equivalent to the boetemplate get_array function. + * It returns a reference to the (sub) array with the given key. This also works + * for keys using the ETemplate referencing scheme like a[b][c] + * + * @param _key is the string index, may contain sub-indices like a[b] + * @param _referenceInto if true none-existing sub-arrays/-indices get created + * to be returned as reference, else false is returned. Defaults to false + * @param _skipEmpty returns false if _key is not present in this content array. + * Defaults to false. + */ + getEntry : function(_key, _referenceInto, _skipEmpty) { + if (typeof _referenceInto == "undefined") + { + _referenceInto = false; + } + + if (typeof _skipEmpty == "undefined") + { + _skipEmpty = false; + } + + // Parse the given key by removing the "]"-chars and splitting at "[" + var indexes = [_key]; + + if (this.splitIds) + { + indexes = _key.replace(/]/g,'').split('['); + } + + var entry = this.data; + for (var i = 0; i < indexes.length; i++) + { + // Abort if the current entry is not an object (associative array) and + // we should descend further into it. + var isObject = entry instanceof Object; + if (!isObject && !_referenceInto) + { + return null; + } + + // Check whether the entry actually exists + var idx = indexes[i]; + if (_skipEmpty && (!isObject || typeof entry[idx] == "undefined")) + { + return null; + } + + entry = entry[idx]; + } + + return entry; + }, + + /** + * Equivaltent to the boetemplate::expand_name function. + * + * Expands variables inside the given identifier to their values inside the + * content array. + */ + expandName : function(_ident) { + // Check whether the identifier refers to an index in the content array + var is_index_in_content = _ident.charAt(0) == '@'; + + // Check whether "$" occurs in the given identifier + var pos_var = _ident.indexOf('$'); + if (pos_var >= 0) + { + // TODO + } + + if (is_index_in_content) + { + // If an additional "@" is specified, this means that we have to return + // the entry from the root element + if (_ident.charAt(1) == '@') + { + _ident = this.getRoot().getEntry(_ident.substr(2)); + } + else + { + _ident = this.getEntry(_ident.substr(1)); + } + } + + return _ident; + }, + + parseBoolExpression: function(_expression) { + // If the first char of the expression is a '!' this means, that the value + // is to be negated. + if (_expression.charAt(0) == '!') + { + return !this.parseBoolExpression(_expression.substr(1)); + } + + // Split the expression at a possible "=" + var parts = _expression.split('='); + + // Expand the first value + var val = this.expandName(parts[0]); + + // If a second expression existed, test that one + if (typeof parts[1] != "undefined") + { + // Expand the second value + var checkVal = this.expandName(parts[1]); + + // Values starting with / are treated as regular expression. It is + // checked whether the first value matches the regular expression + if (checkVal.charAt(0) == '/') + { + return (new RegExp(checkVal.substr(1, checkVal.length - 2))) + .match(val) ? true : false; + } + + // Otherwise check for simple equality + return val == checkVal; + } + + return val != '' && (typeof val != "string" || val.toLowerCase() != "false"); + }, + + openPerspective: function(_owner, _root, _col, _row) { - mgr.perspectiveData.key = _root; + // Get the root node + var root = typeof _root == "string" ? this.data[_root] : + (_root == null ? this.data : _root); + + // Create a new content array manager with the given root + var mgr = new et2_arrayMgr(root, this); + + // Set the owner + mgr.perspectiveData.owner = _owner; + + // Set the root key + if (typeof _root == "string") + { + mgr.perspectiveData.key = _root; + } + + // Set the _col and _row parameter + if (typeof _col != "undefined" && typeof _row != "undefined") + { + mgr.perspectiveData.col = _col; + mgr.perspectiveData.row = _row; + } + + return mgr; } - // Set the _col and _row parameter - if (typeof _col != "undefined" && typeof _row != "undefined") - { - mgr.perspectiveData.col = _col; - mgr.perspectiveData.row = _row; +}); + +var et2_readonlysArrayMgr = et2_arrayMgr.extend({ + + splitIds: false, + + isReadOnly: function(_id, _attr, _parent) { + var entry = null; + + if (_id != null) + { + entry = this.getEntry(_id); + } + + // Let the array entry override the read only attribute entry + if (typeof entry != "undefined" && !(entry instanceof Object)) + { + return entry; + } + + // If the attribute is set, return that + if (typeof _attr != "undefined" && _attr !== null) + { + return et2_evalBool(_attr); + } + + // Otherwise take into accounf whether the parent is readonly + if (typeof _parent != "undefined" && _parent) + { + return true; + } + + // Otherwise return the default value + return (typeof this.getEntry("__ALL__") != "undefined"); } - return mgr; -} +}); + diff --git a/etemplate/js/et2_button.js b/etemplate/js/et2_button.js index 2f5de7a5be..a3ee5c5605 100644 --- a/etemplate/js/et2_button.js +++ b/etemplate/js/et2_button.js @@ -37,17 +37,21 @@ var et2_button = et2_baseWidget.extend(et2_IInput, { } }, - init: function(_parent) { + init: function(_parent, _type, _readonly) { this._super.apply(this, arguments); this.label = ""; this.clicked = false; + this.btn = null; - this.btn = $j(document.createElement("button")) - .addClass("et2_button") - .click(this, function(e) {e.data.buttonClick()}); + if (!_readonly) + { + this.btn = $j(document.createElement("button")) + .addClass("et2_button") + .click(this, function(e) {e.data.buttonClick()}); - this.setDOMNode(this.btn[0]); + this.setDOMNode(this.btn[0]); + } }, buttonClick: function() { @@ -65,7 +69,7 @@ var et2_button = et2_baseWidget.extend(et2_IInput, { }, set_label: function(_value) { - if (_value != this.value) + if (this.btn) { this.label = _value; diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index 15bf011d77..62e73dd610 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -87,6 +87,11 @@ var et2_typeDefaults = { "any": null }; +function et2_evalBool(_val) +{ + return _val ? true : false; +} + /** * Checks whether the given value is of the given type. Strings are converted * into the corresponding type. The (converted) value is returned. All supported diff --git a/etemplate/js/et2_description.js b/etemplate/js/et2_description.js index 883175afab..4fd5985295 100644 --- a/etemplate/js/et2_description.js +++ b/etemplate/js/et2_description.js @@ -88,23 +88,17 @@ var et2_description = et2_baseWidget.extend({ this.setDOMNode(this.span[0]); }, - set_value: function(_value, _force) { - if (_value != this.value || _force) - { - this.value = _value; + set_value: function(_value) { + this.value = _value; - this.span.text(_value); - } + this.span.text(_value); }, set_font_style: function(_value) { - if (_value != this.font_style) - { - this.font_style = _value; + this.font_style = _value; - this.span.toggleClass("et2_bold", _value.indexOf("b") >= 0); - this.span.toggleClass("et2_italic", _value.indexOf("i") >= 0); - } + this.span.toggleClass("et2_bold", _value.indexOf("b") >= 0); + this.span.toggleClass("et2_italic", _value.indexOf("i") >= 0); } }); diff --git a/etemplate/js/et2_grid.js b/etemplate/js/et2_grid.js index a1c89e7fea..2e13265808 100644 --- a/etemplate/js/et2_grid.js +++ b/etemplate/js/et2_grid.js @@ -48,6 +48,8 @@ var et2_grid = et2_DOMWidget.extend({ // Delete all references to cells or widgets this.cells = null; this.managementArray = null; + this.table = null; + this.tbody = null; }, _initCells: function(_colData, _rowData) { diff --git a/etemplate/js/et2_inheritance.js b/etemplate/js/et2_inheritance.js index e122b23878..afcd6a7b1e 100644 --- a/etemplate/js/et2_inheritance.js +++ b/etemplate/js/et2_inheritance.js @@ -314,7 +314,7 @@ } else { - et2_error("error", this, "Attribute '" + _name + "' does not exist!"); + et2_debug("error", this, "Attribute '" + _name + "' does not exist!"); } } diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index dbd18e5669..9b36cf8315 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -14,7 +14,7 @@ /*egw:uses jquery.jquery; - et2_baseWidget; + et2_valueWidget; */ /** @@ -43,16 +43,7 @@ var et2_IInput = new Interface({ * interface. When derriving from this class, call setDOMNode with an input * DOMNode. */ -var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { - - attributes: { - "value": { - "name": "Value", - "description": "The value of the widget", - "type": "string", - "default": et2_no_init - } - }, +var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { init: function() { this._super.apply(this, arguments); @@ -60,21 +51,6 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { this._oldValue = ""; }, - loadingFinished: function() { - this._super.call(this, arguments); - - if (this.id != "") - { - // Set the value for this element - var contentMgr = this.getArrayMgr("content"); - var val = contentMgr.getValueForID(this.id); - if (val !== null) - { - this.set_value(val); - } - } - }, - set_value: function(_value) { this._oldValue = _value; diff --git a/etemplate/js/et2_textbox.js b/etemplate/js/et2_textbox.js index fcf36ac85a..b9f48059d2 100644 --- a/etemplate/js/et2_textbox.js +++ b/etemplate/js/et2_textbox.js @@ -15,6 +15,7 @@ /*egw:uses jquery.jquery; et2_inputWidget; + et2_valueWidget; */ /** @@ -71,3 +72,37 @@ var et2_textbox = et2_inputWidget.extend({ et2_register_widget(et2_textbox, ["textbox", "int", "float"]); +/** + * et2_textbox_ro is the dummy readonly implementation of the textbox. + */ +var et2_textbox_ro = et2_valueWidget.extend({ + + /** + * Ignore all more advanced attributes. + */ + attributes: { + "multiline": { + "ignore": true + } + }, + + init: function() { + this._super.apply(this, arguments); + + this.value = ""; + this.span = $j(document.createElement("span")) + .addClass("et2_textbox_ro"); + + this.setDOMNode(this.span[0]); + }, + + set_value: function(_value) { + this.value = _value; + + this.span.text(_value); + } + +}); + +et2_register_widget(et2_textbox_ro, ["textbox_ro", "int_ro", "float_ro"]); + diff --git a/etemplate/js/et2_valueWidget.js b/etemplate/js/et2_valueWidget.js new file mode 100644 index 0000000000..ec00c47ad5 --- /dev/null +++ b/etemplate/js/et2_valueWidget.js @@ -0,0 +1,50 @@ +/** + * eGroupWare eTemplate2 - JS widget class with value attribute and auto loading + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +/*egw:uses + jquery.jquery; + et2_baseWidget; +*/ + +/** + * et2_valueWidget is the base class for et2_inputWidget - valueWidget introduces + * the "value" attribute and automatically loads it from the "content" array + * after loading from XML. + */ +var et2_valueWidget = et2_baseWidget.extend({ + + attributes: { + "value": { + "name": "Value", + "description": "The value of the widget", + "type": "string", + "default": et2_no_init + } + }, + + loadingFinished: function() { + this._super.call(this, arguments); + + if (this.id != "") + { + // Set the value for this element + var contentMgr = this.getArrayMgr("content"); + var val = contentMgr.getValueForID(this.id); + if (val !== null) + { + this.setAttribute("value", val) + } + } + } + +}); + diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 7ec9895a9d..ef84536148 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -74,6 +74,14 @@ var et2_widget = Class.extend({ */ "type": { "ignore": true + }, + + /** + * Ignore the readonly tag by default - its also read by the + * "createElementFromNode" function. + */ + "readonly": { + "ignore": true } }, @@ -92,7 +100,7 @@ var et2_widget = Class.extend({ * @param _type is the node name with which the widget has been created. This * is usefull if a single widget class implements multiple XET-Node widgets. */ - init: function(_parent, _type) { + init: function(_parent, _type, _readonly) { if (typeof _type == "undefined") { @@ -115,6 +123,7 @@ var et2_widget = Class.extend({ this._children = []; this.type = _type; + this.readonly = _readonly; // The supported widget classes array defines a whitelist for all widget // classes or interfaces child widgets have to support. @@ -164,7 +173,7 @@ var et2_widget = Class.extend({ } // Create the copy - var copy = new (this.constructor)(_parent, _type); + var copy = new (this.constructor)(_parent, _type, this.readonly); // Assign this element to the copy copy.assign(this); @@ -374,13 +383,24 @@ var et2_widget = Class.extend({ _nodeName = _node.nodeName.toLowerCase(); } - // Check whether a widget with the given type is registered. + // Get the constructor for that widget var constructor = typeof et2_registry[_nodeName] == "undefined" ? et2_placeholder : et2_registry[_nodeName]; + // Check whether the widget is marked as readonly and whether a special + // readonly type (suffixed with "_ro") is registered + var readonly = this.getArrayMgr("readonlys").isReadOnly( + _node.getAttribute("id"), _node.getAttribute("readonly"), this.readonly); + et2_debug("log", _node.getAttribute("id"), readonly); + if (readonly && typeof et2_registry[_nodeName + "_ro"] != "undefined") + { + constructor = et2_registry[_nodeName + "_ro"]; + } + // Creates the new widget, passes this widget as an instance and // passes the widgetType. Then it goes on loading the XML for it. - var widget = new constructor(this, _nodeName) + var widget = new constructor(this, _nodeName, readonly); + widget.loadFromXML(_node); // Call the "loadFinished" function of the widget diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 63826057e7..e1d7b30e54 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -86,7 +86,13 @@ etemplate2.prototype._createArrayManagers = function(_data) // Create an array manager object for each part of the _data array. for (var key in _data) { - result[key] = new et2_arrayMgr(_data[key]); + switch (key) { + case "readonlys": + result[key] = new et2_readonlysArrayMgr(_data[key]); + break; + default: + result[key] = new et2_arrayMgr(_data[key]); + } } return result; diff --git a/etemplate/js/test/et2_test_expressions.json b/etemplate/js/test/et2_test_expressions.json index 1f854e19ce..9f8c997834 100644 --- a/etemplate/js/test/et2_test_expressions.json +++ b/etemplate/js/test/et2_test_expressions.json @@ -6,6 +6,9 @@ var expression_test_data = { }, "display_text": "false", "textbox": "This is the outer textbox." + }, + "readonlys": { + "__ALL__": true } }; diff --git a/etemplate/js/test/et2_test_expressions.xet b/etemplate/js/test/et2_test_expressions.xet index 39255a728a..0aad780812 100644 --- a/etemplate/js/test/et2_test_expressions.xet +++ b/etemplate/js/test/et2_test_expressions.xet @@ -3,7 +3,7 @@ <template id="test"> <vbox> <description disabled="!@@display_text" value="Dies ist nur ein test!" /> - <textbox id="textbox" /> + <textbox id="textbox" value="Test"/> </vbox> </template> <textbox id="textbox" /> diff --git a/etemplate/js/test/et2_test_timesheet_edit.json b/etemplate/js/test/et2_test_timesheet_edit.json index b938f6e34b..bf944b8282 100644 --- a/etemplate/js/test/et2_test_timesheet_edit.json +++ b/etemplate/js/test/et2_test_timesheet_edit.json @@ -3,7 +3,7 @@ var timesheet_data = { "ts_id":"1", "ts_project":null, "ts_title":"Test geschrieben", - "ts_description":null, + "ts_description":"This is just a test description", "ts_start":1307030400, "ts_duration":"150", "ts_quantity":"2.5", @@ -69,7 +69,8 @@ var timesheet_data = { "ts_owner":true, "tabs":{ "customfields":true - } + }, + "ts_description": true } } diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 96adcd2ef5..98d801f11e 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -10,6 +10,7 @@ <script src="../et2_widget.js"></script> <script src="../et2_DOMWidget.js"></script> <script src="../et2_baseWidget.js"></script> + <script src="../et2_valueWidget.js"></script> <script src="../et2_inputWidget.js"></script> <script src="../et2_template.js"></script> <script src="../et2_description.js"></script> From 40a11bdb4feaba6071867b43eee8ccb1dd844372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Tue, 16 Aug 2011 12:56:55 +0000 Subject: [PATCH 051/472] Added widget for 'styles' XET tag --- etemplate/js/et2_valueWidget.js | 2 ++ etemplate/js/et2_widget.js | 1 - etemplate/js/etemplate2.js | 1 + etemplate/js/test/test_xml.html | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/etemplate/js/et2_valueWidget.js b/etemplate/js/et2_valueWidget.js index ec00c47ad5..92abbd5506 100644 --- a/etemplate/js/et2_valueWidget.js +++ b/etemplate/js/et2_valueWidget.js @@ -10,6 +10,8 @@ * @version $Id$ */ +"use strict"; + /*egw:uses jquery.jquery; et2_baseWidget; diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index ef84536148..066d3bf6f2 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -391,7 +391,6 @@ var et2_widget = Class.extend({ // readonly type (suffixed with "_ro") is registered var readonly = this.getArrayMgr("readonlys").isReadOnly( _node.getAttribute("id"), _node.getAttribute("readonly"), this.readonly); - et2_debug("log", _node.getAttribute("id"), readonly); if (readonly && typeof et2_registry[_nodeName + "_ro"] != "undefined") { constructor = et2_registry[_nodeName + "_ro"]; diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index e1d7b30e54..fa0b409a92 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -18,6 +18,7 @@ et2_button; et2_description; et2_textbox; + et2_styles; // Requirements for the etemplate2 object et2_xml; diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 98d801f11e..015f743fff 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -18,6 +18,7 @@ <script src="../et2_button.js"></script> <script src="../et2_box.js"></script> <script src="../et2_textbox.js"></script> + <script src="../et2_styles.js"></script> <script src="../etemplate2.js"></script> From 786ec9220c004c4f4ab8d171c48d7c85c37600cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Tue, 16 Aug 2011 13:12:39 +0000 Subject: [PATCH 052/472] Added widget for html-XET tag and added forgotten et2_styles.js --- etemplate/js/et2_baseWidget.js | 2 +- etemplate/js/et2_html.js | 50 ++++++++++++++++++++++++++ etemplate/js/et2_inputWidget.js | 2 +- etemplate/js/et2_styles.js | 62 +++++++++++++++++++++++++++++++++ etemplate/js/etemplate2.js | 1 + etemplate/js/test/test_xml.html | 3 ++ 6 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 etemplate/js/et2_html.js create mode 100644 etemplate/js/et2_styles.js diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js index 02489b3f29..d97aef7a2f 100644 --- a/etemplate/js/et2_baseWidget.js +++ b/etemplate/js/et2_baseWidget.js @@ -7,7 +7,7 @@ * @link http://www.egroupware.org * @author Andreas Stöckel * @copyright Stylite 2011 - * @version $Id: et2_widget.js 36021 2011-08-07 13:43:46Z igel457 $ + * @version $Id$ */ "use strict"; diff --git a/etemplate/js/et2_html.js b/etemplate/js/et2_html.js new file mode 100644 index 0000000000..58cdb904a9 --- /dev/null +++ b/etemplate/js/et2_html.js @@ -0,0 +1,50 @@ +/** + * eGroupWare eTemplate2 - JS widget class containing raw HTML + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + jsapi.jsapi; // Needed for egw_seperateJavaScript + jquery.jquery; + et2_baseWidget; +*/ + +var et2_html = et2_baseWidget.extend({ + + init: function() { + this._super.apply(this, arguments); + + // Allow no child widgets + this.supportedWidgetClasses = []; + + this.htmlNode = $j(document.createElement("span")); + this.setDOMNode(this.htmlNode[0]); + }, + + loadContent: function(_data) { + // Create an object containg the given value and an empty js string + var html = {html: value, js: ''}; + + // Seperate the javascript from the given html. The js code will be + // written to the previously created empty js string + egw_seperateJavaScript(html); + + // Append the html to the parent element + this.htmlNode.append(html.html); + this.htmlNode.append(html.js); + } + +}); + +et2_register_widget(et2_html, ["html"]); + + diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 9b36cf8315..dabda89797 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -7,7 +7,7 @@ * @link http://www.egroupware.org * @author Andreas Stöckel * @copyright Stylite 2011 - * @version $Id: et2_widget.js 36021 2011-08-07 13:43:46Z igel457 $ + * @version $Id$ */ "use strict"; diff --git a/etemplate/js/et2_styles.js b/etemplate/js/et2_styles.js new file mode 100644 index 0000000000..793215319d --- /dev/null +++ b/etemplate/js/et2_styles.js @@ -0,0 +1,62 @@ +/** + * eGroupWare eTemplate2 - JS widget class containing styles + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + et2_widget; +*/ + +/** + * Function which appends the encapsulated style data to the head tag of the + * page. + * + * TODO: The style data could be parsed for rules and appended using the JS + * stylesheet interface, allowing the style only to modifiy nodes of the current + * template. + */ +var et2_styles = et2_widget.extend({ + + init: function() { + this._super.apply(this, arguments); + + // Allow no child widgets + this.supportedWidgetClasses = []; + + // Create the textnode which will contain the style data + this.textNode = document.createTextNode(); + + // Create the style node and append it to the head node + this.styleNode = document.createElement("style"); + this.styleNode.setAttribute("type", "text/css"); + this.styleNode.appendChild(this.textNode); + + (document.getElementsByTagName("head")[0]).appendChild(this.styleNode); + }, + + destroy: function() { + this._super.apply(this, arguments); + + // Remove the style node again and delete any reference to it + (document.getElementsByTagName("head")[0]).removeChild(this.styleNode); + this.styleNode = null; + }, + + loadContent: function(_content) { + // Set the style data + this.textNode.data = _content; + } + +}); + +et2_register_widget(et2_styles, ["styles"]); + diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index fa0b409a92..17d28623d3 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -19,6 +19,7 @@ et2_description; et2_textbox; et2_styles; + et2_html; // Requirements for the etemplate2 object et2_xml; diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 015f743fff..0ff52edd75 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -19,11 +19,14 @@ <script src="../et2_box.js"></script> <script src="../et2_textbox.js"></script> <script src="../et2_styles.js"></script> + <script src="../et2_html.js"></script> <script src="../etemplate2.js"></script> <!--<script src="../et2_tabs.js"></script>--> <script src="../lib/tooltip.js"></script> + <script src="../../../phpgwapi/js/jsapi/jsapi.js"></script> + <script src="et2_test_timesheet_edit.json"></script> <script src="et2_test_expressions.json"></script> From fef5ad8ebdd2a2268a7858994e4ce220dabe4a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Tue, 16 Aug 2011 13:45:41 +0000 Subject: [PATCH 053/472] Improved invalde type handling --- etemplate/js/et2_common.js | 25 ++++++++++++++++++------- etemplate/js/et2_inheritance.js | 3 ++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index 62e73dd610..72d3bd8685 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -97,10 +97,21 @@ function et2_evalBool(_val) * into the corresponding type. The (converted) value is returned. All supported * types are listed in the et2_validTypes array. */ -function et2_checkType(_val, _type) +function et2_checkType(_val, _type, _attr) { + if (typeof _attr == "undefined") + { + _attr = null; + } + function _err() { - throw("'" + _val + "' is not of specified _type '" + _type + "'"); + var res = et2_typeDefaults[_type]; + + et2_debug("warn", "'" + _val + "' was not of specified _type '" + + _type + (_attr != null ? "' for attribute '" + _attr + "' " : "") + + "and is now '" + res + "'"); + + return res; } // If the type is "any" simply return the value again @@ -124,7 +135,7 @@ function et2_checkType(_val, _type) return _val === "true"; } - _err(); + return _err(); } if (_type == "js") @@ -147,7 +158,7 @@ function et2_checkType(_val, _type) return null; } - _err(); + return _err(); } // Check whether the given value is of the type "string" @@ -158,7 +169,7 @@ function et2_checkType(_val, _type) return _val; } - _err(); + return _err(); } // Check whether the value is already a number, otherwise try to convert it @@ -175,7 +186,7 @@ function et2_checkType(_val, _type) return parseFloat(_val); } - _err(); + return _err(); } // Check whether the value is an integer by comparing the result of @@ -187,7 +198,7 @@ function et2_checkType(_val, _type) return parseInt(_val); } - _err(); + return _err(); } // We should never come here diff --git a/etemplate/js/et2_inheritance.js b/etemplate/js/et2_inheritance.js index afcd6a7b1e..e053cdcd4e 100644 --- a/etemplate/js/et2_inheritance.js +++ b/etemplate/js/et2_inheritance.js @@ -334,7 +334,8 @@ _override = true; } - var val = et2_checkType(_value, this.attributes[_name].type); + var val = et2_checkType(_value, this.attributes[_name].type, + _name); if (typeof this["set_" + _name] == "function") { From a6ebfff8272c052fa1175c1d6dc88c3c6b1eeb11 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Tue, 16 Aug 2011 16:44:21 +0000 Subject: [PATCH 054/472] Fix infinite loop --- etemplate/js/et2_widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 066d3bf6f2..5df26cce43 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -455,9 +455,9 @@ var et2_widget = Class.extend({ // Parse the legacy options var splitted = et2_csvSplit(_attrs[i].value); - for (var i = 0; i < splitted.length && i < this.legacyOptions.length; i++) + for (var j = 0; j < splitted.length && j < this.legacyOptions.length; j++) { - this.setAttribute(this.legacyOptions[i], splitted[i]); + this.setAttribute(this.legacyOptions[j], splitted[j]); } } else From fb8ef99c0b5c403ec5c3fd62b7278e456de36f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Tue, 16 Aug 2011 16:46:22 +0000 Subject: [PATCH 055/472] Added align property and working hbox/vbox implementation --- etemplate/js/et2_baseWidget.js | 35 +++++- etemplate/js/et2_box.js | 5 +- etemplate/js/et2_hbox.js | 174 ++++++++++++++++++++++++++++ etemplate/js/et2_styles.js | 15 ++- etemplate/js/et2_widget.js | 6 + etemplate/js/etemplate2.js | 1 + etemplate/js/test/et2_test_hbox.xet | 46 ++++++++ etemplate/js/test/test.css | 50 ++++++-- etemplate/js/test/test_xml.html | 3 +- 9 files changed, 316 insertions(+), 19 deletions(-) create mode 100644 etemplate/js/et2_hbox.js create mode 100644 etemplate/js/test/et2_test_hbox.xet diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js index d97aef7a2f..3fe711cd8b 100644 --- a/etemplate/js/et2_baseWidget.js +++ b/etemplate/js/et2_baseWidget.js @@ -18,22 +18,37 @@ et2_DOMWidget; */ +/** + * Interface for widgets which have the align attribute + */ +var et2_IAligned = new Interface({ + get_align: function() {} +}); + /** * Class which manages the DOM node itself. The simpleWidget class is derrived * from et2_DOMWidget and implements the getDOMNode function. A setDOMNode * function is provided, which attatches the given node to the DOM if possible. */ -var et2_baseWidget = et2_DOMWidget.extend({ +var et2_baseWidget = et2_DOMWidget.extend(et2_IAligned, { attributes: { "statustext": { "name": "Tooltip", "type": "string", "description": "Tooltip which is shown for this element" + }, + "align": { + "name": "Align", + "type": "string", + "default": "left", + "description": "Position of this element in the parent hbox" } }, init: function() { + this.align = "left"; + this._super.apply(this, arguments); this.node = null; @@ -81,7 +96,7 @@ var et2_baseWidget = et2_DOMWidget.extend({ }, getTooltipElement: function() { - return this.getDOMNode(); + return this.getDOMNode(this); }, set_statustext: function(_value) { @@ -111,6 +126,22 @@ var et2_baseWidget = et2_DOMWidget.extend({ this._tooltipElem = elem; } } + }, + + // XXX I really don't like this - I think I'll move attaching the DOM-Nodes + // to the loadFinished function - this should also be faster... + set_align: function(_value) { + if (_value != this.align) + { + this.align = _value; + + // Reattach this node to the DOM + this.onSetParent(); + } + }, + + get_align: function(_value) { + return this.align; } }); diff --git a/etemplate/js/et2_box.js b/etemplate/js/et2_box.js index 2e849d9f47..17ddcc68c1 100644 --- a/etemplate/js/et2_box.js +++ b/etemplate/js/et2_box.js @@ -26,7 +26,8 @@ var et2_box = et2_baseWidget.extend({ this._super.apply(this, arguments); this.div = $j(document.createElement("div")) - .addClass("et2_" + _type); + .addClass("et2_" + _type) + .addClass("et2_box_widget"); this.setDOMNode(this.div[0]); }, @@ -40,5 +41,5 @@ var et2_box = et2_baseWidget.extend({ }); -et2_register_widget(et2_box, ["hbox", "vbox", "box"]); +et2_register_widget(et2_box, ["vbox", "box"]); diff --git a/etemplate/js/et2_hbox.js b/etemplate/js/et2_hbox.js new file mode 100644 index 0000000000..2c5f3932ad --- /dev/null +++ b/etemplate/js/et2_hbox.js @@ -0,0 +1,174 @@ +/** + * eGroupWare eTemplate2 - JS Box object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Andreas Stöckel + * @copyright Stylite 2011 + * @version $Id: et2_box.js 36147 2011-08-16 13:12:39Z igel457 $ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + et2_baseWidget; +*/ + +/** + * Class which implements the hbox and vbox tag + */ +var et2_hbox = et2_baseWidget.extend({ + + init: function(_parent, _type) { + this.alignData = { + "hasAlign": false, + "hasLeft": false, + "hasCenter": false, + "hasRight": false, + "lastAlign": "left" + }; + + this.leftDiv = null; + this.rightDiv = null; + + this._super.apply(this, arguments); + + this.div = $j(document.createElement("div")) + .addClass("et2_" + _type) + .addClass("et2_box_widget"); + + this.setDOMNode(this.div[0]); + }, + + _buildAlignCells: function() { + if (this.alignData.hasAlign) + { + // Check whether we have more than one type of align + var mto = (this.alignData.hasLeft && this.alignData.hasRight) || + (this.alignData.hasLeft && this.alignData.hasCenter) || + (this.alignData.hasCenter && this.alignData.hasRight); + + if (!mto) + { + // If there is only one type of align, we simply have to set + // the align of the top container + if (this.alignData.lastAlign != "left") + { + this.div.addClass("et2_hbox_al_" + this.alignData.lastAlign); + } + } + else + { + // Create an additional container for elements with align type + // "right" + if (this.alignData.hasRight) + { + this.rightDiv = $j(document.createElement("div")) + .addClass("et2_hbox_right") + .appendTo(this.div); + } + + // Create an additional container for elements with align type + // left, as the top container is used for the centered elements + if (this.alignData.hasCenter) + { + // Create the left div if an element is centered + this.leftDiv = $j(document.createElement("div")) + .addClass("et2_hbox_left") + .appendTo(this.div); + + this.div.addClass("et2_hbox_al_center"); + } + } + } + }, + + /** + * The overwritten loadFromXML function checks whether any child element has + * a special align value. + */ + loadFromXML: function(_node) { + // Check whether any child node has an alignment tag + et2_filteredNodeIterator(_node, function(_node) { + var align = _node.getAttribute("align"); + + if (!align) + { + align = "left"; + } + + if (align != "left") + { + this.alignData.hasAlign = true; + } + + this.alignData.lastAlign = align; + + switch (align) + { + case "left": + this.alignData.hasLeft = true; + break; + case "right": + this.alignData.hasRight = true; + break; + case "center": + this.alignData.hasCenter = true; + break; + } + }, this); + + // Build the align cells + this._buildAlignCells(); + + // Load the nodes as usual + this._super.apply(this, arguments); + }, + + assign: function(_obj) { + // Copy the align data and the cells from the object which should be + // assigned + this.alignData = et2_cloneObject(_obj.alignData); + this._buildAlignCells(); + + // Call the inherited assign function + this._super.call(this, arguments); + }, + + getDOMNode: function(_sender) { + // Return a special align container if this hbox needs it + if (_sender != this && this.alignData.hasAlign) + { + // Check whether we've create a special container for the widget + var align = (_sender.implements(et2_IAligned) ? + _sender.get_align() : "left"); + + if (align == "left" && this.leftDiv != null) + { + return this.leftDiv[0]; + } + + if (align == "right" && this.rightDiv != null) + { + return this.rightDiv[0]; + } + } + + // Normally simply return the hbox-div + return this._super.apply(this, arguments); + }, + + set_id: function(_value) { + this._super.apply(this, arguments); + + // Check whether a namespace exists for this element + this.checkCreateNamespace(); + } + +}); + +et2_register_widget(et2_hbox, ["hbox"]); + diff --git a/etemplate/js/et2_styles.js b/etemplate/js/et2_styles.js index 793215319d..344fd153c6 100644 --- a/etemplate/js/et2_styles.js +++ b/etemplate/js/et2_styles.js @@ -32,13 +32,9 @@ var et2_styles = et2_widget.extend({ // Allow no child widgets this.supportedWidgetClasses = []; - // Create the textnode which will contain the style data - this.textNode = document.createTextNode(); - // Create the style node and append it to the head node this.styleNode = document.createElement("style"); this.styleNode.setAttribute("type", "text/css"); - this.styleNode.appendChild(this.textNode); (document.getElementsByTagName("head")[0]).appendChild(this.styleNode); }, @@ -52,8 +48,15 @@ var et2_styles = et2_widget.extend({ }, loadContent: function(_content) { - // Set the style data - this.textNode.data = _content; + if (this.styleNode.styleSheet) + { + // IE + this.styleNode.styleSheet.cssText += _content; + } + else + { + this.styleNode.appendChild(document.createTextNode(_content)); + } } }); diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 5df26cce43..5a74353883 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -536,6 +536,12 @@ var et2_widget = Class.extend({ // Iterate over the widget tree this.iterateOver(function(_widget) { + // The widget must have an id to be included in the values array + if (_widget.id == "") + { + return; + } + // Get the path to the node we have to store the value at var path = _widget.getArrayMgr("content").getPath(); diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 17d28623d3..0cf302d562 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -15,6 +15,7 @@ et2_template; et2_grid; et2_box; + et2_hbox; et2_button; et2_description; et2_textbox; diff --git a/etemplate/js/test/et2_test_hbox.xet b/etemplate/js/test/et2_test_hbox.xet new file mode 100644 index 0000000000..4bed4d0794 --- /dev/null +++ b/etemplate/js/test/et2_test_hbox.xet @@ -0,0 +1,46 @@ +<?xml version="1.0"?> +<overlay> + <vbox> + <description value="Simple hbox behaviour" /> + <hbox> + <button label="btn1" /> + <button label="btn2" /> + <button label="btn3" /> + <button label="btn4" /> + </hbox> + + <description value="Float right" /> + <hbox> + <hbox> + <button label="btn1" /> + <button label="btn2" /> + <button label="btn3" /> + </hbox> + <button align="right" label="btn4" /> + <button label="btn5" /> + </hbox> + + <description value="Float center" /> + <hbox> + <hbox> + <button label="btn1" /> + <button label="btn2" /> + <button label="btn3" /> + </hbox> + <button align="center" label="btn4" /> + <button label="btn5" /> + </hbox> + + + <description value="Only right" /> + <hbox> + <button align="right" label="btn" /> + </hbox> + + <description value="Only center" /> + <hbox> + <button align="center" label="btn" /> + </hbox> + </vbox> +</overlay> + diff --git a/etemplate/js/test/test.css b/etemplate/js/test/test.css index 89ba4c8753..30a049c4bc 100644 --- a/etemplate/js/test/test.css +++ b/etemplate/js/test/test.css @@ -3,6 +3,9 @@ * * @version: $Id$ */ + +/* Stuff for the standalone test webpage */ + body { font-family: Lucida Grande, sans-serif; font-size: 10pt; @@ -33,6 +36,42 @@ body { border-bottom: 1px solid #111; } +/** + * VBox widget + */ +div.et2_vbox>* { + display: block; +} + +/** + * HBox widget + */ + +div.et2_hbox div.et2_hbox { + display: inline; +} + +div.et2_hbox>* { + text-align: left; +} + +div.et2_hbox_left { + float: left; +} + +div.et2_hbox_al_center { + text-align: center; +} + +div.et2_hbox_al_right { + text-align: right; +} + +div.et2_hbox_right { + float: right; + clear: right; +} + .et2_placeholder { display: inline-block; border: 1px solid cornflowerblue; @@ -101,10 +140,6 @@ button.et2_button:focus { outline: none; } -div.et2_hbox { - display: inline; -} - .et2_tabflag { display: inline-block; margin-right: 5px; @@ -132,10 +167,6 @@ div.et2_hbox { font-style: italic; } -.et2_vbox div, .et2_vbox span { - display: block; -} - .egw_tooltip { position: fixed; @@ -145,3 +176,6 @@ div.et2_hbox { max-width: 300px; color: black; } + + + diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 0ff52edd75..fba345dd84 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -17,6 +17,7 @@ <script src="../et2_grid.js"></script> <script src="../et2_button.js"></script> <script src="../et2_box.js"></script> + <script src="../et2_hbox.js"></script> <script src="../et2_textbox.js"></script> <script src="../et2_styles.js"></script> <script src="../et2_html.js"></script> @@ -43,9 +44,9 @@ <a href="#" onclick="open_xet('et2_test_textbox.xet');">Textbox test</a> <a href="#" onclick="open_xet('et2_test_description.xet');">Description test</a> <a href="#" onclick="open_xet('et2_test_expressions.xet', expression_test_data);">Expression test</a> + <a href="#" onclick="open_xet('et2_test_hbox.xet');">HBox test</a> </div> <div class="header">ETemplate2 container:</div> - <div id="time"></div> <div id="container"></div> <script> var et2 = new etemplate2(document.getElementById("container"), ""); From 03b47046859b69ba4320ba63b8000d4dbfac4d87 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Tue, 16 Aug 2011 17:02:09 +0000 Subject: [PATCH 056/472] Add basic implementation of numeric (int & float) and selectbox widgets --- etemplate/js/et2_inputWidget.js | 11 ++++ etemplate/js/et2_number.js | 66 ++++++++++++++++++++ etemplate/js/et2_selectbox.js | 103 ++++++++++++++++++++++++++++++++ etemplate/js/et2_textbox.js | 26 +++++++- etemplate/js/etemplate2.js | 2 + etemplate/js/test/test_xml.html | 3 + 6 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 etemplate/js/et2_number.js create mode 100644 etemplate/js/et2_selectbox.js diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index dabda89797..4c4a045d44 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -79,6 +79,17 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { } } }, + set_required: function(_value) { + var node = this.getInputNode(); + if (node) + { + if(_value) { + $j(node).attr("required", "required"); + } else { + node.removeAttribute("required"); + } + } + }, get_value: function() { return this.getValue(); diff --git a/etemplate/js/et2_number.js b/etemplate/js/et2_number.js new file mode 100644 index 0000000000..0b2d8bfbf3 --- /dev/null +++ b/etemplate/js/et2_number.js @@ -0,0 +1,66 @@ +/** + * eGroupWare eTemplate2 - JS Number object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Nathan Gray + * @copyright Nathan Gray 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + et2_textbox; +*/ + +/** + * Class which implements the "int" and textbox type=float XET-Tags + */ +var et2_number = et2_textbox.extend({ + + attributes: { + // Override default width, numbers are usually shorter + "size": { + "default": 5 + }, + "min": { + "name": "Minimum", + "type": "integer", + "default": et2_no_init, + "description": "Minimum allowed value" + }, + "max": { + "name": "Maximum", + "type": "integer", + "default": et2_no_init, + "description": "Maximum allowed value" + } + }, + + init: function(_parent) { + this._super.apply(this, arguments); + }, + + createInputWidget: function() { + this.input = $j(document.createElement("input")); + this.input.attr("type", "number"); + this.input.addClass("et2_textbox"); + + this.setDOMNode(this.input[0]); + }, + + set_min: function(_value) { + this.min = _value; + if(this.min == null) { + this.input.removeAttr("min"); + } else { + this.input.attr("min",this.min); + } + } +}); + +et2_register_widget(et2_number, ["int", "float"]); + diff --git a/etemplate/js/et2_selectbox.js b/etemplate/js/et2_selectbox.js new file mode 100644 index 0000000000..7c92964298 --- /dev/null +++ b/etemplate/js/et2_selectbox.js @@ -0,0 +1,103 @@ +/** + * eGroupWare eTemplate2 - JS Selectbox object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Nathan Gray + * @copyright Nathan Gray 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + et2_inputWidget; +*/ + +/** + * Class which implements the "menulist" XET-Tag + */ +var et2_selectbox = et2_inputWidget.extend({ + + attributes: { + "multiselect": { + "name": "multiselect", + "type": "boolean", + "default": false, + "description": "Allow selecting multiple options" + }, + "rows": { + "name": "Rows", + "type": "any", // Old options put either rows or empty_label in first space + "default": 1, + "description": "Number of rows to display" + }, + "empty_label": { + "name": "Empty label", + "type": "string", + "default": "", + "description": "Textual label for first row, eg: 'All' or 'None'. ID will be ''" + } + }, + + legacyOptions: ["rows"], + + init: function(_parent) { + this._super.apply(this, arguments); + + this.input = null; + this.id = ""; + + if(this.rows > 1) this.multiselect=true; + this.createInputWidget(); + }, + + /** + * Override load to be able to handle menupopup tag inside of menulist + */ + loadFromXML: function(_node) { + var menupopupElems = et2_directChildrenByTagName(_node, "menupopup"); + if(menupopupElems.length == 1) { + this.loadAttributes(menupopupElems[0].attributes); + } else { + this._super.apply(this,arguments); + } + }, + + createInputWidget: function() { + if(this.type == "menupopup") { + return; + } else { + this.input = $j(document.createElement("select")); + + this.input.addClass("et2_selectbox"); + } + + this.setDOMNode(this.input[0]); + }, + + set_multiselect: function(_value) { + if (_value != this.multiselect) + { + this.multiselect = _value; + if(this.multiselect) { + this.input.attr("multiple","multiple"); + } else { + this.input.removeAttr("multiple"); + } + } + }, + set_rows: function(_rows) { + if (_rows != this.rows) + { + this.rows = _rows; + this.input.attr("size",this.rows); + } + } +}); + +et2_register_widget(et2_selectbox, ["menulist","listbox"]); + diff --git a/etemplate/js/et2_textbox.js b/etemplate/js/et2_textbox.js index b9f48059d2..d0f303721e 100644 --- a/etemplate/js/et2_textbox.js +++ b/etemplate/js/et2_textbox.js @@ -29,6 +29,12 @@ var et2_textbox = et2_inputWidget.extend({ "type": "boolean", "default": false, "description": "If true, the textbox is a multiline edit field." + }, + "size": { + "name": "Size", + "type": "integer", + "default": et2_no_init, + "description": "Field width" } }, @@ -39,6 +45,7 @@ var et2_textbox = et2_inputWidget.extend({ this.id = ""; this.createInputWidget(); + }, createInputWidget: function() { @@ -51,6 +58,10 @@ var et2_textbox = et2_inputWidget.extend({ this.input = $j(document.createElement("input")); } + if(this.size) { + this.set_size(this.size); + } + this.input.addClass("et2_textbox"); this.setDOMNode(this.input[0]); @@ -66,11 +77,22 @@ var et2_textbox = et2_inputWidget.extend({ // Write all settings again this.update(); } - } + }, + /** + * Set input widget size + * @param _size Rather arbitrary size units, approximately characters + */ + set_size: function(_size) { + if (typeof _size != 'undefined' && _size != this.input.attr("size")) + { + this.size = _size; + this.input.attr("size", this.size); + } + } }); -et2_register_widget(et2_textbox, ["textbox", "int", "float"]); +et2_register_widget(et2_textbox, ["textbox"]); /** * et2_textbox_ro is the dummy readonly implementation of the textbox. diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 0cf302d562..9d4a225a2a 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -19,6 +19,8 @@ et2_button; et2_description; et2_textbox; + et2_number; + et2_selectbox; et2_styles; et2_html; diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index fba345dd84..33cbe78631 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -19,6 +19,8 @@ <script src="../et2_box.js"></script> <script src="../et2_hbox.js"></script> <script src="../et2_textbox.js"></script> + <script src="../et2_number.js"></script> + <script src="../et2_selectbox.js"></script> <script src="../et2_styles.js"></script> <script src="../et2_html.js"></script> @@ -43,6 +45,7 @@ <a href="#" onclick="open_xet('et2_test_tabbox.xet');">Tabs test</a> <a href="#" onclick="open_xet('et2_test_textbox.xet');">Textbox test</a> <a href="#" onclick="open_xet('et2_test_description.xet');">Description test</a> + <a href="#" onclick="open_xet('et2_test_basic_widgets.xet');">Basic widgits</a> <a href="#" onclick="open_xet('et2_test_expressions.xet', expression_test_data);">Expression test</a> <a href="#" onclick="open_xet('et2_test_hbox.xet');">HBox test</a> </div> From 63d0baf49713295a262a2364949abeaf185a009e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Tue, 16 Aug 2011 18:18:18 +0000 Subject: [PATCH 057/472] Added event listener system to etemplate2 --- etemplate/js/et2_widget.js | 8 +++- etemplate/js/etemplate2.js | 86 +++++++++++++++++++++++++++++++++++--- 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 5a74353883..44ca3371e7 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -193,7 +193,13 @@ var et2_widget = Class.extend({ { if (!_obj.attributes[key].ignore) { - this.setAttribute(key, _obj.getAttribute(key)); + var value = _obj.getAttribute(key); + + // Check whether the attribute is undefined + if (typeof value != "undefined") + { + this.setAttribute(key, value); + } } } diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 9d4a225a2a..1136923cf2 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -23,6 +23,7 @@ et2_selectbox; et2_styles; et2_html; + et2_tabs; // Requirements for the etemplate2 object et2_xml; @@ -49,6 +50,9 @@ function etemplate2(_container, _menuaction) // Preset the object variable this.widgetContainer = null; + + // Associative array with the event listeners + this.listeners = {}; } /** @@ -132,16 +136,86 @@ etemplate2.prototype.submit = function() // Get the form values var values = this.widgetContainer.getValues(); - // Create the request object - if (typeof egw_json_request != "undefined") + // Trigger the submit event + if (this.fireEvent("submit", [values])) { - var request = new egw_json_request(this.menuaction, [values], this); - request.sendRequest(true); + // Create the request object + if (typeof egw_json_request != "undefined") + { + var request = new egw_json_request(this.menuaction, [values], this); + request.sendRequest(true); + } + else + { + et2_debug("info", "Form got submitted with values: ", values); + } } - else +} + +/** + * Adds an callback function to the given event slot + * + * @param _event is the name of the event + * @param _callback is the function which should be called once the event gets + * fired. + * @param _context is the context in which the function should be executed. + */ +etemplate2.prototype.addListener = function(_event, _callback, _context) +{ + // Add the event slot if it does not exist yet + if (typeof this.listeners[_event] == "undefined") { - console.log(values); + this.listeners[_event] = []; } + + this.listeners[_event].push({ + "callback": _callback, + "context": _context + }); +} + +/** + * Removes the given callback function from the given event slot. + */ +etemplate2.prototype.removeListener = function(_event, _callback) +{ + if (typeof this.listeners[_event] != "undefined") + { + var events = this.listeners[_event]; + + for (var i = events.length - 1; i >= 0; i--) + { + if (events[i].callback == _callback) + { + events.splice(i, 1); + } + } + } +} + +/** + * Fires the given event. The return values are conected via AND + */ +etemplate2.prototype.fireEvent = function(_event, _args) +{ + if (typeof _args == "undefined") + { + _args = []; + } + + var result = true; + + if (typeof this.listeners[_event] != "undefined") + { + var events = this.listeners[_event]; + + for (var i = 0; i < events.length; i++) + { + result = result && events[i].callback.apply(events[i].context, _args); + } + } + + return result; } /** From df2869c07f7f9375e051589324a7b3c8d9846513 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Tue, 16 Aug 2011 18:42:17 +0000 Subject: [PATCH 058/472] Add simple checkbox, missing ID property --- etemplate/js/et2_checkbox.js | 83 ++++++++++++++++++++++++++++++++++++ etemplate/js/etemplate2.js | 1 + 2 files changed, 84 insertions(+) create mode 100644 etemplate/js/et2_checkbox.js diff --git a/etemplate/js/et2_checkbox.js b/etemplate/js/et2_checkbox.js new file mode 100644 index 0000000000..477f61a57b --- /dev/null +++ b/etemplate/js/et2_checkbox.js @@ -0,0 +1,83 @@ +/** + * eGroupWare eTemplate2 - JS Checkbox object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Nathan Gray + * @copyright Nathan Gray 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + et2_inputWidget; +*/ + +/** + * Class which implements the "checkbox" XET-Tag + */ +var et2_checkbox = et2_inputWidget.extend({ + + attributes: { + "set_value": { + "name": "Set value", + "type": "string", + "default": "true", + "description": "Value when checked" + }, + "unset_value": { + "name": "Unset value", + "type": "string", + "default": "false", + "description": "Value when not checked" + } + }, + + init: function(_parent) { + this._super.apply(this, arguments); + + this.input = null; + this.id = ""; + + this.createInputWidget(); + + }, + + createInputWidget: function() { + this.input = $j(document.createElement("input")).attr("type", "checkbox"); + + this.input.addClass("et2_checkbox"); + + this.setDOMNode(this.input[0]); + }, + + /** + * Override default to match against set/unset value + */ + set_value: function(_value) { + if(_value != this.value) { + if(_value == this.set_value) { + this.input.attr("checked", true); + } else { + this.input.removeAttr("checked"); + } + } + }, + + /** + * Override default to return unchecked value + */ + getValue: function() { + if(this.input.attr("checked")) { + return this.set_value; + } else { + return this.unset_value; + } + } +}); + +et2_register_widget(et2_checkbox, ["checkbox"]); diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 1136923cf2..4ba974b624 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -21,6 +21,7 @@ et2_textbox; et2_number; et2_selectbox; + et2_checkbox; et2_styles; et2_html; et2_tabs; From 11ccd9c0571bd9fc8f138557dd4775ebb29d7644 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Tue, 16 Aug 2011 19:01:45 +0000 Subject: [PATCH 059/472] Check that value is a string before treating it as one --- etemplate/js/et2_common.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js index 72d3bd8685..0f345ae24b 100644 --- a/etemplate/js/et2_common.js +++ b/etemplate/js/et2_common.js @@ -129,10 +129,13 @@ function et2_checkType(_val, _type, _attr) return _val; } - var lcv = _val.toLowerCase(); - if (lcv === "true" || lcv === "false" || lcv === "") + if (typeof _val == "string") { - return _val === "true"; + var lcv = _val.toLowerCase(); + if (lcv === "true" || lcv === "false" || lcv === "") + { + return _val === "true"; + } } return _err(); From 510ce7c1598bb0ebe43f89a8ee5590ecfe9d9580 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Tue, 16 Aug 2011 19:40:48 +0000 Subject: [PATCH 060/472] - using etemplate_request object and a etemplate_exec_id - "processing" the submit on serverside (no validation yet) --> content returned by ajax call is not an hiearchical array: eg. "button[save]" => 1, instead of "button" => array("save" => 1) - new call to etemplate_new::exec() is send back via new JSON generic et2_load response --> how do we handle output of callback: a) debug output, eg. echos and b) echo "<html><head><script>window.close();</script></head></html>"; exit; --- etemplate/inc/class.etemplate_new.inc.php | 131 +++++++++++++++++----- etemplate/js/etemplate2.js | 15 ++- 2 files changed, 114 insertions(+), 32 deletions(-) diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index d8f0ea314c..718f063357 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -27,6 +27,22 @@ class etemplate_new */ public $sitemgr=false; + /** + * Request object of the currecntly created request + * + * It's a static variable as etemplates can contain further etemplates (rendered by a different object) + * + * @var etemplate_request + */ + static protected $request; + + /** + * JSON response object, if we run via a JSON request + * + * @var egw_json_response + */ + static protected $response; + /** * constructor of etemplate class, reads an eTemplate if $name is given * @@ -86,12 +102,38 @@ class etemplate_new { if (!$this->rel_path) throw new egw_exception_assertion_failed('No (valid) template read!'); -/* if (self::$response) // call is within an ajax event / form submit - { + // generate new etemplate request object + self::$request = etemplate_request::read(); + self::$request->output_mode = $output_mode; // let extensions "know" they are run eg. in a popup + self::$request->readonlys = $readonlys; + self::$request->content = $content; + self::$request->changes = $changes; + self::$request->sel_options = $sel_options; + self::$request->preserv = $preserv; + self::$request->method = $method; + self::$request->ignore_validation = $ignore_validation; + self::$request->app_header = $GLOBALS['egw_info']['flags']['app_header']; + if (self::$request->output_mode == -1) self::$request->output_mode = 0; + self::$request->template = $this->rel_path; + $data = array( + 'etemplate_exec_id' => self::$request->id(), + 'app_header' => $GLOBALS['egw_info']['flags']['app_header'], + 'content' => $content, + 'sel_options' => $sel_options, + 'readonlys' => $readonlys, + 'modifications' => $this->modifications, + 'validation_errors' => self::$validation_errors, + ); + if (self::$response) // call is within an ajax event / form submit + { + self::$response->generic('et2_load', array( + 'url' => $GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path, + 'data' => $data, + )); } else // first call -*/ { + { egw_framework::validate_file('.','etemplate2','etemplate'); egw_framework::includeCSS('/etemplate/js/test/test.css'); @@ -104,13 +146,7 @@ class etemplate_new <div id="container"></div> <script> var et2 = new etemplate2(document.getElementById("container"), "etemplate_new::ajax_process_content"); - et2.load("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode(array( - 'content' => $content, - 'sel_options' => $sel_options, - 'readonlys' => $readonlys, - 'modifications' => $this->modifications, - 'validation_errors' => self::$validation_errors, - )).'); + et2.load("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode($data).'); </script> '; common::egw_footer(); @@ -120,20 +156,20 @@ class etemplate_new /** * Process via Ajax submitted content */ - static public function ajax_process_content(array $content) + static public function ajax_process_content($etemplate_exec_id, array $content) { - error_log(__METHOD__."(".print_r($content, true).")"); + error_log(__METHOD__."(".array2string($etemplate_exec_id).', '.array2string($content).")"); - $response = egw_json_response::get(); - $response->generic("et2_load", array( - "url" => $GLOBALS['egw_info']['server']['webserver_url']."/etemplate/js/test/et2_test_expressions.xet", - "data" => array( - "content" => array( - "display_text" => "", - "textbox" => "Hello world!" - ) - ) - )); + self::$request = etemplate_request::read($etemplate_exec_id); + error_log('request='.array2string(self::$request)); + + self::$response = egw_json_response::get(); + + // todo: validate content + // $content = self::validate($content); + + // merge with preserve and call our callback + return ExecMethod(self::$request->method, self::complete_array_merge(self::$request->preserv, $content)); } /** @@ -189,7 +225,7 @@ class etemplate_new * @param string $error error-message already translated * @param string $cname=null set it to '', if the name is already a form-name, defaults to self::$name_vars */ - static function set_validation_error($name,$error,$cname=null) + public static function set_validation_error($name,$error,$cname=null) { if (is_null($cname)) $cname = self::$name_vars; //echo "<p>etemplate::set_validation_error('$name','$error','$cname');</p>\n"; @@ -209,7 +245,7 @@ class etemplate_new * @param string $cname=null name-prefix, which need to be ignored, default self::$name_vars * @return boolean true if there are not ignored validation errors, false otherwise */ - function validation_errors($ignore_validation='',$cname=null) + public static function validation_errors($ignore_validation='',$cname=null) { if (is_null($cname)) $cname = self::$name_vars; //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') validation_error="; _debug_array(self::$validation_errors); @@ -248,7 +284,7 @@ class etemplate_new * @param string $attr attribute-name * @return mixed reference to attribute, usually NULL */ - function &get_cell_attribute($name,$attr) + public function &get_cell_attribute($name,$attr) { error_log(__METHOD__."('$name', '$attr')"); @@ -263,7 +299,7 @@ class etemplate_new * @param mixed $val if not NULL sets attribute else returns it * @return mixed number of changed cells or False, if none changed */ - function &set_cell_attribute($name,$attr,$val) + public function &set_cell_attribute($name,$attr,$val) { error_log(__METHOD__."('$name', '$attr', ".array2string($val).')'); @@ -280,7 +316,7 @@ class etemplate_new * @param boolean $disabled=true disable or enable a cell, default true=disable * @return mixed number of changed cells or False, if none changed */ - function disable_cells($name,$disabled=True) + public function disable_cells($name,$disabled=True) { return $this->set_cell_attribute($name,'disabled',$disabled); } @@ -296,7 +332,7 @@ class etemplate_new * @param string $path='/0' default is the first widget in the tree of children * @return false if $path is no grid or array(height,class,valign,disabled) otherwise */ - function set_row_attributes($n,$height=0,$class=0,$valign=0,$disabled=0,$path='/0') + public function set_row_attributes($n,$height=0,$class=0,$valign=0,$disabled=0,$path='/0') { throw new egw_exception_assertion_failed('Not yet implemented!'); @@ -325,7 +361,7 @@ class etemplate_new * @param boolean $enable=false can be used to re-enable a row if set to True * @param string $path='/0' default is the first widget in the tree of children */ - function disable_row($n,$enable=False,$path='/0') + public function disable_row($n,$enable=False,$path='/0') { $this->set_row_attributes($n,0,0,0,!$enable,$path); } @@ -339,7 +375,7 @@ class etemplate_new * @param string $path='/0' default is the first widget in the tree of children * @return false if $path specifies no grid or array(width,disabled) otherwise */ - function set_column_attributes($c,$width=0,$disabled=0,$path='/0') + public function set_column_attributes($c,$width=0,$disabled=0,$path='/0') { throw new egw_exception_assertion_failed('Not yet implemented!'); @@ -367,8 +403,41 @@ class etemplate_new * @param boolean $enable can be used to re-enable a column if set to True * @param string $path='/0' default is the first widget in the tree of children */ - function disable_column($c,$enable=False,$path='/0') + public function disable_column($c,$enable=False,$path='/0') { $this->set_column_attributes($c,0,!$enable,$path); } + + /** + * merges $old and $new, content of $new has precedence over $old + * + * THIS IS NOT THE SAME AS PHP's functions: + * - array_merge, as it calls itself recursive for values which are arrays. + * - array_merge_recursive accumulates values with the same index and $new does NOT overwrite $old + * + * @param array $old + * @param array $new + * @return array the merged array + */ + public static function complete_array_merge($old,$new) + { + if (is_array($new)) + { + if (!is_array($old)) $old = (array) $old; + + foreach($new as $k => $v) + { + if (!is_array($v) || !isset($old[$k]) || // no array or a new array + isset($v[0]) && !is_array($v[0]) && isset($v[count($v)-1])) // or no associative array, eg. selecting multiple accounts + { + $old[$k] = $v; + } + else + { + $old[$k] = self::complete_array_merge($old[$k],$v); + } + } + } + return $old; + } } diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 4ba974b624..242b276b90 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -97,6 +97,9 @@ etemplate2.prototype._createArrayManagers = function(_data) for (var key in _data) { switch (key) { + case "etemplate_exec_id": // already processed + case "app_header": + break; case "readonlys": result[key] = new et2_readonlysArrayMgr(_data[key]); break; @@ -127,6 +130,16 @@ etemplate2.prototype.load = function(_url, _data) this.widgetContainer.setInstanceManager(this); this.widgetContainer.setParentDOMNode(this.DOMContainer); + // store the id to submit it back to server + this.etemplate_exec_id = _data.etemplate_exec_id; + + // set app_header + if (window.opener) { // popup + document.title = _data.app_header; + } else { + // todo for idots or jdots framework + } + // Split the given data into array manager objects and pass those to the // widget container this.widgetContainer.setArrayMgrs(this._createArrayManagers(_data)); @@ -143,7 +156,7 @@ etemplate2.prototype.submit = function() // Create the request object if (typeof egw_json_request != "undefined") { - var request = new egw_json_request(this.menuaction, [values], this); + var request = new egw_json_request(this.menuaction, [this.etemplate_exec_id,values], this); request.sendRequest(true); } else From f0db6211b999fb223d0803eef763bf08998c30ad Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Tue, 16 Aug 2011 20:32:13 +0000 Subject: [PATCH 061/472] Put options in selectbox --- etemplate/js/et2_selectbox.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/etemplate/js/et2_selectbox.js b/etemplate/js/et2_selectbox.js index 7c92964298..2624888a9b 100644 --- a/etemplate/js/et2_selectbox.js +++ b/etemplate/js/et2_selectbox.js @@ -79,6 +79,22 @@ var et2_selectbox = et2_inputWidget.extend({ this.setDOMNode(this.input[0]); }, + set_id: function(_id) { + this._super.apply(this,arguments); + + // Get select options from the manager + var mgr = this.getArrayMgr('sel_options'); + var options = mgr.getValueForID(this.id); + this.set_select_options(options); + }, + + set_select_options: function(_options) { + this.input.children().remove(); + for(var key in _options) { + this.input.append("<option value='"+key+"'" + (key == this.getValue() ? "selected":"") +">"+_options[key]+"</option>"); + } + }, + set_multiselect: function(_value) { if (_value != this.multiselect) { From fae753a55151eaa58042d26651b08c84652f9bb2 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Tue, 16 Aug 2011 20:32:18 +0000 Subject: [PATCH 062/472] added hiearchical names in widget id's like 'button[save]' --- etemplate/js/et2_widget.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 44ca3371e7..9905c65a89 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -550,6 +550,15 @@ var et2_widget = Class.extend({ // Get the path to the node we have to store the value at var path = _widget.getArrayMgr("content").getPath(); + + // check if id contains a hierachical name, eg. "button[save]" + var id = _widget.id; + if (_widget.id.indexOf('[') != -1) + { + var parts = _widget.id.replace(/]/g,'').split('['); + id = parts.pop(); + path = path.concat(parts); + } // Set the _target variable to that node var _target = result; @@ -574,7 +583,7 @@ var et2_widget = Class.extend({ } // Check whether the entry is really undefined - if (typeof _target[_widget.id] != "undefined") + if (typeof _target[id] != "undefined") { et2_debug("error", _widget, "Overwriting value of '" + _widget.id + "', id exists twice!"); @@ -584,7 +593,7 @@ var et2_widget = Class.extend({ var value = _widget.getValue(); if (value !== null) { - _target[_widget.id] = value; + _target[id] = value; } _widget.resetDirty(); From 146c8fbc80981493d7ec40f7a8144070250699e3 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Tue, 16 Aug 2011 20:43:18 +0000 Subject: [PATCH 063/472] disable initial namespace/cname, as we probably wont use it and it gives a fatal error currently --- etemplate/inc/class.etemplate_new.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index 718f063357..9db069b324 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -245,9 +245,9 @@ class etemplate_new * @param string $cname=null name-prefix, which need to be ignored, default self::$name_vars * @return boolean true if there are not ignored validation errors, false otherwise */ - public static function validation_errors($ignore_validation='',$cname=null) + public static function validation_errors($ignore_validation='',$cname='') { - if (is_null($cname)) $cname = self::$name_vars; +// if (is_null($cname)) $cname = self::$name_vars; //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') validation_error="; _debug_array(self::$validation_errors); if (!$ignore_validation) return count(self::$validation_errors) > 0; From e981e7911f2084210c84e5fbde5d4a711764e67f Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Tue, 16 Aug 2011 21:18:06 +0000 Subject: [PATCH 064/472] Get option value from content, add empty label --- etemplate/js/et2_selectbox.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/etemplate/js/et2_selectbox.js b/etemplate/js/et2_selectbox.js index 2624888a9b..95ef429c92 100644 --- a/etemplate/js/et2_selectbox.js +++ b/etemplate/js/et2_selectbox.js @@ -82,14 +82,32 @@ var et2_selectbox = et2_inputWidget.extend({ set_id: function(_id) { this._super.apply(this,arguments); - // Get select options from the manager + // Get select options from the manager(s) + var options = null; + + // Check the sel_options var mgr = this.getArrayMgr('sel_options'); - var options = mgr.getValueForID(this.id); + if(mgr) { + options = mgr.getValueForID(this.id); + } + if(options != null) { + this.set_select_options(options); + } else { + // Check in the content + var mgr = this.getArrayMgr('content'); + if(mgr) { + options = mgr.getValueForID('options-'+this.id); + } + } this.set_select_options(options); }, set_select_options: function(_options) { this.input.children().remove(); + if(this.empty_label) { + this.input.append("<option value=''" + ("" == this.getValue() ? "selected":"") +">"+this.empty_label+"</option>"); + } + if(_options == null) return; for(var key in _options) { this.input.append("<option value='"+key+"'" + (key == this.getValue() ? "selected":"") +">"+_options[key]+"</option>"); } From e7921304796d75a9bd5985460c2822c9d32e5dd6 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Tue, 16 Aug 2011 21:18:26 +0000 Subject: [PATCH 065/472] Stop errors from missing _data and missing array managers --- etemplate/js/et2_inputWidget.js | 9 +++++++++ etemplate/js/et2_valueWidget.js | 10 ++++++---- etemplate/js/et2_widget.js | 16 ++++++++++------ etemplate/js/etemplate2.js | 4 +++- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 4c4a045d44..1b7a31a747 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -45,6 +45,14 @@ var et2_IInput = new Interface({ */ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { + attributes: { + "required": { + "name": "Required", + "default": false, + "type": "boolean", + "description": "If required, the user must enter a value before the form can be submitted" + } + }, init: function() { this._super.apply(this, arguments); @@ -89,6 +97,7 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { node.removeAttribute("required"); } } + }, get_value: function() { diff --git a/etemplate/js/et2_valueWidget.js b/etemplate/js/et2_valueWidget.js index 92abbd5506..778a970017 100644 --- a/etemplate/js/et2_valueWidget.js +++ b/etemplate/js/et2_valueWidget.js @@ -40,10 +40,12 @@ var et2_valueWidget = et2_baseWidget.extend({ { // Set the value for this element var contentMgr = this.getArrayMgr("content"); - var val = contentMgr.getValueForID(this.id); - if (val !== null) - { - this.setAttribute("value", val) + if(contentMgr != null) { + var val = contentMgr.getValueForID(this.id); + if (val !== null) + { + this.setAttribute("value", val) + } } } } diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js index 9905c65a89..3bd3507954 100644 --- a/etemplate/js/et2_widget.js +++ b/etemplate/js/et2_widget.js @@ -395,8 +395,12 @@ var et2_widget = Class.extend({ // Check whether the widget is marked as readonly and whether a special // readonly type (suffixed with "_ro") is registered - var readonly = this.getArrayMgr("readonlys").isReadOnly( - _node.getAttribute("id"), _node.getAttribute("readonly"), this.readonly); + var mgr = this.getArrayMgr("readonlys"); + var readonly = false; + if(mgr != null) { + readonly = mgr.isReadOnly( + _node.getAttribute("id"), _node.getAttribute("readonly"), this.readonly); + } if (readonly && typeof et2_registry[_nodeName + "_ro"] != "undefined") { constructor = et2_registry[_nodeName + "_ro"]; @@ -471,7 +475,8 @@ var et2_widget = Class.extend({ var attrName = _attrs[i].name; var attrValue = _attrs[i].value; - if (typeof this.attributes[attrName] != "undefined") + var mgr = this.getArrayMgr("content"); + if (mgr != null && typeof this.attributes[attrName] != "undefined") { var attr = this.attributes[attrName]; @@ -479,12 +484,11 @@ var et2_widget = Class.extend({ // expression as bool expression. if (attr.type == "boolean") { - attrValue = this.getArrayMgr("content") - .parseBoolExpression(attrValue); + attrValue = mgr.parseBoolExpression(attrValue); } else { - attrValue = this.getArrayMgr("content").expandName(attrValue); + attrValue = mgr.expandName(attrValue); } } diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 242b276b90..4259fd6f06 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -131,7 +131,9 @@ etemplate2.prototype.load = function(_url, _data) this.widgetContainer.setParentDOMNode(this.DOMContainer); // store the id to submit it back to server - this.etemplate_exec_id = _data.etemplate_exec_id; + if(_data) { + this.etemplate_exec_id = _data.etemplate_exec_id; + } // set app_header if (window.opener) { // popup From ea8d70136e68ec8e0717ce5306c889a56c33d520 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Tue, 16 Aug 2011 23:07:44 +0000 Subject: [PATCH 066/472] Implement labelplaceholder for OO.o files --- etemplate/inc/class.bo_merge.inc.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php index 0c06249895..5a01b43c42 100644 --- a/etemplate/inc/class.bo_merge.inc.php +++ b/etemplate/inc/class.bo_merge.inc.php @@ -538,8 +538,7 @@ abstract class bo_merge return $contentstart.implode('\\par \\page\\pard\\plain',$contentrepeatpages).$contentend; case 'application/vnd.oasis.opendocument.text': case 'application/vnd.oasis.opendocument.spreadsheet': - // todo OO writer files - break; + return $contentstart.implode('<text:line-break />',$contentrepeatpages).$contentend; case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': return $contentstart.implode('<w:br w:type="page" />',$contentrep).$contentend; From 2234cc34138ab55ba96787d0e7d41bb53adcd50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= <andreas.stoeckel@googlemail.com> Date: Wed, 17 Aug 2011 09:07:09 +0000 Subject: [PATCH 067/472] Added very simple but working implementation of the tabs widget --- etemplate/js/et2_selectbox.js | 2 +- etemplate/js/et2_tabs.js | 39 ++++++++++--------- etemplate/js/test/test.css | 67 +++++++++++++++++++++++++-------- etemplate/js/test/test_xml.html | 2 +- 4 files changed, 75 insertions(+), 35 deletions(-) diff --git a/etemplate/js/et2_selectbox.js b/etemplate/js/et2_selectbox.js index 95ef429c92..b06b8c93b1 100644 --- a/etemplate/js/et2_selectbox.js +++ b/etemplate/js/et2_selectbox.js @@ -79,7 +79,7 @@ var et2_selectbox = et2_inputWidget.extend({ this.setDOMNode(this.input[0]); }, - set_id: function(_id) { + loadingFinished: function() { this._super.apply(this,arguments); // Get select options from the manager(s) diff --git a/etemplate/js/et2_tabs.js b/etemplate/js/et2_tabs.js index 29e3b572bd..84782c5677 100644 --- a/etemplate/js/et2_tabs.js +++ b/etemplate/js/et2_tabs.js @@ -28,18 +28,10 @@ var et2_tabbox = et2_DOMWidget.extend({ .addClass("et2_tabbox"); // Create the upper container for the tab flags - var cntr = $j(document.createElement("div")) - .addClass("et2_flags") + this.flagContainer = $j(document.createElement("div")) + .addClass("et2_tabheader") .appendTo(this.container); - this.flagContainer = $j(document.createElement("span")) - .addClass("et2_tabflagcntr") - .appendTo(cntr); - - $j(document.createElement("span")) - .addClass("et2_tabspacer") - .appendTo(cntr); - // Create the lower tab container this.tabContainer = $j(document.createElement("div")) .addClass("et2_tabs") @@ -130,18 +122,15 @@ var et2_tabbox = et2_DOMWidget.extend({ for (var i = 0; i < this.tabData.length; i++) { - // Add a spacer to the flag container - $j(document.createElement("span")) - .addClass("et2_flagspacer") - .text("-") - .appendTo(this.flagContainer); - var entry = this.tabData[i]; entry.flagDiv = $j(document.createElement("span")) .addClass("et2_tabflag") .text(entry.label) - .appendTo(this.flagContainer); + .appendTo(this.flagContainer) + .click({"tabs": this, "idx": i}, function(e) { + e.data.tabs.setActiveTab(e.data.idx); + }); entry.contentDiv = $j(document.createElement("div")) .addClass("et2_tabcntr") @@ -151,6 +140,22 @@ var et2_tabbox = et2_DOMWidget.extend({ // Let the widget appear on its corresponding page entry.widget.onSetParent(); } + + this.setActiveTab(0); + }, + + setActiveTab: function(_idx) { + console.log(_idx); + // Remove the "active" flag from all tabs-flags + $j(".et2_tabflag", this.flagContainer).removeClass("active"); + + // Hide all tab containers + this.tabContainer.children().hide(); + + // Set the tab flag with the given index active and show the corresponding + // container + this.flagContainer.children(":eq(" + _idx + ")").addClass("active"); + this.tabContainer.children(":eq(" + _idx + ")").show(); }, getDOMNode: function(_sender) { diff --git a/etemplate/js/test/test.css b/etemplate/js/test/test.css index 30a049c4bc..714b29dd7f 100644 --- a/etemplate/js/test/test.css +++ b/etemplate/js/test/test.css @@ -6,7 +6,7 @@ /* Stuff for the standalone test webpage */ -body { +body, table, td { font-family: Lucida Grande, sans-serif; font-size: 10pt; } @@ -140,21 +140,6 @@ button.et2_button:focus { outline: none; } -.et2_tabflag { - display: inline-block; - margin-right: 5px; - height: 20px; - padding: 5px; - cursor: pointer; - border-width: 1px 1px 0 1px; - border-style: solid; - border-color: silver; -} - -.et2_tabflag.active { - border-bottom: 1px solid white; -} - .et2_textbox { resize: none; } @@ -177,5 +162,55 @@ button.et2_button:focus { color: black; } +/** + * Tabs widget + */ + +.et2_tabflag { + display: inline-block; + margin-right: 5px; + padding: 5px; + cursor: pointer; + border: 1px solid silver; + + background-color: #E0E0E0; + background-image: url(gfx/gradient01.png); + background-position: center; + background-repeat: repeat-x; + + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.et2_tabflag:hover { + color: #050505; + border: 1px solid gray; + background-color: #D0D0EE; +} + +.et2_tabflag:active { + background-image: url(gfx/gradient02.png); + background-color: #D0D0E0; +} + +.et2_tabs { + border-width: 0px 1px 1px 1px; + border-style: solid; + border-color: silver; + padding: 5px; +} + +.et2_tabflag.active { + border-bottom: 1px solid white; + background-color: white; + background-image: none; +} + +.et2_tabheader { + background-image: url(gfx/tab_header_bg.png); + background-position: bottom; + background-repeat: repeat-x; +} diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 33cbe78631..5e38fd895e 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -26,7 +26,7 @@ <script src="../etemplate2.js"></script> - <!--<script src="../et2_tabs.js"></script>--> + <script src="../et2_tabs.js"></script> <script src="../lib/tooltip.js"></script> <script src="../../../phpgwapi/js/jsapi/jsapi.js"></script> From 495632fc40e9163c390b5d57803570e0fa599d93 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Wed, 17 Aug 2011 09:32:55 +0000 Subject: [PATCH 068/472] removed not used file --- admin/inc/hook_config.inc.php | 104 ---------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 admin/inc/hook_config.inc.php diff --git a/admin/inc/hook_config.inc.php b/admin/inc/hook_config.inc.php deleted file mode 100644 index 40ea88affd..0000000000 --- a/admin/inc/hook_config.inc.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - /**************************************************************************\ - * eGroupWare * - * http://www.egroupware.org * - * Written by Mark Peters <skeeter@phpgroupware.org> * - * -------------------------------------------- * - * This program is free software; you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the * - * Free Software Foundation; either version 2 of the License, or (at your * - * option) any later version. * - \**************************************************************************/ - - /* $Id$ */ - - function encryptalgo($config) - { - if(@function_exists('mcrypt_list_algorithms')) - { - $listed = array(); - if(!isset($config['mcrypt_algo'])) - { - $config['mcrypt_algo'] = 'tripledes'; /* MCRYPT_TRIPLEDES */ - } - $algos = @mcrypt_list_algorithms(); - $found = False; - - while (list ($key, $value) = each ($algos)) - { - $found = True; - /* Only show each once - seems this is a problem in some installs */ - if(!in_array($value,$listed)) - { - if ($config['mcrypt_algo'] == $value) - { - $selected = ' selected="selected"'; - } - else - { - $selected = ''; - } - $descr = strtoupper($value); - - $out .= '<option value="' . $value . '"' . $selected . '>' . $descr . '</option>' . "\n"; - $listed[] = $value; - } - } - if(!$found) - { - /* Something is wrong with their mcrypt install or php.ini */ - $out = '<option value="">' . lang('no algorithms available') . '</option>' . "\n";; - } - } - else - { - $out = '<option value="tripledes">TRIPLEDES</option>' . "\n";; - } - return $out; - } - - function encryptmode($config) - { - if(@function_exists('mcrypt_list_modes')) - { - $listed = array(); - if(!isset($config['mcrypt_mode'])) - { - $config['mcrypt_mode'] = 'cbc'; /* MCRYPT_MODE_CBC */ - } - $modes = @mcrypt_list_modes(); - $found = False; - - while (list ($key, $value) = each ($modes)) - { - $found = True; - /* Only show each once - seems this is a problem in some installs */ - if(!in_array($value,$listed)) - { - if ($config['mcrypt_mode'] == $value) - { - $selected = ' selected="selected"'; - } - else - { - $selected = ''; - } - $descr = strtoupper($value); - - $out .= '<option value="' . $value . '"' . $selected . '>' . $descr . '</option>' . "\n"; - $listed[] = $value; - } - } - if(!$found) - { - /* Something is wrong with their mcrypt install or php.ini */ - $out = '<option value="" selected="selected">' . lang('no modes available') . '</option>' . "\n"; - } - } - else - { - $out = '<option value="cbc" selected="selected">CBC</option>' . "\n"; - } - return $out; - } -?> From 7cbff7885496970172ca69cb094201884ddf92a3 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Wed, 17 Aug 2011 09:36:51 +0000 Subject: [PATCH 069/472] config for export limit excepted users/groups, need backend work from nathan --- admin/templates/default/config.tpl | 9 ++++++--- etemplate/inc/class.bo_merge.inc.php | 19 ++++++++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/admin/templates/default/config.tpl b/admin/templates/default/config.tpl index 5dda16f772..e9bf71ade6 100644 --- a/admin/templates/default/config.tpl +++ b/admin/templates/default/config.tpl @@ -25,7 +25,7 @@ <td>{lang_Timeout_for_application_session_data_in_seconds_(default_86400_=_1_day)}:</td> <td><input size="8" name="newsettings[sessions_app_timeout]" value="{value_sessions_app_timeout}"></td> </tr> - + <tr class="row_on"> <td>{lang_Would_you_like_to_show_each_application's_upgrade_status_?}:</td><td> <select name="newsettings[checkappversions]"> @@ -294,12 +294,15 @@ <td>{lang_How_many_entries_should_non-admins_be_able_to_export_(empty_=_no_limit,_no_=_no_export)}:<br />{lang_This_controls_exports_and_merging.}</td> <td><input name="newsettings[export_limit]" value="{value_export_limit}" size="5"></td> </tr> - </tr> <tr class="row_on"> + <td>{lang_Group_excepted_from_above_export_limit_(admins_are_always_excepted)}:</td> + <td>{call_bo_merge::hook_export_limit_excepted}</td> + </tr> + <tr class="row_off"> <td>{lang_Allow_remote_administration_from_following_install_ID's_(comma_separated)}:<br />{lang_Own_install_ID:_}{value_install_id}</td> <td><input name="newsettings[allow_remote_admin]" value="{value_allow_remote_admin}" size="40"></td> </tr> - <tr class="row_off"> + <tr class="row_on"> <td>{lang_Should_exceptions_contain_a_trace_(including_function_arguments)}:</td> <td> <select name="newsettings[exception_show_trace]"> diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php index 5a01b43c42..82fb7884df 100644 --- a/etemplate/inc/class.bo_merge.inc.php +++ b/etemplate/inc/class.bo_merge.inc.php @@ -76,6 +76,19 @@ abstract class bo_merge $this->export_limit = $GLOBALS['egw_info']['server']['export_limit']; } + /** + * Hook returning options for export_limit_excepted groups + * + * @param array $config + */ + public static function hook_export_limit_excepted($config) + { + error_log(__METHOD__.'('.array2string($config).')'); + $accountsel = new uiaccountsel(); + + return $accountsel->selection('newsettings[export_limit_excepted]','export_limit_excepted',$config['export_limit_excepted'],'both',4); + } + /** * Get all replacements, must be implemented in extending class * @@ -322,7 +335,7 @@ abstract class bo_merge } return $content; } - + protected function apply_styles (&$content, $mimetype) { // Tags we can replace with the target document's version $replace_tags = array(); @@ -336,7 +349,7 @@ abstract class bo_merge '/<\/(ol|ul|table)>/' => '</$1><text:p>', //'/<(li)(.*?)>(.*?)<\/\1>/' => '<$1 $2>$3</$1>', ); - $content = preg_replace(array_keys($replace_tags),array_values($replace_tags),$content); + $content = preg_replace(array_keys($replace_tags),array_values($replace_tags),$content); $doc = new DOMDocument(); $xslt = new XSLTProcessor(); @@ -356,7 +369,7 @@ abstract class bo_merge '/<\/(ol|ul|table)>/' => '</$1><w:p><w:r><w:t>', '/<(li)(.*?)>(.*?)<\/\1>/' => '<$1 $2>$3</$1>', ); - $content = preg_replace(array_keys($replace_tags),array_values($replace_tags),$content); + $content = preg_replace(array_keys($replace_tags),array_values($replace_tags),$content); //echo $content;die(); $doc = new DOMDocument(); $xslt = new XSLTProcessor(); From 2a815be3d3ae3e58e890dfd4ac0f4704c6751392 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 14:47:17 +0000 Subject: [PATCH 070/472] Process xml as if it were a MSOffice document --- etemplate/inc/class.bo_merge.inc.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php index 82fb7884df..05e5eb486d 100644 --- a/etemplate/inc/class.bo_merge.inc.php +++ b/etemplate/inc/class.bo_merge.inc.php @@ -360,6 +360,7 @@ abstract class bo_merge break; case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': // ms office 2007 case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': + case 'application/xml': $replace_tags = array( 'b','strong','i','em','u','span' ); @@ -639,6 +640,7 @@ abstract class bo_merge break; case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': // ms office 2007 case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': + case 'application/xml': $replace_tags = array( '<b>','<strong>','<i>','<em>','<u>','<span>','<ol>','<ul>','<li>', '<table>','<tr>','<td>', From 16bafa78b844f53603a1f0e44ddea2eb18296cf0 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 15:38:56 +0000 Subject: [PATCH 071/472] Implement export restriction exception for given users/groups in apps --- addressbook/inc/class.addressbook_ui.inc.php | 6 ++++-- calendar/inc/class.calendar_export_csv.inc.php | 8 +++++--- calendar/inc/class.calendar_export_ical.inc.php | 8 +++++--- etemplate/inc/class.bo_merge.inc.php | 6 ++++-- etemplate/inc/class.nextmatch_widget.inc.php | 6 ++++-- .../class.importexport_admin_prefs_sidebox_hooks.inc.php | 6 ++++-- .../inc/class.importexport_definitions_ui.inc.php | 3 ++- importexport/inc/class.importexport_export_csv.inc.php | 3 ++- importexport/inc/class.importexport_export_ui.inc.php | 3 ++- 9 files changed, 32 insertions(+), 17 deletions(-) diff --git a/addressbook/inc/class.addressbook_ui.inc.php b/addressbook/inc/class.addressbook_ui.inc.php index 5f115806b1..328dc5666a 100644 --- a/addressbook/inc/class.addressbook_ui.inc.php +++ b/addressbook/inc/class.addressbook_ui.inc.php @@ -568,7 +568,8 @@ class addressbook_ui extends addressbook_bo } // check if user is an admin or the export is not generally turned off (contact_export_limit is non-numerical, eg. no) - if (isset($GLOBALS['egw_info']['user']['apps']['admin']) || !$this->config['contact_export_limit'] || (int)$this->config['contact_export_limit']) + $exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + if ((isset($GLOBALS['egw_info']['user']['apps']['admin']) || $exception) || !$this->config['contact_export_limit'] || (int)$this->config['contact_export_limit']) { $actions['export'] = array( 'caption' => 'Export', @@ -798,8 +799,9 @@ class addressbook_ui extends addressbook_bo $action = substr($action,0,7); } // Security: stop non-admins to export more then the configured number of contacts + $exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; if (in_array($action,array('csv','vcard')) && $this->config['contact_export_limit'] && - !isset($GLOBALS['egw_info']['user']['apps']['admin']) && + !(isset($GLOBALS['egw_info']['user']['apps']['admin']) || $exception) && (!is_numeric($this->config['contact_export_limit']) || count($checked) > $this->config['contact_export_limit'])) { $action_msg = lang('exported'); diff --git a/calendar/inc/class.calendar_export_csv.inc.php b/calendar/inc/class.calendar_export_csv.inc.php index 4908e9a734..61237a62a4 100644 --- a/calendar/inc/class.calendar_export_csv.inc.php +++ b/calendar/inc/class.calendar_export_csv.inc.php @@ -26,6 +26,8 @@ class calendar_export_csv implements importexport_iface_export_plugin { $this->bo = new calendar_bo(); $config = config::read('phpgwapi'); + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + // Custom fields need to be specifically requested $cfs = array(); foreach($options['mapping'] as $key => $label) { @@ -42,7 +44,7 @@ class calendar_export_csv implements importexport_iface_export_plugin { 'users' => $options['selection']['owner'], 'cfs' => $cfs // Otherwise we shouldn't get any custom fields ); - if($config['export_limit']) { + if($config['export_limit'] && !($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception)) { $query['offset'] = 0; $query['num_rows'] = (int)$config['export_limit']; } @@ -55,7 +57,7 @@ class calendar_export_csv implements importexport_iface_export_plugin { $query['start'] = 0; $query['cfs'] = $cfs; - if($config['export_limit']) { + if($config['export_limit'] && !($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception)) { $query['num_rows'] = (int)$config['export_limit']; } $ui = new calendar_uilist(); @@ -64,7 +66,7 @@ class calendar_export_csv implements importexport_iface_export_plugin { $query = $GLOBALS['egw']->session->appsession('session_data','calendar'); $query['users'] = explode(',', $query['owner']); $query['num_rows'] = -1; - if($config['export_limit']) { + if($config['export_limit'] && !($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception)) { $query['num_rows'] = (int)$config['export_limit']; } diff --git a/calendar/inc/class.calendar_export_ical.inc.php b/calendar/inc/class.calendar_export_ical.inc.php index 79ae5ab94d..8c4303f851 100644 --- a/calendar/inc/class.calendar_export_ical.inc.php +++ b/calendar/inc/class.calendar_export_ical.inc.php @@ -32,6 +32,8 @@ class calendar_export_ical extends calendar_export_csv { if($key[0] == '#') $cfs[] = substr($key,1); } + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + if($options['selection']['select'] == 'criteria') { $query = array( 'start' => $options['selection']['start'], @@ -42,7 +44,7 @@ class calendar_export_ical extends calendar_export_csv { 'users' => $options['selection']['owner'], 'cfs' => $cfs // Otherwise we shouldn't get any custom fields ); - if($config['export_limit']) { + if($config['export_limit'] && !($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception)) { $query['offset'] = 0; $query['num_rows'] = (int)$config['export_limit']; } @@ -55,7 +57,7 @@ class calendar_export_ical extends calendar_export_csv { $query['start'] = 0; $query['cfs'] = $cfs; - if($config['export_limit']) { + if($config['export_limit'] && !($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception)) { $query['num_rows'] = (int)$config['export_limit']; } $ui = new calendar_uilist(); @@ -64,7 +66,7 @@ class calendar_export_ical extends calendar_export_csv { $query = $GLOBALS['egw']->session->appsession('session_data','calendar'); $query['users'] = explode(',', $query['owner']); $query['num_rows'] = -1; - if($config['export_limit']) { + if($config['export_limit'] && !($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception)) { $query['num_rows'] = (int)$config['export_limit']; } diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php index 05e5eb486d..448cbbf5fc 100644 --- a/etemplate/inc/class.bo_merge.inc.php +++ b/etemplate/inc/class.bo_merge.inc.php @@ -314,7 +314,8 @@ abstract class bo_merge } // check export-limit and fail if user tries to export more entries then allowed - if ($this->export_limit && !$GLOBALS['egw_info']['user']['apps']['admin'] && + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + if ($this->export_limit && !($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception) && count($ids) > (int)$this->export_limit) { $err = lang('No rights to export more then %1 entries!',(int)$this->export_limit); @@ -1155,13 +1156,14 @@ abstract class bo_merge } } } + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; return array( 'icon' => 'etemplate/merge', 'caption' => $caption, 'children' => $documents, // disable action if no document or export completly forbidden for non-admins 'enabled' => (boolean)$documents && (empty($export_limit) || - (int)$export_limit > 0 || $GLOBALS['egw_info']['user']['apps']['admin']), + (int)$export_limit > 0 || $GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception), 'hideOnDisabled' => true, // do not show 'Insert in document', if no documents defined or no export allowed 'group' => $group, ); diff --git a/etemplate/inc/class.nextmatch_widget.inc.php b/etemplate/inc/class.nextmatch_widget.inc.php index c1ecd8a3dc..313dbaa436 100644 --- a/etemplate/inc/class.nextmatch_widget.inc.php +++ b/etemplate/inc/class.nextmatch_widget.inc.php @@ -276,9 +276,10 @@ class nextmatch_widget unset($value['rows']); $extension_data += $value; + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; $value['no_csv_export'] = $value['csv_fields'] === false || $GLOBALS['egw_info']['server']['export_limit'] && !is_numeric($GLOBALS['egw_info']['server']['export_limit']) && - !isset($GLOBALS['egw_info']['user']['apps']['admin']); + !(isset($GLOBALS['egw_info']['user']['apps']['admin']) || $limit_exception); if (!$value['filter_onchange']) $value['filter_onchange'] = 'this.form.submit();'; if (!$value['filter2_onchange']) $value['filter2_onchange'] = 'this.form.submit();'; @@ -1447,7 +1448,8 @@ class nextmatch_widget */ static public function csv_export(&$value,$separator=';') { - if (!isset($GLOBALS['egw_info']['user']['apps']['admin'])) + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + if (!(isset($GLOBALS['egw_info']['user']['apps']['admin']) || $limit_exception)) { $export_limit = $GLOBALS['egw_info']['server']['export_limit']; //if (isset($value['export_limit'])) $export_limit = $value['export_limit']; diff --git a/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php b/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php index 67d43a8874..1741f48228 100644 --- a/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php +++ b/importexport/inc/class.importexport_admin_prefs_sidebox_hooks.inc.php @@ -38,7 +38,8 @@ class importexport_admin_prefs_sidebox_hooks ), ); $config = config::read('phpgwapi'); - if($GLOBALS['egw_info']['user']['apps']['admin'] || $config['export_limit'] !== 'no') + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + if($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception || $config['export_limit'] !== 'no') { $file[] = array( 'text' => 'Export', @@ -122,7 +123,8 @@ class importexport_admin_prefs_sidebox_hooks } } $config = config::read('phpgwapi'); - if (($GLOBALS['egw_info']['user']['apps']['admin'] || !$config['export_limit'] || $config['export_limit'] > 0) && $cache[$appname]['export']) + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + if (($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception || !$config['export_limit'] || $config['export_limit'] > 0) && $cache[$appname]['export']) { $file['Export CSV'] = array('link' => "javascript:egw_openWindowCentered2('". egw::link('/index.php',array( diff --git a/importexport/inc/class.importexport_definitions_ui.inc.php b/importexport/inc/class.importexport_definitions_ui.inc.php index 7b017f9176..eaf9ff63a4 100644 --- a/importexport/inc/class.importexport_definitions_ui.inc.php +++ b/importexport/inc/class.importexport_definitions_ui.inc.php @@ -85,9 +85,10 @@ class importexport_definitions_ui $filter[] = '(owner=0 OR owner IS NULL OR allowed_users IS NOT NULL OR owner = ' . $GLOBALS['egw_info']['user']['account_id'] . ')'; } else { // Filter private definitions + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; $filter['owner'] = $GLOBALS['egw_info']['user']['account_id']; $config = config::read('phpgwapi'); - if($config['export_limit'] == 'no') { + if($config['export_limit'] == 'no' && !$limit_exception) { $filter['type'] = 'import'; } } diff --git a/importexport/inc/class.importexport_export_csv.inc.php b/importexport/inc/class.importexport_export_csv.inc.php index 7a7c0a474f..293487c571 100644 --- a/importexport/inc/class.importexport_export_csv.inc.php +++ b/importexport/inc/class.importexport_export_csv.inc.php @@ -101,7 +101,8 @@ class importexport_export_csv implements importexport_iface_export_record $this->csv_options = array_merge( $this->csv_options, $_options ); } - if(!$GLOBALS['egw_info']['user']['apps']['admin']) { + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + if(!($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception)) { $config = config::read('phpgwapi'); if($config['export_limit'] == 'no') throw new egw_exception_no_permission_admin('Export disabled'); $this->export_limit = (int)$config['export_limit']; diff --git a/importexport/inc/class.importexport_export_ui.inc.php b/importexport/inc/class.importexport_export_ui.inc.php index 9ef69c9ec7..c12b64ce9c 100644 --- a/importexport/inc/class.importexport_export_ui.inc.php +++ b/importexport/inc/class.importexport_export_ui.inc.php @@ -49,7 +49,8 @@ class importexport_export_ui { $preserv = array(); // Check global setting - if(!$GLOBALS['egw_info']['user']['apps']['admin']) { + $limit_exception = count(array_intersect(array($GLOBALS['egw_info']['user']['account_id']) + $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true), unserialize($GLOBALS['egw_info']['server']['export_limit_excepted']))) > 0; + if(!($GLOBALS['egw_info']['user']['apps']['admin'] || $limit_exception)) { $config = config::read('phpgwapi'); if($config['export_limit'] == 'no') { die(lang('Admin disabled exporting')); From 8f5f3347623824ae564a325461bc230a1b095b5a Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 15:47:05 +0000 Subject: [PATCH 072/472] Only process HTML inside Word xml documents --- etemplate/inc/class.bo_merge.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php index 448cbbf5fc..c22ed4e585 100644 --- a/etemplate/inc/class.bo_merge.inc.php +++ b/etemplate/inc/class.bo_merge.inc.php @@ -359,9 +359,9 @@ abstract class bo_merge //echo $content;die(); break; + case 'application/xmlWord.Document': // Word 2003*/ case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': // ms office 2007 case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': - case 'application/xml': $replace_tags = array( 'b','strong','i','em','u','span' ); @@ -639,9 +639,9 @@ abstract class bo_merge '<table>','<tr>','<td>', ); break; + case 'application/xmlWord.Document': // Word 2003*/ case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': // ms office 2007 case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': - case 'application/xml': $replace_tags = array( '<b>','<strong>','<i>','<em>','<u>','<span>','<ol>','<ul>','<li>', '<table>','<tr>','<td>', From d20c38b3d024869da8033a6f82ea12cdd06c289b Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Wed, 17 Aug 2011 16:34:09 +0000 Subject: [PATCH 073/472] added richtext customfield --- etemplate/inc/class.customfields_widget.inc.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/etemplate/inc/class.customfields_widget.inc.php b/etemplate/inc/class.customfields_widget.inc.php index cc348fcf44..6fb047e27e 100644 --- a/etemplate/inc/class.customfields_widget.inc.php +++ b/etemplate/inc/class.customfields_widget.inc.php @@ -58,6 +58,7 @@ class customfields_widget 'url' => 'Url', 'url-email'=> 'EMail', 'url-phone'=> 'Phone number', + 'htmlarea' => 'Formatted Text (HTML)', 'link-entry' => 'Select entry', // should be last type, as the individual apps get added behind ); @@ -435,6 +436,12 @@ class customfields_widget 'size' => $field['len'] )); break; + case 'htmlarea': // defaults: len: width=100%,mode=simple,tooldbar=false; rows: 5 + list($width,$mode,$toolbar) = explode(',',$field['len']); + $input =& etemplate::empty_cell($field['type'],$this->prefix.$lname,array( + 'size' => $mode.','.(($field['rows'] ? $field['rows'] : 5)*16).'px,'.$width.','.($toolbar=='true'?'true':'false'), + )); + break; // other etemplate types, which are used just as is case 'checkbox' : $input =& etemplate::empty_cell($field['type'],$this->prefix.$lname); From abf37487b8ed81df806e2a2f663646336840feb3 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 17:48:39 +0000 Subject: [PATCH 074/472] Fix typo --- etemplate/js/et2_DOMWidget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etemplate/js/et2_DOMWidget.js b/etemplate/js/et2_DOMWidget.js index aad70b65a4..b35e3046ff 100644 --- a/etemplate/js/et2_DOMWidget.js +++ b/etemplate/js/et2_DOMWidget.js @@ -195,7 +195,7 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, { var node = this.getDOMNode(); if (node) { - this.diabled = _value; + this.disabled = _value; if (_value) { From 379b05b39f6cb6e5b2469ce8052ce49d9de0b8ea Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 17:50:15 +0000 Subject: [PATCH 075/472] Get empty label / row count legacy option working --- etemplate/js/et2_selectbox.js | 50 +++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/etemplate/js/et2_selectbox.js b/etemplate/js/et2_selectbox.js index b06b8c93b1..2db451c2fd 100644 --- a/etemplate/js/et2_selectbox.js +++ b/etemplate/js/et2_selectbox.js @@ -51,7 +51,6 @@ var et2_selectbox = et2_inputWidget.extend({ this.input = null; this.id = ""; - if(this.rows > 1) this.multiselect=true; this.createInputWidget(); }, @@ -65,6 +64,13 @@ var et2_selectbox = et2_inputWidget.extend({ } else { this._super.apply(this,arguments); } + + // Legacy options could have row count or empty label in first slot + if(typeof this.rows == "string" && isNaN(this.rows)) { + this.set_empty_label(this.rows); + this.set_rows(1); + } + if(this.rows > 1) this.set_multiselect(true); }, createInputWidget: function() { @@ -79,30 +85,34 @@ var et2_selectbox = et2_inputWidget.extend({ this.setDOMNode(this.input[0]); }, - loadingFinished: function() { + /** + * Override parent to get the select options. + * Can't get them before this, because the ID is not set when createInputWidget() is called. + */ + set_id: function() { this._super.apply(this,arguments); // Get select options from the manager(s) var options = null; - // Check the sel_options - var mgr = this.getArrayMgr('sel_options'); - if(mgr) { - options = mgr.getValueForID(this.id); - } - if(options != null) { - this.set_select_options(options); - } else { - // Check in the content - var mgr = this.getArrayMgr('content'); - if(mgr) { - options = mgr.getValueForID('options-'+this.id); - } - } - this.set_select_options(options); + // Check the sel_options (from managers) + this.set_select_options(null); }, set_select_options: function(_options) { + if(_options == null) { + var mgr = this.getArrayMgr('sel_options'); + if(mgr) { + options = mgr.getValueForID(this.id); + } + if(options == null) { + // Check in the content + var mgr = this.getArrayMgr('content'); + if(mgr) { + options = mgr.getValueForID('options-'+this.id); + } + } + } this.input.children().remove(); if(this.empty_label) { this.input.append("<option value=''" + ("" == this.getValue() ? "selected":"") +">"+this.empty_label+"</option>"); @@ -130,6 +140,12 @@ var et2_selectbox = et2_inputWidget.extend({ this.rows = _rows; this.input.attr("size",this.rows); } + }, + set_empty_label: function(_label) { + if(_label != this.empty_label) { + this.empty_label = _label; + this.set_select_options(null); + } } }); From ba5fee777c3b60eee582d3ee0571a360d1666d61 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 19:46:19 +0000 Subject: [PATCH 076/472] Basic widgets xml file --- etemplate/js/test/et2_test_basic_widgets.xet | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 etemplate/js/test/et2_test_basic_widgets.xet diff --git a/etemplate/js/test/et2_test_basic_widgets.xet b/etemplate/js/test/et2_test_basic_widgets.xet new file mode 100644 index 0000000000..499b02e8f6 --- /dev/null +++ b/etemplate/js/test/et2_test_basic_widgets.xet @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<overlay> + <!-- Test without template --> + <description value="This is a label" id="label_value"/> + <textbox label="This is a text" id="text_value"/> + <textbox label="This is required text" id="text_value" required="true"/> + <int label="This is an integer" id="integer_value" min="5"/> + <textbox type="float" label="This is a float" id="float_value"/> + <textbox multiline="true" label="This is a text area" id="text_area_value"/> + <checkbox label="Checkbox" id="checkbox_value"/> + <radio label="Radio" id="radio_value"/> + <buttononly label="Button" id="button_value"/> + <hrule label="HR"/> + <image label="Image" src="image_value"/> + <menulist> + <menupopup label="Selectbox" id="selectbox_value" options="No value"/> + </menulist> + <listbox label="Multiselect" id="multiselect" rows="5"/> + + <!-- Test with template --> +<!-- + <template id="test.basic_widget_test"> + <description value="This is a label" id="label_value"/> + <textbox label="This is a text" id="text_value"/> + <int label="This is an integer" id="integer_value" min="5"/> + <textbox type="float" label="This is a float" id="float_value"/> + <textbox multiline="true" label="This is a text area" id="text_area_value"/> + <checkbox label="Checkbox" id="checkbox_value"/> + <radio label="Radio" id="radio_value"/> + <buttononly label="Button" id="button_value"/> + <hrule label="HR"/> + <image label="Image" src="image_value"/> + <menulist> + <menupopup label="Selectbox" id="selectbox_value" options="No value"/> + </menulist> + <listbox label="Multiselect" id="multiselect" rows="5"/> + </template> +--> + <!-- Reference the template above (Why?) --> +<!-- + <template id="test.basic_widget_test" /> +--> +</overlay> From c409e8d73eb50d81d1c530b70f5a572a4491c1ed Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 21:32:38 +0000 Subject: [PATCH 077/472] Fix typo breaking selectbox options --- etemplate/js/et2_selectbox.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/etemplate/js/et2_selectbox.js b/etemplate/js/et2_selectbox.js index 2db451c2fd..9df678b1f2 100644 --- a/etemplate/js/et2_selectbox.js +++ b/etemplate/js/et2_selectbox.js @@ -103,13 +103,13 @@ var et2_selectbox = et2_inputWidget.extend({ if(_options == null) { var mgr = this.getArrayMgr('sel_options'); if(mgr) { - options = mgr.getValueForID(this.id); + _options = mgr.getValueForID(this.id); } - if(options == null) { + if(_options == null) { // Check in the content var mgr = this.getArrayMgr('content'); if(mgr) { - options = mgr.getValueForID('options-'+this.id); + _options = mgr.getValueForID('options-'+this.id); } } } From 1761ea02dbdb6c57875c094074256e0ad3f69769 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 21:35:22 +0000 Subject: [PATCH 078/472] Add in jquery.tools form tools --- phpgwapi/js/jquery/jquery.tools.min.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 phpgwapi/js/jquery/jquery.tools.min.js diff --git a/phpgwapi/js/jquery/jquery.tools.min.js b/phpgwapi/js/jquery/jquery.tools.min.js new file mode 100644 index 0000000000..b97a6461d9 --- /dev/null +++ b/phpgwapi/js/jquery/jquery.tools.min.js @@ -0,0 +1,17 @@ +/*! + * jQuery Tools v1.2.5 - The missing UI library for the Web + * + * dateinput/dateinput.js + * rangeinput/rangeinput.js + * tabs/tabs.js + * validator/validator.js + * + * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE. + * + * http://flowplayer.org/tools/ + * + */ +(function(a){a.tools=a.tools||{version:"v1.2.5"};var b=[],c,d=[75,76,38,39,74,72,40,37],e={};c=a.tools.dateinput={conf:{format:"mm/dd/yy",selectors:!1,yearRange:[-5,5],lang:"en",offset:[0,0],speed:0,firstDay:0,min:undefined,max:undefined,trigger:!1,css:{prefix:"cal",input:"date",root:0,head:0,title:0,prev:0,next:0,month:0,year:0,days:0,body:0,weeks:0,today:0,current:0,week:0,off:0,sunday:0,focus:0,disabled:0,trigger:0}},localize:function(b,c){a.each(c,function(a,b){c[a]=b.split(",")}),e[b]=c}},c.localize("en",{months:"January,February,March,April,May,June,July,August,September,October,November,December",shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",days:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",shortDays:"Sun,Mon,Tue,Wed,Thu,Fri,Sat"});function f(a,b){return 32-(new Date(a,b,32)).getDate()}function g(a,b){a=""+a,b=b||2;while(a.length<b)a="0"+a;return a}var h=/d{1,4}|m{1,4}|yy(?:yy)?|"[^"]*"|'[^']*'/g,i=a("<a/>");function j(a,b,c){var d=a.getDate(),f=a.getDay(),j=a.getMonth(),k=a.getFullYear(),l={d:d,dd:g(d),ddd:e[c].shortDays[f],dddd:e[c].days[f],m:j+1,mm:g(j+1),mmm:e[c].shortMonths[j],mmmm:e[c].months[j],yy:String(k).slice(2),yyyy:k},m=b.replace(h,function(a){return a in l?l[a]:a.slice(1,a.length-1)});return i.html(m).html()}function k(a){return parseInt(a,10)}function l(a,b){return a.getFullYear()===b.getFullYear()&&a.getMonth()==b.getMonth()&&a.getDate()==b.getDate()}function m(a){if(a){if(a.constructor==Date)return a;if(typeof a=="string"){var b=a.split("-");if(b.length==3)return new Date(k(b[0]),k(b[1])-1,k(b[2]));if(!/^-?\d+$/.test(a))return;a=k(a)}var c=new Date;c.setDate(c.getDate()+a);return c}}function n(c,g){var h=this,i=new Date,n=g.css,o=e[g.lang],p=a("#"+n.root),q=p.find("#"+n.title),r,s,t,u,v,w,x=c.attr("data-value")||g.value||c.val(),y=c.attr("min")||g.min,z=c.attr("max")||g.max,A;y===0&&(y="0"),x=m(x)||i,y=m(y||g.yearRange[0]*365),z=m(z||g.yearRange[1]*365);if(!o)throw"Dateinput: invalid language: "+g.lang;if(c.attr("type")=="date"){var B=a("<input/>");a.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(a,b){B.attr(b,c.attr(b))}),c.replaceWith(B),c=B}c.addClass(n.input);var C=c.add(h);if(!p.length){p=a("<div><div><a/><div/><a/></div><div><div/><div/></div></div>").hide().css({position:"absolute"}).attr("id",n.root),p.children().eq(0).attr("id",n.head).end().eq(1).attr("id",n.body).children().eq(0).attr("id",n.days).end().eq(1).attr("id",n.weeks).end().end().end().find("a").eq(0).attr("id",n.prev).end().eq(1).attr("id",n.next),q=p.find("#"+n.head).find("div").attr("id",n.title);if(g.selectors){var D=a("<select/>").attr("id",n.month),E=a("<select/>").attr("id",n.year);q.html(D.add(E))}var F=p.find("#"+n.days);for(var G=0;G<7;G++)F.append(a("<span/>").text(o.shortDays[(G+g.firstDay)%7]));a("body").append(p)}g.trigger&&(r=a("<a/>").attr("href","#").addClass(n.trigger).click(function(a){h.show();return a.preventDefault()}).insertAfter(c));var H=p.find("#"+n.weeks);E=p.find("#"+n.year),D=p.find("#"+n.month);function I(b,d,e){x=b,u=b.getFullYear(),v=b.getMonth(),w=b.getDate(),e=e||a.Event("api"),e.type="change",C.trigger(e,[b]);e.isDefaultPrevented()||(c.val(j(b,d.format,d.lang)),c.data("date",b),h.hide(e))}function J(b){b.type="onShow",C.trigger(b),a(document).bind("keydown.d",function(b){if(b.ctrlKey)return!0;var e=b.keyCode;if(e==8){c.val("");return h.hide(b)}if(e==27)return h.hide(b);if(a(d).index(e)>=0){if(!A){h.show(b);return b.preventDefault()}var f=a("#"+n.weeks+" a"),g=a("."+n.focus),i=f.index(g);g.removeClass(n.focus);if(e==74||e==40)i+=7;else if(e==75||e==38)i-=7;else if(e==76||e==39)i+=1;else if(e==72||e==37)i-=1;i>41?(h.addMonth(),g=a("#"+n.weeks+" a:eq("+(i-42)+")")):i<0?(h.addMonth(-1),g=a("#"+n.weeks+" a:eq("+(i+42)+")")):g=f.eq(i),g.addClass(n.focus);return b.preventDefault()}if(e==34)return h.addMonth();if(e==33)return h.addMonth(-1);if(e==36)return h.today();e==13&&(a(b.target).is("select")||a("."+n.focus).click());return a([16,17,18,9]).index(e)>=0}),a(document).bind("click.d",function(b){var d=b.target;!a(d).parents("#"+n.root).length&&d!=c[0]&&(!r||d!=r[0])&&h.hide(b)})}a.extend(h,{show:function(d){if(!(c.attr("readonly")||c.attr("disabled")||A)){d=d||a.Event(),d.type="onBeforeShow",C.trigger(d);if(d.isDefaultPrevented())return;a.each(b,function(){this.hide()}),A=!0,D.unbind("change").change(function(){h.setValue(E.val(),a(this).val())}),E.unbind("change").change(function(){h.setValue(a(this).val(),D.val())}),s=p.find("#"+n.prev).unbind("click").click(function(a){s.hasClass(n.disabled)||h.addMonth(-1);return!1}),t=p.find("#"+n.next).unbind("click").click(function(a){t.hasClass(n.disabled)||h.addMonth();return!1}),h.setValue(x);var e=c.offset();/iPad/i.test(navigator.userAgent)&&(e.top-=a(window).scrollTop()),p.css({top:e.top+c.outerHeight({margins:!0})+g.offset[0],left:e.left+g.offset[1]}),g.speed?p.show(g.speed,function(){J(d)}):(p.show(),J(d));return h}},setValue:function(b,c,d){var e=k(c)>=-1?new Date(k(b),k(c),k(d||1)):b||x;e<y?e=y:e>z&&(e=z),b=e.getFullYear(),c=e.getMonth(),d=e.getDate(),c==-1?(c=11,b--):c==12&&(c=0,b++);if(!A){I(e,g);return h}v=c,u=b;var j=new Date(b,c,1-g.firstDay),m=j.getDay(),p=f(b,c),r=f(b,c-1),w;if(g.selectors){D.empty(),a.each(o.months,function(c,d){y<new Date(b,c+1,-1)&&z>new Date(b,c,0)&&D.append(a("<option/>").html(d).attr("value",c))}),E.empty();var B=i.getFullYear();for(var C=B+g.yearRange[0];C<B+g.yearRange[1];C++)y<=new Date(C+1,-1,1)&&z>new Date(C,0,0)&&E.append(a("<option/>").text(C));D.val(c),E.val(b)}else q.html(o.months[c]+" "+b);H.empty(),s.add(t).removeClass(n.disabled);for(var F=m?0:-7,G,J;F<(m?42:35);F++)G=a("<a/>"),F%7===0&&(w=a("<div/>").addClass(n.week),H.append(w)),F<m?(G.addClass(n.off),J=r-m+F+1,e=new Date(b,c-1,J)):F<m+p?(J=F-m+1,e=new Date(b,c,J),l(x,e)?G.attr("id",n.current).addClass(n.focus):l(i,e)&&G.attr("id",n.today)):(G.addClass(n.off),J=F-p-m+1,e=new Date(b,c+1,J)),y&&e<y&&G.add(s).addClass(n.disabled),z&&e>z&&G.add(t).addClass(n.disabled),G.attr("href","#"+J).text(J).data("date",e),w.append(G);H.find("a").click(function(b){var c=a(this);c.hasClass(n.disabled)||(a("#"+n.current).removeAttr("id"),c.attr("id",n.current),I(c.data("date"),g,b));return!1}),n.sunday&&H.find(n.week).each(function(){var b=g.firstDay?7-g.firstDay:0;a(this).children().slice(b,b+1).addClass(n.sunday)});return h},setMin:function(a,b){y=m(a),b&&x<y&&h.setValue(y);return h},setMax:function(a,b){z=m(a),b&&x>z&&h.setValue(z);return h},today:function(){return h.setValue(i)},addDay:function(a){return this.setValue(u,v,w+(a||1))},addMonth:function(a){return this.setValue(u,v+(a||1),w)},addYear:function(a){return this.setValue(u+(a||1),v,w)},hide:function(b){if(A){b=a.Event(),b.type="onHide",C.trigger(b),a(document).unbind("click.d").unbind("keydown.d");if(b.isDefaultPrevented())return;p.hide(),A=!1}return h},getConf:function(){return g},getInput:function(){return c},getCalendar:function(){return p},getValue:function(a){return a?j(x,a,g.lang):x},isOpen:function(){return A}}),a.each(["onBeforeShow","onShow","change","onHide"],function(b,c){a.isFunction(g[c])&&a(h).bind(c,g[c]),h[c]=function(b){b&&a(h).bind(c,b);return h}}),c.bind("focus click",h.show).keydown(function(b){var c=b.keyCode;if(!A&&a(d).index(c)>=0){h.show(b);return b.preventDefault()}return b.shiftKey||b.ctrlKey||b.altKey||c==9?!0:b.preventDefault()}),m(c.val())&&I(x,g)}a.expr[":"].date=function(b){var c=b.getAttribute("type");return c&&c=="date"||a(b).data("dateinput")},a.fn.dateinput=function(d){if(this.data("dateinput"))return this;d=a.extend(!0,{},c.conf,d),a.each(d.css,function(a,b){!b&&a!="prefix"&&(d.css[a]=(d.css.prefix||"")+(b||a))});var e;this.each(function(){var c=new n(a(this),d);b.push(c);var f=c.getInput().data("dateinput",c);e=e?e.add(f):f});return e?e:this}})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.5"};var b;b=a.tools.rangeinput={conf:{min:0,max:100,step:"any",steps:0,value:0,precision:undefined,vertical:0,keyboard:!0,progress:!1,speed:100,css:{input:"range",slider:"slider",progress:"progress",handle:"handle"}}};var c,d;a.fn.drag=function(b){document.ondragstart=function(){return!1},b=a.extend({x:!0,y:!0,drag:!0},b),c=c||a(document).bind("mousedown mouseup",function(e){var f=a(e.target);if(e.type=="mousedown"&&f.data("drag")){var g=f.position(),h=e.pageX-g.left,i=e.pageY-g.top,j=!0;c.bind("mousemove.drag",function(a){var c=a.pageX-h,e=a.pageY-i,g={};b.x&&(g.left=c),b.y&&(g.top=e),j&&(f.trigger("dragStart"),j=!1),b.drag&&f.css(g),f.trigger("drag",[e,c]),d=f}),e.preventDefault()}else try{d&&d.trigger("dragEnd")}finally{c.unbind("mousemove.drag"),d=null}});return this.data("drag",!0)};function e(a,b){var c=Math.pow(10,b);return Math.round(a*c)/c}function f(a,b){var c=parseInt(a.css(b),10);if(c)return c;var d=a[0].currentStyle;return d&&d.width&&parseInt(d.width,10)}function g(a){var b=a.data("events");return b&&b.onSlide}function h(b,c){var d=this,h=c.css,i=a("<div><div/><a href='#'/></div>").data("rangeinput",d),j,k,l,m,n;b.before(i);var o=i.addClass(h.slider).find("a").addClass(h.handle),p=i.find("div").addClass(h.progress);a.each("min,max,step,value".split(","),function(a,d){var e=b.attr(d);parseFloat(e)&&(c[d]=parseFloat(e,10))});var q=c.max-c.min,r=c.step=="any"?0:c.step,s=c.precision;if(s===undefined)try{s=r.toString().split(".")[1].length}catch(t){s=0}if(b.attr("type")=="range"){var u=a("<input/>");a.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(a,c){u.attr(c,b.attr(c))}),u.val(c.value),b.replaceWith(u),b=u}b.addClass(h.input);var v=a(d).add(b),w=!0;function x(a,f,g,h){g===undefined?g=f/m*q:h&&(g-=c.min),r&&(g=Math.round(g/r)*r);if(f===undefined||r)f=g*m/q;if(isNaN(g))return d;f=Math.max(0,Math.min(f,m)),g=f/m*q;if(h||!j)g+=c.min;j&&(h?f=m-f:g=c.max-g),g=e(g,s);var i=a.type=="click";if(w&&k!==undefined&&!i){a.type="onSlide",v.trigger(a,[g,f]);if(a.isDefaultPrevented())return d}var l=i?c.speed:0,t=i?function(){a.type="change",v.trigger(a,[g])}:null;j?(o.animate({top:f},l,t),c.progress&&p.animate({height:m-f+o.width()/2},l)):(o.animate({left:f},l,t),c.progress&&p.animate({width:f+o.width()/2},l)),k=g,n=f,b.val(g);return d}a.extend(d,{getValue:function(){return k},setValue:function(b,c){y();return x(c||a.Event("api"),undefined,b,!0)},getConf:function(){return c},getProgress:function(){return p},getHandle:function(){return o},getInput:function(){return b},step:function(b,e){e=e||a.Event();var f=c.step=="any"?1:c.step;d.setValue(k+f*(b||1),e)},stepUp:function(a){return d.step(a||1)},stepDown:function(a){return d.step(-a||-1)}}),a.each("onSlide,change".split(","),function(b,e){a.isFunction(c[e])&&a(d).bind(e,c[e]),d[e]=function(b){b&&a(d).bind(e,b);return d}}),o.drag({drag:!1}).bind("dragStart",function(){y(),w=g(a(d))||g(b)}).bind("drag",function(a,c,d){if(b.is(":disabled"))return!1;x(a,j?c:d)}).bind("dragEnd",function(a){a.isDefaultPrevented()||(a.type="change",v.trigger(a,[k]))}).click(function(a){return a.preventDefault()}),i.click(function(a){if(b.is(":disabled")||a.target==o[0])return a.preventDefault();y();var c=o.width()/2;x(a,j?m-l-c+a.pageY:a.pageX-l-c)}),c.keyboard&&b.keydown(function(c){if(!b.attr("readonly")){var e=c.keyCode,f=a([75,76,38,33,39]).index(e)!=-1,g=a([74,72,40,34,37]).index(e)!=-1;if((f||g)&&!(c.shiftKey||c.altKey||c.ctrlKey)){f?d.step(e==33?10:1,c):g&&d.step(e==34?-10:-1,c);return c.preventDefault()}}}),b.blur(function(b){var c=a(this).val();c!==k&&d.setValue(c,b)}),a.extend(b[0],{stepUp:d.stepUp,stepDown:d.stepDown});function y(){j=c.vertical||f(i,"height")>f(i,"width"),j?(m=f(i,"height")-f(o,"height"),l=i.offset().top+m):(m=f(i,"width")-f(o,"width"),l=i.offset().left)}function z(){y(),d.setValue(c.value!==undefined?c.value:c.min)}z(),m||a(window).load(z)}a.expr[":"].range=function(b){var c=b.getAttribute("type");return c&&c=="range"||a(b).filter("input").data("rangeinput")},a.fn.rangeinput=function(c){if(this.data("rangeinput"))return this;c=a.extend(!0,{},b.conf,c);var d;this.each(function(){var b=new h(a(this),a.extend(!0,{},c)),e=b.getInput().data("rangeinput",b);d=d?d.add(e):e});return d?d:this}})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.5"},a.tools.tabs={conf:{tabs:"a",current:"current",onBeforeClick:null,onClick:null,effect:"default",initialIndex:0,event:"click",rotate:!1,history:!1},addEffect:function(a,c){b[a]=c}};var b={"default":function(a,b){this.getPanes().hide().eq(a).show(),b.call()},fade:function(a,b){var c=this.getConf(),d=c.fadeOutSpeed,e=this.getPanes();d?e.fadeOut(d):e.hide(),e.eq(a).fadeIn(c.fadeInSpeed,b)},slide:function(a,b){this.getPanes().slideUp(200),this.getPanes().eq(a).slideDown(400,b)},ajax:function(a,b){this.getPanes().eq(0).load(this.getTabs().eq(a).attr("href"),b)}},c;a.tools.tabs.addEffect("horizontal",function(b,d){c||(c=this.getPanes().eq(0).width()),this.getCurrentPane().animate({width:0},function(){a(this).hide()}),this.getPanes().eq(b).animate({width:c},function(){a(this).show(),d.call()})});function d(c,d,e){var f=this,g=c.add(this),h=c.find(e.tabs),i=d.jquery?d:c.children(d),j;h.length||(h=c.children()),i.length||(i=c.parent().find(d)),i.length||(i=a(d)),a.extend(this,{click:function(c,d){var i=h.eq(c);typeof c=="string"&&c.replace("#","")&&(i=h.filter("[href*="+c.replace("#","")+"]"),c=Math.max(h.index(i),0));if(e.rotate){var k=h.length-1;if(c<0)return f.click(k,d);if(c>k)return f.click(0,d)}if(!i.length){if(j>=0)return f;c=e.initialIndex,i=h.eq(c)}if(c===j)return f;d=d||a.Event(),d.type="onBeforeClick",g.trigger(d,[c]);if(!d.isDefaultPrevented()){b[e.effect].call(f,c,function(){d.type="onClick",g.trigger(d,[c])}),j=c,h.removeClass(e.current),i.addClass(e.current);return f}},getConf:function(){return e},getTabs:function(){return h},getPanes:function(){return i},getCurrentPane:function(){return i.eq(j)},getCurrentTab:function(){return h.eq(j)},getIndex:function(){return j},next:function(){return f.click(j+1)},prev:function(){return f.click(j-1)},destroy:function(){h.unbind(e.event).removeClass(e.current),i.find("a[href^=#]").unbind("click.T");return f}}),a.each("onBeforeClick,onClick".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){b&&a(f).bind(c,b);return f}}),e.history&&a.fn.history&&(a.tools.history.init(h),e.event="history"),h.each(function(b){a(this).bind(e.event,function(a){f.click(b,a);return a.preventDefault()})}),i.find("a[href^=#]").bind("click.T",function(b){f.click(a(this).attr("href"),b)}),location.hash&&e.tabs=="a"&&c.find("[href="+location.hash+"]").length?f.click(location.hash):(e.initialIndex===0||e.initialIndex>0)&&f.click(e.initialIndex)}a.fn.tabs=function(b,c){var e=this.data("tabs");e&&(e.destroy(),this.removeData("tabs")),a.isFunction(c)&&(c={onBeforeClick:c}),c=a.extend({},a.tools.tabs.conf,c),this.each(function(){e=new d(a(this),b,c),a(this).data("tabs",e)});return c.api?e:this}})(jQuery); +(function(a){a.tools=a.tools||{version:"v1.2.5"};var b=/\[type=([a-z]+)\]/,c=/^-?[0-9]*(\.[0-9]+)?$/,d=a.tools.dateinput,e=/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,f=/^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,g;g=a.tools.validator={conf:{grouped:!1,effect:"default",errorClass:"invalid",inputEvent:null,errorInputEvent:"keyup",formEvent:"submit",lang:"en",message:"<div/>",messageAttr:"data-message",messageClass:"error",offset:[0,0],position:"center right",singleError:!1,speed:"normal"},messages:{"*":{en:"Please correct this value"}},localize:function(b,c){a.each(c,function(a,c){g.messages[a]=g.messages[a]||{},g.messages[a][b]=c})},localizeFn:function(b,c){g.messages[b]=g.messages[b]||{},a.extend(g.messages[b],c)},fn:function(c,d,e){a.isFunction(d)?e=d:(typeof d=="string"&&(d={en:d}),this.messages[c.key||c]=d);var f=b.exec(c);f&&(c=i(f[1])),j.push([c,e])},addEffect:function(a,b,c){k[a]=[b,c]}};function h(b,c,d){var e=b.offset().top,f=b.offset().left,g=d.position.split(/,?\s+/),h=g[0],i=g[1];e-=c.outerHeight()-d.offset[0],f+=b.outerWidth()+d.offset[1],/iPad/i.test(navigator.userAgent)&&(e-=a(window).scrollTop());var j=c.outerHeight()+b.outerHeight();h=="center"&&(e+=j/2),h=="bottom"&&(e+=j);var k=b.outerWidth();i=="center"&&(f-=(k+c.outerWidth())/2),i=="left"&&(f-=k);return{top:e,left:f}}function i(a){function b(){return this.getAttribute("type")==a}b.key="[type="+a+"]";return b}var j=[],k={"default":[function(b){var c=this.getConf();a.each(b,function(b,d){var e=d.input;e.addClass(c.errorClass);var f=e.data("msg.el");f||(f=a(c.message).addClass(c.messageClass).appendTo(document.body),e.data("msg.el",f)),f.css({visibility:"hidden"}).find("p").remove(),a.each(d.messages,function(b,c){a("<p/>").html(c).appendTo(f)}),f.outerWidth()==f.parent().width()&&f.add(f.find("p")).css({display:"inline"});var g=h(e,f,c);f.css({visibility:"visible",position:"absolute",top:g.top,left:g.left}).fadeIn(c.speed)})},function(b){var c=this.getConf();b.removeClass(c.errorClass).each(function(){var b=a(this).data("msg.el");b&&b.css({visibility:"hidden"})})}]};a.each("email,url,number".split(","),function(b,c){a.expr[":"][c]=function(a){return a.getAttribute("type")===c}}),a.fn.oninvalid=function(a){return this[a?"bind":"trigger"]("OI",a)},g.fn(":email","Please enter a valid email address",function(a,b){return!b||e.test(b)}),g.fn(":url","Please enter a valid URL",function(a,b){return!b||f.test(b)}),g.fn(":number","Please enter a numeric value.",function(a,b){return c.test(b)}),g.fn("[max]","Please enter a value smaller than $1",function(a,b){if(b===""||d&&a.is(":date"))return!0;var c=a.attr("max");return parseFloat(b)<=parseFloat(c)?!0:[c]}),g.fn("[min]","Please enter a value larger than $1",function(a,b){if(b===""||d&&a.is(":date"))return!0;var c=a.attr("min");return parseFloat(b)>=parseFloat(c)?!0:[c]}),g.fn("[required]","Please complete this mandatory field.",function(a,b){if(a.is(":checkbox"))return a.is(":checked");return b}),g.fn("[pattern]",function(a){var b=new RegExp("^"+a.attr("pattern")+"$");return b.test(a.val())});function l(b,c,e){var f=this,i=c.add(f);b=b.not(":button, :image, :reset, :submit");function l(b,c,d){if(e.grouped||!b.length){var f;if(d===!1||a.isArray(d)){f=g.messages[c.key||c]||g.messages["*"],f=f[e.lang]||g.messages["*"].en;var h=f.match(/\$\d/g);h&&a.isArray(d)&&a.each(h,function(a){f=f.replace(this,d[a])})}else f=d[e.lang]||d;b.push(f)}}a.extend(f,{getConf:function(){return e},getForm:function(){return c},getInputs:function(){return b},reflow:function(){b.each(function(){var b=a(this),c=b.data("msg.el");if(c){var d=h(b,c,e);c.css({top:d.top,left:d.left})}});return f},invalidate:function(c,d){if(!d){var g=[];a.each(c,function(a,c){var d=b.filter("[name='"+a+"']");d.length&&(d.trigger("OI",[c]),g.push({input:d,messages:[c]}))}),c=g,d=a.Event()}d.type="onFail",i.trigger(d,[c]),d.isDefaultPrevented()||k[e.effect][0].call(f,c,d);return f},reset:function(c){c=c||b,c.removeClass(e.errorClass).each(function(){var b=a(this).data("msg.el");b&&(b.remove(),a(this).data("msg.el",null))}).unbind(e.errorInputEvent||"");return f},destroy:function(){c.unbind(e.formEvent+".V").unbind("reset.V"),b.unbind(e.inputEvent+".V").unbind("change.V");return f.reset()},checkValidity:function(c,g){c=c||b,c=c.not(":disabled");if(!c.length)return!0;g=g||a.Event(),g.type="onBeforeValidate",i.trigger(g,[c]);if(g.isDefaultPrevented())return g.result;var h=[];c.not(":radio:not(:checked)").each(function(){var b=[],c=a(this).data("messages",b),k=d&&c.is(":date")?"onHide.v":e.errorInputEvent+".v";c.unbind(k),a.each(j,function(){var a=this,d=a[0];if(c.filter(d).length){var h=a[1].call(f,c,c.val());if(h!==!0){g.type="onBeforeFail",i.trigger(g,[c,d]);if(g.isDefaultPrevented())return!1;var j=c.attr(e.messageAttr);if(j){b=[j];return!1}l(b,d,h)}}}),b.length&&(h.push({input:c,messages:b}),c.trigger("OI",[b]),e.errorInputEvent&&c.bind(k,function(a){f.checkValidity(c,a)}));if(e.singleError&&h.length)return!1});var m=k[e.effect];if(!m)throw"Validator: cannot find effect \""+e.effect+"\"";if(h.length){f.invalidate(h,g);return!1}m[1].call(f,c,g),g.type="onSuccess",i.trigger(g,[c]),c.unbind(e.errorInputEvent+".v");return!0}}),a.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){b&&a(f).bind(c,b);return f}}),e.formEvent&&c.bind(e.formEvent+".V",function(a){if(!f.checkValidity(null,a))return a.preventDefault()}),c.bind("reset.V",function(){f.reset()}),b[0]&&b[0].validity&&b.each(function(){this.oninvalid=function(){return!1}}),c[0]&&(c[0].checkValidity=f.checkValidity),e.inputEvent&&b.bind(e.inputEvent+".V",function(b){f.checkValidity(a(this),b)}),b.filter(":checkbox, select").filter("[required]").bind("change.V",function(b){var c=a(this);(this.checked||c.is("select")&&a(this).val())&&k[e.effect][1].call(f,c,b)});var m=b.filter(":radio").change(function(a){f.checkValidity(m,a)});a(window).resize(function(){f.reflow()})}a.fn.validator=function(b){var c=this.data("validator");c&&(c.destroy(),this.removeData("validator")),b=a.extend(!0,{},g.conf,b);if(this.is("form"))return this.each(function(){var d=a(this);c=new l(d.find(":input"),d,b),d.data("validator",c)});c=new l(this,this.eq(0).closest("form"),b);return this.data("validator",c)}})(jQuery); From 03d549bab9f66c7da518caa3ff8d00741301888b Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 21:36:08 +0000 Subject: [PATCH 079/472] Add validation (basic client & server side) --- etemplate/inc/class.etemplate_new.inc.php | 17 +++++++++++++++- etemplate/js/et2_inputWidget.js | 15 ++++++++++++++ etemplate/js/etemplate2.js | 13 ++++++++++++ etemplate/js/test/test.css | 24 +++++++++++++++++++++++ etemplate/js/test/test_xml.html | 1 + 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index 9db069b324..bc0e0ed4dd 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -166,12 +166,27 @@ class etemplate_new self::$response = egw_json_response::get(); // todo: validate content - // $content = self::validate($content); + $content = self::validate($content); // merge with preserve and call our callback return ExecMethod(self::$request->method, self::complete_array_merge(self::$request->preserv, $content)); } + /** + * Validate the content + * + * ** Test stub! ** First field always fails. + * @todo Fix this for proper server side validation + */ + static public function validate($content) { + self::$response->generic('et2_validation_error', array( + // Validation errors are field_name: message + key($content)=> "First field fails serverside. '".current($content)."'") + ); + + return $content; + } + /** * Path of template relative to EGW_SERVER_ROOT * diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 1b7a31a747..49be7f5866 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -59,6 +59,19 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { this._oldValue = ""; }, + attachToDOM: function() { + this._super.apply(this,arguments); + + $j(this.getInputNode()).attr("novalidate","novalidate"); // Stop browser from getting involved + $j(this.getInputNode()).validator(); + }, + detatchFromDOM: function() { + if(this.getInputNode()) { + $j(this.getInputNode()).data("validator").destroy(); + } + this._super.apply(this,arguments); + }, + set_value: function(_value) { this._oldValue = _value; @@ -80,10 +93,12 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { if (_value != "") { node.setAttribute("id", _value); + node.setAttribute("name", _value); } else { node.removeAttribute("id"); + node.removeAttribute("name"); } } }, diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 4259fd6f06..515b57e23e 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -63,6 +63,7 @@ etemplate2.prototype.clear = function() { if (this.widgetContainer != null) { + $j(':input',this.DOMContainer).validator().data("validator").destroy(); this.widgetContainer.destroy(); this.widgetContainer = null; } @@ -149,6 +150,15 @@ etemplate2.prototype.load = function(_url, _data) etemplate2.prototype.submit = function() { + // Validator + var valid = true; + var inputs = $j(':input',this.DOMContainer).each(function() { + if(typeof $j(this).data("validator") == "undefined") return true; + valid = valid && $j(this).data("validator").checkValidity(); + return true; + }); + if(!valid) return false; + // Get the form values var values = this.widgetContainer.getValues(); @@ -250,6 +260,9 @@ function etemplate2_handle_response(_type, _response) } throw("Error while parsing et2_load response"); + } else if (_type == "et2_validation_error") { + // Display validation errors + $j(':input',this.DOMContainer).data("validator").invalidate(_response.data); } return false; diff --git a/etemplate/js/test/test.css b/etemplate/js/test/test.css index 714b29dd7f..7960d0359b 100644 --- a/etemplate/js/test/test.css +++ b/etemplate/js/test/test.css @@ -214,3 +214,27 @@ button.et2_button:focus { } +/** +* Validation +*/ +input[required] { + background-color: #ffffd0; +} +input.invalid { + border-style: dotted; + border-color: red; +} +.error { + -moz-border-radius: 0 4px 4px 0; + -moz-box-shadow: 0 0 6px #DDDDDD; + background-color: #FFFE36; + border: 1px solid #E1E16D; + color: #000000; + display: none; + font-size: 11px; + height: 15px; + padding: 4px 10px; +} +.error p { + margin: 0; +} diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 5e38fd895e..4b06532ce8 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -29,6 +29,7 @@ <script src="../et2_tabs.js"></script> <script src="../lib/tooltip.js"></script> <script src="../../../phpgwapi/js/jsapi/jsapi.js"></script> + <script src="../../../phpgwapi/js/jquery/jquery.tools.min.js"></script> <script src="et2_test_timesheet_edit.json"></script> From e76cf6eab24e375b4fde4d0ffab95f332e438347 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 22:56:49 +0000 Subject: [PATCH 080/472] - Add labels to input widgets - Add row & col properties to textarea --- etemplate/js/et2_checkbox.js | 2 +- etemplate/js/et2_inputWidget.js | 16 +++++++ etemplate/js/et2_textbox.js | 44 +++++++++++++++++++- etemplate/js/test/et2_test_basic_widgets.xet | 9 ++-- etemplate/js/test/test_xml.html | 1 + 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/etemplate/js/et2_checkbox.js b/etemplate/js/et2_checkbox.js index 477f61a57b..7e2dae93b9 100644 --- a/etemplate/js/et2_checkbox.js +++ b/etemplate/js/et2_checkbox.js @@ -61,7 +61,7 @@ var et2_checkbox = et2_inputWidget.extend({ set_value: function(_value) { if(_value != this.value) { if(_value == this.set_value) { - this.input.attr("checked", true); + this.input.attr("checked", "checked"); } else { this.input.removeAttr("checked"); } diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index 49be7f5866..b6c75b624f 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -51,6 +51,12 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { "default": false, "type": "boolean", "description": "If required, the user must enter a value before the form can be submitted" + }, + "label": { + "name": "Label", + "default": "", + "type": "string", + "description": "The label is displayed by default in front (for radiobuttons behind) each widget (if not empty). If you want to specify a different position, use a '%s' in the label, which gets replaced by the widget itself. Eg. '%s Name' to have the label Name behind a checkbox. The label can contain variables, as descript for name. If the label starts with a '@' it is replaced by the value of the content-array at this index (with the '@'-removed and after expanding the variables)." } }, init: function() { @@ -102,6 +108,16 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { } } }, + + set_label: function(_label) { + if(_label != this.label) + { + label = et2_csvSplit(_label, 2, '%s'); + if(label[0]) this.input.before("<span class='et2_label'>"+label[0]+"</span>"); + if(label[1]) this.input.after("<span class='et2_label'>"+label[1]+"</span>"); + } + }, + set_required: function(_value) { var node = this.getInputNode(); if (node) diff --git a/etemplate/js/et2_textbox.js b/etemplate/js/et2_textbox.js index d0f303721e..b6074fa4bb 100644 --- a/etemplate/js/et2_textbox.js +++ b/etemplate/js/et2_textbox.js @@ -35,7 +35,21 @@ var et2_textbox = et2_inputWidget.extend({ "type": "integer", "default": et2_no_init, "description": "Field width" - } + }, + + // These for multi-line + "rows": { + "name": "Rows", + "type": "integer", + "default": et2_no_init, + "description": "Multiline field height - better to use CSS" + }, + "cols": { + "name": "Size", + "type": "integer", + "default": et2_no_init, + "description": "Multiline field width - better to use CSS" + }, }, init: function(_parent) { @@ -61,7 +75,6 @@ var et2_textbox = et2_inputWidget.extend({ if(this.size) { this.set_size(this.size); } - this.input.addClass("et2_textbox"); this.setDOMNode(this.input[0]); @@ -79,6 +92,33 @@ var et2_textbox = et2_inputWidget.extend({ } }, + set_rows: function(_value) { + if (_value != this.rows) + { + this.rows = _value; + if(this.rows > 1) + { + this.set_multiline(true); + this.input.attr("rows", this.rows); + } else { + this.set_multiline(false); + } + } + }, + set_cols: function(_value) { + if (_value != this.cols) + { + this.cols = _value; + if(this.cols > 1) + { + this.set_multiline(true); + this.input.attr("cols", this.cols); + } else { + this.set_multiline(false); + } + } + }, + /** * Set input widget size * @param _size Rather arbitrary size units, approximately characters diff --git a/etemplate/js/test/et2_test_basic_widgets.xet b/etemplate/js/test/et2_test_basic_widgets.xet index 499b02e8f6..d92fe71bbc 100644 --- a/etemplate/js/test/et2_test_basic_widgets.xet +++ b/etemplate/js/test/et2_test_basic_widgets.xet @@ -6,8 +6,8 @@ <textbox label="This is required text" id="text_value" required="true"/> <int label="This is an integer" id="integer_value" min="5"/> <textbox type="float" label="This is a float" id="float_value"/> - <textbox multiline="true" label="This is a text area" id="text_area_value"/> - <checkbox label="Checkbox" id="checkbox_value"/> + <textbox multiline="true" label="This is a text area" id="text_area_value" rows="3" cols="3"/> + <checkbox label="Checkbox %s here" id="checkbox_value"/> <radio label="Radio" id="radio_value"/> <buttononly label="Button" id="button_value"/> <hrule label="HR"/> @@ -22,10 +22,11 @@ <template id="test.basic_widget_test"> <description value="This is a label" id="label_value"/> <textbox label="This is a text" id="text_value"/> + <textbox label="This is required text" id="text_value" required="true"/> <int label="This is an integer" id="integer_value" min="5"/> <textbox type="float" label="This is a float" id="float_value"/> - <textbox multiline="true" label="This is a text area" id="text_area_value"/> - <checkbox label="Checkbox" id="checkbox_value"/> + <textbox multiline="true" label="This is a text area" id="text_area_value" rows="3" cols="3"/> + <checkbox label="Checkbox %s here" id="checkbox_value"/> <radio label="Radio" id="radio_value"/> <buttononly label="Button" id="button_value"/> <hrule label="HR"/> diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index 4b06532ce8..c3942367b0 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -21,6 +21,7 @@ <script src="../et2_textbox.js"></script> <script src="../et2_number.js"></script> <script src="../et2_selectbox.js"></script> + <script src="../et2_checkbox.js"></script> <script src="../et2_styles.js"></script> <script src="../et2_html.js"></script> From 9f3551cc7af8dd3424a94882cd26b6687bc258a2 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 23:06:25 +0000 Subject: [PATCH 081/472] PHP test page, works inside eGW + validation test --- .../js/test/et2_test_input_validator.json | 13 +++++ .../js/test/et2_test_input_validator.xet | 17 +++++++ etemplate/js/test/test.php | 48 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 etemplate/js/test/et2_test_input_validator.json create mode 100644 etemplate/js/test/et2_test_input_validator.xet create mode 100644 etemplate/js/test/test.php diff --git a/etemplate/js/test/et2_test_input_validator.json b/etemplate/js/test/et2_test_input_validator.json new file mode 100644 index 0000000000..a11a68a7b4 --- /dev/null +++ b/etemplate/js/test/et2_test_input_validator.json @@ -0,0 +1,13 @@ +var validation_data = { + "content": { + "textbox": "Always" + }, + "sel_options": { + "select": { + one: "One", + two: "Two", + three: "Three" + } + }, +}; + diff --git a/etemplate/js/test/et2_test_input_validator.xet b/etemplate/js/test/et2_test_input_validator.xet new file mode 100644 index 0000000000..aaf710a512 --- /dev/null +++ b/etemplate/js/test/et2_test_input_validator.xet @@ -0,0 +1,17 @@ +<overlay> + <grid> + <columns> + <column/> + </columns> + + <rows> + <row><textbox id="textbox" required="false" /></row> + <row><box><description value="Must be checked" /><checkbox id="checkbox" label="Must be checked" required="true" /></box></row> +<!-- Not working yet + <row><int id="int_min" min="5" label="Must be at least 5" /></row> + <row><listbox id="select" options="Select one" required="true" /></row> +--> + <row><button label="Check" /></row> + </rows> + </grid> +</overlay> diff --git a/etemplate/js/test/test.php b/etemplate/js/test/test.php new file mode 100644 index 0000000000..8622b86349 --- /dev/null +++ b/etemplate/js/test/test.php @@ -0,0 +1,48 @@ +<?php + /** + * Test stuff from within an eGW framework + */ + +$GLOBALS['egw_info'] = array( + 'flags' => array( + 'currentapp' => 'etemplate', + 'noheader' => True, + 'nonavbar' => True, + 'app_header' => 'eT2 Test' + ) +); +include('../../../header.inc.php'); + + egw_framework::validate_file('.','etemplate2','etemplate'); + egw_framework::validate_file('jquery','jquery.tools.min','phpgwapi'); // Not needed once JS require works for files like this + egw_framework::includeCSS('/etemplate/js/test/test.css'); + + common::egw_header(); +// parse_navbar(); +?> + <script src="et2_test_timesheet_edit.json"></script> + <script src="et2_test_input_validator.json"></script> +Testing from inside framework, so JS includes work +<div class="header">Choose one of the following tests:</div> + <div id="linklist"> + <a href="#" onclick="open_xet('et2_test_timesheet_edit.xet', timesheet_data);">Timesheet edit dialog</a> + <a href="#" onclick="open_xet('et2_test_template.xet');">Template proxy test</a> + <a href="#" onclick="open_xet('et2_test_grid.xet');">Grid test</a> + <a href="#" onclick="open_xet('et2_test_tabbox.xet');">Tabs test</a> + <a href="#" onclick="open_xet('et2_test_basic_widgets.xet');">Basic widgits</a> + <a href="#" onclick="open_xet('et2_test_input_validator.xet', validation_data);">Validation</a> + </div> + <div class="header">ETemplate2 container:</div> + <div id="time"></div> + <div id="container"></div> + <script> + var et2 = new etemplate2(document.getElementById("container"), "etemplate.etemplate_new.ajax_process_content"); + + function open_xet(file, content) { + et2.load(file, content); + } + </script> +<?php +common::egw_footer(); + +?> From fb43e96aebe22242fc99afbb947fb85789112932 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Wed, 17 Aug 2011 23:26:01 +0000 Subject: [PATCH 082/472] Use getInputNode() instead of inconsistant variable for default label implementation --- etemplate/js/et2_inputWidget.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js index b6c75b624f..087c95bb51 100644 --- a/etemplate/js/et2_inputWidget.js +++ b/etemplate/js/et2_inputWidget.js @@ -112,9 +112,10 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, { set_label: function(_label) { if(_label != this.label) { - label = et2_csvSplit(_label, 2, '%s'); - if(label[0]) this.input.before("<span class='et2_label'>"+label[0]+"</span>"); - if(label[1]) this.input.after("<span class='et2_label'>"+label[1]+"</span>"); + this.label = (typeof _label == 'undefined' ? "" : _label); + var label = et2_csvSplit(_label, 2, '%s'); + if(label[0]) $j(this.getInputNode()).before("<span class='et2_label'>"+label[0]+"</span>"); + if(label[1]) $j(this.getInputNode()).after("<span class='et2_label'>"+label[1]+"</span>"); } }, From b892149294d3282aebec76c2c35dcd2e48ac5d84 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 18 Aug 2011 09:21:03 +0000 Subject: [PATCH 083/472] fixed grid in cf widget displays border, if options are set --- etemplate/inc/class.customfields_widget.inc.php | 1 + 1 file changed, 1 insertion(+) diff --git a/etemplate/inc/class.customfields_widget.inc.php b/etemplate/inc/class.customfields_widget.inc.php index 6fb047e27e..b09dcacbee 100644 --- a/etemplate/inc/class.customfields_widget.inc.php +++ b/etemplate/inc/class.customfields_widget.inc.php @@ -481,6 +481,7 @@ class customfields_widget unset($label); } } + $cell['size'] = ''; if ($type != 'customfields-list') { $cell['data'][0]['A'] = '100'; From d6509ad506ca6345a11abb66abca5dc45e0dfbca Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 18 Aug 2011 09:22:59 +0000 Subject: [PATCH 084/472] fixed grid in cf widget displays border, if options are set --- etemplate/inc/class.customfields_widget.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etemplate/inc/class.customfields_widget.inc.php b/etemplate/inc/class.customfields_widget.inc.php index b09dcacbee..d20806eac2 100644 --- a/etemplate/inc/class.customfields_widget.inc.php +++ b/etemplate/inc/class.customfields_widget.inc.php @@ -199,6 +199,7 @@ class customfields_widget $cell['type'] = 'grid'; $cell['data'] = array(array()); $cell['rows'] = $cell['cols'] = 0; + $cell['size'] = ''; $n = 1; foreach($fields as $lname => $field) @@ -481,7 +482,6 @@ class customfields_widget unset($label); } } - $cell['size'] = ''; if ($type != 'customfields-list') { $cell['data'][0]['A'] = '100'; From bda5e014d7648dde87d642cfa0039638ea5f8ba4 Mon Sep 17 00:00:00 2001 From: Klaus Leithoff <kl@stylite.de> Date: Thu, 18 Aug 2011 14:49:16 +0000 Subject: [PATCH 085/472] * tracker: mailhandling - prevent to use rsh or ssh to establish connection --- phpgwapi/inc/class.translation.inc.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/phpgwapi/inc/class.translation.inc.php b/phpgwapi/inc/class.translation.inc.php index d277dad6df..0f36d5e989 100644 --- a/phpgwapi/inc/class.translation.inc.php +++ b/phpgwapi/inc/class.translation.inc.php @@ -1027,6 +1027,11 @@ class translation if ($element->charset != 'x-unknown') { if( strtoupper($element->charset) != 'UTF-8') $element->text = preg_replace($sar,$rar,$element->text); + if(preg_match('/\?=.+=\?/', $element->text)) + { + $element->text = self::decodeMailHeader($element->text, $element->charset); + $element->charset = $displayCharset; + } $newString .= self::convert($element->text,$element->charset); } else From 341403d0ca008ee1a364ec094e9987830b0e5e4c Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Thu, 18 Aug 2011 16:09:15 +0000 Subject: [PATCH 086/472] Attempt to fix broken bullets, doubled numbers --- etemplate/templates/default/msoffice.xslt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/etemplate/templates/default/msoffice.xslt b/etemplate/templates/default/msoffice.xslt index a9b8eb1431..671d5b3c58 100644 --- a/etemplate/templates/default/msoffice.xslt +++ b/etemplate/templates/default/msoffice.xslt @@ -207,7 +207,7 @@ Breakers <w:numId w:val="1"/> <w:numFmt w:val="bullet"/> <w:lvlJc w:val="left"/> - <w:lvlText w:val="ï‚·"/> + <w:lvlText w:val="·"/> </xsl:otherwise> </xsl:choose> </w:numPr> @@ -220,7 +220,9 @@ Breakers <w:r> <xsl:choose> <xsl:when test="name(..)='ol'"> +<!-- This line gives numbers when opened in OO.o, but when the file is opened in MSWord, the numbers are doubled. <w:t><xsl:number value="position()" format="1" />. </w:t> +--> </xsl:when> <xsl:otherwise> <w:rPr> From 3c5f14e960566f7aeb30165a63f70cf19035d031 Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Thu, 18 Aug 2011 16:42:43 +0000 Subject: [PATCH 087/472] Try to keep whitespace when splitting up styles --- etemplate/templates/default/msoffice.xslt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etemplate/templates/default/msoffice.xslt b/etemplate/templates/default/msoffice.xslt index 671d5b3c58..48a8590fce 100644 --- a/etemplate/templates/default/msoffice.xslt +++ b/etemplate/templates/default/msoffice.xslt @@ -97,11 +97,11 @@ Breakers <w:rPr> <xsl:apply-templates select=".|child::*" /> </w:rPr> - <w:t><xsl:value-of select="." /></w:t> + <w:t xml:space="preserve"><xsl:value-of select="." /></w:t> </w:r> </xsl:when> <xsl:otherwise> - <w:r><w:t><xsl:copy-of select="." /></w:t></w:r> + <w:r><w:t xml:space="preserve"><xsl:copy-of select="." /></w:t></w:r> </xsl:otherwise> </xsl:choose> </xsl:for-each> From 5e54d6b12b9758085d5124ab63acb3bc6b02595c Mon Sep 17 00:00:00 2001 From: Nathan Gray <nathangray.bsc@gmail.com> Date: Thu, 18 Aug 2011 17:34:01 +0000 Subject: [PATCH 088/472] Add basic radio, readonly version of checkbox/radio --- etemplate/js/et2_checkbox.js | 63 +++++++++++++++++++++-- etemplate/js/et2_radiobox.js | 88 +++++++++++++++++++++++++++++++++ etemplate/js/etemplate2.js | 1 + etemplate/js/test/test_xml.html | 1 + 4 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 etemplate/js/et2_radiobox.js diff --git a/etemplate/js/et2_checkbox.js b/etemplate/js/et2_checkbox.js index 7e2dae93b9..50c719ad0f 100644 --- a/etemplate/js/et2_checkbox.js +++ b/etemplate/js/et2_checkbox.js @@ -15,6 +15,7 @@ /*egw:uses jquery.jquery; et2_inputWidget; + et2_valueWidget; */ /** @@ -23,17 +24,29 @@ var et2_checkbox = et2_inputWidget.extend({ attributes: { - "set_value": { + "selected_value": { "name": "Set value", "type": "string", "default": "true", "description": "Value when checked" }, - "unset_value": { + "unselected_value": { "name": "Unset value", "type": "string", "default": "false", "description": "Value when not checked" + }, + "ro_true": { + "name": "Read only selected", + "type": "string", + "default": "x", + "description": "What should be displayed when readonly and selected" + }, + "ro_false": { + "name": "Read only unselected", + "type": "string", + "default": "", + "description": "What should be displayed when readonly and not selected" } }, @@ -60,7 +73,7 @@ var et2_checkbox = et2_inputWidget.extend({ */ set_value: function(_value) { if(_value != this.value) { - if(_value == this.set_value) { + if(_value == this.selected_value) { this.input.attr("checked", "checked"); } else { this.input.removeAttr("checked"); @@ -73,11 +86,51 @@ var et2_checkbox = et2_inputWidget.extend({ */ getValue: function() { if(this.input.attr("checked")) { - return this.set_value; + return this.selected_value; } else { - return this.unset_value; + return this.unselected_value; } } }); et2_register_widget(et2_checkbox, ["checkbox"]); + +/** + * et2_checkbox_ro is the dummy readonly implementation of the checkbox and radio. + */ +var et2_checkbox_ro = et2_checkbox.extend({ + + /** + * Ignore unset value + */ + attributes: { + "unselected_value": { + "ignore": true + } + }, + + init: function(_parent) { + }, + + init: function() { + this._super.apply(this, arguments); + + this.value = ""; + this.span = $j(document.createElement("span")) + .addClass("et2_checkbox_ro"); + + this.setDOMNode(this.span[0]); + }, + + set_value: function(_value) { + if(_value == this.selected_value) { + this.span.text(this.ro_true); + this.value = _value; + } else { + this.span.text(this.ro_false); + } + } + +}); + +et2_register_widget(et2_checkbox_ro, ["checkbox_ro", "radio_ro"]); diff --git a/etemplate/js/et2_radiobox.js b/etemplate/js/et2_radiobox.js new file mode 100644 index 0000000000..5c30187eff --- /dev/null +++ b/etemplate/js/et2_radiobox.js @@ -0,0 +1,88 @@ +/** + * eGroupWare eTemplate2 - JS Radiobox object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Nathan Gray + * @copyright Nathan Gray 2011 + * @version $Id$ + */ + +"use strict"; + +/*egw:uses + jquery.jquery; + et2_inputWidget; +*/ + +/** + * Class which implements the "radiobox" XET-Tag + */ +var et2_radiobox = et2_inputWidget.extend({ + + attributes: { + "set_value": { + "name": "Set value", + "type": "string", + "default": "true", + "description": "Value when selected" + }, + "ro_true": { + "name": "Read only selected", + "type": "string", + "default": "x", + "description": "What should be displayed when readonly and selected" + }, + "ro_false": { + "name": "Read only unselected", + "type": "string", + "default": "", + "description": "What should be displayed when readonly and not selected" + } + }, + + init: function(_parent) { + this._super.apply(this, arguments); + + this.input = null; + this.id = ""; + + this.createInputWidget(); + + }, + + createInputWidget: function() { + this.input = $j(document.createElement("input")).attr("type", "radio"); + + this.input.addClass("et2_radiobox"); + + this.setDOMNode(this.input[0]); + }, + + /** + * Override default to match against set/unset value + */ + set_value: function(_value) { + if(_value != this.value) { + if(_value == this.set_value) { + this.input.attr("checked", "checked"); + } else { + this.input.removeAttr("checked"); + } + } + }, + + /** + * Override default to return unchecked value + */ + getValue: function() { + if(this.input.attr("checked")) { + return this.set_value; + } + } +}); + +et2_register_widget(et2_radiobox, ["radio"]); + diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 515b57e23e..c30b5c7c77 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -22,6 +22,7 @@ et2_number; et2_selectbox; et2_checkbox; + et2_radiobox; et2_styles; et2_html; et2_tabs; diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html index c3942367b0..b7fedc28b7 100644 --- a/etemplate/js/test/test_xml.html +++ b/etemplate/js/test/test_xml.html @@ -22,6 +22,7 @@ <script src="../et2_number.js"></script> <script src="../et2_selectbox.js"></script> <script src="../et2_checkbox.js"></script> + <script src="../et2_radiobox.js"></script> <script src="../et2_styles.js"></script> <script src="../et2_html.js"></script> From d095250d850b0eb214745771e38df37ce1155de3 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 18 Aug 2011 18:08:40 +0000 Subject: [PATCH 089/472] read and parse widgets on serverside --- .../class.etemplate_template_widget.inc.php | 112 ++++++++++ etemplate/inc/class.etemplate_widget.inc.php | 196 ++++++++++++++++++ 2 files changed, 308 insertions(+) create mode 100644 etemplate/inc/class.etemplate_template_widget.inc.php create mode 100644 etemplate/inc/class.etemplate_widget.inc.php diff --git a/etemplate/inc/class.etemplate_template_widget.inc.php b/etemplate/inc/class.etemplate_template_widget.inc.php new file mode 100644 index 0000000000..26e77e2ed9 --- /dev/null +++ b/etemplate/inc/class.etemplate_template_widget.inc.php @@ -0,0 +1,112 @@ +<?php +/** + * EGroupware - eTemplate serverside template widget + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Ralf Becker <RalfBecker@outdoor-training.de> + * @copyright 2002-11 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +/* testwise to have autoloading +if (!isset($GLOBALS['egw_info'])) +{ + $GLOBALS['egw_info'] = array( + 'flags' => array( + 'currentapp' => 'login', + ), + ); + include_once '../../header.inc.php'; +} +*/ +/** + * eTemplate widget baseclass + */ +class etemplate_template_widget extends etemplate_widget +{ + /** + * Cache of already read templates + * + * @var array with name => template pairs + */ + protected static $cache = array(); + + /** + * Read a templates specified by name, template(-set) and version + * + * @param string $name + * @param string $template_set='default' + * @param string $version='' + * @param string $load_via='' use given template to load $name + * @todo Reading customized templates from database + * @return etemplate_template_widget|boolean false if not found + */ + public static function read($name, $template_set='default', $version='', $load_via='') + { + $start = microtime(true); + if (isset(self::$cache[$name]) || !($path = self::relPath($name, $template_set, $version))) + { + if ((!$path || self::read($load_via, $template_set)) && isset(self::$cache[$name])) + { + error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read from cache"); + return self::$cache[$name]; + } + error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') template NOT found!"); + return false; + } + $reader = new XMLReader(); + if (!$reader->open(EGW_SERVER_ROOT.$path)) return false; + + while($reader->read()) + { + if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'template') + { + $template = new etemplate_template_widget($reader); + //echo $template->id; _debug_array($template); + + self::$cache[$template->id] = $template; + + if ($template->id == $name) + { + error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read in ".round(1000.0*(microtime(true)-$start),2)." ms"); + return $template; + } + } + } + // template not found in file, should never happen + error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') template NOT found in file '$path'!"); + return false; + } + + /** + * Get path/URL relative to EGroupware install of a template + * + * @param string $name + * @param string $template_set='default' + * @param string $version='' + * @return string|boolean path of template xml file or false if not found + */ + public static function relPath($name, $template_set='default', $version='') + { + list($app, $rest) = explode('.', $name, 2); + $path = '/'.$app.'/templates/'.$template_set.'/'.$rest.'.xet'; + + if (file_exists(EGW_SERVER_ROOT.$path)) return $path; + + if ($templateSet != 'default') + { + $path = '/'.$app.'/templates/default/'.$rest.'.xet'; + + if (file_exists(EGW_SERVER_ROOT.$path)) return $path; + } + return false; + } +} +/* +header('Content-Type: text/xml'); +$template = etemplate_template_widget::read('timesheet.edit'); +$template->toXml(); +*/ diff --git a/etemplate/inc/class.etemplate_widget.inc.php b/etemplate/inc/class.etemplate_widget.inc.php new file mode 100644 index 0000000000..b000666404 --- /dev/null +++ b/etemplate/inc/class.etemplate_widget.inc.php @@ -0,0 +1,196 @@ +<?php +/** + * EGroupware - eTemplate widget baseclass + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Ralf Becker <RalfBecker@outdoor-training.de> + * @copyright 2002-11 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +/** + * eTemplate widget baseclass + */ +class etemplate_widget +{ + /** + * Widget type + * + * @var string + */ + public $type; + + /** + * Widget id + * + * @var string + */ + public $id; + + /** + * Widget attributes + * + * @var array + */ + public $attrs = array(); + + /** + * Children + * + * @var array + */ + protected $children = array(); + + /** + * Constructor + * + * @param string|XMLReader $xml string with xml or XMLReader positioned on the element to construct + * @throws egw_exception_wrong_parameter + */ + public function __construct($xml) + { + if (is_a($xml, 'XMLReader')) + { + $reader = $xml; + } + else + { + $reader = new XMLReader(); + if (!$reader->XML($xml)) + { + throw new egw_exception_wrong_parameter("Can't parse xml:\n$xml"); + } + } + $this->type = $reader->name; + $depth = $reader->depth; + + // read all attributes + while($reader->moveToNextAttribute()) + { + if ($reader->name == 'id') + { + $this->id = $reader->value; + } + else + { + $this->attrs[$reader->name] = $reader->value; + } + } + + while($reader->read() && $reader->depth > $depth) + { + if ($reader->nodeType == XMLReader::ELEMENT && $reader->depth > $depth) + { + $this->children[] = self::factory($reader->name, $reader, $reader->getAttribute('id')); + } + } + } + + /** + * Factory method to construct all widgets + * + * @param string $type + * @param string|XMLReader $xml + * @param string $id=null + */ + public static function factory($type, $xml, $id=null) + { + static $type2class_name = array(); + + $class_name =& $type2class_name[$type]; + + if (!isset($class_name)) + { + list($basetype) = explode('-',$type); + if (!class_exists($class_name = 'etemplate_'.str_replace('-','_',$type).'_widget') && + !class_exists($class_name = 'etemplate_'.str_replace('-','_',$basetype).'_widget')) + { + // default to widget class, we can not ignore it, as the widget may contain other widgets + $class_name = 'etemplate_widget'; + } + } + // currently only overlays can contain templates, other widgets can only reference to templates via id + if ($type == 'template' && $id && ($template = etemplate_template_widget::read($id))) + { + return $template; + } + return new $class_name($xml); + } + + /** + * Iterate over children to find the one with the given id and optional type + * + * @param string $id + * @param string $type=null + * @return etemplate_widget or NULL + */ + public function getElementById($id, $type=null) + { + foreach($this->children as $child) + { + if ($child->id === $id && (is_null($type) || $child->type === $type)) + { + return $child; + } + if (($element = $child->getElementById($id, $type))) + { + return $element; + } + } + return null; + } + + /** + * Validate input of a widget + * + * @param array $content + * @param string $cname='' current namespace + * @return mixed + */ + public function validate(array $content, $cname = '') + { + + } + + /** + * Convert object to string + * + * @return string + */ + public function __toString() + { + return $this->type.'#'.$this->id; + } + + /** + * Convert widget (incl. children) to xml + * + * @param string $indent='' + * @return string + */ + public function toXml($indent='') + { + echo "$indent<$this->type"; + if ($this->id) echo ' id="'.htmlspecialchars($this->id).'"'; + foreach($this->attrs as $name => $value) + { + echo ' '.$name.'="'.htmlspecialchars($value).'"'; + } + if ($this->children) + { + echo ">\n"; + foreach($this->children as $child) + { + $child->toXml($indent."\t"); + } + echo "$indent</$this->type>\n"; + } + else + { + echo " />\n"; + } + } +} From a488b67f993a9f0bd2926fc6e69bf770a139a243 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Thu, 18 Aug 2011 21:56:37 +0000 Subject: [PATCH 090/472] serverside validation for textbox and button --- etemplate/inc/class.etemplate_new.inc.php | 141 +++-------- etemplate/inc/class.etemplate_widget.inc.php | 232 +++++++++++++++++- .../inc/class.etemplate_widget_button.inc.php | 50 ++++ ...> class.etemplate_widget_template.inc.php} | 49 ++-- .../class.etemplate_widget_textbox.inc.php | 116 +++++++++ 5 files changed, 460 insertions(+), 128 deletions(-) create mode 100644 etemplate/inc/class.etemplate_widget_button.inc.php rename etemplate/inc/{class.etemplate_template_widget.inc.php => class.etemplate_widget_template.inc.php} (64%) create mode 100644 etemplate/inc/class.etemplate_widget_textbox.inc.php diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index bc0e0ed4dd..119ae861b1 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -18,7 +18,7 @@ * * @ToDo supported customized templates stored in DB, currently we only support xet files stored in filesystem */ -class etemplate_new +class etemplate_new extends etemplate_widget_template { /** * Are we running as sitemgr module or not @@ -27,22 +27,6 @@ class etemplate_new */ public $sitemgr=false; - /** - * Request object of the currecntly created request - * - * It's a static variable as etemplates can contain further etemplates (rendered by a different object) - * - * @var etemplate_request - */ - static protected $request; - - /** - * JSON response object, if we run via a JSON request - * - * @var egw_json_response - */ - static protected $response; - /** * constructor of etemplate class, reads an eTemplate if $name is given * @@ -114,7 +98,7 @@ class etemplate_new self::$request->ignore_validation = $ignore_validation; self::$request->app_header = $GLOBALS['egw_info']['flags']['app_header']; if (self::$request->output_mode == -1) self::$request->output_mode = 0; - self::$request->template = $this->rel_path; + self::$request->template = $this->as_array(); $data = array( 'etemplate_exec_id' => self::$request->id(), @@ -134,6 +118,8 @@ class etemplate_new } else // first call { + // missing dependency, thought egw:uses jquery.jquery.tools does NOT work, maybe we should rename it to jquery-tools + egw_framework::validate_file('jquery','jquery.tools.min'); egw_framework::validate_file('.','etemplate2','etemplate'); egw_framework::includeCSS('/etemplate/js/test/test.css'); @@ -165,26 +151,22 @@ class etemplate_new self::$response = egw_json_response::get(); - // todo: validate content - $content = self::validate($content); + if (!($template = self::instance(self::$request->template['name'], self::$request->template['template_set'], + self::$request->template['version'], self::$request->template['load_via']))) + { + throw new egw_exception_wrong_parameter('Can NOT read template '.array2string(self::$request->template)); + } + $validated = array(); + $template->validate($content, $validated); + if (self::validation_errors(self::$request->ignore_validation)) + { + error_log(__METHOD__."(,".array2string($content).') validation_errors='.array2string(self::$validation_errors)); + self::$response->generic('et2_validation_error', self::$validation_errors); + exit; + } + error_log(__METHOD__."(,".array2string($content).') validated='.array2string($validated)); - // merge with preserve and call our callback - return ExecMethod(self::$request->method, self::complete_array_merge(self::$request->preserv, $content)); - } - - /** - * Validate the content - * - * ** Test stub! ** First field always fails. - * @todo Fix this for proper server side validation - */ - static public function validate($content) { - self::$response->generic('et2_validation_error', array( - // Validation errors are field_name: message - key($content)=> "First field fails serverside. '".current($content)."'") - ); - - return $content; + return ExecMethod(self::$request->method, self::complete_array_merge(self::$request->preserv, $validated)); } /** @@ -194,11 +176,16 @@ class etemplate_new */ public $rel_path; + public $name; + public $template_set; + public $version; + public $laod_via; + /** * Reads an eTemplate from filesystem or DB (not yet supported) * * @param string $name name of the eTemplate or array with the values for all keys - * @param string $template template-set, '' loads the prefered template of the user, 'default' loads the default one '' in the db + * @param string $template_set template-set, '' loads the prefered template of the user, 'default' loads the default one '' in the db * @param string $lang language, '' loads the pref. lang of the user, 'default' loads the default one '' in the db * @param int $group id of the (primary) group of the user or 0 for none, not used at the moment !!! * @param string $version version of the eTemplate @@ -207,79 +194,27 @@ class etemplate_new * * @ToDo supported customized templates stored in DB */ - public function read($name,$template='default',$lang='default',$group=0,$version='',$load_via='') + public function read($name,$template_set='default',$lang='default',$group=0,$version='',$load_via='') { - list($app, $tpl_name) = explode('.', $name, 2); + $this->rel_path = self::relPath($this->name=$name, $this->template_set=$template_set, + $this->version=$version, $this->laod_via = $load_via); - $this->rel_path = '/'.$app.'/templates/'.$template.'/'.$tpl_name.'.xet'; - if (!file_exists(EGW_SERVER_ROOT.$this->rel_path) && $template !== 'default') - { - $this->rel_path = '/'.$app.'/templates/default/'.$tpl_name.'.xet'; - } - if (!file_exists(EGW_SERVER_ROOT.$this->rel_path)) - { - $this->rel_path = null; - error_log(__METHOD__."('$name',...,'$load_via') returning FALSE"); - return false; - } - //error_log(__METHOD__."('$name',...,'$load_via') this->rel_path=$this->rel_path returning TRUE"); - return true; + return (boolean)$this->real_path; } /** - * Validation errors from process_show and the extensions, should be set via etemplate::set_validation_error + * Get template data as array * - * @public array form_name => message pairs + * @return array */ - static protected $validation_errors = array(); - - /** - * Sets a validation error, to be displayed in the next exec - * - * @param string $name (complete) name of the widget causing the error - * @param string $error error-message already translated - * @param string $cname=null set it to '', if the name is already a form-name, defaults to self::$name_vars - */ - public static function set_validation_error($name,$error,$cname=null) + public function as_array() { - if (is_null($cname)) $cname = self::$name_vars; - //echo "<p>etemplate::set_validation_error('$name','$error','$cname');</p>\n"; - if ($cname) $name = self::form_name($cname,$name); - - if (self::$validation_errors[$name]) - { - self::$validation_errors[$name] .= ', '; - } - self::$validation_errors[$name] .= $error; - } - - /** - * Check if we have not ignored validation errors - * - * @param string $ignore_validation='' if not empty regular expression for validation-errors to ignore - * @param string $cname=null name-prefix, which need to be ignored, default self::$name_vars - * @return boolean true if there are not ignored validation errors, false otherwise - */ - public static function validation_errors($ignore_validation='',$cname='') - { -// if (is_null($cname)) $cname = self::$name_vars; - //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') validation_error="; _debug_array(self::$validation_errors); - if (!$ignore_validation) return count(self::$validation_errors) > 0; - - foreach(self::$validation_errors as $name => $error) - { - if ($cname) $name = preg_replace('/^'.$cname.'\[([^\]]+)\](.*)$/','\\1\\2',$name); - - // treat $ignoare_validation only as regular expression, if it starts with a slash - if ($ignore_validation[0] == '/' && !preg_match($ignore_validation,$name) || - $ignore_validation[0] != '/' && $ignore_validation != $name) - { - //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') name='$name' ($error) not ignored!!!</p>\n"; - return true; - } - //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') name='$name' ($error) ignored</p>\n"; - } - return false; + return array( + 'name' => $this->name, + 'template_set' => $this->template_set, + 'version' => $this->version, + 'load_via' => $this->load_via, + ); } /** diff --git a/etemplate/inc/class.etemplate_widget.inc.php b/etemplate/inc/class.etemplate_widget.inc.php index b000666404..f0ee22bfaf 100644 --- a/etemplate/inc/class.etemplate_widget.inc.php +++ b/etemplate/inc/class.etemplate_widget.inc.php @@ -11,8 +11,13 @@ * @version $Id$ */ +// include only widgets which can't be autoloaded (or contain sub-widgets which cant) +require_once EGW_INCLUDE_ROOT.'/etemplate/inc/class.etemplate_widget_textbox.inc.php'; + /** * eTemplate widget baseclass + * + * @todo text content, eg. the styles of a template are not parsed, thought they are not used here either */ class etemplate_widget { @@ -44,6 +49,22 @@ class etemplate_widget */ protected $children = array(); + /** + * Request object of the currently created request + * + * It's a static variable as etemplates can contain further etemplates (rendered by a different object) + * + * @var etemplate_request + */ + static protected $request; + + /** + * JSON response object, if we run via a JSON request + * + * @var egw_json_response + */ + static protected $response; + /** * Constructor * @@ -89,6 +110,30 @@ class etemplate_widget } } + /** + * Registry of classes implementing widgets + * + * @var array + */ + static protected $widget_registry = array(); + + /** + * Register a given class for certain widgets + * + * Registration is only needed if widget (base-)name is not autoloadable, + * eg. class etemplate_widget_template does NOT need to be registered. + * + * @param string $class + * @param string|array $widgets + */ + public static function registerWidget($class, $widgets) + { + foreach((array)$widgets as $widget) + { + self::$widget_registry[$widget] = $class; + } + } + /** * Factory method to construct all widgets * @@ -98,22 +143,20 @@ class etemplate_widget */ public static function factory($type, $xml, $id=null) { - static $type2class_name = array(); - - $class_name =& $type2class_name[$type]; + $class_name =& self::$widget_registry[$type]; if (!isset($class_name)) { list($basetype) = explode('-',$type); - if (!class_exists($class_name = 'etemplate_'.str_replace('-','_',$type).'_widget') && - !class_exists($class_name = 'etemplate_'.str_replace('-','_',$basetype).'_widget')) + if (!class_exists($class_name = 'etemplate_widget_'.str_replace('-','_',$type)) && + !class_exists($class_name = 'etemplate_widget_'.str_replace('-','_',$basetype))) { // default to widget class, we can not ignore it, as the widget may contain other widgets $class_name = 'etemplate_widget'; } } // currently only overlays can contain templates, other widgets can only reference to templates via id - if ($type == 'template' && $id && ($template = etemplate_template_widget::read($id))) + if ($type == 'template' && $id && ($template = etemplate_widget_template::instance($id))) { return $template; } @@ -144,15 +187,23 @@ class etemplate_widget } /** - * Validate input of a widget + * Validate input + * + * Default implementation only calls validate on it's children * * @param array $content + * @param array &$validated=array() validated content * @param string $cname='' current namespace - * @return mixed + * @return boolean true if no validation error, false otherwise */ - public function validate(array $content, $cname = '') + public function validate(array $content, &$validated=array(), $cname = '') { - + $ok = true; + foreach($this->children as $child) + { + $ok = $child->validate($content, $validated, $cname) && $ok; + } + return $ok; } /** @@ -179,6 +230,8 @@ class etemplate_widget { echo ' '.$name.'="'.htmlspecialchars($value).'"'; } + echo ' php-class="'.get_class($this).'"'; + if ($this->children) { echo ">\n"; @@ -193,4 +246,163 @@ class etemplate_widget echo " />\n"; } } + + /** + * build the name of a form-element from a basename and name + * + * name and basename can contain sub-indices in square bracets, eg. basename="base[basesub1][basesub2]" + * and name = "name[sub]" gives "base[basesub1][basesub2][name][sub]" + * + * @param string $cname basename + * @param string $name name + * @return string complete form-name + */ + static function form_name($cname,$name) + { + $name_parts = explode('[',str_replace(']','',$name)); + if (!empty($cname)) + { + array_unshift($name_parts,$cname); + } + $form_name = array_shift($name_parts); + if (count($name_parts)) + { + $form_name .= '['.implode('][',$name_parts).']'; + } + return $form_name; + } + + /** + * return a reference to $arr[$idx] + * + * This works for non-trival indexes like 'a[b][c]' too: it returns &$arr[a][b][c] + * $sub = get_array($arr,'a[b]'); $sub = 'c'; is equivalent to $arr['a']['b'] = 'c'; + * + * @param array $arr the array to search, referenz as a referenz gets returned + * @param string $idx the index, may contain sub-indices like a[b], see example below + * @param boolean $reference_into default False, if True none-existing sub-arrays/-indices get created to be returned as referenz, else False is returned + * @param bool $skip_empty returns false if $idx is not present in $arr + * @return mixed reference to $arr[$idx] or false if $idx is not set and not $reference_into + */ + static function &get_array(&$arr,$idx,$reference_into=False,$skip_empty=False) + { + if (!is_array($arr)) + { + throw new egw_exception_assertion_failed(__METHOD__."(\$arr,'$idx',$reference_into,$skip_empty) \$arr is no array!"); + } + if (is_object($idx)) return false; // given an error in php5.2 + + $idxs = explode('[',str_replace(']','',$idx)); + $pos = &$arr; + foreach($idxs as $idx) + { + if (!is_array($pos) && !$reference_into) + { + return False; + } + if($skip_empty && (!is_array($pos) || !isset($pos[$idx]))) return false; + $pos = &$pos[$idx]; + } + return $pos; + } + + /** + * Checks if a widget is readonly: + * - readonly attribute set + * - $readonlys[__ALL__] set and $readonlys[$form_name] !== false + * - $readonlys[$form_name] evaluates to true + * + * @return boolean + */ + public function is_readonly($cname='') + { + $form_name = self::form_name($cname, $this->id); + + $readonly = $this->attrs['readonly'] || self::$request->readonlys[$form_name] || + isset(self::$request->readonlys['__ALL__']) && self::$request->readonlys[$form_name] !== false; + + error_log(__METHOD__."('$cname') this->id='$this->id' --> form_name='$form_name' returning ".array2string($readonly)); + + return $readonly; + } + /** + * Validation errors from process_show and the extensions, should be set via etemplate::set_validation_error + * + * @public array form_name => message pairs + */ + static protected $validation_errors = array(); + + /** + * Sets a validation error, to be displayed in the next exec + * + * @param string $name (complete) name of the widget causing the error + * @param string $error error-message already translated + * @param string $cname=null set it to '', if the name is already a form-name, defaults to self::$name_vars + */ + public static function set_validation_error($name,$error,$cname=null) + { + if (is_null($cname)) $cname = self::$name_vars; + //echo "<p>etemplate::set_validation_error('$name','$error','$cname');</p>\n"; + if ($cname) $name = self::form_name($cname,$name); + + if (self::$validation_errors[$name]) + { + self::$validation_errors[$name] .= ', '; + } + self::$validation_errors[$name] .= $error; + } + + /** + * Check if we have not ignored validation errors + * + * @param string $ignore_validation='' if not empty regular expression for validation-errors to ignore + * @param string $cname=null name-prefix, which need to be ignored, default self::$name_vars + * @return boolean true if there are not ignored validation errors, false otherwise + */ + public static function validation_errors($ignore_validation='',$cname='') + { +// if (is_null($cname)) $cname = self::$name_vars; + //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') validation_error="; _debug_array(self::$validation_errors); + if (!$ignore_validation) return count(self::$validation_errors) > 0; + + foreach(self::$validation_errors as $name => $error) + { + if ($cname) $name = preg_replace('/^'.$cname.'\[([^\]]+)\](.*)$/','\\1\\2',$name); + + // treat $ignoare_validation only as regular expression, if it starts with a slash + if ($ignore_validation[0] == '/' && !preg_match($ignore_validation,$name) || + $ignore_validation[0] != '/' && $ignore_validation != $name) + { + //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') name='$name' ($error) not ignored!!!</p>\n"; + return true; + } + //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') name='$name' ($error) ignored</p>\n"; + } + return false; + } } + +/** + * Named widget having an own namespace: grid, *box + */ +class etemplate_widget_named extends etemplate_widget +{ + /** + * Validate input + * + * Reimplemented because grids can have an own namespace + * + * @param array $content + * @param array &$validated=array() validated content + * @param string $cname='' current namespace + * @return boolean true if no validation error, false otherwise + */ + public function validate(array $content, &$validated=array(), $cname = '') + { + if ($this->id) $cname = self::form_name($cname, $this->id); + + return parent::validate($content, $validated, $cname); + } +} +// register class for layout widgets, which can have an own namespace +etemplate_widget::registerWidget('etemplate_widget_named', array('grid', 'box', 'hbox', 'vbox', 'groupbox')); diff --git a/etemplate/inc/class.etemplate_widget_button.inc.php b/etemplate/inc/class.etemplate_widget_button.inc.php new file mode 100644 index 0000000000..186981ecfc --- /dev/null +++ b/etemplate/inc/class.etemplate_widget_button.inc.php @@ -0,0 +1,50 @@ +<?php +/** + * EGroupware - eTemplate serverside button widget + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Ralf Becker <RalfBecker@outdoor-training.de> + * @copyright 2002-11 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +/** + * eTemplate button widget + */ +class etemplate_widget_button extends etemplate_widget +{ + /** + * Validate input + * + * Readonly buttons can NOT be pressed + * + * @param array $content + * @param array &$validated=array() validated content + * @param string $cname='' current namespace + * @return boolean true if no validation error, false otherwise + */ + public function validate(array $content, &$validated=array(), $cname = '') + { + $form_name = self::form_name($cname, $this->id); + + if (self::get_array($content, $form_name) && !$this->is_readonly($cname)) + { + $valid =& self::get_array($validated, $form_name, true); + $valid = 'pressed'; // that's what it was in old etemplate + + // recored pressed button globally, was in the template object before, not sure self::$request is the right place ... + if ($this->type == 'cancel' || $form_name == 'cancel' || substr($form_name,-10) == '[cancel]') + { + self::$request->canceled = true; + } + else + { + self::$request->button_pressed = true; + } + } + return parent::validate($content, $validated, $cname); + } +} diff --git a/etemplate/inc/class.etemplate_template_widget.inc.php b/etemplate/inc/class.etemplate_widget_template.inc.php similarity index 64% rename from etemplate/inc/class.etemplate_template_widget.inc.php rename to etemplate/inc/class.etemplate_widget_template.inc.php index 26e77e2ed9..5fe6d7ce67 100644 --- a/etemplate/inc/class.etemplate_template_widget.inc.php +++ b/etemplate/inc/class.etemplate_widget_template.inc.php @@ -11,21 +11,21 @@ * @version $Id$ */ -/* testwise to have autoloading +// allow to call direct for tests (see end of class) if (!isset($GLOBALS['egw_info'])) { $GLOBALS['egw_info'] = array( 'flags' => array( 'currentapp' => 'login', - ), + ) ); include_once '../../header.inc.php'; } -*/ + /** * eTemplate widget baseclass */ -class etemplate_template_widget extends etemplate_widget +class etemplate_widget_template extends etemplate_widget { /** * Cache of already read templates @@ -35,23 +35,23 @@ class etemplate_template_widget extends etemplate_widget protected static $cache = array(); /** - * Read a templates specified by name, template(-set) and version + * Get instance of template specified by name, template(-set) and version * * @param string $name * @param string $template_set='default' * @param string $version='' * @param string $load_via='' use given template to load $name * @todo Reading customized templates from database - * @return etemplate_template_widget|boolean false if not found + * @return etemplate_widget_template|boolean false if not found */ - public static function read($name, $template_set='default', $version='', $load_via='') + public static function instance($name, $template_set='default', $version='', $load_via='') { $start = microtime(true); if (isset(self::$cache[$name]) || !($path = self::relPath($name, $template_set, $version))) { if ((!$path || self::read($load_via, $template_set)) && isset(self::$cache[$name])) { - error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read from cache"); + //error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read from cache"); return self::$cache[$name]; } error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') template NOT found!"); @@ -64,14 +64,14 @@ class etemplate_template_widget extends etemplate_widget { if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'template') { - $template = new etemplate_template_widget($reader); + $template = new etemplate_widget_template($reader); //echo $template->id; _debug_array($template); self::$cache[$template->id] = $template; if ($template->id == $name) { - error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read in ".round(1000.0*(microtime(true)-$start),2)." ms"); + //error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read in ".round(1000.0*(microtime(true)-$start),2)." ms"); return $template; } } @@ -104,9 +104,28 @@ class etemplate_template_widget extends etemplate_widget } return false; } + + /** + * Validate input + * + * Reimplemented because templates can have an own namespace specified in options, NOT id! + * + * @param array $content + * @param array &$validated=array() validated content + * @param string $cname='' current namespace + * @return boolean true if no validation error, false otherwise + */ + public function validate(array $content, &$validated=array(), $cname = '') + { + if ($this->attrs['options']) $cname = self::form_name($cname, $this->attrs['options']); + + return parent::validate($content, $validated, $cname); + } } -/* -header('Content-Type: text/xml'); -$template = etemplate_template_widget::read('timesheet.edit'); -$template->toXml(); -*/ + +if ($GLOBALS['egw_info']['flags']['currentapp'] == 'login') +{ + $template = etemplate_widget_template::instance('timesheet.edit'); + header('Content-Type: text/xml'); + echo $template->toXml(); +} \ No newline at end of file diff --git a/etemplate/inc/class.etemplate_widget_textbox.inc.php b/etemplate/inc/class.etemplate_widget_textbox.inc.php new file mode 100644 index 0000000000..dc60f1798a --- /dev/null +++ b/etemplate/inc/class.etemplate_widget_textbox.inc.php @@ -0,0 +1,116 @@ +<?php +/** + * EGroupware - eTemplate serverside textbox widget + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link http://www.egroupware.org + * @author Ralf Becker <RalfBecker@outdoor-training.de> + * @copyright 2002-11 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +/** + * eTemplate textbox widget with following sub-types: + * - textbox optional multiline="true" and rows="123" + * - int + * - float + * - hidden + * - colorpicker + * sub-types are either passed to constructor or set via 'type' attribute! + */ +class etemplate_widget_textbox extends etemplate_widget +{ + /** + * Validate input + * + * Following attributes get checked: + * - needed: value must NOT be empty + * - min, max: int and float widget only + * - maxlength: maximum length of string (longer strings get truncated to allowed size) + * - preg: perl regular expression incl. delimiters (set by default for int, float and colorpicker) + * - int and float get casted to their type + * + * @param array $content + * @param array &$validated=array() validated content + * @param string $cname='' current namespace + * @return boolean true if no validation error, false otherwise + */ + public function validate(array $content, &$validated=array(), $cname = '') + { + $ok = true; + $type = isset($this->attrs['type']) ? $this->attrs['type'] : $this->type; + if (!$this->is_readonly($cname)) + { + if (!isset($this->attrs['preg'])) + { + switch($type) + { + case 'int': + $this->attrs['preg'] = '/^-?[0-9]*$/'; + break; + case 'float': + $this->attrs['preg'] = '/^-?[0-9]*[,.]?[0-9]*$/'; + break; + case 'colorpicker': + $this->attrs['preg'] = '/^(#[0-9a-f]{6}|)$/i'; + break; + } + } + $form_name = self::form_name($cname, $this->id); + + $value = self::get_array($content, $form_name); + $valid =& self::get_array($validated, $form_name, true); + + if ((string)$value === '' && $this->attrs['needed']) + { + self::set_validation_error($form_name,lang('Field must not be empty !!!'),''); + $ok = false; + } + if ((int) $this->attrs['maxlength'] > 0 && strlen($value) > (int) $this->attrs['maxlength']) + { + $value = substr($value,0,(int) $this->attrs['maxlength']); + } + if ($this->attrs['preg'] && !preg_match($this->attrs['preg'],$value)) + { + switch($type) + { + case 'int': + self::set_validation_error($form_name,lang("'%1' is not a valid integer !!!",$value),''); + break; + case 'float': + self::set_validation_error($form_name,lang("'%1' is not a valid floatingpoint number !!!",$value),''); + break; + default: + self::set_validation_error($form_name,lang("'%1' has an invalid format !!!",$value)/*." !preg_match('$this->attrs[preg]', '$value')"*/,''); + break; + } + $ok = false; + } + elseif ($type == 'int' || $type == 'float') // cast int and float and check range + { + if ((string)$value !== '' || $this->attrs['needed']) // empty values are Ok if needed is not set + { + $value = $type == 'int' ? (int) $value : (float) str_replace(',','.',$value); // allow for german (and maybe other) format + + if (!empty($this->attrs['min']) && $value < $this->attrs['min']) + { + self::set_validation_error($form_name,lang("Value has to be at least '%1' !!!",$this->attrs['min']),''); + $value = $type == 'int' ? (int) $this->attrs['min'] : (float) $this->attrs['min']; + $ok = false; + } + if (!empty($this->attrs['max']) && $value > $this->attrs['max']) + { + self::set_validation_error($form_name,lang("Value has to be at maximum '%1' !!!",$this->attrs['max']),''); + $value = $type == 'int' ? (int) $this->attrs['max'] : (float) $this->attrs['max']; + $ok = false; + } + } + } + $valid = $value; + } + return parent::validate($content, $validated, $cname) && $ok; + } +} +etemplate_widget::registerWidget('etemplate_widget_textbox', array('textbox','int','float','passwd','hidden','colorpicker')); \ No newline at end of file From b57b6339445e36509d4a5abea9e3c9760bbdb34c Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Fri, 19 Aug 2011 06:21:46 +0000 Subject: [PATCH 091/472] ability to unset validation messages --- etemplate/inc/class.etemplate.inc.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/etemplate/inc/class.etemplate.inc.php b/etemplate/inc/class.etemplate.inc.php index 9b06cfdc3d..15296ad9bc 100644 --- a/etemplate/inc/class.etemplate.inc.php +++ b/etemplate/inc/class.etemplate.inc.php @@ -2384,7 +2384,7 @@ class etemplate extends boetemplate * Sets a validation error, to be displayed in the next exec * * @param string $name (complete) name of the widget causing the error - * @param string $error error-message already translated + * @param string|boolean $error error-message already translated or false to reset all existing error for given name * @param string $cname=null set it to '', if the name is already a form-name, defaults to self::$name_vars */ static function set_validation_error($name,$error,$cname=null) @@ -2393,11 +2393,18 @@ class etemplate extends boetemplate //echo "<p>etemplate::set_validation_error('$name','$error','$cname');</p>\n"; if ($cname) $name = self::form_name($cname,$name); - if (self::$validation_errors[$name]) + if ($error === false) { - self::$validation_errors[$name] .= ', '; + unset(self::$validation_errors[$name]); + } + else + { + if (self::$validation_errors[$name]) + { + self::$validation_errors[$name] .= ', '; + } + self::$validation_errors[$name] .= $error; } - self::$validation_errors[$name] .= $error; } /** From 107b12abcdbeae785a91e518a9779a8fa2c58639 Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Fri, 19 Aug 2011 06:30:06 +0000 Subject: [PATCH 092/472] - template references can contain attributes, in this case we have to clone the template and set them - optional template namespace is in "content" attribute - ability to unset validation messages --- etemplate/inc/class.etemplate_widget.inc.php | 94 ++++++++++++++----- .../class.etemplate_widget_template.inc.php | 4 +- 2 files changed, 71 insertions(+), 27 deletions(-) diff --git a/etemplate/inc/class.etemplate_widget.inc.php b/etemplate/inc/class.etemplate_widget.inc.php index f0ee22bfaf..6bcf903de1 100644 --- a/etemplate/inc/class.etemplate_widget.inc.php +++ b/etemplate/inc/class.etemplate_widget.inc.php @@ -18,6 +18,10 @@ require_once EGW_INCLUDE_ROOT.'/etemplate/inc/class.etemplate_widget_textbox.inc * eTemplate widget baseclass * * @todo text content, eg. the styles of a template are not parsed, thought they are not used here either + * @todo validation: disabled attribute + * - widget + * - grid row + * - grid column */ class etemplate_widget { @@ -72,6 +76,32 @@ class etemplate_widget * @throws egw_exception_wrong_parameter */ public function __construct($xml) + { + $reader = self::get_reader($xml); + $this->type = $reader->name; + $depth = $reader->depth; + + $this->id = $reader->getAttribute('id'); + + // read all attributes + $this->set_attrs($reader); + + while($reader->read() && $reader->depth > $depth) + { + if ($reader->nodeType == XMLReader::ELEMENT && $reader->depth > $depth) + { + $this->children[] = self::factory($reader->name, $reader, $reader->getAttribute('id')); + } + } + } + + /** + * Get XMLReader for given xml string + * + * @param string|XMLReader $xml string with xml or XMLReader positioned on an element + * @throws egw_exception_wrong_parameter + */ + protected static function get_reader($xml) { if (is_a($xml, 'XMLReader')) { @@ -85,29 +115,34 @@ class etemplate_widget throw new egw_exception_wrong_parameter("Can't parse xml:\n$xml"); } } - $this->type = $reader->name; - $depth = $reader->depth; + return $reader; + } - // read all attributes + /** + * Parse and set extra attributes from xml in template object + * + * Returns a cloned template object, if any attribute needs to be set. + * This is necessary as templates can be used multiple time, so we can not alter the cached template! + * + * @param string|XMLReader $xml + * @param boolean $cloned=true true: object does NOT need to be cloned, false: to set attribute, set them in cloned object + * @return etemplate_widget_template current object or clone, if any attribute was set + */ + public function set_attrs($xml, $cloned=true) + { + $reader = self::get_reader($xml); + + // read and set all attributes + $template = $this; while($reader->moveToNextAttribute()) { - if ($reader->name == 'id') + if ($reader->name != 'id' && $template->attr[$reader->name] != $reader->value) { - $this->id = $reader->value; - } - else - { - $this->attrs[$reader->name] = $reader->value; - } - } - - while($reader->read() && $reader->depth > $depth) - { - if ($reader->nodeType == XMLReader::ELEMENT && $reader->depth > $depth) - { - $this->children[] = self::factory($reader->name, $reader, $reader->getAttribute('id')); + if (!$cloned) $template = clone($this); + $template->attrs[$reader->name] = $reader->value; } } + return $template; } /** @@ -158,7 +193,8 @@ class etemplate_widget // currently only overlays can contain templates, other widgets can only reference to templates via id if ($type == 'template' && $id && ($template = etemplate_widget_template::instance($id))) { - return $template; + // references can set different attributes like: class, span, content (namespace) + return $template->set_attrs($xml, false); // false = need to clone template, if attributs are set! } return new $class_name($xml); } @@ -336,20 +372,28 @@ class etemplate_widget * Sets a validation error, to be displayed in the next exec * * @param string $name (complete) name of the widget causing the error - * @param string $error error-message already translated + * @param string|boolean $error error-message already translated or false to reset all existing error for given name * @param string $cname=null set it to '', if the name is already a form-name, defaults to self::$name_vars */ public static function set_validation_error($name,$error,$cname=null) { - if (is_null($cname)) $cname = self::$name_vars; - //echo "<p>etemplate::set_validation_error('$name','$error','$cname');</p>\n"; + // not yet used: if (is_null($cname)) $cname = self::$name_vars; + error_log(__METHOD__."('$name','$error','$cname')"); + if ($cname) $name = self::form_name($cname,$name); - if (self::$validation_errors[$name]) + if ($error === false) { - self::$validation_errors[$name] .= ', '; + unset(self::$validation_errors[$name]); + } + else + { + if (self::$validation_errors[$name]) + { + self::$validation_errors[$name] .= ', '; + } + self::$validation_errors[$name] .= $error; } - self::$validation_errors[$name] .= $error; } /** @@ -361,7 +405,7 @@ class etemplate_widget */ public static function validation_errors($ignore_validation='',$cname='') { -// if (is_null($cname)) $cname = self::$name_vars; + // not yet used: if (is_null($cname)) $cname = self::$name_vars; //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') validation_error="; _debug_array(self::$validation_errors); if (!$ignore_validation) return count(self::$validation_errors) > 0; diff --git a/etemplate/inc/class.etemplate_widget_template.inc.php b/etemplate/inc/class.etemplate_widget_template.inc.php index 5fe6d7ce67..682683f165 100644 --- a/etemplate/inc/class.etemplate_widget_template.inc.php +++ b/etemplate/inc/class.etemplate_widget_template.inc.php @@ -108,7 +108,7 @@ class etemplate_widget_template extends etemplate_widget /** * Validate input * - * Reimplemented because templates can have an own namespace specified in options, NOT id! + * Reimplemented because templates can have an own namespace specified in attrs[content], NOT id! * * @param array $content * @param array &$validated=array() validated content @@ -117,7 +117,7 @@ class etemplate_widget_template extends etemplate_widget */ public function validate(array $content, &$validated=array(), $cname = '') { - if ($this->attrs['options']) $cname = self::form_name($cname, $this->attrs['options']); + if ($this->attrs['content']) $cname = self::form_name($cname, $this->attrs['content']); return parent::validate($content, $validated, $cname); } From 30ed6a8ab76d246b03e84a9b1aa6c989b638869d Mon Sep 17 00:00:00 2001 From: Ralf Becker <ralfbecker@outdoor-training.de> Date: Fri, 19 Aug 2011 08:22:19 +0000 Subject: [PATCH 093/472] - added legacy-options parsing and defintions for currently implemented widgets - added more server-side debuging: * etemplate_widget_template class can be called via url and displays parsed xml, eg: http://localhost/egroupware/etemplate/inc/class.etemplate_widget_template.inc.php?name=infolog.edit This is different from directly calling the xet file, as it show what got parsed and how: http://localhost/egroupware/infolog/templates/default/edit.xet * etemplate_new class can be called via url to render an arbitrary template, eg: http://localhost/egroupware/etemplate/inc/class.etemplate_new.inc.php?name=timesheet.edit Thought not all are already rendered correct, eg. infolog.edit is not: http://localhost/egroupware/etemplate/inc/class.etemplate_new.inc.php?name=infolog.edit --- etemplate/inc/class.etemplate.inc.php | 2 +- etemplate/inc/class.etemplate_new.inc.php | 42 ++++++- etemplate/inc/class.etemplate_widget.inc.php | 108 +++++++++++++++++- .../class.etemplate_widget_template.inc.php | 12 +- .../class.etemplate_widget_textbox.inc.php | 43 +++++-- etemplate/inc/class.xul_io.inc.php | 11 +- etemplate/setup/etemplates.inc.php | 4 +- etemplate/templates/default/editor.widget.xet | 96 ++++++++-------- 8 files changed, 249 insertions(+), 69 deletions(-) diff --git a/etemplate/inc/class.etemplate.inc.php b/etemplate/inc/class.etemplate.inc.php index 15296ad9bc..9d96c541c6 100644 --- a/etemplate/inc/class.etemplate.inc.php +++ b/etemplate/inc/class.etemplate.inc.php @@ -1698,7 +1698,7 @@ class etemplate extends boetemplate case 'vbox': case 'hbox': case 'groupbox': - case 'box': + case 'box': // size: num,orient,cellpadding,cellspacing,keep $rows = array(); $box_row = 1; $box_col = 'A'; diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index 119ae861b1..e148d2d9d4 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -11,6 +11,19 @@ * @version $Id$ */ +// allow to call direct for tests (see end of class) +if (!isset($GLOBALS['egw_info'])) +{ + $GLOBALS['egw_info'] = array( + 'flags' => array( + 'currentapp' => 'login', + 'nonavbar' => true, + 'debug' => 'etemplate_new', + ) + ); + include_once '../../header.inc.php'; +} + /** * New eTemplate serverside contains: * - main server methods like read, exec @@ -198,8 +211,9 @@ class etemplate_new extends etemplate_widget_template { $this->rel_path = self::relPath($this->name=$name, $this->template_set=$template_set, $this->version=$version, $this->laod_via = $load_via); + error_log(__METHOD__."('$name', '$template_set', '$lang', $group, '$version', '$load_via') rel_path=".array2string($this->rel_path)); - return (boolean)$this->real_path; + return (boolean)$this->rel_path; } /** @@ -390,4 +404,30 @@ class etemplate_new extends etemplate_widget_template } return $old; } + + /** + * Debug callback just outputting content + * + * @param array $content=null + */ + public function debug(array $content=null) + { + common::egw_header(); + _debug_array($content); + common::egw_footer(); + } } + +if ($GLOBALS['egw_info']['flags']['debug'] == 'etemplate_new') +{ + $name = isset($_GET['name']) ? $_GET['name'] : 'timesheet.edit'; + $template = new etemplate_new(); + if (!$template->read($name)) + { + header('HTTP-Status: 404 Not Found'); + echo "<html><head><title>Not Found

        Not Found

        The requested eTemplate '$name' was not found!

        \n"; + exit; + } + $GLOBALS['egw_info']['flags']['app_header'] = $name; + $template->exec('etemplate.etemplate.debug', array(), array(), array(), array(), 2); +} \ No newline at end of file diff --git a/etemplate/inc/class.etemplate_widget.inc.php b/etemplate/inc/class.etemplate_widget.inc.php index 6bcf903de1..2d7f643e09 100644 --- a/etemplate/inc/class.etemplate_widget.inc.php +++ b/etemplate/inc/class.etemplate_widget.inc.php @@ -53,6 +53,13 @@ class etemplate_widget */ protected $children = array(); + /** + * (Array of) comma-separated list of legacy options to automatically replace when parsing with set_attrs + * + * @var string|array + */ + protected $legacy_options; + /** * Request object of the currently created request * @@ -132,6 +139,17 @@ class etemplate_widget { $reader = self::get_reader($xml); + // check if we have to split legacy options (can be by type) + $legacy_options = $this->legacy_options; + if (is_array($legacy_options)) + { + if (!($type = $reader->getAttribute('type'))) + { + $type = $this->type; + } + $legacy_options = $legacy_options[$type]; + } + // read and set all attributes $template = $this; while($reader->moveToNextAttribute()) @@ -140,11 +158,66 @@ class etemplate_widget { if (!$cloned) $template = clone($this); $template->attrs[$reader->name] = $reader->value; + + // split legacy options + if ($legacy_options && $reader->name == 'options') + { + $legacy_options = explode(',', $legacy_options); + foreach(self::csv_split($reader->value, count($legacy_options)) as $n => $val) + { + if ($legacy_options[$n] && (string)$val !== '') $template->attrs[$legacy_options[$n]] = $val; + } + } } } return $template; } + /** + * Split a $delimiter-separated options string, which can contain parts with delimiters enclosed in $enclosure + * + * Examples: + * - csv_split('"1,2,3",2,3') === array('1,2,3','2','3') + * - csv_split('1,2,3',2) === array('1','2,3') + * - csv_split('"1,2,3",2,3',2) === array('1,2,3','2,3') + * - csv_split('"a""b,c",d') === array('a"b,c','d') // to escape enclosures double them! + * + * @param string $str + * @param int $num=null in how many parts to split maximal, parts over this number end up (unseparated) in the last part + * @param string $delimiter=',' + * @param string $enclosure='"' + * @return array + */ + public static function csv_split($str,$num=null,$delimiter=',',$enclosure='"') + { + if (strpos($str,$enclosure) === false) + { + return is_null($num) ? explode($delimiter,$str) : explode($delimiter,$str,$num); // no need to run this more expensive code + } + $parts = explode($delimiter,$str); + for($n = 0; isset($parts[$n]); ++$n) + { + $part =& $parts[$n]; + if ($part[0] === $enclosure) + { + while (isset($parts[$n+1]) && substr($part,-1) !== $enclosure) + { + $part .= $delimiter.$parts[++$n]; + unset($parts[$n]); + } + $part = substr(str_replace($enclosure.$enclosure,$enclosure,$part),1,-1); + } + } + $parts = array_values($parts); // renumber the parts (in case we had to concat them) + + if ($num > 0 && count($parts) > $num) + { + $parts[$num-1] = implode($delimiter,array_slice($parts,$num-1,count($parts)-$num+1)); + $parts = array_slice($parts,0,$num); + } + return $parts; + } + /** * Registry of classes implementing widgets * @@ -249,7 +322,7 @@ class etemplate_widget */ public function __toString() { - return $this->type.'#'.$this->id; + return $this->type.($this->attrs['type'] && $this->attrs['type'] != $this->type ? '('.$this->attrs['type'].')' : '').'#'.$this->id; } /** @@ -264,6 +337,11 @@ class etemplate_widget if ($this->id) echo ' id="'.htmlspecialchars($this->id).'"'; foreach($this->attrs as $name => $value) { + if ($name == 'options' && $this->legacy_options && (!is_array($this->legacy_options) || + isset($this->legacy_options[$this->attrs['type'] ? $this->attrs['type'] : $this->type]))) + { + continue; // do NOT output already converted legacy options + } echo ' '.$name.'="'.htmlspecialchars($value).'"'; } echo ' php-class="'.get_class($this).'"'; @@ -431,6 +509,19 @@ class etemplate_widget */ class etemplate_widget_named extends etemplate_widget { + /** + * (Array of) comma-separated list of legacy options to automatically replace when parsing with set_attrs + * + * @var string|array + */ + protected $legacy_options = array( + 'box' => ',cellpadding,cellspacing,keep', + 'hbox' => 'cellpadding,cellspacing,keep', + 'vbox' => 'cellpadding,cellspacing,keep', + 'groupbox' => 'cellpadding,cellspacing,keep', + 'grid' => null, // not used + ); + /** * Validate input * @@ -450,3 +541,18 @@ class etemplate_widget_named extends etemplate_widget } // register class for layout widgets, which can have an own namespace etemplate_widget::registerWidget('etemplate_widget_named', array('grid', 'box', 'hbox', 'vbox', 'groupbox')); + +/** + * Describtion widget + * + * Reimplemented to set legacy options + */ +class etemplate_widget_description extends etemplate_widget +{ + /** + * (Array of) comma-separated list of legacy options to automatically replace when parsing with set_attrs + * + * @var string|array + */ + protected $legacy_options = 'bold-italic,link,activate_links,label_for,link_target,link_popup_size,link_title'; +} diff --git a/etemplate/inc/class.etemplate_widget_template.inc.php b/etemplate/inc/class.etemplate_widget_template.inc.php index 682683f165..f5462893b7 100644 --- a/etemplate/inc/class.etemplate_widget_template.inc.php +++ b/etemplate/inc/class.etemplate_widget_template.inc.php @@ -17,6 +17,7 @@ if (!isset($GLOBALS['egw_info'])) $GLOBALS['egw_info'] = array( 'flags' => array( 'currentapp' => 'login', + 'debug' => 'etemplate_widget_template', ) ); include_once '../../header.inc.php'; @@ -114,6 +115,7 @@ class etemplate_widget_template extends etemplate_widget * @param array &$validated=array() validated content * @param string $cname='' current namespace * @return boolean true if no validation error, false otherwise + * @todo handle template references containing content in id, eg. id="edit.$cont[something]" */ public function validate(array $content, &$validated=array(), $cname = '') { @@ -123,9 +125,15 @@ class etemplate_widget_template extends etemplate_widget } } -if ($GLOBALS['egw_info']['flags']['currentapp'] == 'login') +if ($GLOBALS['egw_info']['flags']['debug'] == 'etemplate_widget_template') { - $template = etemplate_widget_template::instance('timesheet.edit'); + $name = isset($_GET['name']) ? $_GET['name'] : 'timesheet.edit'; + if (!($template = etemplate_widget_template::instance($name))) + { + header('HTTP-Status: 404 Not Found'); + echo "Not Found

        Not Found

        The requested eTemplate '$name' was not found!

        \n"; + exit; + } header('Content-Type: text/xml'); echo $template->toXml(); } \ No newline at end of file diff --git a/etemplate/inc/class.etemplate_widget_textbox.inc.php b/etemplate/inc/class.etemplate_widget_textbox.inc.php index dc60f1798a..15ed51607e 100644 --- a/etemplate/inc/class.etemplate_widget_textbox.inc.php +++ b/etemplate/inc/class.etemplate_widget_textbox.inc.php @@ -13,8 +13,8 @@ /** * eTemplate textbox widget with following sub-types: - * - textbox optional multiline="true" and rows="123" - * - int + * - textbox with optional multiline="true" and rows="123" + * - integer or int * - float * - hidden * - colorpicker @@ -22,6 +22,26 @@ */ class etemplate_widget_textbox extends etemplate_widget { + /** + * Constructor + * + * @param string|XMLReader $xml string with xml or XMLReader positioned on the element to construct + * @throws egw_exception_wrong_parameter + */ + public function __construct($xml) + { + parent::__construct($xml); + + // normalize types + if ($this->type !== 'textbox') + { + if ($this->type == 'int') $this->type = 'integer'; + + $this->attrs['type'] = $this->type; + $this->type = 'textbox'; + } + } + /** * Validate input * @@ -40,14 +60,13 @@ class etemplate_widget_textbox extends etemplate_widget public function validate(array $content, &$validated=array(), $cname = '') { $ok = true; - $type = isset($this->attrs['type']) ? $this->attrs['type'] : $this->type; if (!$this->is_readonly($cname)) { if (!isset($this->attrs['preg'])) { - switch($type) + switch($this->type) { - case 'int': + case 'integer': $this->attrs['preg'] = '/^-?[0-9]*$/'; break; case 'float': @@ -74,9 +93,9 @@ class etemplate_widget_textbox extends etemplate_widget } if ($this->attrs['preg'] && !preg_match($this->attrs['preg'],$value)) { - switch($type) + switch($this->type) { - case 'int': + case 'integer': self::set_validation_error($form_name,lang("'%1' is not a valid integer !!!",$value),''); break; case 'float': @@ -88,22 +107,22 @@ class etemplate_widget_textbox extends etemplate_widget } $ok = false; } - elseif ($type == 'int' || $type == 'float') // cast int and float and check range + elseif ($this->type == 'integer' || $this->type == 'float') // cast int and float and check range { if ((string)$value !== '' || $this->attrs['needed']) // empty values are Ok if needed is not set { - $value = $type == 'int' ? (int) $value : (float) str_replace(',','.',$value); // allow for german (and maybe other) format + $value = $this->type == 'integer' ? (int) $value : (float) str_replace(',','.',$value); // allow for german (and maybe other) format if (!empty($this->attrs['min']) && $value < $this->attrs['min']) { self::set_validation_error($form_name,lang("Value has to be at least '%1' !!!",$this->attrs['min']),''); - $value = $type == 'int' ? (int) $this->attrs['min'] : (float) $this->attrs['min']; + $value = $this->type == 'integer' ? (int) $this->attrs['min'] : (float) $this->attrs['min']; $ok = false; } if (!empty($this->attrs['max']) && $value > $this->attrs['max']) { self::set_validation_error($form_name,lang("Value has to be at maximum '%1' !!!",$this->attrs['max']),''); - $value = $type == 'int' ? (int) $this->attrs['max'] : (float) $this->attrs['max']; + $value = $this->type == 'integer' ? (int) $this->attrs['max'] : (float) $this->attrs['max']; $ok = false; } } @@ -113,4 +132,4 @@ class etemplate_widget_textbox extends etemplate_widget return parent::validate($content, $validated, $cname) && $ok; } } -etemplate_widget::registerWidget('etemplate_widget_textbox', array('textbox','int','float','passwd','hidden','colorpicker')); \ No newline at end of file +etemplate_widget::registerWidget('etemplate_widget_textbox', array('textbox','int','integer','float','passwd','hidden','colorpicker')); \ No newline at end of file diff --git a/etemplate/inc/class.xul_io.inc.php b/etemplate/inc/class.xul_io.inc.php index ad064012f7..bdf527a816 100644 --- a/etemplate/inc/class.xul_io.inc.php +++ b/etemplate/inc/class.xul_io.inc.php @@ -51,7 +51,7 @@ class xul_io var $widget2xul = array( 'label' => array( '.name' => 'description', - 'label' => 'value' + 'label' => 'value', ), 'text' => array( '.name' => 'textbox', @@ -65,12 +65,17 @@ class xul_io 'integer' => array( '.name' => 'textbox', '.set' => 'type=integer', - 'size' => 'min,max,size' + 'size' => 'min,max,size,precision,step' + ), + 'int' => array( + '.name' => 'textbox', + '.set' => 'type=integer', + 'size' => 'min,max,size,precision,step' ), 'float' => array( '.name' => 'textbox', '.set' => 'type=float', - 'size' => 'min,max,size,precision' + 'size' => 'min,max,size,precision,step' ), 'select' => array( '.name' => 'menulist,menupopup', diff --git a/etemplate/setup/etemplates.inc.php b/etemplate/setup/etemplates.inc.php index f6637d202a..0749a6565d 100644 --- a/etemplate/setup/etemplates.inc.php +++ b/etemplate/setup/etemplates.inc.php @@ -2,7 +2,7 @@ /** * EGroupware - eTemplates for Application etemplate * http://www.egroupware.org - * generated by soetemplate::dump4setup() 2011-07-12 11:52 + * generated by soetemplate::dump4setup() 2011-08-19 09:30 * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package etemplate @@ -183,6 +183,8 @@ $templ_data[] = array('name' => 'etemplate.test.duration','template' => '','lang $templ_data[] = array('name' => 'etemplate.test.grid-export','template' => '','lang' => '','group' => '0','version' => '2','data' => 'a:1:{i:0;a:5:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"some cell";}}i:2;a:1:{s:1:"A";a:6:{s:5:"class";s:9:"hboxClass";s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";i:1;a:3:{s:4:"size";s:1:"1";s:4:"type";s:5:"label";s:5:"label";s:2:"1.";}i:2;a:2:{s:4:"type";s:5:"label";s:5:"label";s:2:"2.";}i:3;a:3:{s:5:"align";s:5:"right";s:4:"type";s:5:"label";s:5:"label";s:10:"last right";}}}}s:4:"cols";i:1;s:4:"rows";i:2;s:4:"size";s:16:"100%,,,gridClass";}}','size' => '100%,,,gridClass','style' => '','modified' => '1179507244',); +$templ_data[] = array('name' => 'etemplate.test.html','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:2:{s:4:"type";s:8:"htmlarea";s:4:"name";s:4:"test";}}}s:4:"rows";i:1;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1313581424',); + $templ_data[] = array('name' => 'etemplate.test.infolog','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:13:"infolog-value";s:4:"name";s:4:"test";s:7:"options";a:0:{}}}}s:4:"rows";i:1;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1242560130',); $templ_data[] = array('name' => 'etemplate.test.required','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:6:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"Text";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:4:"name";s:4:"text";s:6:"needed";s:1:"1";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"File";}s:1:"B";a:3:{s:4:"type";s:4:"file";s:4:"name";s:4:"file";s:6:"needed";s:1:"1";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:8:"Checkbox";}s:1:"B";a:4:{s:4:"type";s:8:"checkbox";s:5:"label";s:22:"Gelesen und verstanden";s:4:"name";s:5:"check";s:6:"needed";s:1:"1";}}i:4;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Radios";}s:1:"B";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:5:{s:4:"type";s:5:"radio";s:4:"size";s:3:"one";s:5:"label";s:3:"One";s:4:"name";s:5:"radio";s:6:"needed";s:1:"1";}i:2;a:5:{s:4:"type";s:5:"radio";s:4:"name";s:5:"radio";s:4:"size";s:3:"two";s:5:"label";s:3:"Two";s:6:"needed";s:1:"1";}}}i:5;a:2:{s:1:"A";a:2:{s:4:"type";s:6:"button";s:5:"label";s:6:"Submit";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:5;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1279699676',); diff --git a/etemplate/templates/default/editor.widget.xet b/etemplate/templates/default/editor.widget.xet index 1208edd546..9759c1d574 100644 --- a/etemplate/templates/default/editor.widget.xet +++ b/etemplate/templates/default/editor.widget.xet @@ -13,44 +13,44 @@ - + - + - - - - + + + + - - - - + + + + - + - - + + - - - + + + - - + + - - + + - - + + @@ -60,18 +60,18 @@ - + - + - + - + - + @@ -87,21 +87,21 @@ - + - + - + - + - + @@ -109,46 +109,46 @@ - - + + - + - - + + -