From 22502eb7a498183fada4a50994fa2bb25e4bb790 Mon Sep 17 00:00:00 2001 From: Russ Handorf Date: Sat, 13 Feb 2016 21:34:23 -0500 Subject: [PATCH] initial commit --- README | 45 + RGraph/LICENSE.txt | 93 + RGraph/css/ModalDialog.css | 90 + RGraph/css/common.css | 297 +++ RGraph/css/website.css | 253 +++ RGraph/docs/.BC.txt | 101 + RGraph/docs/.CHANGELOG.txt | 1277 +++++++++++ RGraph/docs/adjusting.html | 244 ++ RGraph/docs/animation.html | 313 +++ RGraph/docs/annotating.html | 263 +++ RGraph/docs/api.html | 835 +++++++ RGraph/docs/async.html | 265 +++ RGraph/docs/bar.html | 603 +++++ RGraph/docs/bipolar.html | 370 ++++ RGraph/docs/color.html | 274 +++ RGraph/docs/combine.html | 481 ++++ RGraph/docs/context.html | 368 +++ RGraph/docs/css.html | 326 +++ RGraph/docs/domcontentloaded.html | 252 +++ RGraph/docs/donut.html | 168 ++ RGraph/docs/downloads | 2 + RGraph/docs/dynamic.html | 291 +++ RGraph/docs/events.html | 303 +++ RGraph/docs/external.html | 370 ++++ RGraph/docs/funnel.html | 382 ++++ RGraph/docs/gantt.html | 455 ++++ RGraph/docs/hbar.html | 489 ++++ RGraph/docs/hprogress.html | 327 +++ RGraph/docs/index.html | 920 ++++++++ RGraph/docs/ingraph.html | 224 ++ RGraph/docs/issues.html | 248 +++ RGraph/docs/keys.html | 211 ++ RGraph/docs/led.html | 230 ++ RGraph/docs/licensing.html | 258 +++ RGraph/docs/line.html | 745 +++++++ RGraph/docs/meter.html | 344 +++ RGraph/docs/misc.html | 668 ++++++ RGraph/docs/msie.html | 306 +++ RGraph/docs/odo.html | 346 +++ RGraph/docs/pie.html | 498 +++++ RGraph/docs/png.html | 249 +++ RGraph/docs/released.txt | 416 ++++ RGraph/docs/resizing.html | 212 ++ RGraph/docs/rose.html | 442 ++++ RGraph/docs/rscatter.html | 370 ++++ RGraph/docs/scatter.html | 683 ++++++ RGraph/docs/setconfig.html | 206 ++ RGraph/docs/tooltips.html | 587 +++++ RGraph/docs/tradar.html | 398 ++++ RGraph/docs/vprogress.html | 363 +++ RGraph/docs/zoom.html | 388 ++++ RGraph/docs/zoom_thumbnail.html | 191 ++ RGraph/examples/bar.html | 333 +++ RGraph/examples/basic.html | 64 + RGraph/examples/bipolar.html | 255 +++ RGraph/examples/donut.html | 256 +++ RGraph/examples/funnel.html | 234 ++ RGraph/examples/gantt.html | 272 +++ RGraph/examples/hbar.html | 244 ++ RGraph/examples/hprogress.html | 212 ++ RGraph/examples/index.html | 171 ++ RGraph/examples/led.html | 200 ++ RGraph/examples/line.html | 350 +++ RGraph/examples/meter.html | 233 ++ RGraph/examples/odo.html | 241 ++ RGraph/examples/pie.html | 241 ++ RGraph/examples/rose.html | 187 ++ RGraph/examples/rscatter.html | 198 ++ RGraph/examples/scatter.html | 302 +++ RGraph/examples/showcase.html | 68 + RGraph/examples/text.html | 104 + RGraph/examples/tradar.html | 240 ++ RGraph/examples/vprogress.html | 209 ++ RGraph/images/alex.png | Bin 0 -> 2365 bytes RGraph/images/analogo.gif | Bin 0 -> 567 bytes RGraph/images/analogo.png | Bin 0 -> 524 bytes RGraph/images/atom.png | Bin 0 -> 1198 bytes RGraph/images/bara1.gif | Bin 0 -> 39 bytes RGraph/images/bara1.png | Bin 0 -> 117 bytes RGraph/images/bara16.gif | Bin 0 -> 59 bytes RGraph/images/bara16.png | Bin 0 -> 118 bytes RGraph/images/bara2.gif | Bin 0 -> 41 bytes RGraph/images/bara2.png | Bin 0 -> 117 bytes RGraph/images/bara32.gif | Bin 0 -> 71 bytes RGraph/images/bara32.png | Bin 0 -> 118 bytes RGraph/images/bara4.gif | Bin 0 -> 45 bytes RGraph/images/bara4.png | Bin 0 -> 117 bytes RGraph/images/bara8.gif | Bin 0 -> 50 bytes RGraph/images/bara8.png | Bin 0 -> 118 bytes RGraph/images/barb1.gif | Bin 0 -> 67 bytes RGraph/images/barb1.png | Bin 0 -> 149 bytes RGraph/images/barb16.gif | Bin 0 -> 126 bytes RGraph/images/barb16.png | Bin 0 -> 151 bytes RGraph/images/barb2.gif | Bin 0 -> 76 bytes RGraph/images/barb2.png | Bin 0 -> 149 bytes RGraph/images/barb32.gif | Bin 0 -> 165 bytes RGraph/images/barb32.png | Bin 0 -> 152 bytes RGraph/images/barb4.gif | Bin 0 -> 85 bytes RGraph/images/barb4.png | Bin 0 -> 149 bytes RGraph/images/barb8.gif | Bin 0 -> 100 bytes RGraph/images/barb8.png | Bin 0 -> 150 bytes RGraph/images/barc1.gif | Bin 0 -> 68 bytes RGraph/images/barc1.png | Bin 0 -> 159 bytes RGraph/images/barc16.gif | Bin 0 -> 214 bytes RGraph/images/barc16.png | Bin 0 -> 169 bytes RGraph/images/barc2.gif | Bin 0 -> 80 bytes RGraph/images/barc2.png | Bin 0 -> 167 bytes RGraph/images/barc32.gif | Bin 0 -> 318 bytes RGraph/images/barc32.png | Bin 0 -> 170 bytes RGraph/images/barc4.gif | Bin 0 -> 102 bytes RGraph/images/barc4.png | Bin 0 -> 167 bytes RGraph/images/barc8.gif | Bin 0 -> 145 bytes RGraph/images/barc8.png | Bin 0 -> 168 bytes RGraph/images/bard1.gif | Bin 0 -> 43 bytes RGraph/images/bard1.png | Bin 0 -> 121 bytes RGraph/images/bard16.gif | Bin 0 -> 104 bytes RGraph/images/bard16.png | Bin 0 -> 124 bytes RGraph/images/bard2.gif | Bin 0 -> 48 bytes RGraph/images/bard2.png | Bin 0 -> 122 bytes RGraph/images/bard32.gif | Bin 0 -> 147 bytes RGraph/images/bard32.png | Bin 0 -> 124 bytes RGraph/images/bard4.gif | Bin 0 -> 57 bytes RGraph/images/bard4.png | Bin 0 -> 123 bytes RGraph/images/bard8.gif | Bin 0 -> 76 bytes RGraph/images/bard8.png | Bin 0 -> 123 bytes RGraph/images/bare1.gif | Bin 0 -> 71 bytes RGraph/images/bare1.png | Bin 0 -> 162 bytes RGraph/images/bare16.gif | Bin 0 -> 201 bytes RGraph/images/bare16.png | Bin 0 -> 172 bytes RGraph/images/bare2.gif | Bin 0 -> 85 bytes RGraph/images/bare2.png | Bin 0 -> 170 bytes RGraph/images/bare32.gif | Bin 0 -> 300 bytes RGraph/images/bare32.png | Bin 0 -> 173 bytes RGraph/images/bare4.gif | Bin 0 -> 105 bytes RGraph/images/bare4.png | Bin 0 -> 170 bytes RGraph/images/bare8.gif | Bin 0 -> 142 bytes RGraph/images/bare8.png | Bin 0 -> 171 bytes RGraph/images/barf1.gif | Bin 0 -> 39 bytes RGraph/images/barf1.png | Bin 0 -> 117 bytes RGraph/images/barf16.gif | Bin 0 -> 118 bytes RGraph/images/barf16.png | Bin 0 -> 124 bytes RGraph/images/barf2.gif | Bin 0 -> 49 bytes RGraph/images/barf2.png | Bin 0 -> 122 bytes RGraph/images/barf32.gif | Bin 0 -> 181 bytes RGraph/images/barf32.png | Bin 0 -> 124 bytes RGraph/images/barf4.gif | Bin 0 -> 58 bytes RGraph/images/barf4.png | Bin 0 -> 123 bytes RGraph/images/barf8.gif | Bin 0 -> 76 bytes RGraph/images/barf8.png | Bin 0 -> 123 bytes RGraph/images/barg1.gif | Bin 0 -> 93 bytes RGraph/images/barg1.png | Bin 0 -> 164 bytes RGraph/images/barg16.gif | Bin 0 -> 235 bytes RGraph/images/barg16.png | Bin 0 -> 193 bytes RGraph/images/barg2.gif | Bin 0 -> 111 bytes RGraph/images/barg2.png | Bin 0 -> 183 bytes RGraph/images/barg32.gif | Bin 0 -> 337 bytes RGraph/images/barg32.png | Bin 0 -> 194 bytes RGraph/images/barg4.gif | Bin 0 -> 132 bytes RGraph/images/barg4.png | Bin 0 -> 192 bytes RGraph/images/barg8.gif | Bin 0 -> 175 bytes RGraph/images/barg8.png | Bin 0 -> 192 bytes RGraph/images/barh1.gif | Bin 0 -> 94 bytes RGraph/images/barh1.png | Bin 0 -> 174 bytes RGraph/images/barh16.gif | Bin 0 -> 287 bytes RGraph/images/barh16.png | Bin 0 -> 213 bytes RGraph/images/barh2.gif | Bin 0 -> 114 bytes RGraph/images/barh2.png | Bin 0 -> 202 bytes RGraph/images/barh32.gif | Bin 0 -> 447 bytes RGraph/images/barh32.png | Bin 0 -> 214 bytes RGraph/images/barh4.gif | Bin 0 -> 144 bytes RGraph/images/barh4.png | Bin 0 -> 211 bytes RGraph/images/barh8.gif | Bin 0 -> 194 bytes RGraph/images/barh8.png | Bin 0 -> 212 bytes RGraph/images/bari1.gif | Bin 0 -> 68 bytes RGraph/images/bari1.png | Bin 0 -> 146 bytes RGraph/images/bari16.gif | Bin 0 -> 131 bytes RGraph/images/bari16.png | Bin 0 -> 150 bytes RGraph/images/bari2.gif | Bin 0 -> 78 bytes RGraph/images/bari2.png | Bin 0 -> 147 bytes RGraph/images/bari32.gif | Bin 0 -> 172 bytes RGraph/images/bari32.png | Bin 0 -> 153 bytes RGraph/images/bari4.gif | Bin 0 -> 88 bytes RGraph/images/bari4.png | Bin 0 -> 148 bytes RGraph/images/bari8.gif | Bin 0 -> 103 bytes RGraph/images/bari8.png | Bin 0 -> 149 bytes RGraph/images/barj1.gif | Bin 0 -> 94 bytes RGraph/images/barj1.png | Bin 0 -> 158 bytes RGraph/images/barj16.gif | Bin 0 -> 253 bytes RGraph/images/barj16.png | Bin 0 -> 187 bytes RGraph/images/barj2.gif | Bin 0 -> 115 bytes RGraph/images/barj2.png | Bin 0 -> 176 bytes RGraph/images/barj32.gif | Bin 0 -> 393 bytes RGraph/images/barj32.png | Bin 0 -> 189 bytes RGraph/images/barj4.gif | Bin 0 -> 143 bytes RGraph/images/barj4.png | Bin 0 -> 184 bytes RGraph/images/barj8.gif | Bin 0 -> 185 bytes RGraph/images/barj8.png | Bin 0 -> 186 bytes RGraph/images/bn.business.png | Bin 0 -> 4512 bytes RGraph/images/bn.personal.png | Bin 0 -> 4979 bytes RGraph/images/border-radius.png | Bin 0 -> 9437 bytes RGraph/images/buy.png | Bin 0 -> 4365 bytes RGraph/images/buzz.png | Bin 0 -> 1180 bytes RGraph/images/chrome_logo.png | Bin 0 -> 6645 bytes RGraph/images/coins.jpg | Bin 0 -> 1634 bytes RGraph/images/context.png | Bin 0 -> 3569 bytes RGraph/images/delicious.png | Bin 0 -> 1018 bytes RGraph/images/download-beta-sml.png | Bin 0 -> 1877 bytes RGraph/images/download-beta.png | Bin 0 -> 3689 bytes RGraph/images/download-stable-sml.png | Bin 0 -> 2106 bytes RGraph/images/download-stable.png | Bin 0 -> 4609 bytes RGraph/images/download.png | Bin 0 -> 5426 bytes RGraph/images/facebook.png | Bin 0 -> 1053 bytes RGraph/images/favicon.ico | Bin 0 -> 3638 bytes RGraph/images/favicon.png | Bin 0 -> 1245 bytes RGraph/images/friendfeed.png | Bin 0 -> 1071 bytes RGraph/images/googlegroups.png | Bin 0 -> 3191 bytes RGraph/images/html2.gif | Bin 0 -> 231 bytes RGraph/images/html2.png | Bin 0 -> 290 bytes RGraph/images/icons_combined.png | Bin 0 -> 5965 bytes RGraph/images/introspection.png | Bin 0 -> 157292 bytes RGraph/images/logo.png | Bin 0 -> 4154 bytes RGraph/images/merry-christmas-snowman.png | Bin 0 -> 18770 bytes RGraph/images/png.icon.png | Bin 0 -> 1008 bytes RGraph/images/reddit.png | Bin 0 -> 619 bytes RGraph/images/rss.png | Bin 0 -> 657 bytes RGraph/images/rss_big.png | Bin 0 -> 1794 bytes RGraph/images/sq0.png | Bin 0 -> 91 bytes RGraph/images/sq1.png | Bin 0 -> 94 bytes RGraph/images/sq2.png | Bin 0 -> 93 bytes RGraph/images/sq3.png | Bin 0 -> 93 bytes RGraph/images/sq4.png | Bin 0 -> 94 bytes RGraph/images/sq5.png | Bin 0 -> 93 bytes RGraph/images/sq6.png | Bin 0 -> 94 bytes RGraph/images/sq7.png | Bin 0 -> 94 bytes RGraph/images/sq8.png | Bin 0 -> 94 bytes RGraph/images/sq9.png | Bin 0 -> 93 bytes RGraph/images/sqg.png | Bin 0 -> 94 bytes RGraph/images/structure.png | Bin 0 -> 4399 bytes RGraph/images/stumble.png | Bin 0 -> 1275 bytes RGraph/images/twitter.png | Bin 0 -> 1163 bytes RGraph/images/unicef.png | Bin 0 -> 8505 bytes RGraph/index.html | 872 ++++++++ RGraph/scripts/minify | 104 + alert_status.php | 11 + beth.txt | 1 + check_climate_status.php | 43 + check_isy99i_occupancy_status.php | 71 + check_isy99i_status.php | 57 + check_power_status.php | 149 ++ css/ModalDialog.css | 90 + css/common.css | 297 +++ css/website.css | 253 +++ excanvas/EXCANVAS-LICENSE.txt | 214 ++ excanvas/HTACCESS-SAMPLE | 11 + excanvas/excanvas.compressed.js | Bin 0 -> 8660 bytes excanvas/excanvas.original.js | 1421 ++++++++++++ groceries.html | 2 + icons/button_Off.png | Bin 0 -> 3213 bytes icons/button_On.png | Bin 0 -> 3479 bytes icons/left-arrow.png | Bin 0 -> 2169 bytes icons/light.png | Bin 0 -> 7254 bytes icons/music.png | Bin 0 -> 7326 bytes icons/right-arrow.png | Bin 0 -> 2184 bytes icons/weather.png | Bin 0 -> 5739 bytes icons/weather/Chance_Of_Showers.png | Bin 0 -> 11382 bytes icons/weather/Clear.png | Bin 0 -> 6977 bytes icons/weather/Cloudy.png | Bin 0 -> 9774 bytes icons/weather/Cloudy_Period.png | Bin 0 -> 10999 bytes icons/weather/Cloudy_With_Dizzle.png | Bin 0 -> 13328 bytes icons/weather/Few_Flurries.png | Bin 0 -> 11627 bytes icons/weather/Few_Flurries_Night.png | Bin 0 -> 12202 bytes icons/weather/Few_Showers.png | Bin 0 -> 11639 bytes icons/weather/Flurries.png | Bin 0 -> 9924 bytes icons/weather/Fog.png | Bin 0 -> 9337 bytes icons/weather/Folder_Extra.png | Bin 0 -> 7221 bytes icons/weather/Freezing_Rain.png | Bin 0 -> 15657 bytes icons/weather/Mostly_Sunny.png | Bin 0 -> 13291 bytes icons/weather/Note_Extra.png | Bin 0 -> 12393 bytes icons/weather/Overcast.png | Bin 0 -> 9774 bytes icons/weather/Partly cloudy.png | Bin 0 -> 12335 bytes icons/weather/Rain.png | Bin 0 -> 10666 bytes icons/weather/Rain_Or_Snow.png | Bin 0 -> 11308 bytes icons/weather/Risk_Of_Thundershowers.png | Bin 0 -> 14632 bytes icons/weather/Snow.png | Bin 0 -> 10904 bytes icons/weather/Sunny.png | Bin 0 -> 11150 bytes icons/weather/Thunder_Showers.png | Bin 0 -> 14106 bytes icons/weather/Thunderstorms.png | Bin 0 -> 12380 bytes icons/weather/Wet_Flurries.png | Bin 0 -> 13606 bytes icons/weather/Wet_Flurries_Night.png | Bin 0 -> 13306 bytes images/bg.jpg | Bin 0 -> 3541 bytes images/body-box-bottom.png | Bin 0 -> 212 bytes images/body-box-repeatablebody.png | Bin 0 -> 135 bytes images/body-box-top.png | Bin 0 -> 220 bytes images/bottom-controls-off.jpg | Bin 0 -> 10342 bytes images/bottom-controls-on.jpg | Bin 0 -> 23090 bytes images/bottom-controls-repeatablebar.jpg | Bin 0 -> 352 bytes images/cameras-off.png | Bin 0 -> 1096 bytes images/cameras-on.png | Bin 0 -> 2540 bytes images/climate-off.png | Bin 0 -> 1014 bytes images/climate-on.png | Bin 0 -> 2172 bytes images/groceries-off.png | Bin 0 -> 941 bytes images/groceries-on.png | Bin 0 -> 2212 bytes images/header-camera.png | Bin 0 -> 5265 bytes images/header-climate.png | Bin 0 -> 3797 bytes images/header-groceries.png | Bin 0 -> 4846 bytes images/header-lighting.png | Bin 0 -> 9484 bytes images/header-news.png | Bin 0 -> 3304 bytes images/header-power.png | Bin 0 -> 3461 bytes images/header-recipes.png | Bin 0 -> 4356 bytes images/header-repeater.png | Bin 0 -> 197 bytes images/header-security.png | Bin 0 -> 5659 bytes images/header-thejukebox.png | Bin 0 -> 5892 bytes images/header-traffic.png | Bin 0 -> 4077 bytes images/header-weather.png | Bin 0 -> 5646 bytes images/header.png | Bin 0 -> 9777 bytes images/home-off.png | Bin 0 -> 1134 bytes images/home-on.png | Bin 0 -> 2683 bytes images/icon-barchart.png | Bin 0 -> 761 bytes images/icon-sliders.png | Bin 0 -> 724 bytes images/lighting-off.png | Bin 0 -> 930 bytes images/lighting-on.png | Bin 0 -> 3744 bytes images/music-off.png | Bin 0 -> 924 bytes images/music-on.png | Bin 0 -> 2785 bytes images/news-off.png | Bin 0 -> 1158 bytes images/news-on.png | Bin 0 -> 2508 bytes images/power-off.png | Bin 0 -> 948 bytes images/power-on.png | Bin 0 -> 2482 bytes images/receipes-off.png | Bin 0 -> 936 bytes images/receipes-on.png | Bin 0 -> 2387 bytes images/security-off.png | Bin 0 -> 1840 bytes images/security-on.png | Bin 0 -> 3008 bytes images/slider-off.png | Bin 0 -> 417 bytes images/slider-on.png | Bin 0 -> 716 bytes images/traffic-off.png | Bin 0 -> 1484 bytes images/traffic-on.png | Bin 0 -> 3212 bytes images/weather-off.png | Bin 0 -> 1255 bytes images/weather-on.png | Bin 0 -> 3297 bytes includes.php | 45 + index.php | 466 ++++ jukebox.php | 51 + left-arrow.html | 49 + libraries/RGraph.bar.js | 1653 ++++++++++++++ libraries/RGraph.bipolar.js | 713 ++++++ libraries/RGraph.common.adjusting.js | 624 ++++++ libraries/RGraph.common.annotate.js | 317 +++ libraries/RGraph.common.context.js | 559 +++++ libraries/RGraph.common.core.js | 2454 +++++++++++++++++++++ libraries/RGraph.common.resizing.js | 330 +++ libraries/RGraph.common.tooltips.js | 502 +++++ libraries/RGraph.common.zoom.js | 867 ++++++++ libraries/RGraph.funnel.js | 603 +++++ libraries/RGraph.gantt.js | 467 ++++ libraries/RGraph.hbar.js | 893 ++++++++ libraries/RGraph.hprogress.js | 545 +++++ libraries/RGraph.led.js | 225 ++ libraries/RGraph.line.js | 1868 ++++++++++++++++ libraries/RGraph.meter.js | 398 ++++ libraries/RGraph.modaldialog.js | 244 ++ libraries/RGraph.odo.js | 653 ++++++ libraries/RGraph.pie.js | 705 ++++++ libraries/RGraph.rose.js | 531 +++++ libraries/RGraph.rscatter.js | 597 +++++ libraries/RGraph.scatter.js | 1168 ++++++++++ libraries/RGraph.skeleton.js | 306 +++ libraries/RGraph.tradar.js | 624 ++++++ libraries/RGraph.vprogress.js | 554 +++++ menu.html | 125 ++ middle.html | 1 + news.html | 11 + news.php | 47 + other_icons/Security.jpg | Bin 0 -> 14632 bytes other_icons/audio.jpg | Bin 0 -> 11349 bytes other_icons/audio.png | Bin 0 -> 7326 bytes other_icons/cameras.jpg | Bin 0 -> 10825 bytes other_icons/cameras.png | Bin 0 -> 8379 bytes other_icons/climate.jpg | Bin 0 -> 11250 bytes other_icons/climate.png | Bin 0 -> 7070 bytes other_icons/events.jpg | Bin 0 -> 11062 bytes other_icons/events.png | Bin 0 -> 7807 bytes other_icons/lighting.jpg | Bin 0 -> 11580 bytes other_icons/lighting.png | Bin 0 -> 8304 bytes other_icons/power.jpg | Bin 0 -> 11032 bytes other_icons/power.png | Bin 0 -> 7883 bytes other_icons/status.jpg | Bin 0 -> 10434 bytes other_icons/status.png | Bin 0 -> 7300 bytes pxweather.class.php | 257 +++ pxweather/LICENSE.txt | 340 +++ pxweather/README.txt | 302 +++ pxweather/pxweather.class.php | 251 +++ pxweather/xmlize-php4.inc.php | 168 ++ pxweather/xmlize-php5.inc.php | 174 ++ right-arrow.html | 46 + rotate-weather.php | 6 + russ.txt | 1 + security1.html | 19 + set_climate_status.php | 35 + set_isy99i_status.php | 48 + set_summon_status.php | 10 + thermometer-blank-black.png | Bin 0 -> 1753 bytes thermometer-blank.png | Bin 0 -> 1292 bytes thermometer.php | 403 ++++ title_status.php | 22 + top.html | 1 + traffic-iframe.html | 46 + traffic.html | 1 + weather-footer.php | 15 + weather-meter.php | 80 + weather-odometer.php | 55 + weather.php | 80 + weather1-speed.php | 55 + weather1-temp.php | 77 + weather1.js | 21 + weather1.php | 89 + weather2.js | 5 + weather2.php | 4 + weather3.js | 5 + weather3.php | 32 + weather4.js | 5 + weather4.php | 6 + weather5.js | 5 + weather5.php | 19 + weather6.js | 5 + weather6.php | 28 + xml2array.php | 125 ++ xmlize-php5.inc.php | 174 ++ 425 files changed, 49460 insertions(+) create mode 100644 README create mode 100644 RGraph/LICENSE.txt create mode 100644 RGraph/css/ModalDialog.css create mode 100644 RGraph/css/common.css create mode 100644 RGraph/css/website.css create mode 100644 RGraph/docs/.BC.txt create mode 100644 RGraph/docs/.CHANGELOG.txt create mode 100644 RGraph/docs/adjusting.html create mode 100644 RGraph/docs/animation.html create mode 100644 RGraph/docs/annotating.html create mode 100644 RGraph/docs/api.html create mode 100644 RGraph/docs/async.html create mode 100644 RGraph/docs/bar.html create mode 100644 RGraph/docs/bipolar.html create mode 100644 RGraph/docs/color.html create mode 100644 RGraph/docs/combine.html create mode 100644 RGraph/docs/context.html create mode 100644 RGraph/docs/css.html create mode 100644 RGraph/docs/domcontentloaded.html create mode 100644 RGraph/docs/donut.html create mode 100644 RGraph/docs/downloads create mode 100644 RGraph/docs/dynamic.html create mode 100644 RGraph/docs/events.html create mode 100644 RGraph/docs/external.html create mode 100644 RGraph/docs/funnel.html create mode 100644 RGraph/docs/gantt.html create mode 100644 RGraph/docs/hbar.html create mode 100644 RGraph/docs/hprogress.html create mode 100644 RGraph/docs/index.html create mode 100644 RGraph/docs/ingraph.html create mode 100644 RGraph/docs/issues.html create mode 100644 RGraph/docs/keys.html create mode 100644 RGraph/docs/led.html create mode 100644 RGraph/docs/licensing.html create mode 100644 RGraph/docs/line.html create mode 100644 RGraph/docs/meter.html create mode 100644 RGraph/docs/misc.html create mode 100644 RGraph/docs/msie.html create mode 100644 RGraph/docs/odo.html create mode 100644 RGraph/docs/pie.html create mode 100644 RGraph/docs/png.html create mode 100644 RGraph/docs/released.txt create mode 100644 RGraph/docs/resizing.html create mode 100644 RGraph/docs/rose.html create mode 100644 RGraph/docs/rscatter.html create mode 100644 RGraph/docs/scatter.html create mode 100644 RGraph/docs/setconfig.html create mode 100644 RGraph/docs/tooltips.html create mode 100644 RGraph/docs/tradar.html create mode 100644 RGraph/docs/vprogress.html create mode 100644 RGraph/docs/zoom.html create mode 100644 RGraph/docs/zoom_thumbnail.html create mode 100644 RGraph/examples/bar.html create mode 100644 RGraph/examples/basic.html create mode 100644 RGraph/examples/bipolar.html create mode 100644 RGraph/examples/donut.html create mode 100644 RGraph/examples/funnel.html create mode 100644 RGraph/examples/gantt.html create mode 100644 RGraph/examples/hbar.html create mode 100644 RGraph/examples/hprogress.html create mode 100644 RGraph/examples/index.html create mode 100644 RGraph/examples/led.html create mode 100644 RGraph/examples/line.html create mode 100644 RGraph/examples/meter.html create mode 100644 RGraph/examples/odo.html create mode 100644 RGraph/examples/pie.html create mode 100644 RGraph/examples/rose.html create mode 100644 RGraph/examples/rscatter.html create mode 100644 RGraph/examples/scatter.html create mode 100644 RGraph/examples/showcase.html create mode 100644 RGraph/examples/text.html create mode 100644 RGraph/examples/tradar.html create mode 100644 RGraph/examples/vprogress.html create mode 100644 RGraph/images/alex.png create mode 100644 RGraph/images/analogo.gif create mode 100644 RGraph/images/analogo.png create mode 100644 RGraph/images/atom.png create mode 100644 RGraph/images/bara1.gif create mode 100644 RGraph/images/bara1.png create mode 100644 RGraph/images/bara16.gif create mode 100644 RGraph/images/bara16.png create mode 100644 RGraph/images/bara2.gif create mode 100644 RGraph/images/bara2.png create mode 100644 RGraph/images/bara32.gif create mode 100644 RGraph/images/bara32.png create mode 100644 RGraph/images/bara4.gif create mode 100644 RGraph/images/bara4.png create mode 100644 RGraph/images/bara8.gif create mode 100644 RGraph/images/bara8.png create mode 100644 RGraph/images/barb1.gif create mode 100644 RGraph/images/barb1.png create mode 100644 RGraph/images/barb16.gif create mode 100644 RGraph/images/barb16.png create mode 100644 RGraph/images/barb2.gif create mode 100644 RGraph/images/barb2.png create mode 100644 RGraph/images/barb32.gif create mode 100644 RGraph/images/barb32.png create mode 100644 RGraph/images/barb4.gif create mode 100644 RGraph/images/barb4.png create mode 100644 RGraph/images/barb8.gif create mode 100644 RGraph/images/barb8.png create mode 100644 RGraph/images/barc1.gif create mode 100644 RGraph/images/barc1.png create mode 100644 RGraph/images/barc16.gif create mode 100644 RGraph/images/barc16.png create mode 100644 RGraph/images/barc2.gif create mode 100644 RGraph/images/barc2.png create mode 100644 RGraph/images/barc32.gif create mode 100644 RGraph/images/barc32.png create mode 100644 RGraph/images/barc4.gif create mode 100644 RGraph/images/barc4.png create mode 100644 RGraph/images/barc8.gif create mode 100644 RGraph/images/barc8.png create mode 100644 RGraph/images/bard1.gif create mode 100644 RGraph/images/bard1.png create mode 100644 RGraph/images/bard16.gif create mode 100644 RGraph/images/bard16.png create mode 100644 RGraph/images/bard2.gif create mode 100644 RGraph/images/bard2.png create mode 100644 RGraph/images/bard32.gif create mode 100644 RGraph/images/bard32.png create mode 100644 RGraph/images/bard4.gif create mode 100644 RGraph/images/bard4.png create mode 100644 RGraph/images/bard8.gif create mode 100644 RGraph/images/bard8.png create mode 100644 RGraph/images/bare1.gif create mode 100644 RGraph/images/bare1.png create mode 100644 RGraph/images/bare16.gif create mode 100644 RGraph/images/bare16.png create mode 100644 RGraph/images/bare2.gif create mode 100644 RGraph/images/bare2.png create mode 100644 RGraph/images/bare32.gif create mode 100644 RGraph/images/bare32.png create mode 100644 RGraph/images/bare4.gif create mode 100644 RGraph/images/bare4.png create mode 100644 RGraph/images/bare8.gif create mode 100644 RGraph/images/bare8.png create mode 100644 RGraph/images/barf1.gif create mode 100644 RGraph/images/barf1.png create mode 100644 RGraph/images/barf16.gif create mode 100644 RGraph/images/barf16.png create mode 100644 RGraph/images/barf2.gif create mode 100644 RGraph/images/barf2.png create mode 100644 RGraph/images/barf32.gif create mode 100644 RGraph/images/barf32.png create mode 100644 RGraph/images/barf4.gif create mode 100644 RGraph/images/barf4.png create mode 100644 RGraph/images/barf8.gif create mode 100644 RGraph/images/barf8.png create mode 100644 RGraph/images/barg1.gif create mode 100644 RGraph/images/barg1.png create mode 100644 RGraph/images/barg16.gif create mode 100644 RGraph/images/barg16.png create mode 100644 RGraph/images/barg2.gif create mode 100644 RGraph/images/barg2.png create mode 100644 RGraph/images/barg32.gif create mode 100644 RGraph/images/barg32.png create mode 100644 RGraph/images/barg4.gif create mode 100644 RGraph/images/barg4.png create mode 100644 RGraph/images/barg8.gif create mode 100644 RGraph/images/barg8.png create mode 100644 RGraph/images/barh1.gif create mode 100644 RGraph/images/barh1.png create mode 100644 RGraph/images/barh16.gif create mode 100644 RGraph/images/barh16.png create mode 100644 RGraph/images/barh2.gif create mode 100644 RGraph/images/barh2.png create mode 100644 RGraph/images/barh32.gif create mode 100644 RGraph/images/barh32.png create mode 100644 RGraph/images/barh4.gif create mode 100644 RGraph/images/barh4.png create mode 100644 RGraph/images/barh8.gif create mode 100644 RGraph/images/barh8.png create mode 100644 RGraph/images/bari1.gif create mode 100644 RGraph/images/bari1.png create mode 100644 RGraph/images/bari16.gif create mode 100644 RGraph/images/bari16.png create mode 100644 RGraph/images/bari2.gif create mode 100644 RGraph/images/bari2.png create mode 100644 RGraph/images/bari32.gif create mode 100644 RGraph/images/bari32.png create mode 100644 RGraph/images/bari4.gif create mode 100644 RGraph/images/bari4.png create mode 100644 RGraph/images/bari8.gif create mode 100644 RGraph/images/bari8.png create mode 100644 RGraph/images/barj1.gif create mode 100644 RGraph/images/barj1.png create mode 100644 RGraph/images/barj16.gif create mode 100644 RGraph/images/barj16.png create mode 100644 RGraph/images/barj2.gif create mode 100644 RGraph/images/barj2.png create mode 100644 RGraph/images/barj32.gif create mode 100644 RGraph/images/barj32.png create mode 100644 RGraph/images/barj4.gif create mode 100644 RGraph/images/barj4.png create mode 100644 RGraph/images/barj8.gif create mode 100644 RGraph/images/barj8.png create mode 100644 RGraph/images/bn.business.png create mode 100644 RGraph/images/bn.personal.png create mode 100644 RGraph/images/border-radius.png create mode 100644 RGraph/images/buy.png create mode 100644 RGraph/images/buzz.png create mode 100644 RGraph/images/chrome_logo.png create mode 100644 RGraph/images/coins.jpg create mode 100644 RGraph/images/context.png create mode 100644 RGraph/images/delicious.png create mode 100644 RGraph/images/download-beta-sml.png create mode 100644 RGraph/images/download-beta.png create mode 100644 RGraph/images/download-stable-sml.png create mode 100644 RGraph/images/download-stable.png create mode 100644 RGraph/images/download.png create mode 100644 RGraph/images/facebook.png create mode 100644 RGraph/images/favicon.ico create mode 100644 RGraph/images/favicon.png create mode 100644 RGraph/images/friendfeed.png create mode 100644 RGraph/images/googlegroups.png create mode 100644 RGraph/images/html2.gif create mode 100644 RGraph/images/html2.png create mode 100644 RGraph/images/icons_combined.png create mode 100644 RGraph/images/introspection.png create mode 100644 RGraph/images/logo.png create mode 100644 RGraph/images/merry-christmas-snowman.png create mode 100644 RGraph/images/png.icon.png create mode 100644 RGraph/images/reddit.png create mode 100644 RGraph/images/rss.png create mode 100644 RGraph/images/rss_big.png create mode 100644 RGraph/images/sq0.png create mode 100644 RGraph/images/sq1.png create mode 100644 RGraph/images/sq2.png create mode 100644 RGraph/images/sq3.png create mode 100644 RGraph/images/sq4.png create mode 100644 RGraph/images/sq5.png create mode 100644 RGraph/images/sq6.png create mode 100644 RGraph/images/sq7.png create mode 100644 RGraph/images/sq8.png create mode 100644 RGraph/images/sq9.png create mode 100644 RGraph/images/sqg.png create mode 100644 RGraph/images/structure.png create mode 100644 RGraph/images/stumble.png create mode 100644 RGraph/images/twitter.png create mode 100644 RGraph/images/unicef.png create mode 100644 RGraph/index.html create mode 100644 RGraph/scripts/minify create mode 100644 alert_status.php create mode 100644 beth.txt create mode 100644 check_climate_status.php create mode 100644 check_isy99i_occupancy_status.php create mode 100644 check_isy99i_status.php create mode 100644 check_power_status.php create mode 100644 css/ModalDialog.css create mode 100644 css/common.css create mode 100644 css/website.css create mode 100644 excanvas/EXCANVAS-LICENSE.txt create mode 100644 excanvas/HTACCESS-SAMPLE create mode 100644 excanvas/excanvas.compressed.js create mode 100644 excanvas/excanvas.original.js create mode 100644 groceries.html create mode 100644 icons/button_Off.png create mode 100644 icons/button_On.png create mode 100644 icons/left-arrow.png create mode 100644 icons/light.png create mode 100644 icons/music.png create mode 100644 icons/right-arrow.png create mode 100644 icons/weather.png create mode 100644 icons/weather/Chance_Of_Showers.png create mode 100644 icons/weather/Clear.png create mode 100644 icons/weather/Cloudy.png create mode 100644 icons/weather/Cloudy_Period.png create mode 100644 icons/weather/Cloudy_With_Dizzle.png create mode 100644 icons/weather/Few_Flurries.png create mode 100644 icons/weather/Few_Flurries_Night.png create mode 100644 icons/weather/Few_Showers.png create mode 100644 icons/weather/Flurries.png create mode 100644 icons/weather/Fog.png create mode 100644 icons/weather/Folder_Extra.png create mode 100644 icons/weather/Freezing_Rain.png create mode 100644 icons/weather/Mostly_Sunny.png create mode 100644 icons/weather/Note_Extra.png create mode 100644 icons/weather/Overcast.png create mode 100644 icons/weather/Partly cloudy.png create mode 100644 icons/weather/Rain.png create mode 100644 icons/weather/Rain_Or_Snow.png create mode 100644 icons/weather/Risk_Of_Thundershowers.png create mode 100644 icons/weather/Snow.png create mode 100644 icons/weather/Sunny.png create mode 100644 icons/weather/Thunder_Showers.png create mode 100644 icons/weather/Thunderstorms.png create mode 100644 icons/weather/Wet_Flurries.png create mode 100644 icons/weather/Wet_Flurries_Night.png create mode 100755 images/bg.jpg create mode 100755 images/body-box-bottom.png create mode 100755 images/body-box-repeatablebody.png create mode 100755 images/body-box-top.png create mode 100755 images/bottom-controls-off.jpg create mode 100755 images/bottom-controls-on.jpg create mode 100755 images/bottom-controls-repeatablebar.jpg create mode 100644 images/cameras-off.png create mode 100644 images/cameras-on.png create mode 100644 images/climate-off.png create mode 100644 images/climate-on.png create mode 100644 images/groceries-off.png create mode 100644 images/groceries-on.png create mode 100755 images/header-camera.png create mode 100755 images/header-climate.png create mode 100755 images/header-groceries.png create mode 100755 images/header-lighting.png create mode 100755 images/header-news.png create mode 100755 images/header-power.png create mode 100755 images/header-recipes.png create mode 100755 images/header-repeater.png create mode 100755 images/header-security.png create mode 100755 images/header-thejukebox.png create mode 100755 images/header-traffic.png create mode 100755 images/header-weather.png create mode 100755 images/header.png create mode 100644 images/home-off.png create mode 100644 images/home-on.png create mode 100755 images/icon-barchart.png create mode 100755 images/icon-sliders.png create mode 100644 images/lighting-off.png create mode 100644 images/lighting-on.png create mode 100644 images/music-off.png create mode 100644 images/music-on.png create mode 100644 images/news-off.png create mode 100644 images/news-on.png create mode 100644 images/power-off.png create mode 100644 images/power-on.png create mode 100644 images/receipes-off.png create mode 100644 images/receipes-on.png create mode 100644 images/security-off.png create mode 100644 images/security-on.png create mode 100755 images/slider-off.png create mode 100755 images/slider-on.png create mode 100644 images/traffic-off.png create mode 100644 images/traffic-on.png create mode 100644 images/weather-off.png create mode 100644 images/weather-on.png create mode 100644 includes.php create mode 100644 index.php create mode 100644 jukebox.php create mode 100644 left-arrow.html create mode 100644 libraries/RGraph.bar.js create mode 100644 libraries/RGraph.bipolar.js create mode 100644 libraries/RGraph.common.adjusting.js create mode 100644 libraries/RGraph.common.annotate.js create mode 100644 libraries/RGraph.common.context.js create mode 100644 libraries/RGraph.common.core.js create mode 100644 libraries/RGraph.common.resizing.js create mode 100644 libraries/RGraph.common.tooltips.js create mode 100644 libraries/RGraph.common.zoom.js create mode 100644 libraries/RGraph.funnel.js create mode 100644 libraries/RGraph.gantt.js create mode 100644 libraries/RGraph.hbar.js create mode 100644 libraries/RGraph.hprogress.js create mode 100644 libraries/RGraph.led.js create mode 100644 libraries/RGraph.line.js create mode 100644 libraries/RGraph.meter.js create mode 100644 libraries/RGraph.modaldialog.js create mode 100644 libraries/RGraph.odo.js create mode 100644 libraries/RGraph.pie.js create mode 100644 libraries/RGraph.rose.js create mode 100644 libraries/RGraph.rscatter.js create mode 100644 libraries/RGraph.scatter.js create mode 100644 libraries/RGraph.skeleton.js create mode 100644 libraries/RGraph.tradar.js create mode 100644 libraries/RGraph.vprogress.js create mode 100644 menu.html create mode 100644 middle.html create mode 100644 news.html create mode 100644 news.php create mode 100644 other_icons/Security.jpg create mode 100644 other_icons/audio.jpg create mode 100644 other_icons/audio.png create mode 100644 other_icons/cameras.jpg create mode 100644 other_icons/cameras.png create mode 100644 other_icons/climate.jpg create mode 100644 other_icons/climate.png create mode 100644 other_icons/events.jpg create mode 100644 other_icons/events.png create mode 100644 other_icons/lighting.jpg create mode 100644 other_icons/lighting.png create mode 100644 other_icons/power.jpg create mode 100644 other_icons/power.png create mode 100644 other_icons/status.jpg create mode 100644 other_icons/status.png create mode 100644 pxweather.class.php create mode 100755 pxweather/LICENSE.txt create mode 100755 pxweather/README.txt create mode 100755 pxweather/pxweather.class.php create mode 100755 pxweather/xmlize-php4.inc.php create mode 100755 pxweather/xmlize-php5.inc.php create mode 100644 right-arrow.html create mode 100644 rotate-weather.php create mode 100644 russ.txt create mode 100644 security1.html create mode 100644 set_climate_status.php create mode 100644 set_isy99i_status.php create mode 100644 set_summon_status.php create mode 100644 thermometer-blank-black.png create mode 100644 thermometer-blank.png create mode 100644 thermometer.php create mode 100644 title_status.php create mode 100644 top.html create mode 100644 traffic-iframe.html create mode 100644 traffic.html create mode 100644 weather-footer.php create mode 100644 weather-meter.php create mode 100644 weather-odometer.php create mode 100644 weather.php create mode 100644 weather1-speed.php create mode 100644 weather1-temp.php create mode 100644 weather1.js create mode 100644 weather1.php create mode 100644 weather2.js create mode 100644 weather2.php create mode 100644 weather3.js create mode 100644 weather3.php create mode 100644 weather4.js create mode 100644 weather4.php create mode 100644 weather5.js create mode 100644 weather5.php create mode 100644 weather6.js create mode 100644 weather6.php create mode 100644 xml2array.php create mode 100644 xmlize-php5.inc.php diff --git a/README b/README new file mode 100644 index 0000000..6a24292 --- /dev/null +++ b/README @@ -0,0 +1,45 @@ +############################################################################### +# The MIT License (MIT) +# Copyright (c) Russell Handorf +# +# 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. +# +############################################################################### + +I've been building a home automation solution over the years. The code within is built to help manage these systems. + +The graphics were generated by Mike Anthony at http://www.mejadesign.com/. They are to be included for this project. + +Hardware: +-Insteon +-Elk M1 Gold +-TED - The Energy Detector + +Software: +-Zoneminder +-Asterisk +-Wview + +I'm leaving out some code for now for you to edit for your own source. Once I lock up mine, I'll upload it; some stuff is just very specific. I've set some account defaults for you, specifically admin/admin in the ISY and zoneminder. There isnt a central config yet... yet. + +Edit your /etc/hosts to be +[IP] isy99 +[IP] zoneminder +[IP] TED +[IP] weather diff --git a/RGraph/LICENSE.txt b/RGraph/LICENSE.txt new file mode 100644 index 0000000..2a4bc6f --- /dev/null +++ b/RGraph/LICENSE.txt @@ -0,0 +1,93 @@ +THE RGRAPH LICENSE VERSION 1.5.4 + +Everyone is permitted to copy and distribute this license document. + +This license applies to any software originating from the www.rgraph.net website. +Such software is herein referred to as the Software. This license covers +modification and distribution of the Software, use of third-party application +programs based on the Software, and development of software which uses the +Software. Note that ExCanvas is covered by the Apache license. + + +SUMMARY + + +A summary of the license is that non-commercial use of the Software is free, +whilst for commercial use there is a one-time fee of £49 (GBP). + + + +GRANTED RIGHTS + + +1. You are granted the non-exclusive rights set forth in this license + provided you agree to and comply with any and all conditions in + this license. Whole or partial distribution of the Software, + signifies acceptance of this license. + + +2. You may copy and distribute the Software in unmodified form + provided that the entire package, including - but not restricted to + - copyright, trademark notices and disclaimers, as released by the + initial developer of the Software, is distributed. See clause (3) + regarding the inclusion of this license document with your software. + + +3. You may develop application programs, reusable components and other + software items that use the original or modified versions of the + Software. You may distribute these programs or components as long + as this license is distributed along with the Software. If you have + purchased an RGraph license you do not need to include this license + document with your software. + + +4. For commercial use you are required to buy a license from the copyright + holder. A commercial license permits you to use any code you wish that + originated from the RGraph website (www.rgraph.net) and also the + PHPGuru website (www.phpguru.org). This license is £49 (UK pounds). + Commercial use incorporates applications, websites (regardless of + whether they sell products or services or simply promote them), + intranets and use in offline materials. + + +5. Non-commercial use (eg personal, charity and educational) is permitted. + Please link back to the RGraph website. Example code as follows: + + + RGraph: HTML5 canvas graph library + + + Alternatively, if you don't wish to link to the RGraph website, you can + buy an RGraph license and you won't need to. + + +LIMITATIONS OF LIABILITY + +In no event shall the initial developers or copyright holders be +liable for any damages whatsoever, including - but not restricted to +- lost revenue or profits or other direct, indirect, special, +incidental or consequential damages, even if they have been advised +of the possibility of such damages, except to the extent invariable +law, if any, provides otherwise. + + +NO WARRANTY + +The Software and this license document are provided AS IS with NO +WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +CHOICE OF LAW + +This license is governed by the Laws of England. Disputes shall be +settled by Chelmsford town court. + + +QUESTIONS + +Any questions or queries about this license or its extent should +be directed to licensing@rgraph.net + + + diff --git a/RGraph/css/ModalDialog.css b/RGraph/css/ModalDialog.css new file mode 100644 index 0000000..c9c339c --- /dev/null +++ b/RGraph/css/ModalDialog.css @@ -0,0 +1,90 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + + /** + * Modal Dialog + */ + .modalBg { + position: absolute; + top: 0px; + left: 0px; + filter: Alpha(Opacity=50); + -moz-opacity: 0.5; + background-color: #ddd; + visibility: hidden; + width: expression(document.body.clientWidth); + height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight); + z-index: 100; + } + + .modalDialog { + position: absolute; + top: 0px; + left: 0px; + visibility: hidden; + z-index: 101; + background-color: white; + top: expression(document.body.clientHeight / 2 - this.offsetHeight / 2); + left: expression(document.body.clientWidth / 2 - this.offsetWidth / 2); + border: 1px solid #777; + border-top: 0; + padding: 20px; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + + .modalDialog .modalDialogHeader { + margin:0; + padding: 0px; + color: #333; + font-weight: bold; + background-color: #ccc; + border: 1px solid #989898; + position: absolute; + top: 0px; + left: -1px; + height: 7px; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius-bottomleft: 0; + -moz-border-radius-bottomright: 0; + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 0; + } + + .modalShadow { + position: absolute; + background-color: black; + top: 0px; + left: 0px; + z-index: 99; + top: expression(document.body.clientHeight / 2 - this.offsetHeight / 2); + left: expression(document.body.clientWidth / 2 - this.offsetWidth / 2); + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + opacity: 0.5; + } + + /** + * This is not part of the core Modal Dialog styles, instead it's just so that the dialog looks + * respectable. + */ + h4 { + font-family: Verdana, Arial; + padding-top: 10px; + } \ No newline at end of file diff --git a/RGraph/css/common.css b/RGraph/css/common.css new file mode 100644 index 0000000..cb2b287 --- /dev/null +++ b/RGraph/css/common.css @@ -0,0 +1,297 @@ +@font-face { + font-family: Delicious; + src: url('/Delicious-Roman.otf') +} + +/** +* Various +*/ +body { + margin: 0px; +} + +a { + text-decoration: none; +} + +code { + background-color: #dedede; + border: 1px dashed #aaaaaa; + padding: 3px; + display: block; + font-family: Monospace; +} + + +/** +* Datagrid stuff +*/ +table.datagrid { + border-collapse: collapse; + margin-left: 30px; +} + +table.datagrid th { + background-color: #ccc; + border: 1px solid #aaa; + padding: 2px; +} + +table.datagrid tr { + background-color: #ddd; +} + +table.datagrid tr.oddrow { + background-color: #eee; +} + +table.datagrid td { + border: 1px solid #aaa; + padding: 3px; +} + + +/** +* Master div +*/ +.master { + font-family: Georgia; +} + + +/** +* Header section +*/ +.header { + margin-right: 10px; + letter-spacing: 2px; + background-image: url(/images/hdrbg.jpg); + margin-left: 10px; +} + +.header h1 { + margin-top: 0px; +} + +.tagline { + font-size: 8pt; + position: relative; + top: -15px; + left: 15px; + letter-spacing: 0px; +} + + +/** +* Top nav +*/ +.topnav { + color: white; + background-color: #314657; /* Old */ + background-color: #2D4B33; + padding: 1px; + padding-left: 10px; +} + +.topnav a { + color: white; +} + + +/** +* Left nav +*/ +.leftnav, +.searchbox { + width: 180px; + color: black; + background-color: #FF5A18; + margin-left: 5px; + margin-top: 10px; + padding: 10px; + padding-top: 0; + padding-bottom: 0; + padding: expression('10px'); + border: 1px solid #B33E11; +} + +.leftnav { + box-shadow: 3px 3px 3px #aaa; + border-radius: 5px; + -moz-box-shadow: 3px 3px 3px #aaa; + -webkit-box-shadow: 3px 3px 3px #aaa; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + width: 180px; + float: left; + hmargin: 5px; +} + +.leftnav h4 { + border-bottom: 1px solid black; +} +.leftnav a { + color: black; +} + +.leftnav ul { + margin-left: -20px; + margin-left: expression('20px'); + list-style-type: square; +} + + +/** +* Main body section +*/ +.mainbody { + margin-left: 220px; +} + +.borderedTable table { + border-collapse: collapse; +} + +.borderedTable th { + background-color: #dddddd; + border: 1px solid #aaaaaa; + font-size: 70%; + padding-left: 3px; + padding-right: 3px; +} + +.borderedTable td { + vertical-align: top; + font-size: 70%; + border: 1px solid #dddddd; +} + +.newsitem { + margin-bottom: 25px; +} + +.newsitem h2, +.newsitem h1 { + display: inline; +} + +.newsitem .date { + font-size: 70%; +} + +p.firstLetter:first-letter { + font-size: 200%; + font-style: italic; + font-weight: bold; + float: left; + padding-right: 3px; +} + +.newsitem p.update { + background-color: #efefef; + border: 1px dashed black; + padding: 5px; +} + + +/** +* Comments +*/ +.comment { + padding: 5px; + margin-bottom: 20px; + font-size: 80%; + background-color: #efefef; + border: 1px dashed #cccccc; +} + +.comment .body { + margin-top: 5px; + padding-left: 7px; +} + +.comment .quoteLink { + text-align: right; + font-size: 90%; +} + + +/** +* Errors +*/ +.error { + color: red; + font-style: italic; +} + + +/** +* Copyright text +*/ +.copyright { + text-align: right; + font-size: 75%; +} + + +/** +* Admin page +*/ +.adminPage table { + font-family: Verdana; + font-size: 10pt; +} + +.adminPage th { + background-color: #dddddd; +} + + +/** +* Tools page +*/ +#toolsPage th, +#toolsPage td { +} + +#toolsPage th { + font-weight: bold; + text-align: right; + white-space: nowrap; + vertical-align: top; + background-color: #ffffcc; +} + +#toolsPage textarea { + height: 200px; + width: 800px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#ffffff, endColorstr=#ffffcc); +} + +#shortcuts th { + +} + +#shortcuts th { + text-align: left; + background-color: #ededed; + padding: 2px; +} + +/** +* Download header/footer +*/ +div#download pre, +div#download pre a { + +} + +/** +* Code +*/ +div.boxout, +pre.code { + border: 2px dashed gray; + padding: 3px; + background-color: #eee; +} \ No newline at end of file diff --git a/RGraph/css/website.css b/RGraph/css/website.css new file mode 100644 index 0000000..827b5fb --- /dev/null +++ b/RGraph/css/website.css @@ -0,0 +1,253 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + +body { + padding-top: 10px; + font-family: Georgia, Arial, Sans-Serif; +} + +pre#code, +code { + display: block; + border: 1px solid #aaa; + padding: 5px; + background-color: #ddd; +} + +#breadcrumb, +#logo { + border: 2px black solid; + background-color: #eee; + padding: 3px; + top: 0; + right: 0; + position: absolute; + margin: 2px; + opacity: 0.8; +} +#breadcrumb a, +#logo a { + text-decoration: none; +} + +th { + text-align: left; + border: 1px solid gray; + background-color: #ddd; + padding: 3px; + vertical-align: top; +} + +td { + vertical-align: top; +} + +ol li { + margin-top: 20px; +} + +ol#implementation li code { + margin-top: 5px; +} + +td.description { + background-color: #eee; + padding: 3px; + border: 1px solid #ddd; +} + +td.chart { + text-align: center; +} + +.example_boxout { + background-color: #eee; + padding: 3px; + border: 1px solid #aaa; +} + +.code { + padding: 5px; + background-color: #eee; + border: 2px dashed gray +} + +/** +* This is semi-transparent box in the top left corner +*/ +div#devtag { + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: #999 3px 3px 3px; + -moz-box-shadow: #999 3px 3px 3px; + box-shadow: #999 3px 3px 3px; + filter: progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135); + position: fixed; + top: 2px; + right: 2px; + width: 145px; + border: 2px solid black; + text-align: center; + font-weight: bold; + font-family: Arial; + background-color: #fdd; +} + +div#devtag a { + font-size: 10px; + text-decoration: none; + color: blue; + opacity: 1; +} + +/** +* This overrides something defined earlier +*/ +ol#colors li { + margin: 0; +} + +/** +* styles lists +*/ +div.list-item { + width: 220px; + display: inline-block; +} + +div.list-item.label { + width: 170px; +} + +legend { + background-color: #efefef; + border: 1px solid #75736e; +} + +body#licensing span { + font-size: 120%; +} + +/** +* The yellow warning box on the front page +*/ +div.warning { + border: 1px solid black; + text-align: center; + background-color: #ffa; + padding: 5px; + margin-top: 5px; + border-radius: 15px; + -moz-border-radius: 15px; + -webkit-border-radius: 15px; + -webkit-box-shadow: #aaa 1px 1px 15px; + -moz-box-shadow: #aaa 1px 1px 15px; + box-shadow: #aaa 1px 1px 15px; + filter: progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135); + z-index: 98; +} + +div.canvasfallback { + border: 2px dashed red; + background-color: #fee; + width: 475px; + height: 150px; + text-align: center; + padding-top: 50px; +} + +/** +* The title "bar" +*/ +div#title { +} + +div#title div#image { + float: left; + margin-right: 15px; +} + +div#title div#text { + padding-top: 5px; + margin-left: 70px; +} + + +div.warning p { + text-align: center; + margin-top: 5px; + margin-bottom: 5px; + font-weight: bold; +} + + +div.description { + border: 1px dashed gray; + background-color: #eee; + font-size: 75%; + padding: 3px; +} + +div#social { + display: inline; + display: inline-block; +} + + +/*************************************************************************************** +* * +* RGraph CSS classes. * +* * +* These allow you to customise how tooltips and context menus will appear. To override * +* the CSS defined in the graph scripts, you may need to use " ! important" like so: * +* * +* font-weight: bold ! important * +* * +* You don't always need to use this, only if you're trying to override something which * +* the script sets. * +* * +***************************************************************************************/ + +.RGraph_png { +} + +.RGraph_tooltip { +} + +.RGraph_contextmenu { +} + +.RGraph_contextmenu_background { +} + +.RGraph_contextmenu_item { +} + +.RGraph_zoom_window { +} + +.RGraph_zoomed_canvas { +} + +.ModalDialog_background { +} + +.ModalDialog_dialog { +} + +.ModalDialog_topbar { +} \ No newline at end of file diff --git a/RGraph/docs/.BC.txt b/RGraph/docs/.BC.txt new file mode 100644 index 0000000..ede1913 --- /dev/null +++ b/RGraph/docs/.BC.txt @@ -0,0 +1,101 @@ + + Backwards compatibility breaks and advisories + =============================================== + + +---------------------------------------------------------------------------------------+ + o [24-12-2010] | Stable release | + +---------------------------------------------------------------------------------------+ + + o [04-12-2010] chart.key.vpos is now silently converted to chart.key.position.y (note that these two properies behave slightly + differently - chart.key.position.y is an absolute coordinate). ALSO; the key has been rewritten, so check that + your graphs are working as you expect + o [04-12-2010] The HBar labels (from chart.labels.above) now have an extra property (chart.labels.above.decimals) which controls + how many decimals are shown. This defaults to 0, and as a result you may need to set this if you're expecting decimals. + + +---------------------------------------------------------------------------------------+ + o [27-11-2010] | Stable release | + +---------------------------------------------------------------------------------------+ + + o [20-11-2010] For the line/bar/scatter, when the X axis is at the bottom and there is a background bar with a + negative start (or it results in a negative end value), you now get a warning. + o [13-11-2010] All line chart labels are now shown, regardless of how many points on the line there are. + o [06-11-2010] The HBar and Scatter have had their scaled handling changed slightly - now if you specify a maximum Y value, + that is what is used. + o [06-11-2010] The API function RGraph.getSCale(max, obj) now takes two arguments - the maximum value and the graph object. + + +---------------------------------------------------------------------------------------+ + o [30-10-2010] | Stable release | + +---------------------------------------------------------------------------------------+ + + o [30-10-2010] The Scatter chart can now only have 1/3/5 labels + o [30-10-2010] The Line chart can now only have 1/3/5 labels + o [23-10-2010] The Bar chart can now only have 1/3/5/10 labels + o [23-10-2010] The default for chart.scale.decimals has changed, as such you may need to specify this: + myScatter.Set('chart.scale.decimals', 0); + o [09-10-2010] Scatter chart ticksize has changed behaviour slightly, you therefore may need to alter it slightly. + + +---------------------------------------------------------------------------------------+ + o [25-09-2010] | Stable release | + +---------------------------------------------------------------------------------------+ + + o [18-09-2010] For IE9 compatibility purposes, the IE8 DirectX shadow has been removed from the ModalDialog. This only affects + MSIE8. The background is still semi-opaque. + o [18-09-2010] The common function RGraph.isIE9() has changed to RGraph.isIE9up(). The old one will continue to work, but + not indefinitely. + o [11-09-2010] The Odometer properties chart.units.pre and chart.units.post have now changed to chart.value.units.pre + and chart.value.units.post. The properties chart.units.post and chart.units.pre are now used for the main + labels. + o [04-09-2010] HBar and Pie charts have been moved to DOM2 event registration for tooltips + o [04-09-2010] The RGraph.number_format() function has had its argument list changed + o [04-09-2010] Now that RGraph is moving to DOM2 event handlers, tooltips will be incompatible with IE8 + + +---------------------------------------------------------------------------------------+ + o [28-08-2010] | Stable release | + +---------------------------------------------------------------------------------------+ + + o [28-08-2010] Removed option to have the labels on the outside of a Meter. Now they're always on the inside of the Meter + and there's always 11 of them (including zero) + o [14-08-2010] Changed the HBar property chart.strokecolor to chart.strokestyle + o [07-08-2010] The Odometer property chart.needle.thickness has been changed to chart.needle.width. Work has been done on the + needle head. + o [07-08-2010] Progress bar has now been split into two different graph types: + o HProgress + o VProgress + o [07-08-2010] Progress bar property chart.color is now chart.colors, and should be an array + o [07-08-2010] Changed default Bipolar colors to just one - green + + +---------------------------------------------------------------------------------------+ + o [31-07-2010] | Stable release | + +---------------------------------------------------------------------------------------+ + + o [17-07-2010] Stepped line charts and their tickmarks have been marginally altered. No final tickmark is now shown (it looks + odd being isolated) + o [17-07-2010] Changed the Odo chart.needle.style to chart.needle.color + o [17-07-2010] The Odo properties chart.start, chart.end and chart.value have all been changed to internal properties: + obj.start, obj.end and obj.value + o [09-07-2010] With the Odometer the old property chart.needle.style has been renamed to be chart.needle.color + o [09-07-2010] The Progress bar has had it's properties chart.max and chart.value changed to class properties, this means + that if you want to make use of these, you will now need to use myProgress.value and myProgress.max. + myProgress being the name of your graph object. + + +---------------------------------------------------------------------------------------+ + o [26-06-2010] | Stable release | + +---------------------------------------------------------------------------------------+ + + o [08-05-2010] The Rose charts "chart.labels" property is now different to the "chart.key" property + o [01-05-2010] The Donut chart is now a variant of the Pie chart (chart.variant = donut) + o [24-04-2010] The radar chart has been renamed to Rose. The library is now called RGraph.rose.js and the constructor has + been renamed. It has also been prettied up marginally and labels have been added. + o [17-04-2010] All charts have had their property "chart.tooltip.effect" renamed to "chart.tooltips.effect". + The Scatter chart has also had its property "chart.tooltip.hotspot" renamed to "chart.tooltips.hotspot" + o [17-04-2010] Default chart.tooltips bar chart property has changed from an empty array to null. + o [17-04-2010] The RGraph.common.js library has now been split into 5 separate files because it had + become far too large. You can read the new implementation details here: + http://www.rgraph.net/docs/index.html#implementation + o [10-04-2010] The "coords" arrays (for each object) have been unified. Now you no longer need to take + into account the margins. What you get in the coords arrays are as they are used on the + graph. + + +---------------------------------------------------------------------------------------+ + o [27-03-2010] | Initial stable release | + +---------------------------------------------------------------------------------------+ \ No newline at end of file diff --git a/RGraph/docs/.CHANGELOG.txt b/RGraph/docs/.CHANGELOG.txt new file mode 100644 index 0000000..34580b6 --- /dev/null +++ b/RGraph/docs/.CHANGELOG.txt @@ -0,0 +1,1277 @@ + 24th December 2010 (STABLE) + ================== + o [ANNOTATING] Annotating has been changed to allow annotating to occur in the gutter + + 18th December 2010 + ================== + o [MSIE] MSIE 9 now uses the double click event to trigger the context menu + o [ZOOM] Added a note about making the zoom in thumdnail mode circular: + http://www.rgraph.net/docs/zoom.html#thumbnail + + 11th December 2010 + ================== + o [API] Added pointer, in the docs, for how to add text to your charts + o [BAR] The Bar chart now converts null values to zero + o [BAR] You can now specify a textual scale with chart.ylabels.specific + o [GANTT] Fixed background bars when specifying an xmin + o [HPROGRESS] Labels can now be on top of the bar as well as the bottom + o [LINE] You can now specify a textual scale with chart.ylabels.specific + o [MISC] Added the RGraph.SetConfig() function - http://www.rgraph.net/docs/setconfig.html + o [MISC] Added chart.title.background to graph types that use a title + o [PIE] Added chart.highlight.style.2d.color - default is a semi-transparent white color + o [PIE] Added chart.tooltips.event + o [SCATTER] Crosshairs readout now works when the X axis is in the center + + 4th December 2010 + ================= + o [GANTT] Added chart.xmin (default is 0) + o [HBAR] Added chart.labels.above.decimals, defaulting to 0. You may need to set this to the number of desired decimals + if you're expecting decimals + o [LICENSING] If you prefer you can now use PayPal instead of Google Checkout to buy an RGraph license: + http://www.rgraph.net/docs/licensing.html#paypal + o [LINE] Fixed a bug with null points still showing tooltips + o [MISC] The key handling has been rewritten. There is now a documentation page about keys: + http://www.rgraph.net/docs/keys.html + o [MISC] Added default key properties to all relevant graph types - the key has been completely rewritten and as such, + you should check your graphs are as you expect. You may neeed to slightly adjust your key coordinates for example. + o [SCATTER] Added option to have vertical bars (much like the horizontal bars option) + o [SKELETON] Added more default properties + o [VPROGRESS] You can now position the labels on the left of the chart instead of the (default) right. + + 27th November 2010 (STABLE) + ================== + o [BAR] When showing 10 Y labels, chart.scale.decimals is respected + o [DOCS] Add an example showing dynamic updating + o [DOCS] Added animation example using jQuery + o [LINE] When showing 10 Y labels, chart.scale.decimals is respected + o [MISC] Improved the jQuery animation example + o [MISC] Removed the "functions as colors" option - this may re-added at a later date + o [SCATTER] When showing 10 Y labels, chart.scale.decimals is respected + o [SKEL] Added lots more default default properties and functionality that common RGraph functionality + uses, for example: chart.resizable. + + 20th November 2010 + ================== + o [API] Documented RGraph.background.Draw(). + o [DOCS] Added note to AJAX section about types + o [DOCS] Added skeleton object which can be used to ease creating new graph types + o [DOCS] Added note to misc docs about debugging your graphs + o [LINE] Fixed line chart tooltips as separate arguments + o [MISC] Minor adjustments to placement and borders + o [MISC] For the line/bar/scatter, when the X axis is at the bottom and there is a background bar with a + negative start (or it results in a negative end value), you now get a warning. + o [MISC] Added animation example using jQuery + o [MSIE] Changed instances of document.all to RGraph.isIE8() + o [RESIZING] Tweaked the positioning a little, so now nothing should move when you resize a canvas + o [SKEL] Added a skeleton file, which can be used as a base when creating new RGraph libraries. + + 13th November 2010 + ================== + o [API] Added RGraph.array_shift() function (removes an element from the beginning of an array) + o [LINE] Added chart.labels.above and chart.labels.above.size (default is 8) + o [LINE] All chart labels are now shown, regardless of how many points on the line there are. + o [LINE] Sets of line points can now be given as one big multi-dimensional array. This may make it easier to use in AJAX, eg: + http://dev.rgraph.net/tests/line.arguments.html + o [LINE] In Google Chrome, the shadow fix is applied by default. An option exists to enable you to turn this off: chart.chromefix + In a few rare cases you will need to turn off shadow blurring (chart.shadow.blur=0) + o [MISC] Added more options for in-graph labels. See http://www.rgraph.net/docs/ingraph.html + o [MISC] Added note about AJAX and types + o [VPROGRESS] Added chart.tooltips.coords.adjust + o [VPROGRESS] Added chart.min + o [VPROGRESS] Added chart.labels.count, chart.min, chart.scale.decimals + + 6th November 2010 + ================= + o [API] RGraph.getScale() now takes the graph object as the second argument + o [BAR] Added chart.labels.above.decimals, defaulting to 0 + o [BAR] Added chart.labels.above.size, which if specified is used as the font size. An example of this and the above change is + here: http://dev.rgraph.net/tests/above.bar.html + o [BIPOLAR] Added chart.gutter.center, which controls the space where the labels are + O [BIPOLAR] Added chart.scale.round + o [DOCS] Added note to API docs about references available + o [HBAR] Added chart.scale.decimals + o [HBAR] Added chart.scale.round + o [HPROGRESS] Added chart.min, for specifying a minimum value and chart.scale.decimals + o [LINE] Y labels can once again be 1/3/5/10 + o [LINE] Added chart.scale.round + o [LINE] chart.outofbounds is now usable in conjunction with chart.ymax + o [LINE] Added chart.chromefix + o [RESIZE] Resize now sets the placeholder DIVs 'position' CSS value as inline-block, thus reducing page re-organisation + o [ROSE] Added chart.scale.decimals + o [ROSE] Added chart.ymax + o [ROSE] Added chart.ymin (There's an example here: http://dev.rgraph.net/tests/rose.ymin.html + o [RSCATTER] Added chart.scale.decimals // If you use the Rscatter, please test this with your graph(s) + o [RSCATTER] Added chart.scale.round // If you use the Rscatter, please test this with your graph(s) + o [RSCATTER] Added chart.ymin // If you use the Rscatter, please test this with your graph(s) + o [SCATTER] Y labels can once again be 1/3/5/10 + o [SCATTER] Added chart.scale.decimals + o [SCATTER] Added chart.scale.round + o [SCATTER] Scatter chart, translating and crosshairs now work when you tell RGraph how you've translated using + chart.tooltips.coords.adjust + o [SCALE] Added chart.scale.round to: bar, bi-polar, line, rscatter, rose, scatter, tradar This means that scales produced are + rounded up, producing rounder values + o [SCALE] Re-added 10 Y labels to Line/Scatter. This may be best used In conjunction with chart.scale.round + o [TRADAR] Added chart.scale.round + + 30th October 2010 (STABLE) + ================= + o [DOCS] The combination example has been changed and extended. It now shows Pie charts in the tooltips, + which can be clicked on. + o [DOCS] Added note about using RGraph.showPNG() without a context menu. + o [DOCS] RGraph.showPNG() has had it's parameter list changed: http://www.rgraph.net/docs/api.html + o [API] Added fix to crosshairs when coordinates are used in conjunction with an X minimum value + + + 23rd October 2010 + ================= + + Important: + The Line (and Scatter chart) chart have been PARTIALLY REVERTED, meaning that the number of labels is again a + choice between 1/3/5. The option to have 10 labels will be re-added, but for positive charts only, and + probably for scales with maximum values over 10. + + o [API] The RGraph.showPNG() function can now accept the canvas to use as an (optional) argument, + allowing you to use the RGraph.showPNG() function with an image, eg: + http://www.rgraph.net/examples/tradar.html (1st graph) + o [BAR] Bar chart can now only have 1/3/5/10 labels + o [GANTT] Borders are now a little thinner (and less blurry) + o [KEY] Rounded key corners now lives behind an option: chart.key.rounded (default is false), also documented this + o [KEY] Filled keys now only cover the key with one layer of color - so transparency works better + o [PNG] URL is now selected by default + o [SCATTER] Box plot coords bug has been corrected + o [SCATTER] The default for chart.scale.decimals has been changed fr0m 0 (zero) to null. You may need to set this now + with: myScatter.Set('chart.scale.decimals', 0); + + 16th October 2010 + ================= + o [LINE] Y axis can now have an arbitrary number of labels: http://dev.rgraph.net/tests/ymin.html + o [LINE] Made addition so that in Chrome a 1px linewidth is changed to 1.01 + o [MISC] Corners on the key (in graph mode) are now curvy + o [MISC] RGraph.showPNG() now shows the data: URL to the image and makes it easy to copy it to the clipboard + + 9th October 2010 + ================ + o [LINE] Changed decimal handling - you may need to specify this: myLine.Set('chart.scale.decimals', 0); + o [LINE] Added chart.outofbounds (default is false) + o [LINE] Added obj.getPoint(e) method which simplifies getting the pertinent point on the line + chart in events (eg the onmousemove event, and now the Line chart uses it) + o [LINE] Line charts can now have custom tickmarks + o [SCATTER] Added facility for custom tickmarks + o [WEBSITE] Fixed favicon path + + 1st October 2010 + ================ + + In October, 25% of all license fees will be donated to Unicef - the International charity for children + + o [BAR] Added .getBar() method. This allows you to easily get the focused/selected bar. There is an example usage here: + o [DOCS] Documentation is no longer dynamic + o [FUNNEL] Shadows can now go upwards (ie any x/y offset is feasible) + o [FUNNEL] Converted this chart type to DOM2 for tooltips + o [GANTT] This chart has been moved to DOM2 for tooltips + o [HPROGRESS] This chart has been moved to DOM2 for tooltips + o [MISC] Colors can now be functions as well as well as strings/gradients. These colors are resolved once, at the start + of the .Draw() method + o [PIE] Documented method .getSegment(). Used for getting the pertinent + segment when the canvas is clicked on (for example), http://www.rgraph.net/docs/pie.html#available.methods + o [ROSE] This chart has been moved to DOM2 for tooltips + o [ROSE] Documented method .getSegment(). Used for getting the pertinent + segment when the canvas is clicked on (for example), http://www.rgraph.net/docs/rose.html#available.methods + o [RSCATTER] This chart has been moved to DOM2 for tooltips + o [SCATTER] This chart has been moved to DOM2 for tooltips + o [SCATTER] Added new properties: chart.yaxispos + chart.xaxis + chart.noendxtick + o [TOOLTIPS] Fixed a tooltip bug that probably only presented itself on the bar chart example page + o [TRADAR] Added chart.tooltips.highlight (default is true) + o [TRADAR] This chart has been moved to DOM2 for tooltips + o [VPROGRESS] This chart has been moved to DOM2 for tooltips + o [XML] Removed XML documentation + + 25th September 2010 (STABLE) + =================== + o [DOCS] Fleshed out the integration example - http://www.rgraph.net/docs/index.html#mysql + o [DOCS] Added note to docs about line chart obj.original_data + + 18th September 2010 + =================== + o [ANNOTATE] Added onannotatestart and onannotateend events + o [CONTEXT] Fixed submenu offset in MSIE 9 + o [DOCS] Added MySQL integration example to integration docs + o [DOCS] Documented how to use a dynamically created canvas with ExCanvas + o [MODALDIALOG] Removed MSIE 8 DirectX shadow from ModalDialog + o [MODALDIALOG] Better MSIE 9 compatibility + o [PIE] Fixed Pie chart sticks for Chrome 6 + o [TOOLTIPS] If Y position is less than 0, tooltips are now shown below the cursor to mitigate this + o [WEBSITE] Added social networking icons to all pages + o [WEBSITE] "Preload" social networking icons + + 11th September 2010 + =================== + o [API] Updated docs for RGraph.Redraw() slightly + o [LINE] Added chart.toltips.highlight + o [MISC] Updated the combined bar/line example + o [ODO] The chart.units.pre and chart.units.post properties have changed to chart.value.units.pre and chart.value.units.post. + The chart.units.pre and chart.units.post properties have changed functionally. + o [ODO] Added chart.needle.extra to allow you to specify extra needles. + o [RSCATTER] Added chart.toltips.highlight + o [SCATTER] Added chart.toltips.highlight + o [SCATTER] Added coordinates readout: chart.crosshairs.coords + chart.crosshairs.coords.fixed + chart.crosshairs.coords.fadeout + chart.crosshairs.coords.labels.x + chart.crosshairs.coords.labels.y + Example: http://dev.rgraph.net/tests/crosshairs.html + o [ZOOM] Much improved the smoothness of the indicator box when in area mode - see http://www.rgraph.net/docs/zoom.html + for an example of area mode + + 4th September 2010 + ================== + o [API] Changed RGraph.number_format() functions arguments + o [API] Added RGraph.getGutterSuggest() function, which is a suggestion based on the left labels (only) + for the chart.gutter setting. + o [API] Added RGraph.showPNG() function, which makes it easy to get images of graphs. This is designed to be + used in conjunction with the context menu, and is therfore defined in the RGraph.common.context.js file. + There's documentation about it here: http://www.rgraph.net/docs/png.html + o [BAR] Added key shadow control + o [BAR] Added chart.scale.point and chart.scale.decimal + o [BIPOLAR] Added chart.scale.point and chart.scale.decimal + o [FUNNEL] Added key shadow control + o [HBAR] Moved to DOM 2 event handler functions + o [HBAR] Added chart.scale.point and chart.scale.decimal + o [LINE] Added key shadow control + o [LINE] Added warning about Chrome 6 shadow bug + o [LINE] Added chart.noyaxis + o [LINE] Added chart.scale.point and chart.scale.decimal + o [MISC] Added RGraph.getGutterSuggest(). See the misc documentation for more detail + o [MSIE] Now that RGraph is moving to DOM2, tooltips on graph libraries that have been changed will not function in MSIE8. + The graphs will still be shown, however tooltips will not function. MSIE9 will still work. + o [ODO] Pointer is now more pointy + o [PIE] Moved to DOM 2 event handler functions + o [ROSE] Added key shadow control + o [RSCATTER] Added key shadow control + o [SCATTER] Added chart.tooltips.coords.adjust + o [SCATTER] Added key shadow control + o [SCATTER] Added chart.scale.point and chart.scale.decimal + o [TRADAR] Added key shadow control + o [WEBSITE] Added code to async page that demonstrates the difference more + + 28th August 2010 + ================ + o [API] Updated the API docs a little with the correct data properties for some graph types + o [DOCS] Added information about AJAX requests to performance section + o [DOCS] Added information about the DOMContentLoaded event to the docs. + o [LINE] Fixed problem with chart.ylabels = false + o [METER] Added arrow head to the Meter + o [METER] Removed outer labels + o [METER] Increased number of labels to 11 + o [MSIE] A few small tweaks to the palette, the scatter chart, the context menu, and tooltips + o [ODO] A few fixes for the Odometer in Chrome 6, and a few minor enhancements to the appearance. + o [WEBSITE] Live site now uses images.rgraph.net for the index page ** REVERTED ** + o [WEBSITE] Social networking icons are now combined into one image. + + 21st August 2010 + ================ + o [HBAR] Added chart.units.ingraph (for when your units are quite long) + o [MISC] Fixed various bugs in circular charts with Chrome 6 + o [MISC] Added note to front page about suitability for Chrome extensions + o [MSIE] Lots more fixes for MSIE 9 + + 14th August 2010 + ================ + o [BAR] Added chart.tooltips.coords.adjust which allows you to adjust tooltip coordinates when you translate + o [HBAR] HBar shadow is now "unified", so you can have an upwards shadow with a large offset and it still looks OK + o [HBAR] "chart.labels.abovebar" are now left aligned if they would go off the end of the canvas + o [HBAR] Fixed a bug with chart.strokecolor - renamed to chart.strokestyle + o [LINE] Added chart.tooltips.coords.adjust (for when you translate() first) + o [LINE] Tweaked filled/stepped line charts - stepped line charts show trailing line again + o [LINE] Tickmarks, as well as a string, can now also be an array of tickmark styles, eg: + http://dev.rgraph.net/tests/test3.html + o [LINE] Added chart.ylabels.invert + o [MISC] You can now specify in-graph labels like this: + line4.Set('chart.labels.ingraph', [6,'July', 3, 'November']); + If you have a lot ofempty spaces, this will help. + o [MISC] Added type property(=common) to common objects + o [ODO] Improved the appearance of the Odometer border + o [SCATTER] Tickmarks are no longer drawn when the ticks are boxplots + o [SCATTER] Added chart.xmin (upgrade cautiously) + o [SCATTER] Boxplots are now usable when the X axis is in the center + + o [NOTE] Chrome 6 appears to have an issue with canvas shadows. Other browsers are fine. A workaround has been added to the + Line chart library, however it won't be a solution for all cases. In these cases, turn off shadow blurring. + + 7th August 2010 + =============== + o [BAR] Changed this graph type over to the DOM2 .addEventListener() for tooltips + o [BAR] Bar chart can now have an arbitrary number of labels + o [BAR] Added chart.ylabels.inside + o [BAR] Labels can now be at any angle + o [BIPOLAR] Changed the default colors to just one - green + o [EVENTS] Added more events: + o onmodaldialog + o onresize + o onadjust + o onannotate + o [HPROGRESS] Multiple segments are now supported + O [HPROGRESS] Added the ability to configure the number of inner tickmarks + o [LINE] Labels can now be at any angle + o [LINE] Changed this graph type to use the DOM2 .addEventListener() for tooltips + o [MISC] Added isRGraph property to common objects + o [MISC] Added chart.title.hpos to all graph libraries + o [MODALDIALOG] Added onmodaldialog event + o [ODO] Outer shadow is now configurable + o [ODO] Inner shadow is now configurable + o [PROGRESS] This has now been split into the HProgress and VProgress + o [SCATTER] Labels can now be at any angle + o [TOOLTIPS] Added contract effect, similar to expand but in reverse + o [TRADAR] Background grid now matches RScatter in terms of width etc + o [VPROGRESS] Multiple segments are now supported + o [VPROGRESS] Added the ability to configure the number of inner tickmarks + + o [NOTE] Upgrading to the new H/VProgress should be done cautiously as they have undergone significant alterations + + 31st July 2010 + ============== + o [MISC] Stable release + o [DOCS] Added CSS class: RGraph_palette + o [DOCS] Added simple example AJAX function to integration documentation: + http://www.rgraph.net/docs/index.html#integration + o [ZOOM] Fixed a fade-in bug with full canvas zoom + + 24th July 2010 + ============== + o [LINE] This chart can now have text at any angle. Other graph types to follow + o [MISC] The minify script now accepts multiple arguments (filenames), + eg. ./minify file1 file2 file3 ... + + 17th July 2010 + ============== + o [BAR] Abovebar labels in GROUPED charts are now formatted + o [BIPOLAR] Moved this to use addeventListener() for events - this is a test case + o [EVENTS] Renamed the RGraph functions RGraph.AddEventListener() and RGraph.FireEvent() + to RGraph..AddCustomEventListener() and RGraph.FireCustomEvent() + o [EVENTS] Added onbeforedraw event which fires at the start of the .Draw() function + o [EVENTS] Added onzoom event to all types of zoom. See docs for details + o [HBAR] Added formatting to above bar labels + o [HBAR] Fixed grouped HBars with shadows going upwards (partially) + o [ODO] Changed a few internal properties. Read more in the docs/.BC.txt file + o [ODO] Changed chart.needle.style to chart.needle.color + o [RSCATTER] Updated test script + o [TRADAR] Added chart.labels.axes - defaults to "nsew" + o [TRADAR] Added chart.ymax + o [BIPOLAR] Implemented chart.xtickinterval. If you specify this, X tickmark spacing is totally down to this setting + o [MISC] Added chart.tooltips.override (see tooltips docs for details) + + 9th July 2010 + ============= + o [API] Added __index__ to tooltip DIVs, which corresponds to the original tooltips array. If you're not using an array of strings + for your tooltips, this is not pertinent + o [API] The RGraph.Tooltip() function now accepts an extra parameter - the index of the tooltip + o [MISC] Introduced event support. There are currently just three events - ontooltip - which naturally fires when + a tooltip is shown, oncontextmenu - which fires when the RGraph context menu is shown and ondraw - which + fires when the .Draw() method is called.. More information is available here: + http://www.rgraph.net/docs/events.html + o [MISC] Added snap tooltip effect for graph types where the tooltips are triggered using the onmousemove event, + ie Line, Rscatter, Scatter and the Tradar + o [MISC] MooTools compatibility fix + o [MISC] Added obj.isRGraph boolean to all graph objects. This is documented on the misc docs page (docs/misc.html) + o [MSIE] MSIE9 compatibility work + o [ODO] You can now use textual labels instead of numbers, eg. N/S/E/W (using chart.labels) + o [ODO] Added chart.zerostart option determining whether the top label is zero or the end value + o [ODO] Fixed a pointer bug + o [ODO] Fixed a rounding issue and added chart.scale.decimals (default is 0) + o [ODO] Colors can now be configured with: chart.green.color, chart.yellow.color, chart.red.color + o [PROGRESS] Changed a few internal properties. Read more in the docs/.BC.txt file + o [TRADAR] Added background diagonal lines (going from the center outwards) + + + 26th June 2010 + ============== + o Stable release + + 18th June 2010 + ============== + o [BAR] Documented grid properties: chart.background.grid.autofit, chart.background.grid.autofit.numhlines, chart.background.grid.autofit.numvlines + o [DOCS] Documentation pages have been reorganised and a contents list added to each page + o [GANTT] Documented grid properties: chart.background.grid.autofit, chart.background.grid.autofit.numhlines, chart.background.grid.autofit.numvlines + o [HBAR] Documented grid properties: chart.background.grid.autofit, chart.background.grid.autofit.numhlines, chart.background.grid.autofit.numvlines + o [LINE] Documented grid properties: chart.background.grid.autofit, chart.background.grid.autofit.numhlines, chart.background.grid.autofit.numvlines + o [SCATTER] Documented grid properties: chart.background.grid.autofit, chart.background.grid.autofit.numhlines, chart.background.grid.autofit.numvlines + o [WEBSITE] Added warning about MSIE versions less than 8 + + 5th June 2010 + ============= + o [HBAR] Added the following properties: chart.title.xaxis + chart.title.yaxis + chart.title.xaxis.pos + chart.title.yaxis.pos + o [ROSE] Slightly increased the area recognised to initiate resizing the Rose (ie the size of the hotspot) + o [TRADAR] Added adjusting to the TRadar + + 29th May 2010 + ============= + o [BAR] Added adjusting + o [ODO] Added gray border effect + o [ODO] Added chart.tickmarks.highlight + o [PROGRESS] Added adjusting + o [ROSE] Added adjusting + o [SCATTER] Added chart.ymin + + 22nd May 2010 + ============= + o [LINE] Added interactive adjustments + + 15th May 2010 + ============= + o [API] Updated the .getSegment() for use with the Rose chart and Donut variant charts + o [API] Added RGraph.array_pad() function + o [BAR] You can now have grouped bar charts with shadows going to the left + o [LINE] Linewidth can now, as well as being a single number, be an array of numbers, one for each line + o [LINE] You can now have labels on the inside of the Y axis as opposed to having them in the gutter + o [MISC] ModalDialog and zoom background DIVs are now much better in regards to page coverage (the semi-opaque background) + o [MISC] Removed RGraph.getPageWidth() and RGraph.getPageHeight() functions + o [MISC] You can now pass a color as the second argument to RGraph.Redraw() which it will use + o [MISC] Resizing the window when zoomed no longer hides the zoom + o [ODO] Little bit of work on pointers and MSIE compatibility + o [ODO] Added "digital" readout option, as shown on the example page + o [PROGRESS] This chart type can now have an "in-bar" indicator + o [PIE] Converted this chart to use RGraph.getSegment() for tooltips + o [ROSE] You can now set the strokestyle + o [ROSE] Converted this chart to use RGraph.getSegment() for tooltips + o [SCATTER] Added chart.line.linewidth and, as with the line, it can be either a number or an array of numbers + o [SCATTER] chart.line.stepped can now, as well as simply true or false, be an array of booleans. This allows you to have + multiple lines, some stepped, some not. + + 8th May 2010 + ============ + o [MISC] You can now have multi-line labels by using the text "\r\n" in your label (without the quotes) + o [MISC] Resizing a graph no longer affects the page layout + o [ROSE] Added labels to this chart + o [ROSE] The Rose chart origin is now the "north" axis + o [WEBSITE] Re-arranged the front page + o [WEBSITE] Removed a lot of examples from the website and made the whole thing a little more streamlined + o [ZOOM] Once visible, you can now double click a zoomed area to expand it to a full size zoom. You can see + this on the line graph on the front page. + + 1st May 2010 + ============ + o [DONUT] This is no longer a seperate class, but now a variant of the Pie chart (chart.variant = donut) + o [MISC] Added note about copying the text in tooltips using Firefox + o [ROSE] Tooltip highlighted area is now "under" the labels (as opposed to "over") + + 25th April 2010 + =============== + o [MISC] Separated out resizing functionality into it's own file - RGraph.common.resizing.js This further reduces the size of + RGraph.common.core.js + o [MISC] In area zoom, you can now left-drag to move the zoom itself around, and right-drag to move the zoomed canvas around inside + the zoom + o [MISC] Added RGraph_zoomed_area CSS class + o [MISC] Added chart.crosshairs.linewidth to bar, line and scatter + o [MISC] You can now have a single level of submenu items with the context menu + o [RADAR] This chart has been renamed to Rose and the appearance enhanced + + 17th April 2010 + =============== + o [BAR] This chart type can now use the onmousemove event for tooltips instead of the onmousedown + o [DOCS] Added tooltips documentation page - this explains tooltips and how you can specify them. There are now 4 methods available. + o [MISC] The zoomed area is now draggable once visible + o [MISC] Split out RGraph.common.js into separate files, consisting of: + o RGraph.common.core.js + o RGraph.common.annotate.js + o RGraph.common.context.js + o RGraph.common.tooltips.js + o RGraph.common.zoom.js + If you don't use any of the interactive features, the core common library is now roughly half the size. See + http://www.rgraph.net/docs/index.html#implementation for details of the new way to implement RGraph + o [MISC] You can now specify the CSS class that tooltips use (using chart.tooltips.css.class). If you have multiple + graphs on one page and want the tooltips to appear differently, this is how to do it + o [MISC] New tooltip effect - "none". Which, as the name implies, doesn't fade or expand. + + 10th April 2010 + =============== + o [MISC] Cleaned up each graphs coords array. If you use the coords arrays, you may need to adjust your numbers slightly. + The new coords may be off for you by one or two chart.margin (it can be hmargin or vmargin depending on your graph type) + o [MISC] Added details of backwards compatibility breaks + o [MISC] New zoom mode - area. You can see this on the front page line graph and on the zoom documentation page + o [MISC] Added resizing capability. Will not work with other dynamic features (except the context menu) + + 3rd April 2010 + ============== + o [BAR] Added new grid properties: chart.background.grid.autofit + chart.background.grid.autofit.numhlines + chart.background.grid.autofit.numvlines + o [BAR] Added chart.title.xaxis + o [BAR] Added chart.title.yaxis + o [BAR] Added chart.title.xaxis.pos + o [BAR] Added chart.title.yaxis.pos + o [GANTT] Adjusted the background grid, adding the required default properties + o [GANTT] Added new grid properties: chart.background.grid.autofit + chart.background.grid.autofit.numhlines + chart.background.grid.autofit.numvlines + o [HBAR] Added new grid properties: chart.background.grid.autofit + chart.background.grid.autofit.numhlines + chart.background.grid.autofit.numvlines + o [LINE] Multiple shadow colors are now facilitated (see example on front page) + o [LINE] Added new grid properties: chart.background.grid.autofit + chart.background.grid.autofit.numhlines + chart.background.grid.autofit.numvlines + o [LINE] Added chart.title.xaxis + o [LINE] Added chart.title.yaxis + o [LINE] Added chart.title.xaxis.pos + o [LINE] Added chart.title.yaxis.pos + o [LINE] Added chart.backdrop, chart.backdrop.alpha and chart.backdrop.size + o [LINE] Shadow color can now be an array of shadow colors. ie. A different one for each line + o [MISC] Added note about installing your own event handlers to misc documentation page + o [MISC] Added RGraph.SetShadow() - a shortcut function for setting the shadow + o [ODO] Added option to not draw the pointer tail + o [ODO] Added chart.needle.type option. It can be "pointer" (default) or "triangle". + o [PROGRESS] Added chart.margin + o [PROGRESS] Added inner tickmarks (chart.tickmarks.inner) + o [PROGRESS] Made examples a bit better + o [SCATTER] Connecting lines can now be stepped (chart.line.stepped) + o [SCATTER] You can now specify the exact X point at which an X label is drawn + o [SCATTER] Added new grid properties: chart.background.grid.autofit + chart.background.grid.autofit.numhlines + chart.background.grid.autofit.numvlines + o [SCATTER] Added chart.title.xaxis + o [SCATTER] Added chart.title.yaxis + o [SCATTER] Added chart.title.xaxis.pos + o [SCATTER] Added chart.title.yaxis.pos + + ++------------------------------------------------------------------------------------------------------------+ +| STABLE RELEASE - 27th March 2010 | ++------------------------------------------------------------------------------------------------------------+ + + + 27th March 2010 + =============== + o [MISC] Just tweaks - nothing major + + 20th March 2010 + =============== + o [MISC] Reverted dark background color for zoom back to the lighter one + o [MODALDIALOG] Reverted the dark background color back to the lighter one + o [METER] Added more feint tickmarks + o [METER] Labels are now angled. This will be an option in the future + o [ODO] Added more feint tickmarks + o [ODO] Labels are now angled. This will be an option in the future + o [ODO] Significant changes to this see the docs page - http://www.rgraph.net/docs/odo.html + + 13th March 2010 + =============== + o [MISC] Removed curvy corner from context menu + o [WEBSITE] Added Google Buzz social networking icon + o [MODALDIALOG] Darkened the background a little. You can set this back if you wish by using the ModalDialog_dialog CSS class + + 6th March 2010 + ============== + o [METER] Documented shadow properties + o [MISC] Added RGraph.getPageWidth() which returns the page width, accommodating browser differences + o [MISC] Added RGraph.getPageHeight() which returns the page height, accommodating browser differences + o [MODALDIALOG] Increased the radius of the corners (ie they're more rounded now) + o [MODALDIALOG] Documented the ModalDialog CSS classes and also added miscellaneous documentation + o [MSIE] Added context menu to the MSIE example + + 27th February 2010 + ================== + o [API] Added information about the coords array. + o [API] Added a little information about dynamically updating your graphs + o [MISC] Zoom in canvas mode now has a dark background option - chart.zoom.background - can be true or false and defaults to true + Note: If you use the full canvas zoom, this will affect you - if you don't like it, you will need to turn it off + o [MISC] Added RGraph_zoomed_canvas CSS class. Also tweaked the default CSS for the two types of zoom + o [MISC] Tweaked the animation example + + 20th February 2010 + ================== + o [DOCS] Added reasonable caching strategy + o [DOCS] Expanded the API docs regarding the data properties + o [LINE] Removed chart.border property. You should use CSS on your canvas element instead. + o [LINE] Added chart.ymin property + o [LINE] Tickmarks are no longer drawn if the tick is outside the Y scale range + o [METER] Added shadow + o [WEBSITE] Removed most tables from the website + o [WEBSITE] Fixed the issue with the front page graphs, Google Chrome and missing text. This was done by NOT using + asynchronous processing. + + 9th February 2010 + ================= + o [PIE] Fixed pie chart sticks with athick white border + o [PIE] Added chart.labels.sticks.color + o [DOCS] Added link anchors to documentation pages, eg: http://www.rgraph.net/docs/bar.html#chart.labels + + 7th February 2010 + ================= + o [BAR] Added ability to specify number of Y labels - 1, 3 or 5 (the default). + o [LINE] Added ability to specify number of Y labels - 1, 3 or 5 (the default). + o [LINE] Added a little missing documentation + o [LINE] Small fix to MSIE arrow style tickmarks + o [MISC] Optimisations to all chart libraries + o [MISC] Added RGraph_zoom_window CSS class - the front page uses it if you want an example + o [SCATTER] Added ability to specify number of Y labels - 1, 3 or 5 (the default). + o [SCATTER] Added a little missing documentation + + 30th January 2010 + ================= + o [BAR] Performance tweaks. + o [DOCS] Made note about using tables for layout and how it can impact negatively on graph speed. + o [DOCS] Documented Pie chart label sticks. + o [LINE] Performance tweaks. + o [MISC] Opera (10.5) now supports the canvas text and shadow APIs + + 23rd January 2010 + ================= + o [LINE] Fix to arrow style tickmarks + o [MISC] Very minor change to tooltips and event handling + o [SCATTER] Added diamond shape tickmarks + + 16th January 2010 + ================= + o [BAR] Documented chart.ylabels + o [CONTEXT] Context menus are now positioned correctly when you specify a DOCTYPE in MSIE + o [LINE] Added and documented chart.ylabels + o [MODAL DIALOG] This is now completely static (when scrolling) in all browsers (Chrome, FF, MSIE, Safari, Opera), (MSIE requires that + you use a doctype. + o [ODO] Improved MSIE support (spurious circles are no longer drawn) + + 9th January 2010 + ================ + o [BAR] Added glass variant + o [BAR] Added sketch variant + o [DOCS] Documented getCanvasXY() function + o [MISC] Links now work in tooltips + o [MISC] Added standard box-shadow: CSS property where necessary + o [MISC] Slight border-radius change to context menu + o [PIE] Added small (optional) label sticks + o [PROGRESS] Added indicator arrows + + 2nd January 2010 + ================ + o [METER] Added this as a new chart type + o [MISC] More optimisations for Meter, Line and Bar charts + o [TRADAR] Added tooltips + o [TRADAR] Added ability to specify offsetx and offsety for labels + + 19th December 2009 + ================== + o [BAR] Added support for MSIE shadows. Shadow blurring is not available though + o [BAR] Fixed dot chart colours not showing correctly in MSIE + o [BIPOLAR] Added support for MSIE shadows. Shadow blurring is not available though + o [FUNNEL] Optimised this chart type a little + o [FUNNEL] Added support for MSIE shadows. Shadow blurring is not available though + o [LINE] Added support for MSIE shadows. Shadow blurring is not available though + o [MISC] The context menu for Safari, Opera and Firefox Mac is now triggered by a double click (left mouse button). + o [MSIE] Tooltips now work (albeit a little unreliably), but this browser is very slow at showing them. Using a doctype will + cause them to be ou of position. + o [PIE] Added support for MSIE shadows. Shadow blurring is not available though + o [PROGRESS] Added support for MSIE shadows. Shadow blurring is not available though + + 12th December 2009 + ================== + o [MSIE] Microsoft Internet Explorer is now supported in a limited fashion. You can see it in action here: + http://www.rgraph.net/docs/msie.html This is not using Google Chrome Frame. + o [TRADAR] Rewrote so that it works with MSIE. This rewrite means that tooltips will be feasible (I'm yet to add them) + o [WEBSITE] Significant reorganisation of website + + 5th December 2009 + ================= + o [API] Added and documented RGraph.Async() function, which can be used to help speed up your pages. There's a page which details it: + http://www.rgraph.net/docs/async.html + o [MISC] Removed text support for Opera. The graphs are still displayed, albeit without text + o [MISC] Changed to object detection in place of specific browser detection for older browsers. This means more + browsers are accounted for. + o [MISC] Added RGraph.getSegment() function, which returns the applicable segment information + (x, y, radius, startAngle, endAngle) + o [SCATTER] Added ability to do Barplots using the Scatter chart. + o [SCATTER] Can now specify the scatter to not display tick marks (be specifying the tickmark as null) + + 28th November 2009 + ================== + o [DOCS] Added RGraph.HideContext() to API documentation. + o [MISC] Simplified logic for showing the context menu. Please test your browser on the website before upgrading as this may + cause regressions. + o [MISC] Fixed slight oddity for zoom which resulted in a small zoom thumbnail + o [MISC] The RGraph website now works with Google Chrome Frame. NB: If you're having a similar problem, ensure the META + tag is in the first 1Kb of the page. + o [MISC] Achieved a degree of Opera compatibility. Please bear in mind that Opera does not yet support the canvas text + or shadow APIs so do not expect to see any shadows on your graphs. Text is simulated however, so the graphs + are still usable in some circumstances however. Also bear in mind that Opera support is buggy. + + 20th November 2009 + ================== + o [MISC] Added new mode for zoom - thumbnail This shows a zoom thumbnail (you must set chart.zoom.mode to thumbnail) instead of + zooming the entire canvas. The line graph on the front page shows an example of it. + o [MISC] Context menu in Mac Firefox is now attached to the left mouse button instead of the right + o [NOTE] Annotations are now persistent in Chrome (dev channel releases at the moment) and Chrome Frame + + 14th November 2009 + ================== + o [ALL] Finished zoom function + o [PIE] Work on linewidth and line color + o [MISC] Changed Safari to use left click for context menu - should elimate the temperamentality + + 8th November 2009 + ================= + o [ALL] Added zoom functionality (This is not finished yet) + o [API] Corrected this regarding graph data + o [MISC] Added RGraph.ClearAnnotations() to API documentation. NB: This function is called when you call RGraph.Clear() + + 31st October 2009 + ================= + o [DOCS] Correct the docs regarding text sizes + o [PIE] Miscellaneous fixes + o [RADAR] Changed to be left aligned + + 25th October 2009 + ================= + o [ALL] Added property: chart.text.font + o [ALL] Added property: chart.text.color + o [ALL] Changed from pixels to points for font sizes (you may need to reduce your font sizes slightly). Default is now 10pt + o [DONUT] Added ability to set key as being in gutter + o [DONUT] Added chart.align for left/center/right aligning the chart + o [PIE] Added chart.align for left/center/right aligning the chart + + 17th October 2009 + ================= + o [BAR] Added new option: chart.axis.color + o [Bipolar] Added new option: chart.axis.color + o [DOCS] Automated generation of API (properties) documentation + o [HBAR] Added new option: chart.axis.color + o [LINE] Added new option: chart.noxaxis + o [LINE] Added new option: chart.axis.color + o [LINE] Reduced default X/Y shadow offset + o [LINE] Added new option: chart.noendtick - useful for when you're generating line charts with Y axes on both sides + o [MISC] Changed "Combining..." page to illustrate combining two line charts + o [MISC] Added XML documentation + o [MISC] Added performance note about combining libraries + o [SCATTER] Added new option: chart.axis.color + + 10th October 2009 + ================= + o [BAR] Added chart.background.grid.hlines, chart.background.grid.chart.background.grid.vlines and chart.background.grid.border + o [BAR] Changed chart.labels.abovebar to chart.labels.above + o [BAR] Added chart.labels.above to stacked bar charts + o [BIPOLAR] Fixed using chart.xmax + o [BIPOLAR] Added chart.scale.decimals + o [HBAR] Added chart.background.grid.hlines, chart.background.grid.chart.background.grid.vlines and chart.background.grid.border + o [HBAR] Added chart.labels.above. Not technically "above" the bar (not at all), but it's so named for API compatibility + o [HBAR] Added chart.labels.above to stacked chart + o [LINE] Added chart.background.grid.hlines, chart.background.grid.chart.background.grid.vlines and chart.background.grid.border + o [PIE] Miscellaeous work + o [SCATTER] Added chart.background.grid.hlines, chart.background.grid.chart.background.grid.vlines and chart.background.grid.border + o [WEBSITE] Added sharing buttons + + 3rd October 2009 + ================ + o [ALL] Charts now clean up events if tooltips are not installed. This means that if tooltips are not being used + the onmousemove/onclick events (depending on the graph library) are reset to null. + o [BAR] 3D effect now works with background grid and bars + o [DOCS] Added API documentation (replaces working.html) + o [MISC] Changed various graphs default background bar colors to white + O [MISC] Removed array_range() function - unused + o [LINE] More (general) work + o [LINE] chart.fillstyle can now be an array as well as a string + o [LINE] Added 3D variant to line chart. + o [MISC] Added minified library archive + + 19th September 2009 + =================== + o [ALL] Added new option - chart.title.color - to all graph types (except the LED) + o [LINE] Slight modification to filled line charts and the (stroke) colour. + o [LINE] Changed stepped line chart so last vertical line is not drawn + o [LINE] Changed the look (for the better) of filled line charts and thick lines + o [LINE] Added option - chart.axesontop - useful in a minority of cases; causes the axes to be + redrawn after the graph + o [LINE] Added "chart.filled.range" option. Used to compare the range/difference between two sets of data. + o [MISC] Fixed negative horizontal bars + o [LINE] Fixed problem with null arguments + o [LINE] Filled line charts now work a little better with negative values + o [PROGRESS] Added chart.tickmarks.color + o [PROGRESS] Added chart.text.color + + 6th September 2009 + ================== + o [ALL] Fixed libraries to work with Prototype.js + o [ALL] Added chart.title.vpos allowing you override and specify the position of the title. This should be a + decimal from 0 to 1. By default it's not used + o [BAR] Can now have Y axis labels in right hand gutter + o [LINE] Can now have Y axis labels in right hand gutter + o [COMMON] Fixed scale generation bug when maximum value is zero (ie all of your values are zero) + + 22nd August 2009 + ================ + o [MISC] Optimisations on various graph libraries + o [MISC] Very minor albeit better HTML5 compliance + o [LINE] You can now specify the Y axis position - left (default) or right + + 8th August 2009 + =============== + o [BAR] Added 3D effect to regular, grouped and stacked charts + o [GANTT] Can now specify background grid width + o [LED] The text is now stripped of right-most whitespace + + 25th July 2009 + ============== + o [MISC] Stop using $() function for better compatibility with outside libraries + o [SCATTER] Support supplying multiple datasets as one big array instead of multiple arrays + o [ALL] Changed all graph types to "new RGraph.xxx()" format + + 3rd July 2009 + ============= + o [DOCS] Misc updates + o [DOCS] Fixed docs regarding default gutter size + o [LINE] Handle null values better + o [LINE] Documented optional different fill colour + o [MISC] Added caching enhancements + o [MISC] Slight change to FixEventObject() so offsetX and offsetY are available in Firefox + o [SCATTER] Allow multiple datasets. Effect is only visible when lines are shown + o [SCATTER] Key can now be shown for multiple lines + + 20th June 2009 + ============== + o [ALL] Code optimisations + o [ALL] Annotations are now persistent in browsers that support HTML5 DOM storage (currently Firefox 3.5 and Safari 4) + o [BAR] Added ability to specify labels above bars on single and grouped bar charts + o [SCATTER] Added ability to show connecting line + + 6th June 2009 + ============= + o [ALL] On graphs that support tooltips, you can now have context menus at the same time as tooltips + o [MISC] Fixes to hiding palette in Chrome + o [MISC] Fixed a palette resizing bug + o [MISC] Changed the number of frames for expand and fade tooltip effects from 5 to 10 - looks a little smoother + o [MISC] Fixed a minor scale bug + o [MISC] Changed name of ShowPalette() function to RGraph.Showpalette() + o [PIE] Fixed minor pie chart bugs with mouse cursor + + 23rd May 2009 + ============= + o [ALL] Documented context menu + o [ALL] Added annotations - useful to highlight interactively, and added example to front page line chart + o [BAR] Added pyramid chart variant + o [BAR] Added arrow chart variant + o [BAR] Added crosshairs + o [FUNNEL] Added tooltips + o [LINE] Added crosshairs + o [LINE] Can now have a context menu at the same time as tooltips + o [MISC] Added annotations mini colour palette + o [SCATTER] Added crosshairs + o [SCATTER] Fixed bug where pre/post units were not being shown + o [SCATTER] Can now have a context menu at the same time as tooltips + + 9th May 2009 + ============ + o [BAR] Can now better control the shadow + o [BAR] Now ymax is exactly that which is used + o [BAR] You can now control the number of decimals that are used + o [BIPOLAR] Added shadow + o [HBAR] Can now better control the shadow + o [HBAR] Added tooltipcapability + o [PIE] Can now better control the shadow + o [LINE] Can now better control the shadow + o [LINE] Reversed order of arguments to the constructor - ie the data - so they are uniform with things like labels and tooltips + o [LINE] Can now have a fill colour that's different to the line colour (see the last example on the lines example page) + o [LINE] Added arrow style tickmarks (filled and not) - look best with a linewidth of 1 or 2 + o [LINE] Number of labels is now independent of number of datapoints, as are number of X tickmarks + The second to last two line chart examples show this in action + o [LINE] Added an interesting example showing off the new independence of labels, datapoints and tickmarks. The ninth + line example (the sin/cos/tan curves) has 361 datapoints but only 5 labels - 361 labels would be a bit much. + o [LINE] Line chart no longer draws in the gutter (see this in action by looking at the above tangent curve example) + o [PROGRESS] Brought shadow into line with the rest of the graphs + o [PROGRESS] Tidied this up a little + o [PROGRESS] Added tooltip capability + o [RADAR] Added tooltip capability + o [DOCS] Added small note about canvas and accessibility + o [MISC] Fixed a few HTML warnings + o [MISC] Cleaned up CSS warnings + o [MISC] Updated license + o [MISC] Slight tweaks to context menu: Specifying a null callback now means that that menu item + will not trigger the rollover effect + o [MISC] Fixed a scale bug where the top value is 5.xxx + o [WEBSITE] Made the line graph and pie chart on the front page a little more interactive + o [WEBSITE] Added a funnel chart to the front page + o [FUNNEL] Added horizontal alignment for labels + + 25th April 1009 + =============== + o [MISC] Changed to .zip format for archive instead of .tar.gz - easier to work with + o [MISC] Fixed issue with "expand" type tooltips & timers + o [MISC] Unified default gutter setting (25px) + o [MISC] Made shadows all point the same way across all graphs + o [MISC] Fixed horizontal background bars so that specifying a value greater than the ymax (or less than the negative ymax) + uses the ymax value instead + o [MISC] ModalDialog fixes for width and height settings on various browsers and DOM modes + o [MISC] Scale is now generated more accurately for *really* tiny values + o [LINE] Performance enhancements regarding scale generation + + 11th April 2009 + =============== + o [MISC] Slight aleration to improve "grow" option of tooltips. Instead of starting at the top and growing downwards, it now + starts in the center and grows outward in all directions + o [MISC] Changed "grow" to "expand" for tooltips + o [ODO] Documented ability to turn off the pointer end + o [DONUT] Added ring-in-ring effect, enabling multiple datasets + o [DONUT] Added option to use in-graph key instead of labels + o [LINE] Changed "tick" style tickmarks to "halftick". "tick" now gives a fullheight tickmark, and also added "endtick" + which gives a full height tick mark at the ends of the lines + o [MISC] Added doctype to all pages and fixed modaldialog accordingly + o [MISC] CSS and DTD fixes across the site + o [MISC] ModalDialog fixes + o [MISC] Add type attribute back to SCRIPT tags - needed for DTD compliance + o [HBAR] Added new graph type - Horizontal Bar chart + + 28th March 2009 + =============== + o [BAR] Added dot chart capability + o [BAR] When mouse is over a hotspot, cursor now changes + o [PIE] When mouse is over a hotspot, cursor now changes + o [LINE] When mouse is over a hotspot, cursor now changes + o [GANTT] When mouse is over a hotspot, cursor now changes + o [DONUT] When mouse is over a hotspot, cursor now changes + o [SCATTER] When mouse is over a hotspot, cursor now changes + o [MISC] Added new effect for tooltips. So now you can have "fade" (default) or "grow" + o [MISC] Added drop shadow to context menu + o [MISC] Resolved Chrome color, shadow and gradient bugs + o [DOCS] Added short section about suggested library layout + o [WEBSITE] Always now show two download links + + 14th March 2009 + =============== + o o------------------------------------------------------------------------------------------------------------------o + | IMPORTANT ! | + | Every single one of the property names has been changed to be a little more unified. The new format is now | + | "chart.xxx" where xxx is the actual name. Some of the names have been changed completely, eg. "chart.text.size", | + | which was formerly "textheight", whilst others only marginally. This was necessary to bring some semblance of | + | uniformity to the RGraph properties across all of the libraries, make it look a bit more "proffessional" and | + | provide plenty of scope for future properties. | + | | + | You should also note that as of this release (14th March 2009) that RGraph has been changed to use the canvas | + | text and shadow APIs. This may mean you needing to upgrade your browser if you want to use the latest version. | + | At the time of writing, this meant Firefox 3.1b2, Safari 4 and Chrome 2. If you don't wish to upgrade your | + | browser, or need Opera support, then you will need to remain on the 28th February 2009 version. | + o------------------------------------------------------------------------------------------------------------------o + o [FUNNEL] Added key ability to Funnel chart + o [FUNNEL] Added shadow for key + o [BAR] Added shadow for key + o [LINE] Added shadow for key + o [RADAR] Added shadow for key + o [TRADAR] Added shadow for key + o [RADAR] Added tick marks to the axes + o [PIE] Added border option. + o [BAR] Added "in graph" static labels, useful for highlighting things + o [LINE] Added "in graph" static labels, useful for highlighting things + o [MISC] Provided easy access to minified copies of the libraries + o [ODO] Added inner and outer shadows + o [BAR] Changed to canvas text & shadow API + o [BIPOLAR] Changed to canvas text & shadow API + o [DONUT] Changed to canvas text & shadow API + o [FUNNEL] Changed to canvas text & shadow API + o [GANTT] Changed to canvas text & shadow API + o [LED] Changed to canvas text & shadow API + o [LINE] Changed to canvas text & shadow API + o [ODO] Changed to canvas text & shadow API + o [PIE] Changed to canvas text & shadow API + o [PROGRESS] Changed to canvas text & shadow API + o [radar] Changed to canvas text & shadow API + o [SCATTER] Changed to canvas text & shadow API + o [TRADAR] Changed to canvas text & shadow API + + 28th February 2009 + ================== + o [MISC] Added performance information about onload + o [BAR] Can now specify Y axis units (both before and after the number) + o [LINE] Can now specify Y axis units (both before and after the number) + o [SCATTER] Can now specify Y axis units (both before and after the number) + o [PROGRESS] Can now specify Y axis units (both before and after the number) + o [BIPOLAR] Can now specify X axis units (both before and after the number) + o [BAR] Fixed scale bug + o [MISC] Added UK pound sign to font set + o [FUNNEL] Added new chart - Funnel chart. Can be used to represent sales processes + o [FUNNEL] Made funnel use canvas shadow API + o [MISC] Changed minification script to work "in-place" NOTE + o [PROGRESS] Made progress use canvas shadow API + o [MISC] Tested RGraph on Safari 4.0 - appears to be fine + o [LINE] Added ability to specify horizontal coloured bars + o [BAR] Added ability to specify horizontal coloured bars + o [SCATTER] Added ability to specify horizontal coloured bars + + 14th February 2009 + ================== + o [PIE] Added tooltips + updated docs to correspond + o [WEBSITE] Added tooltips to Pie on front page + o [LED] Added "counter-like" basic LED grid + o [DONUT] Made donut a proxy to pie chart + o [DONUT] Added tooltips + o [MISC] Moved CSS styles to scripts. You no longer need to define CSS styles unless you wish to override something + o [PIE] Made tooltips for pie use 3D effect. This is optional - it can be the traditional 2D or the new 3D effect + o [SCATTER] Can now have the X axis in the center + o [SCATTER] Added tooltip facility + o [MISC] Consolidated invoice handling + o [MISC] Minor fix to DOM structure of context menu + o [LINE] Can now have combined Line and Bar chart so you can overlay Line graphs on top of Bar charts + o [BAR] Can now have combined Line and Bar chart so you can overlay Line graphs on top of Bar charts + o [MISC] Moved showcase examples to separate pages - showcase.html was doing too much and becoming far too slow + + 31st January 2009 + ================= + o [ODO] Added .beginPath() when starting to draw the Odo - needed for animation + o [MISC] Rewrote ModalDialog + o [GANTT] Corrected gantt chart docs + o [MISC] Context menu is now always the correct width + o [BAR] Added ability to specify X axis labels to be drawn at eith 45 or 90 degrees + o [LINE] Added ability to specify X axis labels to be drawn at eith 45 or 90 degrees + o [SCATTER] Added ability to specify X axis labels to be drawn at eith 45 or 90 degrees + o [BIPOLAR] Added tooltips + o [DOCS] Re-jigged (ever so slightly) docs index layout + o [DOCS] Added info on working with RGraph objects in conjunction with accessing the underlying + canvas/context objects + o [DONUT] Made sure the above was valid + o [PROGRESS] Made sure the above was valid + + 17th January 2009 + ================= + o [MISC] Added licensing FAQ page including invoice mailer + o [MISC] Moved CSS to css subfolder + o [MISC] Renamed modaldialog and removed external fade library + o [MISC] Added example of how to integrate RGraph with external libraries using the ModalDialog + o [MISC] ymax property is no longer deprecated - it can be used to stop the scale changing when animating your graphs. + o [MISC] Added documentation page about animation + o [SCATTER] Added square tick type + o [PIE] Fixed last segments line width + o [MISC] Updated copyright notice + o [DOCS] Added basic example for implementation guidance + o [MISC] Changed test page to use tables instead of divs. This will make it more apparent if something breaks + in the RGraph.getMouseXY() function. + o [ODO] Changed to use 10 labels instead of 8 - should make for nicer scale values. + o [ODO] Made tick marks tie into labels more + + 4th January 2009 + ================ + o [DOCS] Added note about pre-caching + o [SCATTER] Added color example to scatter chart + o [MISC] Fixed tooltips appearing in the wrong place + o [MISC] Removed tooltip shadow layer. Shadows are accomodated for in CSS3 + o [DOCS] CSS class documentation + o [MISC] More work on things working with html5 doctype + o [MISC] Removed shadow layer from tooltips. This will be accomodated in CSS3, and is already by some browsers (MSIE (!), Chrome, + Safari, and the forthcoming FF 3.1) + o [MISC] Ditto for context menus + o [MISC] Changed RGraph.getMouseXY() to be more accomodating + o [WEBSITE] Added favicon.png + o [WEBSITE] Added example of pie chart to front page + o [WEBSITE] Changed front page to use tables instead of divs to tell if tooltips keep working + o [MISC] Overhauled RGraph.getMouseXY() so that it works in spite of being nested in tables. It also works + if you position the canvas absolutely and only specify one of the top or left. Wonderbar! + o [SCATTER] Added ability to specify the color of the tick ie:[x, y, color] It's optional. ** Could do with a key ** + o [DOCS] Added color information + o [DOCS] Added context menu information + o [MISC] Made context menus more XP style + o [GANTT] Customised the example more, showing the completage indicators. + o [GANTT] Events and vertical bars are now defined in the usual way, by using the Set() method + o ]MISC] Added __object__ property to all graph objects + o [MISC] Unified text size at 10 points (and 2 greater for titles). + o [MISC] Added context menus to all graph types + o [MISC] Fixed tooltip widths on front page. And siving in general in Opera + + 20th December 2008 + ================== + o [MISC] Converted all graphs to use dollar ($) function in place of document.getElementById("...") + o [TRADAR] Now defaults to drawing the key out of graph + o [LINE] Now labels are turned off if there's fewer labels than data points (every line) + o [MISC] Added better smaller scales - now goes down to 0.0005 + o [DOCS] Added more details on tooltips and positioning + o [LINE] Added gridwidth property + o [BAR] Added gridwidth property + o [MISC] Removed rotating text example (it's still in the archive - it's just not linked) + o [MISC] More work on scales when decimal values are involved, plus graphs now use thousand seperators to aid readability + o [MISC] More work on tooltips and their positioning. + o [MISC] Added "keyposition" option, which can be either "gutter" or "graph" and determines where the key is drawn + o [MISC] Unified all graphs to use the same "textheight" property for text. + o [MISC] All titles are now drawn two pixels larger than the "textheight" property + o [LINE] Key can now be placed above the actual graph area if desired + o [BAR] Key can now be placed above the actual graph area if desired + o [MISC] Fixes to number formatting, including when there multiple graphs on a page + o [BAR] Changed summary line to default to off + o [BIPOLAR] Scale values now contain thousand separators + o [SCATTER] Scale values now contain thousand separators + o [LINE] Scale values now contain thousand separators + o [BAR] Scale values now contain thousand separators + o [MISC] Updated issues.html with details of the smallest scales + o [SCATTER] Deprecated the ymax property. RGraph.getScale() is now good enough (xMax is bipolar chart equivalent) + o [LINE] Deprecated the ymax property. RGraph.getScale() is now good enough + o [BIPOLAR] Deprecated the xmax property. RGraph.getScale() is now good enough + o [BAR] Deprecated the ymax property. RGraph.getScale() is now good enough + o [MISC] Made RGraph.getScale() return the whole scale (all five values), not just the top value + This means better quality scales can be produced. + o [MISC] Made note about positioning in docs on issues page + o [ODO] Work on Small scale values + o [BIPOLAR] Work on Small scale values + o [BAR] Work on Small scale values + o [LINE] Work on Small scale values + o [MISC] Added tooltip fade in effect using CSS3 opacity + o [BAR] Added tooltip functionality to stacked bar chart + o [BAR] Added tooltip functionality to grouped bar chart + o [MISC] Added gradient to front page graphs + o [TRADAR] Added gradient to bipolar on test page + o [TRADAR] Re-added traditional radar chart. It doesn't work in Opera 9.x, only Opera 10+. Documentation for this also fine tuned + o [MISC] Tidied up RGraph.common.js + o [MISC] Removed drawTextAngle() - RGraph.Text() does this + o [MISC] Added a bar chart with centre X axis to example page + o [GANTT] Fixed Gantt chart title text placement + o [GANTT] Added title text size property + o [WEBSITE] Changed colour of example on website + o [RADAR] Changed key to be the same as the bar/line/tradar + o [DOCS] Lots of link updates + + 5th December 2008 + ================= + o [LINE] Made keys and lines (ie stacked/filled) totally correspond. + o [BAR] Stopped bar chart tooltips redrawing the axes. Not entirely sure why it's doing this, but it seems fine without it. + o [DOCS] Bundled license document with archive + o [DOCS] Documentation and example updates. + o [MISC] Changed index.php to index.html Not earth shattering, but should make it clearer for people where to start, + and also makes the downloaded index.html styled as it should be. + o [WEBSITE] Added Cache-Control: Header + o [WEBSITE] Added link to support group on Google more obvious + o [DOCS] Added list of common issues + o [MISC] Added header into files that didn't have it + o [MISC] Removed CanvasText.enable() - unneccessary + o [ODO] Shortened the Odos pointer + + 28th November 2008 + ================== + o [MISC] Got rid of HTML5 doctypes - they seem to be interfering with tooltip positioning. + If you don't use tooltips, you'll therefore be fine. + o [ODO] Better needle. I think. + o [BAR] Keys for charts are now specified in the same order as the pertaining datasets + o [LINE] Keys for charts are now specified in the same order as the pertaining datasets + o [MISC] Added CSS3 shadows to tooltips + o [GANTT] Fixed bug in Gantt chart textsize property + o [LINE] Finally made shadows 100% accurate (ie tickmarks now have shadows too), including stepped line + o [WEBSITE] Added tooltips to line chart on front page + o [MISC] Fixed release script (check) + o [LINE] Added keys to line & bar chart + o [BAR] Added keys to line & bar chart + o [MISC] o-----------------------------------------------------------------------------------------------------o + | Use unified better getters/setters for all charts. This is a MAJOR update, since it affects all the | + | charts in a fundamental way. For the better. Any update should be done cautiously. But since | + | RGraph is beta, all updates should be done that way. Judging by the RGraph test page though, | + | everything seems fine. | + o-----------------------------------------------------------------------------------------------------o + + 15th November 2008 + ------------------ + o [BAR] Removed animation + o [LINE] Documented stepped line chart + o [LINE] Fixed tick marks + o [LINE] Added ability to specify line chart as being stepped + o [MISC] Documented default values. + o [GANTT] Added gantt chart + o [PROGRESS] Corrected name of Progressbar + o [LINE] Moved the background drawing to RGraph.common.js + o [SCATTER] Moved the background drawing to RGraph.common.js + o [MISC] Tooltips now move to the left of the cursor when it's too far right + o [MISC] Changed print_r() to pr() - less to type + o [MISC] Added GetDays() function for Gantt chart + o [GANT] Added it + o [MISC] Added an RGraph.print_r() method for easier debugging + o [MISC] Added a registry object to the common library to resolve scoping issues and so we don't need to use globals. Globals suck. + o [SCATTER] Added a plus tick style to the scatter chart - added a demo too + o [SCATTER] Fixed a bug in the Scatter graphs background drawing + o [BAR] Moved bar charts DrawBackground() into the RGraph.background class. Should make reuse far easier. + o [BAR] "backgroundGrid" property changed to "grid" + o [MISC] Added a minification script. This script doesn't reduce the scripts to the bare minimum. But it can take 50% off the size (!). + o [LINE] Can now specify colour of shadows for line and bar graphs + o [BAR] Can now specify colour of shadows for line and bar graphs + o [LINE] line chart now has real shadows and so they can be used for lines of any thickness + o [LINE] can now specify shadow offset + o [SCATTER] Fixed background bar boundaries + o [SCATTER] Added plus cross type + o [MISC] Moved background drawing to common library + o [WEBSITE] sitemap.xml Now has correct date which changes correctly when a release is performed CHECK + o [MISC] Tooltip nows store the text in __text__ variable on the tooltip object (.innerHTML changes the HTML when it's set) + + 1st November 2008 + ------------------ + o [BAR] Last bar chart example now uses a gradient + o [MISC] Changed hyphens to be slightly shorter + o [WEBSITE] Changed sitemap to use an update frequency of weekly. Last modified is now updated when a release is performed + o [BAR] Can now specify the grid size on the bar chart + o [LINE] Setting propeties can now be any case, upper or lower + o [MISC] Added RGraph.print_r() function + o [LINE] TickSize now actually has an effect + o [LINE] Added tooltips to line chart + o [WEBSITE] Moved support forum to Google group + o [MISC] Added object registration (for redrawing) + o [BAR] Removed margin from being accounted for in height calculation + o [LINE] Made tickmarks more coherent + o [BAR] Bar chart now uses canvas ID in some, but not all, error messages + o [LINE] Added small drop shadow to line chart + o [WEBSITE] Added example graphs to front page + o [BAR] Added tooltips to line chart + o [WEBSITE] Added more performance related information + o [PIE] Added drop shadow + + 25th October 2008 + ----------------- + o [DOCS[ Added integration section + o [RADAR] Added title to radar + o [RADAR] Added textStyle to radar + o [PIE] Made one of the pie charts use a gradient + o [PROGRESS] Added shadows + o [PROGRESS] Added title + o [ODO] Converted plain colour to radial gradient + o [PIE] Added gutter and title + o [DONUT] Added gutter and title + o [MISC] Fixed comma issue with rendering text + o [MISC] Added something to text bounding box illustrating exactly where the point specified is + o [BIPOLAR] Bipolar middle bit is now 60px wide instead of 50 + o [BAR] Fixed shadow bugettee in Safari, Chrome, Opera + o [ODO] Documented and vastly improved. Made it use a gutter now allowind for a title (implemented) + o [MISC] Added common function, DrawTitle() + o [MISC] Added a Javascript version of the PHP function range() + o [MISC] Added ability to specify a title to the bar chart, line graph and scatter graph. + o [MISC] Changed directory layout slightly + o [MISC] Forum is now ecluded from the tar + o [MISC] Much improved scale auto-generation + o [DOCS] Added code samples to docs pages + o [DOCS] Added section on the front page about performance + o [SCATTER] Many improvements to the scatter graph + o [SCATTER] Much better auto scale generation + o [SCATTER] Made scatter use RGraph common library for text + o [RADAR] Converted to use common library for text + o [LINE] Much improved scale auto-generation + o [LINE] Changed to rounded line ends - not very noticable though + o [LINE] Converted labels to be drawn by the RGraph library + o [BAR] Added optional shadow effect + o [BAR] Removed ability to have X axis at the top. It served no real purpose and only served to complicate the code + o [BAR] Added animation + o [BAR] Much improved scale auto-generation + o [BAR] Converted text functions to use RGraph common library + o [BAR] Can now specify a title for the bar chart + o [BAR] Fixed a bug for Chrome + o [BAR] Fixed minor bugs in bar chart (background bars) + o [BAR] Added grouping property, which defaults to stacked, but can also be grouped, producing what you would + expect (unless you're expecting a chicken. + o [BAR] Added a few warnings concerning bad combinations of axis positions + o [ODO] Added more labels, now at 8 instead of 4 + + 24th September 2008 + ------------------- + o [WEBSITE] Added RSS feed to forum + o [DOCS] Added more documentation + o [ALL] Unified (sort of) the error messages + o [ODO] Added odometer + o [BIPOLAR] Added a bottom gutter for scale to go in + o [BIPOLAR] Added bottom text labels + o [PIE] Made pie chart work without translating + o [TRADAR] Added real radar chart. + o [BAR] Bar chart can now have the X axis in the center, so it now able to represent negative values + o [LINE] Allowed multiple lines + o [LINE] Line chart can now have the X axis in the center, so it now able to represent negative values + o [LINE] Fixed bug in line chart that meant if it was filled the filled line was stopping too short + o [LINE] Made it more obvious (I think) for specifying data when using multiple data sets (ie multiple lines) + + 4th September 2008 + ------------------ + o Various additions including labels on all the graphs \ No newline at end of file diff --git a/RGraph/docs/adjusting.html b/RGraph/docs/adjusting.html new file mode 100644 index 0000000..aa49251 --- /dev/null +++ b/RGraph/docs/adjusting.html @@ -0,0 +1,244 @@ + + + + + + + RGraph: HTML5 canvas graph library - Adjusting your graphs interactively + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Adjusting your graphs interactively

+ + + + [No canvas support] + [No canvas support] + [No canvas support] + [No canvas support] + [No canvas support] + + + +

+ Since 24th May 2010 you have had the ability to adjust your graphs interactively. Currently the Bar chart, Line chart, + Progress Bar, Rose chart and the Tradar have this facility. Some graph types use multiple event handlers and as such + are unlikely to work well with other dynamic features. The Line chart is an example of this, and whilst it does work + with the context menu (and so the full canvas zoom), it is unlikely to work with other dynamic features. +

+ + +

+ At the current time this feature on the Bar and Line charts don't work with X axis in the center. +

+ + +

+ If your intention is to make some sort of interactive console, new HTML5 input types may also be of interest (for example the new range input type + which gives you a "slider bar"). Eg (Chrome/Safari/Opera): +

+ +

+ + +

+ + + \ No newline at end of file diff --git a/RGraph/docs/animation.html b/RGraph/docs/animation.html new file mode 100644 index 0000000..71669dd --- /dev/null +++ b/RGraph/docs/animation.html @@ -0,0 +1,313 @@ + + + + + + + RGraph: HTML5 canvas graph library - Animating your graphs + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Animating your graphs

+ + + +
+ [No canvas support] +
+ +

+ Animating your graphs is a relatively easy affair, whilst not being supported natively as it would only serve to + over-complicate the RGraph libraries. The way to do it is to use + the function RGraph.Clear(canvas), passing it your canvas object that is returned by + document.getElementById(). By default this will cover the canvas in white. You can change this by + passing it the color you want it to use as the second (optional) argument. You could even use a gradient if + you wanted. Then you can simply redraw the entire graph. +

+ +

+ One thing you should note, is that you may have to specify the scale manually, to prevent it from changing + from frame to frame. This can be done by using the chart.ymax property. +

+ +

+ You can review the source of this page if you need further help. Two global variables are set - the number of frames + and the current frame number (which starts at one). The graphs are then drawn with appropriate data + (ie the data multiplied by the frame number over the total number of frames). If the frame number is less than + the total number of frames, the frame number is incremented and the function (window.onload) is called again + after a small delay. +

+ +

Animation using jQuery

+ + +
+ [No canvas support] +
+ + + + +

+ You can if you prefer use an external library for animation, like jQuery. +

+ +

+ The graph to the right is animated using + jQuery. In the example the width is maintained by placing the canvas within a DIV which has the width/height CSS + attributes set. +

+ +

+ In this instance, the + Google hosted jQuery is used. +

+ + +
+
+ + \ No newline at end of file diff --git a/RGraph/docs/annotating.html b/RGraph/docs/annotating.html new file mode 100644 index 0000000..0e7dce3 --- /dev/null +++ b/RGraph/docs/annotating.html @@ -0,0 +1,263 @@ + + + + + + + RGraph: HTML5 canvas graph library - Annotating your graphs + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Annotating your graphs

+ + + +
+ [No canvas support]
+
+ +

+ The annotations feature brings presentation style functionality to RGraph graphs. You can use this feature + for highlighting your graphs if you need to. +

+ + + + +

How do annotations work?

+ +

+ Enabling annotations is a very simple affair, and consists of doing the following: +

+ +
myGraph.Set('chart.annotatable', true);
+ + +

Browser support

+ +

+ Annotations are supported in all browsers that RGraph works with - Firefox 3.5+, Chrome 2+, Safari 4+, Opera 10.5+ and + MSIE/Google Chrome Frame. They DO NOT however work with MSIE 8/ExCanvas. +

+ + +

What can I use annotations for?

+ +

+ As mentioned you can use it for presentations, highlighting things to yourself or others or just to have fun drawing (!). +

+ + +

Are annotations persistent?

+ +

+ That depends on which browser you're using. The annotation data is stored in the users web browser (not on the web server), + meaning currently (21st March 2010) browser support is limited to Firefox 3.5+, Safari 4+, + Chrome 4+ and Opera 10.5+. MSIE 8 also has the required storage capabilities, but since it doesn't yet support canvas, the point is moot. + The user does not have to + confirm anything for storage to be allowed - try it out on this page by drawing on the graph and then refreshing the page. +

+ + +

How do I show the mini-palette?

+ + +

+ You can show the palette by using the RGraph.Showpalette function shown below as a context menu item: +

+ +
+myObj.Set('chart.contextmenu', [
+                                ['Show palette', RGraph.Showpalette],
+                                ['Clear', function () {RGraph.Clear(myObj.canvas); myObj.Draw();}]
+                               ]);
+
+ +

+ This code will result in the same context menu as the graph above. +

+ + +

How can I clear the annotations?

+ + You can simply clear the graph and redraw it: + +
RGraph.Clear(myGraph.canvas); // Clear the graph
+myGraph.Draw();               // Redraw it
+ +

+ In the graph above, there is a context menu that allows you to both clear the graph and also demonstrates the mini-palette + feature available to you. +

+ + +

Replaying annotations when they're off

+ +

+ When annotations are not enabled, any prior annotations that may have been made are not displayed. To show them you need + to use the API function RGraph.ReplayAnnotations(object) after the call to .Draw(). +

+ + \ No newline at end of file diff --git a/RGraph/docs/api.html b/RGraph/docs/api.html new file mode 100644 index 0000000..c6a94f2 --- /dev/null +++ b/RGraph/docs/api.html @@ -0,0 +1,835 @@ + + + + + + + RGraph: HTML5 canvas graph library - API documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - API documentation

+ + + +
+ + + + +

Overview

+ +

+ Working with RGraph objects is purposefully easy, to make them straight forward to integrate into your own scripts if you want to. For any + particular graph type there are a few files required - the common libraries and the graph specific library. Eg: +

+ +
+<script src="RGraph.common.core.js"></script>
+<script src="RGraph.bar.js"></script>
+
+ +

+ RGraph.common.core.js is a function library that contains a large set of functions that support the graph classes. + Some functions, and sets of functions, have their own files. For example, the zoom functions reside in RGraph.common.zoom.js, + so if you don't need zoom, you don't need this file. + Each of the graph libraries (RGraph.*.js) contains that particular graphs class. If you'd like to see a "bare bones" + implementation, you can look at the basic example. There's also a + skeleton example to make it easier to create new graph types. +

+ + +

Canvas and context references

+ +

+ Each graph object maintains references to the context and canvas as properties. So to get hold of them all you + need to do is this: +

+ +
+<script>
+    window.onload = function ()
+    {
+        // 1/2 First draw the chart
+        var myBar = new RGraph.Bar('myCanvas', [1,5,8,4,6,3,1,5,7,8,4,6]);
+        myBar.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+        myBar.Draw();
+    
+        // 2/2 Now get hold of the references
+        var context = myBar.context; // Get hold of a reference to the context
+        var canvas  = myBar.canvas;  // Get hold of a reference to the canvas
+    }
+</script>
+
+ + +

Working with events

+ +

+ When working with events, you may come across the situation where you have a reference to the canvas, but + also need to access the graph object. For this reason the constructor of each object adds a reference to the object to the + canvas and you can access it like this: +

+ +
+<script>
+    document.getElementById("myCanvas").onclick = function (e)
+    {
+        var src = (RGraph.isIE8() ? event.srcElement) : e.target;
+    
+        // The RGraph object constructors add __object__ to the canvas.
+        var myBar = src.__object__;
+    }
+</script>
+
+ + +

Working with graph coordinates

+ +

+ For most graph types, the coordinates of elements (eg bars, lines etc) are to be found in the class variable obj.coords. + This is usually a multi-dimensional array consisting of the coordinates of those shapes, or of points. As an example the bar + chart maintains the X, Y, width and height of each bar (or sections of bars in a stacked bar chart). The coords array is + usually a flat array, even when you have multiple sets of data. +

+ +

+ By using the RGraph.getMouseXY() function and this array you can determine if a bar was clicked on, or if the mouse is near a + line point etc. +

+ +
+var myCoords = myBar.coords;
+
+ +

+ Note: Previously the coords array values sometimes included the margin values, and sometimes didn't. As of 17th + April 2010 the values have all been unified to not include the margin values, so the values are as reported. +

+ + +

Working with graph data

+ +

+ Another variable you may need is the data variable. For most graph types, this is where the data is stored. It is usually + untouched, so it is as you supplied to the graph objects constructor. A notable exception to this is filled line charts. + Here the original data is stored in the class variable original_data. The data supplied is modified to produce the stacking + effect. If you need to modify a filled line charts data you will need to change this variable instead. +

+ +

+ Not all graph types use the data variable. For some the name is different so that it makes a little more sense. The + graph types and their associate data variables are listed below1. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Graph typeData variable(s)
Barobj.data
Bi-polarobj.left, obj.right
DonutThis is now a variant of the Pie chart
Funnelobj.data
GanttSee the docs
Horizontal Barobj.data
Horizontal Progress barobj.max, obj.value
LEDobj.text
Lineobj.original_data3
Meterobj.min, obj.max, obj.value
Odometerobj.start, obj.end, obj.value
Pieobj.angles, obj.data
Radial Scatter chartobj.data
Roseobj.max, obj.data
Scatterobj.max, obj.data2
Traditional Radarobj.data, obj.max
Vertical Progress barobj.max, obj.value
+ +
    +
  1. In the table, obj refers to your graph object.
  2. +
  3. For the Scatter chart, each data point is an array of X/Y coordinates, the color and the tooltip for that point.
  4. +
  5. + The Line chart obj.original_data is an aggregation of all the datasets given to the Line chart, so the first + dataset is held in obj.original_data[0], the second in obj.original_data[1] etc. +
  6. +
+ + +

Updating your graphs dynamically

+ +

+ Note: + It is important that you're careful with types when making AJAX requests. Since the response is initially a string, + and your AJAX function/library may not do conversions for you, you may need to convert these strings to numbers. To + do this you can use the Number() or parseInt() functions. For example: +

+ +
+<script>
+    num = Number('23');
+    num = parseInt('43');
+</script>
+
+ +

+ A common request is to be able to update graphs dynamically. This is quite simple and consists of three steps: +

+ +
    +
  1. Get the new data from the server (with an AJAX request for example).
  2. +
  3. Set the data in your graph object. See the above table for the appropriate property to use.
  4. +
  5. Call the .Draw() method again.
  6. +
+ +

+ If you don't need to get data from your server (ie it's all client-side) then you can omit the first step. Also, it may be + sufficient to simply recreate the entire object from scratch. This means that you won't have to alter and + RGraph internal properties - just recreate the graph object and configuration. There's a simple function + you can use for AJAX purposes here. +

+ + + +

Setting properties

+ +

+ To set RGraph properties, ideally you should use each objects setter (there's also a corresponding getter). These functions + accomodate some backwards compatibility changes, so by not using them you run the risk of your graphs not working entirely as + expected. +

+ +
+myObj.Set('chart.gutter', 25);
+myObj.Get('chart.gutter');
+
+ + +

 

+

References available on RGraph objects

+

+ RGraph stores various references to objects on the canvas (typically) to make getting hold of them easier. There's also a + Registry object in + which references are stored. Typically the objects are named with the format __xxx__, and you can inspect the + objects by using a console(eg the inspector that's part of Google Chrome - CTRL+SHIFT+J). Some examples are: +

+ + + + These are just a sample of what's available, to find more you should use an introspection tool, look at the source, or ask + on the support mailing list. + + + + +

Scale information

+

+ For the Bar, Bipolar, HBar, Line and Scatter charts the scale that is used is stored in the scale class variable. Eg: +

+ +
+<script>
+    var myBar = new RGraph.Bar('cvs', [56,43,52,54,51,38,46,42,52]);
+    myBar.Draw();
+    
+    var myScale = myBar.scale
+</script>
+
+ + +

Adding text to your graphs

+

+ If you want to add arbitrary text to your graph(s) you can use the API function RGraph.Text(). +

+ +
+<script>
+    // Draw a basic graph
+    var myObj = new RGraph.Bar('myCanvas', [4,5,5,8,7,6,4,8,5,9]);
+    myObj.Draw();
+    
+    // Draw some text
+    myObj.context.beginPath();
+        size = 12;
+        font = 'Verdana';
+        text = 'Some text!;
+        x    = 10;
+        y    = 10;
+
+        RGraph.Text(myObj.context, font, size, x, y, text);
+    myObj.context.fill();
+</script>
+
+ + +

RGraph functions

+ +

+ This is a list of some of the functions available to you in the RGraph common libraries. + It's not every single one that's available, but is a list of the common ones that you're likely to want to use. Arguments + in square brackets are optional. +

+ +
+<script src="RGraph.common.core.js"></script>
+
+<script>
+    // Returns 9
+    myArray = [3,2,5,4,9,7,8];
+    max = RGraph.array_max(myArray);
+</script>
+
+ + +

Arrays

+ + + + +

Strings

+ + + + +

Numbers

+ + + + +

Miscellaneous

+ + + + +

Custom RGraph event related functions

+ + + + +

Other

+ +

+ These are functions which are less generic, and used to build the graphs. You may still wish to use them however. +

+ + + + + +

The skeleton file

+

+ The skeleton object + (RGraph.skeleton.js) gives you a base for creating new graph types that + match the RGraph object system (eg getters, setters, RGraph names etc). Example usage of the skeleton object would be: +

+ +
+<script>
+    var myObj = new RGraph.Skeleton('cvs', [3,3,4,5,3,8,3,2,1,9]);
+    myObj.Set('chart.colors', ['red']);
+    myObj.Draw();
+
+    var colors = myObj.Get('chart.colors');
+</script>
+
+ + +

Questions

+ +

+ If you have a question regarding the API, you can ask it on the + mailing list +

+ + \ No newline at end of file diff --git a/RGraph/docs/async.html b/RGraph/docs/async.html new file mode 100644 index 0000000..bdf4f9c --- /dev/null +++ b/RGraph/docs/async.html @@ -0,0 +1,265 @@ + + + + + + + RGraph: HTML5 canvas graph library - Asynchronous processing + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Asynchronous processing

+ + + +

Waiting for onload event...

+ +

+ + + + + These images are here to pad the page and slow down loading so that the window.onload event is slowed. This makes the + difference far more visible. +

+ + [No canvas support] + + + +

+ Asynchronous processing can speed up the display of your graphs, because the browser gets to your code, sets it + going and then continues on rendering the page. Particularly if you have a weighty page, + it can make quite a difference. The RGraph.Async() function itself is very simple, but because it can make + a significant difference to the speed of your page, it is documented here. There's an example of it to the right. + One thing to remember is to ensure your canvas tag is defined first before you set the function that creates + the graph going. +

+ +

+ Although asynchronous processing can speed up your pages, it can also give the appearance of slower pages due to partial + rendering, (ie your pages render a bit at a time). You therefore will need to experiment to get the best result for you. +

+ +
+ +
+<script src="RGraph.common.js"></script>
+<script src="RGraph.line.js"></script>
+
+<canvas id="myCanvas" width="300" height="100">[No canvas support]</canvas>
+
+<script>
+    /**
+    * Create the line graph
+    */
+    function CreateLineGraph ()
+    {
+        var line = new RGraph.Line('myCanvas', [1,2,4,2,1,3,5,6,6,5,3,5]);
+        line.Set('chart.title', 'Sales for Acme Inc.');
+        line.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+        line.Set('chart.hmargin', 10);
+        line.Set('chart.linewidth', 5);
+        line.Set('chart.shadow', true);
+        line.Set('chart.shadow.offsetx', 0);
+        line.Set('chart.shadow.offsety', 0);
+        line.Set('chart.shadow.blur', 15);
+        line.Draw();
+    }
+
+    RGraph.Async(CreateLineGraph);
+</script>
+
+ +

Things to remember

+ + + +

See also

+ + You might also be interested in the alternative, DOMContentLoaded event. + + + \ No newline at end of file diff --git a/RGraph/docs/bar.html b/RGraph/docs/bar.html new file mode 100644 index 0000000..55df870 --- /dev/null +++ b/RGraph/docs/bar.html @@ -0,0 +1,603 @@ + + + + + + RGraph: HTML5 canvas graph library - bar chart documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Bar chart documentation

+ + +

+ The bar graph, along with the line chart, is probably the most configurable of all the charts available, + simply because it's more common. +

+ +

+ The example file is here. +

+ + + +
 
+<script>
+    window.onload = function ()
+    {
+        var data = [280,45,133,166,84,259,266,960,219,311];
+    
+        var bar = new RGraph.Bar('myCanvas', data);
+        bar.Set('chart.labels', ['Richard', 'Alex', 'Nick', 'Scott', 'Kjnell', 'Doug', 'Charles', 'Michelle', 'Mark', 'Alison']);
+        bar.Set('chart.gutter', 45);
+        bar.Set('chart.background.barcolor1', 'rgba(255,255,255,1)');
+        bar.Set('chart.background.barcolor2', 'rgba(255,255,255,1)');
+        bar.Set('chart.background.grid', true);
+        bar.Set('chart.colors', ['rgba(255,0,0,1)']);
+        bar.Draw();
+    }
+</script>
+
+ + +

Properties

+ +

+ You can use these properties to control how the bar graph apears. You can set them by using the Set() method. Eg: +

+ +

+ myBar.Set('name', 'value'); +

+ + + + + + +

Background

+chart.background.barcolor1
+ The color of the background bars, (1 of 2).
Default: white

+ +chart.background.barcolor2
+ The color of the background bars, (2 of 2).
Default: white

+ +chart.background.grid
+ Whether to show the background grid or not.
Default: true

+ +chart.background.grid.color
+ The color of the background grid.
Default: #ddd

+ +chart.background.grid.hsize
+ The horizontal background grid size.
Default: 40

+ +chart.background.grid.vsize
+ The vertical background grid size.
Default: 18

+ +chart.background.grid.width
+ The width that the background grid lines are. Decimals (eg 0.5) are permitted.
Default: 1

+ +chart.background.grid.border
+ Determines whether a border line is drawn around the grid.
Default: true

+ +chart.background.grid.hlines
+ Determines whether to draw the horizontal grid lines.
Default: true

+ +chart.background.grid.vlines
+ Determines whether to draw the vertical grid lines.
Default: true

+ +chart.background.grid.autofit
+ Instead of specifying a pixel width/height for the background grid, you can use autofit and specify how many horizontal and vertical lines you want.
Default: false

+ +chart.background.grid.autofit.numhlines
+ When using autofit this allows you to specify how many horizontal grid lines you want.
Default: 7

+ +chart.background.grid.autofit.numvlines
+ When using autofit this allows you to specify how many vertical grid lines you want.
Default: 20

+ +chart.background.hbars
+ An array of information stipulating horizontal coloured bars. You can use these to indicate limits. Eg: myBar.Set('hbars', [[75, 10, 'yellow'], [85, 15, 'red']]); This would give you two bars, one red and a lower yellow bar. The units correspond to your scale, and are the starting point and the height.
Default: null

+ +

Colors

+chart.strokecolor
+ The color of the outline of the bars.
Default: #666

+ +chart.colors
+ An array of the colors of the actual bars.
Default: An array - ['rgb(0,0,255)', '#0f0', '#00f', '#ff0', '#0ff', '#0f0']

+ +

Margins

+chart.hmargin
+ The horizontal margin (in pixels) of the graph.
Default: 5

+ +chart.gutter
+ The gutter of the graph. This is the area outside of the X and Y axis - where the labels go. If you're short on space for your labels, try increasing this.
Default: 25

+ +

Labels and text

+chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size (in points) of the labels.
Default: 10

+ +chart.text.angle
+ The angle of the horizontal text labels (at the bottom of the graph). This can be one of three values - 0, 45 or 90.
Default: 0 (Horizontal)

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.labels
+ An array of the labels to be used on the graph.
Default: An empty array

+ + + chart.labels.above
+ If true, values will be shown above the bars. For regular and stacked bar charts units are included, whereas for + grouped bar charts they're not (usually there isn't enough space for them). +
Default: false

+ + + chart.labels.above.decimals
+ This stipulates how many decimals are used in the above bar labels. +
Default: 0

+ + + chart.labels.above.size
+ The font size of the above bar labels. Useful if you only have a few bars. +
Default: false

+ + +chart.labels.ingraph
+ An array of labels for the graph which are drawn "inside" the graph. If you have 5 data points then this should have a corresponding number of elements, though there is a shorthand available.
Default: null

+ +chart.ylabels
+ Can be true or false and determines whether the chart has Y axis labels.
Default: true

+ +chart.ylabels.count
+ A value that controls how many Y labels there are. Previously (prior to 8th August 2010) this could be 1,3,5. Now it can be any number, but keep in mind that if you use this it may result in decimals.
Default: 5

+ +chart.xlabels.offset
+ This allows you finer grained control over the X label positioning if you need it.
Default: 0

+ +chart.numyticks
+ The number of Y tickmarks. If you have changed the number of Y labels, you may also want to change this to match.
Default: 10

+ + +

Titles

+ + +chart.title
+The title of the graph, if any.
+Default: null

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.xaxis
+ This allows to specify a title for the X axis.
Default: none

+ +chart.title.yaxis
+ This allows to specify a title for the Y axis.
Default: none

+ +chart.title.xaxis.pos
+ This is multiplied with the gutter to give the position of the X axis title.
Default: 0.25

+ +chart.title.yaxis.pos
+ This is multiplied with the gutter to give the position of the Y axis title.
Default: 0.25

+ +

Shadow

+chart.shadow
+ Whether a drop shadow is applied.
Default: false

+ +chart.shadow.color
+ The color of the shadow.
Default: #666

+ +chart.shadow.offsetx
+ The X offset of the shadow.
Default: 3

+ +chart.shadow.offsety
+ The Y offset of the shadow.
Default: 3

+ +chart.shadow.blur
+ The severity of the shadow blurring effect.
Default: 3

+ +

Scale

+chart.scale.decimals
+ The number of decimal places to display for the Y scale.
Default: 0

+ +chart.scale.point
+ The character used as the decimal point.
Default: .

+ + + chart.scale.round
+ Whether to round the maximum scale value up or not. This will produce slightly better scales in some instances.
+ Default: null

+ + +chart.units.pre
+ The units that the Y axis is measured in. This string is displayed BEFORE the actual number, allowing you to specify values such as "$50".
Default: none

+ +chart.units.post
+ The units that the Y axis is measured in. This string is displayed AFTER the actual number, allowing you to specify values such as "50ms".
Default: none

+ +chart.ymax
+ The optional maximum Y scale value. If not specified then it will be calculated.
Default: null (It's calculated)

+ + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + + + +

Interactive features

+chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.tooltips
+ A numerically indexed array of tooltips that are shown when a bar is clicked. These can contain HTML.
Default: null

+ +chart.tooltips.effect
+ The animated effect used for showing tooltips. Can be either fade or expand.
Default: fade

+ +chart.tooltips.event
+ This is the event that triggers the tooltips. It can be either onclick or onmousemove.
Default: onclick

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.tooltips.coords.adjust
+ When you translate (to make the best use of space for example) this allows you to adjust the tooltip coordinates accordingly.
Default: [0,0]

+ +chart.crosshairs
+ If true, you will get a crosshair centering on the current mouse position.
Default: false

+ +chart.crosshairs.linewidth
+ This controls the linewidth of the crosshairs.
Default: 1

+ +chart.crosshairs.color
+ The color of the crosshairs.
Default: #333

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +chart.adjustable
+ Defaulting to false, this determines whether your bar chart will be adjustable.
Default: false

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+ +

Miscellaneous

+chart.line
+ Formerly a boolean, this now stipulates a line graph object which is to be drawn on top of the bar chart. You can see an example here.
Default: null

+ +chart.variant
+ This simply stipulates whether you want a regular bar chart, a dot chart, a pyramid chart a 3D chart, a sketch or a glassy chart. Possible values are:The pyramid, dot, arrow, sketch and glass variants are only effective for regular bar charts - not grouped or stacked charts.
Default: bar

+ +chart.xaxispos
+ The position of the X axis. This can be bottom or center.
Default: bottom

+ +chart.axis.color
+ The color of the axes.
Default: black

+ +chart.grouping
+ How the bars are grouped, and it should be one of: grouped or stacked
Default: grouped

+ + + +
 
+

Methods

+ + + obj.getBar()

+ This method makes it easier to get hold of which bar has been clicked on, or hovered over. It returns an array of: + + + An example usage is: + +
+<canvas id="cvs" width="600" height="250">[No canvas support]</canvas>
+
+<script src="RGraph.common.core.js"></script>
+<script src="RGraph.bar.js"></script>
+
+<script>
+    myGraph = new RGraph.Bar('myCanvas', [1.2, 1.3, 1.4, 1.5,6,1.9,2,2.1,2.5]);
+    myGraph.Set('chart.labels', ['John', 'Barry', 'Rich', 'Craig', 'Tom', 'Frank', 'Helen', 'Joyce', 'Fred'])
+    myGraph.Draw();
+
+    RGraph.Register(myGraph);
+    
+    myGraph.canvas.onclick = function (e)
+    {
+        RGraph.Redraw();
+    
+        var canvas  = e.target;
+        var context = canvas.getContext('2d');
+        var obj     = canvas.__object__;
+        var coords  = obj.getBar(e);
+        
+        if (coords) {
+            var top    = coords[1];
+            var left   = coords[2];
+            var width  = coords[3];
+            var height = coords[4];
+            
+            context.beginPath();
+                context.strokeStyle = 'black';
+                context.fillStyle = 'rgba(255,255,255,0.5)';
+                context.strokeRect(top, left, width, height);
+                context.fillRect(top, left, width, height);
+            context.stroke();
+            context.fill();
+        }
+    }
+</script>
+
+ + + + \ No newline at end of file diff --git a/RGraph/docs/bipolar.html b/RGraph/docs/bipolar.html new file mode 100644 index 0000000..0dbcdea --- /dev/null +++ b/RGraph/docs/bipolar.html @@ -0,0 +1,370 @@ + + + + + + + RGraph: HTML5 canvas graph library - Bi-polar chart documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Bi-polar chart documentation

+ + + +

+ The Bi-polar chart is good for comparing two things side by side. For example sales trends for two separate years, that you + want to compare. +

+ +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var left  = [5,6,8,9,12,13,4,9];
+        var right = [5,8,4,11,15,26,13,16];
+    
+        var bipolar = new RGraph.Bipolar('myBipolar', left, right);
+        bipolar.Set('chart.colors', ['#fff', '#eef', '#ddf', '#ccf', '#bbf', '#bbf', '#aaf', '#99f']);
+        bipolar.Set('chart.margin', 3);
+        bipolar.Set('chart.labels', ['Barry', 'John', 'Fred', 'George', 'Rich', 'Larry', 'John', 'Mike']);
+        bipolar.Set('chart.title.left', '2007');
+        bipolar.Set('chart.title.right', '2008');
+        bipolar.Set('chart.gutter', 35);
+        bipolar.Draw();
+    }
+</script>
+
+ + +

Properties

+ +

+ You can use these properties to control how the chart apears. You can set them by using the Set() method. Eg: +

+ +

+ myBipolar.Set('name', 'value'); +

+ + + + + + +

Margins

+chart.gutter
+ The space given over to the labels.
Default: 25

+ +chart.margin
+ The space above and below each bar.
Default: 2

+ +

Titles

+ +chart.title
+The main title of the chart.
+Default: (An empty string)

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.color
+ The color of the title.
Default: black

+ + +chart.title.left
+ The left title.
Default: An empty string

+ +chart.title.right
+ The right title.
Default: An empty string

+ + +

Colors

+ + + chart.colors
+ An array of colors. These too can be gradients that you make if you wish.
+ Default: ['#fcf', '#00f', '#f00', '#0f0', '#ff0', '#0ff', '#f0f', '#ff6101', '#b401ff', '#e4ff01', '#fb8195', '#ccc']

+ + + chart.strokestyle
+ This is the color used as the stroke style. If you didn't want it, you could set this to rgba(0,0,0,0)
+ Default: #333

+ + +

Labels, text and axes

+chart.xtickinterval
+ The X tick mark interval.
Default: null

+ +chart.axis.color
+ The color of the axes.
Default: black

+ +chart.xmax
+ This allows you to set the maximum X value that the chart uses, instead of it being auto-generated.
Default: null


+ +chart.scale.decimals
+ This allows you to set the precision of the X labels.
Default: null

+ +chart.scale.point
+ The character used as the decimal point.
Default: .

+ +chart.scale.thousand
+ The character used as the thousand separator
Default: ,

+ +chart.labels
+ An array of the graphs labels (they go in the middle).
Default: null

+ +chart.text.size
+ The size of the text used (in points).
Default: 10

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +

Scale

+ + + + chart.scale.round
+ Whether to round the maximum scale value up or not. This will produce slightly better scales in some instances.
+ Default: null

+ +chart.units.pre
+ The units that are applied to the X axis labels (these are pre-pended to the number).
Default: none

+ +chart.units.post
+ The units that are applied to the X axis labels (these are appended to the number).
Default: none

+ +

Interactive features

+chart.tooltips
+ A numerically indexed array of tooltips that are shown when a bar is clicked. These can contain HTML.
Default: An empty array

+ +chart.tooltips.effect
+ The animated effect used for showing tooltips. Can be either fade or expand.
Default: fade

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.contextmenu
+ An array of context menu items. Cannot be used in conjunction with tooltips.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +

Shadow

+chart.shadow
+ Turns the shadow on or off.
Default: false

+ +chart.shadow.color
+ The color of the shadow.
Default: #666

+ +chart.shadow.offsetx
+ The horizontal offset of the shadow.
Default: 3

+ +chart.shadow.offsety
+ The vertical offset of the shadow.
Default: 3

+ +chart.shadow.blur
+ How severe the blurring effect is for the shadow.
Default: 3

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+

+ + + \ No newline at end of file diff --git a/RGraph/docs/color.html b/RGraph/docs/color.html new file mode 100644 index 0000000..6929859 --- /dev/null +++ b/RGraph/docs/color.html @@ -0,0 +1,274 @@ + + + + + + + RGraph: HTML5 canvas graph library - About canvas color definitions + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - About canvas color definitions

+ + + +

+ You will probably want to know the different ways you can define a color. There are a few + ways which you can use, all of which are quite straight-forward. +

+ + + + +
 
+

Named colors

+ +

+ The first, and easiest, is to use named colors. This gives you a range of color values that have been predefined for you. Eg: +

+ +
myObject.Set('chart.colors', ['red', 'blue']);
+ + +
 
+

Hex values

+ +

+ The next, is straight forward hex values like you can use in normal CSS. These consist of a hash sign, + followed by three or six hexadecimal characters. Eg: +

+ +
myObject.Set('chart.colors', ['#f00', '#0000ff']);
+ + +
 
+

RGB values

+ +

+ Also as used in CSS, RGB values are the same as what you can use in CSS. Eg: +

+ +
myObject.Set('chart.colors', ['rgb(255,0,0)', 'rgb(0,0,255)']);
+ + +
 
+

RGBA values

+ +

+ Probably new to most people, is rgba(). Similar to regular rgb() values, but with a fourth value that allows you to specify the + alpha value, which stipulates how transparent the color is. An alpha value of 0 is totally transparent, and a value of 1, is + totally opaque (ie. you can't see through it). With a value of 1, rgba() acts exactly like rgb(). This example gives you red + and blue colors that are semi-transparent: +

+ +
myObject.Set('chart.colors', ['rgba(255,0,0,0.5)', 'rgba(0,0,255,0.5)']);
+ + +
 
+

HSL() values

+ +

+ Also probably quite new to you, are hsl() values. Much like rgb(), but instead of red green and blue, it allows you to specify + the Hue, Saturation and Light values instead. For example: +

+ +
myObject.Set('chart.colors', ['hsl(255, 100%, 50%)', 'hsl(169, 100%, 50%)']);
+ + +
 
+

HSLA() values

+ +

+ Much like rgb() and rgba(), hsl() has a corresponding hsla() version, which allows you to specify an alpha (transparency) value. + Eg: +

+ +
myObject.Set('chart.colors', ['hsla(255, 100%, 50%, 0.5)', 'hsla(169, 100%, 50%, 0.5)']);
+ + +
 
+

Linear gradients

+ +

+ Gradients can be used in place of color values. You can create a linear gradient like so: +

+ +
myGradient = myObject.context.createLinearGradient(0,0,0,250);
+myGradient.addColorStop(0, 'red');
+myGradient.addColorStop(1, 'blue');
+ +

+ This creates a gradient that goes from red to blue. The gradient starts at 0,0, and finishes at 0,250. ie A vertical + gradient. You may not see the whole gradient - that depends on the extent of the shape you're filling. You can use the gradient + in place of a regular color definition. Eg: +

+ +
myObject.Set('chart.colors', [myGradient]);
+ + +
 
+

Radial gradients

+ +

+ Radial gradients are much like their linear counterparts, but circular, as the name suggests. Eg: +

+ +
myGradient = myObject.context.createRadialGradient(0,0,0,0,0,100);
+myGradient.addColorStop(0, 'red');
+myGradient.addColorStop(1, 'blue');
+
+ +

+ Instead of four arguments, it takes six - the coordinates of the start point along with the radius, and the coordinates + of the end point, along with the radius. After it has been created, you can treat as you would a linear gradient: +

+ +
myObject.Set('chart.colors', [myGradient]);
+ + +
 
+

More information

+ +

+ You can read more about CSS3 color definitions here. +

+ + \ No newline at end of file diff --git a/RGraph/docs/combine.html b/RGraph/docs/combine.html new file mode 100644 index 0000000..4aac7c8 --- /dev/null +++ b/RGraph/docs/combine.html @@ -0,0 +1,481 @@ + + + + + + + RGraph: HTML5 canvas graph library - combining bar and line graphs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Combining charts

+ + + + + + +

Combining bar and line charts

+ + [No canvas support] + + + +

+ This is an example of combining Bar and Line charts. It's quite straight-forward, and the code here shows you how it can be achieved. +

+ +

+ If the values for the line and bar result in different Y scales you may need to specify the chart.ymax property for each graph + so that the scales are the same. The line turns off Y labels so as not to overwrite the Bars labels. +

+ + Tooltips + +

+ You can have tooltips on the Line chart by setting chart.tooltips.highlighting to false, like below. + The order in which you create the graphs is also important, you must define the Bar chart first, and subsequently the Line + chart. +

+ +
line.Set('chart.tooltips.highlighting', false);
+ +

+ Because the tooltips are only triggered by the Line chart, you should put all of the information, for both the Line and the + Bar chart, in the tooltips. +

+ + +

Combining Line charts

+ + + [No canvas support] + + +

+ Another type of chart you may want is a line chart with Y axes on both sides, as illustrated on the right. You should + be careful with this chart type as it can easily lead to confusion. +

+ +

+ This chart is made up from two line charts, one with the Y axis on the left and one on the right. The code that makes up + this chart is below. +

+ +

+ The only reason to combine line charts is to get Y axes on the left and right. If you simply want mutiple lines, + you can do this without combining any charts. See the line chart example page +

+ +
+ +
+<script>
+    window.onload = function
+    {
+        line2 = new RGraph.Line('myCanvas2', [51,22,23,33,35,23,32,45]);
+        line2.Set('chart.hmargin', 10);
+        line2.Set('chart.labels', ['Kiff', 'Wayne', 'Pete', 'Lou', 'Jake', 'Jo', 'Fred', 'Bob']);
+        line2.Set('chart.linewidth', 3);
+        line2.Set('chart.shadow', true);
+        line2.Set('chart.shadow.offsetx', 2);
+        line2.Set('chart.shadow.offsety', 2);
+        line2.Set('chart.ymax', 65);
+        line2.Set('chart.units.post', 'l');
+        line2.Set('chart.gutter', 35);
+        line2.Set('chart.noxaxis', true);
+        line2.Set('chart.noendxtick', true);
+        line2.Set('chart.title', 'An example of axes both sides');
+        line2.Draw();
+
+        line3 = new RGraph.Line('myCanvas2', [42,50,51,23,46,48,65,11]);
+        line3.Set('chart.hmargin', 10);
+        line3.Set('chart.linewidth', 3);
+        line3.Set('chart.shadow', true);
+        line3.Set('chart.shadow.offsetx', 2);
+        line3.Set('chart.shadow.offsety', 2);
+        line3.Set('chart.yaxispos', 'right');
+        line3.Set('chart.noendxtick', true);
+        line3.Set('chart.background.grid', false);
+        line3.Set('chart.ymax', 65);
+        line3.Set('chart.colors', ['blue', 'red']);
+        line3.Set('chart.units.pre', '$');
+        line3.Set('chart.gutter', 35);
+        line3.Set('chart.key', ['Cost', 'Volume']);
+        line3.Set('chart.key.background', 'rgba(255,255,255,0.5)');
+        line3.Draw();
+    }
+</script>
+
+ + + + \ No newline at end of file diff --git a/RGraph/docs/context.html b/RGraph/docs/context.html new file mode 100644 index 0000000..1e19e79 --- /dev/null +++ b/RGraph/docs/context.html @@ -0,0 +1,368 @@ + + + + + + + RGraph: HTML5 canvas graph library - Context menus + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Context menus

+ + + + + + + +
 
+

What are context menus?

+ +

+ Context menus are what you see when you click your right mouse button. With RGraph, you can specify custom menus + for your graphs if you wish. This way you can define custom actions to be associated with menu items. Context menus are a + very easy way to extend the functionality of your graphs, allowing you to associate presentation style functionality + with them. +

+ +

+ Important: Opera does not allow you to customise the context menu, so with this browser you + should use the left mouse button on the graph, instead of the right. +

+ + +
 
+

What do they look like?

+ + An RGraph context menu + +

+ Context menus look like the image on the right. You can of course customise their look by using stylesheets. The CSS classes + you need to use are RGraph_contextmenu_background, RGraph_contextmenu and RGraph_contextmenu_item. Eg: +

+ +
+ +
+<style type="text/css">
+    .RGraph_contextmenu {
+    }
+
+    .RGraph_contextmenu_item {
+    }
+
+    .RGraph_contextmenu_background {
+    }
+</style>
+ +

+ The "! important" is not necessary if you're not overriding a style that is set by the graph script. If you're having trouble, + it's a good idea to use it though. +

+ + +
 
+

Can I have multiple levels of menus?

+ +

+ Yes, as of 24th April 2010 you can have a dual level context menu, which can reduce "option overload" in your user interface. + This example defines a simple context menu: +

+ +
+bar.Set('chart.contextmenu', [
+                              ['Zoom', RGraph.Zoom],
+                              ['Application', [['Login...', function () {ModalDialog.Show('modaldialog_login', 300);}]] ],
+                              null,
+                              ['Cancel', function () {}]
+                             ]);
+
+ +

+ As you can see there could easily get to be a lot of arrays, so it may help you during development to structure your code by using + indentation. +

+ + +
 
+

How do I define context menus?

+ +

+ Defining a context menu is quite a simple affair. Eg: +

+ +
+myBar.Set('chart.contextmenu', [
+                                ['Menu item 1', Callback1],
+                                ['Menu item 2', Callback2]
+                               ]);
+ +

+ As you can see, the value is a two dimension array. The second being an array consisting of a string which is used as the name of the + menu item, and a function object (NOT the function name as a string). The function object is the function called when the menu item is selected. +

+ + +
 
+

Can I have "separators"?

+ +

+ Yes. Simply pass null instead of an array as your menu item. Eg: +

+ +
+myBar.Set('chart.contextmenu', [
+                                ['Menu item 1', Callback1],
+                                null,
+                                ['Menu item 2', Callback2]
+                               ]);
+ + +
 
+

How do I bypass them?

+ +

+ If for any reason you wish to access the browsers own context menu, you can hold down your CTRL key on your keyboard when you + click, and the canvas context menu will be bypassed. Try it on the graph below by holding your CTRL key whilst right clicking. +

+ + +
 
+

What can I use them for?

+ +

+ Since the context menu items run Javascript functions when selected, you can use them for pretty much + anything you want. For example you could make a presentation system, with the context menu controlling which + graph is shown on the canvas. For example: +

+ +
+ [No canvas support] +
+ + +

Is there an example file that uses the CSS classes?

+ +

+ You can take a look at the bottom of the CSS file for this website. +

+ + +
 
+

Context menus, Macs, Safari, Opera and MSIE 9

+ +

+ Mac Safari, Mac Firefox, Windows Safari and MSIE 9 (beta 1) can have trouble displaying the context menu. So for this reason, for these browsers, + the context menu is attached to a double click of the left mouse button. Opera doesn't support customising the context menu so + this browser also uses a left mouse button double click to trigger the context menu. +

+ + + + + \ No newline at end of file diff --git a/RGraph/docs/css.html b/RGraph/docs/css.html new file mode 100644 index 0000000..4bedc4f --- /dev/null +++ b/RGraph/docs/css.html @@ -0,0 +1,326 @@ + + + + + + + RGraph: HTML5 canvas graph library - available CSS classes + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Available CSS classes

+ + + +

+ This is information about the CSS classes available to you to allow you to customise the appearance of tooltips and + context menus. +

+ + + + +
 
+

RGraph_png

+

+ This controls the appearance of the PNG image which is shown when you use the context menu option RGraph.showPNG(). +

+ + +
 
+

RGraph_palette

+

+ This controls the appearance of the mini-palette that can be used with annotating. +

+ + +
 
+

RGraph_tooltip

+

+ This controls the appearance of tooltips. The default is to have them look like Windows tooltips. +

+ + +
 
+

RGraph_contextmenu

+

+ This controls how context menus appear. The default is similar to the look that Windows XP has. +

+ + +
 
+

RGraph_contextmenu_item

+

+ This controls how individual items on the context menu will appear, for example the default has roughly 25px padding-left + to accomodate the left bar. +

+ + +
 
+

RGraph_contextmenu_background

+

+ This is the Windows XP style left vertical bar. By default this is light grey. +

+ + +
 
+

RGraph_zoom_window

+

+ This is the class to use if you want to customise the mini-zoom window. +

+ + +
 
+

RGraph_zoomed_canvas

+

+ This is the class to use if you want to customise the full canvas zoom. +

+ + +
 
+

RGraph_zoomed_area

+

+ This is the class to use if you want to customise the zoomed area. +

+ + +
 
+

ModalDialog_background

+

+ This class controls the dark semi-opaque background for the ModalDialog. +

+ + +
 
+

ModalDialog_dialog

+

+ This class controls the ModalDialog itself. +

+ + +
 
+

ModalDialog_topbar

+

+ This class controls the top bar for the ModalDialog. You could, for example, use the display CSS property to + hide this if you don't want it. +

+ + +
 
+

Example usage

+

+ Here is an example of using the CSS classes. At the time of writing, some of the items here were only implemented in newer + web browsers: +

+ +
+<style>
+    .RGraph_png {
+    }
+
+    .RGraph_palette {
+    }
+
+    .RGraph_tooltip {
+    }
+    
+    .RGraph_contextmenu {
+    }
+    
+    .RGraph_contextmenu_background {
+    }
+    
+    .RGraph_contextmenu_item {
+    }
+    
+    .RGraph_zoom_window {
+    }
+    
+    .RGraph_zoomed_canvas {
+    }
+    
+    .RGraph_zoomed_area {
+    }
+    
+    .ModalDialog_background {
+    }
+    
+    .ModalDialog_dialog {
+    }
+    
+    .ModalDialog_topbar {
+    }
+</style>
+
+ + +
 
+

! important

+ +

+ If you're attempting to override default styles, then because of the ordering (ie the script is setting the style AFTER + your own CSS) you may need to use the "! important" modifier, for example: +

+ +
+<style>
+    .RGraph_tooltip {
+        background-color: white ! important;
+    }
+</style>
+
+ + \ No newline at end of file diff --git a/RGraph/docs/domcontentloaded.html b/RGraph/docs/domcontentloaded.html new file mode 100644 index 0000000..bce4c83 --- /dev/null +++ b/RGraph/docs/domcontentloaded.html @@ -0,0 +1,252 @@ + + + + + + + RGraph: HTML5 canvas graph library - DOMContentLoaded event + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - DOMContentLoaded example

+ + + +

Waiting for onload event...

+ + + + +

+ + + + + These images are here to pad the page and slow down loading so that the window.onload event is slowed. This makes the + difference far more visible. +

+ + [No canvas support] + +

+ The DOMContentLoaded event is an extremely useful event and can make a big impact on the performance of your pages, hence this + example. The DOMContentLoaded event fires when the pages HTML and scripts have loaded, but not necessarily any images or CSS. + This can make a big improvement on the apparent speed of your page(s). +

+ +

+ You can read more about the DOMContentLoaded event on the Mozilla site, here, + and the Microsoft site here. +

+ +
+ +
+function createGraph(func)
+{
+    if(window.addEventListener) {
+        window.addEventListener('DOMContentLoaded', func, false);
+    } else {
+        document.attachEvent("onDOMContentLoaded", func);
+    }
+}
+
+ +

Browser support

+ +

+ The DOMContentLoaded event is supported by the following browsers: +

+ + + +

See also

+ + You might also be interested in asynchronous graph creation as an alternative. + + + \ No newline at end of file diff --git a/RGraph/docs/donut.html b/RGraph/docs/donut.html new file mode 100644 index 0000000..a7b8c9f --- /dev/null +++ b/RGraph/docs/donut.html @@ -0,0 +1,168 @@ + + + + + + + RGraph: HTML5 canvas graph library - donut chart documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Donut chart documentation

+ + +

+ The Donut chart was formerly a separate chart, however it's now simply a variant of the Pie chart. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var data = [45,57,48,32];
+    
+        var donut = new RGraph.Pie('myDonut', data);
+        donut.Set('chart.labels', ['Jan', 'Ben', 'Mark', 'Lucy']);
+        donut.Set('chart.linewidth', 5);
+        donut.Set('chart.strokestyle', 'white');
+        donut.Set('chart.tooltips', ['Jan', 'Ben', 'Mark', 'Lucy']);
+        donut.Set('chart.variant', 'donut');
+        donut.Draw();
+    }
+</script>
+
+ + + + + \ No newline at end of file diff --git a/RGraph/docs/downloads b/RGraph/docs/downloads new file mode 100644 index 0000000..2b4a17c --- /dev/null +++ b/RGraph/docs/downloads @@ -0,0 +1,2 @@ + + + + + + + RGraph: HTML5 canvas graph library - Retrieving a PNG of your graph + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Updating your graphs dynamically

+ + + + [No canvas support] + + +

+ The example on the right shows a line chart that automatically updates itself every 250 milliseconds. An ideal + use for this could be showing a networks bandwidth usage, or a servers load value. +

+ +

+ This particular example shows a stacked line chart with two data series, though if you're showing load/stress values, a + non-filled chart might be a better choice. +

+ +

+ To get up-to-date data from your server you could simply have the page refresh itself, storing the data on the server, + or use AJAX if you want the data stored client-side. +

+ +

+ Be careful of the data types you use to pass the data to RGraph - you should use numbers to represent values, not strings. +

+ +
+ +
+<canvas id="cvs" width="600" height="250">[No canvas support]</canvas>
+
+<script>
+    d1 = [];
+    d2 = [];
+    
+    // Pre-pad the arrays with 100 null values
+    for (var i=0; i< 100; ++i) {
+        d1.push(null);
+        d2.push(null);
+    }
+
+    function getGraph(id, d1, d2)
+    {
+        var graph = new RGraph.Line(id, d1, d2);
+        graph.Set('chart.gutter', 25);
+        graph.Set('chart.background.barcolor1', 'white');
+        graph.Set('chart.background.barcolor2', 'white');
+        graph.Set('chart.title.xaxis', 'Time');
+        graph.Set('chart.filled', true);
+        graph.Set('chart.fillstyle', ['#daf1fa', '#faa']);
+        graph.Set('chart.colors', ['rgb(169, 222, 244)', 'red']);
+        graph.Set('chart.linewidth', 3);
+        graph.Set('chart.ymax', 20);
+        graph.Set('chart.xticks', 25);
+
+        return graph;
+    }
+    
+    function drawGraph (e)
+    {
+        // Clear the canvas and redraw the graph
+        RGraph.Clear(document.getElementById("cvs"));
+        var graph = getGraph('cvs', d1, d2);
+        graph.Draw();
+        
+        // Add some data to the data arrays
+        d1.push(RGraph.random(5, 10));
+        d2.push(RGraph.random(5, 10));
+        
+        // Get rid of the first values of the arrays
+        if (d1.length > 100) {
+            d1 = RGraph.array_shift(d1);
+            d2 = RGraph.array_shift(d2);
+        }
+
+        setTimeout(drawGraph,250);
+    }
+    
+    drawGraph();
+</script>
+
+ + + \ No newline at end of file diff --git a/RGraph/docs/events.html b/RGraph/docs/events.html new file mode 100644 index 0000000..3a91a1e --- /dev/null +++ b/RGraph/docs/events.html @@ -0,0 +1,303 @@ + + + + + + + RGraph: HTML5 canvas graph library - Custom RGraph events + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Custom RGraph events

+ + + + + + +

Introduction

+ +

+ Custom events allow you to easily interact with and extend RGraph for your own purposes. The list of available events is below, + as is an example of how to make use of them with the RGraph.AddCustomEventListener() function. Event handler functions (ie your + functions) are passed a single parameter - the graph object. With this you can get references to the canvas and context. There's + an example of this below. +

+ +
<script>
+    window.onload = function ()
+    {
+        var line = new RGraph.Line('myLine', [45,12,16,18,44,54,23,21,56]);
+        line.Set('chart.tooltips', ['Fred', 'Barney', 'Jay', 'Pete', 'Frank', 'Bob', 'Ted', 'Lou', 'Kev']);
+        line.Set('chart.labels', ['Fred', 'Barney', 'Jay', 'Pete', 'Frank', 'Bob', 'Ted', 'Lou', 'Kev']);
+        line.Set('chart.hmargin', 5);
+        line.Set('chart.tickmarks', 'dot');
+        line.Draw();
+
+        /**
+        * This is the call to the RGraph function that registers the event listener
+        * 
+        *      line: The graph object
+        * ontooltip: The name of the event
+        *    myFunc: The function that handles the event
+        */
+        RGraph.AddCustomEventListener(line, 'ontooltip', myFunc);
+    }
+
+    /**
+    * The function that is called when the ontooltip event fires. It is  passed a single parameter - the graph object.
+    * With this you can get the ID and references to the canvas and context:
+    *  o obj.id
+    *  o obj.canvas
+    *  o obj.context
+    */
+    function myFunc(obj)
+    {
+        var id      = obj.id;
+        var canvas  = obj.canvas;
+        var context = obj.context;
+
+        alert('This alert was triggered by the custom ontooltip event');
+    }
+</script>
+
+ + +

Available events

+ +

+ + ontooltip
+ This event fires immediately after a tooltip has been created. This event allows you to easily show graphs in your tooltips (tooltip + effects that involve moving the tooltip, eg. contract, expand & snap, will not function). You + can find the tooltip object in the RGraph registry - RGraph.Registry.Get('chart.tooltip'). Note that if you're testing and + using a function that pauses execution (eg alert()), this will also pause any timers (for animation effects etc). If you want to + avoid this you should use a function that doesn't block execution, eg the Firebug/WebKit function, console.log() (you can use the + cl() shortcut in RGraph). +

+ +

+ + oncontextmenu
+ This event fires immediately after the RGraph context menu is shown. If you want it, you can get at the context menu in the + RGraph registry: RGraph.Registry.Get('chart.contextmenu') Like the ontooltip event, using alert() can + pause the fade in timers, so you should consider using the Firebug/Webkit console.log functions instead. +

+ +

+ + onbeforedraw
+ Much like the ondraw event, however this fires at the start of the .Draw() method, in effect "before" the method. +

+ +

+ + ondraw
+ The ondraw event fires after the .Draw() method has run. Note that the interactive features of RGraph may call the .Draw() + method multiple times - the zoom in area mode is a prime example. + A graph with tooltips is also an example. In this case it would demonstrate that the .Draw() method is called twice (and + hence the ondraw event), whereas the ontooltip event only fires once. + +

+ + Note: The ondraw event is not only fired by its own graph, + but (if you're using tooltips for example), can also be fired by other graphs on the page. +

+ +

+ + onzoom
+ The onzoom event fires whenever the canvas is zoomed. When the zoom is in area and canvas modes this fires once, + but when in thumbnail mode this event is like the onmousemove event in that it fires whenever the mouse is moved. +

+ +

+ + onmodaldialog
+ The onmodaldialog event fires when the ModalDialog is shown. This event is easily replicated yourself, though using this event + may help you to keep your code tidy. This event is utilised slightly differently to the other events: + +

ModalDialog.AddCustomEventListener('onmodaldialog', function () {alert('Hello world!');});
+

+ +

+ + onresize
+ The onresize event fires when a canvas is resized. It also fires when the canvas is reset to the original size. +

+ +

+ + onadjust
+ The onadjust event fires whenever one of the supported graph types is adjusted. It usually fires in conjunction with the + onmousemove event, and can be blocked by alert(). You therefore may need to use a different function (eg console.log()) + whilst debugging. +

+ +

+ + onannotatestart
+ The onannotatestart event fires at the beginning of the annotating procedure (ie in a similar vein to the onmousedown event). +

+ +

+ + onannotate
+ The onannotate event fires when the graph has been annotated. It fires during the annotate procedure. +

+ +

+ + onannotateend
+ The onannotateend event fires at the end of the annotating procedure (ie in a similar vein to the onmouseup event). +

+ + \ No newline at end of file diff --git a/RGraph/docs/external.html b/RGraph/docs/external.html new file mode 100644 index 0000000..a8b7ca3 --- /dev/null +++ b/RGraph/docs/external.html @@ -0,0 +1,370 @@ + + + + + + + RGraph: HTML5 canvas graph library - Integrating RGraph with external libraries + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Integrating RGraph with external libraries

+ + + + + + [No canvas support] + +

+ This page shows you how you can easily integrate the graphs with other external Javascript libraries. This particular example + attaches a context menu to the graph, of which the only option is to show a login dialog. This could, for example, be used to + allow logging in to an admin area. +

+ +

+ The dialog doesn't need to require user input - it could just be a static "Please wait..." type dialog, which is shown while a + subsequent page loads that takes a few seconds. +

+ +

+ The ModalDialog was originally an external library, however it's now part of the RGraph package. It's also covered by the + RGraph license - so if you have an RGraph license, then the ModalDialog is part of that. +

+ +

+ +
+<script src="RGraph.common.core.js">
+<script src="RGraph.common.context.js">
+<script src="RGraph.line.js">
+<script src="RGraph.modaldialog.js">
+
+<script>
+    window.onload = function ()
+    {
+        /**
+        * Draw the line graph
+        */
+        var line = new RGraph.Line('myLine', [45,12,16,18,44,54,23,21,56,58,33,47]);
+        line.Set('chart.background.barcolor1', 'white');
+        line.Set('chart.background.barcolor2', 'white');
+        line.Set('chart.tickmarks', null);
+        line.Set('chart.hmargin', 10);
+        line.Set('chart.linewidth', 3);
+        line.Set('chart.shadow', true);
+        line.Set('chart.shadow.offset', 2);
+        line.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+        line.Set('chart.title', 'A line graph with context menu');
+        
+        // This defines a context menu which calls the given function. This function in turn shows the dialog
+        line.Set('chart.contextmenu', [['Login to admin area...', function () {ModalDialog.Show('myDialog', 300);}}]]);
+        
+        line.Draw();
+    }
+</script>
+ +

+ If you're interested in using this modal dialog, then you'll probably also want the CSS that styles it. This can be found in the + "css" directory. +

+ + +

Note about Microsoft Internet Explorer 8 and the ModalDialog

+ +

+ Microsoft Internet Explorer 8 only supports fixed positioning in strict rendering mode, therefore you must specify a DTD + when using this browser. Eg: +

+ +
+<!DOCTYPE html >
+
+ + +

Hiding the ModalDialog

+

+ To hide the ModalDialog (from a "Cancel" button for example), you can use the Close() method: +

+ +
+<input type="reset" value="Cancel" onclick="ModalDialog.Close()">
+
+ + +

Customising the ModalDialog

+

+ You can customise the appearance of the ModalDialog by using three CSS classes, which are documented here. + This page customises the dialog slightly by changing the shadow X/Y offsets: +

+ +
+<style>
+    /*
+    * These are the CSS classes that you can use to customise the appearance of the ModalDialog. If you're trying to
+    * override something which the scripts set, then because of the ordering you may need to use the "! important"
+    * modifier.
+    */
+    
+    /**
+    * This is the semi-opaque background
+    */
+    .ModalDialog_background {
+    }
+
+
+    /**
+    * This is the dialog itself
+    */
+    .ModalDialog_dialog {
+        -webkit-box-shadow: gray 0 0 15px ! important;
+        -moz-box-shadow: 0 0 15px gray ! important;
+        box-shadow: 0 0 15px gray ! important;
+    }
+
+
+    /**
+    * This is gray bar at the top of the dialog
+    */
+    .ModalDialog_topbar {
+    }
+</style>
+
+ + +

ModalDialog integration

+

+ To integrate the ModalDialog look at the sample code above (the key line is where the context menu is defined). The method you should call is ModalDialog.Show(id, width). + The id is the id of the layer to use. Only the .innerHTML is used, not the layer itself, so it can be hidden by + setting the display CSS display property to none. The width is a number which is used as the width of the dialog. +

+ +

+ The only library needed for the ModalDialog to work is RGraph.modaldialog.js - you do not need to use + RGraph.common.js. This makes for far smaller download requirements. + +

+ + + + + + + + + \ No newline at end of file diff --git a/RGraph/docs/funnel.html b/RGraph/docs/funnel.html new file mode 100644 index 0000000..9591adb --- /dev/null +++ b/RGraph/docs/funnel.html @@ -0,0 +1,382 @@ + + + + + + + RGraph: HTML5 canvas graph library - funnel chart documentation + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Funnel chart documentation

+ + +

+ This is a funnel chart. It can be used to illustrate stages of a sales or order fulfillment process, and in doing so highlight any bottlenecks + or steps where large amounts of customers are lost. +

+ +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var funnel = new RGraph.Funnel('funnel1', [100,45,45,26,21,5]);
+        funnel.Set('chart.text.boxed', false);
+        funnel.Set('chart.title', 'Leads through to sales');
+        funnel.Set('chart.labels', ['A', 'B', 'C', 'D', 'E', 'F']);
+        funnel.Set('chart.shadow', true);
+        funnel.Draw();
+    }
+</script>
+
+ + +

Properties

+ +

+ You can use these properties to control how the Funnel chart appears. You can set them by using the Set() method. Eg: +

+ +

+ myFunnel.Set('name', 'value'); +

+ + + + +

Margins

+chart.gutter
+ The gutter of the chart. This is the whitespace area around the chart.
Default: 25

+ +

Colors

+chart.colors
+ These are the colors used for each segment.
Default: ['red', 'green', 'gray', 'blue', 'black', 'white']

+ +

Labels and text

+chart.labels
+ An array of the labels to be used on the graph.
Default: An empty array

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size (in points) of the labels.
Default: 10

+ +chart.text.boxed
+ Whether the text is contained within a white bounding box. In some cases this can help readability.
Default: true

+ +chart.text.halign
+ The horizontal alignment of the text. Can be center or left.
Default: left

+ +

Titles

+chart.title
+ The title of the graph, if any.
Default: null

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.color
+ The color of the title.
Default: black

+ +

Shadow

+chart.shadow
+ Whether a drop shadow is applied to the Funnel chart. The funnel is the first to use the canvas shadow API, and as such they won't be supported on all browsers. Currently only Safari 4+ (possibly earlier versions too), Firefox 3.5+ and Chrome 2+ support canvas shadows.
Default: false

+ +chart.shadow.color
+ The color of the drop shadow.
Default: #666

+ +chart.shadow.blur
+ The severity of the shadow blurring effect.
Default: 3

+ +chart.shadow.offsetx
+ The X offset of the shadow.
Default: 3

+ +chart.shadow.offsety
+ The Y offset of the shadow.
Default: 3

+ +

Interactive features

+chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.tooltips
+ An array of tooltips for the Funnel chart segments.
Default: null

+ +chart.tooltips.effect
+ The animated effect that tooltips use - fade or expand
Default: fade

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ + + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + + + +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+

+ + \ No newline at end of file diff --git a/RGraph/docs/gantt.html b/RGraph/docs/gantt.html new file mode 100644 index 0000000..9f3f376 --- /dev/null +++ b/RGraph/docs/gantt.html @@ -0,0 +1,455 @@ + + + + + + + RGraph: HTML5 canvas graph library - gantt chart documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Gantt chart documentation

+ + + +

+ The Gantt chart can be used to easily represent schedules, making visualising this information far more straightfoward. +

+ + + +

Example

+ +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var gantt = new RGraph.Gantt('gantt');
+        gantt.Set('chart.xmax', 365);
+        gantt.Set('chart.gutter', 35);
+        gantt.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+        gantt.Set('chart.title', 'Holiday schedule for Xyz Ltd');
+        gantt.Set('chart.defaultcolor', 'rgba(255,0,0,1)');
+        gantt.Set('chart.tooltips', ["<b>Richard</b><br />Richard is going on holiday to Malta.<br />He'll be away for 28 days.",
+                                     "<b>Fred</b><br />Fred is also going away for 28 days",
+                                     "<b>Barney</b><br />Barney is off work for two weeks",
+                                     "<b>Gloria</b><br />Gloria is off for 3 weeks",
+                                     "<b>Paul</b><br /> Away for 31 days",
+                                     "<b>Harry</b><br />Away for three weeks",
+                                     "<b>Shane</b><br />Away for one week",
+                                     "<b>Barry</b><br />Away for two weeks",
+                                     "<b>Cynthia</b><br />Away for two weeks",
+                                     "<b>Graham</b><br />Away for August and September",
+                                     "<b>Paul</b><br />Away for 31 days"]);
+        gantt.Set('chart.events'[
+                                 [31, 28, null, 'Richard'],
+                                 [31, 28, null, 'Fred'],
+                                 [59, 14, null, 'Barney'],
+                                 [59, 21, null, 'Gloria'],
+                                 [59, 31, null, 'Paul'],
+                                 [80, 21, null, 'Harry'],
+                                 [94, 7, null, 'Shane'],
+                                 [120, 14, null, 'Barry'],
+                                 [130, 14, null, 'Cynthia'],
+                                 [211, 61, null, 'Graham'],
+                                 [334, 31, null, 'Paul'],
+                                ]);
+        gantt.Set('chart.vbars', [
+                                  [0, 31, 'rgba(192,255,192,0.5)'],
+                                  [59, 31, 'rgba(192,255,192,0.5)'],
+                                  [120, 31, 'rgba(192,255,192,0.5)'],
+                                  [181, 31, 'rgba(192,255,192,0.5)'],
+                                  [243, 30, 'rgba(192,255,192,0.5)'],
+                                  [304, 30, 'rgba(192,255,192,0.5)'],
+                                 ]);
+    
+        gantt.Draw();
+    }
+</script>
+
+ +

Properties

+ +

+ You can use these properties to control how the bar graph apears. +

+ + + + + + +

Chart configuration

+ + chart.xmax
+ Required. This determines how many "units" wide the Gantt chart is. For example to represent a year, you would use 365, giving + a granularity of one day.
+ Default: none

+ + + chart.xmin
+ This option can sometimes make using a Gantt chart spread over several pages easier.
+ Default: 0

+ + + +

Background

+chart.background.barcolor1
+ Color of the background bars
Default: white

+ +chart.background.barcolor2
+ Color of the background bars
Default: white

+ +chart.background.grid
+ Whether a grid is shown as part of the background
Default: true

+ +chart.background.grid.color
+ The color of the background grid.
Default: #eee

+ +chart.background.grid.hsize
+ The size of the horizontal grid.
Default: 20

+ +chart.background.grid.vsize
+ The size of the vertical grid.
Default: 20

+ +chart.background.grid.width
+ The line width of the background grid.
Default: 1

+ +chart.background.grid.autofit
+ Instead of specifying a pixel width/height for the background grid, you can use autofit and specify how many horizontal and vertical lines you want.
Default: false

+ +chart.background.grid.autofit.numhlines
+ When using autofit this allows you to specify how many horizontal grid lines you want.
Default: 7

+ +chart.background.grid.autofit.numvlines
+ When using autofit this allows you to specify how many vertical grid lines you want.
Default: 20

+ +

Margins

+chart.gutter
+ How big the gutter is. This is the top, bottom and right gutters. The left gutter is three times the gutter wide, to accomodate the labels.
Default: 25

+ +

Labels and text

+chart.text.size
+ The size of the text (in points).
Default: 10

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.labels
+ An array of the labels which are applied to the chart.
Default: [] (An empty array)

+ +

Titles

+chart.title
+ The title of the chart.
Default: not set

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +

Interactive features

+chart.tooltips
+ An array of tooltips that are shown when the bars are clicked. They can contain HTML.
Default: [] (An empty array)

+ +chart.tooltips.effect
+ The animated effect used for showing tooltips. Can be either fade or expand.
Default: fade

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.contextmenu
+ An array of context menu items. Cannot be used in conjunction with tooltips.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+ +

Miscellaneous

+chart.borders
+ Whether a border is shown on the event bars
Default: true

+ +chart.defaultcolor
+ The default color of bars. If you don't specify a color for the event, this will be used.
Default: white

+ +chart.events
+ An array of event information that is displayed on the gantt. See below for further information.
Default: [] (An empty array)

+ +chart.vbars
+ Vertical bars used for decorative purposes, or for marking something on the chart (an event for example). See below for further information.
Default: [] (An empty array)

+

+ + +

Adding events to your Gantt chart

+ +

+ To add events, you specify them using the chart.events property. You could use the following to set some events on your gantt chart: +

+ +
gantt.Set('chart.events', [
+                       [31, 28, 75, 'Richard'],
+                       [12, 28, 67, 'Fred'],
+                       [59, 14, 0, 'Barney'],
+                       [59, 21, 5, 'Gloria'],
+                       [46, 31, 94, 'Paul'],
+                       [80, 21, 46, 'Harry'],
+                       [94, 17, 84, 'Shane'],
+                       [34, 14, 32, 'Barry'],
+                       [64, 14, 28, 'Cynthia', 'red', 'yellow'],
+                       [13, 61, 74, 'Graham'],
+                       [84, 31, 16, 'Paul']
+                      ]);
+
+ +

+ The first value is the (zero indexed) start number relative to your chart.xmax. So if you have set your chart.xmax to 62, (to represent + two months), and this value is 31, the start will be the start of the second month. In this case you could give two labels - + ['July', 'August']. +

+ +

+ The second value is the duration. So using the previous example, if you set this to 7, you would have an event lasting a week. +

+ +

+ The third value is the "percentage complete" indicator. This is shown to the right of the event, and is optional - you can + specify null if you wish. +

+ +

+ The fourth value is the label that is used on the left hand side. +

+ +

+ The optional fifth value stipulates the background colour that the bar is. Default is white. +

+ +

+ And the last optional 6th value is the foreground color of the bar. Defaulting to #0c0. +

+ + +

Adding vertical bars to your Gantt chart

+ +

+ You can add decorative vertical bars like so: +

+ +
gantt.Set('chart.vbars', [
+                    [0, 31, 'rgba(192,255,192,0.5)'],
+                    [59, 31, 'rgba(192,255,192,0.5)'],
+                    [120, 31, 'rgba(192,255,192,0.5)'],
+                    [181, 31, 'rgba(192,255,192,0.5)'],
+                    [243, 30, 'rgba(192,255,192,0.5)'],
+                    [304, 30, 'rgba(192,255,192,0.5)'],
+                   ]);
+
+ +

+ You can use these for decorative purposes, or to mark events/limits. The first value is the start index, as above. + The second value is the unit length, again as above. The third value is the color of the vertical bar. +

+ + + \ No newline at end of file diff --git a/RGraph/docs/hbar.html b/RGraph/docs/hbar.html new file mode 100644 index 0000000..cd30f97 --- /dev/null +++ b/RGraph/docs/hbar.html @@ -0,0 +1,489 @@ + + + + + + + RGraph: HTML5 canvas graph library - horizontal bar chart documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Horizontal bar chart documentation

+ + + +

+ The horizontal bar graph is a variation on the bar chart which can be useful when you have larger labels, since you have + more space available to you for them. +

+ +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var data = [280,45,133,166,84,259,266,960,219,311];
+    
+        var hbar = new RGraph.HBar('myCanvas', data);
+        hbar.Set('chart.labels', ['Richard', 'Alex', 'Nick', 'Scott', 'Kjnell', 'Doug', 'Charles', 'Michelle', 'Mark', 'Alison']);
+        hbar.Set('chart.gutter', 45);
+        hbar.Set('chart.background.barcolor1', 'rgba(255,255,255,1)');
+        hbar.Set('chart.background.barcolor2', 'rgba(255,255,255,1)');
+        hbar.Set('chart.background.grid', true);
+        hbar.Set('chart.colors', ['rgba(255,0,0,1)']);
+        hbar.Draw();
+    }
+</script>
+
+ +

Properties

+ +

+ You can use these properties to control how the bar graph apears. You can set them by using the Set() method. Eg: +

+ +

+ myHBar.Set('name', 'value'); +

+ + + + + +

Margins

+chart.gutter
+ The gutter of the graph. This is the area outside of the X and Y axis - where the labels go. If you're short on space for your labels, try increasing this.
Default: 25

+ +

Colors

+chart.colors
+ An array of the colors of the actual bars.
Default: An array - ['rgb(0,0,255)', '#0f0', '#00f', '#ff0', '#0ff', '#0f0']

+ +

Background

+chart.background.barcolor1
+ The color of the background bars, (1 of 2).
Default: white

+ +chart.background.barcolor2
+ The color of the background bars, (2 of 2).
Default: white

+ +chart.background.grid
+ Whether to show the background grid or not.
Default: true

+ +chart.background.grid.color
+ The color of the background grid.
Default: #ddd

+ +chart.background.grid.hsize
+ The horizontal background grid size.
Default: 40

+ +chart.background.grid.vsize
+ The vertical background grid size.
Default: 18

+ +chart.background.grid.width
+ The width that the background grid lines are. Decimals (eg 0.5) are permitted.
Default: 0.5

+ +chart.background.grid.border
+ Determines whether a border line is drawn around the grid.
Default: true

+ +chart.background.grid.hlines
+ Determines whether to draw the horizontal grid lines.
Default: true

+ +chart.background.grid.vlines
+ Determines whether to draw the vertical grid lines.
Default: true

+ +chart.background.grid.autofit
+ Instead of specifying a pixel width/height for the background grid, you can use autofit and specify how many horizontal and vertical lines you want.
Default: false

+ +chart.background.grid.autofit.numhlines
+ When using autofit this allows you to specify how many horizontal grid lines you want.
Default: 14

+ +chart.background.grid.autofit.numvlines
+ When using autofit this allows you to specify how many vertical grid lines you want.
Default: 20

+ +

Labels and text

+chart.labels
+ An array of the labels to be used on the graph.
Default: An empty array

+ + + chart.labels.above
+ This is a boolean which if true, will cause labels to be shown to the right of the bars. (It's called "above" + for API compatibility).
+ Default: false

+ + + chart.labels.above.decimals
+ This is a number which controls how many decimals are shown. It defaults to 0, and since it was added (4th December 2010) + you may need to set this, otherwise no decimals will be shown.
+ Default: 0

+ + +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size (in points) of the labels.
Default: 10

+ +

Titles

+chart.title
+ The title of the graph, if any.
Default: null

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.xaxis
+ This allows to specify a title for the X axis.
Default: none

+ +chart.title.yaxis
+ This allows to specify a title for the Y axis.
Default: none

+ +chart.title.xaxis.pos
+ This is multiplied with the gutter to give the position of the X axis title.
Default: 0.25

+ +chart.title.yaxis.pos
+ This is multiplied with the gutter to give the position of the Y axis title.
Default: 0.5

+ +chart.title.color
+ The color of the title.
Default: black

+ +

Scale and axes

+chart.scale.point
+ The character used as the decimal point.
Default: .

+ +chart.scale.thousand
+ The character used as the thousand separator
Default: ,

+ + + chart.scale.round
+ Whether to round the maximum scale value up or not. This will produce slightly better scales in some instances.
+ Default: null

+ + +chart.xmax
+ (Optional) An optional max figure for the X scale.
Default: none (one is calculated)

+ +chart.yaxispos
+ The position of the Y axis. Works with regular and grouped charts. Can be either center or left.
Default: left

+ +chart.axis.color
+ The color of the axes.
Default: black

+ +chart.units.pre
+ The units that the X axis is measured in. This string is displayed BEFORE the actual number, allowing you to specify values such as "$50".
Default: none

+ +chart.units.post
+ The units that the X axis is measured in. This string is displayed AFTER the actual number, allowing you to specify values such as "50ms".
Default: none

+ +chart.units.ingraph
+ If your units are long, setting this stipulates them to be used for ingraph labels only.
Default: false

+ +

Miscellaneous

+chart.grouping
+ How the bars are grouped, and it should be one of: grouped or stacked
Default: grouped

+ +chart.vmargin
+ The vertical margin that is applied to each individual bar.
Default: 3

+ +chart.strokestyle
+ The color of the outlines of the bars.
Default: black

+ +

Shadow

+chart.shadow
+ Whether a small drop shadow is applied.
Default: false

+ +chart.shadow.color
+ The color of the shadow.
Default: #666

+ +chart.shadow.offsetx
+ The X offset of the shadow.
Default: 3

+ +chart.shadow.offsety
+ The Y offset of the shadow.
Default: 3

+ +chart.shadow.blur
+ The severity of the shadow blurring effect.
Default: 3

+ + + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + + +

Interactive features

+chart.contextmenu
+ An array of context menu items. You cannot have context menus AND tooltips, only one or the other. More information on context menus is here.
Default: [] (An empty array)

+ +chart.tooltips
+ An array of tooltips for the chart.
Default: An empty array

+ +chart.tooltips.effect
+ The visual effect used when showing tooltips. Can be either fade or expand.
Default: fade

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+

+ + + \ No newline at end of file diff --git a/RGraph/docs/hprogress.html b/RGraph/docs/hprogress.html new file mode 100644 index 0000000..a5a2e4d --- /dev/null +++ b/RGraph/docs/hprogress.html @@ -0,0 +1,327 @@ + + + + + + + RGraph: HTML5 canvas graph library - horizontal progress bar documentation + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Horizontal Progress bar documentation

+ + + +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var myProgress = new RGraph.HProgess('myProgress', 78, 100);    
+        myProgress.Set('chart.colors', ['red']);
+        myProgress.Draw();
+    }
+</script>
+
+ +

Properties

+ +

+ You can use these properties to control how the progress bar apears. You can set them by using the Set() method. Eg: +

+ +

+ myProgress.Set('name', 'value'); +

+ + + + + +

Chart configuration

+chart.tickmarks
+ Whether the tickmarks are drawn.
Default: true

+ +chart.tickmarks.color
+ The color used for tickmarks.
Default: black

+ +chart.tickmarks.inner
+ This controls whether the bar has inner tickmarks
Default: false

+ +chart.value
+ The indicated value. You don't need to set this because it's one of the arguments to the constructor.

+ +chart.max
+ The maximum value. You don't need to set this because it's one of the arguments to the constructor.

+ +chart.numticks
+ How many tick marks there are.
Default: 10

+ +chart.numticks.inner
+ How many inner tick marks there are.
Default: 50

+ +chart.arrows
+ This stipulates that two indicator arrows are drawn. It works best if you have tickmarks off, and no title.
Default: false

+ +

Margins

+chart.gutter
+ The size of the gutter.
Default: 25

+ +

Colors

+chart.colors
+ The colors of the bar(s). This can be a solid color, or a gradient that you create.
Default: [#0c0]

+ +chart.background.color
+ The background color.
Default: #eee

+ +

Shadow

+chart.shadow
+ Whether the progress bar has a shadow. This uses the canvas shadow API and therefore is only supported on Chrome 2, Safari 3.1 and Firefox 3.1 (and above).
Default: false

+ +chart.shadow.offsetx
+ The X offset of the progress bar shadow.
Default: 3

+ +chart.shadow.offsety
+ The Y offset of the progress bar shadow.
Default: 3

+ +chart.shadow.color
+ The color of the shadow.
Default: rgba(0,0,0,0.5)

+ +chart.shadow.blur
+ The blurring effect that is applied to the shadow.
Default: 3

+ +

Labels and text

+chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size of the text (in points).
Default: 10

+ +chart.labels
+ Labels that are applied to the graph.
Default: An empty array

+ +

Scale

+chart.units.pre
+ The units that the Y scale is measured in (these are preppend to the number).
Default: none

+ +chart.units.post
+ The units that the Y scale is measured in (these are appended to the number).
Default: none

+ +

Titles

+chart.title
+ The title of the progress bar.
Default: An empty string

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.color
+ The color of the title.
Default: black

+ +

Interactive features

+chart.tooltips
+ An array, albeit one element only. This is shown when the progress bar is clicked on. This can contain HTML.
Default: An empty array

+ +chart.tooltips.effect
+ The animated effect used for showing the tooltip. Can be either fade or expand.
Default: fade

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +chart.adjustable
+ Defaulting to false, this determines whether your progress bar will be adjustable (click the bar and drag it).
Default: false

+ +

Zoom

+chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+

+ + + \ No newline at end of file diff --git a/RGraph/docs/index.html b/RGraph/docs/index.html new file mode 100644 index 0000000..5a368ed --- /dev/null +++ b/RGraph/docs/index.html @@ -0,0 +1,920 @@ + + + + + + + RGraph: HTML5 canvas graph library - documentation + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Documentation

+ + + +

+ The following documentation is available: +

+ +
+

Chart types

+ +
+ +
+

Features

+ +
+ +
+

Miscellaneous

+ + +

On this page:

+ + +
+ + + + + + + +
+
+ + + + +
 
 
+

Benefits of HTML5 canvas graphs

+ +

+ HTML5 introduces a new HTML element - the CANVAS tag. This tag allows for two dimensional drawing easily using Javascript. + This makes it perfect for producing graphs. Because Javascript runs on your users computer, none of the stress on your server + normally associated with producing graphs is incurred. Not only that but because + of the greater processing power that is typically available on users' computers, they will be much faster. And, + because the code can be both compressed (for example if you're using Apache, mod_gzip will do this automatically for you) and + cached, bandwidth usage can be massively reduced. This makes it economically attractive to employ, (ie it can save you + money...). +

+ +

+ Imagine, you are creating 100,000 graphs a day and the data is such that the resulting graphs cannot be cached. With the RGraph + library you can reduce that figure to zero. All the processing and graph creation is done by each individual client, much like + rendering the HTML you send to them. So you don't have to send any images, you simply send them the Javascript libraries once. + So, much lower bandwidth bills and far less strain on your webserver. +

+ +

+ And if that wasn't enough, because the graphs are created using Javascript, they will work offline if you view a .html page + on your own PC. Download the archive and see! Useful if you need to do a presentation for example and want to use the same + graph(s) as your website. +

+ +
+
+
    +
  • Cross browser support.
  • +
  • 17 Different base graph types (Examples).
  • +
  • Graphs work on and off-line.
  • +
  • Interactive features.
  • +
+
+ +
+
    +
  • Graphs are created on the client - no server overhead.
  • +
  • Very easy setup (see Implementing RGraph).
  • +
  • Fully documented.
  • +
  • Very easy to learn.
  • +
+
+
+ + + +
 
 
+

Browser support

+ +

+ Since the graphs are produced using HTML5 features (the new canvas tag), client support is currently: +

+ + + +

+ The HTML5 canvas tag is part of the HTML5 specification, + and all of the above browsers have some sort of support for it. +

+ +

+ Canvas & Microsoft Internet Explorer (MSIE)
+ Microsoft Internet Explorer 8 doesn't natively support the HTML5 <canvas> tag. To support + MSIE 8 you will need to use either + Google Chrome Frame or + ExCanvas from Google + (which is included in the RGraph archive). Read more about Internet Explorer compatibility + here. + +

+ + + Starting with preview 3 Microsoft Internet Explorer 9 has full support for <canvas>. You can view some screenshots + here. + MSIE 6 and 7 are supported by way of Google Chrome Frame. + +

+ +

+ RGraph and older browsers
+ Older browsers (eg Chrome 1, Firefox 3, Safari 3, Opera 9.5) are supported, however if they don't support the canvas shadow or + text APIs, these will naturally be unavailable. Earlier versions of these browsers may work, but are untested. +

+ + +
 
 
+

Improving the performance of your graphs

+ +

+ Although performance is excellent, (traditionally your webserver has been + producing all of your graphs, and now the client produces them, and typically only one at a time), you may still want to tune + RGraph further. The biggest thing you can do is use compression, which reduces the initial download time of the libraries, but + there are a number of things you can do: +

+ + + + A reasonable performance strategy + +

+ Although there's a lot you can do in regards to performance, a few of the points here will suffice for most + websites: + +

+ + The number one thing you should do is compress your libraries. This has multiple benefits and provides by far the most gain, + effectively for free. Secondly, use the minified libraries. Since you can download them here, + you might as well use them. Then we have pre-emptive caching. Since most websites won't show graphs on the front page or will + have a login page that is shown before any graphs, this effectively eliminates the graph library download. And lastly caching + should be done as a matter of course. There's no reason to keep downloading the same library so even caching for only 30 minutes + (or the duration of an average visit to your website) will produce results. +

+ +

+ +

+ + +
 
 
+

Implementing RGraph

+ +

+ Getting RGraph up and running is very easy and consists of three steps. If you're having trouble I suggest you get hold of a copy of + Firefox along with Firebug - its + Javascript error console will make debugging your issue much easier. Many problems are down to a library not having been included or + not using the onload event when you need to. You might also benefit from using the Web Developer toolbar + for Firefox. This allows you to easily disable caching, thus eliminating any problems that that causes. You could equally use + the Chrome developer tools (CTRL+SHIFT+J), optionally in docked mode, which also provides a good quality Javascript console. +

+ +
    +
  1. + Include the libraries (put this in your documents <HEAD>): +
    +<script src="RGraph.common.core.js"></script>
    +
    +<script src="RGraph.common.adjusting.js"></script> <!-- Just needed for adjusting -->
    +<script src="RGraph.common.annotate.js"></script>  <!-- Just needed for annotating -->
    +<script src="RGraph.common.context.js"></script>   <!-- Just needed for context menus -->
    +<script src="RGraph.common.resizing.js"></script>  <!-- Just needed for resizing -->
    +<script src="RGraph.common.tooltips.js"></script>  <!-- Just needed for tooltips -->
    +<script src="RGraph.common.zoom.js"></script>      <!-- Just needed for zoom -->
    +
    +<script src="RGraph.bar.js"></script>              <!-- Just needed for bar graphs -->
    +<script src="RGraph.bipolar.js"></script>          <!-- Just needed for bi-polar graphs -->
    +<script src="RGraph.funnel.js"></script>           <!-- Just needed for funnel charts -->
    +<script src="RGraph.gantt.js"></script>            <!-- Just needed for gantt charts -->
    +<script src="RGraph.hbar.js"></script>             <!-- Just needed for horizontal bar charts -->
    +<script src="RGraph.hprogress.js"></script>        <!-- Just needed for horizontal progress bars -->
    +<script src="RGraph.led.js"></script>              <!-- Just needed for LED charts -->
    +<script src="RGraph.line.js"></script>             <!-- Just needed for line graphs -->
    +<script src="RGraph.meter.js"></script>            <!-- Just needed for meter charts -->
    +<script src="RGraph.odo.js"></script>              <!-- Just needed for odometers -->
    +<script src="RGraph.pie.js"></script>              <!-- Just needed for pie AND donut charts -->
    +<script src="RGraph.rose.js"></script>             <!-- Just needed for rose charts -->
    +<script src="RGraph.rscatter.js"></script>         <!-- Just needed for rscatter charts -->
    +<script src="RGraph.scatter.js"></script>          <!-- Just needed for scatter graphs -->
    +<script src="RGraph.tradar.js"></script>           <!-- Just needed for traditional radar charts -->
    +<script src="RGraph.vprogress.js"></script>        <!-- Just needed for vertical progress bars -->
    +
    +
  2. + +
  3. + Add the canvas tag (put it where you want the graph to appear): +
    +<canvas id="myCanvas" width="600" height="250">[No canvas support]</canvas>
    +
    +
  4. + +
  5. + Create the graph (since it is using the onload event, you can put this anywhere): + +
    +<script>
    +    window.onload = function ()
    +    {
    +        var data = [280, 45, 133, 166, 84, 259, 266, 960, 219, 311, 67, 89];
    +
    +        var bar = new RGraph.Bar('myCanvas', data);
    +        bar.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
    +        bar.Set('chart.gutter', 35);
    +        bar.Draw();
    +    }
    +</script>
    +
    +
  6. +
+ +

+ There's also a very basic example of using RGraph, that does very little. It can be helpful to + illustrate how you can get RGraph up and running. +

+ +

Common library split (17th April 2010)

+

+ The common library has now been split into separate files. This was because the single common library had become far too large. + If you don't use any of the dynamic features, then you still need to change your code, as RGraph.common.js is now + called RGraph.common.core.js. +

+ + +
 
 
+

Suggested structure for RGraph

+ + Suggested structure for RGraph + +

+ The suggested layout structure for the RGraph libraries is shown on the right. The www.example.com folder represents + the root/top level of your website with the javascript directory beneath that. The css and images + folders are shown for + illustrative purposes only. If you follow this layout then your URLs to the RGraph libraries would be: +

+ +

+ /javascript/rgraph/RGraph.common.core.js
+ /javascript/rgraph/RGraph.bar.js
+ etc +

+ +

+ By using this structure you make RGraph easy to update should you need to, and also keep all the RGraph libraries in + one, easy to find, place. +

+ +
+ + +
 
 
+

Integration with server side scripting

+ +

+ This is a very easy process, as easy as sending content to the browser. All you need to do is make the data variable + (as in the example below) contain the data you want to be displayed. Eg: +

+ +
+<script src="RGraph.common.core.js"></script>
+<script src="RGraph.line.js"></script>
+
+<canvas id="myCanvasTag" width="600" height="200">[No canvas support]</canvas>
+
+<script>
+    data = [78,16,26,23,25,51,34,64,84,84];
+
+    line = new RGraph.Line("myCanvasTag", data);
+    line.Set("chart.labels", ["Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov"]);
+    line.Draw();
+</script>
+
+ +

+ To get the above using PHP you could do this: +

+ +
<?php
+    // This simply makes a string out of the array of data
+    $myData = join(',', array(78,16,26,23,25,51,34,64,84,84));
+
+    // This prints out the required HTML markup
+    print('<script src="RGraph.common.core.js"></script>' . "\n");
+    print('<script src="RGraph.line.js"></script>' . "\n\n");
+    print('<canvas id="myCanvasTag" width="600" height="200">[No canvas support]</canvas>' . "\n\n");
+    print('<script>' . "\n");
+    print('    var data = [' . $myData . '];' . "\n\n");
+    print('    var line = new RGraph.Line("myCanvasTag", data);' . "\n");
+    print('    line.Set("chart.labels", ["Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov"]);' . "\n");
+    print('    line.Draw();' . "\n");
+    print('</script>');
+?>
+
+ +

+ Strictly speaking the var isn't necessary, however if you put the code inside a + function (like window.onload), it's probably best to do so as using var will + make the variable local, and not global. So doing so will help prevent naming clashes. +

+ + + +
 
 
+

Integration with PHP & MySQL

+ +

+ This is a simple matter of formatting what you get back from MySQL into a string, as the MySQL dump and PHP code + below shows (it's based on a database called RGraph_example): +

+ +
+#
+# Table structure for table `daily_statistics`
+#
+
+CREATE TABLE `daily_statistics` (
+  `st_day` char(9) NOT NULL,
+  `st_statistics` tinyint(4) NOT NULL,
+  UNIQUE KEY `st_day` (`st_day`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+#
+# Dumping data for table `daily_statistics`
+#
+
+INSERT INTO `daily_statistics` VALUES ('Mon', 124);
+INSERT INTO `daily_statistics` VALUES ('Tue', 95);
+INSERT INTO `daily_statistics` VALUES ('Wed', 64);
+INSERT INTO `daily_statistics` VALUES ('Thu', 94);
+INSERT INTO `daily_statistics` VALUES ('Fri', 75);
+INSERT INTO `daily_statistics` VALUES ('Sat', 98);
+INSERT INTO `daily_statistics` VALUES ('Sun', 84);
+
+ +
+<?php
+    /**
+    * Change these to your own credentials
+    */
+    $hostname = "localhost";
+    $username = "root";
+    $password = "PASSWORD";
+    $database = "RGraph_example";
+    
+    $connection = mysql_connect($hostname, $username, $password) OR die('Could not connect to MySQL: ' . mysql_error());
+    mysql_select_db($database);
+    
+    $result = mysql_query("SELECT st_day, st_statistics FROM daily_statistics");
+    if ($result) {
+    
+        $labels = array();
+        $data   = array();
+    
+        while ($row = mysql_fetch_assoc($result)) {
+            $labels[] = $row["st_day"];
+            $data[]   = $row["st_statistics"];
+        }
+
+        // Now you can aggregate all the data into one string
+        $data_string = "[" . join(", ", $data) . "]";
+        $labels_string = "['" . join("', '", $labels) . "']";
+    } else {
+        print('MySQL query failed with error: ' . mysql_error());
+    }
+?>
+<html>
+<head>
+
+    <!-- Don't forget to update these paths -->
+
+    <script src="libraries/RGraph.common.core.js" ></script>
+    <script src="libraries/RGraph.line.js" ></script>
+
+</head>
+<body>
+    
+    <canvas id="cvs" width="600" height="250">[No canvas support]</canvas>
+    <script>
+        graph = new RGraph.Line('cvs', <?php print($data_string) ?>);
+        graph.Set('chart.background.grid.autofit', true);
+        graph.Set('chart.gutter', 17);
+        graph.Set('chart.hmargin', 10);
+        graph.Set('chart.tickmarks', 'endcircle');
+        graph.Set('chart.labels', <?php print($labels_string) ?>);
+        
+        graph.context.translate(12, 0);
+        
+        graph.Draw();
+    </script>
+
+</body>
+</html>
+
+ +

+ This PHP code provides the data in two strings - $labels_string and $data_string. These variables are then used + in the RGraph code to provide the data and the labels. +

+ +

Remember:

+ + + + +
 
 
+

Making AJAX requests

+ +

+ Note: + It is important that you're careful with types when making AJAX requests. Since the response is initially a string, + and your AJAX function/library may not do conversions for you, you may need to convert these strings to numbers. To + do this you can use the Number() or parseInt() functions. For example: +

+ +
+<script>
+    num = Number('23');
+    num = parseInt('43');
+</script>
+
+ +

+ Here is a simple function that you could use to get data from your server using AJAX: +

+ +
+<script>
+    /**
+    * Makes an AJAX call. It calls the given callback (a function) when ready
+    * 
+    * @param string   url      The URL to retrieve
+    * @param function callback A function object that is called when the response is ready, there's an example below
+    *                          called "myCallback".
+    */
+    function AjaxCall (url, callback)
+    {
+        // Mozilla, Safari, ...
+        if (window.XMLHttpRequest) {
+            var httpRequest = new XMLHttpRequest();
+        
+        // MSIE
+        } else if (window.ActiveXObject) {
+            var httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
+        }
+        
+        httpRequest.onreadystatechange = callback;
+        
+        httpRequest.open('GET', url, true);
+        httpRequest.send();
+    }
+
+
+    /**
+    * This sample callback function is called when the data is ready (readyState=4)
+    */
+    function myCallback ()
+    {
+        if (this.readyState == 4 && this.status == 200) {
+            // Everything is good, the response is received
+            alert(this.responseText);
+        }
+    }
+</script>
+
+ +

And you would use it like this:

+ +
+<script>
+    AjaxCall('http://www.example.com/getSomething.php', myCallback);
+</script>
+
+ +

+ There's an example here that shows updating your graph dynamically. +

+ + + +
 
 
+

Support forum

+ + + + + + + + + + + + + + + + + + + + + + +
+ Google Groups +
+ Subscribe to RGraph support +
+
+ Email: + +
+
+ Visit this group +
+ RSS Feed + Atom XML Feed +
+ + +

+ Support is available via a Google Groups forum. If you think that the issue you have is common, try the issues + page first, and then try searching the forum in case your question has been answered previously. If that all yields nothing, + post a question to the forum. +

+ +

+ If you want to keep up-to-date on RGraph, then subscribe to the group, as I post update notifications here. You can also follow me on + Twitter. I post update notifications here along with HTML5 related news. +

+ +
+
+ + + \ No newline at end of file diff --git a/RGraph/docs/ingraph.html b/RGraph/docs/ingraph.html new file mode 100644 index 0000000..a97293d --- /dev/null +++ b/RGraph/docs/ingraph.html @@ -0,0 +1,224 @@ + + + + + + + RGraph: HTML5 canvas graph library - In-graph labels + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - In-graph labels

+ + + +
+ +

+ This page shows the various options for in-graph labels. The in-graph labels can be set like this: +

+ +
obj.Set('chart.labels.ingraph', [,,'Hoolio',,'Olga']);
+ +

+ Or like this if you want to be more specific: +

+ +
obj.Set('chart.labels.ingraph', [,,['Hoolio', 'red', 'yellow', -1, 60],,'Olga']);
+ +

+ The array can consist of: +

+ + + +

Example line chart

+ + [No canvas support] + + +

Example bar chart

+ + [No canvas support] + + +

Example bar chart (arrow variant)

+ + [No canvas support] + + + +

Example bar chart (dot variant)

+ [No canvas support] + + + + \ No newline at end of file diff --git a/RGraph/docs/issues.html b/RGraph/docs/issues.html new file mode 100644 index 0000000..0225d81 --- /dev/null +++ b/RGraph/docs/issues.html @@ -0,0 +1,248 @@ + + + + + + + RGraph: HTML5 canvas graph library - Common issues + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Common issues

+ + + + + + + + + + + + + + + + + + + + +
+ Google Groups +
+ Subscribe to RGraph support +
+
+ Email: + +
+
+ Visit this group +
+ + +

+ These are some common issues that you should be aware of. If you're having trouble, you may want to look through these to see + if any apply to you or may be the source of your problem. +

+ + +

Tooltips not working as of the October 2010 release

+ +

+ If you're specifying numbers instead of strings for your tooltips, they will not work any more. Simply cast them to + strings, like this: +

+ +
+
+// This WILL NOT work any more
+myBar.Set('chart.tooltips', [56, 67, 53]);
+
+
+// Do any of these instead
+myBar.Set('chart.tooltips', ['56', (67).toString(), String(53)]);
+
+ + +

Annotations aren't saved when running locally in Mozilla Firefox

+ +

+ The solution here is to run the graphs using a web server. At this time (March 2010) only Safari, Chrome and Opera + support saving annotations when running locally. +

+ + +

Missing text in Google Chrome

+ +

+ Since one of the Chrome 4 dev releases there has been an issue with Google Chrome 4 and 5, asynchronous processing and not rendering + graph labels. This has been remedied by simply not using asynchronous processing. Because of the tag placement on the front page, + the effect shouldn't be apparent. Other browsers (eg Firefox, Safari, Opera, MSIE) are fine. +

+ + +

Firefox, tooltips and the clipboard

+ +

+ Firefox, tooltips and using the clipboard is a little convoluted. To copy the text in a tooltip you must do the following: +

+ +
    +
  1. Select the text you want with the mouse.
  2. +
  3. Press CTRL+C (it may be a different key combination if you're not using Windows) to copy the text to the clipboard.
  4. +
+ +

+ Note: Recent versions of Firefox 4 (from beta 6 onwards) appear to work as expected, and you can copy text with the mouse as normal. +

+ +

Shadows in Google Chrome and the line chart

+ +

+ Shadows in recent versions of Google Chrome are somewhat broken. Firefox, MSIE, Opera and Safari are fine. The reason for this + error is a combination of factors it seems - shadow blurring and line width. Fixes have been added to allow shadow blurring and + a 1 pixel linewidth, though some graph types may still be affected. +

+ + + + + \ No newline at end of file diff --git a/RGraph/docs/keys.html b/RGraph/docs/keys.html new file mode 100644 index 0000000..ee26238 --- /dev/null +++ b/RGraph/docs/keys.html @@ -0,0 +1,211 @@ + + + + + + + RGraph: HTML5 canvas graph library - Examples of keys + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Examples of keys

+ +
+ [No canvas support] + [No canvas support] +
+ +

+ As of 4th December 2010 the code that produces the keys has been rewritten. There are two variants of keys available, + a horizontal one designed to sit in the gutter, and a vertical one that is designed to sit on top of (ie over) the graph. +

+ +

+ The actual positioning is now configurable though, so you could have a horizontal key and position it to sit on top + of the chart. +

+ +

Key properties

+ +

+ The available key properties and their defaults are listed below (some graph types have slightly different defaults to + suit): +

+ + + + + + \ No newline at end of file diff --git a/RGraph/docs/led.html b/RGraph/docs/led.html new file mode 100644 index 0000000..da51561 --- /dev/null +++ b/RGraph/docs/led.html @@ -0,0 +1,230 @@ + + + + + + + RGraph: HTML5 canvas graph library - LED Grid documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - LED Grid documentation

+ + + +

+ The LED grid can be used to represent simple letters and numbers. +

+ +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var led = new RGraph.LED('myCanvas', '456461');
+        led.Set('chart.dark', '#666');
+        led.Set('chart.light', 'rgba(255,255,255,1)');
+        led.Draw();
+    }
+</script>
+
+ +

Properties

+ +

+ You can use these properties to control how the LED grid apears. +

+ + + + + +

Chart configuration

+chart.dark
+ Color of the darkened (ie unlit) lights
Default: #eee

+ +chart.light
+ Color of lit lights
Default: #f66

+ +chart.background
+ The color of the background.
Default: white

+ +

Interactive features

+chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+

+ + + \ No newline at end of file diff --git a/RGraph/docs/licensing.html b/RGraph/docs/licensing.html new file mode 100644 index 0000000..8190e8a --- /dev/null +++ b/RGraph/docs/licensing.html @@ -0,0 +1,258 @@ + + + + + + + RGraph: HTML5 canvas graph library - Licensing FAQs + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Licensing FAQs

+ + + +
+
+
+ + + + + + + +
+
+
+ +

+ If you have any questions regarding licensing, these are some FAQs that should help answer them. +

+ +

FAQs

+ + + + + + + + + +
+ Do I need to buy a license?

+ For commercial/business use yes, you need a license to use RGraph. RGraph is not free software. + For non-commercial use (eg personal, charity and educational), RGraph is freely usable and you + don't need to buy a license though. You can read the license itself + here. +
+ + +

 

+ + + How much is a license?

+ A license is a one-time fee of £49 (UK pounds). That's roughly $70 (US dollars) at + the time of writing. + + + +

 

+ + Where can I read the license?

+ The license is further down this page. + +

+ + +

 

+ What does the license cover?

+ The RGraph license covers RGraph as a whole. Excepting ExCanvas, all code that you find in the RGraph archive is + covered by the RGraph license. The license also covers code that I've written that is available from phpguru.org. + This is a mainly + PHP focused website, but also plays host to a fair amount of Javascript too. So if your development language of choice is not PHP, + you may still find something of use there.

+ +

+ + +

 

+ Can you send me an invoice?

+ Of course, simply go here: http://www.rgraph.net/invoice.html, enter your email + address and you'll be sent an invoice that you can use for tax purposes. + +

+ + +

 

+ Can I use PayPal?

+
+
+ + + + +
+
+ Yes, you can use PayPal if you prefer. Please use the PayPal button shown here to start the process. + +

+ + + +

 

+

Contact

+

+ If you have a question about RGraph licensing, you can send it to licensing@rgraph.net + or you can order directly using Google Checkout. +

+ + +

 

+

License

+ +

+ The license text: +

+ + + + \ No newline at end of file diff --git a/RGraph/docs/line.html b/RGraph/docs/line.html new file mode 100644 index 0000000..049da0d --- /dev/null +++ b/RGraph/docs/line.html @@ -0,0 +1,745 @@ + + + + + + + RGraph: HTML5 canvas graph library - line chart documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Line chart documentation

+ + + +

+ The line chart, along with the bar chart, is probably the most configurable of all the charts available. +

+ +

+ The example file is here. +

+ + + +
+<script>
+    window.onload = function ()
+    {
+        var data = [10,4,17,50,25,19,20,25,30,29,30,29];
+    
+        var line = new RGraph.Line("myLine", data);
+        line.Set('chart.background.barcolor1', 'rgba(255,255,255,1)');
+        line.Set('chart.background.barcolor2', 'rgba(255,255,255,1)');
+        line.Set('chart.background.grid.color', 'rgba(238,238,238,1)');
+        line.Set('chart.colors', ['rgba(255,0,0,1)']);
+        line.Set('chart.linewidth', 2);
+        line.Set('chart.filled', true);
+        line.Set('chart.hmargin', 5);
+        line.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+        line.Set('chart.gutter', 40);
+        line.Draw();
+    }
+</script>
+
+ + +

Properties

+ +

+ You can use these properties to control how the bar graph apears. You can set them by using the Set() method. Eg: +

+ +

+ myLine.Set('name', 'value'); +

+ + + + + +

Background

+chart.background.barcolor1
+ The color of the background bars (1 of 2).
Default: rgba(0,0,0,0)

+ +chart.background.barcolor2
+ The color of the background bars (2 of 2).
Default: rgba(0,0,0,0)

+ +chart.background.grid
+ Whether to show the background grid or not.
Default: true

+ +chart.background.grid.color
+ The color of the background grid.
Default: #eee

+ +chart.background.hbars
+ An array of information stipulating horizontal colored bars. You can use these to indicate limits. Eg: myLine.Set('hbars', [[75, 10, 'yellow'], [85, 15, 'red']]); This would give you two bars, one red and a lower yellow bar. The units correspond to your scale, and are the starting point and the height.
Default: null

+ +chart.background.grid.hsize
+ The horizontal size of the grid.
Default: 25

+ +chart.background.grid.vsize
+ The vertical size of the grid.
Default: 25

+ +chart.background.grid.width
+ The width of the background grid.
Default: 1

+ +chart.background.grid.border
+ Determines whether a border line is drawn around the grid.
Default: true

+ +chart.background.grid.hlines
+ Determines whether to draw the horizontal grid lines.
Default: true

+ +chart.background.grid.vlines
+ Determines whether to draw the vertical grid lines.
Default: true

+ +chart.background.grid.autofit
+ Instead of specifying a pixel width/height for the background grid, you can use autofit and specify how many horizontal and vertical lines you want.
Default: false

+ +chart.background.grid.autofit.numhlines
+ When using autofit this allows you to specify how many horizontal grid lines you want.
Default: 7

+ +chart.background.grid.autofit.numvlines
+ When using autofit this allows you to specify how many vertical grid lines you want.
Default: 20

+ +chart.backdrop
+ When enabled this specifies that the line(s) will have a backdrop effect. You can control the transparency with the other backdrop settings).
Default: false

+ +chart.backdrop.size
+ This controls the size/extent of the backdrop effect.
Default: 30

+ +chart.backdrop.alpha
+ This controls how much transparency the backdrop effect has. It can go from 0 - 1.
Default: 0.2

+ +

Labels and text

+ + + chart.labels.above
+ Whether the values are shown in labels drawn above the line.
+ Default: false

+ + + chart.labels.above.size
+ The size of the labels which are drawn above the line.
+ Default: 8

+ + + chart.labels
+ An array of the X labels for the graph.
+ Default: [] (An empty array)

+ + +chart.labels.ingraph
+ An array of labels for the graph which are drawn "inside" the graph. If you have 5 data points then this should have a corresponding number of elements, though there is a shorthand available.
Default: null

+ +chart.ylabels
+ Can be true or false and determines whether the chart has Y axis labels.
Default: true

+ +chart.ylabels.invert
+ Reverses the Y axis so that 0 is at the top, instead of the bottom.
Default: false

+ +chart.ylabels.count
+ A value (1, 3 or 5) that controls how many Y labels there are.
Default: 5

+ +chart.ylabels.inside
+ This controls whether the Y labels are drawn inside the Y axis or not. If your labels are large, this may help.
Default: false

+ +chart.ylabels.inside.color
+ If the Y labels are to be drawn inside the Y axis, this is used as the background color.
Default: rgba(255,255,255,0.5)

+ +chart.xlabels.inside
+ This controls whether the X labels are drawn inside the X axis or not. By using this you can significantly reduce the size of the gutter needed.
Default: false

+ +chart.xlabels.inside.color
+ If the X labels are to be drawn inside the X axis, this is used as the background color.
Default: rgba(255,255,255,0.5)

+ +chart.text.size
+ The size of the text (in points).
Default: 10

+ +chart.text.angle
+ The angle of the horizontal text labels (at the bottom of the graph). Previously this could be 0, 45 or 90, but now (31st July 2010) this can be any angle.
Default: 0 (Horizontal)

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +

Margins

+chart.gutter
+ The gutter of the graph. This is the bit of the graph that the labels are in.
Default: 25

+ +chart.hmargin
+ The size of the horizontal margin. This is on the inside of the axes.
Default: 0

+ +

Colors

+chart.colors
+ An array of line colors.
Default: ['#f00', '#0f0', '', '#00f', '#f0f', '#ff0', '#0ff'] 9

+ +chart.colors.alternate
+ Set this to true if you want your line color(s) to be alternated. See note
Default: false

+ +chart.fillstyle
+ A single color or an array of colors that filled line charts will use.

Important: This used to be a string, and still can be, but can now also be an array.
Default: null

+ +chart.filled
+ Whether the area under the graph is filled or not. This looks best when there is no horizontal margin.
Default: false

+ +chart.filled.range
+ This is useful for indicating a range. Exactly two datasets are required, with the space between them filled. This is useful for indicating a range.The line chart examples page demonstrates this in action.
Default: false

+ +

Shadow

+chart.shadow
+ If true a shadow will be applied to the line.
Default: false

+ +chart.shadow.color
+ The color of the shadow. As well as a single color definition, this can also be an array of colors. This means that if you have multiple lines on your chart, each can have a different shadow color.
Default: rgba(0,0,0,0.5)

+ +chart.shadow.offsetx
+ The X offset in pixels for the shadow.
Default: 3

+ +chart.shadow.offsety
+ The Y offset in pixels for the shadow.
Default: 3

+ +chart.shadow.blur
+ The severity of the shadow blurring effect.
Default: 3

+ +

Interactive features

+chart.tooltips
+ These are tooltips for the line(s). It should be an array of tooltips. If you have multiple lines, simply pass multiple arrays to the Set() method.
Default: [] (An empty array)

+ +chart.tooltips.effect
+ The animated effect used for showing tooltips. Can be either fade or expand.
Default: fade

+ +chart.tooltips.coords.adjust
+ If you translate() before drawing your graph to reduce wasted space, the coords used for tooltips may need adjusting by how much you translate() by. This setting is how to do it. It should be an array of the X/Y adjustments. There's an example of this on the misc documentation page.
Default: [0,0]

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.tooltips.highlight
+ If you don't want/need the graph to be highlighted and thus avoid redrawing, (eg When combining charts), then set this to false.
Default: true

+ +chart.crosshairs
+ If true, you will get a crosshair centering on the current mouse position.
Default: false

+ +chart.crosshairs.linewidth
+ This controls the linewidth of the crosshairs.
Default: 1

+ +chart.crosshairs.color
+ The color of the crosshairs.
Default: #333

+ +chart.contextmenu
+ An array of context menu items. Unlike the bar chart, you CAN have context menus at the same time as tooltips. More information on context menus is here.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only color allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +chart.adjustable
+ Defaulting to false, this determines whether your graph will be adjustable (click a point and drag it).
Default: false

+ +

Titles

+chart.title
+ The title of the chart.
Default: none

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.xaxis
+ This allows to specify a title for the X axis.
Default: none

+ +chart.title.yaxis
+ This allows to specify a title for the Y axis.
Default: none

+ +chart.title.xaxis.pos
+ This is multiplied with the gutter to give the position of the X axis title.
Default: 0.25

+ +chart.title.yaxis.pos
+ This is multiplied with the gutter to give the position of the Y axis title.
Default: 0.25

+ + + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + +

Scale

+chart.units.post
+ The units (if any) that the Y axis is measured in (gets appended to the number)
Default: none

+ +chart.units.pre
+ The units (if any) that the Y axis is measured in (gets preppended to the number)
Default: none

+ +chart.scale.decimals
+ Determines the precision of the numbers used as the scale.
Default: 0

+ +chart.scale.point
+ The character used as the decimal point.
Default: .

+ + + chart.scale.thousand
+ The character used as the thousand separator
Default: ,

+ + + chart.scale.round
+ Whether to round the maximum scale value up or not. This will produce slightly better scales in some instances.
+ Default: null

+ + +chart.ymin
+ The optional minimum Y scale value. If not specified then it will be zero.
Default: null

+ + + chart.ymax
+ The optional maximum Y scale value. If not specified then it will be calculated.
+ Default: null (It's calculated)

+ + chart.outofbounds
+ Normally, out-of-bounds values are not drawn. By setting this to true you can change this behaviour.
+ Default: false

+ + +

Axis properties

+chart.xticks
+ The number of X tickmarks.
Default: null (linked to number of datapoints)

+ +chart.ticksize
+ The size of the tick marks. This only affects certain styles of tickmarks.
Default: 3

+ +chart.tickdirection
+ Whether the ticks are above or below the axis.
Default: -1 (-1 is below, 1 is above)

+ +chart.axis.color
+ The color of the axes.
Default: black

+ +chart.xaxispos
+ The position of the X axis. It can be either bottom or center.
Default: bottom

+ +chart.yaxispos
+ Specifies the Y axis position. Can be left or right.
Default: left

+ +chart.axesontop
+ A minor option, this sets the axes to be redrawn after the graph has been drawn. This is only useful in a certain set of circumstances - the graph is filled and the line width is small.
Default: false

+ +chart.noaxes
+ Whether the axes are drawn
Default: false (the axes ARE drawn)

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+ +

Miscellaneous

+chart.tickmarks
+ What kind of tickmarks to use on the graph. This can be:

Note that "arrow" and "filledarrow" look better with a thinner (1 or 2) linewidth setting. Also note that now (10th August 2010) as well as a string, this can be an array of different tickmark styles.
Default: null

+ +chart.tickmarks.dot.color
+ This is the color of the BORDER around the dot/borderedcircle style tickmarks.
Default: #fff

+ +chart.stepped
+ Draws the line as stepped. Useful for showing stock performance for example.
Default: false

+ +chart.linewidth
+ The width of the line (ie the actual line on the line graph). Note: If your line is stepped and filled, and you don't want a trailing line indicating the last value, you can set this to zero.
Default: 1

+ +chart.variant
+ At present this can only be 3d, and gives a small 3D effect.
Default: null

+

+ + chart.chromefix
+ Since version 6, Chrome has had a shadow bug, which becomes apparent when you use shadow blurring. This value defaults + to true and means that RGraph will skirt the bug with a small fix.
Default: true

+ +

+ + + +

Methods

+ + + obj.getPoint()

+ This method makes it easier to get hold of which point on the Line chart has been hovered over. It returns an array of: + + + + An example usage is: + +
+<canvas id="cvs" width="600" height="300">[No canvas support]</canvas>
+
+<script src="RGraph.common.core.js"></script>
+<script src="RGraph.line.js"></script>
+
+<script>
+    myGraph = new RGraph.Line('cvs', [10,4,2,4,1]);
+    myGraph.Set('chart.hmargin', 10);
+    myGraph.Set('chart.tickmarks', 'endcircle');
+    myGraph.Set('chart.labels', ['Fred','John','Kev','Lou','Pete']);
+    myGraph.Draw();
+
+
+    RGraph.Register(myGraph);
+    
+    myGraph.canvas.onmousemove = function (e)
+    {
+        RGraph.FixEventObject(e);
+
+        var canvas  = e.target;
+        var context = canvas.getContext('2d');
+        var obj     = e.target.__object__;
+      
+        // This is the new method which simplifies getting coordinates
+        var point = obj.getPoint(e);
+      
+      
+        if (point) {
+            
+            canvas.style.cursor = 'pointer';
+            
+            // Is this the same tooltip as the one (if any) that's already being shown
+            if (RGraph.Registry.Get('chart.tooltip') && RGraph.Registry.Get('chart.tooltip').__index__ == point[3]) {
+                return;
+            }
+
+            // Start afresh
+            RGraph.Redraw();
+
+            // Show the tooltip
+            RGraph.Tooltip(canvas, obj.Get('chart.labels')[point[3]], e.pageX, e.pageY, point[3]);
+
+            // Highlight the point
+            context.strokeStyle = 'gray';
+            context.fillStyle = 'white';
+            context.beginPath();
+            context.moveTo(point[1], point[2]);
+            context.arc(point[1], point[2], 2, 0, 6.26, 0);
+            context.stroke();
+            context.fill();
+            
+            return;
+        }
+        
+        canvas.style.cursor = 'default';
+    }
+    
+    window.onclick = function ()
+    {
+        RGraph.Redraw();
+    }
+</script>
+
+ + +

Combining the Line and Bar charts

+ +

+ You can combine the Bar and Line charts with a bit of magic. It's actually quite easy to do. Find out more here. + In the same vein, you can have Y axes on both the left and right. +

+ + + +

Alternative colors

+ +

+ Instead of a string stipulating the color, each element of the colors array can itself be a two element array, + stipulating the up color, and the down color. To use alternating colors you must also stipulate the alternate property: +

+ + +
+myLine.Set('chart.colors.alternate', true);
+myLine.Set('chart.colors', ['red', ['blue', 'yellow'], 'green]);
+
+ + +

Custom tickmarks

+

+ If none of the available tickmark styles are suitable, you can instead specify a function object that draws the tickmark, + enabling you to draw the tickmark yourself. For example: +

+ +
+<script>
+    line.Set('chart.tickmarks', myTick);
+
+    /**
+    * The function that is called once per tickmark, to draw it
+    * 
+    * @param object obj   The graph object
+    * @param array  data  The entire line data
+    * @param number value The individual points value
+    * @param number index The current index, in the data array
+    * @param number x     The X coordinate
+    * @param number y     The Y coordinate
+    * @param string color The color of the line
+    * @param number prevX The previous X coordinate
+    * @param number prevY The previous Y coordinate
+    */
+    function myTick (obj, data, value, index, x, y, color, prevX, prevY)
+    {
+        // Draw your custom tick here
+    }
+</script>
+
+ + \ No newline at end of file diff --git a/RGraph/docs/meter.html b/RGraph/docs/meter.html new file mode 100644 index 0000000..212edfc --- /dev/null +++ b/RGraph/docs/meter.html @@ -0,0 +1,344 @@ + + + + + + + RGraph: HTML5 canvas graph library - meter documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Meter documentation

+ + + +

+ This is the Meter chart. Similar to half the Odometer. The difference is purely visual, but may well be more suited to + a control panel type application. +

+ +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var meter = new RGraph.Meter('myCanvas', 50, 100, 60);
+        meter.Set('chart.contextmenu', [
+                                        ['Show palette', RGraph.Showpalette],
+                                        ['Clear annotations', function () {RGraph.Clear(meter.canvas); meter.Draw();}],
+                                        null,
+                                        ['Cancel', function () {}]
+                                       ]);
+        meter.Set('chart.annotatable', true);
+        meter.Set('chart.label.position', 'inside');
+        meter.Set('chart.title', 'A sample measurement');
+        meter.Set('chart.title.vpos', 0.5);
+        meter.Set('chart.units.post', 'k');
+        meter.Set('chart.red.start', 0);
+        meter.Set('chart.red.end', 3);
+        meterSet('chart.yellow.start', 3);
+        meter.Set('chart.yellow.end', 6);
+        meter.Set('chart.green.start', 6);
+        meter.Set('chart.green.end', 10);
+        meter.Draw();
+    }
+</script>
+
+

Properties

+ +

+ You can use these properties to control how the Meter apears. You can set them by using the Set() method. Eg: +

+ +

+ myMeter.Set('name', 'value'); +

+ + + + + +

Margins

+chart.gutter
+ The gutter of the graph.
Default: 25

+ +

Colors

+chart.border.color
+ The color of the outline (including tickmarks).
Default: black

+ +chart.green.start
+ The value that the green area should begin at.
Default: 35% of the maximum value

+ +chart.green.end
+ The value that the green area should end at.
Default: The maximum value

+ +chart.green.color
+ The color of the green area, (can be any color)..
Default: #207A20

+ +chart.yellow.start
+ The value that the yellow area should begin at.
Default: 10% of the maximum value

+ +chart.yellow.end
+ The value that the yellow area should end at.
Default: 35% of the maximum value

+ +chart.green.color
+ The color of the yellow area, (can be any color)..
Default: #D0AC41

+ +chart.red.start
+ The value that the red area should begin at.
Default: The minimum value

+ +chart.red.end
+ The value that the red area should end at.
Default: 10% of the maximum value

+ +chart.red.color
+ The color of the red area, (can be any color)..
Default: #9E1E1E

+ +

Labels and text

+chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size (in points) of the labels.
Default: 10

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +

Titles

+chart.title
+ The title of the graph, if any.
Default: null

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +

Scale

+chart.units.pre
+ The units that the labels are measured in. This string is displayed BEFORE the actual number, allowing you to specify values such as "$50".
Default: none

+ +chart.units.post
+ The units that the labels are measured in. This string is displayed AFTER the actual number, allowing you to specify values such as "50ms".
Default: none

+ +

Interactive features

+chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively).
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only color allowed for annotations.
Default: black

+ +

Shadow

+chart.shadow
+ If true a shadow will be applied to the meter.
Default: false

+ +chart.shadow.color
+ The color of the shadow.
Default: rgba(0,0,0,0.5)

+ +chart.shadow.offsetx
+ The X offset in pixels for the shadow.
Default: 3

+ +chart.shadow.offsety
+ The Y offset in pixels for the shadow.
Default: 3

+ +chart.shadow.blur
+ The severity of the shadow blurring effect.
Default: 3

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+ +

Miscellaneous

+chart.linewidth
+ The width of the outline of the Meter.
Default: 2

+

+ + \ No newline at end of file diff --git a/RGraph/docs/misc.html b/RGraph/docs/misc.html new file mode 100644 index 0000000..4e80d8b --- /dev/null +++ b/RGraph/docs/misc.html @@ -0,0 +1,668 @@ + + + + + + + RGraph: HTML5 canvas graph library - Miscellaneous + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Miscellaneous documentation

+ + + + + + +
 
 
+

Canvas fallback content and visually impaired users

+ +

+ When using the canvas element you should be aware of the accessibility of your graphs, for example where vision limited users are + concerned. Screen readers, for example, may not be able to convert a graph into something that is reasonable, so you should + consider + doing this yourself, possibly using the canvas fallback content (ie the content in between the canvas tags). A possible example + would be to put a table of data inside the canvas tag that the graph on the canvas represents. Doing this goes a long way + towards making the data available to everyone. You might also wish to consider using the full canvas + zoom or the resizing feature to enable people to enlarge the graph. +

+ + +
 
 
+

Upper and lower limits for horizontal bars

+ +

+ If you don't wish to specify an upper or lower limit for horizontal bars, and you just want them to extend to the upper or lower + limits of the graph, whatever they may be, you can specify null for the value determining how far they extend. For cases where + the X axis is in the middle and you're specifying a negative start value, or you want the bar to extend all the way to the + bottom, you can simply specify an arbitrary length (eg -999999). Eg: +

+ +
myBar.Set('chart.background.hbars', [[0, null, 'green'], [0,-999999,'red']]);
+ + +
 
 
+

Setting the canvas width and height

+ +

+ To set the canvas width and height you must use the HTML width/height attributes and NOT CSS. If you do use CSS, the canvas + will be scaled, and not enlarged, to fit the new width/height. Eg: +

+ +
<canvas id="myCanvas" width="200" height="100">[No canvas support]<canvas>
+ +

+ + +
 
 
+

RGraph and older browsers

+ +

+ Older versions of browsers are supported (assuming they have canvas support), however, if they don't support the canvas text + or shadow APIs these will naturally be unavailable. The graphs will still be drawn, though without shadows or text. +

+ + +
 
 
+

RGraph and Microsoft Internet Explorer

+ +

+ You can now use RGraph with Internet Explorer 8 in conjunction with ExCanvas, (which brings a degree of <canvas> support to MSIE). + Bear in mind though that shadows are not available and thus are simulated. Microsoft Internet Explorer 9 has native <canvas> + support. You can see some screenshots of it here. +

+ + +
 
 
+

Debugging tips

+ +

+ If you're having a hard time debugging your graph, try these: +

+ + + + + + +
 
 
+

Inspecting an RGraph graph

+ +

+ To help when debugging your RGraph graphs and canvas elements, you can use you browsers built in debugging tools. + An example is the WebKit developer tools which are available in Google Chrome and Apple Safari. There is a screenshot + of these tools (in docked mode) here. To view these + tools in Google Chrome press CTRL+SHIFT+J. Inspect the canvas, and then the associated object can be found via + the __object__ property. +

+ + + +
 
 
+

Double click context menus

+ +

+ Windows Opera, Windows Safari, Mac Safari and Mac Firefox all attach the context menu to the double click event (left mouse button), + not the right, in order to make it more reliable. +

+ + + +
 
 
+

Adding your own event handlers

+ +

+ Because each RGraph object exposes the canvas element (the same as what you get from document.getElementById()), + you can use normal procedures to add your own event handlers. Eg If you wanted to add your own onclick handler you could + do this: +

+ +
+<script>
+    var myBar = new RGraph.Bar('cvs', [7,4,2,6,3,4,8]);
+    myBar.Draw();
+
+    myBar.canvas.onclick = function ()
+    {
+    }
+</script>
+
+

+ But what if, for example, you're using an RGraph feature which + uses the event handler that you need? In this case you can use the standard DOM method addEventListener(). This will add + your new event handler without replacing any existing one (ie the one installed by RGraph). For example: +

+ +
+<script>
+    var myBar = new RGraph.Bar('cvs', [7,4,2,6,3,4,8]);
+    myBar.Draw();
+
+    function myFunc ()
+    {
+    }
+
+    myBar.canvas.addEventListener('click', myFunc, false)
+</script>
+
+ + + +
 
 
+

Carriage returns and newlines in labels

+ +

+ You can put carriage returns in your labels by using the string \r\n. This means your labels will span multiple lines. + Like so: +

+ +
myBar.Set('chart.labels', 'John\r\n(Winner!)', ...)
+ + + +
 
 
+

Why is the Traditional Radar chart so called?

+ +

+ Historical reasons. There used to be two Radar charts in RGraph - the TRadar and an older one called the Pseudo radar chart. + The Pseudo Radar chart was converted into the Rose chart. Renaming the TRadar will only cause problems and there's no pressing + reason to do so, so for the moment it remains the TRadar chart. +

+ + + +
 
 
+

Character set issues

+ +

+ If you're seeing strange, unrecognised characters in your text labels or titles, you may need to specify the correct + character set that the browser should use. In PHP you can do this with the header() function (which, as the + name suggests, sends a HTTP header): +

+ +
<?php
+    header("Content-Type: text/html; charset=ISO-8859-1");
+?>
+ +

+ If you use Apache, you could use the header directive, though this may be overridden by other directives, + eg AddDefaultCharset. +

+ + +
 
 
+

How to identify an RGraph object

+ +

+ Because identity can sometimes be a tricky affair, there are a few RGraph properties that you can use to check whether an object + is an RGraph object: +

+ + + + + + + + +
+ + +
+ +
+
+ + + + +
 
 
+

Static Y axis

+ + + + + A static Y axis is useful if you have a wide chart but limited space. Whilst not part of the RGraph libraries itself, it can be + achieved with a little HTML, like the graph shown. The HTML and the script to achieve this is documented in the source + of this page. It involves placing an extra canvas above the graph with the Y axis drawn on it. This canvas doesn't + move when the main canvas scrolls left and right. + +

+ + Note: Because Firefox doesn't support the event.offsetX and event.offsetY properties, and they have to be simulated, + scrolling and tooltips in this case and this browser doesn't work. + + + + + +
+
+ + + + + +
 
 
+

Reducing white space

+ + + + + +

+ If the labels that you have require a large gutter you can reduce the amount of wasted space by using the standard 2D + context method translate(). This effectively moves the coordinate system so that (0,0) is no longer in the top + left corner, but whereever you put it. For example if you translate by (15,-15), the origin will then be 15 pixels right and + 15 pixels up compared to where it was. +

+ +

+ Because the coordinate system is being changed things that rely on coordinates, eg tooltips, will be affected. For this reason + there is the property chart.tooltips.coords.adjust which you can use to tell RGraph that you've translated and the + tooltip coordinates will be adjusted appropriately. +

+ +
+// This moves the graph to the right by 15px, and up by 15px. Do this before the call to .Draw()
+myObject.context.translate(15,-15);
+
+ + + +
+ + + +
 
 
+

In-graph labels

+ +

+ As well as an array of strings, like this: +

+ +
obj.Set('chart.labels.ingraph', ['First label','Second label']);
+ +

+ The string can also be an array, consisting of color and placement information, like this: +

+ +
obj.Set('chart.labels.ingraph', ['First label',['Second label', 'red', 'yellow', -1, 50] ]);
+ + +

+ You can read more information about this here. +

+ + +
 
 
+

Shorthand for in-graph labels

+

+ Instead of providing a full array of null elements for in-graph labels which may get a little unwieldy, + you can instead specify an integer that specifies how many elements to skip. Like this: +

+ +
line.Set('chart.labels.ingraph', [6, 'July', 3, 'November']);
+ +
+
+ + +
 
 
+

DOM2 Event handlers

+

+ All the graphs have now (1st October 2010) been converted to DOM2 for tooltips event registration. This allows them to + be far more co-operative if you're using events. Tooltips will not be compatible with MSIE8 - the graphs will still be + drawn, albeit without tooltips. +

+ + + +
+ + +
 
 
+

Gutter suggestion function

+

+ RGraph now contains a function (RGraph.getGutterSuggest()) that will provide a simple suggestion for the gutter setting. This function is based on the + left gutter and labels and should be considered an approximate value. +

+ +
+ + + + +
 
 
+

Data types

+

+ If your data values aren't the correct type - ie numbers - it can cause problems. Pay particular attention to this + when you're getting your data from data sources which may be classed as strings, such as JSON or AJAX requests. +

+ + + + + +
 
 
+

Creating your own Graph type

+

+ If you wish to create your own graph type, there is a skeleton file + here that you can use as a starting point. + This file contains the bare bones of an RGraph object, such as the .Get() and .Set() methods, as well as examples + of common properties. +

+ + +
 
 
+

Known issues

+ +

+ There's a few known issues documented here +

+ + +

+ + \ No newline at end of file diff --git a/RGraph/docs/msie.html b/RGraph/docs/msie.html new file mode 100644 index 0000000..8db59c2 --- /dev/null +++ b/RGraph/docs/msie.html @@ -0,0 +1,306 @@ + + + + + + RGraph: HTML5 canvas graph library - Microsoft Internet Explorer support + + + + + + + + + + + + + + + + + + + + + + + + +

+ +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Microsoft Internet Explorer (MSIE) support

+ + + +

+ +

+ Microsoft Internet Explorer 9 + +

+ Starting from preview 3, Internet Explorer 9 has support for canvas, including the text and shadow APIs. It also + benefits from hardware acceleration, and quick rendering times. You can see some screenshots + here. +

+
+ +
+ + [No canvas support] + + + + + + +

Introduction

+ +

+ As of December 2009 RGraph now works partially with Internet Explorer without Google Chrome Frame. + Graphs are rendered as VML. You are still recommended to use + Google Chrome Frame to get the best results. + The interactive features are unlikely to work correctly. RGraph only works with Microsoft + Internet Explorer 8. +

+ +

+ Thanks go to everyone involved with the ExCanvas project for providing the ExCanvas library. +

+ + +

Getting hold of ExCanvas

+ +

+ Google ExCanvas is distributed with RGraph in the "excanvas" directory. There is a minified gzip compressed version, along + with the original. +

+ + +

Caveats

+ + + + +

Google Chrome Frame

+

+ Instead of ExCanvas you can also use Google Chrome Frame. This basically turns Internet Explorer into Google Chrome, and fully + supports RGraph. Since it involves a plugin installation, this is a better option if you can fully influence the users PC. If you + can fully influence the users PC however, a better option might be to simply use one of the browsers with native + support. +

+ + +
+ + + +

Using a dynamically created canvas

+

+ If you're creating your canvas dynamically there is an extra step that you must perform to allow it to be recognised by + ExCanvas: +

+ +
+var canvas = document.createElement('CANVAS');
+    canvas.id = 'cvs';
+    canvas.width = 600;
+    canvas.height = 250;
+    canvas.style.border = '1px dashed black';
+document.body.appendChild(canvas);
+
+G_vmlCanvasManager.initElement(canvas);
+
+ + + +
+
+
+ + + + + \ No newline at end of file diff --git a/RGraph/docs/odo.html b/RGraph/docs/odo.html new file mode 100644 index 0000000..fe6dcb2 --- /dev/null +++ b/RGraph/docs/odo.html @@ -0,0 +1,346 @@ + + + + + + + RGraph: HTML5 canvas graph library - Odometer documentation + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Odometer documentation

+ + + +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        // ID, MINIMUM, MAXIMUM, INDICATED VALUE
+        var odo = new RGraph.Odometer('myOdo', 0, 100, 18);
+        
+        odo.Set('chart.green.max', 75);
+        odo.Set('chart.red.min', 90);
+        odo.Set('chart.label.area', 50);
+        odo.Set('chart.needle.thickness', 2);
+    
+        odo.Draw();
+    }
+</script>
+
+ + + +

Properties

+ +

+ You can use these properties to control how the bar graph apears. You can set these properties using the Set() method. +

+ + + + + +

Chart configuration

+chart.value.text
+ Controls whether the value is indicated as a text label in the center of the dial.
Default: false

+ +chart.value.units.pre
+ The pre units used on the textual value.
Default: nothing (An empty string)

+ +chart.value.units.post
+ The post units used on the textual value.
Default: nothing (An empty string)

+ +chart.border
+ This controls the gray border of the Odometer.
Default: false

+ +chart.tickmarks.highlighted
+ This controls whether the tickmarks are highlighted in red/yellow/green.
Default: false

+ +chart.zerostart
+ If you want the top value on your chart to be zero instead of the maximum value, set this to true.
Default: false

+ +

Margins

+chart.gutter
+ The width of the area outside the odometer.
Default: 25

+ +

Colors

+chart.green.max
+ This is the point at which the green area ends.
Default: 75% of the maximum value

+ +chart.red.min
+ This is the point at which the red area starts. The yellow area is between the green and red areas.
Default: 90% of the maximum value

+ +

Labels and text

+chart.labels
+ Instead of using computed numbers, which uses the maximum value, you can specify the Odometer to use textual labels instead, with this option.
Default: null

+ +chart.label.area
+ The width of the area that labels are put in.
Default: 35

+ +chart.text.size
+ The size of the text (in points).
Default: 10

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +

Needle

+chart.needle.width
+ How thick the needle is.
Default: 2

+ +chart.needle.color
+ The color that is applied to the needle.
Default: black

+ +chart.needle.head
+ This controls whether the arrow head on the end of the needle is displayed.
Default: true

+ +chart.needle.type
+ This determines which type of needle is used. It can be pointer or triangle.
Default: pointer

+ +chart.needle.extra
+ With this you can specify a number of extra pointers that will be drawn on the Odometer. An example would be a meter that's used to show upload and download data. An example use:
odo.Set('chart.needle.extra', [[16, 'red'], [24, 'blue']]);

Default: [] (An empty array)

+ +

Title

+chart.title
+ The title text.
Default: no title set

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +

Shadow

+chart.shadow.inner
+ Whether a drop shadow is applied to the inner circle of the Odometer
Default: false

+ +chart.shadow.outer
+ Whether a drop shadow is applied to the whole Odometer.
Default: false

+ +

Interactive features

+chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+ +

Scale

+chart.units.pre
+ The units that the value is measured in. This string is displayed BEFORE the actual value, allowing you to specify values such as "$50".
Default: none

+ +chart.units.post
+ The units that the value is measured in. This string is displayed AFTER the actual value, allowing you to specify values such as "50ms".
Default: none

+ +chart.scale.decimals
+ The number of decimal places to display for the labels.
Default: 0

+

+ + + \ No newline at end of file diff --git a/RGraph/docs/pie.html b/RGraph/docs/pie.html new file mode 100644 index 0000000..ee53f12 --- /dev/null +++ b/RGraph/docs/pie.html @@ -0,0 +1,498 @@ + + + + + + + RGraph: HTML5 canvas graph library - Pie chart documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Pie chart documentation

+ + + +

+ The pie chart can be used, for example, to represent something that is akin to percentages. ie A set of data that + should be taken as part of a whole. +

+ +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var data = [564,155,499,611,322];
+    
+        var pie = new RGraph.Pie('myPie', data);
+        pie.Set('chart.labels', ['Abc', 'Def', 'Ghi', 'Jkl', 'Mno']);
+        pie.Set('chart.linewidth', 5);
+        pie.Set('chart.stroke', '#fff');
+        pie.Draw();
+    }
+</script>
+
+ + + + +

Properties

+ +

+ You can use these properties to control how the pie chart looks. You can set them by using the Set() method. Eg: +

+ +

+ myPie.Set('name', 'value'); +

+ + + + + +

Margins

+chart.gutter
+ The gutter of the graph (for text labels).
Default: 25

+ +

Colors

+chart.colors
+ Colors to be used for the pie segments.
Default: ['rgb(255,0,0)', '#ddd', 'rgb(0,255,0)', 'rgb(0,0,255)', 'rgb(255,255,0)', 'rgb(0,255,255)', 'red', 'pink', 'black', 'white']

+ +chart.strokestyle
+ The color of the seperating lines. By setting this to your background color, and setting the linewidth to approx. 5, it will make the pie chart look "exploded".
Default: #999

+ +

Labels and text

+chart.text.size
+ The size of the text (in points).
Default: 10

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.labels
+ An array of labels to be used for the chart.
Default: [] (an empty array)

+ +chart.labels.sticks
+ Stipulates that small sticks for the labels are shown. The example page has an example of this.
Default: false

+ +chart.labels.sticks.color
+ Sets the color of the label sticks.
Default: #aaa

+ +

Titles

+chart.title
+ The title of the pie chart.
Default: none

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +

Shadows

+chart.shadow
+ Whether a simple shadow effect is applied.
Default: false

+ +chart.shadow.color
+ The color of the shadow.
Default: rgba(0,0,0,0.5)

+ +chart.shadow.blur
+ The severity of the shadow blurring effect.
Default: 3

+ +chart.shadow.offsetx
+ The X offset of the shadow.
Default: 3

+ +chart.shadow.offsety
+ The Y offset of the shadow.
Default: 3

+ +

Interactive features

+ + + chart.tooltips
+ An array of tooltips, starting from the middle right (ie east) axis, and going clockwise sequentially.
+ Default: [] (An empty array)

+ + + chart.tooltips.event
+ This can be onclick or onmousemove and determines which event is used for tooltips.
+ Default: onclick

+ + + chart.tooltips.effect
+ The animated effect used for showing tooltips. Can be either fade or expand.
+ Default: fade

+ + + chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
+ Default: RGraph_tooltip

+ + + chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more + information on the tooltips documentation page
+ Default: null

+ + + +chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ + + + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + + + +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+ +

Scale

+chart.units.pre
+ The units that the value is measured in. This string is displayed BEFORE the actual number, allowing you to specify values such as "$50" and is only used if chart.value.text is true.
Default: none

+ +chart.units.post
+ The units that the value is measured in. This string is displayed AFTER the actual number, allowing you to specify values such as "50ms" and is only used if chart.value.text is true.
Default: none

+ +

Miscellaneous

+chart.align
+ Whether to left, center or right align the pie chart.
Default: center

+ +chart.linewidth
+ By setting this to roughly 5, and setting the strokestyle to the same colour as your background colour,you will get a segment separation effect.
Default: 1

+ +chart.variant
+ This can be either pie (the default) or donut. Setting this to donut is how you get a donut chart.
Default: pie

+ +chart.value.text
+ Set this to true if you want the value displayed in text beow the center of the pointer.
Default: false

+ + + chart.highlight.style
+ Can be either 2d or 3d and determines which style of segment highlighting is used in + conjunction with tooltips.
+ Default: 2d

+ + + chart.highlight.style.2d.color
+ When 2D highlighting for tooltips is used, this controls the color of the highlighting.
+ Default: rgba(255,255,255,0.5)

+ + + +
 
+

Methods

+ + RGraph.getSegment()

+ + RGraph.getSegment() makes it easy to determine which segment of the Pie chart was clicked on. It provides: + + + +
+<script>
+    RGraph.Register(myGraph);
+    
+    myGraph.canvas.onclick = function (e)
+    {
+        RGraph.FixEventObject(e);
+        RGraph.Redraw();
+
+        var canvas  = e.target;
+        var context = canvas.getContext('2d');
+        var obj     = canvas.__object__;
+        var segment = RGraph.getSegment(e);
+        
+        if (segment) {
+            context.fillStyle = 'rgba(255,255,255,0.5)';
+            context.beginPath();
+                
+                // Angles are provided in degrees, so convert them to radians
+                segment[3] /= 57.29;
+                segment[4] /= 57.29;
+            
+                context.moveTo(segment[0], segment[1]);
+                context.arc(segment[0], segment[1], segment[2], segment[3], segment[4], 0);
+            context.stroke();
+            context.fill();
+            
+            e.stopPropagation();
+        }
+    }
+    
+    window.onclick = function (e)
+    {
+        RGraph.Redraw();
+    }
+</script>
+
+ + + \ No newline at end of file diff --git a/RGraph/docs/png.html b/RGraph/docs/png.html new file mode 100644 index 0000000..1c4c676 --- /dev/null +++ b/RGraph/docs/png.html @@ -0,0 +1,249 @@ + + + + + + + RGraph: HTML5 canvas graph library - Retrieving a PNG of your graph + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Retrieving a PNG of your graph

+ + + + + +
+ Get PNG + [No canvas support] +
+ + +

+ RGraph provides an easy way to get a PNG image of your graph. This allows you to + easily save the image locally to use in (for example) a document, spreadsheet or presentation. +

+ +

+ Originally, the function was designed to be used with a context menu, so it is located in the RGraph.common.context.js. + Now though, you do not have to use the function with a context menu, and can instead pass in the canvas as the optional argument. There's an + example of its usage on the first Tradar example. +

+ +
+ +

Include the context menu code:

+
<script src="../libraries/RGraph.common.context.js" ></script>
+ +

Add the context menu:

+
+myGraph.Set('chart.contextmenu', [
+                                  ['Get PNG', RGraph.showPNG],
+                                  null,
+                                  ['Cancel', function () {}]
+                                 ]);
+ +

Using the function without a context menu

+ +

+ If you want to use the function with a piece of text (or an image) as the "link", optionally positioned over the canvas, you can pass + the canvas into the function as an argument, along with the event object. +

+ +
+<!-- This CSS positions the link over the top right of the canvas -->
+<style>
+    span#png_link {
+        position: absolute;
+        left: 450px;
+        top: 30px;
+        border: 1px black solid;
+        padding: 1px;
+        background-color: #eee;
+        cursor: pointer;
+    }
+</style>
+
+<div style="position: relative">
+    <span id="png_link" onclick="RGraph.showPNG(myCanvas, event)">Get PNG</span>
+    <canvas id="cvs" width="600" height="250">[No canvas support]</canvas>
+</div>
+
+ + + \ No newline at end of file diff --git a/RGraph/docs/released.txt b/RGraph/docs/released.txt new file mode 100644 index 0000000..c82ed8a --- /dev/null +++ b/RGraph/docs/released.txt @@ -0,0 +1,416 @@ +This version released on: Fri, 24 Dec 2010 12:51:38 +0000 + +A RGraph +A RGraph/RGraph_ChromeExtension_sample.zip +A RGraph/tests.old +A RGraph/tests.old/ramon.html +A RGraph/tests.old/animated_meter.html +A RGraph/tests.old/context.html +A RGraph/tests.old/zoom.html +A RGraph/tests.old/kwong.html +A RGraph/tests.old/clear.html +A RGraph/tests.old/key.html +A RGraph/tests.old/getPoint.html +A RGraph/tests.old/grafica.html +A RGraph/tests.old/lots-of-points.html +A RGraph/tests.old/above.bar.html +A RGraph/tests.old/set.config.html +A RGraph/tests.old/getSegment.html +A RGraph/tests.old/ralphoid.html +A RGraph/tests.old/pointers.html +A RGraph/tests.old/test4.html +A RGraph/tests.old/scatter_crosshairs.html +A RGraph/tests.old/test6.html +A RGraph/tests.old/browsers.html +A RGraph/tests.old/smoothing.html +A RGraph/tests.old/null.values.html +A RGraph/tests.old/scale2.html +A RGraph/tests.old/boxplots.html +A RGraph/tests.old/sparklines.html +A RGraph/tests.old/getGutterSuggest.html +A RGraph/tests.old/ymin.html +A RGraph/tests.old/scatter_yvalues.html +A RGraph/tests.old/tooltips.html +A RGraph/tests.old/crosshairs.html +A RGraph/tests.old/ajax.html +A RGraph/tests.old/rose.ymin.html +A RGraph/tests.old/gantt-xmin.html +A RGraph/tests.old/scale.html +A RGraph/tests.old/tickmarks.html +A RGraph/tests.old/noxaxis.html +A RGraph/tests.old/ingraph.labels.html +A RGraph/tests.old/animated_line.html +A RGraph/tests.old/line.arguments.html +A RGraph/tests.old/msie.html +A RGraph/tests.old/ie-events.html +A RGraph/tests.old/chrome-text.html +A RGraph/tests.old/trends.html +A RGraph/tests.old/3D-effect.html +A RGraph/tests.old/out-of-bounds.html +A RGraph/tests.old/resize.html +A RGraph/tests.old/mfrancis.html +A RGraph/tests.old/rscatter.ymin.html +A RGraph/tests.old/scatter_vbars.html +A RGraph/tests.old/test3.html +A RGraph/tests.old/smallrunedex.html +A RGraph/tests.old/getBar.html +A RGraph/tests.old/scatter.html +A RGraph/tests.old/log-scale.html +A RGraph/tests.old/kwong2.html +A RGraph/tests.old/highlight.html +A RGraph/tests.old/shadows.html +A RGraph/tests.old/missing.html +A RGraph/tests.old/animated_rose.html +A RGraph/tests.old/scale3.html +A RGraph/robots.txt +A RGraph/scripts +A RGraph/scripts/makedocs.sh +A RGraph/scripts/generate_xml.php +A RGraph/scripts/diff.sh +A RGraph/scripts/makexml.sh +A RGraph/scripts/generate_docs.php +A RGraph/scripts/tests.php +A RGraph/scripts/release.sh +A RGraph/scripts/index.html +A RGraph/scripts/minify +A RGraph/docs +A RGraph/docs/hprogress.html +A RGraph/docs/meter.html +A RGraph/docs/gantt.html +A RGraph/docs/.BC.txt +A RGraph/docs/async.html +A RGraph/docs/tradar.html +A RGraph/docs/color.html +A RGraph/docs/animation.html +A RGraph/docs/.CHANGELOG.txt +A RGraph/docs/odo.html +A RGraph/docs/external.html +A RGraph/docs/context.html +A RGraph/docs/zoom.html +A RGraph/docs/downloads +A RGraph/docs/adjusting.html +A RGraph/docs/css.html +A RGraph/docs/ingraph.html +A RGraph/docs/vprogress.html +A RGraph/docs/.htaccess +A RGraph/docs/licensing.html +A RGraph/docs/hbar.html +A RGraph/docs/combine.html +A RGraph/docs/pie.html +A RGraph/docs/tooltips.html +A RGraph/docs/setconfig.html +A RGraph/docs/domcontentloaded.html +A RGraph/docs/dynamic.html +A RGraph/docs/png.html +A RGraph/docs/forum +A RGraph/docs/funnel.html +A RGraph/docs/line.html +A RGraph/docs/rscatter.html +A RGraph/docs/zoom_thumbnail.html +A RGraph/docs/bipolar.html +A RGraph/docs/donut.html +A RGraph/docs/resizing.html +A RGraph/docs/misc.html +A RGraph/docs/msie.html +A RGraph/docs/.TODO.txt +A RGraph/docs/annotating.html +A RGraph/docs/events.html +A RGraph/docs/bar.html +A RGraph/docs/led.html +A RGraph/docs/scatter.html +A RGraph/docs/index.html +A RGraph/docs/forums +A RGraph/docs/rose.html +A RGraph/docs/api.html +A RGraph/docs/keys.html +A RGraph/docs/issues.html +A RGraph/docs/examples +A RGraph/css +A RGraph/css/common.css +A RGraph/css/ModalDialog.css +A RGraph/css/website.css +A RGraph/css/index.html +A RGraph/css/.htaccess +A RGraph/analog.css +A RGraph/downloads +A RGraph/example-images +A RGraph/example-images/gauge.png +A RGraph/example-images/fuel.png +A RGraph/invoice.html +A RGraph/LICENSE.txt +A RGraph/screenshots +A RGraph/screenshots/led.png +A RGraph/screenshots/bar.png +A RGraph/screenshots/scatter.png +A RGraph/screenshots/rose.png +A RGraph/screenshots/meter.png +A RGraph/screenshots/hprogress.png +A RGraph/screenshots/hbar.png +A RGraph/screenshots/tradar.png +A RGraph/screenshots/pie.png +A RGraph/screenshots/gantt.png +A RGraph/screenshots/odo.png +A RGraph/screenshots/rscatter.png +A RGraph/screenshots/line.png +A RGraph/screenshots/funnel.png +A RGraph/screenshots/bipolar.png +A RGraph/screenshots/donut.png +A RGraph/screenshots/vprogress.png +A RGraph/sitemap.xml +A RGraph/tests +A RGraph/tests/_pie.html +A RGraph/tests/_odo.html +A RGraph/tests/eric.html +A RGraph/tests/chrome6-shadow.html +A RGraph/tests/_rscatter.html +A RGraph/tests/_line.html +A RGraph/tests/css-2D-transforms.html +A RGraph/tests/_bipolar.html +A RGraph/tests/thermometer +A RGraph/tests/thermometer/RGraph.thermometer.js +A RGraph/tests/thermometer/index.html +A RGraph/tests/_vprogress.html +A RGraph/tests/thomas.html +A RGraph/tests/border-radius.html +A RGraph/tests/_bar.html +A RGraph/tests/_scatter.html +A RGraph/tests/scatter_animated.html +A RGraph/tests/GetHeight.html +A RGraph/tests/_hprogress.html +A RGraph/tests/_hbar.html +A RGraph/images +A RGraph/images/barg2.png +A RGraph/images/barg4.png +A RGraph/images/analogo.gif +A RGraph/images/twitter.png +A RGraph/images/barg8.png +A RGraph/images/barc1.gif +A RGraph/images/bara32.png +A RGraph/images/barg2.gif +A RGraph/images/bare32.png +A RGraph/images/bard16.png +A RGraph/images/barg4.gif +A RGraph/images/bari32.png +A RGraph/images/barh16.png +A RGraph/images/barg8.gif +A RGraph/images/html2.png +A RGraph/images/alex.png +A RGraph/images/bard2.png +A RGraph/images/sqg.png +A RGraph/images/bara32.gif +A RGraph/images/bard4.png +A RGraph/images/barh1.png +A RGraph/images/bare32.gif +A RGraph/images/bard16.gif +A RGraph/images/bard8.png +A RGraph/images/bari32.gif +A RGraph/images/barh16.gif +A RGraph/images/html2.gif +A RGraph/images/download-stable-sml.png +A RGraph/images/bard2.gif +A RGraph/images/bard4.gif +A RGraph/images/barh1.gif +A RGraph/images/bard8.gif +A RGraph/images/bara2.png +A RGraph/images/bara4.png +A RGraph/images/bare1.png +A RGraph/images/bara8.png +A RGraph/images/bari2.png +A RGraph/images/bari4.png +A RGraph/images/bari8.png +A RGraph/images/download.png +A RGraph/images/bara2.gif +A RGraph/images/download-beta-sml.png +A RGraph/images/bara4.gif +A RGraph/images/bare1.gif +A RGraph/images/favicon.ico +A RGraph/images/icons_combined.png +A RGraph/images/reddit.png +A RGraph/images/bard32.png +A RGraph/images/bara8.gif +A RGraph/images/barc16.png +A RGraph/images/bari2.gif +A RGraph/images/barh32.png +A RGraph/images/bari4.gif +A RGraph/images/barg16.png +A RGraph/images/context.png +A RGraph/images/bari8.gif +A RGraph/images/barb1.png +A RGraph/images/.htaccess +A RGraph/images/barf2.png +A RGraph/images/chrome_logo.png +A RGraph/images/barf4.png +A RGraph/images/bard32.gif +A RGraph/images/barj1.png +A RGraph/images/barc16.gif +A RGraph/images/introspection.png +A RGraph/images/border-radius.png +A RGraph/images/barh32.gif +A RGraph/images/barf8.png +A RGraph/images/barg16.gif +A RGraph/images/sq0.png +A RGraph/images/sq2.png +A RGraph/images/coins.jpg +A RGraph/images/sq4.png +A RGraph/images/barb1.gif +A RGraph/images/facebook.png +A RGraph/images/sq6.png +A RGraph/images/png.icon.png +A RGraph/images/sq8.png +A RGraph/images/barf2.gif +A RGraph/images/barf4.gif +A RGraph/images/barj1.gif +A RGraph/images/barf8.gif +A RGraph/images/favicon.png +A RGraph/images/barc2.png +A RGraph/images/barc4.png +A RGraph/images/barg1.png +A RGraph/images/barc8.png +A RGraph/images/structure.png +A RGraph/images/barc2.gif +A RGraph/images/stumble.png +A RGraph/images/barc32.png +A RGraph/images/barc4.gif +A RGraph/images/barg1.gif +A RGraph/images/barb16.png +A RGraph/images/barg32.png +A RGraph/images/barc8.gif +A RGraph/images/download-beta.png +A RGraph/images/barf16.png +A RGraph/images/barj16.png +A RGraph/images/bard1.png +A RGraph/images/barc32.gif +A RGraph/images/barh2.png +A RGraph/images/barb16.gif +A RGraph/images/barh4.png +A RGraph/images/barg32.gif +A RGraph/images/barf16.gif +A RGraph/images/barh8.png +A RGraph/images/barj16.gif +A RGraph/images/rss.png +A RGraph/images/merry-christmas-snowman.png +A RGraph/images/bard1.gif +A RGraph/images/barh2.gif +A RGraph/images/barh4.gif +A RGraph/images/barh8.gif +A RGraph/images/bara1.png +A RGraph/images/bare2.png +A RGraph/images/friendfeed.png +A RGraph/images/bare4.png +A RGraph/images/bari1.png +A RGraph/images/logo.png +A RGraph/images/bare8.png +A RGraph/images/bara1.gif +A RGraph/images/unicef.png +A RGraph/images/barb32.png +A RGraph/images/bara16.png +A RGraph/images/bare2.gif +A RGraph/images/googlegroups.png +A RGraph/images/bare4.gif +A RGraph/images/bari1.gif +A RGraph/images/barf32.png +A RGraph/images/bare16.png +A RGraph/images/bn.personal.png +A RGraph/images/bare8.gif +A RGraph/images/barj32.png +A RGraph/images/bari16.png +A RGraph/images/barb2.png +A RGraph/images/bn.business.png +A RGraph/images/barb4.png +A RGraph/images/barf1.png +A RGraph/images/barb32.gif +A RGraph/images/bara16.gif +A RGraph/images/barb8.png +A RGraph/images/buy.png +A RGraph/images/barj2.png +A RGraph/images/barf32.gif +A RGraph/images/atom.png +A RGraph/images/bare16.gif +A RGraph/images/barj4.png +A RGraph/images/barj32.gif +A RGraph/images/sq1.png +A RGraph/images/bari16.gif +A RGraph/images/barj8.png +A RGraph/images/sq3.png +A RGraph/images/sq5.png +A RGraph/images/barb2.gif +A RGraph/images/sq7.png +A RGraph/images/barb4.gif +A RGraph/images/barf1.gif +A RGraph/images/sq9.png +A RGraph/images/barb8.gif +A RGraph/images/download-stable.png +A RGraph/images/analogo.png +A RGraph/images/delicious.png +A RGraph/images/barj2.gif +A RGraph/images/barj4.gif +A RGraph/images/barj8.gif +A RGraph/images/index.html +A RGraph/images/barc1.png +A RGraph/images/rss_big.png +A RGraph/images/buzz.png +A RGraph/captcha.html +A RGraph/favicon.png +A RGraph/excanvas +A RGraph/excanvas/EXCANVAS-LICENSE.txt +A RGraph/excanvas/excanvas.compressed.js +A RGraph/excanvas/excanvas.original.js +A RGraph/excanvas/.htaccess +A RGraph/excanvas/HTACCESS-SAMPLE +A RGraph/info.txt +A RGraph/index.html +A RGraph/404.html +A RGraph/.htaccess +A RGraph/libraries +A RGraph/libraries/RGraph.skeleton.js +A RGraph/libraries/RGraph.line.js +A RGraph/libraries/RGraph.funnel.js +A RGraph/libraries/RGraph.rscatter.js +A RGraph/libraries/RGraph.bipolar.js +A RGraph/libraries/RGraph.vprogress.js +A RGraph/libraries/RGraph.common.annotate.js +A RGraph/libraries/RGraph.led.js +A RGraph/libraries/RGraph.common.tooltips.js +A RGraph/libraries/RGraph.bar.js +A RGraph/libraries/RGraph.scatter.js +A RGraph/libraries/RGraph.rose.js +A RGraph/libraries/RGraph.common.zoom.js +A RGraph/libraries/RGraph.common.context.js +A RGraph/libraries/RGraph.hprogress.js +A RGraph/libraries/RGraph.hbar.js +A RGraph/libraries/RGraph.meter.js +A RGraph/libraries/RGraph.modaldialog.js +A RGraph/libraries/RGraph.gantt.js +A RGraph/libraries/RGraph.pie.js +A RGraph/libraries/RGraph.tradar.js +A RGraph/libraries/index.html +A RGraph/libraries/.htaccess +A RGraph/libraries/RGraph.common.core.js +A RGraph/libraries/RGraph.common.adjusting.js +A RGraph/libraries/RGraph.common.resizing.js +A RGraph/libraries/RGraph.odo.js +A RGraph/examples +A RGraph/examples/meter.html +A RGraph/examples/hprogress.html +A RGraph/examples/hbar.html +A RGraph/examples/showcase.html +A RGraph/examples/pie.html +A RGraph/examples/gantt.html +A RGraph/examples/tradar.html +A RGraph/examples/odo.html +A RGraph/examples/basic.html +A RGraph/examples/text.html +A RGraph/examples/line.html +A RGraph/examples/funnel.html +A RGraph/examples/rscatter.html +A RGraph/examples/bipolar.html +A RGraph/examples/donut.html +A RGraph/examples/vprogress.html +A RGraph/examples/led.html +A RGraph/examples/bar.html +A RGraph/examples/scatter.html +A RGraph/examples/index.html +A RGraph/examples/rose.html +A RGraph/examples/.htaccess +A RGraph/common.php +Exported revision 1358. diff --git a/RGraph/docs/resizing.html b/RGraph/docs/resizing.html new file mode 100644 index 0000000..53af352 --- /dev/null +++ b/RGraph/docs/resizing.html @@ -0,0 +1,212 @@ + + + + + + + RGraph: HTML5 canvas graph library - Resizing your graphs + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Resizing your graphs

+ + + + [No canvas support] + +

 

+ +

+ RGraph has the facility to allow you to resize your graphs. This is new as of 10th April 2010. Because of the + numerous events it has to install code on, it is unlikely to work with other dynamic features. The context + menu does though, and now that tooltips use DOM2 events, so do they. It can be useful if you are, + for example, doing a presentation and need to enlarge the graph. +

+ +

+ All you need to do to enable it is set chart.resizable to true. There are certain caveats that you should be aware of though: +

+ +
+ + + + + \ No newline at end of file diff --git a/RGraph/docs/rose.html b/RGraph/docs/rose.html new file mode 100644 index 0000000..e965c3b --- /dev/null +++ b/RGraph/docs/rose.html @@ -0,0 +1,442 @@ + + + + + + + RGraph: HTML5 canvas graph library - rose chart documentation + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Rose chart documentation

+ + + +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var data = [41,37,16,3,3];
+    
+        var rose = new RGraph.Rose('myRose', data);
+        rose.Set('chart.labels', ['MSIE 7 (41%)',
+                                  'MSIE 6 (37%)',
+                                  'Firefox (16%)',
+                                  'Safari (3%)',
+                                  'Other (3%)']);
+        rose.Draw();
+    }
+</script>
+
+ + + + +

Properties

+ +

+ You can use these properties to control how the Rose chart appears. You can set them by using the Set() method. Eg: +

+ +

+ myRose.Set('name', 'value'); +

+ + + + + + +

Margins

+chart.gutter
+ The gutter used on the chart
Default: 25

+ +

Colors

+chart.colors
+ An array of colors to be used by the chart.
Default: ['rgb(255,0,0)', 'rgb(0,255,255)', 'rgb(0,255,0)', 'rgb(127,127,127)', 'rgb(0,0,255)', 'rgb(255,128,255)']

+ +chart.colors.alpha
+ Instead of using rgba(), you can use color definitions such as red along with this setting to add transparency.
Default: null

+ +

Labels and text

+chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size of the text (in points).
Default: 10

+ +chart.labels
+ The labels, if any, for the graph.
Default: none

+ +chart.labels.axes
+ This controls the axes that show the scale labels. Each letter stands for the appropriate axis (North, South, East and West)
Default: nsew

+ +chart.labels.position
+ This can be either center or edge and determines the position of the labels.
Default: center

+ +

Titles

+chart.title
+ The title of the chart.
Default: none

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ + +

Axis properties

+ chart.ymax
+ This can be set to control the maximum value of the scale. It's so called to maintain a degree of API compatibility across graph libraries.
Default: null

+ + +

Scale

+ + + chart.scale.round
+ Whether to round the maximum scale value up or not. This will produce slightly better scales in some instances.
+ Default: null

+ + + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + + + +

Interactive features

+chart.tooltips
+ An array of tooltips. You can use HTML if you so wish.
Default: [] (An empty array)

+ +chart.tooltips.effect
+ The tooltip effect used. Can be either fade or expand.
Default: fade

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +chart.adjustable
+ Defaulting to false, this determines whether your rose chart will be adjustable (click the edge of a segment and drag to adjust it).
Default: false

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+ + + +
 
+

Methods

+ + RGraph.getSegment()

+ + RGraph.getSegment() makes it easy to determine which segment of the Rose chart was clicked on. It provides: + + + +
+<script>
+    RGraph.Register(myGraph);
+    
+    myGraph.canvas.onclick = function (e)
+    {
+        RGraph.FixEventObject(e);
+        RGraph.Redraw();
+
+        var canvas  = e.target;
+        var context = canvas.getContext('2d');
+        var obj     = canvas.__object__;
+        var segment = RGraph.getSegment(e);
+        
+        if (segment) {
+            context.fillStyle = 'rgba(255,255,255,0.5)';
+            context.beginPath();
+                
+                // Angles are provided in degrees, so convert them to radians
+                segment[3] /= 57.29;
+                segment[4] /= 57.29;
+            
+                context.moveTo(segment[0], segment[1]);
+                context.arc(segment[0], segment[1], segment[2], segment[3], segment[4], 0);
+            context.stroke();
+            context.fill();
+            
+            e.stopPropagation();
+        }
+    }
+    
+    window.onclick = function (e)
+    {
+        RGraph.Redraw();
+    }
+</script>
+
+ + + \ No newline at end of file diff --git a/RGraph/docs/rscatter.html b/RGraph/docs/rscatter.html new file mode 100644 index 0000000..e72ee56 --- /dev/null +++ b/RGraph/docs/rscatter.html @@ -0,0 +1,370 @@ + + + + + + RGraph: HTML5 canvas graph library - Radial scatter chart documentation + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Radial scatter chart documentation

+ + + +

+ The Radial scatter graph is, as the name suggests, a circular variant of the scatter graph. +

+ +

+ The example file is here. +

+ +
 
+<script>
+    window.onload = function ()
+    {
+        var data = [
+                    [15,53,'red'],
+                    [45,63,null, 'The tooltip'],
+                    [48,45,'green'],
+                    [52,38],
+                    [51,61]
+                   ];
+
+        var rscatter= new RGraph.Rscatter('myCanvas', data);
+        rscatter.Set('chart.labels', ['NE','E','SE','S','SW','W','NW','N']);
+        rscatter.Set('chart.gutter', 35);
+        rscatter.Draw();
+    }
+</script>
+
+ +

Properties

+ +

+ You can use these properties to control how the chart appears. You can set them by using the Set() method. Eg: +

+ +

+ myRscatter.Set('name', 'value'); +

+ + + + + +

Margins

+chart.gutter
+ The gutter of the graph. This is the area outside of the X and Y axis - where the labels go. If you're short on space for your labels, try increasing this.
Default: 25

+ +

Labels and text

+chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size (in points) of the labels.
Default: 10

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.labels
+ The labels, if any, for the graph.
Default: none

+ +chart.labels.axes
+ This controls the axes that show the scale labels. Each letter stands for the appropriate axis (North, South, East and West)
Default: nsew

+ +chart.labels.position
+ This can be either center or edge and determines the position of the labels.
Default: center

+ +

Titles

+chart.title
+ The title of the graph, if any.
Default: null

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ + + + + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + + + +

Interactive features

+chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.tooltips.effect
+ The animated effect used for showing tooltips. Can be either fade or expand.
Default: fade

+ +chart.tooltips.event
+ This is the event that triggers the tooltips. It can be either onclick or onmousemove.
Default: onclick

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+

+ +

+ + + \ No newline at end of file diff --git a/RGraph/docs/scatter.html b/RGraph/docs/scatter.html new file mode 100644 index 0000000..c269758 --- /dev/null +++ b/RGraph/docs/scatter.html @@ -0,0 +1,683 @@ + + + + + + + RGraph: HTML5 canvas graph library - scatter graph documentation + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Scatter graph documentation

+ + + +

+ A scatter graph. Used to represent many data points over a period of time. For example, events occurring in a given year. +

+ +

+ The example file is here. +

+ + + +
+<script>
+    window.onload = function ()
+    {
+        var data = [
+                    [67,78,null, 'The winner!'], [67,40,'red'], [58,12], [78,56], [365,90], [360,300], [320,150], [15,45],
+                    [16,43], [84,12], [67,89,'green'], [90,23,'green'], [23,80], [80,66], [55,66], [88,12], [43,45], [61,12],
+                    [15,89], [13,16]
+                   ];
+        var sg = new RGraph.Scatter('myScatter', data);
+        sg.Set('chart.background.barcolor1','rgba(255,255,255,1)');
+        sg.Set('chart.background.barcolor2', 'rgba(255,255,255,1)');
+        sg.Set('chart.grid.color', 'rgba(238,238,238,1)');
+        sg.Set('chart.gutter', 30);
+        sg.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+        sg.Set('chart.xmax', 365); // Important!
+        sg.Draw();
+    }
+</script>
+
+ +

+ As you can see each mark on the Scatter chart is made by supplying an array of up to 4 elements: +

+ + + +

+ If you wish to specify a tooltip, but not a color (ie use the default color instead), you can pass null instead of a color. +

+ + + +

Properties

+ +

+ You can use these properties to control how the Scatter apears. You can set them by using the Set() method. Eg: +

+ +

+ myScatter.Set('chart.xmax', 365); +

+ + + + + +

Background

+chart.background.barcolor1
+ The color of the background bars.
Default: rgba(0,0,0,0)

+ +chart.background.barcolor2
+ The color of the background bars.
Default: rgba(0,0,0,0)

+ +chart.background.grid
+ Whether to show the background grid or not.
Default: true

+ +chart.background.grid.color
+ The color of the background grid.
Default: #eee

+ + + chart.background.hbars
+ An array of information stipulating horizontal coloured bars. You can use these to indicate limits. Eg: + +
myScatter.Set('chart.background.hbars', [[75, 10, 'yellow'], [85, 15, 'red']]);
+ + This would give you two bars, one red and a lower yellow bar. The units correspond to your scale, and are the + starting point and the height.
+ Default: null

+ + chart.background.vbars
+ An array of vertical bar information. They're specified like his: +
myScatter.Set('chart.background.vbars', [[0, 181, 'rgba(0,255,0,0.5)']]);
+ Default: null

+ + +chart.background.grid.border
+ Determines whether a border line is drawn around the grid.
Default: true

+ +chart.background.grid.hlines
+ Determines whether to draw the horizontal grid lines.
Default: true

+ +chart.background.grid.vlines
+ Determines whether to draw the vertical grid lines.
Default: true

+ +chart.background.grid.autofit
+ Instead of specifying a pixel width/height for the background grid, you can use autofit and specify how many horizontal and vertical lines you want.
Default: false

+ +chart.background.grid.autofit.numhlines
+ When using autofit this allows you to specify how many horizontal grid lines you want.
Default: 7

+ +chart.background.grid.autofit.numvlines
+ When using autofit this allows you to specify how many vertical grid lines you want.
Default: 20

+ +

Labels and text

+chart.labels
+ An array of the X labels for the graph.
Default: [] (An empty array)

+ +chart.ylabels
+ A boolean (true or false) that controls whether the graph has Y labels.
Default: true

+ +chart.ylabels.count
+ A value (1, 3 or 5) that controls how many Y labels there are.
Default: 5

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size of the text (in points).
Default: 10

+ +chart.text.angle
+ The angle of the horizontal text labels (at the bottom of the graph). This can be one of three values - 0, 45 or 90.
Default: 0 (Horizontal)

+ +

Margins

+chart.gutter
+ The gutter on the graph (the area outside of the axes).
Default: 25

+ +

Axis properties

+chart.xmax
+ The maximum X axis value you wish to set. For example if you're displaying products sold in a year, you might use 365.
Default: none - must be supplied

+ +chart.ymax
+ The optional maximum Y scale value. If not specified then it will be calculated.
Default: null (It's calculated)

+ +chart.ymin
+ The optional minimum Y scale value. If not specified it will be zero.
Default: null

+ +chart.ticksize
+ The size of the tickmarks.
Default: 3

+ +chart.tickmarks
+ The style of the tickmarks. Can be: cross, plus, circle, diamond, square or null (no tickmarks).
Default: cross

+ +chart.xticks
+ This controls whether the X axis tickmarks are drawn.
Default: true

+ +chart.noendxtick
+ Whether to draw an end X tick. Usually used when combining Scatter charts
Default: false

+ +chart.xaxis
+ This controls whether the X axis is drawn.
Default: true

+ +chart.xaxispos
+ Where the X axis should be drawn. Can be either center or bottom.
Default: bottom

+ +chart.yaxispos
+ Where the Y axis should be drawn. Can be either left or right.
Default: left

+ +chart.yaxispos
+ Where the Y axis should be drawn. Can be either left or right.
Default: left

+ +chart.axis.color
+ The color of the axes.
Default: black

+ +chart.noaxes
+ If this is set to true, no axes will be drawn.
Default: false

+ +

Titles

+chart.title
+ The title of the scatter graph.
Default: none

+ + +chart.title.background
+The background color (if any) for the title.
+Default: null

+ + +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.xaxis
+ This allows to specify a title for the X axis.
Default: none

+ +chart.title.yaxis
+ This allows to specify a title for the Y axis.
Default: none

+ +chart.title.xaxis.pos
+ This is multiplied with the gutter to give the position of the X axis title.
Default: 0.25

+ +chart.title.yaxis.pos
+ This is multiplied with the gutter to give the position of the Y axis title.
Default: 0.25

+ + +

Scale

+chart.scale.decimals
+ The number of decimal places to display for the Y scale.
Default: 0

+ +chart.scale.point
+ The character used as the decimal point.
Default: .

+ +chart.scale.thousand
+ The character used as the thousand separator
Default: ,

+ + + chart.scale.round
+ Whether to round the maximum scale value up or not. This will produce slightly better scales in some instances.
+ Default: null

+ + +chart.units.pre
+ The units (if any) that the Y axis is measured in (these are preppended to the number).
Default: none

+ +chart.units.post
+ The units (if any) that the Y axis is measured in (these are appended to the number).
Default: none

+ + +

Interactive features

+ +

+ Note: Unlike other charts, the Scatter chart tooltips are specified as part of the data array. See above. +

+ + + chart.tooltips.effect
+ The animated effect used for showing tooltips.
+ Default: fade

+ + +chart.tooltips.hotspot
+ This controls the size of the hotspot on the chart for tooltips.
Default: 3

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.tooltips.coords.adjust
+ If you translate() before drawing your graph to reduce wasted space, the coords used for tooltips may need adjusting by how much you translate() by. This setting is how to do it. It should be an array of the X/Y adjustments. There's an example of this on the misc documentation page.
Default: [0,0]

+ +chart.crosshairs
+ If true, you will get a crosshair centering on the current mouse position.
Default: false

+ +chart.crosshairs.linewidth
+ This controls the linewidth of the crosshairs.
Default: 1

+ +chart.crosshairs.color
+ The color of the crosshairs.
Default: #333

+ +chart.crosshairs.coords
+ If true, this will show the coordinates that the crosshairs are currently over.
Default: false

+ +chart.crosshairs.fixed
+ If true, this makes the coordinates static (attached), instead of following the pointer around.
Default: false

+ +chart.crosshairs.fadeout
+ If true, when you move your mouse off of the canvas the coordinates will fade out.
Default: false

+ +chart.crosshairs.labels.x
+ Instead ox X and Y, you can specify more meaningful labels.
Default: X

+ +chart.crosshairs.labels.y
+ Instead ox X and Y, you can specify more meaningful labels.
Default: Y

+ +chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: null

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: #000

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +

Line properties

+chart.line
+ Whether to show a connecting line (like in the sixth example).
Default: false

+ +chart.line.colors
+ The colors of the lines connecting the tick marks.
Default: ['green', 'red']

+ +chart.line.shadow.color
+ The color of the lines shadow (if any).
Default: rgba(0,0,0,0) (invisible)

+ +chart.line.shadow.offsetx
+ The X offset of the lines shadow.
Default: 3

+ +chart.line.shadow.offsety
+ The Y offset of the lines shadow.
Default: 3

+ +chart.line.shadow.blur
+ The severity of the line shadows blurring effect.
Default: 2

+ +chart.line.stepped
+ Like the line chart, Scatter chart lines can be stepped by setting this to true
Default: false

+ + + + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + + + + + +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+ +

Miscellaneous

+chart.defaultcolor
+ This is the default color of tick marks, which is used if a color isn't given.
Default: #000

+ +chart.boxplot.width
+ This stipulates the default width of boxes. For more on boxplots, see here.
Default: 8

+

+ + +

Box plots

+ +

+ Instead of a single Y value, you have the ability to specify an array of 5, 6, 7 or 8 values, which will be used to make a box plot. + The example page shows a box plot. These values are (in order): + +

+ +
+<script>
+    scatter8 = new RGraph.Scatter('scatter8', [
+                                               [10,[1,1,16,24,24, 'red', 'green']],
+                                               [105,[5,10,15,25,25, 'red', 'green']],
+                                               [125,[10,15,25,35,45, 'red', 'green']],
+                                               [325,[10,15,25,35,45, 'red', 'green', 30]]
+                                              ]);
+    scatter8.Set('chart.title', 'An example of a boxplot');
+    scatter8.Set('chart.labels', ['Q1', 'Q2', 'Q3', 'Q4']);
+    scatter8.Set('chart.xmax', 365);
+    scatter8.Set('chart.ymax', 50);
+    scatter8.Set('chart.boxplot.width', 12); // The default width
+    scatter8.Draw();
+</script>
+
+

+ + + +

Specific points for labels on the X axis

+ +

+ Instead of a simple string which is used as the label, each entry of the chart.labels array can be a two element array + consisting of the label, and the X value that the label should be placed at. For example: +

+ +
+scatter.Set('chart.labels', [
+                             ['Quarter 1', 0],
+                             ['Quarter 2', 90],
+                             ['Quarter 3', 181],
+                             ['Quarter 4', 273]
+                            ]);
+
+ + + + +

Custom tickmarks

+ +

+ If none of the available tickmark styles are suitable, you can instead specify a function object that draws the tickmark, + enabling you to draw the tickmark yourself. For example: +

+ +
+<script>
+    line.Set('chart.tickmarks', myTick);
+
+    /**
+    * The function that is called once per tickmark, to draw it
+    * 
+    * @param object obj   The graph object
+    * @param object data  The graph data
+    * @param number x     The X coordinate
+    * @param number y     The Y coordinate
+    * @param number xVal  The X value
+    * @param number yVal  The Y value
+    * @param number xMax  The maximum X scale value
+    * @param number xMax  The maximum Y scale value
+    * @param string color The color of the tickmark
+    */
+    function myTick (obj, data, x, y, xVal, yVal, xMax, yMax, color)
+    {
+        // Draw your custom tick here
+    }
+</script>
+
+ + +

Note about colors and the key

+ +

+ If you're using a key you may need to set chart.line.colors to allow it to use the correct colors. For example: +

+ +
myObj.Set('chart.line.colors', ['red','green','blue']);
+ + \ No newline at end of file diff --git a/RGraph/docs/setconfig.html b/RGraph/docs/setconfig.html new file mode 100644 index 0000000..ca056bd --- /dev/null +++ b/RGraph/docs/setconfig.html @@ -0,0 +1,206 @@ + + + + + + + RGraph: HTML5 canvas graph library - API documentation + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - The RGraph.SetConfig() function

+ + + + +
+ A graph showing RGraph.SetConfig()
+ [No canvas support] +
+ + + +

+ Instead of using a number of .Set() calls, you may find that using the RGraph.SetConfig() method more to your tastes. The + method is an alternative to setting the configuration of your graph. It can also facilitate reuse better, so that the + appearance of all of your websites charts is the same. There's an example of its use below: +

+ +
+ +
+<script>
+    window.onload = function ()
+    {
+        /**
+        * This configuration could be stored in a central configuration file, making its reuse easier. You could also have
+        * several different configurations that you pick and choose from depending on the requirements. Values in
+        * subsequent calls to .SetConfig() will overwrite previous ones.
+        */
+        var config = {
+                      'chart.colors':                  ['red', 'green'],
+                      'chart.labels':                  ['John','Fred','June','Charles','Lou', 'Olga'],
+                      'chart.title.yaxis':             'Amount',
+                      'chart.title.yaxis.pos':         -0.2,
+                      'chart.title.xaxis':             'Person',
+                      'chart.background.grid.autofit': true
+                     }
+        var bar = new RGraph.Bar('cvs', [48,56,52,49,43,51]);
+        RGraph.SetConfig(bar, config);
+        bar.context.translate(20,-20);
+        bar.Draw();
+    }
+</script>
+
+ + + \ No newline at end of file diff --git a/RGraph/docs/tooltips.html b/RGraph/docs/tooltips.html new file mode 100644 index 0000000..94864a7 --- /dev/null +++ b/RGraph/docs/tooltips.html @@ -0,0 +1,587 @@ + + + + + + + RGraph: HTML5 canvas graph library - Tooltips + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Tooltips

+ + + +
+ [No canvas support]
+ Tooltip effect: + +
+ + + + + + +

Introduction

+ +

+ Tooltips are a very effective and straight forward way to extend your graphs and add more information to them, without overloading + the user. +

+ + +

What can they hold?

+ +

+ At the base level, tooltips are DIVs, so they can hold a multitude of HTML - images, videos etc. See below + for information on showing graphs in tooltips. +

+ + +

How can I specify them?

+ +

+ You can specify them by including the tooltips code and then using the chart.tooltips property. For example: +

+ +
    +
  1. + Include the RGraph libraries. +
    +<script src="RGraph.common.core.js"></script>
    +<script src="RGraph.common.tooltips.js"></script>
    +<script src="RGraph.line.js"></script>
    +
    +
  2. + +
  3. + Define your graph and set the tooltips property. +
    +<script>
    +    window.onload = function ()
    +    {
    +        var line = new RGraph.Line('cvs', [64,34,26,35,51,24]);
    +        line.Set('chart.tooltips', ['<b>Winner!</b><br />John', 'Fred', 'Jane', 'Lou', 'Pete', 'Kev']);
    +        line.Set('chart.tooltips.effect', 'expand');
    +        line.Set('chart.gutter', 30);
    +        line.Set('chart.hmargin', 10);
    +        line.Set('chart.linewidth', 2);
    +        line.Set('chart.shadow', true);
    +        line.Set('chart.shadow.offsetx', 0);
    +        line.Set('chart.shadow.offsety', 0);
    +        line.Set('chart.shadow.color', 'green');
    +        line.Set('chart.shadow.blur', 25);
    +        line.Set('chart.colors', ['green']);
    +        line.Set('chart.tickmarks', 'circle');
    +        line.Set('chart.labels', ['John', 'Fred', 'Jane', 'Lou', 'Pete', 'Kev']);
    +        line.Draw();
    +    }
    +</script>
    +
    +
  4. +
+ + +

What can I specify?

+ +

+ The tooltips that you specify are usually strings (which can contain HTML). They can however also be functions which are called when they're about + to be displayed. The function should return the text that is used as the tooltip. You have the option to either specify + one function per data point, or just one function for all of the tooltips. You can mix functions and strings if you wish. + These functions are passed the numerical, zero-indexed tooltip index and the return value is used as the tooltip + text. So to summarise: +

+ + + + +

Can I show graphs in tooltips?

+ + [No canvas support] + +

+ You can, and with the custom event support that RGraph has (as of 10th July 2010), it's reasonably easy. Simply attach your function that + creates the graph to the ontooltip event. This allows the tooltip HTML to be created and added to the page + so that the code that creates the graph can run. The sequence is: +

+ +
    +
  1. Specify the HTML for the tooltip as normal (including the <canvas> tag).
  2. +
  3. Use the ontooltip RGraph event so that a function is called when a tooltip is shown.
  4. +
  5. This function should subsequently create the graph.
  6. +
+ +

+ The tooltip DIV is to be found in the RGraph registry - RGraph.Registry.Get('chart.tooltip'). And if you want it the + numerical zero indexed count of the tooltip is to be found in the __index__ property: + RGraph.Registry.Get('chart.tooltip').__index__ +

+ +
+<script src="RGraph.common.core.js" ></script>
+<script src="RGraph.common.tooltips.js" ></script>
+<script src="RGraph.bar.js" ></script>
+<script src="RGraph.line.js" ></script>
+
+<style>
+    .RGraph_tooltip {
+        background-color: white ! important;
+    }
+</style>
+
+<canvas id="cvs" width="600" height="250">[No canvas support]</canvas>
+
+<script>
+    window.onload = function ()
+    {
+        labels = ['Gary','Pete','Lou','Ned','Kev','Fred'];
+
+        bar = new RGraph.Bar("cvs", [4.5,28,13,26,35,36]);
+        bar.Set('chart.tooltips', function (idx) {return labels[idx] + 's stats<br/><canvas id="__tooltip_canvas__" width="400" height="150">[No canvas support]</canvas>';});
+        bar.Set('chart.hmargin', 10);
+        bar.Set('chart.tickmarks', 'endcircle');
+        bar.Set('chart.colors', ['blue']);
+        bar.Set('chart.ymax', 100);
+        bar.Set('chart.gutter', 30);
+        bar.Set('chart.labels', labels);
+        bar.Draw();
+        
+        RGraph.AddCustomEventListener(line, 'ontooltip', CreateTooltipGraph);
+    }
+      
+
+    
+    /**
+    * This is the function that is called by the ontooltip event to create the tooltip charts
+    * 
+    * @param obj object   The graph object
+    */
+    function CreateTooltipGraph(obj)
+    {
+        // This data could be dynamic
+        var line  = new RGraph.Line('__tooltip_canvas__', [5,8,7,6,9,5,4,6,3,5,4,4]);
+        line.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+        line.Set('chart.gutter', 20);
+        line.Set('chart.hmargin', 5);
+        line.Set('chart.tickmarks', 'endcircle');
+        line.Set('chart.background.grid.autofit', true);
+        line.Draw();
+    }
+    
+</script>
+
+ +

+ If you want to see more source code, simply view the source of this page and look at the code that creates the bar chart. +

+ +
+ + +

Can I customise the appearance of tooltips?

+ +

+ Yes. You can either use the default CSS class RGraph_tooltip, or you can specify a specific CSS class that a + graphs tooltips should use with the property chart.tooltips.css.class. The two graphs on this page have + different looking tooltips by using this method - the line graph uses the default look, whilst the bar chart + overrides the CSS class name and sets it to bar_chart_tooltips_css. For example: +

+ +
bar.Set('chart.tooltips.css.class', 'bar_chart_tooltips_css');
+ +
+<style>
+    .bar_chart_tooltips_css {
+        background-color: white ! important;
+        border: 2px solid black ! important;
+        padding: 3px;
+    }
+</style>
+
+ +

+ You can read more about RGraph CSS classes here. +

+ + +

What tooltip effects are available?

+ +

+ These effects are available to you: +

+ + + +

+ All of them are as their names imply. fade is a straight forward fade in effect, expand is another effect + which expands outward from the center of the tooltip, contract is like the expand effect but in reverse, snap is an effect which can be used in a limited set of circumstances + and "snaps" to the current mouse position and none is simply no effect at all. The default effect used + by all graph types is fade. Note: If you're showing canvases in your tooltips then the expand, contract and snap + effects will not work - you must use fade or none. +

+ +

+ Note: The snap effect is only available to graph types where the tooltip is triggered using the onmousemove event. + Currently this means the Line chart, Rscatter graph, Scatter graph and Tradar chart. It can also + be negatively effected when using multiple graphs on one page. +

+ + + +

Tooltips, the clipboard and Firefox

+ +

+ If you're using Firefox, there's a note about tooltips and the clipboard (ie copying text) on the issues page. +

+ + +

Can I override the tooltip function?

+ +

+ You can by stipulating chart.tooltips.override. This should be a function object that handles everything with regard + to showing the tooltip. Highlighting the graph is still done for you - the override function is only concerned with showing + the tooltip. The override function is passed these arguments: +

+ + + +

+ Note: Although "id:xxx" strings are not expanded for you, you can easily do this yourself by using the + RGraph.getTooltipText('id:xxx') function. +

+ +
+<script>
+    function tooltip_override (canvas, text, x, y, idx)
+    {
+        alert('In tooltip override function...');
+    }
+    myObj.Set('chart.tooltips.override', tooltip_override);
+</script>
+
+ + + \ No newline at end of file diff --git a/RGraph/docs/tradar.html b/RGraph/docs/tradar.html new file mode 100644 index 0000000..4837931 --- /dev/null +++ b/RGraph/docs/tradar.html @@ -0,0 +1,398 @@ + + + + + + + RGraph: HTML5 canvas graph library - Traditional radar chart documentation + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Traditional radar chart documentation

+ + + +

+ A traditional radar chart. +

+ +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var data = [3, 3, 41, 37, 16];
+    
+        var tradar = new RGraph.Tradar('myTradar', data);
+        tradar.Set('chart.background.circles', true);
+        tradar.Set('chart.color', 'rgba(255,0,0,0.5)');
+        tradar.Set('chart.circle', 20);
+        tradar.Set('chart.circle.fill', 'rgba(200,255,200,0.5)');
+        tradar.Set('chart.labels', ['Safari (3%)', 'Other (3%)', 'MSIE 7 (41%)', 'MSIE 6 (37%)', 'Firefox (16%)']);
+        tradar.Set('chart.key', ['Market share', 'A made up figure']);
+        tradar.Draw();
+    }
+</script>
+
+ + +

Properties

+ +

+ You can use these properties to control how the chart apears. You can set these properties by using the Set() method. Eg: +

+ +

+ myTradar.Set('color', 'rgba(255,0,0,0.5)'); +

+ + + + + +

Margins

+chart.gutter
+ The gutter that the chart uses. This is effectively the margin.
Default: 25

+ +

Colors

+chart.color
+ The color of the radar chart.
Default: rgba(255,0,0,0.5)

+ +

Title

+chart.title
+ The title, if any, of the chart.
Default: Not set

+ +chart.title.color
+ The color of the title.
Default: black

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +

Labels and text

+chart.labels
+ The labels to use for the chart.
Default: An empty array

+ +chart.labels.axes
+ This controls the axes that show the scale labels. Each letter stands for the appropriate axis (North, South, East and West)
Default: nsew

+ +chart.labels.offsetx
+ The X pixel offset for the labels.
Default: 10

+ +chart.labels.offsety
+ The Y pixel offset for the labels.
Default: 10

+ +chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size of the text (in points).
Default: 10

+ + +

Scale

+ chart.ymax
+ The optional maximum Y scale value. If not specified then it will be calculated.
Default: null (It's calculated)

+ + + chart.scale.round
+ Whether to round the maximum scale value up or not. This will produce slightly better scales in some instances.
+ Default: null

+ + +

Miscellaneous

+chart.background.circles
+ Whether to draw the grey background circles.
Default: true

+ +chart.linewidth
+ The width of the outline.
Default: 1

+ +chart.circle
+ What value to draw a circle at. Defaults to zero (off). You could use this to represent a threshold of some sort.
Default: 0

+ +chart.circle.fill
+ What color to fill the circle with.
Default: red

+ +chart.circle.stroke
+ What color to stroke (ie The outline) the circle with.
Default: black

+ + + + + + + +

Key

+ + + chart.key
+ An array of key information.
+ Default: [] (An empty array)

+ + + chart.key.background
+ The color of the key background. Typically white, you could set this to something like rgba(255,255,255,0.7) to allow people to see things behind it.
+ Default: white

+ + + chart.key.position
+ Determines the position of the key.Either graph (default), or gutter.
+ Default: graph

+ + chart.key.position.x
+ This allows you to specify a specific X coordinate for the key.
+ Default: null

+ + chart.key.position.y
+ This allows you to specify a specific Y coordinate for the key.
+ Default: null

+ + chart.key.position.gutter.boxed
+ If you have the key in gutter mode (ie horizontal), this allows you to give a background color.
+ Default: true

+ + + chart.key.shadow
+ Whether a small drop shadow is applied to the key.
+ Default: false

+ + + chart.key.shadow.color
+ The color of the shadow.
+ Default: #666

+ + + chart.key.shadow.blur
+ The extent of the blurring effect used on the shadow.
+ Default: 3

+ + + chart.key.shadow.offsetx
+ The X offset of the shadow.
+ Default: 2

+ + + chart.key.shadow.offsety
+ The Y offset of the shadow.
+ Default: 2

+ + chart.key.rounded
+ This controls whether the corners of the key (in graph mode) are curved. If the key is gutter mode, this has no effect.
+ Default: false

+ + chart.key.color.shape
+ This can be square, circle or line and controls how the color indicators in the key appear.
+ Default: square

+ + + + + + + + +

Interactive features

+chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.tooltips
+ A numerically indexed array of tooltips that are shown when a hotspot is hovered over. These can contain HTML.
Default: An empty array

+ +chart.tooltips.effect
+ The visual effect used when showing tooltips. Can be either fade or expand.
Default: fade

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ +chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
Default: null

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +

Zoom

+chart.zoom.mode
+ Can be used to control whether the zoom is in thumbnail or canvas mode. Possible values are: thumbnail and canvas.
Default: canvas

+ +chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.thumbnail.width
+ When the zoom is in thumbnail mode, this is the width (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.thumbnail.height
+ When the zoom is in thumbnail mode, this is the height (in pixels) of the thumbnail.
Default: 75

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+

+ + \ No newline at end of file diff --git a/RGraph/docs/vprogress.html b/RGraph/docs/vprogress.html new file mode 100644 index 0000000..9bcd2e7 --- /dev/null +++ b/RGraph/docs/vprogress.html @@ -0,0 +1,363 @@ + + + + + + + RGraph: HTML5 canvas graph library - progress bar documentation + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Vertical Progress bar documentation

+ + + +

+ The example file is here. +

+ +
+<script>
+    window.onload = function ()
+    {
+        var myProgress = new RGraph.VProgess('myProgress', 78, 100);    
+        myProgress.Set('chart.colors', ['red']);
+        myProgress.Draw();
+    }
+</script>
+
+ +

Properties

+ +

+ You can use these properties to control how the progress bar apears. You can set them by using the Set() method. Eg: +

+ +

+ myProgress.Set('name', 'value'); +

+ + + + + +

Chart configuration

+chart.tickmarks
+ Whether the tickmarks are drawn.
Default: true

+ + + chart.labels.count
+ This controls how many labels there are. +
Default: 10

+ + +chart.tickmarks.color
+ The color used for tickmarks.
Default: black

+ + +chart.tickmarks.inner
+ This controls whether the bar has inner tickmarks
Default: false

+ + + chart.value
+ The indicated value. You don't need to set this because it's one of the arguments to the constructor.
+ Default: none (An argument to the constructor) +

+ + + chart.min
+ The minimum value. Setting a minimum value allows to show a more detailed progress bar.
+ Default: 0

+ + + chart.max
+ The maximum value. You don't need to set this because it's one of the arguments to the constructor.

+ + +chart.numticks
+ How many tick marks there are.
Default: 10

+ +chart.numticks.inner
+ How many inner tick marks there are.
Default: 50

+ +chart.arrows
+ This stipulates that two indicator arrows are drawn. It works best if you have tickmarks off, and no title.
Default: false

+ +

Margins

+chart.gutter
+ The size of the gutter.
Default: 25

+ +

Colors

+chart.color
+ The color of the bar. This can be a solid color, or a gradient that you create.
Default: #0c0

+ +chart.background.color
+ The background color.
Default: #eee

+ +

Shadow

+chart.shadow
+ Whether the progress bar has a shadow. This uses the canvas shadow API and therefore is only supported on Chrome 2, Safari 3.1 and Firefox 3.1 (and above).
Default: false

+ +chart.shadow.offsetx
+ The X offset of the progress bar shadow.
Default: 3

+ +chart.shadow.offsety
+ The Y offset of the progress bar shadow.
Default: 3

+ +chart.shadow.color
+ The color of the shadow.
Default: rgba(0,0,0,0.5)

+ +chart.shadow.blur
+ The blurring effect that is applied to the shadow.
Default: 3

+ +

Labels and text

+chart.text.font
+ The font used to render the text.
Default: Verdana

+ +chart.text.color
+ The color of the labels.
Default: black

+ +chart.text.size
+ The size of the text (in points).
Default: 10

+ + + chart.labels
+ Labels that are applied to the graph.
Default: An empty array

+ + + chart.labels.position
+ Can be left or right and controls which side the labels are positioned on.
+ Default: right

+ + + +

Scale

+ chart.units.pre
+ The units that the Y scale is measured in (these are preppend to the number).
Default: none

+ + + chart.units.post
+ The units that the Y scale is measured in (these are appended to the number).
Default: none

+ + + chart.scale.decimals
+ This stipulates how many decimal places there are. +
Default: 0

+ + + +

Titles

+chart.title
+ The title of the progress bar.
Default: An empty string

+ +chart.title.hpos
+ This allows you to completely override the horizontal positioning of the title. It should be a number between 0 and 1, and is multiplied with the whole width of the canvas and then used as the horizontal position.
Default: null

+ +chart.title.vpos
+ This allows you to completely override the vertical positioning of the title. It should be a number between 0 and 1, and is multiplied with the gutter and then used as the vertical position. It can be useful if you need to have a large gutter.
Default: null

+ +chart.title.color
+ The color of the title.
Default: black

+ +

Interactive features

+chart.tooltips
+ An array, albeit one element only. This is shown when the progress bar is clicked on. Tooltips can contain HTML.
Default: An empty array

+ +chart.tooltips.effect
+ The animated effect used for showing the tooltip. Can be either fade or expand.
Default: fade

+ +chart.tooltips.css.class
+ This is the name of the CSS class the graph uses.
Default: RGraph_tooltip

+ + + chart.tooltips.override
+ If you wish to handle showing tooltips yourself, this should be a function object which does just that. There's more information on the tooltips documentation page
+ Default: null

+ + + chart.tooltips.coords.adjust
+ If you translate to gain space, then you can use this to tell RGraph that you have, so that the coordinates for the + tooltip(s) are accurate.
+ Default: [0, 0]

+ + +chart.contextmenu
+ An array of context menu items. More information on context menus is here.
Default: [] (An empty array)

+ +chart.annotatable
+ Whether annotations are enabled for the chart (ie you can draw on the chart interactively.
Default: false

+ +chart.annotate.color
+ If you do not allow the use of the palette, then this will be the only colour allowed for annotations.
Default: black

+ +chart.resizable
+ Defaulting to false, this determines whether your graph will be resizable. Because of the numerous event handlers this has to install code on, This feature is unlikely to work with other dynamic features (the context menu is fine however).
Default: false

+ +chart.adjustable
+ Defaulting to false, this determines whether your progress bar will be adjustable (click the bar and drag it).
Default: false

+ +

Zoom

+chart.zoom.factor
+ This is the factor that the graph will be zoomed by (bigger values means more zoom)
Default: 1.5

+ +chart.zoom.fade.in
+ Whether the zoomed canvas fades in or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.fade.out
+ Whether the zoomed canvas fades out or not. This also can be used to control the fade in for the zoom in thumbnail mode.
Default: true

+ +chart.zoom.hdir
+ The horizontal direction of the zoom. Possible values are: left, center, right
Default: right

+ +chart.zoom.vdir
+ The vertical direction of the zoom. Possible values are: up, center, down
Default: down

+ +chart.zoom.delay
+ The delay (in milliseconds) between frames.
Default: 50

+ +chart.zoom.frames
+ The number of frames in the zoom animation.
Default: 10

+ +chart.zoom.shadow
+ Whether or not the zoomed canvas has a shadow or not.
Default: true

+ +chart.zoom.background
+ Defaulting to true, this determines whether the zoom has a dark, semi-opaque background that covers the entire web page.
Default: true

+

+ + + \ No newline at end of file diff --git a/RGraph/docs/zoom.html b/RGraph/docs/zoom.html new file mode 100644 index 0000000..c74256b --- /dev/null +++ b/RGraph/docs/zoom.html @@ -0,0 +1,388 @@ + + + + + + + RGraph: HTML5 canvas graph library - Zooming your graphs + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Zooming your graphs

+ + + + + + + + +

Canvas mode

+ + + + + + + + + + + +
+

+ As of November 2009 RGraph has had the ability to provide a zoom facility. It's designed to be used in + conjunction with a context menu as in the example to the right. +

+ +

+ You can control the zoom using these properties: +

+ +
    +
  • chart.zoom.modeDefault: canvas
  • +
  • chart.zoom.factorDefault: 1.5
  • +
  • chart.zoom.fade.in Default: true
  • +
  • chart.zoom.fade.out Default: true
  • +
  • chart.zoom.hdir Default: right
  • +
  • chart.zoom.vdir Default: down
  • +
  • chart.zoom.delay Default: 50
  • +
  • chart.zoom.frames Default: 10
  • +
  • chart.zoom.shadow Default: true
  • +
  • chart.zoom.mode Default: canvas
  • +
  • chart.zoom.thumbnail.width Default: 75
  • +
  • chart.zoom.thumbnail.height Default: 75
  • +
  • chart.zoom.background Default: true
  • +
+
+ [No canvas support] +
+ The possible values of chart.zoom.hdir are: left, center, right. + The possible values of chart.zoom.vdir are: up, center, down. chart.zoom.delay + is the delay in between frames (in milliseconds) and chart.zoom.frames is the number of frames in the zoom. chart.zoom.shadow + is whether the zoomed canvas has a shadow or not. The possible values of chart.zoom.mode are canvas (default) + and thumbnail. +
+ + + +
+ +
+<script>
+    var graph = new RGraph.Line('myc', [4,6,8,7,9,4,3,8,7,4,5,5,5]);
+    graph.Set('chart.labels', ['Fry','Hav','Jim','Moo','Io','Olga','Tim','Gaz','Jake','Pippa','Lou','Fred','John']);
+    graph.Set('chart.contextmenu', [
+                                    ['Clear annotations', function () {RGraph.Clear(graph.canvas); graph.Draw();}],
+                                    ['Zoom in', RGraph.Zoom]
+                                   ]);
+    graph.Set('chart.title', 'Chart with zoom (context, annotatable)');
+    graph.Set('chart.shadow', true);
+    graph.Set('chart.annotatable', true);
+    graph.Draw();
+</script>
+
+ + + +

Thumbnail mode

+ + [No canvas support] + +

+ The zoom has an alternative thumbnail mode, which displays a small thumbnail zoom instead of zooming the entire canvas. + The graph to the left shows an example of this. +

+ +

+ It uses some of the same properties as the regular zoom, eg chart.fade.in, chart.fade.out, chart.zoom.shadow +

+ +
+ +
+<script>
+    var myLine = new RGraph.Line('myc2', [40,48,45,64,34,22,23,56,56,54,84,44], [4,5,6,7,20,21,1,9,9,8,5,4]);
+    myLine.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+    myLine.Set('chart.hmargin', 10);
+    myLine.Set('chart.linewidth', 3);
+    myLine.Set('chart.title', 'A sample line chart');
+    myLine.Set('chart.zoom.mode', 'thumbnail');
+    myLine.Set('chart.zoom.vdir', 'center');
+    myLine.Set('chart.zoom.thumbnail.width', 100);
+    myLine.Set('chart.zoom.thumbnail.height', 100);
+    myLine.Set('chart.colors', ['red', 'black']);
+    myLine.Set('chart.shadow', true);
+    myLine.Set('chart.contextmenu', [['Zoom entire graph', RGraph.Zoom]]);
+</script>
+
+ +

+ Making the zoom circular

+ A circular zoom window + It is possible to make the zoom in area mode circular by utilising the border-radius CSS property. Currently support for + this is limited to FireFox 4b7+, so it's not part of the main RGraph software. The CSS ncessary to achieve this is + thus: +

+ +
+<style>
+    .RGraph_zoom_window {
+        border-radius: 50px ! important;
+    }
+</style>
+
+ + This a graph demonstrating this technique here. Note that browser support for this technique is limited. + +
+ + + +

Area mode

+ + [No canvas support] + +

+ Another type of zoom available is area. This is somewhat similar to thumbnail, but allows you to draw a rectangle around + the specific area that you want to zoom. +

+ +

+ Again, this uses some common zoom properties, such as chart.zoom.factor. +

+ +

+ Once visible, you can drag the zoomed area around with the left mouse button (a left drag), and drag the zoomed canvas around + within the zoom by using the right mouse button (a right-drag). And a double click will expand the zoomed area to cover the + whole canvas. +

+ +
+ +
+<script>
+    var myLine = new RGraph.Line('myc3', [15,30,62,26,46,86,48,51,51,35,32, 35]);
+    myLine.Set('chart.zoom.mode', 'area');
+    myLine.Set('chart.hmargin', 10);
+    myLine.Set('chart.linewidth', 1);
+    myLine.Set('chart.title', 'A graph with zoom in area mode');
+    myLine.Set('chart.tickmarks', 'endcircle');
+    myLine.Set('chart.labels', ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
+    myLine.Draw();
+<script>
+
+ + + \ No newline at end of file diff --git a/RGraph/docs/zoom_thumbnail.html b/RGraph/docs/zoom_thumbnail.html new file mode 100644 index 0000000..cef8b78 --- /dev/null +++ b/RGraph/docs/zoom_thumbnail.html @@ -0,0 +1,191 @@ + + + + + + + RGraph: HTML5 canvas graph library - Zooming your graphs + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - A circular thumbnail demonstration

+ + + + + [No canvas support] + + +

+ This is a demonstration of the zoom in thumbnail mode with some custom CSS (the border-radius property) which facilitates + making the thumbnail circular. +

+ +

+ Remember that browser support for this is limited - currently (18th December 2010) only Firefox 4b7+ supports this. +

+ +

+ «Back to zoom documentation +

+ + + \ No newline at end of file diff --git a/RGraph/examples/bar.html b/RGraph/examples/bar.html new file mode 100644 index 0000000..bca43bd --- /dev/null +++ b/RGraph/examples/bar.html @@ -0,0 +1,333 @@ + + + + + + + + RGraph: HTML5 canvas graph library - bar chart + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Bar chart

+ + + +
+

+ The bar chart is probably one of the most widely used of charts, and also one of the most versatile. It's defined as a chart with + rectangular bars with lengths proportional to the values they represent. The bar chart can be used to represent two + or more values. With grouped and stacked bar charts, you can visualise two or more sets of data. For example two years + worth of sales figures. Doing this you will be able to easily see differences, for example a better year when it comes + to sales. You can also show negative values by having the X axis in the center, like the examples shown. If you use a + grouped or stacked bar chart, a key may be helpful to your users. +

+ +

+ By using the tooltips feature, you can provide more detail about what a particular bar represents. The tooltips in + RGraph can contain wide range of HTML, so you can use them to show photos or movies for example. +

+ +
+ +
+ +
+
+ [No canvas support] + [No canvas support] +
+ +
+ [No canvas support] + [No canvas support] +
+
+
+ + + \ No newline at end of file diff --git a/RGraph/examples/basic.html b/RGraph/examples/basic.html new file mode 100644 index 0000000..ce2be6c --- /dev/null +++ b/RGraph/examples/basic.html @@ -0,0 +1,64 @@ + + + + + + + + RGraph: HTML5 canvas graph library - a basic example + + + + + + + + + + + + + +

RGraph: HTML5 canvas graph library - A basic example

+ + + [No canvas support] + + + + +

+ This is a very basic example that does little more than display a graph. If you're trying to understand how RGraph + works, this should help as there is very little happening on this page. To see the source code of this + page simply view the source (Right click > View Source). +

+ + + \ No newline at end of file diff --git a/RGraph/examples/bipolar.html b/RGraph/examples/bipolar.html new file mode 100644 index 0000000..1ea7dbe --- /dev/null +++ b/RGraph/examples/bipolar.html @@ -0,0 +1,255 @@ + + + + + + + + + RGraph: HTML5 canvas graph library - bi-polar chart + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Bi-polar chart

+ + + +
+

+ The Bi-polar chart is also (possibly more commonly) known as an age-frequency chart or a population pyramid. It allows you to very straight forwardly + compare two sets of data. For example two years worth of sales figues. Using this type of chart abnormalities will become + apparent. Other charts that would also be comparable, include a grouped bar chart, a stacked bar chart, and a multiple + line graph. +

+ +
+ +
+ +
+
+ [No canvas support] + [No canvas support] +
+ +
+ [No canvas support] + [No canvas support] +
+
+
+ + + \ No newline at end of file diff --git a/RGraph/examples/donut.html b/RGraph/examples/donut.html new file mode 100644 index 0000000..567c6fe --- /dev/null +++ b/RGraph/examples/donut.html @@ -0,0 +1,256 @@ + + + + + + + RGraph: HTML5 canvas graph library - donut chart + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Donut chart

+ + + +
+ +

+ Formerly the Donut chart was a separate class, though now it's a variant of the Pie chart. This means smaller downloads and + a much simpler implementation. Essentially it's a Pie chart with a big hole in the middle. If you want to compare multiple + datasets you will probably be better off with something like a stacked or grouped bar chart, as you will be able to make + comparisons easier. +

+ +
+ +
+ +
+
+ [No canvas support] + [No canvas support] +
+ +
+ [No canvas support] + [No canvas support] +
+
+
+ + + + \ No newline at end of file diff --git a/RGraph/examples/funnel.html b/RGraph/examples/funnel.html new file mode 100644 index 0000000..066822a --- /dev/null +++ b/RGraph/examples/funnel.html @@ -0,0 +1,234 @@ + + + + + + + RGraph: HTML5 canvas graph library - funnel chart + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + +

RGraph: HTML5 canvas graph library - Funnel chart

+ + + +

+ The funnel chart can be used to show stages in a sales or order process, from initial lead/contact through to actual sale. + It works well if you have a diminishing process, like that shown below. It can show potential revenue in each stage, or + like below, it can show actual numbers. It can also highlight potential problems in an organisations sales and/or order fulfillment + processes. +

+ +
+
+ +
+ +
+
+ [No canvas support] +
+ +
+ [No canvas support] +
+
+
+ +
+
Initial contact
All potential cutomers were contacted and
interest was established.
+
Established lead
Customers who were interested had their details
recorded and passed to the sales team.
+
Sales Call
Interested Customers were called by the
sales team.
+
Site visit
The Customers site was visited by a representative
of the sales core.
+
Sale agreed
A sale was finalised by the sales core.
+
+ + + \ No newline at end of file diff --git a/RGraph/examples/gantt.html b/RGraph/examples/gantt.html new file mode 100644 index 0000000..eac08a9 --- /dev/null +++ b/RGraph/examples/gantt.html @@ -0,0 +1,272 @@ + + + + + + + RGraph: HTML5 canvas graph library - gantt chart + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Gantt chart

+ + + +
+

+ A Gantt chart is used to show scheduling information. It is commonly used in project management but can also be used, + for example, to show holiday schedule information. In this case it would be easy to see when someone is unavailable. + The Gantt chart can have clickable bars that can be used to provide more detail. It can also show vertical bars + that can be used to indicate events, or as in the cases below, can be decorative. +

+ +

+ The chart is made of "units", in this case 365. This represents days in a year. The labels are separate, being equally + spaced across the chart. This means you can use more meaningful labels, which are easier to comprehend. As in the + example charts. +

+
+ +
+ +
+ +
+ [No canvas support] + [No canvas support] +
+ + + \ No newline at end of file diff --git a/RGraph/examples/hbar.html b/RGraph/examples/hbar.html new file mode 100644 index 0000000..4d2eb98 --- /dev/null +++ b/RGraph/examples/hbar.html @@ -0,0 +1,244 @@ + + + + + + + RGraph: HTML5 canvas graph library - horizontal bar chart + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Horizontal bar chart

+ + + +

+ A horizontal bar chart can be useful when your labels are too big for a regular bar chart. +

+ + + + [No canvas support] + [No canvas support] + + + \ No newline at end of file diff --git a/RGraph/examples/hprogress.html b/RGraph/examples/hprogress.html new file mode 100644 index 0000000..826becd --- /dev/null +++ b/RGraph/examples/hprogress.html @@ -0,0 +1,212 @@ + + + + + + + RGraph: HTML5 canvas graph library - horizontal progress bar + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Horizontal Progress bar

+ + + +

+ This is a Progress Bar for showing state. You can show anything with it - use it to show load on your server, + or percentage space free on your servers disk drive. You could even incorporate it with some AJAX to retrieve status information + from your webserver dynamically, making the Progress Bar realtime. To redraw the progress bar simply call RGraph.Clear() + (which clears the canvas) and then call myProgress.Draw() again. +

+ +

+ The colours, title and scale are configurable, allowing you to represent a wide range of values. +

+ +
+ +
+ +
+ [No canvas support] + [No canvas support] +
+ + + \ No newline at end of file diff --git a/RGraph/examples/index.html b/RGraph/examples/index.html new file mode 100644 index 0000000..fc2f7da --- /dev/null +++ b/RGraph/examples/index.html @@ -0,0 +1,171 @@ + + + + + + RGraph: HTML5 canvas graph library - examples + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Example pages

+ + + +

+ The following example pages are available: +

+ + + + + + + \ No newline at end of file diff --git a/RGraph/examples/led.html b/RGraph/examples/led.html new file mode 100644 index 0000000..bfa3827 --- /dev/null +++ b/RGraph/examples/led.html @@ -0,0 +1,200 @@ + + + + + + + RGraph: HTML5 canvas graph library - LED grid + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - LED Grid

+ + + +

+ An LED grid, that could be used to show a multitude of things. Could be used as a website counter for example. + It supports the A-Z, 0-9 and space characters. As you can see the colors are also user-definable. It also + supports the context menu, and therefore the zoom. The first LED grid demonstrates this. +

+ +
+ +
+ +
+ [No canvas support] + [No canvas support] + [No canvas support] + [No canvas support] + [No canvas support] +
+ +











+ + + \ No newline at end of file diff --git a/RGraph/examples/line.html b/RGraph/examples/line.html new file mode 100644 index 0000000..023cc61 --- /dev/null +++ b/RGraph/examples/line.html @@ -0,0 +1,350 @@ + + + + + + + + RGraph: HTML5 canvas graph library - line chart + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Line chart

+ + + +
+

+ Like the Bar chart, the line chart is one of the most versatile chart types. It is similar, but can indicate chronological + data better. The line chart is good if, for example, you want to illustrate sales figures over a year (or any period of + time). You'll then be able to easily see whether sales are going up, down or are stagnant. It will also become apparent + which months are busier than others. By using a multiple line chart you can add multiple sets of data (eg two or more years + of figures) to your chart. You can customise the line chart by stipulating it as being filled, having drop shadows, keys, + having the X axis in the centre, different colors, different tickmark styles and tooltips etc. +

+ +

+ The first graph uses external DIVs for the tooltip contents. The DIVs are at the bottom of this page (they're set not to + be visible). Using external DIVs for tooltips can make maintenance easier. +

+ +
+ +
+ +
+ [Please wait...] + [Please wait...] + [Please wait...] + [Please wait...] +
+
+ + +
+ +
Los Angeles
Home of sexy time!
+
Plymouth
Plenty of surfers dude
+
Meadowhall
Shopping heaven (or hell...) here
+
Sydney
Home of kangeroos
+
Toronto
Brrrr, chilly
+
France
Ever had frogs legs?
+
Norway
Skiing here
+
Sweden
Skiing here too
+
Spain
Hola!
+
Deli
Hot and humid here
+
Congo
Not exactly a holiday resort
+
Plymouth
Plenty of surfers here
+
Brazil
Fooseball
+
Califonia
"I'll be back..." And he was
+
New York
Home of the Friends comedy show
+
Paris
Ever eaten frogs legs?
+
UK
Not a place for getting sun-tans
+
Antartica
Surprisingly, incorporates the driest place in the world
+
Sahara
A questionable film, and a rather hot place
+
Zagreb
Anyone know where this is...?
+
+ + + \ No newline at end of file diff --git a/RGraph/examples/meter.html b/RGraph/examples/meter.html new file mode 100644 index 0000000..c444415 --- /dev/null +++ b/RGraph/examples/meter.html @@ -0,0 +1,233 @@ + + + + + + + RGraph: HTML5 canvas graph library - meter + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + +

RGraph: HTML5 canvas graph library - Meter

+ + + + + +
+

+ The Meter is similar to the Odometer albeit only a semi-circle and not a full circle. It can be better when trying illustrate + a particular level, but only have a limited amount of space. It could also be quite effective as part of a control panel. +

+ +

+
+ +
+ +
+ +
+
[No canvas support]
+
[No canvas support]
+
[No canvas support]
+
+ + + \ No newline at end of file diff --git a/RGraph/examples/odo.html b/RGraph/examples/odo.html new file mode 100644 index 0000000..7305e87 --- /dev/null +++ b/RGraph/examples/odo.html @@ -0,0 +1,241 @@ + + + + + + + RGraph: HTML5 canvas graph library - odometer + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + +

RGraph: HTML5 canvas graph library - Odometer

+ + + + + +
+

+ The Odometer can be used to provide an indication of a particular value. For example you could easily use it to + represent values for a control panel that shows information about a server. An Odometer indicating how much disk + space is used for example, would be more visual than a simple number. +

+ +

+ The green, yellow and red areas are configurable, allowing you to add some level of urgency into your figures. The + figures are also configurable, so it can go from 0-10, or from 0-100. +

+
+ +
+ +
+ +
[No canvas support]
+
[No canvas support]
+
[No canvas support]
+ + \ No newline at end of file diff --git a/RGraph/examples/pie.html b/RGraph/examples/pie.html new file mode 100644 index 0000000..0519f10 --- /dev/null +++ b/RGraph/examples/pie.html @@ -0,0 +1,241 @@ + + + + + + + RGraph: HTML5 canvas graph library - pie chart + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Pie chart

+ + + +
+ +

+ The Pie chart can be used when you need to represent value as part of a whole. It is commonly used to represent percentages, + relative magnitudes or relative frequencies. If your intent is to compare a particular value (slice) against the whole of + the Pie chart, then it can be quite effective. If however you want to compare two seperate segments, then it can get + more difficult. If this is the case, you may want to consider a bar chart for example. +

+ +

+ The colours can of course be customised, as can the borders (using the same color as the background and a line width of + about 5 gives the effect of segment separation. The chart can also have a drop shadow if you want one, but this shouldn't + be used in conjunction with segment seperation. +

+ +

+ The first pie chart has a fade-in effect. This not part of the RGraph library but is very easy to implement. +

+
+ +
+ +
+ +
+ [No canvas support] + [No canvas support] +
+ + + \ No newline at end of file diff --git a/RGraph/examples/rose.html b/RGraph/examples/rose.html new file mode 100644 index 0000000..b48aad0 --- /dev/null +++ b/RGraph/examples/rose.html @@ -0,0 +1,187 @@ + + + + + + + RGraph: HTML5 canvas graph library - rose chart + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Rose chart

+ + + +

+ The Rose chart was formally called the Radar chart. +

+ + + + [No canvas support] + [No canvas support] + + \ No newline at end of file diff --git a/RGraph/examples/rscatter.html b/RGraph/examples/rscatter.html new file mode 100644 index 0000000..b6e6297 --- /dev/null +++ b/RGraph/examples/rscatter.html @@ -0,0 +1,198 @@ + + + + + + + + RGraph: HTML5 canvas graph library - Radial scatter graph + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Radial scatter graph

+ + + +

+ The Radial scatter chart is a circular variant of the regular Scatter chart, and as the name suggests, circular. It + may be more suited to your dataset than the regular scatter chart. +

+ +
+ +
+ +
+ [No canvas support] + [No canvas support] +
+ + + \ No newline at end of file diff --git a/RGraph/examples/scatter.html b/RGraph/examples/scatter.html new file mode 100644 index 0000000..18f906e --- /dev/null +++ b/RGraph/examples/scatter.html @@ -0,0 +1,302 @@ + + + + + + + + RGraph: HTML5 canvas graph library - scatter graph + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Scatter graph

+ + + +

+ The Scatter graph uses two variables to plot points and makes it clear where there are congregations. The data points + make up the X and Y coordinates. The labels on the X axis are separate from the X units, allowing you to "group" them. For + example, like the example, you could set the maxium X value to be 365, but only have four labels. That way you would + have a granularity of a day, but the X axis would only have four labels. Like the example. +

+ +
+ +
+ + [No canvas support] + [No canvas support] + + + + + + + + + + +
[No canvas support]
+
+ This is an example of a box plot. You can read about them here. +
+
+ + [No canvas support] + + + + \ No newline at end of file diff --git a/RGraph/examples/showcase.html b/RGraph/examples/showcase.html new file mode 100644 index 0000000..a6d0c56 --- /dev/null +++ b/RGraph/examples/showcase.html @@ -0,0 +1,68 @@ + + + + + + + RGraph: HTML5 canvas graph library - shwowcase page + + + + + + +

RGraph: HTML5 canvas graph library - Showcase page

+ + + +

+ Since the showcase page was becoming too slow and heavy and producing an awful lot of graphs, each graph type now has its + own example page. +

+ + + + + + + \ No newline at end of file diff --git a/RGraph/examples/text.html b/RGraph/examples/text.html new file mode 100644 index 0000000..bb0e7a1 --- /dev/null +++ b/RGraph/examples/text.html @@ -0,0 +1,104 @@ + + + + + + + RGraph: HTML5 canvas graph library - Animated rotating text with the RGraph software + + + + + + + + + + + + +

RGraph: A text function that does horizontal and vertical alignment (and spins)

+ + + + + + + + + + + +
The fallback HTML
+   +   + +
+ +

+ RGraph.Text() is a text drawing function that allows vertical and horizontal alignment, and allows you to specify the angle of the + text too. The animation is done by a simple gobal variable, setTimeout() and redrawing the entire + canvas every frame. Perhaps not the most efficient of methods, but remember that your Javascript will likely be + running on computers that have more processing power than + some small countries... Reset the page +

+ +

+ In a similar vein you could easily make some text that bounces from one side of the screen to the other, + hurrah - the return of <marquee>! +

+ +
+ More examples can be found on the individual example pages, and a more complete + reference to the Text() function can be found in the API docs. +
+ + + \ No newline at end of file diff --git a/RGraph/examples/tradar.html b/RGraph/examples/tradar.html new file mode 100644 index 0000000..fc28a35 --- /dev/null +++ b/RGraph/examples/tradar.html @@ -0,0 +1,240 @@ + + + + + + + + RGraph: HTML5 canvas graph library - Traditional radar chart + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Traditional radar chart

+ + + +
+
+ +

+ A traditional radar chart, that is similar to the Rose chart. Each of the data points is + arranged equally in terms of angle, whilst the magnitude of each point is shown by the distance from the centre. Thus, + data points of a higher magnitude can be seen as they are more distant from the centre. +

+ +

+ Suitable for many datasets, but not all. If not, then the Rose chart may be more apt. +

+ +

+ The circle, as can be seen in the second example, could be used to indicate a threshold of sorts. In the example, + it could be minimum sales required for a particular month. Months that fall below this threshold can be clearly seen. +

+ +
+ +
+ +
+ [No canvas support] + Get PNG + [No canvas support] +
+ + + + + + \ No newline at end of file diff --git a/RGraph/examples/vprogress.html b/RGraph/examples/vprogress.html new file mode 100644 index 0000000..dc37bd6 --- /dev/null +++ b/RGraph/examples/vprogress.html @@ -0,0 +1,209 @@ + + + + + + + RGraph: HTML5 canvas graph library - vertical progress bar + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Bookmark and share: + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+
+ + + + + +

RGraph: HTML5 canvas graph library - Vertical Progress bar

+ + + +

+ This is a Progress Bar for showing state. You can show anything with it - use it to show load on your server, + or percentage space free on your servers disk drive. You could even incorporate it with some AJAX to retrieve status information + from your webserver dynamically, making the Progress Bar realtime. To redraw the progress bar simply call RGraph.Clear() + (which clears the canvas) and then call myProgress.Draw() again. +

+ +

+ The colours, title and scale are configurable, allowing you to represent a wide range of values. +

+ +
+ +
+ +
+ [No canvas support] + [No canvas support] +
+ + + \ No newline at end of file diff --git a/RGraph/images/alex.png b/RGraph/images/alex.png new file mode 100644 index 0000000000000000000000000000000000000000..b4bce5eeb65188a1ac105daea3b04c7ef64e8150 GIT binary patch literal 2365 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 literal 0 HcmV?d00001 diff --git a/RGraph/images/analogo.gif b/RGraph/images/analogo.gif new file mode 100644 index 0000000000000000000000000000000000000000..9fd0aade1c7268a8f529e8dec86c8926de14a3e2 GIT binary patch literal 567 zcmV-70?7SGNk%w1VKx9Z0P+9;0095l+1bCpzkq;%{{R300000000000A^8LW00062 zEC2ui05$+N000C2Sh3vxFiNP@yg0KmmepVwaGfWf7g>5m>%MR-&-7rgqaXmhzUu&B zFBts!h(+Qq2~gn*$|TVEQ&N4{Y}VN*2&L2I@v9@434*gZeco|5+PFNvF4x(# zeVLrAk+(;cbGy5$X@fetW3fVhi?ge#zyg&_rCExMgsFFKqOX^lvwX;Gl5JDX#+i-e zn7l_#*Kos3wdnB7>mKoH-k;UH;*FZr)Zd`AjZ^1pL$qv$rX>_qOUXWWmw-j`CuUqD zVT?%G+6et9q7-5LP<6s}M;jPx1?k1x=xZg$A*TG*!9^zI5{%C(CMyH%U^$Rgq;LY~ z4UnUg@>1qFcj}*0XdZLTOJoe$J6_w!@Bq59>l|J7)Z8jrtZGbRC~aVa#CF)CoQ}dx z^&+vYxwAqmZk?O(7eKc;X)*i(QdP@ivhWHiOp>NoeRGQ#c8o5coPEA1SB8gqB2P#P zfAOqaXJ66Ko+qXjy*e1*r>7I9F0`6?5R}AnKk42goFv`(I`J zjZJ`t@sN(xryqaJr}VSTYNd6`E?Q>7b*E(}yo4>k&$WXc9EoY;$nr_d8{>H^JMo=7 ztjz0Gb(>H;k#Y`Lspt-BD`nUm%uk>#{{(Ni*JIrY7lem-T*DLsD?vJ=z* O0000!3-o~I^W$QE#77r_fyzr6T$7cbB zI14-?iy0WWK7cTz(;AZ*KtYytM_)$E)e-c?47?>FXd_r8$C2KzK(fmF~;{Q@0 zQvAObh&2DN4f?+}>i^o7|64WxZ;krDSMmQ|&HsB1|L+B|m;OJd`Tv;V|6@!4pHuvQ zPV@gc!~f@i>|_70Y5u`|NoEu2T6>A(GVEO5LlD`)fkvJG)jW}f{Ano!@gB|5iF63RrZxRvV1yg*9RZIV6fbLZ|hlsWRuK|3|4arZN7zQ813Du`Ib}TkK6<+ z?pb|XR{mMN&fSIWRlvc;HFg21wqXyY!Atj(9vbre(!pv-L~D@BEn=SLD1a;kDA<( Rn?2A+44$rjF6*2UngH}fl-U3P literal 0 HcmV?d00001 diff --git a/RGraph/images/bara1.gif b/RGraph/images/bara1.gif new file mode 100644 index 0000000000000000000000000000000000000000..9cdd5c21e9081ee5042d3452ede60a8b5d172182 GIT binary patch literal 39 rcmZ?wbh9u|3@AOMLlFtN4tuRLAL%3uuu!Vn4F literal 0 HcmV?d00001 diff --git a/RGraph/images/bara1.png b/RGraph/images/bara1.png new file mode 100644 index 0000000000000000000000000000000000000000..5b680241ac8de1ecf1f308b7d9c9b3b8e6e98524 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*$P6Tpoc7%Tq?iMILR|M78!H`dxCrEmmAFQf z1m~xflqVLYGNfmw85QKED;VjS=ou}JbLRu9;P!NJ45_%4oZtZD@GvmGe_^Z&WHETU L`njxgN@xNA2^1W} literal 0 HcmV?d00001 diff --git a/RGraph/images/bara16.gif b/RGraph/images/bara16.gif new file mode 100644 index 0000000000000000000000000000000000000000..d3bea17daaf063ff9cb6d6a83f76d0fc9bc25291 GIT binary patch literal 59 zcmZ?wbhEHbY+ztxXkcL2Z*2Vk|9>3@AOMLlFiExauRQ&hfAO3xx4Jjq+w+^h?UBc{ NXPwJlg)=Z%0{~qa7pMRL literal 0 HcmV?d00001 diff --git a/RGraph/images/bara16.png b/RGraph/images/bara16.png new file mode 100644 index 0000000000000000000000000000000000000000..2e085c2606a680fa810c195cbd2047cb3b047bd3 GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^4M5Ds$P6S6C0Trd6mx)2i0gi1W2M6l7lB-{64!{5 z;QX|b^2DN4hV;xdqk_D21tUEZJ)^~O?tDNMJf1F&Ar-fh6Be)od1(xc+xZT@2C^7D MUHx3vIVCg!0JHNPM*si- literal 0 HcmV?d00001 diff --git a/RGraph/images/bara2.gif b/RGraph/images/bara2.gif new file mode 100644 index 0000000000000000000000000000000000000000..1b978229b01de596ade9bad7b6b6f585ec13aa48 GIT binary patch literal 41 tcmZ?wbh9u|6kuRuXkcL2Z*2Vk|9>3@AOMLlFmbf>uRQ&hKUs^x8UWko3ibd1 literal 0 HcmV?d00001 diff --git a/RGraph/images/bara2.png b/RGraph/images/bara2.png new file mode 100644 index 0000000000000000000000000000000000000000..ec8904d6b062d9d963e9d666c0c6e8413c267e66 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~h$P6SuZ0cD8q?iMILR|M78!H`dxCrEmmAFQf z1m~xflqVLYGNfmw85QKED;VjS=ou}JbLRu9;P!NJ45_%4oZ!IDz#zoH_$0LVIZ&9v M)78&qol`;+04LBLl>h($ literal 0 HcmV?d00001 diff --git a/RGraph/images/bara32.gif b/RGraph/images/bara32.gif new file mode 100644 index 0000000000000000000000000000000000000000..919e45579a9ef82d9dd56bb808f3024722dee269 GIT binary patch literal 71 zcmZ?wbh9u|WME`tXkcL2Z*2Vk|9>3@5CDoWFsZfluRQ&hfAO3xx4Jjq+w+^h?UBc{ aXPwJlo!a(}`}ilH>)(2x|B7W`um%8?5g&5^ literal 0 HcmV?d00001 diff --git a/RGraph/images/bara32.png b/RGraph/images/bara32.png new file mode 100644 index 0000000000000000000000000000000000000000..f2f1e60ad5d3158afe8de575c08d96ee76a989ed GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5*ch3Cq}ZfOJwS>%z$e6Yzp=5>;f9MK(Gu5) zlHmNblJdl®4-G^2vNbOj?l6FsBFaqfIT6+E6Ujv*Ddk`p9AykiWE|Ne@20a*;5 Lu6{1-oD!M<`Uf2P literal 0 HcmV?d00001 diff --git a/RGraph/images/bara4.gif b/RGraph/images/bara4.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f2200bd0e04824641d26f4309b7281c08795508 GIT binary patch literal 45 xcmZ?wbh9u|RA69ZXkcL2Z*2Vk|9>3@AOMLlF!8kXuRQ&hfAO3xx3akytN|K74bK1o literal 0 HcmV?d00001 diff --git a/RGraph/images/bara4.png b/RGraph/images/bara4.png new file mode 100644 index 0000000000000000000000000000000000000000..77a114be859ed755ab6fbccf79dd97585b1cd129 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-p$P6TBIP%Q_Qp^E9A+Gz4jg<~JTm*8(N?apK zg7ec#$`gxH8PYS;j0*D76^!&u^o$nAx$^;4aC^EqhE&{2PB_5Mz#zxKm>M~+5Gc&x M>FVdQ&MBb@0K48C0ssI2 literal 0 HcmV?d00001 diff --git a/RGraph/images/bara8.gif b/RGraph/images/bara8.gif new file mode 100644 index 0000000000000000000000000000000000000000..dba412045ae50eacee7d2510733965fc1543ccfa GIT binary patch literal 50 zcmZ?wbh9u|bYNg(XkcL2Z*2Vk|9>3@AOMLlFbTHwuRQ&hfAO3xx4Jjq+w*(92!k~M DfCv&b literal 0 HcmV?d00001 diff --git a/RGraph/images/bara8.png b/RGraph/images/bara8.png new file mode 100644 index 0000000000000000000000000000000000000000..a318390b2b84774947e672561b5910af8990475d GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^4nWMt$P6SsmvOxTQp^E9A+Gz4jg<~JTm*8(N?apK zg7ec#$`gxH8PYS;j0*D76^!&u^o$nAx$^;4@OZj7hE&{2PEcS6^2`_*J36x(fh-13 LS3j3^P6-L1ke-=lRFIdhV5DcFXS6uZoe!u&#?!?yq~ca` t0t2I?LP7u&6I-%ELIERFTYv%sgUS--zkSj3^?>RaJYD@<);T3K0RV)yCS(8r literal 0 HcmV?d00001 diff --git a/RGraph/images/barb16.gif b/RGraph/images/barb16.gif new file mode 100644 index 0000000000000000000000000000000000000000..7d327d450bfae5d966ca845770f30708707a4203 GIT binary patch literal 126 zcmZ?wbhEHbY+ztxIK;s4tfJyUM8q{WxBbS(8w?CO)ztojfer%@fYdNBdvol%^UvUv z=jy!%FV61%pPUU@=I+-L1ke-=lRFIdhV5DcFXS6uZoe!u&&eO#)q~ca` v!U7SFAP$Ks8Z11=M3~sbxfq=_S{WENNZKFtPMf?QsFK0c)z4*}Q$iB}lC&tB literal 0 HcmV?d00001 diff --git a/RGraph/images/barb2.gif b/RGraph/images/barb2.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8fcec29185fba82dc9783afa53391c87f58466b GIT binary patch literal 76 zcmZ?wbh9u|6kuRuIK;s4tfJyUM8q{WxBbS(8w?CO)ztojfer%@fYdNBOLFYGBVce! avSqJD_rcx&nHBp|JVi2At#f5!um%7c;v1d- literal 0 HcmV?d00001 diff --git a/RGraph/images/barb2.png b/RGraph/images/barb2.png new file mode 100644 index 0000000000000000000000000000000000000000..cd365f5f670d834e722d54ade241f2b6e902c181 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~h!VDxWf|#!WDWL$L5Z7lF6%QgJuDQAGH#Xj2 zV9=?imRrwW1C$jjag8Vm&QB{TPb^AhNY6|&D#%M$Fw!&8Gg=(y&IeQ>zopr0Fh)TW&i*H literal 0 HcmV?d00001 diff --git a/RGraph/images/barb32.gif b/RGraph/images/barb32.gif new file mode 100644 index 0000000000000000000000000000000000000000..5579e9d3c78c7691047c64d7c7cd02349c9fef37 GIT binary patch literal 165 zcmZ?wbh9u|WME`tIK;s4tfJyUM8q{WxBbS(8w?CO)ztojfer%*0M#%s7jf*m^UvUv z=jy!{ug~s|chu-h$()z5YF*CjeFZw_OLVy^*1fNJ|Np>(0uLRj{u4`zPM+bNcVR_| z*V?G{H`bJ$ep|Kw!G;PR)fwksY^ge%xBLEw9W{RIZ@>Ss=U>c=-~SsLo0?l%+uA!i RySjUN`}!wLtm9;`1^{>wQ=|X@ literal 0 HcmV?d00001 diff --git a/RGraph/images/barb32.png b/RGraph/images/barb32.png new file mode 100644 index 0000000000000000000000000000000000000000..fe4049cdfc9523bb83fe2a8f6d7d8d83ee03ff19 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5*jSi>l=TzoI4Lx%HZkh=d#Wzp$P!doGc0e literal 0 HcmV?d00001 diff --git a/RGraph/images/barb4.gif b/RGraph/images/barb4.gif new file mode 100644 index 0000000000000000000000000000000000000000..726cd51a4fdd356fce4c1bc11feb0487859c2534 GIT binary patch literal 85 zcmZ?wbh9u|RA69ZIK;s4tfJyUM8q{WxBbS(8w?CO)ztojfer%@fYdNBD{<_)^H1l5 k=jy#7FV61%e@CG&C3Bw2!gV>X_vI*_FUh@M!o*+=0G00~AOHXW literal 0 HcmV?d00001 diff --git a/RGraph/images/barb4.png b/RGraph/images/barb4.png new file mode 100644 index 0000000000000000000000000000000000000000..13e38e92ff37c1b5e8d03627bb3744bf21f73215 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-p!VDw>7B;>CQbGYfA+FCVDjq~cTyt~VZ*085 zz@Sr2Ew`S%1}H05;u=vBoS#-wo>-L1ke-=lRFIdhV5DcFXS6uZoe!u&#?!?yq~ca` sf&+U~MuQ_KuYts3MmBMi0|H%a3?Fs*KOXy_4Kj(r)78&qol`;+02N6oQvd(} literal 0 HcmV?d00001 diff --git a/RGraph/images/barb8.gif b/RGraph/images/barb8.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb82f0c43be2de75ff0363798b19ec38311eb160 GIT binary patch literal 100 zcmZ?wbh9u|bYNg(IK;s4tfJyUM8q{WxBbS(8w?CO)ztojfer%@fYdNB8*=Qr^UvUv z#Hzg(ug_YGCusDgWX^kGxhCiJz5<=|Mv3<;*1fNJ|GjlVfrpM%{|OZ%Mh0sD+v_Sj literal 0 HcmV?d00001 diff --git a/RGraph/images/barb8.png b/RGraph/images/barb8.png new file mode 100644 index 0000000000000000000000000000000000000000..00db16cb124032806ea9039ac075805744aad68e GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^4nWMt!VDxE-CE}WDWL$L5Z7lF6%QgJuDQAGH#Xj2 zV9=?imRrwW1C$jjag8Vm&QB{TPb^AhNY6|&D#%M$Fw!&8Gg=(y&IeQ>>*?YcQgJIe uL4k#ZlYvc@so~%ZhJ*q|1_>ul28Pc0@()E8iR=a{WbkzLb6Mw<&;$V6IVTnX literal 0 HcmV?d00001 diff --git a/RGraph/images/barc1.gif b/RGraph/images/barc1.gif new file mode 100644 index 0000000000000000000000000000000000000000..ac54bcd12ce24cc727f1e971cb6f47a53d543ced GIT binary patch literal 68 zcmZ?wbh9u|-L1ke-=lRFIdhV5DcFXS6uZoe!u&&C|s(q~ca` z0uZDoh=_=!CIkfqr6!n}nWZKa78a%^@bdDqGDsg|mN^~O$O+WJ;OXk;vd$@?2>@hT BDuVz3 literal 0 HcmV?d00001 diff --git a/RGraph/images/barc16.gif b/RGraph/images/barc16.gif new file mode 100644 index 0000000000000000000000000000000000000000..e81b8b4b5c39692af824155000d8bc67bc0600d1 GIT binary patch literal 214 zcmV;{04e`RNk%v~VSoSz0KxzO=6HDESXkCZM!z#NurM%*CMN&?|NsC0EC2ui0Du4n z000A{2)a2s>vxZk{kdlp*j*yX$m7156oQam8pP87Uq@D$-st&8F4Xv!OudTDIwXU$S Qw7Ivby}Gu%!mtSdJHfkVApigX literal 0 HcmV?d00001 diff --git a/RGraph/images/barc16.png b/RGraph/images/barc16.png new file mode 100644 index 0000000000000000000000000000000000000000..9309f185c4d45d1d963233ab5513c7778308d5f4 GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^4M5Ds!VDyT{_M5|QbGYfA+FCVDjq~cTyt~VZ*085 zz@Sr2Ew`S%1}H05;u=vBoS#-wo>-L1ke-=lRFIdhV5DcFXS6uZoe!wOz|+Msq~ca` z0uU_aFy`Xw3Tl#^F=a}K=0Tn_$Br$VlE5Y=E*|b>z?_|tp`j|lFw5R>qo$ZHFHkRo Mr>mdKI;Vst08R8Td;kCd literal 0 HcmV?d00001 diff --git a/RGraph/images/barc2.gif b/RGraph/images/barc2.gif new file mode 100644 index 0000000000000000000000000000000000000000..c31c1229e5694f921404cf5d37ea15880226d677 GIT binary patch literal 80 zcmZ?wbh9u|6kuRuIK;s4tfJyUM8q{WxBbS(8w?CO)ztojfer%@fYdNB%W~`r*rRts ea(RhT_L|Mo2|rpFIL}$pInVFmKHWEJ4AuaimmfX= literal 0 HcmV?d00001 diff --git a/RGraph/images/barc2.png b/RGraph/images/barc2.png new file mode 100644 index 0000000000000000000000000000000000000000..e9894c6b064cae9771fc3cb9d65177a8124919f0 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~h!VDxWf|#!WDWL$L5Z7lF6%QgJuDQAGH#Xj2 zV9=?imRrwW1C$jjag8Vm&QB{TPb^AhNY6|&D#%M$Fw!&8Gg=(y&IeSX=jq}YQgJIe z0SH)=-5ebQ1=13Nf`V8R+0v4egMpmF!a^YD+Jy@N0&EOvT5RUCXFh!e)XCuK>gTe~ HDWM4f!No4o literal 0 HcmV?d00001 diff --git a/RGraph/images/barc32.gif b/RGraph/images/barc32.gif new file mode 100644 index 0000000000000000000000000000000000000000..a2d943b9a8c3c6dface1bb9b3fae33c4e83b5d75 GIT binary patch literal 318 zcmV-E0m1%9Nk%v~VE_RJ0KxzO=6HDESXkCZM!z#NurM%*CMN&?|NsC0EC2ui00037 z000C22)al8fIec< zC|u%-PbcySoi?e`sy55Tdaq#RR~%+41?aRRtp>2s>vxKih+!Ni;j(ekdu;?hI|8=nhu(q0G*kfprW0mo}dG!p`W9yrLL!~sH&;3tFyMX zxVy5wue`s$vBAW{#<#5m%F7PR%mB{H&C%1&)z8rc*V53`-PYgO-r3vQ;oRis=IQL? z?%?h4@8a_H^!MoA1^fIC{rnC7`4brMU%`F{0SX*waACrI4;dnKNReR0h88no+&BzT QV@Hk(J%$7cabW@gJ4xB7KL7v# literal 0 HcmV?d00001 diff --git a/RGraph/images/barc32.png b/RGraph/images/barc32.png new file mode 100644 index 0000000000000000000000000000000000000000..25bf53ca4049dc427e0a2be5cedece170c3f35b0 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5*jSi>3v@ufo&o0z!x^~NJSYZfkC$lS?z+cG(^=-b}i PK+O!Eu6{1-oD!M7B;>CQbGYfA+FCVDjq~cTyt~VZ*085 zz@Sr2Ew`S%1}H05;u=vBoS#-wo>-L1ke-=lRFIdhV5DcFXS6uZoe!u&&(p;*q~ca` z0uZ}hIRbYe!Mr>Cc=q_Kgt^lYVMHZgJW@RTzLq@<*}dKlZ@^5pu+1uOyTWbkzL Kb6Mw<&;$UWEiixp literal 0 HcmV?d00001 diff --git a/RGraph/images/barc8.gif b/RGraph/images/barc8.gif new file mode 100644 index 0000000000000000000000000000000000000000..3dea117adc3b8b8aff301dacd873c67a6f9be671 GIT binary patch literal 145 zcmZ?wbh9u|bYNg(IK;s4tfJyUM8q{WxBbS(8w?CO)ztojfer%@fYdNB$8qcm*z?ZR zGPP!UDo4}*bL?eF0@Iey=v(T!szKrWIiKU(0-o=_d*4#_9J_=>f1mQE6*4Nb{ZmVB vmKZH%XexVsqiA!Slex{eY5NlmZ`{$?asTahYrW-%pO)`&-hW-4fx#L85#^p*iBu@cva zlHmNblJdl®4-G^2vNbOj?l6FsBFaqfIT6+E6Ujv*Ddk`q!IoEaDl7}$BvUS1Cr OXYh3Ob6Mw<&;$Tbf*t?> literal 0 HcmV?d00001 diff --git a/RGraph/images/bard16.gif b/RGraph/images/bard16.gif new file mode 100644 index 0000000000000000000000000000000000000000..02effec69fe1a59491c872156303b9a478aae493 GIT binary patch literal 104 zcmZ?wbhEHbY+ztxXkcL2Z*0uKz@P)fKpqk=uu3)5RqGz-?&Ycgag5T4{F{I*Fa)Jvp&lUj&2H`e_#G8KW RX9J}eJYD@<);T3K0RSJ;9ZLWJ literal 0 HcmV?d00001 diff --git a/RGraph/images/bard2.gif b/RGraph/images/bard2.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ff157eaafb0220b1da85f88d0875bcf20525d6e GIT binary patch literal 48 zcmZ?wbh9u|6kuRuXkcL2Z*0uKz@P)f3?LB(CjJ)w#^tmB#Y78-vaP>3QH;SF0M%y- AkN^Mx literal 0 HcmV?d00001 diff --git a/RGraph/images/bard2.png b/RGraph/images/bard2.png new file mode 100644 index 0000000000000000000000000000000000000000..f56db0ac43838ef6d4c561c75df671c2205b31b6 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~h$P6SuZ0cD8;sp4Fxb8PL1~R>#^p*iBu@cva zlHmNblJdl®4-G^2vNbOj?l6FsBFaqfIT6}+AKJ&FOcLvX O5)7WMelF{r5}E*is~y|` literal 0 HcmV?d00001 diff --git a/RGraph/images/bard32.gif b/RGraph/images/bard32.gif new file mode 100644 index 0000000000000000000000000000000000000000..da07a92ad16b0237b0b7c959ff9591c9de4f20bf GIT binary patch literal 147 zcmV;E0Brw9Nk%v~VE_RJ0Du4hzcVuc001li000000R{j70&;{8fv21PTw4=W2CvbP z<}ZO>NRFl@qNRFbtJ`iV%+~ZRzj@r*yWhhFe?pFNMobQuM;#OSbT)ZYV6_OnDz#B+ z_A3Q@!{o8qDn^&pXYAVD-lpN~I{hwx=i^=b-rt88_$SC^I7gT`xOk|?h?r0S06VAC BKnnl> literal 0 HcmV?d00001 diff --git a/RGraph/images/bard32.png b/RGraph/images/bard32.png new file mode 100644 index 0000000000000000000000000000000000000000..8b507f47dfb064a2369276de1d64016fcbf85fa3 GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5*ch3Cq}ZfOJs?hiPl)S&V`CuG>q&1JNTS3w zq9iy!t)x7$D3u{SGtHgq128p&NCI)XdhJz7n S<~##RF?hQAxvX3@tJ;OoJZd> J)hJd5YXDgJ4wnD` literal 0 HcmV?d00001 diff --git a/RGraph/images/bard4.png b/RGraph/images/bard4.png new file mode 100644 index 0000000000000000000000000000000000000000..7f6ff8245c77fc851a64e4859e32c18b4cbe3fda GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-p$P6TBIP%Q_aRPioT=yFr1DRe=ddq;6Scz*y zNpOBzNqJ&XDnoi^no&Vsx`L6OiJsBoICnmv3O-L4$B>F!$q6h>Y%wehjBN~(xeij? PKp6&4S3j3^P63@tJ;OoJZd> e)kRCIl2+f&(>!zSi|+o)J2!XVPZnWdum%7Yof?b) literal 0 HcmV?d00001 diff --git a/RGraph/images/bard8.png b/RGraph/images/bard8.png new file mode 100644 index 0000000000000000000000000000000000000000..c49f78b2655c1980eca19d033c70635a36c4415f GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^4nWMt$P6SsmvOxTaRPioT=yFr1DRe=ddq;6Scz*y zNpOBzNqJ&XDnoi^no&Vsx`L6OiJsBoICnmv3O-L4$B>F!$q6k?Y(WwXtZod3En>`3 PKp6&4S3j3^P6-{3=BHe)c*hfuLBfi0I6YM7U9?> Y@F}3h@im7^wouo9*My!Wf+`Hw0Q@f%(f|Me literal 0 HcmV?d00001 diff --git a/RGraph/images/bare1.png b/RGraph/images/bare1.png new file mode 100644 index 0000000000000000000000000000000000000000..3dbd49a303e03645b448463104004dc1d72509ad GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*!VDyNv=5yCQlbGqA+FCVDuB!f5fRti-1ZwA zZ!j?ER8uSJeDDA$DpukeQ4*Y=R#Ki=l**8vnPyawm#$!>XQF4cIL@69s6x%t#WAGf zR&oLmqyz*71*I66nVF>&6c!eyaPac-rg(UJd$TZ@JY{w6EKWZF)WP8C>gTe~DWM4f D3_C2Q literal 0 HcmV?d00001 diff --git a/RGraph/images/bare16.gif b/RGraph/images/bare16.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e06ff5ae5eeb3f055734a752b841a8d0ae7e477 GIT binary patch literal 201 zcmV;)05<&aT zd1N-3%Vg9zRXVFg>{EK}La&6dm=G9?%Vu&~okpA8WB7S357*gmy1q>>`2Pg~fPaF6 zfrf{Mg@cQLjf9Agev*ldk(Y{*2AiA)0iB$mpq`_oqoSawovNXwtedZXQF4cIL@69sKUV0#WAGf zR&oLmEaA}B)YJ@WlI-d2<<&gMqo=3WHzlF%!i5VCUIxxlQBg{&5)4=0ged-2%X0wg OW$<+Mb6Mw<&;$SoGBe8n literal 0 HcmV?d00001 diff --git a/RGraph/images/bare2.gif b/RGraph/images/bare2.gif new file mode 100644 index 0000000000000000000000000000000000000000..b807ac50673cff4faccbe5caa0d727454e4571aa GIT binary patch literal 85 zcmZ?wbh9u|6kuRuIK;s4tfGQ}f#E?!#5Fg!{l>-{3=BHe)c*hfuLBfi0I6YMR^r$t nu*dO)rqa~J7q&*%85R3nJh~hgu5&%Ls!{R0o6l)SCI)K&YHu7C literal 0 HcmV?d00001 diff --git a/RGraph/images/bare2.png b/RGraph/images/bare2.png new file mode 100644 index 0000000000000000000000000000000000000000..f47d362e3b6c3944ead91b3815ef43c609119850 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~h!VDxWf|#!WDbWC*5Z7lF6+q^Lh=^-$Zu^am zHy9Xns;L!qK6n5W6)SO#C<)F_D=AMbN@YmTOfxFTOII+`Gto0z9OuplRH5hT;uunK zD>(rOSdvv$Rb2(r49v{TSQ6R9#l_tP(l~f|d07(MwrttrBEZJ5PlT(LUG!ibP$z?@ LtDnm{r-UW|);}x5 literal 0 HcmV?d00001 diff --git a/RGraph/images/bare32.gif b/RGraph/images/bare32.gif new file mode 100644 index 0000000000000000000000000000000000000000..6b7dae94bab0f3c14f7f7b4751ca159e2850ef33 GIT binary patch literal 300 zcmV+{0n`3RNk%v~VE_RJ0KxzO=6HAj007`vSk^{HzcVwiFffTGCjbBcEC2ui00037 z000B|2)Yow?ln1Oe3xZNxAGO%jTR}E=&5QZo4PCa%JC=MxDe#{&g(zm&&MO?jJ+W8 zwiFhX&|&l`tx~VYY1X>MCb?fPb3iT+0_HM0eP*}W>vY^aSG((E{9AtS!~J}Jf`No| zfQEyJg?5RIi+Kc*k^}*hl9iT}nVOlHmY$QKmz$!IrJSFns-3H;tgo)Ip{=v9wX&nO zxwxhUzP|+lz`w%7!N$kN#ly?M&BVyhzS7Ce(bvk@*4f;}M?B%*;;aPDX}1D;$H8 Ss`mjkGkCiCxvX-{3=BHe)c*hfuLBfi0I6YMHsjbO zu;-oW&6d4N4_23dyQ$FU?9lfta+T`CeJ%|9KgrxKT=?Gg!25mi{x^&z`r8;jt%y;Z Jdy<908UW41Dp>#k literal 0 HcmV?d00001 diff --git a/RGraph/images/bare4.png b/RGraph/images/bare4.png new file mode 100644 index 0000000000000000000000000000000000000000..55e908882d47ab543747731a4deffcd42a0c376b GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-p!VDw>7B;>CQlbGqA+FCVDuB!f5fRti-1ZwA zZ!j?ER8uSJeDDA$DpukeQ4*Y=R#Ki=l**8vnPyawm#$!>XQF4cIL@69s6x-v#WAGf zR&oLmxE%EI^6EM<1aeH*GoIsj-OE24VMrtdio_$* wxMVJsNN7=-ELg9F0QRcgX1!l;cRR+GxrVgb5Lm0*ZgyNAhr8`-{5t^vI}8Ij2><{9 literal 0 HcmV?d00001 diff --git a/RGraph/images/bare8.png b/RGraph/images/bare8.png new file mode 100644 index 0000000000000000000000000000000000000000..394629437cbea1efc76eb609a43d9fb96cf14fd5 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^4nWMt!VDxE-CE}WDbWC*5Z7lF6+q^Lh=^-$Zu^am zHy9Xns;L!qK6n5W6)SO#C<)F_D=AMbN@YmTOfxFTOII+`Gto0z9OuplRH5(b;uunK zD>(rOj&x6*GDYNLB3p8DvUAOhgGY}Z6_iio;N|5#(k^-F(j}pfi3|@yv;@-(ycPhp OGI+ZBxvXG B4K4rx literal 0 HcmV?d00001 diff --git a/RGraph/images/barf2.png b/RGraph/images/barf2.png new file mode 100644 index 0000000000000000000000000000000000000000..0301e20427fda3ff2b370c1b2e9f43c8191d909f GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~h$P6SuZ0cD8;sp4Fxb8PLmW`g+5Iai(C?Zzk z8c`CQpH@bS RDFI3_c)I$ztaD0e0s!G@A!Psn literal 0 HcmV?d00001 diff --git a/RGraph/images/barf32.gif b/RGraph/images/barf32.gif new file mode 100644 index 0000000000000000000000000000000000000000..7cc2992aba9a8bd4e9c87f318fb6ec325a117754 GIT binary patch literal 181 zcmV;m080NyNk%v~VE_RJ0Du4hzcVu(TahdP000000R{j70+fVrp{t0@+<{9b8Z5xs za{YN2IEoZ`nh?6Gkz2uy+)1Hb;;G*9uO9=>gf+*_m_zQAJ?76Dgbt;}N7A~)HnmS~ z)H?-NCs%UTyhV4_Uv}6%zMSQ0`r6*czxDA=na^_PH#b;UD0n0mn0LsS2)DS`DESCT j6WLcenfbSg`FR;i1Uf28MS5zgs0ztySqhs6vLp1$pTTMtUZCMvLRz`G6|;JzX3_DsCkw{P1VsV`XJH`ze0m Te;1=zpcI3rtDnm{r-UW|v~VB{ literal 0 HcmV?d00001 diff --git a/RGraph/images/barf4.gif b/RGraph/images/barf4.gif new file mode 100644 index 0000000000000000000000000000000000000000..a321258fa206314a6e059c78f3864b3a0a7d74be GIT binary patch literal 58 zcmZ?wbh9u|RA69ZXkcL2Z)_|ZJyC}N2tXnXOp-163s-lXxzp&aCZ%)WX3^hD35za~ K%2@%74AuaneGr`h literal 0 HcmV?d00001 diff --git a/RGraph/images/barf4.png b/RGraph/images/barf4.png new file mode 100644 index 0000000000000000000000000000000000000000..381e5ee69cf67285c99bc0398f23ea1f9eba26a6 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-p$P6TBIP%Q_aRPioT=yFr%SKOZh@B+?6cHEaktaVt6D2Y<^B4u-V_++Tlx S=)VG#VeoYIb6Mw<&;$UNq#EaktaVt6D2Y>4l1BS{Q;x9j| S-8TWsFnGH9xvXuDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H l+J7XV!vF*zy$mcu0w*+E_fC7Uw)elBQs1Jad1)*R)&TAtCdmK* literal 0 HcmV?d00001 diff --git a/RGraph/images/barg1.png b/RGraph/images/barg1.png new file mode 100644 index 0000000000000000000000000000000000000000..42943495126827c2e3e5331091f0b38d5e807b5b GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*!VDyNv=5yCQi=gSA+FCVDuB!f5fMQ0nwuMt z+;40QBsUls0Le}@wNf7ueIQG$#5JNMI6tkVJh3R1Aw4tAs30$0!AQ?U&uDR+J0DPm zjHioZNX4z>1O`S`g@gh|rZy9Wgcl4uDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H z+J7XV!vF*zy$mc11Wsr+@0}LZ^YzK}@Ww`t2}?U>t@h$7;NdUvJ-sRS@y58%#`hUC z1o#@=l7uu>EasnUD$#0nS{d?M*!rs5PF8(JnQxPhrW@ZlkhhutgT1E~&~o6K zo0~$`lKsZUve6Sa7#K(dG<2$|i8!Slu?*q`suwG9jVKAuPb(=;EJ|fa&rCBa$V*o+ z(lgOBS{&!j2UKC^>Eaktacl0;gA5D`3@isjJrr9-f?&jxsJ7YX8@e8?o^|P^lvjF| h=G?W5OV-W1WdDb$$8pD|1~H%s44$rjF6*2UngGVrKt%um literal 0 HcmV?d00001 diff --git a/RGraph/images/barg2.gif b/RGraph/images/barg2.gif new file mode 100644 index 0000000000000000000000000000000000000000..22dc68479ac00de3e19ab6049356612f851f6d66 GIT binary patch literal 111 zcmZ?wbh9u|6kuRuc+9}?tfIng+QSDC5e6*>uDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H z+J7XV!vF*zy$mcW0w*+^_lCV#+x}lpu`elc-m-=3UOn8Wr*yt3>HfAw?|(h|zmJ2# F8UQwSGcN!D literal 0 HcmV?d00001 diff --git a/RGraph/images/barg2.png b/RGraph/images/barg2.png new file mode 100644 index 0000000000000000000000000000000000000000..c68a70f279c86badfe9d614a6cd5d4e988bc3ff9 GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~h!VDxWf|#!WDU|@95Z7lF6>ifWK8T1gXgP4r z%}pU|$$n#F+31NI3=AX!8ama~M4Zx&SO)O|)r*z5MwA5Sr6z#mEsk^N1FF#Rba4!+xRsp1z~rcq5WvKgtdLN^*c70U;KAHfq>%7}p=qYWfel<7 cWz38W`l5oJuP?b90QE6=y85}Sb4q9e09TeX4gdfE literal 0 HcmV?d00001 diff --git a/RGraph/images/barg32.gif b/RGraph/images/barg32.gif new file mode 100644 index 0000000000000000000000000000000000000000..b57f0a7f32bd54d0d154d5471c7c3ce51b61b842 GIT binary patch literal 337 zcmV-X0j~Z>Nk%v~VE_RJ0OJ4v=6HBUmf_%7STKaZ)<#AkYNWq2GaXxzurM$fP=JXh zCKN(u|NsC0|NsC0|NsC0EC2ui00037000F35XdQmy_Qmp_2idVfq@8+rHGoVO0usD z!n4fLx83O>ZwbI4a6l{)g+ikd8B`XTL+1c0kWQgiY8ETicDYV(7_1bR$xHN8O(eMA z?t*+Shr{V~`x`&k$N2?*1b~5lgo1~LfQXBVe2kBdc#xBld6s>cat558oClzxpq`$h zqNJUsp{Sp#2doCJudK4LwY09bxwxvjy}YKr!N8})tHz)R%FD_L&d<)w%+S!%%hb=- z&DaUr2;AM;;NIin+~nux*y!u()a>u>)$-Z&&IiUuua#3)c>M~(*rK^_#zF9HBN4#BUb literal 0 HcmV?d00001 diff --git a/RGraph/images/barg32.png b/RGraph/images/barg32.png new file mode 100644 index 0000000000000000000000000000000000000000..62f3d489639921753d6019dc37a512c2360680bf GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5*jSi>5yg>D0C9V-A!TD(=<%vb94C$F^Mg@84 z3PyS+dPa-m-1&ei%spKkLn>|^J$jIVL4kqgV5o;;t4I)xcoNk;`+P%JQn=~TW!W00 k!QLxxT6vwl8vKf%K}2H0ys))E6BrmgUHx3vIVCg!096V-3IG5A literal 0 HcmV?d00001 diff --git a/RGraph/images/barg4.gif b/RGraph/images/barg4.gif new file mode 100644 index 0000000000000000000000000000000000000000..927951f17846a4d54c5e428e2543d063b482fe0c GIT binary patch literal 132 zcmZ?wbh9u|RA69Zc+9}?tfIng+QSDC5e6*>uDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H z+J7XV!vF*zy$mdt0w*+^_f8AyY5jjsp-+iplFGt$Sr7N=oj$Z7@&31k@2&bi+q4vD a_(=4-DG7FlSj<1yTB6nJwDJlEgEau2$vNr( literal 0 HcmV?d00001 diff --git a/RGraph/images/barg4.png b/RGraph/images/barg4.png new file mode 100644 index 0000000000000000000000000000000000000000..262d862f7b3b52eecc104a00fa5bed023ffa124d GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-p!VDw>7B;>CQYryHA+FCVD%_?$d=L>~&~o6K zo0~$`lKsZUve6Sa7#K(dG<2$|i8!Slu?*q`suwG9jVKAuPb(=;EJ|fa&rCBa$V*o+ z(lgOBS{&!j2UKC|>EaktaVt52fyq&!;j))Q0uPJ9tb?o^PK^w1#!DC-Ed>r_wDBp- k-~mdKI;Vst0NnF7DgXcg literal 0 HcmV?d00001 diff --git a/RGraph/images/barg8.gif b/RGraph/images/barg8.gif new file mode 100644 index 0000000000000000000000000000000000000000..625b9d6cdff3a34f73744fb2cb2f8202acc03873 GIT binary patch literal 175 zcmZ?wbh9u|bYNg(c+9}?tfIng+QSDC5e6*>uDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H z+J7XV!vF*zy$mcV0w*+^_f8Ay`TAsfcw=M2yk`s6X?1N{Q+;UloJ-6L-&Z~SZzspk zA@Z)nKAAt#z+(Qn<`S(|rwbrda T{`hB2U3o)wQ)LUcAcHjkzTZ%2 literal 0 HcmV?d00001 diff --git a/RGraph/images/barg8.png b/RGraph/images/barg8.png new file mode 100644 index 0000000000000000000000000000000000000000..a5704037e7c87eb5bcfd562151780a1ab2efdb6b GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^4nWMt!VDxE-CE}WDU|@95Z7lF6>ifWK8T1gXgP4r z%}pU|$$n#F+31NI3=AX!8ama~M4Zx&SO)O|)r*z5MwA5Sr6z#mEsk^N1FA6fba4!+xK(=eAOnK}1Ixis55-oIAQuDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H m+J7XV!vF*zy$meE0w*{{1T3Nt?KVxwP)y0x%vj~ZU=0B4fFyMQ literal 0 HcmV?d00001 diff --git a/RGraph/images/barh1.png b/RGraph/images/barh1.png new file mode 100644 index 0000000000000000000000000000000000000000..fd4293eaee373d4ed1237cc1de5ac6d3927fffb1 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*!VDyNv=5yCQi=gSA+FCVDuB!f5fMQ0nwuMt z+;40QBsUls0Le}@wNf7ueIQG$#5JNMI6tkVJh3R1Aw4tAs30$0!AQ?U&uDR+J0DPm znx~6nNX4z>goK0#NeMwgmy!|+3qK|$czd5tdhp`Ki=+opTeCzN%=6gHkGh_81?ph% MboFyt=akR{0MLUmfB*mh literal 0 HcmV?d00001 diff --git a/RGraph/images/barh16.gif b/RGraph/images/barh16.gif new file mode 100644 index 0000000000000000000000000000000000000000..cff0ef192456fa7b24a89094893bc69cc67d8e0b GIT binary patch literal 287 zcmV+)0pR{eNk%v~VSoSz0OJ4v=6HBUmf_%7STKaZ)<#AkYNWq2GaXxzurM$fP=JXh zCKN(u|NsC0|NsC0|NsC0EC2ui0Du4n000Ek5XcEsxHv32ZN3{%!R$U(eBXwwsVA-_vn&ZFFjJ8wQAp76*)thlz-bjf{_wl9QE+0h5#fkdd35nV_5p zqXw6bo}a0m2(Pdf3A3~tu(1KOwE(xTvbqVjy}!D`x5T@>2*|U>xWK`@!@0m43fI^c l3)|e*+1DD~+ZEs1;@;ok;^gV)=-KMs?C|dM*zw#E06Qw&kbVFF literal 0 HcmV?d00001 diff --git a/RGraph/images/barh16.png b/RGraph/images/barh16.png new file mode 100644 index 0000000000000000000000000000000000000000..02f5330d6054f7048e6ef510172958bdad07d6ac GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^4M5Ds!VDyT{_M5|QYryHA+FCVD%_?$d=L>~&~o6K zo0~$`lKsZUve6Sa7#K(dG<2$|i8!Slu?*q`suwG9jVKAuPb(=;EJ|fa&rCBa$V*o+ z(lgOBS{&!j2UOwZ>EaktaVt3?A>o0Lh{zPR*=a#RmxRpBwy8}|ODHV-D8$R#3u1bE zpBB>BUk_wHc=6)Jq&b$wW;;!oudfPSy`=p8JzqUuh6{cLig|g8Aa^o&y85}Sb4q9e E01i7x4gdfE literal 0 HcmV?d00001 diff --git a/RGraph/images/barh2.gif b/RGraph/images/barh2.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ff2a4c276329b210dbda84bf281b512f9e153da GIT binary patch literal 114 zcmZ?wbh9u|6kuRuc+9}?tfIng+QSDC5e6*>uDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H z+J7XV!vF*zy$mes0w*{_c39{r?Aq?Ek>`>b<+>`*?RAv9PQFKOwCB2fulLd23kn1o G8LRifWK8T1gXgP4r z%}pU|$$n#F+31NI3=AX!8ama~M4Zx&SO)O|)r*z5MwA5Sr6z#mEsk^N1FEq1ba4!+xRsocknliAL}W@@LQv2pAv3dWX$ggeABA{%d(#rUy-y42 x>#t9H@Z!abNpmcV&6uyR3SGUV{QW&%hR@&lSgq~f-vAoL;OXk;vd$@?2>|sQLXH3c literal 0 HcmV?d00001 diff --git a/RGraph/images/barh32.gif b/RGraph/images/barh32.gif new file mode 100644 index 0000000000000000000000000000000000000000..3214fb1492fcec5ad5badcbda3e9daa383d11b4e GIT binary patch literal 447 zcmV;w0YLsoNk%v~VE_RJ0OJ4v=6HBUmf_%7STKaZ)<#AkYNWq2GaXxzurM$fP=JXh zCKN(u|NsC0|NsC0|NsC0EC2ui00037000F35XcEsxHv32ZN3{D)V_AOtswWmm0=u1!d^C+Vy6^ z*6w;67r)7MGrT=V=hb&?a)ESwgnou+X>J6Kjur)xk{gbX0g{sdm5q>?1(chen4p!S znVSTrk))QMpPHeUo~)d*qp+p6r?IZIsk*DUt+T?ly~V%BsH(39&d(MH($gEy&;irb z0M^dY*$36!-r3>S(s4Ry=vXs73)~5 pWu>02nl>xgux8)3g}Roj*RN#n)`hE9u3o=l0mlV97q8U_06PjX;==#{ literal 0 HcmV?d00001 diff --git a/RGraph/images/barh32.png b/RGraph/images/barh32.png new file mode 100644 index 0000000000000000000000000000000000000000..265baebba03addd3f0b35a6dcaa9b990a007740a GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5*jSi>5yg>D0C9V-A!TD(=<%vb94C$F^Mg@84 z3PyS+dPa-m-1&eiyggkULn>}1CnO|15E2oYB4;qm)6>)Y#*G_Q3o_Wm#KrY5Ubyh0 zagpSWOP4ksIemIHdso_n7cX8+nqyh~&EXzopr03{$zw*UYD literal 0 HcmV?d00001 diff --git a/RGraph/images/barh4.gif b/RGraph/images/barh4.gif new file mode 100644 index 0000000000000000000000000000000000000000..af0b116b632c2a1ac383a542cd1b18d0f35b8325 GIT binary patch literal 144 zcmZ?wbh9u|RA69Zc+9}?tfIng+QSDC5e6*>uDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H z+J7XV!vF*zy$md_0w*{_c39|G7B;>CQYryHA+FCVD%_?$d=L>~&~o6K zo0~$`lKsZUve6Sa7#K(dG<2$|i8!Slu?*q`suwG9jVKAuPb(=;EJ|fa&rCBa$V*o+ z(lgOBS{&!j2UOwV>EaktaVt3?A>o0Lh{%+-%RXLSQHPElyJj$}@#xW`-X{r?Ui<8W>~pdhLfrH!#bdu44$rjF6*2U FngFIGNG|{Y literal 0 HcmV?d00001 diff --git a/RGraph/images/barh8.gif b/RGraph/images/barh8.gif new file mode 100644 index 0000000000000000000000000000000000000000..60462be38f80b9c079998522247535b9e1668df6 GIT binary patch literal 194 zcmZ?wbh9u|bYNg(c+9}?tfIng+QSDC5e6*>uDQ7>WG&fmY%Ci+af5+@L_kBQnwp4H z+J7XV!vF*zy$men0w*{_c39|Gb>C+{(n;mnRTNYdh z(vUJglz5?ew(%Zc*5)zVxYonqWQz3p8cQhhz56S^n&Pna}Wkii-NO)gfb literal 0 HcmV?d00001 diff --git a/RGraph/images/barh8.png b/RGraph/images/barh8.png new file mode 100644 index 0000000000000000000000000000000000000000..bcc8b31ff59d2cb410b135a194e0123b1f232f04 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^4nWMt!VDxE-CE}WDU|@95Z7lF6>ifWK8T1gXgP4r z%}pU|$$n#F+31NI3=AX!8ama~M4Zx&SO)O|)r*z5MwA5Sr6z#mEsk^N1FG=!ba4!+xRsocknliAL}bb_Ph(BZOipR(=*NpBBVuCqxHvm6F1*N- zlbIR$=;_m|J2Ke%`ug-v&NNO3D%cUWHcEAG_4m9O6Nab=3&GzTKi>cv%HZkh=d#Wz Gp$PyjxktzV literal 0 HcmV?d00001 diff --git a/RGraph/images/bari1.gif b/RGraph/images/bari1.gif new file mode 100644 index 0000000000000000000000000000000000000000..a27f61c16c0e2b6aa97e823fb4a776fd1bdd6ccf GIT binary patch literal 68 zcmZ?wbh9u|4-qCH2qmgl7BR OX+a#4$_X554Aua#qZ$GL literal 0 HcmV?d00001 diff --git a/RGraph/images/bari1.png b/RGraph/images/bari1.png new file mode 100644 index 0000000000000000000000000000000000000000..9b6bc7b987036a1d75662fc0cae0dffac75be27f GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^93afX3?$7I7w-U4`~f~8uKSIRA4EhvtEl*J;X1ogQu&X%Q~loCIHUKC}jWu literal 0 HcmV?d00001 diff --git a/RGraph/images/bari16.gif b/RGraph/images/bari16.gif new file mode 100644 index 0000000000000000000000000000000000000000..71ce8c1c25851582d06dfde5a868a40f8c57b4dd GIT binary patch literal 131 zcmZ?wbh9u|Y+&GEIK;rP-`My;M8va-iVqhqbgHTShXEZ1AONXhU=HBeb?2YKDbLk= z4PKnx{XapYFC}x{f(7exUhgZ=IbV`{|HFd!HShl)SWw`hBh~LPr|4vk)zlR$O1##( e8Qxe^cKWE$z6TpBeDr3Yf3c# literal 0 HcmV?d00001 diff --git a/RGraph/images/bari16.png b/RGraph/images/bari16.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff4e4c4c5741ad20c477ade87e739e18eff5ff5 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^4M5Dn!VDx2e}3f)r1%4TLR|M78$XDMcveyI;lhPZ zHMNS#mB)ZmVkNE-CBgY=CFO}lsSN3vX+{Nk=?X@ACVEDTDgFST5ZC?2#t$MQo>f$QxNxCU zO|4>bF!$q5aN rjv5I8O-yXb8V(%?t{!OQ7GYpGUBmWrUFfrOK!psRu6{1-oD!M<9sw(N literal 0 HcmV?d00001 diff --git a/RGraph/images/bari32.gif b/RGraph/images/bari32.gif new file mode 100644 index 0000000000000000000000000000000000000000..3293a995f36f490f2b39b88fd90a642d33d66b57 GIT binary patch literal 172 zcmZ?wbh9u|WMJfAIK;rP-`My;M8va-iVqhqbgHTShXEZ15CE!SV6NoYb?2YKDbLk= zEnc799q*{omy$UzW7WEx*ZT@|&X?$NRjhko^Zx&V1qB{DQvD~E6rDW7JMY4Z60fyU z>u;q5|AP$`Jh`*Zzt~cBHjh8|!;Tui^|#-z>90Hg{`dceMp2fQ*0%PJ&aUpB V-oE|`6DLicGIiSY8LgZQ)&NpnSfu~} literal 0 HcmV?d00001 diff --git a/RGraph/images/bari32.png b/RGraph/images/bari32.png new file mode 100644 index 0000000000000000000000000000000000000000..3d0e340a8fa6faf5cae51ce2573eb27b258ae858 GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5I9Qm0EaktaVt4N yB16IAK!amu17q_?hUP~8Mn->TX1*9U2?hr7PkD`A)5SoJVDNPHb6Mw<&;$TWqAL3U literal 0 HcmV?d00001 diff --git a/RGraph/images/bari4.gif b/RGraph/images/bari4.gif new file mode 100644 index 0000000000000000000000000000000000000000..b688bf574330980eff97040760fc446d6883166c GIT binary patch literal 88 zcmZ?wbh9u|RAAs>IK;rP-`My;M8va-iVqhqbgHTShXEZ1AONXhU{>YWb?2YX3D4Dg kLtdQS{r`?aUrOdYl@;q`pY0P>InSGTzhd3{3MK|?0JtkCM*si- literal 0 HcmV?d00001 diff --git a/RGraph/images/bari4.png b/RGraph/images/bari4.png new file mode 100644 index 0000000000000000000000000000000000000000..e0f3f04692c5d5ca36db3ec6d2f869227789fc0f GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-k!VDy{RzH{nr1%4TLR|M78$XDMcveyI;lhPZ zHMNS#mB)ZmVkNE-CBgY=CFO}lsSN3vX+{Nk=?X@ACVEDT& literal 0 HcmV?d00001 diff --git a/RGraph/images/bari8.gif b/RGraph/images/bari8.gif new file mode 100644 index 0000000000000000000000000000000000000000..5af4a5fcfd4e643c58575736a210d9e5219e44de GIT binary patch literal 103 zcmZ?wbh9u|bYS3MIK;rP-`My;M8va-iVqhqbgHTShXEZ1AONXhU^d~{b?2YKDT!5k zEnc6s7EjRVOUaz~!g5W{>wN_}=ZmuLTfBQ)bKn2Kf&dQ(z_9eM^g`>3i~yig22WQ%mvv4FO#r&IDH8wy literal 0 HcmV?d00001 diff --git a/RGraph/images/barj1.gif b/RGraph/images/barj1.gif new file mode 100644 index 0000000000000000000000000000000000000000..12f3be6a7ee27b1ccafc709044e0b9027ef794b8 GIT binary patch literal 94 zcmZ?wbh9u|{L_BUm*Sv$Pz1YjVKAuPb(=;EJ|fa&rCBa$V*o+(lgOBS{&!j2UH>B>Eakt waVt52fl*ZFVdQ&MBb@08=9>1^@s6 literal 0 HcmV?d00001 diff --git a/RGraph/images/barj16.gif b/RGraph/images/barj16.gif new file mode 100644 index 0000000000000000000000000000000000000000..227798da8121079c8c1c8261e5e660268161997c GIT binary patch literal 253 zcmZ?wbh9u|Y+&GEc+9}C-`H3-dg6nK2!oab&nhb1rak;{;lhmv|2x&xM4Zz8V*nin zAOPuQVA&*aLbG}Aw4k1^Po{@AHgZf@+A(Xj7gqrfe~ItuO}URZ#(g%v&!8c|*XWic zq^V*t|6EgvR;$y>kk`W2SKW59>NCoGn{+hY_{M>}&HNuM?!29L`ekml%>QfhKiKN( zYnmEbTk0|rx?*}F`XaM>C-qO67?tAXG|O&|)jVsTxr^p6S!m;?qq0h2jm$b(y|tUx tZ`mlP!Le)iF3x@X_wCtp;J~5XNA@4vdxG;6$C5L$QH2{w#ehL5p literal 0 HcmV?d00001 diff --git a/RGraph/images/barj16.png b/RGraph/images/barj16.png new file mode 100644 index 0000000000000000000000000000000000000000..b5b57f2279b2a68772f80273a5db239778c93988 GIT binary patch literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^4M5Dn!VDx2e}3f)q~rp8LR|M78_Pydd=L>~&~o5e zMTOh6haWCnxbfhBr<$6GQ`*zVPrd_Hij}xVlmzFem6RtIr81;vrWqCFr7IZendliU zj&tV&sxb3(aSW-rm7Ku9v@;&vc!80{ exUnHdisA8``oDY*cj5ZC?2#bR= zQQKK1H--l W{2!<1T3rNcWAJqKb6Mw<&;$S=+cZwbI4a6l{)g+ikd8B`XTL+1c0kWQgiY8ETicDYV(7_1bR$xHN8O(eMA z?t*+Shr{V~`x`&k$N2?*1b~5lgo1~LfQXBVe2kBdc#xBld6s>cat558oClzxpq`$h zqNJUsp{Sp#2doCJudK4LwY09bxwxvjy}YKr!N8})tHz*|mwJiJjn0wKmD0<0&DPJ@ z(c078)pyz8+v45i-+O>&X-r$}U+!b@XY%Vv?e_2Z@%r=p^-1{v?i1LL;J+qPaP08V zf?*7YH6Z4YxKKkwiw`kI)Hso2#SK3hL2eY;k>tk@BoL@vsWO4fmo8bdgb7pTN}4Zi nw#1o0Cjy>5bprJ{R47lPM~&h{x>PAmrca&Ll$w*O%Lo8FF%r-} literal 0 HcmV?d00001 diff --git a/RGraph/images/barj32.png b/RGraph/images/barj32.png new file mode 100644 index 0000000000000000000000000000000000000000..75cfb8d8afeb07a5f5644cbd4724ce15648b50ee GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5I9Qm0c+9}C-`H3-dg6nK2!oab&nhb1rak;{;lhmv|2x&xM4Zz8V*nin zAOPuQU~v&Rq1n85T2N2x|9c93N*t3^7Ou;BxKHo&p$&=mzb$-k)%V%vX4f~NZ5^za g*-eAmW-y;^DV`X%g0ZD+wQt4#I6ZNmJ_ZJB01+rgBLDyZ literal 0 HcmV?d00001 diff --git a/RGraph/images/barj4.png b/RGraph/images/barj4.png new file mode 100644 index 0000000000000000000000000000000000000000..da91e06367fcd3d6bed8eb6bfd49bdcaf26e16cd GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-k!VDy{RzH{nq~rp8LR|M78_Pydd=L>~&~o5e zMTOh6haWCnxbfhBr<$6GQ`*zVPrd_Hij}xVlmzFem6RtIr81;vrWqCFr7IZendliU zj&tV&sxbC+aSW-rm7Ku97({ literal 0 HcmV?d00001 diff --git a/RGraph/images/barj8.gif b/RGraph/images/barj8.gif new file mode 100644 index 0000000000000000000000000000000000000000..c680ba3873fe4d95392e58e57e1138ffd1048439 GIT binary patch literal 185 zcmZ?wbh9u|bYS3Mc+9}C-`H3-dg6nK2!oab&nhb1rak;{;lhmv|2x&xM4Zz8V*nin zAOPuQV966Wq1n85T2Rl|C)2|l8x!U|Td+>6Ytx$QL#yXpVqW;Z>fwJoIere2cOCZ0 z{E-G0^UpPxXtg@640$bVebsFzyJ};kz~r+&CYRI>@ZQL?@beR9^kB4(^MBMV(9qbx X+0xq5)YR72(b(16)7-}?$Y2csD|J@Z literal 0 HcmV?d00001 diff --git a/RGraph/images/barj8.png b/RGraph/images/barj8.png new file mode 100644 index 0000000000000000000000000000000000000000..17105d4df314dbedcaf7e22c2799abfe21db78c4 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^4nWMo!VDyL`#gCAq~rp8LR|M78_Pydd=L>~&~o5e zMTOh6haWCnxbfhBr<$6GQ`*zVPrd_Hij}xVlmzFem6RtIr81;vrWqCFr7IZendliU zj&tV&sxb9*aSW-rm7Ku9FVdQ&MBb@09Ro=CjbBd literal 0 HcmV?d00001 diff --git a/RGraph/images/bn.business.png b/RGraph/images/bn.business.png new file mode 100644 index 0000000000000000000000000000000000000000..c37f7c4da0f1d60922735ca6e9b33e20fe9746ac GIT binary patch literal 4512 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 literal 0 HcmV?d00001 diff --git a/RGraph/images/border-radius.png b/RGraph/images/border-radius.png new file mode 100644 index 0000000000000000000000000000000000000000..9f16386010470d5021906be82d56c83df085da63 GIT binary patch literal 9437 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 literal 0 HcmV?d00001 diff --git a/RGraph/images/buy.png b/RGraph/images/buy.png new file mode 100644 index 0000000000000000000000000000000000000000..b1c72af76687c97f21fc4e18a68ca01391ac9740 GIT binary patch literal 4365 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 literal 0 HcmV?d00001 diff --git a/RGraph/images/context.png b/RGraph/images/context.png new file mode 100644 index 0000000000000000000000000000000000000000..573658bc1cb5cd982c188563068105253d4abd73 GIT binary patch literal 3569 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 literal 0 HcmV?d00001 diff --git a/RGraph/images/delicious.png b/RGraph/images/delicious.png new file mode 100644 index 0000000000000000000000000000000000000000..1bda07e7a3cfe02b50e4e6ca67d70361b5decf7e GIT binary patch literal 1018 zcmVWdKukZXh%uPh)f-GB7YXATc&NH8nagG9WE5FfcG()T{RZ000McNliru z+6Dv=I3Q1i$Xx&c010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00UA< zL_t(|+ND%Mi(EwzuBz@g*^Sv?K*cy1Ly(Y=^&kYqqnCw%2=3@f4`M)+;2-efZwcP? zBzOuW3I;q#JcvOS_Yk7&27}4CnR##Kz3wW%>Yk19Z1c9~ZNKiXzVEB5X0tEp|BYCG zl-?1_Mr6c9;w#Fm^!aBuu6@1N$Vm|~Gm@y*r+)t7M_V6!vL4qdhOZoAND~n@5r^_W zpP7RxJ^$RR=U%=T^f*2m6F@@1C%X2{uk%H?{PEeRpQU*B?rWz`c~~=H7Isd)*(njt zX0!YEQzIJ$jtqt#k}YkV82|A7tutrNzWpA>>2x|CkEKTO?~uWUe*i<2k}f*40B~@_ zvYH`|*hA`u_{W{%#V{;$9zqyVJ#;w4NR85hAN`$EBo+uzQ|Al7MVBmcJ0Bb(gkY3c z=lBr7988p!ZJtk4#=%(jSay#vH^Y$)&}ke(RZAii3asP<=Uq)%?YopaZgXbfu>})l z&G7liFj%Ur-5%ITPiiPjULtNN3p*Pv&dis6 z3SwDdqLbq+rk>UW0~L@fAwila8CcQd;e?iXFNMKkM-o&skRy|3mGD5q9g2@u8JSEb zUDws3EJekjraD?KpL+e`TbC}qk^5r_$v}asn}p~R+CIPV;!Cp%F-GvHSI*H>}j>UbzvE{5X8`S0)Vw{7eDU%Bwx z_VzXhsn<+tQCgYGy0$i|26%&kNNpmLd-wj_-Q69JPp*38%9T%Jj5oi#+4nui#_K8% zg|zML>|FigDhN03T0XoJeQa%Qoj(0z@xENYw{M^O`KMdMP+Aha;XkBl;t(V@Xb7+b o1Xe-t=-T?`=H~hHzf?Q_0Xg~Zw>6w9K>z>%07*qoM6N<$f>o{5?*IS* literal 0 HcmV?d00001 diff --git a/RGraph/images/download-beta-sml.png b/RGraph/images/download-beta-sml.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf11f7c7b982c04b5e3a8cb64e9863c59ed7892 GIT binary patch literal 1877 zcmV-b2demqP)3$g6#nMT@}@J>DV@%gX$iFpTT3Z5EXE(A7!y>G5(=V!K!XxBE;0U~ia#Y{ zVl*)Zh=|gECPo8>sDnT&22qhv7AtE@i>3QaXY2B2^PG3*wVlokEqaqP^OpP0_uaGH zbFMCtNMMFTN3w$CQIe%3{z3YSt_S*tCr#bx^#xefnLTKe-QfE3l+gf^4=zHc2Wlk7x`~ zBD9)Vh*lMcCD#F6>FYq*n`GiBU~(LxY1@*nnufqwzZrR6MVYhI*TYe;&s6Bz5ugIsuu zu4=me_y9)^HNa^Hmd^)DTsjzJGOIoZkw^@Ez9{s14IIcZ3}bXm(YUB$GU|};EQVCM z2PoP?#End1)nrRdwZLIEJA;4yc?0Gb1B*)l7dgagwGgoWbz}y#73=q1!8{xi| zsYX#_B)_l>hN}00*&FDA%bMwip2q6Upri;_ec?Cu61D@jP~tXU`olkb`kAf96hiV4zlzj0@u;o zTnl58&m}{WfQiJ2nGTJ_VD~lP#%`gMu>|Hgfmb-yZvMOr-MvAIbYVJ~FlD1&1RYOR z2^a*Kdl*bYQ51@A+Mn)x#VPJoF_Q#1oOiJDGoJk@oh{5R(bF7StfV(4fhDnW$t3R6 zhW@T3B>FtyyF)qfEd@smDrV9iD=^$%HrRRy-Cm%yP%z>jvk6H+X~F`$`nZw?V7BH@ zYYBFR;wM*le*q#xWsJ?5SHo0*zgv#0zPBV(+(2)P2H~L_oxY?k^ZGYec>cew*Xrz z*Jf2geNr`+K6eE^U3Cfx);k;~@}XAEjkQdmoXy+X5rxe>F*!~jUJX=Xeti>QTZoD} z584KZVSEhP3Z2PphhJZf%1zDcH4RWg%FuwIOGYUU|t0(nsS5aBI*QgDyTOHf4$ zU~(q47ohy9@6pz0%xqiQ^KXam!@~Mzb*}aelZo4wq*y_s@ea@SiVHRKcnLr!+wCX+sLZcINIAsz&-vJl5r<0gk2{S!o z@L$&w`0>9CMIx} z`l$ATs^?MU06O}U*-k&BN+JnL|NTD!f4zElOQ_&aW(4QK^~IF80B}6S!P(B(lF*LN zcw=~Q&C6)-B`b`Hd>tXI1m`{P-7HL^^(}swuASa1XVw$=$&BE zo4%lk`onqeh;lAEWyZ|VlEp^ry3Tzim?K&;Hx)YBY!d~9tDz)|9>GN|ICa9_ z)&pdzM8=hKS$DWAV5p>K#9hzdr?h0L1eC!%+DuN-Dr>s_{77v|UDUU%ptvb1)RXJ% z0-RUDy@8hc<=V`VpQlw_?y6 zKrNN5>N4`9r65TnLt7pRA>j8>_Yi+Q+QCFGN;VORlKGWL9J+W&jTK8SogGSFBYA_&ptgSZa4^vZr=KK? zqZ#*bbRWFli2k-FnE7ZH3aaM<4lr&TXE|m=?^*>@(G%qBO?(j1qP>A!bTFBEnNs8) z52t(xjmPLel1Pkplk|vd^;wh-sKJTDsrdFk9!}H8%#Y`BEva P00000NkvXXu0mjfObTWi literal 0 HcmV?d00001 diff --git a/RGraph/images/download-beta.png b/RGraph/images/download-beta.png new file mode 100644 index 0000000000000000000000000000000000000000..aab14cdc41f8e4497dc9beb18116c7864e8ca00a GIT binary patch literal 3689 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 Hu0mjf%hdQ) literal 0 HcmV?d00001 diff --git a/RGraph/images/download-stable-sml.png b/RGraph/images/download-stable-sml.png new file mode 100644 index 0000000000000000000000000000000000000000..92df4fedf1047bd7fe4eaaf5536b81d9e7b5da43 GIT binary patch literal 2106 zcmV-A2*vk_P) z)zC;=5`dLQ@MGk4c(uXhb@ zuQZx_XXeg1-($Y-8_DxL%;#}kS7KZ1I8HY|SMj|?lB9^l5AKnW6(z>k0a=!N6-7D0 zx%q7@2;8X=Fr3Y1x1`hQ7@L=2vu)esxHp!*?Iqa6yBOm-FaN~EKO`Bx+y2sA8W7{Q zWo>djZ#$)`vpgH`5B(EIuO7#xTZ2fMHxN)=7z&^%5~6`6SW&wQ_cuI%HH{BJb`0Qri}?pf}u9z(R;p&Z`}JmPRc@;A`)@zzJJSPEy zb9)@4y4v?%IEc-?FCiERVA+Bw7U?QNDkwSEOBOt50?HH#c8ejqGv zei7ek{RujvkK{-=PNz0Q69ocfCmikozkA-i_&$F8;fsidYp^&%NmL2dn&*QDG|&Vs z=xq9akp}v&{|1S4-z=>F8COF{Ux^LNeu|a#oxV9J;A8YFe~mh|m;;;GdX8N^h0TY5 zi)a$DrAcedltur_R%DbXbiOW zkiaHRzwYDuPQ;_eZhJC2iH(Q0A!r1!xT+o!XF~+l+3O^s3y+r-I-iR9K7xc!67kdk zjt}jJ14{_Iom1fg0jlL`p4++|C*Q)gxRr9F{wd;}~;`wA$vQlM1KrRDwXHp7( znJ{Cxbn_@&*hmpmaFfYqEyHN@dzX*mRyK+H-~tZAZxsSmo@$aWxyt6ab_qa*T7Oqf zsFF=n#4t2I2nMHSkD;CBkh?Th#i7_o^w!Fp^psf6OV0CwbGK8zN6VC4G}FnHY#z`W zbFBGTE^vIL#_x+v!IoqM9Zp^p1jOm>61wbAH4PtMKSKh6!pfXNJqDC0-rn#UMzalY zJwNrZw@OtkX}%T&Xe`}{->?6h-_Il=d?D-HMm&85`Ow@Ue4s_VeU|u~8|c$iDY+~+ zVDC3yz>-isUhDofuBECez3r1IZ|54sG7n={_fG#G(U*|mIT+7=j(q%Skwr?Ku#${i z9_>8sNQ;kh)CJ5X%~MWzT4>;icze99n*`D@Z5}Zm zH=zOBrO(pg`bYcl#<`d0MIr|-)ZSY%C-$t;7osuLCi0Ka!VwXOPOw_JvVQ3Us4+qq zP2Ki2APAa*gwO^_495Gh|H7+xBrz>{Z`pa*Q<)K4m}^!E4O}6C6LQ`!_9&i=U#@u^ zBa>r1>y`)u%;mYLX6M`4cpv_JX%9DY%WUr8uNR*s_>nolDZSB*w%UgoFEp?++9R<2 zV@NIRwjC$_+*dcU*r>&S62lM}reD=aFxf1hjEghzlX&OTKNOJ=;0G@~$3%0uEO^e` zL8kcCSW*9|P=A~QyM65ZnsLK0wkocIH#cmFzE^sB;z1Y!a?82$9VVh zUZ2Di`1#R8bDM^$uM4ck*PEVTN;g20Z>9Rj#oX+o^Z>JC&))Oz4nEgIR<$JMVlp}2 zyZxfn5k;w{l@_Jbti49wfIeUi-~Q3?05%@phHEU#TUnOh=a=OkmQ|T$%W~71M1qMX zWmyETM|H&t9`B!_xq3yREN2>?yDTrTcijk0v5$7@$$BPs47`Px&%TW&V+`x+6f^~O zY9fCzVMOD_jCTSH3IAfk8_~%<~J?24>GM)pp=34ePKb+Q~5;{5LL~oA#dbYBsOSscD*9 z*kZi6_!m(U^ZSWR!kfq@ipIFkBXEow+`|9=|I2B~QF0uK1lCfG-IQjPC}gCZ(~3xz k$S1V{_Prvy&i8u$U)^|Uab^{iWB>pF07*qoM6N<$g1%4vGynhq literal 0 HcmV?d00001 diff --git a/RGraph/images/download-stable.png b/RGraph/images/download-stable.png new file mode 100644 index 0000000000000000000000000000000000000000..057b9712b022865482ab156ca9f69811c1c57d29 GIT binary patch literal 4609 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 literal 0 HcmV?d00001 diff --git a/RGraph/images/download.png b/RGraph/images/download.png new file mode 100644 index 0000000000000000000000000000000000000000..722b45917ba9a5d9ce085c6fa2e813b41d4d271c GIT binary patch literal 5426 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 literal 0 HcmV?d00001 diff --git a/RGraph/images/facebook.png b/RGraph/images/facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..40b9d27961280306d20ce5f8516782d73cb9b188 GIT binary patch literal 1053 zcmV+&1mgRNP)WdKxlWgsyiN_B1^GB7bPATcpIGdMamFd!{3FfcH$^Iz-$000McNliru z+6EL72`tm{05t#r010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00VVN zL_t(|+I3V*j~hi0uBv{F$M&q(Ym@NPFOr zkV6te6tU4F780R-YHg3bv!0pmE~;mZkg{fM%iTRyUp>CB8b7`J4ZQv^uzY2K%)~&< z$b>-1Py;&*i~$s*LODVW|My_TL6m=42j`vqh~jbc0Z#xVHoOEvUL!`!##ziA`&x0G zwe?CTNo@j1bLaA6o}W~p^;rnU=(k8jq98a!)qB^@-@bX}`rE@^r$yQv9aj$?Z*AOv zUiu|j;G!F+{umU6cQ2p&;?5@@-dKMlv!_NSz-Tmna34dh^pYwT@tcMMTLZUmUH|yj z!V?pck-C(~(xOG#~X;8Tq^-@owHosTljZw@ob1Dt>7T=w%E0#i zQh*Q{Z$(SsLo=Drowo|LE3Cc(_Y9F-1 z&|68lAy%Y5`48=i4Nl)*tB$iuyX#wP^9UA^5b%p&oq(mbWE?;iTab| z8&d|~04fC`>yl0l8M$FlnwYJ$`~A$=mh)l~U{uCG XC{)y7;_J3%00000NkvXXu0mjfIW6b+ literal 0 HcmV?d00001 diff --git a/RGraph/images/favicon.ico b/RGraph/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..421f02db80fa648d126b8fb5eb5315b6d7679959 GIT binary patch literal 3638 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 d0d>C7{{euWjG}JVx9$zj%((4e#PzGOzEn z9yIS1<7|7ee4Xa=tlXGGD;l`n*L|*;Agx-&7RTJq@QT4(cs zzbc3;a56CWTDwSeU;NB7SKmF^y+)+q+kxXHY5&iwUD#;u^g{jmlCT%$mwH5lAtX z1o;IsI6S+N2IPp9xJHx&=ckpFCl;kLq-UlX738HW80i`787&hG>;|e>>gnPbQgN&G z!bYxU2OhQu_n93x-M@5l=>ogfeubkt-`U;`csWX1a(I{;SbTEUbtDnm{r-UW|WQldw literal 0 HcmV?d00001 diff --git a/RGraph/images/icons_combined.png b/RGraph/images/icons_combined.png new file mode 100644 index 0000000000000000000000000000000000000000..7652beb69b90a08dd805a4fda7f1819f9622668b GIT binary patch literal 5965 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 vw^VZj(5Mxd72^&24@K^XE8_9 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�+d;@(Xknx9vJD?K57*f6x7kz@0+g? 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

o^z*hv|LID-;`lhDGF0lK>%lLkX z052~osh^< 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 Eg400ED*ylh literal 0 HcmV?d00001 diff --git a/RGraph/images/merry-christmas-snowman.png b/RGraph/images/merry-christmas-snowman.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4de646fbaf277008340e4e9f88a8ec4012f55e GIT binary patch literal 18770 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 literal 0 HcmV?d00001 diff --git a/RGraph/images/png.icon.png b/RGraph/images/png.icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f04b7a37fc2666a2ae74e6632b67ca1e6522106c GIT binary patch literal 1008 zcmVWdKxlWgsy*AWvg-ATls9Fd#BAIx{gkG&3MAFfcGMiaMz~00007bV*G` z2igh~6(9+L*odS6000SaNLh0L01FZT01FZU(%pXi00004XF*Lt006O%3;baP0009= zNklwonSCM23Y0C3cF1X=6whN)$yD znHGixy@$-QkRdDxWqhA|fA9V8|8ZHq-{N%6?|07meZRl+{T=Q5`}@Pg!_m>v+uNJw zuX%cUdV71zT%ulHUIv3f^RE#)K0Xcz2(Y)eSDg3v_m`KKcXxNp4JOm;^~M01s;jH5 zt*w8kj5JkMRkydd61BCpO-)UerP>JD*w`@2a&vRDsHjL1%RTPy?&<02LqkKPH)hJo z$swgqr?a!O^YQU zG&+TKQc}|D>gq3(0gc08IXpa+D9hH?*0HfMjU}Uum6eqg&DGVlsi|pgZEbIFj}dU- zetv#tsrdj+?Be1AP{0`+9F!;pWa;bcyR)9b2?+_@H8nL=Qc?mlCnqOmGdFg2cD}y8`uqE5XJ@PL0bEK- z%HrZ8qR?5)L>a*j#?a7E@i;g*baZrtg@w(}&o?$Ua<8(P`R?v6lbDzoc^j!G0{LmO zgM)*orzbNfbh*5|ytTD;a&pqs(}NbGqob3PlY4u6WkX|xGTx^4`Fe@)FH)oogn?n@5o-|f)aByE=pR=>Gnk$Lx>+5T3YRbyW!o$Or z62YEJmzI_gr*scBpapSWUtd2yKB5S7^*G?@=olX#pOux>+}ymdun-Xu@u8~hDJ?C{ z%gf^li;IhmU1B06Y`E_1>`Zpn)zwj+?d@&eNjzpwiHV6kY)D85*J-{sy0WFEWq*Gk z1~iH|BO@cHr>B8GFfc&N5qGED#l18Mq zPKmBZ#Qm@ii%oaUuU$) z;Hzk1Vd2Kc#>B*ggiz-2@bKv9DC5=Dl}N+G!y_Xj1EKL5YJr0ndGJ{&HC5X;(eDp_ eRFg>lKiF?6j1rY;%<$9z0000WdKuQbRaP~AWC&^ATls9Fd#8DIx#UiG&UeDFfcGMh$CB200007bV*G` z2igV`7ZNvXz4#FT000SaNLh0L01EH`01EH{Laa2H00004XF*Lt006O%3;baP0005P zNklyU)bq>JKs zMZGaWktfax*VRk3_)9x3shVcZ#%!ph@tSWi#tWVTUpftu9oizG(D%u3E)L>pJdZs` zQIysDW>@kXpY}rb8xeEoWe&Q7QZQ%_7Iott>ip0P0jHG98Id$}lfZRpUnHTXq}%Nl zG=H1J7TD9k1<>$e)r9~A9n3~i6hWzMI^~=$*-1<9W%^$sec+ zIaD8g)2z)pL3v(dS^mT&r{SL#QZLUBP?l92wr%hCMIoR8ANc|}4Zp0T%%Um@#278G zqU^TOt*Tj;1?{Ws47vlclDKo%ePHW`UkNVe#m(^x61+i?L%XUxW2~pwLm&+N38hhz zbxrpD0^!z?6U?+85m_e5avb_dpS0aUeEHP+FZ1G8`2cTH|9IIpn>zpi002ovPDHLk FV1nrg44(i1 literal 0 HcmV?d00001 diff --git a/RGraph/images/rss.png b/RGraph/images/rss.png new file mode 100644 index 0000000000000000000000000000000000000000..ef47bcb9555ae6151083ef769b6a612c4a74f3df GIT binary patch literal 657 zcmV;C0&e|@P)WdKukZXh)vL}gRyz5W0mZL>2f|kLc;zW)HjiXP@Q?l7n*~!5 z%IsW?kb2en=kjX2;wS(uUQulYaUcIX?(^>pn5(jd#d+G_-I@Ox^qH)x8ScmZxpNUL z0pw;d{#%7x9DfL-rKW!{K?vj7;s1*AATEywBlppNx6Z@Vo&R?v9UL||#Bl&7cnG7Q z|6o`ChjJNIq8MN9`v+uyy34>|&1?{ct{#^-214^IS_lKNER)R@h@<{r(Ej}tBC+Dn z*8eQtb*!GX3^1ubPw|Ko2w_xPLA=NR4!ZySWXSBel#$zj;U7HoR{Yt#0-7{5cCr}k zVEzbHhDRKC2!nDC3W5us`+I6BgK7se_kRpE|Nmc|{~wE9oZ|5Oi7Q^A(F$UJX#Rcr z5tGv#Mj)HFhQ%xbp-kGDk>Sz554gn%#VcAG{*RJ|A13~hzQqzW_s^Qi|9Drh1=YjU z9sRQ=5v1h(X6)jm#q0aV->XoaaYXeOgtcAuFBWso{>3g%lC3lbuo7`V%HaX3bLdyU r!fbtf=!duWdK)YWFRp&AX8;AV7bC+hsTH zALyb$itf8A`q~w#n+Aw$B~F?+ilo@GX(|#UiIgak;_Kc!=k(0IR9ploa5Xx-k8i&7 z`py6maTxZh+wHZtgNN(tv-()wZ#Vz?dv*VPJ?sGy0s|_!5E;eLkA6A>B1AzK3!TjhL#z8i+Mii2zV>GRspn0< zx-E$M!7XZc$r7NvqfpD+tYkf7=XPRuFJh-+p3Zj97!7&J(|%*E`8Sow6-?)o_k^P$ zvTTQ71i8T!!{@j2=G6MaE3S{9}YdQh9_`!-H~&fZZYsa`{}9<)6*7ksFoIsw0K3e%I7X>ZM2g9Mmoc{UCt5DmLB9fvp z#fii-KafOWt_+@0;ZX9sILyt-b<96_r$Z+WY3qSUwM_JeKBh;TeI3Y>7|y1e%Yke6lOPL#E{T=4W|03@RJ8 zKeRTYDVia*SrX7!R`6g8BlmT#s4qSTsT`n*^6tTSNndylXCJ3Vg*$aRsL;uQo_`WD zWk`(S#6nQr^mi-PMiFqJ8p^X0(-nQ_+;?JOhjd(}-8#XWn;3llQLtZg5r{xRK!5RyV;Y01Sal>6QYOPws(mJ< z1LXzGO-U%QIM2OSxc#whoiJnK>UY6QD3h=!jsE5*cIZrHdXrA~E;aJe94>#6aM**0bMLl_*$?1|P zhZF75REV{wH0yo;XXfgQ`rI}1)T`dN-hf1odxPNLf2RFyAq$C=xwOLL6LuI5wmzn= zhzsa^NpPi?C}JATn#ldpz(^OQwIf}VMMH5xc^PpkJgx`ZAGoFwh{^M!UJ~=5eqh^8 zcF|4h(lmh)n)Jy1GY#i~2xwJ4W+xT_9aiYH;~Hid1Uq+m&~uxO=cTDEsj%I#r!D8L z)|f3wFFBeldZ&!*R;Q+J`f&R&_}5!13|;jcR{X!eC5g6yBI)nFhyK0)sPQ8AyP+Sr z>gjX__cny6Y!n_Jaiqh}Z>^2h85vG8x!jx~vR|yzUw*B;EOk!oaU<$$5bFKSj|R0G zfhTo7JlvN%wq9@i;dd&L7Ob$H|#mv*+_Gg#-gS05)XetCw8KshK;4X@k zB5v(iH#w#s-5hzX9AaudZ7wh8S6(ow#U(ib$h?;6Dzi`~7e}v=n=rsyLJ!gGaHBMy z)ozAKD$c4>;^@52r||M}@%1+a5WYJ0bnm<;YOlktj6$hMHzT8yj$75p;K+#njqXQB kAcV1ToL&^C<73Z%0fYF_oXtvAZ=jyfK@qEiosrwQ8;wpWjCM#22WQ%mvv4FO#ouv761SM literal 0 HcmV?d00001 diff --git a/RGraph/images/sq2.png b/RGraph/images/sq2.png new file mode 100644 index 0000000000000000000000000000000000000000..763f5ef6e4efe0338d03fbe7011a2bbd3e92f13f GIT binary patch literal 93 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V6Od#Ihzopr0B`aafdBvi literal 0 HcmV?d00001 diff --git a/RGraph/images/sq4.png b/RGraph/images/sq4.png new file mode 100644 index 0000000000000000000000000000000000000000..7585cc8061117a1649aee863b14aa5fdc508f8e8 GIT binary patch literal 94 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V6Od#Ih literal 0 HcmV?d00001 diff --git a/RGraph/images/sq8.png b/RGraph/images/sq8.png new file mode 100644 index 0000000000000000000000000000000000000000..341f8e624aee728c99fe61f0f81a3a9d28e363bc GIT binary patch literal 94 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V6Od#Ihzopr0AGX_j{pDw literal 0 HcmV?d00001 diff --git a/RGraph/images/sqg.png b/RGraph/images/sqg.png new file mode 100644 index 0000000000000000000000000000000000000000..edbaf8b2d1de1874868ace88d657e9c630ba7044 GIT binary patch literal 94 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V6Od#IhOUm literal 0 HcmV?d00001 diff --git a/RGraph/images/structure.png b/RGraph/images/structure.png new file mode 100644 index 0000000000000000000000000000000000000000..855d5181e96113f95875e532b5ff58b86004e180 GIT binary patch literal 4399 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 Is5-^|56|vXSO5S3 literal 0 HcmV?d00001 diff --git a/RGraph/images/stumble.png b/RGraph/images/stumble.png new file mode 100644 index 0000000000000000000000000000000000000000..80c153e832a7bcd0419db3d9a6b7750a84f72d52 GIT binary patch literal 1275 zcmVWdKukZXh%uPh)f-GB7YXATc&NH8wgiI3O)BFfcIQIZq@2000McNliru z+6Dv>0SN+dx4ZxV010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00dJ> zL_t(|+8vbJZxuxx$A5F%**$x1JuNLgEu1vA3KUIjOca!hff%9*kq0k{iO>E4zWCz* zV&a3=2Q`SqM`($LixO^ap)GAGP6aYSgTceEHGW{qYqft((v8{BvuT*Kud} zg#sCIUSd%|nbDdMqO2>lG7h|6iHrh5nzrg=2g8Zc`a$|~YiIVs)pEV`bYr!bZHIBh zA@FBlggE9xDQB$_rYlm7{8oNJ5KZf0qcPf;yR$$yJMHz2l@@JYt{^<;h5xi;Ei%Xy@fp#-xbGJ5QdQ?;OeSivhe;3u&B@vhZAt)zo3M z+97rDlsg3k5fYC-^XFX@gQ1a8I zA4Z2p##`ef`&tJE#$vpGs2rR<*;@IzlM!sdxmPT~AXOOUT$UC>NKAJ6xYEbBF`jBH(e6J$*nFbrL&Ae2#_kKccC(s-!AB4j7>Vav>Dw zA)?IZ24N_qH5z(_k$wt%>d>)Uw{Lgz?$Op%Z>R7$sIToceB`|o$Ab#RC5kbQX(NDo z0dW5j>}GyjHb1}o-{SB)*bb36^A(r zV$5sC5Xyt1D8SgfyNwNAU4OB-yo5|)i$WABC1PyiAnmJF`{R&!l!^%rG(^~VjxQ0A zd}lAgN~B<<%2L?#&vz6b1fM+{aN4L->xty2M{3{BT=PAg{D=K#n5fg zJTggyvWUuv+K9LSWUb69Aw75IL!_Pa!M=3)%Jgr4?xx-@j0jj?55j)z>6;?Op#3$; zr4JlvC5g4=h<*OWg$tj4LJ9mr;Iq@mr^1jfJzk4htdUb#`o2SaHO?{X^Jcu>_l3O> lSx2-!Fxq^3>S)A%{T~pcfG(3kCn5j<002ovPDHLkV1fw6SH%DT literal 0 HcmV?d00001 diff --git a/RGraph/images/twitter.png b/RGraph/images/twitter.png new file mode 100644 index 0000000000000000000000000000000000000000..4bcc4f21734d7ff9f3b95a55db51bee687e884e3 GIT binary patch literal 1163 zcmV;61a$j}P)WdKukZXh%uPh)f-GB7YXATc;PGdMajHy|xAFfcHxWX^5?000McNliru z+6Dv=IU10YAg%xa010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00ZMm zL_t(|+C5ZFZyZGs?dtB`S?{jbYa82Gjs-!9ut}UlkRT{Ra72O|H;()v{zq;cKpa6L zAgsuMMB+ps$FbwJiP!rv8}EE{cQvoZHZwcDU)8T)y?Rv?}G!(3Ed zYZe;~HY%M?(~P|q8dv9E5-~9{>D{rlP-o+m-kej3(VwcBf}uF|jc{`u)(kY!36A*39k4k1|Q zy>}%vB*~DNxm0x@gHzPY;*)Wqs*32y%kAXO+MAE|4^A_u6$>4rzyjfXo@)RK4;DdK zIj<1)dyjXH7&>SMgkEi&e|5LD+L=8bA2AtGL~-yQT7>f~v&JG4RRs;4S)f1>uCTBf z4!ZCJBnwr^U%P^|C=i%!z$-9NO881^AR}#$Rk4ri_A=dC5MKyE6|Z$V?HWCLH7E)Y z%_DM0p`xHf=cFQ9lVkQQwXce!-fq$-E2b)=7%yY~@z33-r$Z1U*(+NtazyrCB=rCa z-f?hEOEI8F^xmlKGo35E^i(7<>&tJ%7<_dJeTP(p1$c;`(ICo)SHscf^~J?z*2`xe zpP6rdown7&0h}6;W@;C zUEuC;bD_~q^k3r<5{NPlKtn8J;R8Uy<{~>ph~cNF&jxAw@tv(NH)dERv1&}18u2gt z{Xh1ednhRYxHUS@%7R<~41KGzv*DeC!`;K)+*~^`HEAyj9=v#j)q>0vF&o@hv(|X0+x5EfzBSXR7$|W# zaHMm=R!b;KhIot;g5L@Xs3Zj9cC*RT=~8FTesF7J|GV#flFWAII7s!XcD7f8&cw@s zCv8}L(2|9w{N%Vx@!tJ=$mPNA?$*QY?UyGfK^mkA7o{)f-2Y?dYILfq6!xw4^^ZP$ d|J@rq{{dae-}9L7`9J^w002ovPDHLkV1n%b7Bc_< literal 0 HcmV?d00001 diff --git a/RGraph/images/unicef.png b/RGraph/images/unicef.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f7fcd60efdb2f442fd4affe6bb54b7ce397cd9 GIT binary patch literal 8505 zcmV-9A;#W`P)WdKuQbRaS{AX8;o#1q3r9qOQ6EhG#}GpleoKabeY!An&=TE9!f@ zBFefbU|3fLL{V1}1p|@?hA=tDp3u|PmG@LN-BaDuJw1Um@8f>`@eS40Rew15-gEx{ zRuP(}Sx(z&^B8@y8}R?uM9os*R2yY2k|OeKL^wtC{h9^5`lVet9`q*V*MLifE9uEiFp3qKU?c;K(2=aY+naC8}e>$r}@xfn1-4rXK*J zLewtU!#mZEc78s>Ha46*+3gB!&z6ac%0;!)@mQLum=GS;^H%?>QGTUb8XrLxx->S{0ONW-(ue`Gj|gwo%74k`7G`iPVJUH`xcX;y`Jq%MjU)b$##W1}UDiqk z6*rw6O>G)s3#Tm83;3PwYLD+{SU&&+jP;Fz#3`9Ckk{syihc)^S%h>ljU^K3u3G(z zL#+^fP~I$S)AsWt!^m~Rt!IRj2s~HC(tE~+*+@&Vpdo|2T_-oT&l$u#QVN%Rvs!6ei~!*9&sqz%)`QMiA)MhJW?d^swKxpOpDiPBN*lP zqil%`arY77-ehJ%1bN>P;r#~rh6H-eQ0u6j&Mc02F^d}(MqYcsMOfI&Vmrv@2D|)H zmGo(zwToW#13*{_;=*W(H^DvXl%$mVOt3|QSd(kb^+153h^QbUphD1Q9N;gAqM}Wm zdZ1946iLFN->8+m2cNHyewWO=n9U^`)HI$Zl8rxZO{9NcA|7$6zdF==l9_F-%EU+# zL-gKI?ye)k5F3XO<-Wp5Ou#DY3uuSj<=bkSPDbt*t(UD z=a&fp(wsDXhCq)n*>BcLQ8Wmn#f%16ldLVN5P<=E47Ivm27fFTRNMp{t5Q^}L=q|{ zi6K_i$@d%<)(*2KFo;Z+I}Qt*N9m(iE@-7sp%gaqFX#i_}sepX3AcIA_K5kTsTxy#VAoZRG#Bnib z`H(yZ40LUSOcR#JQrSs+`GZb%QZxmHc}+YGzi&~3USNY=0d*K`B`%7lhS*3<;pMUP zA^s=;>m>~__2Wi)WsViV`cnq;PQ7f=fxO0I8`e;Y?njG$hwl0Z4Ltpw=BnGw__oz^!`4j@3r zzi(9#GvNneB$3Jz2%AH?mvloK256^4t&-F_Q3JzIVu|tLWVW>j7Y9Mx)vm(T5LA)W zK?p{Llc{V7CTsql=p>c>tWwma(*RnRqfi-`tt(?`W4Vb8N1GX)IJX7~61NV}XAO#G zd5x69k~vnQS+=}bDeg6~+B_RMKb-~N#NSuPQS0scEkH8H?{@yHNe1TZvR2~iUW9nG zSa1gu#Jw2WvUaF7mhP%^*A=)xSl|& zb;|$-IRBwlxo98n*I;C$%`AiIjjU)hi zXo~p**$*0Jz!A4Wm_bKp9}%uCaJ2`?7gxs}oyJ**h0F4J2nV@KkDXg0V)o-10vT{j zIEnClT>|ai2^wxA8zlc9pCAr_-YzT`OAXXxo*qhJE{LK4TXbf3yNba3uEB)e2H?L^ zB|VDP8#79u>sWGxSF(HOsb--2a335Q{ zGwCciIpQ{&jfvUXrY@-vLHFDzfX~l7_BA@4zuj7L%# zx*H3Um~Sv=?|+dLmgjUZ48&Jxv#&?m#_#3}JsfILxp?yc+B;j%l!-;2ufj;nx;)zy z6Zb|8!^~Y0W4q~~3o6ll5HtnU0j>u5H^IXU?6SoRh-iuc9}3oHgvNL3r3X`(iIMbc zMqv9dgBFyFT1BU6o|n$volNg?sP2}y4nWWGQkK^;*~)G_+~UsJY!m{#ZYc- zJ?ieoF4eps_*^D8B}k>o8#$a=XuRBsue6)CSP<{Km@mW>q>Rt)3RpH+NUn_p^)3^% zfTavT2&ChTc-o5wwExv=(b8=Lp#jT|r-?6`aYr3_=`0b)5D0bVF?ZXE0|W+hNhaIH z2{#S!30EcE@Bm1aO)VXXe|8cbOkMg3?r%K5T2(I#p8J5<-=7lHt)XD=PU`sf=QgGL zKHB+G(6JB#YwKlXs4HTq$4kT#K^+vR^*?pu;4f54J-RbacB&c>@MMV~t9tZ89D1Qr z#Ldo&I(dK?9cnRPq;K_zU9p5TFnllf!jG?r4VnSL4ev@~E{~<)l$XU&UYTIl2>5x| ziw9Fo5f*H0yQ7zYfK89nFZItx8FUH(3^}V^f$$D6K8PHCY2^Hj}Cv#qivgVn38 zHnqslX0U)V8b2b8ygc^gEliCFRV@_X9m?Qq+f3e*WRwyGI}_}EMUH&NLHLZy7+77VGZ{g;pgr zuZ%b9E^#6#NEk)@>QL9^(O^;dYEBvx*-7P{I6x%yuAZ<PFDCV1rB=YoO*MHQnR+0j)*0fLz~s*oCZ7XWE<>#j-4iIsn0zgkk7pbw)G(+({2V9l! zjJ{qYy{sO6HY{w+0qs=$u{Ai6md zYL7!e&+glIxSbJB!VA^zO*3NCSrNT|6e5-;=B2TVE5yt9yB%^$6@qqkJbiyrJAwm<$nA+Vumv>W zoLPakjY0qdUfuOT1Ic}Jv)&uyyTvT@ywcLIXb1s(dfbT%nRC!R6)Ry`H{AB; zN}cHawMN=7+%`LjffIvI%t>W_Xwz47SG&G9j~6eM-Er-8LnkDHO= zt1|n-33_2*_^XF8?a(R#M;CvSd1O40*}xrcInWJ4o+P+wza3?}`Jn6BG7)jhee%wBbyc18ag$OU9J%Ph zbp@^`(ikL*rCDqQMJy~AcNwzf(rD`bA_1Y|kyPd{*<7$I1OSBDZ$uS3*fJ=1mv*)* zC)TfgY+MAn!G84b7De0Du3i`&G_OBaEO;MZfe&38V@qWTK+3zEu&q_Gq;|EV_RmIn zY30!sYsAi%vf1-`xJK03VrXJ+8oS=EZ+JeG!aiRq0+&c1TUwQsL%3(k#1T84F%*H` z`N`2>)+B2y>*UXeTlYBCNqhNQ2I$pwm{YKduUo`FrnAU6$gaT(*8?c`9Fv@f%lz6U z7yqQ`WKjs+F7;iIe!o!;cBWn+WU4T5Pb3CqvI#&4-F02&owfBcNSyogvqR~H(Cuuv z;S(i7i>z7XT0#BXfPqs`{X#yxpOG))e&H6JQ9rd8XCLck1L|x*Ve4 zZc1%e#T~`LZKe$r ze;_;4Q}fbl)Zl=nC;1NCk8R3=@{XCF6h%$+D8_T6^sS9AJTtw#MjBxwAMTVmklJrM z$-5Hs*;kTfI$ z2#pF+1HK_ol8puXkzu6wp&$V3xeC3rkQHwa;a1l}WD4%chciFPvvvKHX#hZAEFVl} zHk)=4A1o4fx2uq_SysL18$|V^M&+QNU6(*luctpTr31)fe4;1< z(%&m90EG{SSs{TA@s^Wl|H$Po%U8X7kL7~)`w~51f(!X25DdoKL#(5HUnKy}v?iCk z_MpqVYqhai!N**xWH!vls@$L~z1MbIB7JQ<^R~uvv3IOn(97Q3sz#ov~qG-M3Ac5AOh0N_ci@U!kzWw4<$B{Lz3ReKeI_;9DE#HFK1-_ezR~Q^e)5luOk< zZIYH&24L%O@B5P>DP<7-Gr~z@XIy_p#6G8Lj_9yISL*+!vjig9W2tQSxBY?w0*wQa zSy3y!ULzq6d;5n$868f649`wt+_ymr1eGI=GWK&!GK?i5s2B_lVXS6e5K5sz8hI15 zsxKsWoR8ZfO}dv50zQ-o1-~MPLrYfIOW(98M_ih>NEKNYV|RT#jhNX*`UI=kJ|^tL z1{o0>>J(|weF4JrNdFZ^{d-REp`8{-c?&Aw%Dt8#Q)6^pu&qt`u}!TM)kaCL;s@xF z1s+dhatxh(;a>iG;|(=W4`de_3l-pb5GIhUf~r62f*^rjgH*y}d-Q6GZoNU~h)b;! zHFy9r5T-3H)FUe=-KzA*VDx?wMnOPK4=XLu(^^S&J2`1wA-d~&*~-z;P{BFNG`o@Z$EgY&}sA9Lq)=C)zbSztzJrt1Uhve zUoL7tjt^`MHs8ezNGcR3EJ?c#iXPrJHxw5{(;Bd4GK?jHtP zy|qoHh0J{=)Wn~$B25U0(@`u+PM8YHbz)*qFG_BkbA zJ=M?bI7W!Co0T(nJI~(3@9ph76T3D+wcJ}Mg{O<~J^iJoiK^|21+TwC?%r58OYC@cL%j7Tf z>r@Yi+Wpzjs}K&oemJbxb{qjQE}VKal|dNyKA{GmUR)urZ<625{ZD(>0vy#!f-#KUZ=I-9zWNA}poavd6uy@bnKmYm9 z|NrOwj~l6Z7g>JO%kEx^tOv{GCn`tYvXD>V6gYH_<&Y?R?b6VBo6JhtS6NJXVA#~d z$!h=e9IfvoK}?H@8LnFW4%x)a&?AyOh`VuDk5D3__o>K2!1aOqzbIJic2rc%TXH@y-tBnY9bu+bL^6PB6F_H zRZ!<3jiMn{5ix5(BJb*$N|7*L7BZ4$K{!CBghgTK8~=TM4tI;15u?UTuPFpGRh=Xz z1MFfRz*KsYvtYi5*n9!W)iKd~Rd3Qbbm~bOqoOUqt5t@D${a?SECg|Fy&BiZEyY1^ zFeH`}8X|c9t~zCUOgz}{Twkx2hlMRwVQ6-)gV!|$(&ouw9<}?a|A502yiaDt|vk$5TQsDKe%GXp`D%ad&B#ZGJ0 zNqxas>E2TL_Tw54Rs$w(ETlQe{F&6UV7%KR37ceCnH^?&Cye44-O)OlMn2Y{PKt;d zDnh9LTnBYIgi_rwBZ?IQ5>W@FVzT}5$fcnUll-jR1XX>ZL>?y#Ji!(|-q4^zI|CW5 zE(;aQG`!@Qv*xE8wYTb&dD(2FpDC8HC;rr9oi+$G%DSis0S%!GAeS_%XdV^=U#SSq ziisz6=ke3#)^;1cjsq^_`+Dn}lmVYgai`~+0 z?n=>-`6M^B$0(6WI7V@v(OOp7U7S1{0=^X&~{WO znb$of^89)V@$b5VcSbmNK^a;ic zqwnSzFSGj|K_9QbhovlB)B{kV(^O&6Vw1y?y6PX(E7zi!Fly677_#9T}rdk zfC2y{*wSk?%7QTx=9P7=p!|Xw0Oy`Mg{Kc#GA>y5c0U&Hr7r8v39`GQw-yIqoRSQZ z1Xug$VHKqR_g7FxhZDmTW^PlxevC9ND&BcQck2`dsrB-_1<@vKuU6(V z$$@{s8=4meg}rqOPqnactaN2WyroI|_G#m;5*cXZOM^}R5X;@eJ6tkO`c$I^PP47k z%1F!co-{JR^mt{+6=k(CaW32Rr*n8(Vl#2B>dhMe0*hMQP$7GjhA*;wJbQcXAx>xf zEj!){zwEGB+n_hm0wg+Lyl2_BLMreCBI)CW)K@^rfraN8U=W>dG6_`1e8Ju>@f;Gc zRNwNbjn|Hr_}X;k=Oe>C#aEWdUJLsjC30Q5vcmg<$e2G`LPd_N-?FyL#s|HLHVc%^xj(uZ?!&0sSxW$d@35Y&S0gO$nHGCv&maD9}8(*WF(dwl~Ta z0upopg3I3*Ct(rp*yZY8zZYvcjR;AM@2ri~MJ2a+ zNVw>$OdMxIf&c}@A6m#g9MK{48Y4w^L&pZYgB!!qxIg?geIXXc(<}pW z{$qljaF?OCd`68u?8)RXO$d}n7M^6`oTfhAPyxMlX_NMw|BOs{5{BT@KjPDs_UDnn zif65Z(D9-U%lFfB=2K_PJQG=Flq>|n)12^uc{Mm%aH2eSyw(0ilxE7soWpf!zhmij)cnY)a-Ih1J{n1tfC;L1V#$gMH z;RZH+oPfN5{kp?Cl1JZh+K`AGdhr%C3Fl6X=kdug~VDhYydIwqCA$DX!D3_pA;`8`BsgWokZSg928!AgRI9I_^<8z^-`LRmk5z zWAaqw_m;^w7X`uh{ybG#b4tf#UQR{p;^F%8(6R|b>AZz(EU)s6CvQ%T+!r_g&|@ub zOvd*?OrW19E5qCy9l+pJ)+-LLqhLv1uZcWx%J}1XYiU!mH*Ctylf(R03K~f<uS5{x_J zD1uekc4cIBT;J9;IA4H`jp1H701S-ok4r{}v`^njE2j$`C}?MbW*#XI3p}{xpBLz@ zz_gf%0s3t6?>+~L`kVsEi;gDM0nvO&5iw8jy#0N)#IAC^Iw^SCfqn=421jbwGytCW zT!*>8-vR5yh@TrjR0ISs4Fe9qt4TLi@B+qwRm9e*Rz%R8Hyb0%FKJ_xSp`y_23K%0 zkS|0gHpWs<1Rq4|fj$RxHai^&_5JiMqqQ-ShnOB6pg{~%6p_Et1gGCq8o4}@d1A*X z$5n#fZY-oX8E68j0Ty|MA_DDz8Due&B?|HvaIaknJ7LphUQ{S~lN10Fz=P*kr5{-V nIpD8S#EhVd4}2;=C~4)t_59HIcoC4V00000NkvXXu0mjfp&T0D literal 0 HcmV?d00001 diff --git a/RGraph/index.html b/RGraph/index.html new file mode 100644 index 0000000..b7767e2 --- /dev/null +++ b/RGraph/index.html @@ -0,0 +1,872 @@ + + + + + + + + + + RGraph: HTML5 canvas graph library based on the HTML5 canvas tag + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + +
+ + +
+
+
+ RGraph: HTML5 canvas graphing library +
+ +
+

RGraph: HTML5 canvas graph library based on the HTML5 canvas tag

+ Interactive javascript/HTML5 canvas graphs using the HTML5 canvas tag for all platforms + +
+ + + + + + + +
+ + + Bookmark and share: + + + +
+ + Bookmark with delicious + + + + tweet this site + + + + +
+ + +
+ +   +
+
+ +
+ +
+
+
Note: Starting from preview 3, Internet Explorer 9 has canvas support.
+
+
+ + + + + + +
+ +
+ + +
+ [Please wait for the onload event to fire...] + + + +
+ An example of the line chart. This chart has zoom functionality enabled in area mode. Simply draw a rectangle around + the area you wish to zoom in on. Once the zoom appears you can move it around with the left mouse button, move the + canvas around within the zoom using the right mouse button and double click the zoom to expand it full size.
+ More Line charts... +
+ + +
+ + + [Please wait for the onload event to fire...] + + + +
+ The bar chart has tooltips, along with a context menu. The context menu has options to zoom the canvas (in full + canvas mode) and shows an example of the ModalDialog which is part of RGraph. The context menu shows one + level of submenus. It also shows how you can add an option to get a PNG version of the graph.
+ More Bar charts... +
+ +
+ + + [Please wait for the onload event to fire...] + + + +
+ The Rose chart is a less well known chart but can be very effective in showing information in some circumstances. This + example shows tooltips and adjusting.
+ More Rose charts... +
+
+
+ + + + + +
+ +

Introduction to RGraph

+ +

+ RGraph is a HTML5 canvas graph library. It uses features that became available in HTML5 (specifically, the CANVAS tag) + to produce a wide variety of graph types: bar chart, bi-polar chart (also known as an age frequency chart), donut chart, + funnel chart, gantt chart, horizontal bar chart, LED display, line graph, meter, odometer, pie chart, progress bar, rose chart, + scatter graph and traditional radar chart. RGraph is covered by the RGraph License. +

+ + Ideal for Chrome extensions! + +

+ Being Javascript, RGraph is ideal for use in Chrome extensions and Web Apps. You can download a sample + extension here. +

+ +

+ Full documentation » +

+ +
+ +

Contents

+ + + +

Features

+ + + +

Implementation information

+ + + +

Other

+ + +
+ +
+ + + +
 
 
+

Download

+ + + + + + + + [Only available on http://www.rgraph.net] + + + + + + + +

License

+ +
+ +
+
+ + + + + + + +
+
+
+ +

+ RGraph is covered by the RGraph license. A summary is that for commercial/business use + there is a small one-time licensing fee to pay. For non-commercial purposes it's freely usable. + + There are some + licensing FAQs that should help to answer any + questions you might have. If you need one, you can get an invoice here. +

+ +

+ If you have any questions about RGraph licensing, you can send your question to: licensing@rgraph.net. + If your question is of a support nature though, please use the support forum. +

+ + + +

+ +

+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RGraph/scripts/minify b/RGraph/scripts/minify new file mode 100644 index 0000000..3524429 --- /dev/null +++ b/RGraph/scripts/minify @@ -0,0 +1,104 @@ +#!/usr/bin/php -q + \ No newline at end of file diff --git a/alert_status.php b/alert_status.php new file mode 100644 index 0000000..0b3edee --- /dev/null +++ b/alert_status.php @@ -0,0 +1,11 @@ +=1) { + echo "Russ- You're being summoned!
"; +} +if (summon_status("beth")>=1) { + echo "Beth- You're being summoned!
"; +} +?> diff --git a/beth.txt b/beth.txt new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/beth.txt @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/check_climate_status.php b/check_climate_status.php new file mode 100644 index 0000000..4223782 --- /dev/null +++ b/check_climate_status.php @@ -0,0 +1,43 @@ +"; +$array=xml2array($output); +#print_r($array); + +echo ""; + echo ""; + echo ""; + echo ""; + $mode=$array['nodeInfo']['node']['property']['1_attr']['formatted']; + echo ""; + $fan=$array['nodeInfo']['properties']['property']['0_attr']['formatted']; + echo ""; + echo ""; + echo ""; +echo "
Set Temperature:".$array['nodeInfo']['node']['property']['2_attr']['formatted']."
Current Temperature:".($array['nodeInfo']['node']['property']['0_attr']['formatted'])."
Temperature Mode:".($array['nodeInfo']['node']['property']['1_attr']['formatted'])."
Fan Status:".($array['nodeInfo']['properties']['property']['0_attr']['formatted'])."
Humidity:".($array['nodeInfo']['properties']['property']['2_attr']['formatted'])."
  
Mode Fan
"; +?> diff --git a/check_isy99i_occupancy_status.php b/check_isy99i_occupancy_status.php new file mode 100644 index 0000000..da43b25 --- /dev/null +++ b/check_isy99i_occupancy_status.php @@ -0,0 +1,71 @@ +"; +echo ""; +foreach ($programs as $program) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL,"http://isy99/rest/programs/$program"); + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($ch, CURLOPT_USERPWD, 'admin:admin'); + + $output = curl_exec($ch); + $array=xml2array($output); + #echo "
";
+  #$array=xml2array($output);
+  #print_r($array);
+  #exit;
+
+  echo "
"; + $status=($array['programs']['program_attr']['status']); + if ($status=="true") { + echo ""; + } else { + echo ""; + } + $i++; + if ($i==5) { + echo "
".$array['programs']['program']['name']."
"; + $i=0; + $colspan++; + } +} +$colspan++; +echo "
"; +echo ""; +echo "
"; +echo ""; +if (summon_status("russ")>=1) { + echo ""; +} else { + echo ""; +} +echo ""; +if (summon_status("beth")>=1) { + echo ""; +} else { + echo ""; +} +echo "
Summon Russ + +Summon Beth + +
"; +echo ""; +?> diff --git a/check_isy99i_status.php b/check_isy99i_status.php new file mode 100644 index 0000000..613e1a8 --- /dev/null +++ b/check_isy99i_status.php @@ -0,0 +1,57 @@ +"; +#$array=xml2array($output); +#print_r($array); +#exit; + +$device=$_GET['device']; +$i=0; + +$ch = curl_init(); +curl_setopt($ch, CURLOPT_URL,"http://isy99/rest/nodes"); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); +curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); +curl_setopt($ch, CURLOPT_USERPWD, 'admin:admin'); + +$output = curl_exec($ch); +$array=xml2array($output); + +echo "
"; +echo ""; +foreach ($array[nodes][node] as $device) { + $match=0; + foreach ($blacklist as $item) { + if ($device[address] == $item) { + $match=1; + } + } + if ($match == 0) { + $address = "nodes/".str_replace(' ', '%20', ($device[address])); + $name = $device[name]; + $status = $device['property_attr']['formatted']; + if ($status=="On" or $status=="true") { + $i++; + echo ""; + echo ""; + } elseif ($status=="Off" or $status=="false") { + $i++; + echo ""; + echo ""; + } + if ($i==8) { + echo "
".$name."
".$name."
"; + $i=0; + } + } +} + +echo "
"; + +?> diff --git a/check_power_status.php b/check_power_status.php new file mode 100644 index 0000000..afaff9a --- /dev/null +++ b/check_power_status.php @@ -0,0 +1,149 @@ +"; +$array=xml2array($output); +#print_r($array); + +echo "AC Line Power Now:" . ($array['LiveData']['Voltage']['Total']['VoltageNow']/10)."
"; +#echo "Current Kw:" . ($array['LiveData']['Power']['Total']['PowerNow']/1000)."
"; +echo "Server Kw Draw:" . ($array['LiveData']['Power']['MTU1']['PowerNow']/1000)."
"; +echo "House Kw Draw:" . abs(($array['LiveData']['Power']['MTU1']['PowerNow']/1000)-($array['LiveData']['Power']['MTU2']['PowerNow']/1000))."
"; +echo "Total Kw Draw:" . ($array['LiveData']['Power']['MTU2']['PowerNow']/1000)."
"; + + + + + + + + +function xml2array($contents, $get_attributes=1, $priority = 'tag') { + if(!$contents) return array(); + + if(!function_exists('xml_parser_create')) { + //print "'xml_parser_create()' function not found!"; + return array(); + } + + //Get the XML parser of PHP - PHP must have this module for the parser to work + $parser = xml_parser_create(''); + xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); + xml_parse_into_struct($parser, trim($contents), $xml_values); + xml_parser_free($parser); + + if(!$xml_values) return;//Hmm... + + //Initializations + $xml_array = array(); + $parents = array(); + $opened_tags = array(); + $arr = array(); + + $current = &$xml_array; //Refference + + //Go through the tags. + $repeated_tag_index = array();//Multiple tags with same name will be turned into an array + foreach($xml_values as $data) { + unset($attributes,$value);//Remove existing values, or there will be trouble + + //This command will extract these variables into the foreach scope + // tag(string), type(string), level(int), attributes(array). + extract($data);//We could use the array by itself, but this cooler. + + $result = array(); + $attributes_data = array(); + + if(isset($value)) { + if($priority == 'tag') $result = $value; + else $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode + } + + //Set the attributes too. + if(isset($attributes) and $get_attributes) { + foreach($attributes as $attr => $val) { + if($priority == 'tag') $attributes_data[$attr] = $val; + else $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr' + } + } + + //See tag status and do the needed. + if($type == "open") {//The starting of the tag '' + $parent[$level-1] = &$current; + if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag + $current[$tag] = $result; + if($attributes_data) $current[$tag. '_attr'] = $attributes_data; + $repeated_tag_index[$tag.'_'.$level] = 1; + + $current = &$current[$tag]; + + } else { //There was another element with the same tag name + + if(isset($current[$tag][0])) {//If there is a 0th element it is already an array + $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result; + $repeated_tag_index[$tag.'_'.$level]++; + } else {//This section will make the value an array if multiple tags with the same name appear together + $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array + $repeated_tag_index[$tag.'_'.$level] = 2; + + if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well + $current[$tag]['0_attr'] = $current[$tag.'_attr']; + unset($current[$tag.'_attr']); + } + + } + $last_item_index = $repeated_tag_index[$tag.'_'.$level]-1; + $current = &$current[$tag][$last_item_index]; + } + + } elseif($type == "complete") { //Tags that ends in 1 line '' + //See if the key is already taken. + if(!isset($current[$tag])) { //New Key + $current[$tag] = $result; + $repeated_tag_index[$tag.'_'.$level] = 1; + if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data; + + } else { //If taken, put all things inside a list(array) + if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array... + + // ...push the new element into that array. + $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result; + + if($priority == 'tag' and $get_attributes and $attributes_data) { + $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data; + } + $repeated_tag_index[$tag.'_'.$level]++; + + } else { //If it is not an array... + $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value + $repeated_tag_index[$tag.'_'.$level] = 1; + if($priority == 'tag' and $get_attributes) { + if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well + + $current[$tag]['0_attr'] = $current[$tag.'_attr']; + unset($current[$tag.'_attr']); + } + + if($attributes_data) { + $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data; + } + } + $repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken + } + } + + } elseif($type == 'close') { //End of tag '' + $current = &$parent[$level-1]; + } + } + + return($xml_array); +} + +?> diff --git a/css/ModalDialog.css b/css/ModalDialog.css new file mode 100644 index 0000000..c9c339c --- /dev/null +++ b/css/ModalDialog.css @@ -0,0 +1,90 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + + /** + * Modal Dialog + */ + .modalBg { + position: absolute; + top: 0px; + left: 0px; + filter: Alpha(Opacity=50); + -moz-opacity: 0.5; + background-color: #ddd; + visibility: hidden; + width: expression(document.body.clientWidth); + height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight); + z-index: 100; + } + + .modalDialog { + position: absolute; + top: 0px; + left: 0px; + visibility: hidden; + z-index: 101; + background-color: white; + top: expression(document.body.clientHeight / 2 - this.offsetHeight / 2); + left: expression(document.body.clientWidth / 2 - this.offsetWidth / 2); + border: 1px solid #777; + border-top: 0; + padding: 20px; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + + .modalDialog .modalDialogHeader { + margin:0; + padding: 0px; + color: #333; + font-weight: bold; + background-color: #ccc; + border: 1px solid #989898; + position: absolute; + top: 0px; + left: -1px; + height: 7px; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius-bottomleft: 0; + -moz-border-radius-bottomright: 0; + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 0; + } + + .modalShadow { + position: absolute; + background-color: black; + top: 0px; + left: 0px; + z-index: 99; + top: expression(document.body.clientHeight / 2 - this.offsetHeight / 2); + left: expression(document.body.clientWidth / 2 - this.offsetWidth / 2); + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + opacity: 0.5; + } + + /** + * This is not part of the core Modal Dialog styles, instead it's just so that the dialog looks + * respectable. + */ + h4 { + font-family: Verdana, Arial; + padding-top: 10px; + } \ No newline at end of file diff --git a/css/common.css b/css/common.css new file mode 100644 index 0000000..cb2b287 --- /dev/null +++ b/css/common.css @@ -0,0 +1,297 @@ +@font-face { + font-family: Delicious; + src: url('/Delicious-Roman.otf') +} + +/** +* Various +*/ +body { + margin: 0px; +} + +a { + text-decoration: none; +} + +code { + background-color: #dedede; + border: 1px dashed #aaaaaa; + padding: 3px; + display: block; + font-family: Monospace; +} + + +/** +* Datagrid stuff +*/ +table.datagrid { + border-collapse: collapse; + margin-left: 30px; +} + +table.datagrid th { + background-color: #ccc; + border: 1px solid #aaa; + padding: 2px; +} + +table.datagrid tr { + background-color: #ddd; +} + +table.datagrid tr.oddrow { + background-color: #eee; +} + +table.datagrid td { + border: 1px solid #aaa; + padding: 3px; +} + + +/** +* Master div +*/ +.master { + font-family: Georgia; +} + + +/** +* Header section +*/ +.header { + margin-right: 10px; + letter-spacing: 2px; + background-image: url(/images/hdrbg.jpg); + margin-left: 10px; +} + +.header h1 { + margin-top: 0px; +} + +.tagline { + font-size: 8pt; + position: relative; + top: -15px; + left: 15px; + letter-spacing: 0px; +} + + +/** +* Top nav +*/ +.topnav { + color: white; + background-color: #314657; /* Old */ + background-color: #2D4B33; + padding: 1px; + padding-left: 10px; +} + +.topnav a { + color: white; +} + + +/** +* Left nav +*/ +.leftnav, +.searchbox { + width: 180px; + color: black; + background-color: #FF5A18; + margin-left: 5px; + margin-top: 10px; + padding: 10px; + padding-top: 0; + padding-bottom: 0; + padding: expression('10px'); + border: 1px solid #B33E11; +} + +.leftnav { + box-shadow: 3px 3px 3px #aaa; + border-radius: 5px; + -moz-box-shadow: 3px 3px 3px #aaa; + -webkit-box-shadow: 3px 3px 3px #aaa; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + width: 180px; + float: left; + hmargin: 5px; +} + +.leftnav h4 { + border-bottom: 1px solid black; +} +.leftnav a { + color: black; +} + +.leftnav ul { + margin-left: -20px; + margin-left: expression('20px'); + list-style-type: square; +} + + +/** +* Main body section +*/ +.mainbody { + margin-left: 220px; +} + +.borderedTable table { + border-collapse: collapse; +} + +.borderedTable th { + background-color: #dddddd; + border: 1px solid #aaaaaa; + font-size: 70%; + padding-left: 3px; + padding-right: 3px; +} + +.borderedTable td { + vertical-align: top; + font-size: 70%; + border: 1px solid #dddddd; +} + +.newsitem { + margin-bottom: 25px; +} + +.newsitem h2, +.newsitem h1 { + display: inline; +} + +.newsitem .date { + font-size: 70%; +} + +p.firstLetter:first-letter { + font-size: 200%; + font-style: italic; + font-weight: bold; + float: left; + padding-right: 3px; +} + +.newsitem p.update { + background-color: #efefef; + border: 1px dashed black; + padding: 5px; +} + + +/** +* Comments +*/ +.comment { + padding: 5px; + margin-bottom: 20px; + font-size: 80%; + background-color: #efefef; + border: 1px dashed #cccccc; +} + +.comment .body { + margin-top: 5px; + padding-left: 7px; +} + +.comment .quoteLink { + text-align: right; + font-size: 90%; +} + + +/** +* Errors +*/ +.error { + color: red; + font-style: italic; +} + + +/** +* Copyright text +*/ +.copyright { + text-align: right; + font-size: 75%; +} + + +/** +* Admin page +*/ +.adminPage table { + font-family: Verdana; + font-size: 10pt; +} + +.adminPage th { + background-color: #dddddd; +} + + +/** +* Tools page +*/ +#toolsPage th, +#toolsPage td { +} + +#toolsPage th { + font-weight: bold; + text-align: right; + white-space: nowrap; + vertical-align: top; + background-color: #ffffcc; +} + +#toolsPage textarea { + height: 200px; + width: 800px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#ffffff, endColorstr=#ffffcc); +} + +#shortcuts th { + +} + +#shortcuts th { + text-align: left; + background-color: #ededed; + padding: 2px; +} + +/** +* Download header/footer +*/ +div#download pre, +div#download pre a { + +} + +/** +* Code +*/ +div.boxout, +pre.code { + border: 2px dashed gray; + padding: 3px; + background-color: #eee; +} \ No newline at end of file diff --git a/css/website.css b/css/website.css new file mode 100644 index 0000000..827b5fb --- /dev/null +++ b/css/website.css @@ -0,0 +1,253 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + +body { + padding-top: 10px; + font-family: Georgia, Arial, Sans-Serif; +} + +pre#code, +code { + display: block; + border: 1px solid #aaa; + padding: 5px; + background-color: #ddd; +} + +#breadcrumb, +#logo { + border: 2px black solid; + background-color: #eee; + padding: 3px; + top: 0; + right: 0; + position: absolute; + margin: 2px; + opacity: 0.8; +} +#breadcrumb a, +#logo a { + text-decoration: none; +} + +th { + text-align: left; + border: 1px solid gray; + background-color: #ddd; + padding: 3px; + vertical-align: top; +} + +td { + vertical-align: top; +} + +ol li { + margin-top: 20px; +} + +ol#implementation li code { + margin-top: 5px; +} + +td.description { + background-color: #eee; + padding: 3px; + border: 1px solid #ddd; +} + +td.chart { + text-align: center; +} + +.example_boxout { + background-color: #eee; + padding: 3px; + border: 1px solid #aaa; +} + +.code { + padding: 5px; + background-color: #eee; + border: 2px dashed gray +} + +/** +* This is semi-transparent box in the top left corner +*/ +div#devtag { + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: #999 3px 3px 3px; + -moz-box-shadow: #999 3px 3px 3px; + box-shadow: #999 3px 3px 3px; + filter: progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135); + position: fixed; + top: 2px; + right: 2px; + width: 145px; + border: 2px solid black; + text-align: center; + font-weight: bold; + font-family: Arial; + background-color: #fdd; +} + +div#devtag a { + font-size: 10px; + text-decoration: none; + color: blue; + opacity: 1; +} + +/** +* This overrides something defined earlier +*/ +ol#colors li { + margin: 0; +} + +/** +* styles lists +*/ +div.list-item { + width: 220px; + display: inline-block; +} + +div.list-item.label { + width: 170px; +} + +legend { + background-color: #efefef; + border: 1px solid #75736e; +} + +body#licensing span { + font-size: 120%; +} + +/** +* The yellow warning box on the front page +*/ +div.warning { + border: 1px solid black; + text-align: center; + background-color: #ffa; + padding: 5px; + margin-top: 5px; + border-radius: 15px; + -moz-border-radius: 15px; + -webkit-border-radius: 15px; + -webkit-box-shadow: #aaa 1px 1px 15px; + -moz-box-shadow: #aaa 1px 1px 15px; + box-shadow: #aaa 1px 1px 15px; + filter: progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135); + z-index: 98; +} + +div.canvasfallback { + border: 2px dashed red; + background-color: #fee; + width: 475px; + height: 150px; + text-align: center; + padding-top: 50px; +} + +/** +* The title "bar" +*/ +div#title { +} + +div#title div#image { + float: left; + margin-right: 15px; +} + +div#title div#text { + padding-top: 5px; + margin-left: 70px; +} + + +div.warning p { + text-align: center; + margin-top: 5px; + margin-bottom: 5px; + font-weight: bold; +} + + +div.description { + border: 1px dashed gray; + background-color: #eee; + font-size: 75%; + padding: 3px; +} + +div#social { + display: inline; + display: inline-block; +} + + +/*************************************************************************************** +* * +* RGraph CSS classes. * +* * +* These allow you to customise how tooltips and context menus will appear. To override * +* the CSS defined in the graph scripts, you may need to use " ! important" like so: * +* * +* font-weight: bold ! important * +* * +* You don't always need to use this, only if you're trying to override something which * +* the script sets. * +* * +***************************************************************************************/ + +.RGraph_png { +} + +.RGraph_tooltip { +} + +.RGraph_contextmenu { +} + +.RGraph_contextmenu_background { +} + +.RGraph_contextmenu_item { +} + +.RGraph_zoom_window { +} + +.RGraph_zoomed_canvas { +} + +.ModalDialog_background { +} + +.ModalDialog_dialog { +} + +.ModalDialog_topbar { +} \ No newline at end of file diff --git a/excanvas/EXCANVAS-LICENSE.txt b/excanvas/EXCANVAS-LICENSE.txt new file mode 100644 index 0000000..6e802f3 --- /dev/null +++ b/excanvas/EXCANVAS-LICENSE.txt @@ -0,0 +1,214 @@ + Versions + ======== + The excanvas.original.js is the original unminified and uncompressed library. The excanvas.compressed.js has been minified by hand and + Gzip compressed. + + License for excanvas.js + ======================= + + This license is applicable to excanvas.original.js and excanvas.compressed.js ONLY. + + License + ======= + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/excanvas/HTACCESS-SAMPLE b/excanvas/HTACCESS-SAMPLE new file mode 100644 index 0000000..f0010f7 --- /dev/null +++ b/excanvas/HTACCESS-SAMPLE @@ -0,0 +1,11 @@ +## +## This is an example Apache .htaccess file that can be used to add the required +## Content-Encoding: header to the compressed version of the ExCanvas library. +## This .htaccess file is ONLY required for the compressed version. +## +## If you are not using the compressed version, or are doing the compression +## yourself (it could for example, be built into your web server), then you +## do not need this file. +## + +AddEncoding gzip .js \ No newline at end of file diff --git a/excanvas/excanvas.compressed.js b/excanvas/excanvas.compressed.js new file mode 100644 index 0000000000000000000000000000000000000000..fc3d35c73606b2cdcea1cfb77aa125f90251d04d GIT binary patch literal 8660 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 literal 0 HcmV?d00001 diff --git a/excanvas/excanvas.original.js b/excanvas/excanvas.original.js new file mode 100644 index 0000000..650e3f3 --- /dev/null +++ b/excanvas/excanvas.original.js @@ -0,0 +1,1421 @@ +// 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]) { + if (IE_VERSION >= 7) { + doc.namespaces.add(prefix, urn).doImport('#default#VML'); + } else { + // IE6 cannot handle the third argument. + doc.namespaces.add(prefix, urn); + } + } + } + + 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; + } + }; + + 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; + } + + function processStyle(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 {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; + } + + function processLineCap(lineCap) { + switch (lineCap) { + case 'butt': + return 'flat'; + case 'round': + return 'round'; + case 'square': + default: + return '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 = this.getCoords_(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 = this.getCoords_(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 = this.getCoords_(aX, aY); + var cp1 = this.getCoords_(aCP1x, aCP1y); + var cp2 = this.getCoords_(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 = this.getCoords_(aCPx, aCPy); + var p = this.getCoords_(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 = this.getCoords_(aX, aY); + var pStart = this.getCoords_(xStart, yStart); + var pEnd = this.getCoords_(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 = this.getCoords_(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 = ctx.getCoords_(x0, y0); + var p1 = ctx.getCoords_(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 = ctx.getCoords_(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'}); + }; + + /** + * @private + */ + contextPrototype.getCoords_ = function(aX, aY) { + var m = this.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 = this.getCoords_(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/groceries.html b/groceries.html new file mode 100644 index 0000000..cc460ee --- /dev/null +++ b/groceries.html @@ -0,0 +1,2 @@ + +
diff --git a/icons/button_Off.png b/icons/button_Off.png new file mode 100644 index 0000000000000000000000000000000000000000..ba79473e597f846ea8dcddee9049851c8ef0aaed GIT binary patch literal 3213 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 literal 0 HcmV?d00001 diff --git a/icons/button_On.png b/icons/button_On.png new file mode 100644 index 0000000000000000000000000000000000000000..44e5fe306a38344dde6734509de386090135fa4d GIT binary patch literal 3479 zcmV;I4QTR-P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipM> z5+)7Nka%wZ01X#OL_t(&-o=`0kX%P~$A8`T-kI5%*_oZ)mDbYgg^A%Rp#Rg6C*0jEMiL75bGT#$;PYyyQ{7FJ|Seo0Pj3t`EY zyq0WB=(X>iow<*`-T5$gX6MfA$dXW?x6X&T_w>2v-+j*Mb55_|!jCp!IxrJxuX{cW z90dje|3ZCCTmTska0##hxE@#pbO1IW>-a(-hyd°QlR^aJ|$0iYMy3T%m1TL2`} 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 literal 0 HcmV?d00001 diff --git a/icons/light.png b/icons/light.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd895cde18a88abfc852e7ed000019df6199afb GIT binary patch literal 7254 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 literal 0 HcmV?d00001 diff --git a/icons/music.png b/icons/music.png new file mode 100644 index 0000000000000000000000000000000000000000..342deb358d255f7dc0ddaec029c7d2880a6061c4 GIT binary patch literal 7326 zcmV;P9AV>$P)=vPt zKnNQ`QaIcYz$7u|aIg)=HrPfswq@CtZAoL@qZ!TB)7QTD|9`hyvdm?Z+JWb3_0072 z``-1v_x~fUy7$*`h8~i5mQfTGA4&ivgc1~g)5Ao`dL)Nppx7QcqmS1f{?RF4Q_qm% zq_iI;j8cWtfN~bfIFt&MLIDQ7S4T;r^r5t)971Uk#{&Wsi-5oz|6DLuuX*&eZeBeN zr6uwC0-@-9lygz0pw!e>6c>*vj|9t$3zf2>d^wVz2a+s-Wtz~|6|*y%Zbo|s^!-Pp zanrQB1qeG(wxKkm#8A217X{*s0dVJ)@4~Dm6OJ{_hvcDgu*;eNPt2YR>3|A}Vi}h7 zJ?%WikEXr2l5#~q`3{=4o z09fqy&Tt6WXuWCj?;NXBJYRuwb7e{4>}xKXn>VGt8nQVZ63HxRIRkWbadc^Bbw%b1 zE2KCosv0I3KGjv8gJFS*uM>DGs!(532Dg24iF(aN^Xi`4@XNuPp>dJ~qwYEr|ryi1Gt;^{cN~G_z*u{7F(yHzC>^hh#=$%Ci!H)@I70NRkbv zZG&vtV97Rm1U_39*!UiHj6&YRk;cqtk(WrI$}*Hj3gFJ`mZ}$>GiBl<&%AXW!t~NVFdlS{!2W zG~^HfQV#!TN|SQ75Xoggi;FvA$=_#U>bgSs3h!Ip0fJ`4YlP<|M?q>12*3DvCcSj52V2`bc|sv@MtlM zK(om0fh!IU0B{lzBs@$=Fi&89AS_J$M^flI60d}mJMh1}pbzf4;X+@1b=mwUU)%Ci zabK^XBubu&iclWB-XpH%TzARbvtZ?U)2IsFgK|E3!?rbb(wWQwbgm5L`}v{3rFUMpJVeQ^ zzq23oSQ=E@Wd5hxz}(X&4{*wbLy>HoKUp3{Ec+y{utx#Gw!rlkH*eTO-b0Tcd}EP} zd}B5q-iV%`1IXrG<+K4^f`w(*?k( z^@Qkmuf2HwSWJ8nPY!~X9RN$UK=s=Qf(b!94q#dH;mykUF+~s&S1j9QfetXkLIE6b zV1x&ZNSMI?&gmB97{9RG%0W!?{#!1|$Fh5+V56b6Yf7Zk1%R5CYs-oXW-psRSxRMc zkjxH(f!SCJD4+x-@T33xRSW|pFn$ICFt#VzP9l`t#!!T_t2h9hq$mu_4JU&^B#X$E zHKLr-gABB4@vLe*yiqh@%2x%zu|9G8%dc5JkGeWYX<630f{JST(B6J@cmzQu5PUWS zFcJ795^*6G>)=|>9#NreH}j9k^bQeX$_;r%Dx)L8G8tK-vgvS#p=1eg!^*Q|^oBWt zq2@oh#wUGM4Nrw7O3)Y<+G`j{mY=-~d1$ znn+dV`V|X;#L9@-NfJ?76^V`?W8Vid3KDye{1^@h0%C%EoK$#}S!$|81x z(wAX^4&A+=s4#E*tg~ui5M9qeg!zr~C2&O(ldI2%!v%+`}iJ9kfKn) z50#~1D9H1RR#;;507{zlHz}0SFusvZaUgg(?Z+-Mi{SfIMX*HtjLG$(V^(}6heqS; z2rzlU!dVSP*hMZ8jZ@}}GDKMbP=a#a(s`4@l*I{k`YvipSl5P@r_N4B>nk$%1R29Y z#@ryIH^>O1suExvkh;nusIM-8{GfkWD1aLVHoIt`^zs?6fd^5ik5 zxQ6foc8(@X9$GEoAJZFZAewUZR;7Pri~NCr;B9Oul*OX&;l(Jz6 zmUkFTYoKWc1FJNW2R#ERkuyv;cQBDH1_%Sk$tfs?3yuv_8>&?Vpk9pY`oE|L5cRFC zsVY__k!Z;MWmHTNp+rhkEK>6$Ir9RcsZ16{%aj&}S(0NV1wS7^<#TAwUp}`HK00u8 z0I%7F=XA7wSxF?X?15XaP|5Y3az+Wgs4&DvY2+CO0xTKk$)O-|FOX#?BxJV(ttltH zSszpEB%k%^I~xPH-${J~$sX--`}vUoklD&=D~c7C>_KwN6iwMEZyQd`D!g|mmo({_ zLV)Iem>`3GzpxH)w?~UU{>)qU&gS-3EK$_EZ%C%IG!CE9(H+0($3K5|!T;QQZGb>< zYCSa(VJw%F2p#KF3r@;-j^5h{|RgVqh0-pK5@xUP@?Ej554sE$1`sG=3<_2DE3+T^g*u( zgJB?eLLr`s!J(dg(A>Qj_IK`qPfzTDL)`~p$>j6ls+IH0XV(13stFbKFs5h>t4xNK zV>iEO;`#8{JHNjJ{}=`Una&>y`UJWNfWn_yQ|q?5!Ygc^3qZ_aEt?XZ%Idoz8I+v1)9CxdJx3;DYa3u$oxI29$(O>7atz7w*l{=- zI{-)e_ru}d{cy17Q@lS?<~*2RKL@_M_$nAzdKZ+3%fPgC6b%*5VDprMn05fKg>>FB zm~kTk>hqvT$3*X0K`*SVu2ad zX|%BwnIw*iT22n2Cc?lsuiN_~Y--*NZSh0Uii%Gi(*Wec7fhWA|5SAe)E3u3ejtQO z=}cj!td)T7bSM6u!`m}ig|a9`+XkM)XM8WQg~9+WN<2mAMoL; z5-Mo2__NsI!_2wCbKN{;QVau+TszfR?zPG*QV9lht?AyboW2A<;%ga@N zU}9Nu*iX5_Lgx4Pmbc*Umv4c4F8(2W@1o0~zHBU1GZzM?n2By|pfz)5C!|xobY2T)My&!Gt;bQ@DTyRT$`jd9WUiEL+8hu(b`XV%q#^JYw7ykFOK_~6KU&{+8x^k-U_r5Pi&JxU9OhTPgK-Wn#{{9wf5#I0HEa5+}<7Q zj}N8`h?vM?ut8;wx3EHSHs!H~b$9GlOpr9`No6#~>62Naw>nn}<6Dt=awT*IQyFG? znm15=r_Tx6f#1J71CyUx?JKRWS)qoH_*3}OMLB1D) z;+WjqofflP!rNSyEIIXr;~o9%wE?XYntMNhbPla+rcbh>?NORfku7%YQ}VFJS3+^9 z8VdX+5b{MJsOG~!dH_0-dyq%$g?wz^2hy~p2)!c#ARSJiG;P^^XaNEshH8?#^@DZ4 z5+_5n$O%q3SgvERH}xh4p$B_+LIqfKmW$eZ6or+75@icSB3(5oqZ;0-0PE z*8ceCaG+;5_!WuW_DD|RtPK)J-;B)cO03&8h4~@Q^km-bct65jR_4=Bu^>X{V#yR6 zV-XG3(dx%KW2_qthXOz>lR8bJPZakw>+9?tgswg;ce*8L7O*6hrM|%CXYzc-P#PMG zmaSsPA+-SWhYZJiyI^l?I~+n9+|tzw$9mhK*jI;n(!X!eI`On_r?w*GyC@YAI63SS za;kO896)Dv%QQYlr{DL^_U7uVm(7+KDFVK{#pZkxhz?A2UlyTbv62}}YS`23ELo}w zxwpdJLnSVW$&l(i(OdQ`8Xq=ykomBLmc`kkEQW?=SgeeVi_CxtMQ6joXb0>)d=#zv zE>jkH1&lA53=L&dU_tejaQC9Kp-`!Xe}8h_QM~d4nZekb5B|PTqa7mH2{NU#m~;b% z#a69PwK{AWxop%I$XoyNJ0C5$?EGm(0YC2z9OWhOGF_X4fj1scXPKhJ;oU(8O^OKw zu`hrc680qu&jUtKRrNlL>iK|Q~Q0F5h}12;ap2IiMv0QE(UaDLfUaO0#& zP#UfVMfGC?7J`c62vn68!ecMIXIQ4SBb$mhwIA4lFkU#cg9Ps(XP~Go6O$H${JI6>2WqBHTvF$Em>kG{jWIhd2#d&%^omWKP zz~945t#giU77GOPf`H1FCg6^VKZ8}Z--6ji^PxzMAaWWSB?s7mLP4Gkth<@#dItvG zNv!1d<6^Rlk~0kE*3RHmRrm-@7TutuxR31%Qdn+qIz?x$#{i)nAqu}=a#xKw0t*>_ zw|WliH``H&o|H4$kR*U*w=g8JaC>h3R?RlD@5eem-PyK(yNP|rNt->m9*WCRMqL;g z=sFJ3gS&D)#}52m%cM6y`ohMXCDNwobKD(YhQW7&I7%|bl;MiI=SGS+FN-+HxU$^+2)!|gU*KYk}Q*W&E=<_@F9@)EYbCV|&xb>Z(h;#GqZZF~9qlLnd z?d#Da?LEV$v5s{mF+Dz=P+-?kxYtrDAa@Ojbp+-WWb=RQEZ=4>Xf&i417eYxz3AV~6{O{`@rQ^NXt?6UYKfLk5)=viq z6G$6$Q&4(qBna%9ipoTmK05?l08HMWDsB6=(QN&N`k9Ng$6wrd2Gjt7jZiJ;qu;mFZm`0Km76LLb^lI@5-^NyWcBYmbZz3hT|5&*02{k4sy&;fuhmO~I22Oy z-Mstej-J@m`)|I)7sgohvC<-eF7cL_fNso$=;mD)(yF z!5tf-d*0~QGD*{;yy3qER?B(vleb)OEnGE!InwJ4B(yH*O??cp>~XZd%EMI#7+ED; z0E8Df&A#sTKKMl_zCI)vnMD6bW2c`Nt(-7@ibW3{l-v9{=oeLc~2?H|9rKh|+D zjqz!Vn5TO*eBXk31x5K!KK$*UAvFeQ9as;E+zHk~^C`E?HghSmj^v4!K-jX`=w;9o z3Z};^Sb$;}n1it{|G{nR+ptPJQ#<+W9eQ@`ieEna*5a4n-8p{gyh)+u3noKRIFBjk zN2^oQqa%@_2@qS-riR4g!wZL0F~t>GEW82-K=!$L8`YEAD`@q71aeHnA}|HlA#JD`qglyDaP<*s68D81}P-sgAl)cz8B-0P)ccXofC# z9^Ru5bhR~=)lF=zYMA+UE>m+sduPu%&;0Gf`i8oS;^_@Fe&i2wbwv?WmlZKf5A6%$ z`-D1r2B5XG176wv9DI0eqn*j+z_2rtUm5BV=+V}+sSm3XDeopa2LyE~loy91*DaYk z19o*ii<)YDV}S!QL%>U-AIrd@);2#{_Am z26}SH6S93BhXx|$bqC7EPFxo$ubsRvJvi-PYkQ+4E0vNY7b1IfelO&dTvloJfT~C+jEWj;v`M87JXUvd zT|fzAN4XH5+W0EiNqA2D$|W%>0FgCULj`);_TsxYsxq}U%SC{g{vLRnEl*o@E)3rV+A@_zpdmoHl|bbXJ1u!fDWxZpIgN*XqP53;dN(Q*aLK zZtaJsKln2kZ^C0@btuVJ#6D~7oN@wvA$5x$AY_j;Zo; zzgHSy1!Jj zzwl3HMgU=Xc0yb1#A^)e{&&OKN@4bo?E7@4$A*^lQH{x4@Iu zaTfm>VSVFNN$~T4fKz}Wjrc{`$iHQ|0xnrLV+*_|tgeaAWISGF zf92l|dckmpDx>^}(s5UrZ7?^$$QhWaQ8~ZrXN#HMc>`}=0#KPh8#?+Ebc=^X-DdGm zyYO1$8|?9s6{hF+g;`diqA+N^2v2#w+w_!7L*y=999t)E=luE}lBfb;fUK!r; z+P%L5P1+B=={;<*gIQhjL)c#nWufU1?UUf{ryqij*6s)O7htXUk>wyNpK~sXAb7)2 z@r0ptiqNq}>lXh}00hL|ojl*S;YT%f6?Z*&&D}6}d_4k?5|$4^dtV%0+WrnayLBDp zx{U|)m*6FF!_<$b5CDDT#Sw_l(#QTHH}{VKz%N{x_Vj{p6^Dxrspp6o!M_| z5D~`m;lUU`Dgaafr~ps_paMVzfC>O(_Xy1Op9^K^n};QYR+4Cw&P_TuUWOiypGRlb z676MZGl({N?&0sZZDmtM1CD0^+GwDTwvw1Yp%>Wq%0(rU{_F>~w!FS@CitZ8H?G~; z!n_@;=CqC}Cy4a*=l%%ZTr`uXEe)%;wT&?V4E)^F58VX9`bD!W2#t>v4}?+R1dRou zYi|y^_vPSi)r6);ivz;whyrM=7wqcE!Jh{r*s%B<3&NbozH2-FO#l&M>j}gkbnT6- zPuQ?n%wg{1g@NFW0t-+x5Pv|*0K0l3>l5Bp5avBOau7y=27uK7&`cE3B0}a6S##K^ zAT&Rk}_|23=?5+fLut_Xdp9_INIOIXY4tI z@Zk~#;n~B3;1xGsgLRrNWaa3o83fsFOyW4W^MYzNtsM^Qs?9$&m5K>KWegw5W zlK29XzXuKm4&Ce&d-}2DWt;&aF&8&f*lZ+lz&YXb zGy=0_gt3vKw-4Y`)r9}87Kma@y#J8GX7hpJz{mmudabNRpymktZBjIhDT89jI=dLt zykLNhr$Ry!DshlzK2m+RzAL$N92nq<=L@QF~8ew)IoI=&%WK#Xh6X6?LOXLIaD7ZL?78{Q9v%VPe z(&fZyy2L5QWcMSt>k0xFUv5mF;6WX!{uL_x7q>OEmh8nyo?J%M*+-MOWy};y=n5cB ze%)}s2CjOkg8^ByWm&@!djbUmfSA@MiC`J=^9&#ps+{vPniaCp#%cx8Bp3r@g^#t+ z;oT?UJ*y3*1(9e0FX^Wrvq<=9WcSy-EDez_?`SxxhDaU&zA2z37D#6%qGayUuEr5%>)lNw{+ogFe=`)PnIDg4Qu}%m ze(Cz1cIUrc(NxeMOq9O~XaU6;-n=PQwDSSn{??CH_-!kj3jS-6vID@Rhv)JPj{nV5 ztKrPL5SDM)Wrg2<&)lWOxL;6Cf2ve6YN)RbVZ}Q?u|sI@xbM7WVABz! z?@LDhUmro43D1G9ibklzs=$o809I|>1=!d7>JJZHd@pgwa{{O%;?qY8LcsvkEZkIZ zB9v(%IsmAagX(DCU+eFG4;JwGQE&I#KRtQbYT{4ew{Nb$q5~9!<0}kyJ$31W^zm?h ztFyRAIRSvWn|(^>bf^6Rzt3gVKQ7q({_p=9GbZoV>Odzrpv#{$f8#-~2h?GXb`8jM z`iFVvc9<^Ys5F5gcCBc_9T%Bk1%L_w6#yy#Q~;;|P`cw^0R{jv;0`Zp%S6Ed0000< KMNUMnLSTYQ5B?tj literal 0 HcmV?d00001 diff --git a/icons/weather.png b/icons/weather.png new file mode 100644 index 0000000000000000000000000000000000000000..e1862d839dfbf665b4ad704b5e53950fb155f471 GIT binary patch literal 5739 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 WPCbwZnqLMv0OdCt@>Q~yVgCoi{Vm)8 literal 0 HcmV?d00001 diff --git a/icons/weather/Clear.png b/icons/weather/Clear.png new file mode 100644 index 0000000000000000000000000000000000000000..4a5b3e77cdd863df882fc83ffa6dd68271e6e0aa GIT binary patch literal 6977 zcmbVQXEfYT)c&p2dyC!)(Ysi^_g;L)v^u8Zv?zv~q%$@t(bLT#H;`DS>320l(7E>Hs<5pD`PwIC~!R0 z%-#S19@&2b1mu3C0svfHXGKLlJtq$zk2g*po=obBicFr~9*)kh9RMI;G2aksWVlNq zjaofd(2RwpYkC+w!Dcd0NPv;2uyZlv5NpIT7cD%|?}M1x({%0|@OrgaBR41JRyBjwJ~87KHFg z5!b|qkppr;NeW*9ITa8rKbzeUC`1QrMqb%%0(!iF4M+H&X#kdgl@kmCEYg{ufC^Ip zCNhUuCBR7%sGN8auMC(90OXFEeGp)t7Z6Z4aa03pn*hW(G2V9o8y^tRkB#O8(1QV+ zAy(D^;B5{-u5xA~b;?~$yuF*U#<6yo@=zNt^@m86uLh!iSeiBm}B?0-7-VE=oK=LRgZCJNNL$bf=Vc*|bC0$*x!5S#iS zexm^3tj(kQ*E4J|%qePP!vEn|_D;3%DFAa+PxS%-Dd5qqn^*4Lvztbl6|qw}`mtc+B6_HL|}p38>+mmIwaLf`3KnkOM& zk8v}hv?tL&TkL}FXYCO<=<-9@WVXzUu^_v6Q`RJG%ADvc=594~(gZf9;aGBg7R?k< zH9>=TBPL@t`ZH;7G)Ro4N^6Sb5FiwJ`>tJ8Fg@bCzVt8rM#Yx0=QM9sit&Eh`v~SH zQxxX?^lqS$P82KJ`T5O>XfatvaZmv9mkLX`@3jEmK(9ibI1f(RtC2dEO8jpFG_@}( z!EJFDuO{mJ(Mcne5jbM#{t8UC4DxEGTBbVlYGq7xY$7C!IL~pwZ}odPSklTg8`xV( zuKTF$gal(u)p%HENt4O=iGyPm`<}Cr#wiMMw0uBQulr&&MLMN2b%Tt~wqDI4- zHoR!>`W*|B&cnn#6up(d)w?CUMZ3j(W`Ub;C+GF$%JBCygC8y$)Z4_{BHNe_*+TNh zpK}dX%8HCgM3c=Gs*2zSHTp4SWFo$~kg+HVbXR&^B7CcIbF^#MH0t_0uS`9_HLvDb|) zg!pl_W#7@aB}iA47eN$-HH1y-4Up-MvRIqhURNJ|bZ~Z_m1ZHs;#bL!Ie&A~eihMb z5p=M0t;o#EH2tRbP5+zfeur4~VQK!?4&^qpn+QVrK@AQ|4pnIKI7a@C;ez2xDQ+o+ zwzR}WHD85m32jlEl7E+b=}~q;rxmO~%cFEPuw&;RT`2#Z(Vg4B(hF65Q_OmNHq0gb zaVn{PQ7;cEdj7$sQ+>sky>f~rwi&ir8*fuuCZ#^lsJvGpN^~Bu++^Ey8*m%=%#O*< z%&w`ur+t)bpxyG7^Q)wmq}Jfr=veXCY>sH2wBVf3PTo%5T;5ufjd_4M54;TC?4bUA z%lxa^5xm_!+8kn5Vrp#uvRrNok8tn$EX^S!i$VDSQ}S-b7uyJ&(Cm z4R?cw+CuFpp-uhOy+>&sX`!v5@9(6s2x1lpztNl1hrMa=CYN|2v6?&n@klnb|2%V- zA8I;5JTWi42`3xj>~qdH%$rt)QbJqaL?L4n;xr>i__Ad9@@NNEhB~%1d@j6RZUjwT z_nJ`)}?CfP9Q_56Y&4UW+ zLTY$5M7d-t_*|qGpSOy%$`0^3nvKqw=9{X&)}({*aaD`CzwTVSJw(R*&i{?K8BCeY zKlIWwuxPyJJi3&koR5@8B2!K)R!2PjM4p(dj3V*r8JYjnB;3Fr`W`3?|D@Pt?7X5S z7lY238kcrZ>Oo4oXdqj^a0$n3sVN`46e^gt z)8NoO=pRSFkxGZ?@Av)g2~GSA8Cb)v^&cuR%y@C(3Sa*knLnH3!uk$%Fmdb}i~9k| z{8qp{b~sx9W9h^5kH?=L4oQ1RH&Wpx?=($#=}rH1RJuUEOL+w@;ch;`;C}Z4vr?)# z9?s=9qxVv@%cP z;;YG*D6^h~&p%rZ*rtu~_|cWKoZe9Wt*^y?!g0!R_s=SCfdye^Mb@7zLU)3N#Rh`4 z7Y&COm&!~0S!2(Z+M?i!EuXujn%f;phsVbxWsSZVog4i#5<8k&X|$cYa-Te+4Q{^_ zIha|pXh+@240kRWgN(Ij9A_ME)Nkrhvej`FyH}YvZZE5J+`JA4!BgNnELKAJT+6Q+ z`YCB6gXCH6eO1Ci#?JfvV}D)(F#_ZF9|wN3dMX8O?V@njPz(eTi++j0l^a;ojDGY` zdVUv$+_PMjJj2`@3p%~CNuc<0slnhTM~aVxRU#+33y!j5FS6H#-kO!(Cb+JaV66Vcu zH$Kv~;LmYX)vnuaeJ*z>zo57hGb3wpzdV1u9PWbfFGNl*tD-QYqbBZCE|Q59F_LqV zN8S;<+bD%$r}YM9^|_vTFwLxhVQKAESLn(?fb*$sWRWS7RwbXeaSqOFJ^f= z^|i`8?%5deP+0}Js7ppXmqCR{LmbV8;x8@@Rb^`BC&ezsTzoH_QXTD-HWZnQ#G9Gu z5CdW&33Fm$3m4-ZJG(J&#yg;n(2lnGQ!D?8S1;EVgi)(GEe{WYtK)CRjad{vWN_;@ zV?+S*XrM@RG;|zvY*K7uHex0Bu=fGm_6^9b_@><27S1g^eC{d>_CPI@&`2&%@v z#y%0myGJNn?OR85p%oCZukSErX<*FKRLw`;*G8f;GzIUrvrk186KkmLe9C%;ThAd z{e^ni)mh!H(Mak2<-KIC98EFoH<~Qy7VNpBXPsjKuij3Id;gk>+TOk}mGK!9)w(i5 zE84_K(5*1rnImMUYi+CLIr~~ci2uL2yo&^heFlcrW&+}jla(Vlg;F2*X7xU<4`MNa;dYP#C66_d_ zjEq*b8I@Ue`}->iONr;mk`r%ilfNAFbuFeG%y7D1>U2}_KvoFjMD-D3j2E@(xPoJJT{pasbB%5B2%(%u7M;M`#Fej0lhitnaz%Ec)2~>7$<&J9)bek=693YyppvGa` ztTM!UvgAoqm362m?JcGWDp~Ai2`c>rbeIhua z`~ZlR+=zQ_>RHF#xG(&e_3dSkV?`_Gxmqj}NG4IQi2Ho&;f9mqvQeIue7d;h4C{FG zY!?Xi5=Hc8PfAvFiHu*KipFMJee6fVp|l26cH;A)$BdIo8eUiV)3uTGYYSW}<#io0X{TCT?(vVQdk!-Y3y!=o@lmauhc{g56vaqk?03-|x ze1O6BU)V4^3Hu&%IXfsR_bOxcOK#Z9G_qzm1=F0?$-P#yd2pWOW5V-WClF1_OpvSi1*3qS^Tf8*ZkvaMa?nxF=ug|bim-uqH)m|g ze=Avp&*CK-u+7!KGJCJTA!BA~FdS<^#@&4E1^uxjT@Qm9kk`2zcj2H6m<>`d0t6Jh z_~?8{m96HX@8z}}u%L^aP$(FLs|iT{_HR19XB~L=kKiW^F1A*F^UUCxm)|O>oVSE{ zv6BTDTVPrzdl-lKS2#!%;a7Seb2E}ifXbQdtp3+&>e~6A8vi=GNQaa3y^GM`Bo$lQbF6E9ni zK+@&tZ1@;J?tU9OaN8&;uDT{#pBNODZE$Dk$0o|_5}$fHx7?HuQ)?9WcI;#wfdl z=6QC2H8c%^0diA8KW%_flL?qBnpqIHkjQKDap$3p_D=zMA73W1DwmK?>kxp_v(Db9 ze+WA5RFObn8IrnJgx#^ENYOP2k=PViXMW}h(HxMGtml}?^{a5^aQyToccJfK$@xd6 zn{Fc~@-lgNu^vv&tH3!Pwixi3h&Xzbs^H2A8L1>SgJD+jyq{hhg~+`O(pQ_q(}<(c zx?J>q?AE#M=BOn}SO@6Hj+hDgW5i2IQoEkYx=%cWujV)=h|m*y%*@E7A!(XgNgvLh#CNng2&R8OWJaDDZ(xDi1 z&G2wBam?SMIC{Zo+Al2Xg2Z5-wjnKj!N@R)m8*q%-gbu?lM?`a|Mi+{ya;(2$37`> zvqZu?lL`rzfsnc-q&XV4vMhxo z&glJ~;W?X7N6VZA^b=bJ-;?iT>xZN0PQxz1OSMuXneuu?<%JDfVUi(=XnUPvoCiz! zI8)M#47(p*N)`1OT{4u|wYTi+&-`%UeyJQ@XK$12U1aMYoR79zUXdPmC?%-V1>zL> zRm8FM>sc>699X!%pFPH$&q@LOtnRtT(Z#VQa==YjQODaRGvsQoO*VFNEm?2D-Uz6j%m$dl4aiwhUIWlUB?Xf#n=CFaL7 zVAr;z!;tD4T$ntE5f!1N0q`|Yfm1&Hv7D}SmwdtnS%Y5EXLoBROokd!^L;QVQiKP6b%F^Wk%1-e|0Bf;SOl+$)Tx6lfy*GvxEE*)y^Y zr636eYB7X&V^kh)XG%f6wPVlTbHr-X9G;{Y(Dt-jjtQ}yiGq`vTPkMh7ZKIOc8yB2$o|UfHD}z`1{F%`1}F`B zQ5T&*Wg;x6?98%ivK2zSel~29h&d75PR96aln0xBv6~#`0||eL@OLF{D)0=4d^N~L zA~|5tM-Dppc%NhnaqI)_4*8;X)!-4t@40*b%K%Cp8fyd}34egO{m~x=2K^)g9EpT+ zYM@i!wc$TBM_%Y#x;7kH;?Mx=nmN>e0d=9mkac?4b)8k;`rVP}1kV5D9=3s*_= ztA2g%E~0jG*9IB?x=#6etM|DVE)FS(H51nctG>+fhb|7edaKYEHpzx_)azT))+k^( zJ!pFn>Kd&Mwb03}-q)1L5s4?yFi_&m-J~OYm025DHR~jOW+kFfZ^a9`;}KAP)DIuo z(*&>v|FqOhhq6{jow<&DK7w-x2qt}QCNIYew=K!MXWb3)jwLe*Jy-+F4*uL+{UR20 z4P760?2uU4uk#uUGF})r{*K^Y52>2eX#Jkzzj(-sxM@epELNH@S_q=ovR%=Z{DS_d z<9yJQ?zZkB+DG%N`^_Mn=1SehmaoQ7N{?RfK0Qc-(~7DxUFUv<@gSf#k`{7wcTvFT zcE3BZO0U^iS)cUhCB>DM*-+?MkS}Vx^;nq&0gI&ktft*}zvw9)^nH&dddSlIYJ#X( z6MQ91BsoWOX7L7VTKOr`HM?E>sfo>ADS~Q0Skr1@2VT8V}9S>(KGd>+2?- zFZK~*(%u7WAwLhWc! zL+28LtzWE0;S4j{H>#bKMiB8*UPV8JJ?$>n;A~aJy9tiieb~oPz=BaaSqQMDKTVZ0 ztz7jassOzN z4)2LiqD#(4`(bN%LnUa(;c*z_;j59>*{Z)D3B702)nts{gED#f8u7+2JD620)zr4) z<=!MRCP`>8i3hmP;<-{y@G-1mLj#6nWtv?*O2}8L$sYo{mBvYfu2MzAi6->;D$o4E z;Ym$m3QP#)59_W(2O$@a#~vHS>jH)e7!SW?8k>H!z!m~%ks-hLBSMusa!go2%b|10 zG7W7lj%6MSoSkyXq7mB$kzD}>+O`EcLA)m@<%0|Q;cqOCXj%Vg0hv49iArf{;Tv_{ z5X*%+-@qE18^uHxP0;-a#kn%S-b$qj7{vFK1h^PhMICB1hFGqn1VqCUz_%SaDW!sM z=yC%RtkKbUWJ#{32Mg$>ecdk^c)dR%9xc(f`K*`n{MCKMpc1HW70QHgV2VtWz5Qo6 z$5Fn_HZ*45jGIC$n4s>lFCo&eV@sJ9EtObxzdOE!;=;j0$M)`5BX^hoe|6gbyEos8 d&v>8(7Jro^`uy8;9{(f&b!8o;Y6Y9f{{fo+46y(J literal 0 HcmV?d00001 diff --git a/icons/weather/Cloudy.png b/icons/weather/Cloudy.png new file mode 100644 index 0000000000000000000000000000000000000000..5272f3be15cd3796d1b4e66ea3d08f2c889e9441 GIT binary patch literal 9774 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 literal 0 HcmV?d00001 diff --git a/icons/weather/Cloudy_Period.png b/icons/weather/Cloudy_Period.png new file mode 100644 index 0000000000000000000000000000000000000000..5958159189336e749c8b6ad356838792cd47924c GIT binary patch literal 10999 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 a0RQ>}JE{))nO^=R02Jlk$yUmk2K^82wU%`N literal 0 HcmV?d00001 diff --git a/icons/weather/Cloudy_With_Dizzle.png b/icons/weather/Cloudy_With_Dizzle.png new file mode 100644 index 0000000000000000000000000000000000000000..afa6b31309fe9e07da7630aed6310063615160c4 GIT binary patch literal 13328 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 z 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 G7V>|-Iws}- literal 0 HcmV?d00001 diff --git a/icons/weather/Few_Flurries.png b/icons/weather/Few_Flurries.png new file mode 100644 index 0000000000000000000000000000000000000000..519cd34d39490b3071afeb1137869e2647a8636f GIT binary patch literal 11627 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 hyU61u_WdRZF#Dg24#{|Cg{*be{z literal 0 HcmV?d00001 diff --git a/icons/weather/Few_Flurries_Night.png b/icons/weather/Few_Flurries_Night.png new file mode 100644 index 0000000000000000000000000000000000000000..86e2c0b9458b8535bbc050f0da8f1e7625961083 GIT binary patch literal 12202 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 literal 0 HcmV?d00001 diff --git a/icons/weather/Few_Showers.png b/icons/weather/Few_Showers.png new file mode 100644 index 0000000000000000000000000000000000000000..4a404990d41fefbe55ea4495afed0ba7b96cd413 GIT binary patch literal 11639 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 z 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 YGbdeS=&x7z?=V31sg`2BJUrrm0FUKSEC2ui literal 0 HcmV?d00001 diff --git a/icons/weather/Freezing_Rain.png b/icons/weather/Freezing_Rain.png new file mode 100644 index 0000000000000000000000000000000000000000..6aebf91f46abd495754aa850ad1ff456f05230a2 GIT binary patch literal 15657 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

A2@_&el%{3PkuV2uCf11LPb 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 LvSh8eN$~#xU|s}g literal 0 HcmV?d00001 diff --git a/icons/weather/Mostly_Sunny.png b/icons/weather/Mostly_Sunny.png new file mode 100644 index 0000000000000000000000000000000000000000..16daeafc611451364999732c1c0b4e130f8340e6 GIT binary patch literal 13291 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 literal 0 HcmV?d00001 diff --git a/icons/weather/Overcast.png b/icons/weather/Overcast.png new file mode 100644 index 0000000000000000000000000000000000000000..5272f3be15cd3796d1b4e66ea3d08f2c889e9441 GIT binary patch literal 9774 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 literal 0 HcmV?d00001 diff --git a/icons/weather/Partly cloudy.png b/icons/weather/Partly cloudy.png new file mode 100644 index 0000000000000000000000000000000000000000..cc7fd7dab884e892706154542d6df8c7825f52b0 GIT binary patch literal 12335 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 literal 0 HcmV?d00001 diff --git a/icons/weather/Rain_Or_Snow.png b/icons/weather/Rain_Or_Snow.png new file mode 100644 index 0000000000000000000000000000000000000000..1f6eaafebc63683793d6cd2fdbdb598821e8bafa GIT binary patch literal 11308 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 XWHjaJ#;*rN`vssZuOU|{V;=NBXtk0X literal 0 HcmV?d00001 diff --git a/icons/weather/Risk_Of_Thundershowers.png b/icons/weather/Risk_Of_Thundershowers.png new file mode 100644 index 0000000000000000000000000000000000000000..b1a34382a016d7cf9130b53911e1b693b0e4f14f GIT binary patch literal 14632 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 Ruk;)sC#5XeC~o@ge*iI2D8B#z literal 0 HcmV?d00001 diff --git a/icons/weather/Snow.png b/icons/weather/Snow.png new file mode 100644 index 0000000000000000000000000000000000000000..dba540f9982b0d7638800f957e8c9c64f1fe4ef4 GIT binary patch literal 10904 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 literal 0 HcmV?d00001 diff --git a/icons/weather/Thunder_Showers.png b/icons/weather/Thunder_Showers.png new file mode 100644 index 0000000000000000000000000000000000000000..63757a8bf7748781969c26bf305e595ceeb016d5 GIT binary patch literal 14106 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 literal 0 HcmV?d00001 diff --git a/icons/weather/Wet_Flurries.png b/icons/weather/Wet_Flurries.png new file mode 100644 index 0000000000000000000000000000000000000000..146fcb239be89e1996a97683469c031b7f08cf8a GIT binary patch literal 13606 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 Y+MA5ym;BNMc;YFbte_!ZBWn@zf7ZbE(f|Me literal 0 HcmV?d00001 diff --git a/icons/weather/Wet_Flurries_Night.png b/icons/weather/Wet_Flurries_Night.png new file mode 100644 index 0000000000000000000000000000000000000000..2a32cdcd142660b875d60af99d2231321d97f877 GIT binary patch literal 13306 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 S(9(~$!yv-&|GyCB5B)EVKCc`A literal 0 HcmV?d00001 diff --git a/images/body-box-bottom.png b/images/body-box-bottom.png new file mode 100755 index 0000000000000000000000000000000000000000..ce135f9df44d061a0b49956e25247d74b7070185 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0y~yU_Jn3b8)Z%$!cHoD?m!J#5JNMI6tkVJh3R1!7(L2 zDOJHUH!(dmC^a#qvhZZ84Ny^;r;B4q#jQ8j4{|mb2)G_}Z8b^wT$aeMlzB+Yhk0EB zcic3|A17<`^E*3qfyx)`ILQg51P%ZRg$70j1_uUa28IR(khP3FK*FB&Ljj1>C7sVO x{~eIwP*{8J`KhgUe*Fb<0*=nLF8Zx}fZ^IH_O@-YExUnY44$rjF6*2UngGODKzslI literal 0 HcmV?d00001 diff --git a/images/body-box-repeatablebody.png b/images/body-box-repeatablebody.png new file mode 100755 index 0000000000000000000000000000000000000000..4bb90b558c42f2164db81ab8cb8fa75d8c46b008 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0y~yU_Jn3GjXs1$?0-icLFKN64!{5;QX|b^2DN42FH~A zq*MjZ+{EQl+H0Qf_8*);F0b`|hI_?V^?}Tc8^#^+ zK-wyR-5y9SU}us5Qj9!60?cAD0J1m|fW(ix+6NdEcd_v*E}uLJ$Y=0$^>bP0l+XkK D!`nep literal 0 HcmV?d00001 diff --git a/images/bottom-controls-off.jpg b/images/bottom-controls-off.jpg new file mode 100755 index 0000000000000000000000000000000000000000..ec972b98f3fdd11d90faec1901ab08bb2c25c6e0 GIT binary patch literal 10342 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 literal 0 HcmV?d00001 diff --git a/images/bottom-controls-on.jpg b/images/bottom-controls-on.jpg new file mode 100755 index 0000000000000000000000000000000000000000..36cde2fe2538ecc18dcbdd7a3a07e14724d88db1 GIT binary patch literal 23090 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 literal 0 HcmV?d00001 diff --git a/images/cameras-off.png b/images/cameras-off.png new file mode 100644 index 0000000000000000000000000000000000000000..65edad00f6de29db89c2940f80d95a71c8b48d54 GIT binary patch literal 1096 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 literal 0 HcmV?d00001 diff --git a/images/climate-on.png b/images/climate-on.png new file mode 100644 index 0000000000000000000000000000000000000000..5cf97fb7f2c49fc02abd353ede6d1355d184c599 GIT binary patch literal 2172 zcmV-?2!r>DP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipS? z0v8L4{e>0)000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000NqNklGB{huQadJ3Bw$dlDm!c6O$xr>g5))!+X1 zlg-UdUt3$Fez-d#!YYnwUm}9L101-XKick(X*Yc~?}La?6a`sVhszwQikZ!>r;gYA zZu?H(_vfAM>SO+yySF<$WQ2!Ab&)=X40cnS`2lU~Bda%@8d`_Tw1XjV>w9NRAB(0? zn=M)WMjdYTNR5GdUyiNnsKd6)maNT*`T(rj$f1R+Zd+6PF1zX|%cj+A(P#~EsBZMM zm<{>PGK1XIS2i{em#N-;Q_`xBCR-aL+*P3Z3~h5}{$Bl?L*8kFc~?q^2xfM`pKRIb zVaR~YSN=N8>wlZtblKBaW9oz_TNWa1^X+tWRrNq*ilSh5cNa6m-3cLZ^ypF6*Vhk4 zWeoJ&P+I@n3h5?C=G*qcYU*rCX~wjQqTu}b^IX1snXRoY0CskExOwv?ckkY1V`JkG z4`};dSK2kzof*|UcI=pMY;3HgIMj`+!}Hv^b6mZ8wbA%%*RFBz-o0J|w2Y0rySwPr z^D$>V;`8_0+PgcKE?vUi+1}pf#*G_XzkZ#^j~|m#;^M`N2U4NwdrfE?Yfsh&DfGwonEJu2qCb!xrv!^>((vq+_^Jz?#h)bY;JBg_Bp1Y4k>avG)LQ_+&A*m0%T^h z^Y-oAJb(Ticjx~7`@|S$WMrO{EHg{A*{OZ==rl_8v+bFxR(P09P!tMZ)^@XtqB^5M;m8tEBC!b#0_xF6mbx7EIN4N!w-Lt zNd}@M4|p<60Z%xB%{kpicIviwElb_^!%)weu5-*tn<#5mIcW$fm6!*fJ%35?P_-kH zti)pp7@#PJ5j4cME+oz%-9)hKRc^67QpAn84{?B$oEQr}`Sg#xD!--JOB9orq?CxJ zU;!5c^MxyMmk*tbhp`cDg1u@+iUJ{#TOg$bn)uu2f8`hNz0Y@c3*IhXQbZ6+L^ISQ zu7(^gFDsFrvc3iL;$ohWlAvM;LKLU)31K3fd+>nu$u7qwBcu{bWko@!(G68zk4>Q= zvqv^`p6%kyjqhQ&2qIu6h$Or)q69uYdkzudqksLAgtBH4ivdwbgJa2Om3{28v+Leq z0idg+E`s7x1x$k?sUjed_~`CGs+=Y#6C;&|3y53gc%YX@_f_LMA8%w@Ll{)wis|+9 zfC8@76yw23sYE1aCmAPn4UrOeoehL(KuNe9tkiW~yZ(P08tT=(k$Ch$VrYRA4EKau z1{lGG7>%+l`Q)AN5j|oCg*v4<(ModPcfiJ}E=|?ElX$cxewV&fhgH4EMajs-F%KvO zNtBcvCGv;uCuFK52aiUI1pv_!ndU?XrJW2laqS^mSRfLV{8P>-ie7D3L5j#FpCmsBiBaqL$0hw|b;S1f_ztNeVvPLiBL11CQJ3zNwnc^?QbWU_~uapcHbm2B(a zqJSZmQvydfju1_GRqQdHE&GJ`Mb_+DTV(s9-Fr_`wRmvh$$!4)`=`&ab@DhW8L#4m z5CWi>Mc&fDiBl(tG4jpR#~=Y=xt~4EZvf1<$@=Ehp-Z&Jb|whMgZuyHyC=5DvNd*p z^-I2f`VHs*{srRB-Jk!AlP6D-d!URZ_a8h$B{2lCL-(H#_>zmT9`2J1 zv4m^j?IRof4BE^d7wt-Nb@ytmn;gvo##E71u!ILe+-3!?l4_UVVrfz{A3l8enoIZXAPj@C z)Y$ZNP6qa2DsvJLDl_MOMZ5l8sd+%+8S31!!rrRdFRG?yP3y=-Hl)WIysY{-@m9bn{vK$=bPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipS^ z6EPN@$ZID6000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0009BNkl)OuM^)RhYm>~GV=4Jo?Nf1w-JP9I#$YkRCCR*F%`JGadwH4=N z!=K5m>5@L*e4dvijKy(G_(P53kF`H1*d-!M*b25TZ3$b#mar9UUD^`1ge_r9c(H^T zW1l|%O2UjWNGWqMj4`M=C+C(@f^!ZcGR6^6p`UYZy#J}inwhXNN*Sa?mKmsvRHB3s zkWwN^5)e^AJb?W9C%j}P!pbNj$_*DnfO8Jlbq(Wm0YV4>z{kf2TCEngx3|%5w{duQ zh|y>SDP=B>F_zD%`t=2vTJTTBXdK7rcDraa8W@kqI668)mSqMlUG(zuG7b(7&}y}E zPubeq!s+QL9LLG~lt3W_T-Sx?d3bw!n?GS?xN^;YzYoS3(lmwd`&eCF#b7W%mSwq6 zMXTLzqu1-f^Sqok0Bmk<;_mJa*VotJoEzTbI1c*#K3vzu@$oS@=kq13$1V{;N@);` zq6n|AuLW0*q6pn?7XXlDnX!OGgkG1t%vb^N(TO;PdlyEG;czZEda6cp-#A zwJZUCWg+VI`eL%Qo``(kM;L}k)3j2M%HosX)JsuSeJ`7DVP#1OfxW#wNGWr{Ns=H* z5<|dvJcj3a@O{6qaA}$vn~gHcx)&^@Ea^r#j$>rp;c$qXo121L4h944@9!fBf&$?z z%PQSkpXcf6X|aa~BEo1iGDJK)JQ%f9r*d|7hEAu0X0vI;cU3G;R)?#rt8Wu#^?IFV z6|3SeilV%>-rwIF<*RI5v)RPP#s+G&TICK-A1kHA#l;2Q-`~HVcY+|GSrS%NpT1w# zW3X&nxU#Z>Fboj{0cy2c;UJMD2_7FG@%;Rp*Za8(p5`PqxxJj`^!2MQ0My(nj=%D) zs-va7;;~memarvk30uOJuqA8>Tf$bbb!ki361Ie`;4e1@!2Tote{TN(rIsIZ-N72b P00000NkvXXu0mjfsM4@W literal 0 HcmV?d00001 diff --git a/images/groceries-on.png b/images/groceries-on.png new file mode 100644 index 0000000000000000000000000000000000000000..42284757a151ea53f92db955b6b9f360c849dc87 GIT binary patch literal 2212 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 XZs~hVTINKg00000NkvXXu0mjfAg~%- literal 0 HcmV?d00001 diff --git a/images/header-climate.png b/images/header-climate.png new file mode 100755 index 0000000000000000000000000000000000000000..ed723b62de6ff8bdd1f0051b9a53944ecc461833 GIT binary patch literal 3797 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 G*#7{i=`n}^ literal 0 HcmV?d00001 diff --git a/images/header-groceries.png b/images/header-groceries.png new file mode 100755 index 0000000000000000000000000000000000000000..5926e61336e75305e6e8d9eb9dc6a41324b2bd0d GIT binary patch literal 4846 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 Q;{yvrTU{Sis|tqw2hn#Q3jhEB literal 0 HcmV?d00001 diff --git a/images/header-lighting.png b/images/header-lighting.png new file mode 100755 index 0000000000000000000000000000000000000000..3c76fd6c2ce728b44a058c8123f76ccabf051157 GIT binary patch literal 9484 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�f&a@uzO zpCblou@>6yhpe6iJrw7Cy{^*{zHdTRgu!48x6b~Xp!Bm0d>hKe#U(aBKc7;Lo8cyY zb;m?ZkRS}7PhBilh)Sn58!f5b-_5_>?YD#<*80V@vN9FLLo@eJ!m5jf~)-U;4Rl219NKBP5dV>Z&*Tt<+ml3XUTFjSxs z+LR(KD?9kqcoeCoCP8a7FExm?u(Y)NwX%{gvU58NCs&4BD>)ZaKcwvD=BCkL@4FMJ zRP68tsW6_G!ekx(!cUPLAw28KeAO?M%6HNZkC)TStZnFcIfo{0c0Pr>Ff@7{-G8N; zLfZA$EZRk zRaHr#hb&=chWEO{lu+`B7XM)mOazuXFLagT77IduW?<%n z&K=rn--onJpG*Ey=0&Q}*FM4xxtddIw?b~Ex|~d%;aIrQy3$r={h^h2<=C}mN1%YV z^kB!BB+|iDH6DEJS}`+O=rWy7Z<4>rypGGbk$OY_o6B6=EXhd6x6K=|f@CX7UdhPR z<$ii5x`R+CI{!$L-LK=f&3;9NRFsf$2Ws?%_me~we6f80Hy`Q(okQfR?44L+6k6R` zPH2-98ZJaQDD&9+(z=#1FqLj!6Ctb-8DbUQXT=fj61=eCdYr1Tp$SuGp-WHPD(?u_ z3EuznNCvvai_jvzt6GQL82P(OllkB>c_v(%M>0y3zy!Nrbm{a;!Q(B<$Ec8Ptw=Y` zOmWAb_WXblc-&!TT`EuRZw66x09 zG(F$0bl$$Bv}QO~#k)-3UVdB3tSq^?dL-qdXNm=1^K75#YouyQ?A+`m-=|3G^EEpq z^oEx>gC=$5RCBykn8sY5RcMjC0`YJrX^O%I+Xsgz*hhLm)<1VL?Imu8AS7^K|7Zad zhAu{E#~+(?>+!Ip4E9lLT3Zjg%ArSUkxqs>>t|CsTP>sK(R;tEUh%6_leZH~Jw)51 zg@APOspIm`*VBPC^Hcv7JNPFe@;&?h@m~snqv9U$>c_N$6J7;?>6<`nbnnLe3wBtF A7XSbN literal 0 HcmV?d00001 diff --git a/images/header-recipes.png b/images/header-recipes.png new file mode 100755 index 0000000000000000000000000000000000000000..53b40fb3fa4f4600637c8f57c7ac963ef02ac55f GIT binary patch literal 4356 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 literal 0 HcmV?d00001 diff --git a/images/header-repeater.png b/images/header-repeater.png new file mode 100755 index 0000000000000000000000000000000000000000..88c2fe2cab2987e92164cd8470912e0a29bf780c GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^Oh9bM!3HE5`A&TTQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jiqbt@978H@CE0AK|6k9hkia-uf$eZT$Ka~j>dZuQg` zOsxNZBEWfyi0l^Og)=nRbe=p^ayi1MED+9QD9k;ff?;A(LIu+#M#H#+67LhU_8q+P tr^&PN&aZyXjHB`j|Bkb4ZDdq9z)%vtp#46N&IO>A44$rjF6*2UngB1GL_+`o literal 0 HcmV?d00001 diff --git a/images/header-security.png b/images/header-security.png new file mode 100755 index 0000000000000000000000000000000000000000..acb5b1a1c1261ef9c9069c04d56f36aa963388b7 GIT binary patch literal 5659 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 literal 0 HcmV?d00001 diff --git a/images/home-off.png b/images/home-off.png new file mode 100644 index 0000000000000000000000000000000000000000..eb4c5fb822eec81b7ac5a77742a94f617698fac5 GIT binary patch literal 1134 zcmV-!1d;oRP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipS^ z6DSr2$ihDW000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000BYNklrW67%O#Ho+Z%$XUd;^5$buqI7njoMm)-5{ch*$QlB#uc;c!z>X&2oZgnW88!g z&|1gFmU(t*m}Q_+%Bits7fnRY%_|L9dvOeMQE;{euoXxtk;M`V6DVGE7=|&xi?E}$ zo-%hSWi+04&4mh-%O`Ed&4s%*A?e=I2~-jbzVAb8jYgvpo8!9Q_SH0^7J)5Npj?Ym zN}=EHLrRHui5{{B8T{`mNat*tFw zU0ucIJv}|;qQJTO?7W4TK=1DE004u*0K?%BM1+3752aL0d>9~id-GQAv$kl=V!#CY z@$rF^lM@gThQlGc-7ao!ZU6vb7*564B(Yj4v#wz8GCQRdZf|d)wZ>pDK)2h4)*3{F zPNxIU^FTxh!w_2QsJpDgOj1&TF{2ylLW4kE&MJVv|So*9yC_P)QrqdCvdeyQ~7mjQQh6$rL3Wce>?~RoSmIT zKwGU=;=QvrfaeM!@bdD4&CSisKyv|WwqCCX0QmX&L9^M+lzENEOVV&8v%e+XP(&yUP;TRPCDA zb-%f3Yz=1CwlZduj!EpA)4Yejo9uJ?msFUW;c3yrqp;#V$+VaeAwl%Z%k8YBR z`K+O5Ba1kh%-W|3N&fBfXU?vc5yX}HtV^U85h&Lj({w!WJ%-S`tUFf?`J6z$+^_)!UV!dAf&tBuXKqZ}gz9Qf5B{^lf75R AGynhq literal 0 HcmV?d00001 diff --git a/images/home-on.png b/images/home-on.png new file mode 100644 index 0000000000000000000000000000000000000000..1c0404400a9be763cc43ca5c5072a3790638c27c GIT binary patch literal 2683 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 pN!-002ovPDHLkV1nc*1_}TG literal 0 HcmV?d00001 diff --git a/images/icon-barchart.png b/images/icon-barchart.png new file mode 100755 index 0000000000000000000000000000000000000000..caee9586100027c40d0a26c6175a0ca115e1d48b GIT binary patch literal 761 zcmVi zUqa0=3|H6n9Tb_q?;BKyXKPv3ZK;t-*NuM>BJYLfcRHQN5OI=Dr_UY7`Qdqy^YPEt0>u0rEeHM$wvLJqs*jMbgH=7NW3JH*)0Tcj{Fx&0+ z8QNN>QmHQ?;S!*ywrxMb@0mH;i*c;h>$O`f7Ef>^jvI}}@pL-fK`93pEtN{oQS7MS@4o@YlTak!1nMvgwyR|_ z866}>tJS(W91e>p@-3UqZbqY#!0bG%1zHVor>Cb;U?kMCfRF$R8j_qD4@gWV6XCk< z0xAmmeEua!J};Nc2}uw?FsSvw=aYk267oX&9h3%LK>uRSqU3` zR#h#LT!B?Q+_xuYt9wEQm2?i9Yx+vL0{%&;e7=yD@P~^alpzac}yTBP}{Q{%NOAzs=kO64O?-&DiK-6bd_!bEI r1aKYt5vW?gX56cABt~)bmjD9*FdSANk|<=800000NkvXXu0mjfCUslw literal 0 HcmV?d00001 diff --git a/images/icon-sliders.png b/images/icon-sliders.png new file mode 100755 index 0000000000000000000000000000000000000000..24c1b1786e249e43151f3fc5efa9083b53c8f0a6 GIT binary patch literal 724 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 literal 0 HcmV?d00001 diff --git a/images/news-off.png b/images/news-off.png new file mode 100644 index 0000000000000000000000000000000000000000..61e169015d008584074664b886bdf85963fff65c GIT binary patch literal 1158 zcmV;11bO?3P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf00v@9M??Vs0RI60 zpuMM)00007bV*G`2ipS^6E79efCWMT000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}000BgNkl;w@-QC@}q<^!_ zXHU{QJ3Dhp|7J;>?d|Q{F+3WL$QTpF@41WNm|$~Rhhs4dxtOi3t^X=%X0%W!5MOb` zWLZtp-!UWaOHhf&ZLFs6V+~*VS=Kt=09ON?WpvtDAGz`xoD4FQeN(Mg)g&z$;m@C+ zpEMi}6PA7on7_ZUu;3)Gb*KUc1AP7X_@G9kLG^l_Ha9n^SS%*eoCY{MtJCSw_4PGf zTwJ*ISQo;wvBr2aoc>`XAU5v!_?R{}HXJcv-j}7PrzdK)TF!|fVAabKWPEaRLhI}6 ziIkZw#Iw(JZEcNCPfuNlOrwr*jxCnUlDtf0XJ#};H;sZ<=hT7YFZ@ZLy>zIF#QoK+*? z08P-mr))^PCGG1etV8BR3~PeS+AGxFV1_xKWaiWaoTU_BX0a|fh8dt_nLlft%w~G8 z&=MESFd7SZP&0n97q0K`@4E8X7S2G7Q3Wo5;Ccu2b%EH5oB(ZRt1EiW%8!-MRDb{`Ht&7I6EE_V0 z5!YE)*(1jQ>weSr(oq;jnL!DeHW_`_plCTD8pG1?pS*O-s>fPj9mDpoj3^9i8mYNg zG=?>e)ZEM1zeVN@YkD+qd(EDtZ3dl7I&U)6w8xf9GiO-Sqj}qF_L7!mU@qyr$xzdt YzvyO9ZsfDELI3~&07*qoM6N<$f;8Y7qW}N^ literal 0 HcmV?d00001 diff --git a/images/news-on.png b/images/news-on.png new file mode 100644 index 0000000000000000000000000000000000000000..87aab11a1feb4d0e85f3b0d58e37498d375b3617 GIT binary patch literal 2508 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 literal 0 HcmV?d00001 diff --git a/images/power-on.png b/images/power-on.png new file mode 100644 index 0000000000000000000000000000000000000000..215683f98225890b71d1e3f1a5698ea8d1a40904 GIT binary patch literal 2482 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 KMNUMnLSTYVbf?Dv literal 0 HcmV?d00001 diff --git a/images/receipes-on.png b/images/receipes-on.png new file mode 100644 index 0000000000000000000000000000000000000000..5f11dc5414ea896e177204b5b09c2b77b7ca5d59 GIT binary patch literal 2387 zcmV-Z39R;sP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipS? z0v9{1B(=H#000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000QCNklmwjxSYj+43?VIE#L$>|B>h*o^+7{Zo(m)cKdCfbz>nQ>I z7Gqb5*mvLhxqaBOZQRvs-SvdUF-&Xh{fC76wnbk5e`6SLGGa-=#=`x+v{*gA4RyD@ zZ&&zl!kOjVyD=d&CX~kT-Z5jYa_N2d?~0PuYfH-79g2*H0@zs3?*p-Y+<04rZY(|9 z=;GMb+s8|f$?0PvY-j0N&&hQJJ0v8J$=_|Y{Fr*YjoV)^b`v;l_flY0VihxYfd%glx zstPEPHVY1##@8;8xNKf2na!nq|$|`bx4`B z`yga+P@P0{RQCi0NZ$AU8=IkuQMtMv*4;jewrK&93MvRAj8n)aJi~PS=hdGQ8ALJ5 zA?2Wt6ZgQ(?B2DOjUg(|fsrA&sLN|3NCfyitI)SNc&hv~B?qB}1!9u^Hz zYQ;7^LaqbaCRLTJfn};is#4W&q^tYRjbc!n21$hC25Ox{1Y}!`>K2;WSBU0mfDhjG zWeQg?6-X@T()216DzEW1wIQzynUL92 zy}(u15T7OQ-Bok15!}WI+v}u4GHEqG4m0kX zsENb8{M@4u104;T5f&~UjQWl*eEP#Y^rd^q8iY)r3!LR3O=~r;W3{Y|`4p6i9Zo_(6n?md;jZY351Xx+`@zxW4Ab2>MXvlhlo z$f49M@9SrkxhiC1Vp+1~b`-!&XGvfdBoRWrm}fmo^~g-RWilTlhit#E5M9qR&%elB zcYFlJf~br0YY0cr$vlz3p3@=RN28z7Ski1^3RCO}3mQKB@r758l71wiTW-0<`wSUt zxbN0Vi;Vu=`xJ#WIx;Nb}La6A>HLmhKRbjz(_B zki)HqJ-Z$PiE2|6BpxJ|fJ`)~8Px^Z*hvhGOJVwzla-ZzI1iRoZJ(p@zWts`#-L&h<`N)x=i0LC!5Ff1UU!IL$A}Bo;9kL)7a(1%>bKF+pzRv{S%|p_8=^10(^?bGVZX3CY%Xf!t5N*?Y#_q1Ym&Y~D z`!>%WO)M@kM=#6Ev8ngl<=I0&%(^T@zh19y+z~jm+t~+JhkSbbPJ6by?AC6Z`1M}q z>Q0gTGJ$4Sck)hy*ZLMnx67NCNhEgmzn5(6(#Um5_5UO<_x3%Sp11%2002ovPDHLk FV1fuRi5~y} literal 0 HcmV?d00001 diff --git a/images/security-off.png b/images/security-off.png new file mode 100644 index 0000000000000000000000000000000000000000..b29ecfd54f507f806fb012c0c49bce67cb515d30 GIT binary patch literal 1840 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'http://weather/weather/all-output.xml'); + $arrFeeds = array(); + foreach ($doc->getElementsByTagName('weather') as $node) { + $itemRSS = array ( + $item => $node->getElementsByTagName($item)->item(0)->nodeValue, + ); + array_push($arrFeeds, $itemRSS); + } + echo $itemRSS[$item]; +} + +function summon($person,$status) { + if ($person == "russ") { + $myFile = "russ.txt"; + $fh = fopen($myFile, 'w') or die("can't open file"); + fwrite($fh, $status); + fclose($fh); + } + if ($person == "beth") { + $myFile = "beth.txt"; + $fh = fopen($myFile, 'w') or die("can't open file"); + fwrite($fh, $status); + fclose($fh); + } +} + +function summon_status($person) { + if ($person == "russ") { + $myFile = "russ.txt"; + $fh = fopen($myFile, 'r') or die("can't open file"); + $status = fread($fh, 5); + fclose($fh); + } + if ($person == "beth") { + $myFile = "beth.txt"; + $fh = fopen($myFile, 'r') or die("can't open file"); + $status = fread($fh, 5); + fclose($fh); + } + return($status); +} +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..f47bbef --- /dev/null +++ b/index.php @@ -0,0 +1,466 @@ + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + +
+
+
+ +
+
+ +
+
+ + + +
+
+ + + +
+
+
+
+ +Middle + +
+
+
+
+ +
+ + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + + + + diff --git a/jukebox.php b/jukebox.php new file mode 100644 index 0000000..60ace13 --- /dev/null +++ b/jukebox.php @@ -0,0 +1,51 @@ +$name  "; +} + + +if ($_GET['ip']) { + $ip=$_GET['ip']; + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL,"http://$ip:8800/xbmcCmds/xbmcHttp?command=querymusicdatabase(select%20strArtist%20from%20artist%20order%20by%20strArtist)"); + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + #curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + #curl_setopt($ch, CURLOPT_USERPWD, 'admin:admin'); + $output = curl_exec($ch); + + echo "

";
+  print_r($output);
+  $array=xml2array($output);
+  print_r($array);
+}
+
+exit;
+$ch = curl_init();
+
+curl_setopt($ch, CURLOPT_URL,"http://isy99/rest/nodes/11%20BE%2054%201");
+
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+curl_setopt($ch, CURLOPT_USERPWD, 'admin:admin');
+
+$output = curl_exec($ch);
+
+#echo "
";
+$array=xml2array($output);
+#print_r($array);
+
+echo "";
+  echo "";
+  echo "";
+  echo "";
+  echo "";
+echo "
Set Temperature:".$array['nodeInfo']['node']['property']['0_attr']['formatted']."
Current Temperature:".($array['nodeInfo']['node']['property']['3_attr']['formatted'])."
Temperature Mode:".($array['nodeInfo']['node']['property']['1_attr']['formatted'])."
Humidity:".($array['nodeInfo']['properties']['property']['2_attr']['formatted'])."
"; +?> diff --git a/left-arrow.html b/left-arrow.html new file mode 100644 index 0000000..13b85e2 --- /dev/null +++ b/left-arrow.html @@ -0,0 +1,49 @@ + + + + + + + +
+ + diff --git a/libraries/RGraph.bar.js b/libraries/RGraph.bar.js new file mode 100644 index 0000000..317691d --- /dev/null +++ b/libraries/RGraph.bar.js @@ -0,0 +1,1653 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The bar chart constructor + * + * @param object canvas The canvas object + * @param array data The chart data + */ + RGraph.Bar = function (id, data) + { + // Get the canvas and context objects + this.id = id; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null; + this.canvas.__object__ = this; + this.type = 'bar'; + this.max = 0; + this.stackedOrGrouped = false; + this.isRGraph = true; + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + + // Various config type stuff + this.properties = { + 'chart.background.barcolor1': 'rgba(0,0,0,0)', + 'chart.background.barcolor2': 'rgba(0,0,0,0)', + 'chart.background.grid': true, + 'chart.background.grid.color': '#ddd', + 'chart.background.grid.width': 1, + 'chart.background.grid.hsize': 20, + 'chart.background.grid.vsize': 20, + 'chart.background.grid.vlines': true, + 'chart.background.grid.hlines': true, + 'chart.background.grid.border': true, + 'chart.background.grid.autofit':false, + 'chart.background.grid.autofit.numhlines': 7, + 'chart.background.grid.autofit.numvlines': 20, + 'chart.ytickgap': 20, + 'chart.smallyticks': 3, + 'chart.largeyticks': 5, + 'chart.numyticks': 10, + 'chart.hmargin': 5, + 'chart.strokecolor': '#666', + 'chart.axis.color': 'black', + 'chart.gutter': 25, + 'chart.labels': null, + 'chart.labels.ingraph': null, + 'chart.labels.above': false, + 'chart.labels.above.decimals': 0, + 'chart.labels.above.size': null, + 'chart.ylabels': true, + 'chart.ylabels.count': 5, + 'chart.ylabels.inside': false, + 'chart.xlabels.offset': 0, + 'chart.xaxispos': 'bottom', + 'chart.yaxispos': 'left', + 'chart.text.color': 'black', + 'chart.text.size': 10, + 'chart.text.angle': 0, + 'chart.text.font': 'Verdana', + 'chart.ymax': null, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.title.xaxis': '', + 'chart.title.yaxis': '', + 'chart.title.xaxis.pos': 0.25, + 'chart.title.yaxis.pos': 0.25, + 'chart.colors': ['rgb(0,0,255)', '#0f0', '#00f', '#ff0', '#0ff', '#0f0'], + 'chart.grouping': 'grouped', + 'chart.variant': 'bar', + 'chart.shadow': false, + 'chart.shadow.color': '#666', + 'chart.shadow.offsetx': 3, + 'chart.shadow.offsety': 3, + 'chart.shadow.blur': 3, + 'chart.tooltips': null, + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.event': 'onclick', + 'chart.tooltips.coords.adjust': [0,0], + 'chart.tooltips.highlight': true, + 'chart.background.hbars': null, + + 'chart.key': [], + 'chart.key.background': 'white', + 'chart.key.position': 'graph', + 'chart.key.shadow': false, + 'chart.key.shadow.color': '#666', + 'chart.key.shadow.blur': 3, + 'chart.key.shadow.offsetx': 2, + 'chart.key.shadow.offsety': 2, + 'chart.key.position.gutter.boxed': true, + 'chart.key.position.x': null, + 'chart.key.position.y': null, + 'chart.key.color.shape': 'square', + 'chart.key.rounded': true, + 'chart.key.text.size': 10, + + 'chart.contextmenu': null, + 'chart.line': null, + 'chart.units.pre': '', + 'chart.units.post': '', + 'chart.scale.decimals': 0, + 'chart.scale.point': '.', + 'chart.scale.thousand': ',', + 'chart.crosshairs': false, + 'chart.crosshairs.color': '#333', + 'chart.linewidth': 1, + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 10, + 'chart.zoom.delay': 50, + 'chart.zoom.shadow': true, + 'chart.zoom.mode': 'canvas', + 'chart.zoom.thumbnail.width': 75, + 'chart.zoom.thumbnail.height': 75, + 'chart.zoom.background': true, + 'chart.resizable': false, + 'chart.adjustable': false + } + + // Check for support + if (!this.canvas) { + alert('[BAR] No canvas support'); + return; + } + + // Check the common library has been included + if (typeof(RGraph) == 'undefined') { + alert('[BAR] Fatal error: The common library does not appear to have been included'); + } + + /** + * Determine whether the chart will contain stacked or grouped bars + */ + for (i=0; i 0) { + + alert('[BAR] (' + this.id + ') Sorry, tooltips are not supported with dot or pyramid charts'); + } + + /** + * Stop the coords array from growing uncontrollably + */ + this.coords = []; + + /** + * Work out a few things. They need to be here because they depend on things you can change before you + * call Draw() but after you instantiate the object + */ + this.max = 0; + this.grapharea = this.canvas.height - ( (2 * this.gutter)); + this.halfgrapharea = this.grapharea / 2; + this.halfTextHeight = this.Get('chart.text.size') / 2; + + // Progressively Draw the chart + RGraph.background.Draw(this); + + + //If it's a sketch chart variant, draw the axes first + if (this.Get('chart.variant') == 'sketch') { + this.DrawAxes(); + this.Drawbars(); + } else { + this.Drawbars(); + this.DrawAxes(); + } + + this.DrawLabels(); + + + // Draw the key if necessary + if (this.Get('chart.key').length) { + RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.colors')); + } + + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + + /** + * Is a line is defined, draw it + */ + var line = this.Get('chart.line'); + + if (line) { + + // Check the length of the data(s) + if (line.original_data[0].length != this.data.length) { + alert("[BAR] You're adding a line with a differing amount of data points to the bar chart - this is not permitted"); + } + + // Check the X axis positions + if (this.Get('chart.xaxispos') != line.Get('chart.xaxispos')) { + alert("[BAR] Using different X axis positions when combining the Bar and Line is not advised"); + } + + line.Set('chart.gutter', this.Get('chart.gutter')); + line.Set('chart.noaxes', true); + line.Set('chart.background.barcolor1', 'rgba(0,0,0,0)'); + line.Set('chart.background.barcolor2', 'rgba(0,0,0,0)'); + line.Set('chart.background.grid', false); + line.Set('chart.ylabels', false); + line.Set('chart.hmargin', (this.canvas.width - (2 * this.gutter)) / (line.original_data[0].length * 2)); + + // If a custom yMax is set, use that + if (this.Get('chart.ymax')) { + line.Set('chart.ymax', this.Get('chart.ymax')); + } + + line.Draw(); + } + + + /** + * Draw "in graph" labels + */ + if (this.Get('chart.labels.ingraph')) { + RGraph.DrawInGraphLabels(this); + } + + /** + * Draw crosschairs + */ + if (this.Get('chart.crosshairs')) { + RGraph.DrawCrosshairs(this); + } + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + + /** + * This function enables adjusting + */ + if (this.Get('chart.adjustable')) { + RGraph.AllowAdjusting(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * Draws the charts axes + */ + RGraph.Bar.prototype.DrawAxes = function () + { + var gutter = this.gutter; + var xaxispos = this.Get('chart.xaxispos'); + var yaxispos = this.Get('chart.yaxispos'); + + this.context.beginPath(); + this.context.strokeStyle = this.Get('chart.axis.color'); + this.context.lineWidth = 1; + + // Draw the Y axis + if (yaxispos == 'right') { + this.context.moveTo(this.canvas.width - gutter, gutter); + this.context.lineTo(this.canvas.width - gutter, this.canvas.height - gutter); + } else { + this.context.moveTo(gutter, gutter); + this.context.lineTo(gutter, this.canvas.height - gutter); + } + + // Draw the X axis + this.context.moveTo(gutter, (xaxispos == 'center' ? this.canvas.height / 2 : this.canvas.height - gutter)); + this.context.lineTo(this.canvas.width - gutter, xaxispos == 'center' ? this.canvas.height / 2 : this.canvas.height - gutter); + + var numYTicks = this.Get('chart.numyticks'); + + // Draw the Y tickmarks + var yTickGap = (this.canvas.height - (2 * gutter)) / numYTicks; + var xpos = yaxispos == 'left' ? gutter : this.canvas.width - gutter; + + for (y=gutter; + xaxispos == 'center' ? y <= (this.canvas.height - gutter) : y < (this.canvas.height - gutter); + y += yTickGap) { + + if (xaxispos == 'center' && y == (this.canvas.height / 2)) continue; + + this.context.moveTo(xpos, y); + this.context.lineTo(xpos + (yaxispos == 'left' ? -3 : 3), y); + } + + // Draw the X tickmarks + xTickGap = (this.canvas.width - (2 * gutter) ) / this.data.length; + yStart = this.canvas.height - gutter; + yEnd = (this.canvas.height - gutter) + 3; + + //////////////// X TICKS //////////////// + + // Now move the Y start end positions down if the axis is set to center + if (xaxispos == 'center') { + yStart = (this.canvas.height / 2) + 3; + yEnd = (this.canvas.height / 2) - 3; + } + + for (x=gutter + (yaxispos == 'left' ? xTickGap : 0); x 0) { + RGraph.DrawBars(this); + } + + var variant = this.Get('chart.variant'); + + /** + * Draw the 3D axes is necessary + */ + if (variant == '3d') { + RGraph.Draw3DAxes(this); + } + + /** + * Get the variant once, and draw the bars, be they regular, stacked or grouped + */ + + // Get these variables outside of the loop + var xaxispos = this.Get('chart.xaxispos'); + var width = (this.canvas.width - (2 * gutter) ) / this.data.length; + var orig_height = height; + var hmargin = this.Get('chart.hmargin'); + var shadow = this.Get('chart.shadow'); + var shadowColor = this.Get('chart.shadow.color'); + var shadowBlur = this.Get('chart.shadow.blur'); + var shadowOffsetX = this.Get('chart.shadow.offsetx'); + var shadowOffsetY = this.Get('chart.shadow.offsety'); + var strokeStyle = this.Get('chart.strokecolor'); + var colors = this.Get('chart.colors'); + + for (i=0; i 0.4 ? -1 : 3) - (r * width),y - 1); + this.context.lineTo(x + hmargin + width - (r > 0.4 ? 1 : -1) - (r * width), y + height + (r == 0.2 ? 1 : -2)); + } + + this.context.stroke(); + + // Regular bar + } else if (variant == 'bar' || variant == '3d' || variant == 'glass') { + + if (document.all && shadow) { + this.DrawIEShadow([x + hmargin, y, barWidth, height]); + } + + if (variant == 'glass') { + RGraph.filledCurvyRect(this.context, x + hmargin, y, barWidth, height, 3, this.data[i] > 0, this.data[i] > 0, this.data[i] < 0, this.data[i] < 0); + RGraph.strokedCurvyRect(this.context, x + hmargin, y, barWidth, height, 3, this.data[i] > 0, this.data[i] > 0, this.data[i] < 0, this.data[i] < 0); + } else { + this.context.strokeRect(x + hmargin, y, barWidth, height); + this.context.fillRect(x + hmargin, y, barWidth, height); + } + + + // This bit draws the text labels that appear above the bars if requested + if (this.Get('chart.labels.above')) { + + // Turn off any shadow + if (shadow) { + RGraph.NoShadow(this); + } + + var yPos = y - 3; + + // Account for negative bars + if (this.data[i] < 0) { + yPos += height + 6 + (this.Get('chart.text.size') - 4); + } + + this.context.fillStyle = this.Get('chart.text.color'); + RGraph.Text(this.context, this.Get('chart.text.font'), typeof(this.Get('chart.labels.above.size')) == 'number' ? this.Get('chart.labels.above.size') : this.Get('chart.text.size') - 3, x + hmargin + (barWidth / 2), yPos, RGraph.number_format(this, Number(this.data[i]).toFixed(this.Get('chart.labels.above.decimals')),this.Get('chart.units.pre'), this.Get('chart.units.post')), null, 'center'); + } + + // 3D effect + if (variant == '3d') { + + var prevStrokeStyle = this.context.strokeStyle; + var prevFillStyle = this.context.fillStyle; + + // Draw the top + this.context.beginPath(); + this.context.moveTo(x + hmargin, y); + this.context.lineTo(x + hmargin + 10, y - 5); + this.context.lineTo(x + hmargin + 10 + barWidth, y - 5); + this.context.lineTo(x + hmargin + barWidth, y); + this.context.closePath(); + + this.context.stroke(); + this.context.fill(); + + // Draw the right hand side + this.context.beginPath(); + this.context.moveTo(x + hmargin + barWidth, y); + this.context.lineTo(x + hmargin + barWidth + 10, y - 5); + this.context.lineTo(x + hmargin + barWidth + 10, y + height - 5); + this.context.lineTo(x + hmargin + barWidth, y + height); + this.context.closePath(); + + this.context.stroke(); + this.context.fill(); + + // Draw the darker top section + this.context.beginPath(); + this.context.fillStyle = 'rgba(255,255,255,0.3)'; + this.context.moveTo(x + hmargin, y); + this.context.lineTo(x + hmargin + 10, y - 5); + this.context.lineTo(x + hmargin + 10 + barWidth, y - 5); + this.context.lineTo(x + hmargin + barWidth, y); + this.context.lineTo(x + hmargin, y); + this.context.closePath(); + + this.context.stroke(); + this.context.fill(); + + // Draw the darker right side section + this.context.beginPath(); + this.context.fillStyle = 'rgba(0,0,0,0.4)'; + this.context.moveTo(x + hmargin + barWidth, y); + this.context.lineTo(x + hmargin + barWidth + 10, y - 5); + this.context.lineTo(x + hmargin + barWidth + 10, y - 5 + height); + this.context.lineTo(x + hmargin + barWidth, y + height); + this.context.lineTo(x + hmargin + barWidth, y); + this.context.closePath(); + + this.context.stroke(); + this.context.fill(); + + this.context.strokeStyle = prevStrokeStyle; + this.context.fillStyle = prevFillStyle; + + // Glass variant + } else if (variant == 'glass') { + + var grad = this.context.createLinearGradient( + x + hmargin, + y, + x + hmargin + (barWidth / 2), + y + ); + grad.addColorStop(0, 'rgba(255,255,255,0.9)'); + grad.addColorStop(1, 'rgba(255,255,255,0.5)'); + + this.context.beginPath(); + this.context.fillStyle = grad; + this.context.fillRect(x + hmargin + 2,y + (this.data[i] > 0 ? 2 : 0),(barWidth / 2) - 2,height - 2); + this.context.fill(); + } + + // Dot chart + } else if (variant == 'dot') { + + this.context.beginPath(); + this.context.moveTo(x + (width / 2), y); + this.context.lineTo(x + (width / 2), y + height); + this.context.stroke(); + + this.context.beginPath(); + this.context.fillStyle = this.Get('chart.colors')[i]; + this.context.arc(x + (width / 2), y + (this.data[i] > 0 ? 0 : height), 2, 0, 6.28, 0); + + // Set the colour for the dots + this.context.fillStyle = this.Get('chart.colors')[0]; + + this.context.stroke(); + this.context.fill(); + + // Pyramid chart + } else if (variant == 'pyramid') { + + this.context.beginPath(); + var startY = (this.Get('chart.xaxispos') == 'center' ? (this.canvas.height / 2) : (this.canvas.height - this.Get('chart.gutter'))); + + this.context.moveTo(x + hmargin, startY); + this.context.lineTo( + x + hmargin + (barWidth / 2), + y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0) + ); + this.context.lineTo(x + hmargin + barWidth, startY); + + this.context.closePath(); + + this.context.stroke(); + this.context.fill(); + + // Arrow chart + } else if (variant == 'arrow') { + var startY = (this.Get('chart.xaxispos') == 'center' ? (this.canvas.height / 2) : (this.canvas.height - this.gutter)); + + this.context.lineWidth = this.Get('chart.linewidth') ? this.Get('chart.linewidth') : 1; + this.context.lineCap = 'round'; + + this.context.beginPath(); + + this.context.moveTo(x + hmargin + (barWidth / 2), startY); + this.context.lineTo(x + hmargin + (barWidth / 2), y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0)); + this.context.arc(x + hmargin + (barWidth / 2), + y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0), + 5, + this.data[i] > 0 ? 0.78 : 5.6, + this.data[i] > 0 ? 0.79 : 5.48, + this.data[i] < 0); + + this.context.moveTo(x + hmargin + (barWidth / 2), y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0)); + this.context.arc(x + hmargin + (barWidth / 2), + y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0), + 5, + this.data[i] > 0 ? 2.355 : 4, + this.data[i] > 0 ? 2.4 : 3.925, + this.data[i] < 0); + + this.context.stroke(); + + this.context.lineWidth = 1; + + // Unknown variant type + } else { + alert('[BAR] Warning! Unknown chart.variant: ' + variant); + } + + this.coords.push([x + hmargin, y, width - (2 * hmargin), height]); + + + /** + * Stacked bar + */ + } else if (typeof(this.data[i]) == 'object' && this.Get('chart.grouping') == 'stacked') { + + var barWidth = width - (2 * hmargin); + var redrawCoords = [];// Necessary to draw if the shadow is enabled + var startY = 0; + + for (j=0; j 0) { + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = String(obj.Get('chart.tooltips')(barCoords[5])); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[barCoords[5]]) == 'function') { + var text = String(obj.Get('chart.tooltips')[barCoords[5]](barCoords[5])); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && (typeof(obj.Get('chart.tooltips')[barCoords[5]]) == 'string' || typeof(obj.Get('chart.tooltips')[barCoords[5]]) == 'number')) { + var text = String(obj.Get('chart.tooltips')[barCoords[5]]); + + } else { + var text = null; + } + + if (text) { + canvas.style.cursor = 'pointer'; + } else { + canvas.style.cursor = 'default'; + } + + /** + * Hide the currently displayed tooltip if the index is the same + */ + if ( RGraph.Registry.Get('chart.tooltip') + && RGraph.Registry.Get('chart.tooltip').__canvas__.id != obj.id + && obj.Get('chart.tooltips.event') == 'onmousemove') { + + RGraph.Redraw(); + RGraph.HideTooltip(); + } + + /** + * This facilitates the tooltips using the onmousemove event + */ + + if ( obj.Get('chart.tooltips.event') == 'onmousemove' + && ( + (RGraph.Registry.Get('chart.tooltip') && RGraph.Registry.Get('chart.tooltip').__index__ != barCoords[5]) + || !RGraph.Registry.Get('chart.tooltip') + ) + && text) { + /** + * Show a tooltip if it's defined + */ + RGraph.Redraw(obj); + + obj.context.beginPath(); + obj.context.strokeStyle = 'black'; + obj.context.fillStyle = 'rgba(255,255,255,0.5)'; + obj.context.strokeRect(barCoords[1], barCoords[2], barCoords[3], barCoords[4]); + obj.context.fillRect(barCoords[1], barCoords[2], barCoords[3], barCoords[4]); + + obj.context.stroke(); + obj.context.fill(); + + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, barCoords[5]); + } + } else { + canvas.style.cursor = 'default'; + } + } + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove); + this.canvas.addEventListener('mousemove', canvas_onmousemove, false); + + + /** + * Install the onclick event handler for the tooltips + */ + if (this.Get('chart.tooltips.event') == 'onclick') { + + canvas_onclick = function (e) + { + var e = RGraph.FixEventObject(e); + + // If the button pressed isn't the left, we're not interested + if (e.button != 0) return; + + e = RGraph.FixEventObject(e); + + var canvas = document.getElementById(this.id); + var obj = canvas.__object__; + var barCoords = obj.getBar(e); + + /** + * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn + * This "deselects" any already selected bar + */ + RGraph.Redraw(); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + if (barCoords) { + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = String(obj.Get('chart.tooltips')(barCoords[5])); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[barCoords[5]]) == 'function') { + var text = String(obj.Get('chart.tooltips')[barCoords[5]](barCoords[5])); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object') { + var text = String(obj.Get('chart.tooltips')[barCoords[5]]); + + } else { + var text = null; + } + + /** + * Show a tooltip if it's defined + */ + if (text && text != 'undefined') { + + // [TODO] Allow customisation of the highlight colors + obj.context.beginPath(); + obj.context.strokeStyle = 'black'; + obj.context.fillStyle = 'rgba(255,255,255,0.5)'; + obj.context.strokeRect(barCoords[1], barCoords[2], barCoords[3], barCoords[4]); + obj.context.fillRect(barCoords[1], barCoords[2], barCoords[3], barCoords[4]); + + obj.context.stroke(); + obj.context.fill(); + + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, barCoords[5]); + } + } + + /** + * Stop the event bubbling + */ + e.stopPropagation(); + } + RGraph.AddEventListener(this.id, 'click', canvas_onclick); + this.canvas.addEventListener('click', canvas_onclick, false); + } + + + // This resets the bar graph + // 8th August 2010 : Is this redundant + //if (typeof(obj) != 'undefined' && obj == RGraph.Registry.Get('chart.tooltip')) { + // obj.style.display = 'none'; + // RGraph.Registry.Set('chart.tooltip', null) + //} + } + } + + /** + * Draws the labels for the graph + */ + RGraph.Bar.prototype.DrawLabels = function () + { + var context = this.context; + var gutter = this.gutter; + var text_angle = this.Get('chart.text.angle'); + var text_size = this.Get('chart.text.size'); + var labels = this.Get('chart.labels'); + + + // Draw the Y axis labels: + if (this.Get('chart.ylabels')) { + this.Drawlabels_center(); + this.Drawlabels_bottom(); + } + + /** + * The X axis labels + */ + if (typeof(labels) == 'object' && labels) { + + var yOffset = 13 + Number(this.Get('chart.xlabels.offset')); + + /** + * Text angle + */ + var angle = 0; + var halign = 'center'; + + if (text_angle > 0) { + angle = -1 * text_angle; + halign = 'right'; + yOffset -= 5; + } + + // Draw the X axis labels + context.fillStyle = this.Get('chart.text.color'); + + // How wide is each bar + var barWidth = (this.canvas.width - (2 * gutter) ) / labels.length; + + // Reset the xTickGap + xTickGap = (this.canvas.width - (2 * gutter)) / labels.length + + // Draw the X tickmarks + var i=0; + var font = this.Get('chart.text.font'); + + for (x=gutter + (xTickGap / 2); x<=this.canvas.width - gutter; x+=xTickGap) { + RGraph.Text(context, font, + text_size, + x + (this.Get('chart.text.angle') == 90 ? 0: 0), + (this.canvas.height - gutter) + yOffset, + String(labels[i++]), + (this.Get('chart.text.angle') == 90 ? 'center' : null), + halign, + null, + angle); + } + } + } + + /** + * Draws the X axis in the middle + */ + RGraph.Bar.prototype.Drawlabels_center = function () + { + var font = this.Get('chart.text.font'); + var numYLabels = this.Get('chart.ylabels.count'); + + this.context.fillStyle = this.Get('chart.text.color'); + + if (this.Get('chart.xaxispos') == 'center') { + + /** + * Draw the top labels + */ + var interval = (this.grapharea * (1/10) ); + var text_size = this.Get('chart.text.size'); + var gutter = this.gutter; + var units_pre = this.Get('chart.units.pre'); + var units_post = this.Get('chart.units.post'); + var context = this.context; + var align = ''; + var xpos = 0; + var boxed = false; + + this.context.fillStyle = this.Get('chart.text.color'); + this.context.strokeStyle = 'black'; + + if (this.Get('chart.ylabels.inside') == true) { + var xpos = this.Get('chart.yaxispos') == 'left' ? gutter + 5 : this.canvas.width - gutter - 5; + var align = this.Get('chart.yaxispos') == 'left' ? 'left' : 'right'; + var boxed = true; + } else { + var xpos = this.Get('chart.yaxispos') == 'left' ? gutter - 5 : this.canvas.width - gutter + 5; + var align = this.Get('chart.yaxispos') == 'left' ? 'right' : 'left'; + var boxed = false; + } + + + + + + + + + + + + + /** + * Draw specific Y labels here so that the local variables can be reused + */ + if (typeof(this.Get('chart.ylabels.specific')) == 'object') { + + var labels = this.Get('chart.ylabels.specific'); + var grapharea = this.canvas.height - (2 * gutter); + + // Draw the top halves labels + for (var i=0; i=0; --i) { + var y = gutter + (grapharea * ( (i+1) / (labels.length * 2) )) + (grapharea / 2); + + RGraph.Text(context, font, text_size, xpos, y, labels[labels.length - i - 1], 'center', align, boxed); + } + + return; + } + + + + + + + + + + + + + if (numYLabels == 3 || numYLabels == 5) { + RGraph.Text(context, font, text_size, xpos, gutter + this.halfTextHeight, RGraph.number_format(this, this.scale[4], units_pre, units_post), null, align, boxed); + + if (numYLabels == 5) { + RGraph.Text(context, font, text_size, xpos, (1*interval) + gutter + this.halfTextHeight, RGraph.number_format(this, this.scale[3], units_pre, units_post), null, align, boxed); + RGraph.Text(context, font, text_size, xpos, (3*interval) + gutter + this.halfTextHeight, RGraph.number_format(this, this.scale[1], units_pre, units_post), null, align, boxed); + } + + if (numYLabels == 3 || numYLabels == 5) { + RGraph.Text(context, font, text_size, xpos, (4*interval) + gutter + this.halfTextHeight, RGraph.number_format(this, this.scale[0], units_pre, units_post), null, align, boxed); + RGraph.Text(context, font, text_size, xpos, (2*interval) + gutter + this.halfTextHeight, RGraph.number_format(this, this.scale[2], units_pre, units_post), null, align, boxed); + } + } else if (numYLabels == 10) { + // 10Y labels + interval = (this.grapharea / numYLabels) / 2; + + for (var i=0; i= (left + obj.Get('chart.tooltips.coords.adjust')[0]) + && mouseX <= (left + width+ obj.Get('chart.tooltips.coords.adjust')[0]) + && mouseY >= (top + obj.Get('chart.tooltips.coords.adjust')[1]) + && mouseY <= (top + height + obj.Get('chart.tooltips.coords.adjust')[1]) ) { + + return [obj, left, top, width, height, i]; + } + } + + return null; + } diff --git a/libraries/RGraph.bipolar.js b/libraries/RGraph.bipolar.js new file mode 100644 index 0000000..d563fb4 --- /dev/null +++ b/libraries/RGraph.bipolar.js @@ -0,0 +1,713 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The bi-polar/age frequency constructor. + * + * @param string id The id of the canvas + * @param array left The left set of data points + * @param array right The right set of data points + */ + RGraph.Bipolar = function (id, left, right) + { + // Get the canvas and context objects + this.id = id; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext('2d'); + this.canvas.__object__ = this; + this.type = 'bipolar'; + this.coords = []; + this.max = 0; + this.isRGraph = true; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + + // The left and right data respectively + this.left = left; + this.right = right; + this.data = [left, right]; + + this.properties = { + 'chart.margin': 2, + 'chart.xtickinterval': null, + 'chart.labels': [], + 'chart.text.size': 10, + 'chart.text.color': 'black', + 'chart.text.font': 'Verdana', + 'chart.title.left': '', + 'chart.title.right': '', + 'chart.gutter': 25, + 'chart.gutter.center': 60, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.colors': ['#0f0'], + 'chart.contextmenu': null, + 'chart.tooltips': null, + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.highlight': true, + 'chart.units.pre': '', + 'chart.units.post': '', + 'chart.shadow': false, + 'chart.shadow.color': '#666', + 'chart.shadow.offsetx': 3, + 'chart.shadow.offsety': 3, + 'chart.shadow.blur': 3, + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.xmax': null, + 'chart.scale.decimals': null, + 'chart.scale.point': '.', + 'chart.scale.thousand': ',', + 'chart.axis.color': 'black', + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 10, + 'chart.zoom.delay': 50, + 'chart.zoom.shadow': true, + 'chart.zoom.mode': 'canvas', + 'chart.zoom.thumbnail.width': 75, + 'chart.zoom.thumbnail.height': 75, + 'chart.zoom.background': true, + 'chart.zoom.action': 'zoom', + 'chart.resizable': false, + 'chart.strokestyle': '#333' + } + + // Pad the arrays so they're the same size + while (this.left.length < this.right.length) this.left.push(0); + while (this.left.length > this.right.length) this.right.push(0); + + // Check the common library has been included + if (typeof(RGraph) == 'undefined') { + alert('[BIPOLAR] Fatal error: The common library does not appear to have been included'); + } + } + + + /** + * The setter + * + * @param name string The name of the parameter to set + * @param value mixed The value of the paraneter + */ + RGraph.Bipolar.prototype.Set = function (name, value) + { + this.properties[name.toLowerCase()] = value; + } + + + /** + * The getter + * + * @param name string The name of the parameter to get + */ + RGraph.Bipolar.prototype.Get = function (name) + { + return this.properties[name.toLowerCase()]; + } + + + /** + * Draws the graph + */ + RGraph.Bipolar.prototype.Draw = function () + { + /** + * Fire the onbeforedraw event + */ + RGraph.FireCustomEvent(this, 'onbeforedraw'); + + + /** + * Clear all of this canvases event handlers (the ones installed by RGraph) + */ + RGraph.ClearEventListeners(this.id); + + + // Reset the data to what was initially supplied + this.left = this.data[0]; + this.right = this.data[1]; + + /** + * Reset the coords array + */ + this.coords = []; + + this.GetMax(); + this.DrawAxes(); + this.DrawTicks(); + this.DrawLeftBars(); + this.DrawRightBars(); + + if (this.Get('chart.axis.color') != 'black') { + this.DrawAxes(); // Draw the axes again (if the axes color is not black) + } + + this.DrawLabels(); + this.DrawTitles(); + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + + /** + * Install the on* event handlers + */ + if (this.Get('chart.tooltips')) { + + + // Register the object so that it gets redrawn + RGraph.Register(this); + + + /** + * Install the window onclick handler + */ + + /** + * Install the window event handler + */ + var eventHandler_window_click = function () + { + RGraph.Redraw(); + } + window.addEventListener('click', eventHandler_window_click, false); + RGraph.AddEventListener('window_' + this.id, 'click', eventHandler_window_click); + + + + /** + * If the cursor is over a hotspot, change the cursor to a hand + */ + var eventHandler_canvas_mousemove = function (e) + { + e = RGraph.FixEventObject(e); + + var canvas = document.getElementById(this.id); + var obj = canvas.__object__; + + /** + * Get the mouse X/Y coordinates + */ + var mouseCoords = RGraph.getMouseXY(e); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0; i= left && mouseX <= (left + width ) && mouseY >= top && mouseY <= (top + height) ) { + canvas.style.cursor = 'pointer'; + return; + } + } + + canvas.style.cursor = 'default'; + } + this.canvas.addEventListener('mousemove', eventHandler_canvas_mousemove, false); + RGraph.AddEventListener(this.id, 'mouseover', eventHandler_canvas_mousemove); + + + /** + * Install the onclick event handler for the tooltips + */ + var eventHandler_canvas_click = function (e) + { + e = RGraph.FixEventObject(e); + + var canvas = document.getElementById(this.id) + var obj = canvas.__object__; + + /** + * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn + * This "deselects" any already selected bar + */ + RGraph.Clear(canvas); + obj.Draw(); + + /** + * Get the mouse X/Y coordinates + */ + var mouseCoords = RGraph.getMouseXY(e); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0; i= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) { + + + /** + * Show a tooltip if it's defined + * FIXME pageX and pageY not supported in MSIE + */ + if (obj.Get('chart.tooltips')) { + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = obj.Get('chart.tooltips')(i); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[i]) == 'function') { + var text = obj.Get('chart.tooltips')[i](i); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object') { + var text = obj.Get('chart.tooltips')[i]; + + } else { + var text = ''; + } + + obj.context.beginPath(); + obj.context.strokeStyle = 'black'; + obj.context.fillStyle = 'rgba(255,255,255,0.5)'; + obj.context.strokeRect(left, top, width, height); + obj.context.fillRect(left, top, width, height); + + obj.context.stroke(); + obj.context.fill(); + + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i); + } + } + } + + /** + * Stop the event bubbling + */ + e.stopPropagation(); + + return false; + } + this.canvas.addEventListener('click', eventHandler_canvas_click, false); + RGraph.AddEventListener(this.id, 'click', eventHandler_canvas_click); + + // This resets the bipolar graph + if (RGraph.Registry.Get('chart.tooltip')) { + RGraph.Registry.Get('chart.tooltip').style.display = 'none'; + RGraph.Registry.Set('chart.tooltip', null) + } + } + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * Draws the axes + */ + RGraph.Bipolar.prototype.DrawAxes = function () + { + // Draw the left set of axes + this.context.beginPath(); + this.context.strokeStyle = this.Get('chart.axis.color'); + + this.axisWidth = (this.canvas.width - this.Get('chart.gutter.center') ) / 2; + this.axisHeight = this.canvas.height - (2 * this.Get('chart.gutter')); + + this.context.moveTo(this.Get('chart.gutter'), this.canvas.height - this.Get('chart.gutter')); + this.context.lineTo(this.axisWidth, this.canvas.height - this.Get('chart.gutter')); + this.context.lineTo(this.axisWidth, this.Get('chart.gutter')); + + this.context.stroke(); + + // Draw the right set of axes + this.context.beginPath(); + + this.axisWidth = ((this.canvas.width - this.Get('chart.gutter.center')) / 2) + this.Get('chart.gutter.center'); + + this.context.moveTo(this.axisWidth, this.Get('chart.gutter')); + this.context.lineTo(this.axisWidth, this.canvas.height - this.Get('chart.gutter')); + this.context.lineTo(this.canvas.width - this.Get('chart.gutter'), this.canvas.height - this.Get('chart.gutter')); + + this.context.stroke(); + } + + + /** + * Draws the tick marks on the axes + */ + RGraph.Bipolar.prototype.DrawTicks = function () + { + var numDataPoints = this.left.length; + var barHeight = ( (this.canvas.height - (2 * this.Get('chart.gutter')))- (this.left.length * (this.Get('chart.margin') * 2) )) / numDataPoints; + + // Draw the left Y tick marks + for (var i = this.canvas.height - this.Get('chart.gutter'); i >= this.Get('chart.gutter'); i -= (barHeight + ( this.Get('chart.margin') * 2)) ) { + if (i < (this.canvas.height - this.Get('chart.gutter')) ) { + this.context.beginPath(); + this.context.moveTo(this.axisWidth - this.Get('chart.gutter.center'), i); + this.context.lineTo(this.axisWidth - this.Get('chart.gutter.center') + 3, i); + this.context.stroke(); + } + } + + //Draw the right axis Y tick marks + for (var i = this.canvas.height - this.Get('chart.gutter'); i >= this.Get('chart.gutter'); i -= (barHeight + ( this.Get('chart.margin') * 2)) ) { + if (i < (this.canvas.height - this.Get('chart.gutter')) ) { + this.context.beginPath(); + this.context.moveTo(this.axisWidth, i); + this.context.lineTo(this.axisWidth - 3, i); + this.context.stroke(); + } + } + + // Draw the left sides X tick marks + var xInterval = (this.canvas.width - (2 * this.Get('chart.gutter')) - this.Get('chart.gutter.center')) / 10; + + // Is chart.xtickinterval specified ? If so, use that. + if (typeof(this.Get('chart.xtickinterval')) == 'number') { + xInterval = this.Get('chart.xtickinterval'); + } + + for (i=this.Get('chart.gutter'); i<(this.canvas.width - this.Get('chart.gutter.center') ) / 2; i += xInterval) { + this.context.beginPath(); + this.context.moveTo(i, this.canvas.height - this.Get('chart.gutter')); // 4 is the tick height + this.context.lineTo(i, (this.canvas.height - this.Get('chart.gutter')) + 4); + this.context.closePath(); + + this.context.stroke(); + } + + // Draw the right sides X tick marks + var stoppingPoint = (this.canvas.width - (2 * this.Get('chart.gutter')) - this.Get('chart.gutter.center')) / 2; + var stoppingPoint = stoppingPoint + this.Get('chart.gutter.center') + this.Get('chart.gutter') + + for (i=this.canvas.width - this.Get('chart.gutter'); i > stoppingPoint; i-=xInterval) { + this.context.beginPath(); + this.context.moveTo(i, this.canvas.height - this.Get('chart.gutter')); + this.context.lineTo(i, (this.canvas.height - this.Get('chart.gutter')) + 4); + this.context.closePath(); + + this.context.stroke(); + } + + // Store this for later + this.barHeight = barHeight; + } + + + /** + * Figures out the maximum value, or if defined, uses xmax + */ + RGraph.Bipolar.prototype.GetMax = function() + { + var max = 0; + var dec = this.Get('chart.scale.decimals'); + + // chart.xmax defined + if (this.Get('chart.xmax')) { + + max = this.Get('chart.xmax'); + + this.scale = []; + this.scale[0] = Number((max / 5) * 1).toFixed(dec); + this.scale[1] = Number((max / 5) * 2).toFixed(dec); + this.scale[2] = Number((max / 5) * 3).toFixed(dec); + this.scale[3] = Number((max / 5) * 4).toFixed(dec); + this.scale[4] = Number(max).toFixed(dec); + + this.max = max; + + + // Generate the scale ourselves + } else { + this.leftmax = RGraph.array_max(this.left); + this.rightmax = RGraph.array_max(this.right); + max = Math.max(this.leftmax, this.rightmax); + + this.scale = RGraph.getScale(max, this); + this.scale[0] = Number(this.scale[0]).toFixed(dec); + this.scale[1] = Number(this.scale[1]).toFixed(dec); + this.scale[2] = Number(this.scale[2]).toFixed(dec); + this.scale[3] = Number(this.scale[3]).toFixed(dec); + this.scale[4] = Number(this.scale[4]).toFixed(dec); + + this.max = this.scale[4]; + } + + // Don't need to return it as it is stored in this.max + } + + + /** + * Function to draw the left hand bars + */ + RGraph.Bipolar.prototype.DrawLeftBars = function () + { + // Set the stroke colour + this.context.strokeStyle = this.Get('chart.strokestyle'); + + for (i=0; i coords[i][0] - 5 + && mouseCoords[1] > coords[i][1] - 5 + && mouseCoords[0] < coords[i][0] + 5 + && mouseCoords[1] < coords[i][1] + 5 + ) { + + var numDataSeries = obj.original_data.length; + var numDataPoints = obj.original_data[0].length; + var data_series = i / numDataPoints; + data_series = Math.floor(data_series); + + + + canvas.style.cursor = 'ns-resize'; + RGraph.Registry.Set('chart.adjusting.line.' + id, [obj, i, [coords[i][0], coords[i][1]], data_series]); + + return; + } + } + } + + + canvas.onmousemove = function (e) + { + e = RGraph.FixEventObject(e); + var id = e.target.__object__.id; + + var state = RGraph.Registry.Get('chart.adjusting.line.' + id); + + if (state) { + var obj = state[0]; + var idx = state[1]; + var canvas = obj.canvas; + var context = obj.context; + var data_series = state[3]; + var points = obj.original_data[data_series]; + var mouseCoords = RGraph.getMouseXY(e); + var x = mouseCoords[0]; + var y = mouseCoords[1]; + + if (y >= (obj.canvas.height - obj.Get('chart.gutter'))) { + y = obj.canvas.height - obj.Get('chart.gutter'); + } else if (y <= obj.Get('chart.gutter')) { + y = obj.Get('chart.gutter'); + } + + var pos = obj.canvas.height - (2 * obj.Get('chart.gutter')); + pos = pos - (y - obj.Get('chart.gutter')); + var value = (obj.max / (obj.canvas.height - (2 * obj.Get('chart.gutter')))) * pos; + + // Adjust the index so that it's applicable to the correct data series + for (var i=0; i obj.coords[i][0] - 5 + && y > obj.coords[i][1] - 5 + && x < obj.coords[i][0] + 5 + && y < obj.coords[i][1] + 5 + ) { + + canvas.style.cursor = 'ns-resize'; + return; + } + } + } + + e.target.style.cursor = null; + } + + + canvas.onmouseup = function (e) + { + var id = e.target.__object__.id; + + RGraph.Registry.Set('chart.adjusting.line.' + id, null); + e.target.style.cursor = null; + } + + + canvas.onmouseout = function (e) + { + canvas.onmouseup(e); + } + + /** + * Progress bar + */ + } else if (obj.type == 'hprogress') { + + + canvas.onmousedown = function (e) + { + var id = e.target.__object__.id; + + RGraph.Registry.Set('chart.adjusting.progress.' + id, [true]); + + canvas.onmousemove(e); + } + + + canvas.onmousemove = function (e) + { + var id = e.target.__object__.id; + var state = RGraph.Registry.Get('chart.adjusting.progress.' + id); + + if (state && state.length) { + var obj = e.target.__object__; + var canvas = obj.canvas; + var context = obj.context; + + if (obj.type == 'hprogress') { + + var coords = RGraph.getMouseXY(e); + coords[0] = Math.max(0, coords[0] - obj.Get('chart.gutter')); + var barWidth = canvas.width - (2 * obj.Get('chart.gutter')); + + // Work out the new value + var value = (coords[0] / barWidth) * (obj.max - obj.Get('chart.min')); + value += obj.Get('chart.min'); + + obj.value = Math.max(0, value.toFixed()); + RGraph.Clear(obj.canvas); + obj.Draw(); + + } else if (obj.type == 'vprogress') { + + var coords = RGraph.getMouseXY(e); + coords[1] = Math.max(0, coords[1] - obj.Get('chart.gutter')); + var barHeight = canvas.height - (2 * obj.Get('chart.gutter')); + + // Work out the new value + var value = ( (barHeight - coords[1]) / barHeight) * obj.max; + + obj.value = Math.max(0, value.toFixed()); + RGraph.Clear(obj.canvas); + obj.Draw(); + } + + /** + * Fire the onadjust event + */ + RGraph.FireCustomEvent(obj, 'onadjust'); + } + } + + + canvas.onmouseup = function (e) + { + var id = e.target.__object__.id; + RGraph.Registry.Set('chart.adjusting.progress.' + id, null); + } + + + canvas.onmouseout = function (e) + { + canvas.onmouseup(e); + } + + /** + * Rose chart + */ + } else if (obj.type == 'rose') { + + + obj.Set('chart.ymax', obj.max); + + + canvas.onmousemove = function (e) + { + var obj = e.target.__object__; + var id = obj.id; + var canvas = obj.canvas; + var context = obj.context; + var coords = RGraph.getMouseXY(e); + var segment = RGraph.Registry.Get('chart.adjusting.rose.' + id); + var x = Math.abs(coords[0] - obj.centerx); + var y = Math.abs(coords[1] - obj.centery); + var theta = Math.atan(y / x) * (180 / Math.PI); // theta is now in DEGREES + + + // Account for the correct quadrant + if (coords[0] >= obj.centerx && coords[1] < obj.centery) { + theta = 90 - theta; + } else if (coords[0] >= obj.centerx && coords[1] >= obj.centery) { + theta += 90; + } else if (coords[0] < obj.centerx && coords[1] >= obj.centery) { + theta = 90 - theta; + theta = 180 + theta; + + } else if (coords[0] < obj.centerx && coords[1] < obj.centery) { + theta = theta + 270; + } + + var Opp = y; + var Adj = x; + var Hyp = Math.abs(Adj / Math.sin(theta / (180 / Math.PI))); + + for (var i=0; i obj.angles[i][0] + && theta < obj.angles[i][1] ) { + + if (RGraph.Registry.Get('chart.adjusting.rose.' + id) && i == segment[5]) { + var newvalue = (Hyp / (obj.radius - 25) ) * obj.max; + obj.data[i] = Math.min(newvalue, obj.max); + + RGraph.Clear(obj.canvas); + obj.Draw(); + + /** + * Fire the onadjust event + */ + RGraph.FireCustomEvent(obj, 'onadjust'); + } + + if (Hyp <= (obj.angles[i][2] + 5) && Hyp >= (obj.angles[i][2] - 5) ) { + canvas.style.cursor = 'move'; + return; + + } else if (obj.Get('chart.tooltips') && Hyp <= (obj.angles[i][2] - 5) ) { + canvas.style.cursor = 'pointer'; + return; + } + + } + } + + canvas.style.cursor = 'default'; + } + + + canvas.onmousedown = function (e) + { + var obj = e.target.__object__; + var id = obj.id; + var canvas = obj.canvas; + var context = obj.context; + var coords = RGraph.getMouseXY(e); + var segment = RGraph.getSegment(e, 5); + + if (segment && segment.length && !RGraph.Registry.Get('chart.adjusting.rose.' + id)) { + var x = Math.abs(coords[0] - obj.centerx); + var y = Math.abs(coords[1] - obj.centery); + + var a = Math.atan(y / x) * (180 / Math.PI); // a is now in DEGREES + + // Account for the correct quadrant + if (coords[0] >= obj.centerx && coords[1] < obj.centery) { + a = 90 - a; + a += 270; + } else if (coords[0] >= obj.centerx && coords[1] >= obj.centery) { + // Nada + } else if (coords[0] < obj.centerx && coords[1] >= obj.centery) { + a = 90 - a; + a += 90; + } else if (coords[0] < obj.centerx && coords[1] < obj.centery) { + a += 180; + } + + var hyp = Math.abs(y / Math.sin(a / 57.3)); + + if (hyp >= (segment[2] - 10) ) { + + /** + * Hide any currently shown tooltip + */ + if (RGraph.Registry.Get('chart.tooltip')) { + RGraph.Registry.Get('chart.tooltip').style.display = 'none'; + RGraph.Registry.Set('chart.tooltip', null); + } + + RGraph.Registry.Set('chart.adjusting.rose.' + id, segment); + + e.stopPropagation(); + } + } + } + + + canvas.onmouseup = function (e) + { + var obj = e.target.__object__; + var id = obj.id; + + if (RGraph.Registry.Get('chart.adjusting.rose.' + id)) { + + RGraph.Registry.Set('chart.adjusting.rose.' + id, null); + e.stopPropagation(); + + return false; + } + } + + + canvas.onmouseout = function (e) + { + canvas.onmouseup(e); + } + + /** + * Bar chart + */ + } else if (obj.type == 'bar') { + + // Stacked bar charts not supported + if (obj.Get('chart.grouping') == 'stacked') { + alert('[BAR] Adjusting stacked bar charts is not supported'); + return; + } + + + var canvas = obj.canvas; + var context = obj.context; + + + canvas.onmousemove = function (e) + { + var obj = e.target.__object__; + var id = obj.id; + var canvas = obj.canvas; + var context = obj.context; + var mouse = RGraph.getMouseXY(e); + var mousex = mouse[0]; + var mousey = mouse[1]; // mousey, mousey... + + // Loop through the coords to see if the mouse position is at the top of a bar + for (var i=0; i obj.coords[i][0] && mousex < (obj.coords[i][0] + obj.coords[i][2])) { + + // Change the mouse pointer + if (mousey > (obj.coords[i][1] - 5) && mousey < (obj.coords[i][1] + 5)) { + canvas.style.cursor = 'ns-resize'; + } else { + canvas.style.cursor = 'default'; + } + + var idx = RGraph.Registry.Get('chart.adjusting.bar.' + id) + + if (typeof(idx) == 'number') { + var newheight = obj.grapharea - (mousey - obj.Get('chart.gutter')); + var newvalue = (newheight / obj.grapharea) * obj.max; + + // Top and bottom boundaries + if (newvalue > obj.max) newvalue = obj.max; + if (newvalue < 0) newvalue = 0; + + ///////////////// This was fun to work out... ///////////////// + for (var j=0, index=0; j obj.coords[i][0] && mousex < (obj.coords[i][0] + obj.coords[i][2]) + + ) { + + obj.Set('chart.ymax', obj.max); + RGraph.Registry.Set('chart.adjusting.bar.' + id, i); + canvas.onmousemove(e); + } + } + } + + + + canvas.onmouseup = function (e) + { + var id = e.target.__object__.id; + + RGraph.Registry.Set('chart.adjusting.bar.' + id, null); + } + + + canvas.onmouseout = function (e) + { + canvas.onmouseup(e); + } + + + /** + * The Tradar chart + */ + } else if (obj.type == 'tradar') { + + + var canvas = obj.canvas; + var context = obj.context; + + + canvas.onmousemove = function (e) + { + var obj = e.target.__object__; + var id = obj.id; + var canvas = obj.canvas; + var context = obj.context; + var mouseDown = RGraph.Registry.Get('chart.adjusting.tradar.' + id); + var mouseCoords = RGraph.getMouseXY(e); + + + if (mouseDown) { + + canvas.style.cursor = 'move'; + + var dx = mouseCoords[0] - obj.centerx; + var dy = mouseCoords[1] - obj.centery; + var hyp = Math.sqrt((dx * dx) + (dy * dy)); + + var newvalue = (hyp / (obj.size / 2)) * obj.max; + + newvalue = Math.min(obj.max, newvalue); + newvalue = Math.max(0, newvalue); + + /** + * Only redraw the graph if the mouse is in the same quadrant as the point + */ + if ( (dx >= 0 ? true : false) == mouseDown[1] && (dy >= 0 ? true : false) == mouseDown[2]) { + obj.data[mouseDown[0]] = newvalue; + RGraph.Clear(canvas); + obj.Draw(); + + /** + * Fire the onadjust event + */ + RGraph.FireCustomEvent(obj, 'onadjust'); + } + + + } else { + + // Determine if the mouse is near a point, and if so, change the pointer + for (var i=0; i obj.centerx, obj.coords[i][1] > obj.centery]); + return; + } + } + + canvas.style.cursor = 'default'; + } + + + canvas.onmouseup = function (e) + { + RGraph.Registry.Set('chart.adjusting.tradar.' + e.target.id, null); + canvas.style.cursor = 'default'; + } + + + canvas.onmouseout = function (e) + { + canvas.onmouseup(e); + } + } + } + + + /** + * Returns 1 or -1 depening on whether the given number is positive or negative. + * Zero is considered positive. + * + * @param int num The number + * @return int 1 if the number is positive or zero, -1 if it's negative + */ + //RGraph.getSign = function (num) + //{ + // return num >= 0 ? 1 : -1; + //} \ No newline at end of file diff --git a/libraries/RGraph.common.annotate.js b/libraries/RGraph.common.annotate.js new file mode 100644 index 0000000..6cb5e15 --- /dev/null +++ b/libraries/RGraph.common.annotate.js @@ -0,0 +1,317 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'}; + + + /** + * The function which controls the annotate feature + * + * @param object obj The graph object + */ + RGraph.Annotate = function (obj) + { + /** + * This installs some event handlers + */ + if (obj.Get('chart.annotatable')) { + + var canvas = obj.canvas; + var context = obj.context; + + /** + * Capture the mouse events so we can set whther the mouse is down or not + */ + canvas.onmousedown = function (e) + { + if (e.button == 0) { + + e.target.__object__.Set('chart.mousedown', true); + + // Get the context + var obj = e.target.__object__; + var context = obj.canvas.getContext('2d'); + + // Don't want any "joining" lines or colour "bleeding" + context.beginPath(); + + // Accommodate Chrome + var coords = RGraph.getMouseXY(e); + var x = coords[0]; + var y = coords[1]; + + // Clear the annotation recording + RGraph.Registry.Set('annotate.actions', [obj.Get('chart.annotate.color')]); + + context.strokeStyle = obj.Get('chart.annotate.color'); + + context.moveTo(x, y); + + // Set the lineWidth + context.lineWidth = 1; + + RGraph.Registry.Set('started.annotating', false); + + /** + * Fire the onannotatestart event + */ + RGraph.FireCustomEvent(obj, 'onannotatestart'); + } + + return false; + } + + /** + * This cancels annotating for ALL canvases + */ + window.onmouseup = function (e) + { + var tags = document.getElementsByTagName('canvas'); + + for (var i=0; i 0 && window.localStorage) { + + var id = '__rgraph_annotations_' + e.target.id + '__'; + var annotations = window.localStorage[id] ? window.localStorage[id] + '|' : ''; + annotations += RGraph.Registry.Get('annotate.actions'); + + // Store the annotations information in HTML5 browser storage here + window.localStorage[id] = annotations; + } + + // Clear the recorded annotations + RGraph.Registry.Set('annotate.actions', []); + + /** + * Fire the annotate event + */ + RGraph.FireCustomEvent(e.target.__object__, 'onannotateend'); + } + + canvas.onmouseup = function (e) + { + //window.onmouseup(e); + } + + //canvas.onmouseout = window.onmouseup; + + /** + * The canvas onmousemove function + */ + canvas.onmousemove = function (e) + { + var e = RGraph.FixEventObject(e); + var obj = e.target.__object__; + var coords = RGraph.getMouseXY(e); + var x = coords[0]; + var y = coords[1]; + var gutter = obj.Get('chart.gutter'); + var width = canvas.width; + var height = canvas.height; + + obj.context.lineWidth = 1; + + // Don't allow annotating in the gutter + // + // CHANGED 20TH DECEMBER 2010 TO ALLOW ANNOTATING IN THE GUTTER + if (true) { + + canvas.style.cursor = 'crosshair'; + + if (obj.Get('chart.mousedown')) { + + // Special case for HBars and Gantts with their extra wide left gutter + if ( (obj.type != 'hbar' && obj.type != 'gantt') || x > (3 * gutter)) { + + /** + * This is here to stop annotating in the gutter + */ + if (RGraph.Registry.Get('started.annotating') == false) { + context.moveTo(x, y); + RGraph.Registry.Set('started.annotating', true) + } + + context.lineTo(x, y); + + RGraph.Registry.Set('annotate.actions', RGraph.Registry.Get('annotate.actions') + '|' + x + ',' + y); + + context.stroke(); + + /** + * Fire the annotate event + */ + RGraph.FireCustomEvent(obj, 'onannotate'); + } + } + + } else { + canvas.style.cursor = 'default'; + } + } + + RGraph.ReplayAnnotations(obj); + } + } + + + /** + * Shows the mini palette used for annotations + * + * @param object e The event object + */ + RGraph.Showpalette = function (e) + { + var isSafari = navigator.userAgent.indexOf('Safari') ? true : false; + + e = RGraph.FixEventObject(e); + + var canvas = e.target.parentNode.__canvas__; + var context = canvas.getContext('2d'); + var obj = canvas.__object__; + var div = document.createElement('DIV'); + var coords = RGraph.getMouseXY(e); + + div.__object__ = obj; // The graph object + div.className = 'RGraph_palette'; + div.style.position = 'absolute'; + div.style.backgroundColor = 'white'; + div.style.border = '1px solid black'; + div.style.left = 0; + div.style.top = 0; + div.style.padding = '3px'; + div.style.paddingBottom = 0; + div.style.paddingRight = 0; + div.style.opacity = 0; + div.style.boxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; + div.style.WebkitBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; + div.style.MozBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; + div.style.filter = 'progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135)'; + + var common_css = 'padding: 1px; display: inline; display: inline-block; width: 15px; height: 15px; margin-right: 3px; cursor: pointer;' + (isSafari ? 'margin-bottom: 3px' : ''); + var common_mouseover = ' onmouseover="this.style.border = \'1px black solid\'; this.style.padding = 0"'; + var common_mouseout = ' onmouseout="this.style.border = 0; this.style.padding = \'1px\'" '; + + var str = ''; + + var colors = ['red', 'blue', 'green', 'black', 'yellow', 'magenta', 'pink', 'cyan', 'purple', '#ddf', 'gray', '#36905c']; + + for (i=0; i '; + + // This makes the colours go across two levels + if (i == 5) { + str += '
'; + } + } + + div.innerHTML = str; + document.body.appendChild(div); + + /** + * Now the div has been added to the document, move it up and left and set the width and height + */ + div.style.width = (div.offsetWidth - (RGraph.isIE9up() ? 12 : 5)) + 'px'; + div.style.height = (div.offsetHeight - (RGraph.isIE9up() ? 13 : 5)) + 'px'; + div.style.left = Math.max(0, e.pageX - div.offsetWidth - 2) + 'px'; + div.style.top = (e.pageY - div.offsetHeight - 2) + 'px'; + + /** + * Store the palette div in the registry + */ + RGraph.Registry.Set('palette', div); + + setTimeout("RGraph.Registry.Get('palette').style.opacity = 0.2", 50); + setTimeout("RGraph.Registry.Get('palette').style.opacity = 0.4", 100); + setTimeout("RGraph.Registry.Get('palette').style.opacity = 0.6", 150); + setTimeout("RGraph.Registry.Get('palette').style.opacity = 0.8", 200); + setTimeout("RGraph.Registry.Get('palette').style.opacity = 1", 250); + + RGraph.HideContext(); + + window.onclick = function () + { + RGraph.HidePalette(); + } + + // Should this be here? Yes. This function is being used as an event handler. + e.stopPropagation(); + return false; + } + + + /** + * Clears any annotation data from global storage + * + * @param string id The ID of the canvas + */ + RGraph.ClearAnnotations = function (id) + { + if (window.localStorage && window.localStorage['__rgraph_annotations_' + id + '__'] && window.localStorage['__rgraph_annotations_' + id + '__'].length) { + window.localStorage['__rgraph_annotations_' + id + '__'] = []; + } + } + + + /** + * Replays stored annotations + * + * @param object obj The graph object + */ + RGraph.ReplayAnnotations = function (obj) + { + // Check for support + if (!window.localStorage) { + return; + } + + var context = obj.context; + var annotations = window.localStorage['__rgraph_annotations_' + obj.id + '__']; + var i, len, move, coords; + + context.beginPath(); + context.lineWidth = 2; + + if (annotations && annotations.length) { + annotations = annotations.split('|'); + } else { + return; + } + + for (i=0, len=annotations.length; i document.body.offsetWidth) { + x -= div.offsetWidth; + } + + // Reposition the menu (now we have the real offsetWidth) + div.style.left = x + 'px'; + div.style.top = y + 'px'; + + /** + * Do a little fade in effect + */ + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu')) obj.style.opacity = 0.2", 50); + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu')) obj.style.opacity = 0.4", 100); + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu')) obj.style.opacity = 0.6", 150); + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu')) obj.style.opacity = 0.8", 200); + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu')) obj.style.opacity = 1", 250); + + // The fade in effect on the left gray bar + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu.bg')) obj.style.opacity = 0.2", 50); + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu.bg')) obj.style.opacity = 0.4", 100); + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu.bg')) obj.style.opacity = 0.6", 150); + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu.bg')) obj.style.opacity = 0.8", 200); + setTimeout("if (obj = RGraph.Registry.Get('chart.contextmenu.bg')) obj.style.opacity = 1", 250); + + // Store the context menu in the registry + RGraph.Registry.Set('chart.contextmenu', div); + RGraph.Registry.Set('chart.contextmenu.bg', bg); + RGraph.Registry.Get('chart.contextmenu').oncontextmenu = function () {return false;}; + RGraph.Registry.Get('chart.contextmenu.bg').oncontextmenu = function () {return false;}; + + /** + * Install the event handlers that hide the context menu + */ + canvas.addEventListener('click', function () {RGraph.HideContext();}, false); + + window.onclick = function (e) + { + RGraph.HideContext(); + + // Removed on 3/7/10 - stops a bug in conjunction with annotating which presents itself on the Rscatter + //RGraph.Redraw(); + + // Fire the onclick event again + if (e.target.onclick && e.button == 0) { + e.target.onclick(e); + } + } + + window.onresize = function () {RGraph.HideContext();} + + e.stopPropagation(); + + /** + * Fire the (RGraph) oncontextmenu event + */ + RGraph.FireCustomEvent(canvas.__object__, 'oncontextmenu'); + + return false; + } + + + /** + * Hides the context menu if it's currently visible + */ + RGraph.HideContext = function () + { + var cm = RGraph.Registry.Get('chart.contextmenu'); + var cmbg = RGraph.Registry.Get('chart.contextmenu.bg'); + + //Hide any submenu currently being displayed + RGraph.HideContextSubmenu(); + + if (cm) { + cm.parentNode.removeChild(cm); + cmbg.parentNode.removeChild(cmbg); + + cm.style.visibility = 'hidden'; + cm.style.display = 'none'; + RGraph.Registry.Set('chart.contextmenu', null); + + cmbg.style.visibility = 'hidden'; + cmbg.style.display = 'none'; + RGraph.Registry.Set('chart.contextmenu.bg', null); + } + } + + + /** + * Hides the context menus SUBMENU if it's currently visible + */ + RGraph.HideContextSubmenu = function () + { + var sub = RGraph.Registry.Get('chart.contextmenu.submenu'); + + if (sub) { + sub.style.visibility = 'none'; + sub.style.display = 'none'; + RGraph.Registry.Set('chart.contextmenu.submenu', null); + } + } + + + /** + * Shows the context menu after making a few checks - not opera (doesn't support oncontextmenu, + * not safari (tempermentality), not chrome (hmmm) + */ + RGraph.ShowContext = function (obj) + { + RGraph.HidePalette(); + + if (obj.Get('chart.contextmenu') && obj.Get('chart.contextmenu').length) { + + var isOpera = navigator.userAgent.indexOf('Opera') >= 0; + var isSafari = navigator.userAgent.indexOf('Safari') >= 0; + var isChrome = navigator.userAgent.indexOf('Chrome') >= 0; + var isMacFirefox = navigator.userAgent.indexOf('Firefox') > 0 && navigator.userAgent.indexOf('Mac') > 0; + var isIE9 = navigator.userAgent.indexOf('MSIE 9') >= 0; + + if (((!isOpera && !isSafari) || isChrome) && !isMacFirefox && !isIE9) { + + obj.canvas.oncontextmenu = function (e) + { + e = RGraph.FixEventObject(e); + + if (e.ctrlKey) return true; + + RGraph.Contextmenu(obj.canvas, obj.Get('chart.contextmenu'), e); + + return false; + } + + // Accomodate Opera, IE9 and Safari - use double click event + } else { + + obj.canvas.addEventListener('dblclick', function (e) + { + if (e.ctrlKey) return true; + + if (!RGraph.Registry.Get('chart.contextmenu')) { + RGraph.Contextmenu(obj.canvas, obj.Get('chart.contextmenu'), e); + } + }, false); + } + } + } + + + /** + * This draws a submenu should it be necessary + * + * @param object obj The graph object + * @param object menu The context menu + */ + RGraph.Contextmenu_submenu = function (obj, menuitems, parentMenuItem) + { + RGraph.HideContextSubmenu(); + + var canvas = obj.canvas; + var context = obj.context; + var menu = parentMenuItem.parentNode; + + var subMenu = document.createElement('DIV'); + subMenu.style.position = 'absolute'; + subMenu.style.width = '100px'; + subMenu.style.top = menu.offsetTop + parentMenuItem.offsetTop + 'px'; + subMenu.style.left = (menu.offsetLeft + menu.offsetWidth - (document.all ? 9 : 0)) + 'px'; + subMenu.style.backgroundColor = 'white'; + subMenu.style.border = '1px solid black'; + subMenu.className = 'RGraph_contextmenu'; + subMenu.__contextmenu__ = menu; + subMenu.style.boxShadow = '3px 3px 3px rgba(96,96,96,0.5)'; + subMenu.style.MozBoxShadow = '3px 3px 3px rgba(96,96,96,0.5)'; + subMenu.style.WebkitBoxShadow = '3px 3px 3px rgba(96,96,96,0.5)'; + subMenu.style.filter = 'progid:DXImageTransform.Microsoft.Shadow(color=#aaaaaa,direction=135)'; + document.body.appendChild(subMenu); + + for (var i=0; iURL:'; + div.innerHTML += '
' + + + + /** + * Create the image rendition of the graph + */ + var img = document.createElement('IMG'); + RGraph.Registry.Set('chart.png', img); + img.__canvas__ = canvas; + img.__object__ = obj; + img.id = '__rgraph_image_img__'; + img.className = 'RGraph_png'; + + img.src = canvas.toDataURL(); + + div.appendChild(img); + + setTimeout(function () {document.getElementById("__rgraph_dataurl__").select();}, 50); + + window.addEventListener('resize', function (e){var img = RGraph.Registry.Get('chart.png');img.style.left = (document.body.clientWidth / 2) - (img.width / 2) + 'px';}, false); + + bg.onclick = function (e) + { + var div = document.getElementById("__rgraph_image_div__"); + var bg = document.getElementById("__rgraph_image_bg__"); + + if (div) { + div.style.opacity = 0; + + div.parentNode.removeChild(div); + + div.id = ''; + div.style.display = 'none'; + div = null; + } + + if (bg) { + bg.style.opacity = 0; + + bg.id = ''; + bg.style.display = 'none'; + bg = null; + } + } + + window.addEventListener('resize', function (e) {bg.onclick(e);}, false) + + /** + * This sets the image as a global variable, circumventing repeated calls to document.getElementById() + */ + __rgraph_image_bg__ = bg; + __rgraph_image_div__ = div; + + + setTimeout('__rgraph_image_div__.style.opacity = 0.2', 50); + setTimeout('__rgraph_image_div__.style.opacity = 0.4', 100); + setTimeout('__rgraph_image_div__.style.opacity = 0.6', 150); + setTimeout('__rgraph_image_div__.style.opacity = 0.8', 200); + setTimeout('__rgraph_image_div__.style.opacity = 1', 250); + + setTimeout('__rgraph_image_bg__.style.opacity = 0.1', 50); + setTimeout('__rgraph_image_bg__.style.opacity = 0.2', 100); + setTimeout('__rgraph_image_bg__.style.opacity = 0.3', 150); + setTimeout('__rgraph_image_bg__.style.opacity = 0.4', 200); + setTimeout('__rgraph_image_bg__.style.opacity = 0.5', 250); + + + + img.onclick = function (e) + { + if (e.stopPropagation) e.stopPropagation(); + else event.cancelBubble = true; + } + + if (event && event.stopPropagation) { + event.stopPropagation(); + } + } \ No newline at end of file diff --git a/libraries/RGraph.common.core.js b/libraries/RGraph.common.core.js new file mode 100644 index 0000000..71ca938 --- /dev/null +++ b/libraries/RGraph.common.core.js @@ -0,0 +1,2454 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + /** + * Initialise the various objects + */ + if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'}; + + + RGraph.Registry = {}; + RGraph.Registry.store = []; + RGraph.Registry.store['chart.event.handlers'] = []; + RGraph.background = {}; + RGraph.objects = []; + RGraph.Resizing = {}; + RGraph.events = []; + + + + /** + * Returns five values which are used as a nice scale + * + * @param max int The maximum value of the graph + * @param obj object The graph object + * @return array An appropriate scale + */ + RGraph.getScale = function (max, obj) + { + /** + * Special case for 0 + */ + if (max == 0) { + return ['0.2', '0.4', '0.6', '0.8', '1.0']; + } + + var original_max = max; + + /** + * Manually do decimals + */ + if (max <= 1) { + if (max > 0.5) { + return [0.2,0.4,0.6,0.8, Number(1).toFixed(1)]; + + } else if (max >= 0.1) { + return obj.Get('chart.scale.round') ? [0.2,0.4,0.6,0.8,1] : [0.1,0.2,0.3,0.4,0.5]; + + } else { + + var tmp = max; + var exp = 0; + + while (tmp < 1.01) { + exp += 1; + tmp *= 10; + } + + var ret = ['2e-' + exp, '4e-' + exp, '6e-' + exp, '8e-' + exp, '10e-' + exp]; + + + if (max <= ('5e-' + exp)) { + ret = ['1e-' + exp, '2e-' + exp, '3e-' + exp, '4e-' + exp, '5e-' + exp]; + } + + return ret; + } + } + + // Take off any decimals + if (String(max).indexOf('.') > 0) { + max = String(max).replace(/\.\d+$/, ''); + } + + var interval = Math.pow(10, Number(String(Number(max)).length - 1)); + var topValue = interval; + + while (topValue < max) { + topValue += (interval / 2); + } + + // Handles cases where the max is (for example) 50.5 + if (Number(original_max) > Number(topValue)) { + topValue += (interval / 2); + } + + // Custom if the max is greater than 5 and less than 10 + if (max < 10) { + topValue = (Number(original_max) <= 5 ? 5 : 10); + } + + /** + * Added 02/11/2010 to create "nicer" scales + */ + if (obj && typeof(obj.Get('chart.scale.round')) == 'boolean' && obj.Get('chart.scale.round')) { + topValue = 10 * interval; + } + + return [topValue * 0.2, topValue * 0.4, topValue * 0.6, topValue * 0.8, topValue]; + } + + + /** + * Returns the maximum value which is in an array + * + * @param array arr The array + * @param int Whether to ignore signs (ie negative/positive) + * @return int The maximum value in the array + */ + RGraph.array_max = function (arr) + { + var max = null; + + for (var i=0; i ' + RGraph.pr(obj[i], true, indent + ' ') + '\n'; + } + + var str = str + indent + ')'; + break; + + case 'function': + str += obj; + break; + + case 'boolean': + str += 'Boolean: ' + (obj ? 'true' : 'false'); + break; + } + + /** + * Finished, now either return if we're in a recursed call, or alert() + * if we're not. + */ + if (arguments[1]) { + return str; + } else { + alert(str); + } + } + + + /** + * The RGraph registry Set() function + * + * @param string name The name of the key + * @param mixed value The value to set + * @return mixed Returns the same value as you pass it + */ + RGraph.Registry.Set = function (name, value) + { + // Store the setting + RGraph.Registry.store[name] = value; + + // Don't really need to do this, but ho-hum + return value; + } + + + /** + * The RGraph registry Get() function + * + * @param string name The name of the particular setting to fetch + * @return mixed The value if exists, null otherwise + */ + RGraph.Registry.Get = function (name) + { + //return RGraph.Registry.store[name] == null ? null : RGraph.Registry.store[name]; + return RGraph.Registry.store[name]; + } + + + /** + * This function draws the background for the bar chart, line chart and scatter chart. + * + * @param object obj The graph object + */ + RGraph.background.Draw = function (obj) + { + var canvas = obj.canvas; + var context = obj.context; + var height = 0; + var gutter = obj.Get('chart.gutter'); + var variant = obj.Get('chart.variant'); + + context.fillStyle = obj.Get('chart.text.color'); + + // If it's a bar and 3D variant, translate + if (variant == '3d') { + context.save(); + context.translate(10, -5); + } + + // X axis title + if (typeof(obj.Get('chart.title.xaxis')) == 'string' && obj.Get('chart.title.xaxis').length) { + + var size = obj.Get('chart.text.size'); + var font = obj.Get('chart.text.font'); + + context.beginPath(); + RGraph.Text(context, font, size + 2, obj.canvas.width / 2, canvas.height - (gutter * obj.Get('chart.title.xaxis.pos')), obj.Get('chart.title.xaxis'), 'center', 'center', false, false, false, true); + context.fill(); + } + + // Y axis title + if (typeof(obj.Get('chart.title.yaxis')) == 'string' && obj.Get('chart.title.yaxis').length) { + + var size = obj.Get('chart.text.size'); + var font = obj.Get('chart.text.font'); + + context.beginPath(); + RGraph.Text(context, font, size + 2, gutter * obj.Get('chart.title.yaxis.pos'), canvas.height / 2, obj.Get('chart.title.yaxis'), 'center', 'center', false, 270, false, true); + context.fill(); + } + + obj.context.beginPath(); + + // Draw the horizontal bars + context.fillStyle = obj.Get('chart.background.barcolor1'); + height = (obj.canvas.height - obj.Get('chart.gutter')); + + for (var i=gutter; i < height ; i+=80) { + obj.context.fillRect(gutter, i, obj.canvas.width - (gutter * 2), Math.min(40, obj.canvas.height - gutter - i) ); + } + + context.fillStyle = obj.Get('chart.background.barcolor2'); + height = (obj.canvas.height - gutter); + + for (var i= (40 + gutter); i < height; i+=80) { + obj.context.fillRect(gutter, i, obj.canvas.width - (gutter * 2), i + 40 > (obj.canvas.height - gutter) ? obj.canvas.height - (gutter + i) : 40); + } + + context.stroke(); + + + // Draw the background grid + if (obj.Get('chart.background.grid')) { + + // If autofit is specified, use the .numhlines and .numvlines along with the width to work + // out the hsize and vsize + if (obj.Get('chart.background.grid.autofit')) { + var vsize = (canvas.width - (2 * obj.Get('chart.gutter')) - (obj.type == 'gantt' ? 2 * obj.Get('chart.gutter') : 0)) / obj.Get('chart.background.grid.autofit.numvlines'); + var hsize = (canvas.height - (2 * obj.Get('chart.gutter'))) / obj.Get('chart.background.grid.autofit.numhlines'); + + obj.Set('chart.background.grid.vsize', vsize); + obj.Set('chart.background.grid.hsize', hsize); + } + + context.beginPath(); + context.lineWidth = obj.Get('chart.background.grid.width') ? obj.Get('chart.background.grid.width') : 1; + context.strokeStyle = obj.Get('chart.background.grid.color'); + + // Draw the horizontal lines + if (obj.Get('chart.background.grid.hlines')) { + height = (canvas.height - gutter) + for (y=gutter; y < height; y+=obj.Get('chart.background.grid.hsize')) { + context.moveTo(gutter, y); + context.lineTo(canvas.width - gutter, y); + } + } + + if (obj.Get('chart.background.grid.vlines')) { + // Draw the vertical lines + var width = (canvas.width - gutter) + for (x=gutter + (obj.type == 'gantt' ? (2 * gutter) : 0); x<=width; x+=obj.Get('chart.background.grid.vsize')) { + context.moveTo(x, gutter); + context.lineTo(x, obj.canvas.height - gutter); + } + } + + if (obj.Get('chart.background.grid.border')) { + // Make sure a rectangle, the same colour as the grid goes around the graph + context.strokeStyle = obj.Get('chart.background.grid.color'); + context.strokeRect(gutter, gutter, canvas.width - (2 * gutter), canvas.height - (2 * gutter)); + } + } + + context.stroke(); + + // If it's a bar and 3D variant, translate + if (variant == '3d') { + context.restore(); + } + + // Draw the title if one is set + if ( typeof(obj.Get('chart.title')) == 'string') { + + if (obj.type == 'gantt') { + gutter /= 2; + } + + RGraph.DrawTitle(canvas, obj.Get('chart.title'), gutter, null, obj.Get('chart.text.size') + 2); + } + + context.stroke(); + } + + + /** + * Returns the day number for a particular date. Eg 1st February would be 32 + * + * @param object obj A date object + * @return int The day number of the given date + */ + RGraph.GetDays = function (obj) + { + var year = obj.getFullYear(); + var days = obj.getDate(); + var month = obj.getMonth(); + + if (month == 0) return days; + if (month >= 1) days += 31; + if (month >= 2) days += 28; + + // Leap years. Crude, but if this code is still being used + // when it stops working, then you have my permission to shoot + // me. Oh, you won't be able to - I'll be dead... + if (year >= 2008 && year % 4 == 0) days += 1; + + if (month >= 3) days += 31; + if (month >= 4) days += 30; + if (month >= 5) days += 31; + if (month >= 6) days += 30; + if (month >= 7) days += 31; + if (month >= 8) days += 31; + if (month >= 9) days += 30; + if (month >= 10) days += 31; + if (month >= 11) days += 30; + + return days; + } + + + + + + + + + + + + + + + + /** + * Draws the graph key (used by various graphs) + * + * @param object obj The graph object + * @param array key An array of the texts to be listed in the key + * @param colors An array of the colors to be used + */ + RGraph.DrawKey = function (obj, key, colors) + { + var canvas = obj.canvas; + var context = obj.context; + context.lineWidth = 1; + + context.beginPath(); + + /** + * Key positioned in the gutter + */ + var keypos = obj.Get('chart.key.position'); + var textsize = obj.Get('chart.text.size'); + var gutter = obj.Get('chart.gutter'); + + /** + * Change the older chart.key.vpos to chart.key.position.y + */ + if (typeof(obj.Get('chart.key.vpos')) == 'number') { + obj.Set('chart.key.position.y', obj.Get('chart.key.vpos') * gutter); + } + + if (keypos && keypos == 'gutter') { + + RGraph.DrawKey_gutter(obj, key, colors); + + + /** + * In-graph style key + */ + } else if (keypos && keypos == 'graph') { + + RGraph.DrawKey_graph(obj, key, colors); + + } else { + alert('[COMMON] (' + obj.id + ') Unknown key position: ' + keypos); + } + } + + + + + + /** + * This does the actual drawing of the key when it's in the graph + * + * @param object obj The graph object + * @param array key The key items to draw + * @param array colors An aray of colors that the key will use + */ + RGraph.DrawKey_graph = function (obj, key, colors) + { + var canvas = obj.canvas; + var context = obj.context; + var text_size = typeof(obj.Get('chart.key.text.size')) == 'number' ? obj.Get('chart.key.text.size') : obj.Get('chart.text.size'); + var text_font = obj.Get('chart.text.font'); + var gutter = obj.Get('chart.gutter'); + var hpos = obj.Get('chart.yaxispos') == 'right' ? gutter + 10 : canvas.width - gutter - 10; + var vpos = gutter + 10; + var title = obj.Get('chart.title'); + var blob_size = text_size; // The blob of color + var hmargin = 8; // This is the size of the gaps between the blob of color and the text + var vmargin = 4; // This is the vertical margin of the key + var fillstyle = obj.Get('chart.key.background'); + var strokestyle = 'black'; + var height = 0; + var width = 0; + + + // Need to set this so that measuring the text works out OK + context.font = text_size + 'pt ' + obj.Get('chart.text.font'); + + // Work out the longest bit of text + for (i=0; i=0; i--) { + var j = Number(i) + 1; + + // Draw the blob of color + if (obj.Get('chart.key.color.shape') == 'circle') { + context.beginPath(); + context.strokeStyle = 'rgba(0,0,0,0)'; + context.fillStyle = colors[i]; + context.arc(hpos + 5 + (blob_size / 2), vpos + (5 * j) + (text_size * j) - text_size + (blob_size / 2), blob_size / 2, 0, 6.26, 0); + context.fill(); + + } else if (obj.Get('chart.key.color.shape') == 'line') { + context.beginPath(); + context.strokeStyle = colors[i]; + context.moveTo(hpos + 5, vpos + (5 * j) + (text_size * j) - text_size + (blob_size / 2)); + context.lineTo(hpos + blob_size + 5, vpos + (5 * j) + (text_size * j) - text_size + (blob_size / 2)); + context.stroke(); + + } else { + context.fillStyle = colors[i]; + context.fillRect(hpos + 5, vpos + (5 * j) + (text_size * j) - text_size, text_size, text_size + 1); + } + + context.beginPath(); + + context.fillStyle = 'black'; + + RGraph.Text(context, + text_font, + text_size, + hpos + blob_size + 5 + 5, + vpos + (5 * j) + (text_size * j), + key[i]); + } + context.fill(); + } + + + + + + + /** + * This does the actual drawing of the key when it's in the gutter + * + * @param object obj The graph object + * @param array key The key items to draw + * @param array colors An aray of colors that the key will use + */ + RGraph.DrawKey_gutter = function (obj, key, colors) + { + var canvas = obj.canvas; + var context = obj.context; + var text_size = typeof(obj.Get('chart.key.text.size')) == 'number' ? obj.Get('chart.key.text.size') : obj.Get('chart.text.size'); + var text_font = obj.Get('chart.text.font'); + var gutter = obj.Get('chart.gutter'); + var hpos = canvas.width / 2; + var vpos = (gutter / 2) - 5; + var title = obj.Get('chart.title'); + var blob_size = text_size; // The blob of color + var hmargin = 8; // This is the size of the gaps between the blob of color and the text + var vmargin = 4; // This is the vertical margin of the key + var fillstyle = obj.Get('chart.key.background'); + var strokestyle = 'black'; + var length = 0; + + + + // Need to work out the length of the key first + context.font = text_size + 'pt ' + text_font; + for (i=0; i=0; i--) { + newarr.push(arr[i]); + } + + return newarr; + } + + + /** + * Formats a number with thousand seperators so it's easier to read + * + * @param integer num The number to format + * @param string The (optional) string to prepend to the string + * @param string The (optional) string to ap + * pend to the string + * @return string The formatted number + */ + RGraph.number_format = function (obj, num) + { + var i; + var prepend = arguments[2] ? String(arguments[2]) : ''; + var append = arguments[3] ? String(arguments[3]) : ''; + var output = ''; + var decimal = ''; + var decimal_seperator = obj.Get('chart.scale.point') ? obj.Get('chart.scale.point') : '.'; + var thousand_seperator = obj.Get('chart.scale.thousand') ? obj.Get('chart.scale.thousand') : ','; + RegExp.$1 = ''; + var i,j; + + // Ignore the preformatted version of "1e-2" + if (String(num).indexOf('e') > 0) { + return String(prepend + String(num) + append); + } + + // We need then number as a string + num = String(num); + + // Take off the decimal part - we re-append it later + if (num.indexOf('.') > 0) { + num = num.replace(/\.(.*)/, ''); + decimal = RegExp.$1; + } + + // Thousand seperator + //var seperator = arguments[1] ? String(arguments[1]) : ','; + var seperator = thousand_seperator; + + /** + * Work backwards adding the thousand seperators + */ + var foundPoint; + for (i=(num.length - 1),j=0; i>=0; j++,i--) { + var character = num.charAt(i); + + if ( j % 3 == 0 && j != 0) { + output += seperator; + } + + /** + * Build the output + */ + output += character; + } + + /** + * Now need to reverse the string + */ + var rev = output; + output = ''; + for (i=(rev.length - 1); i>=0; i--) { + output += rev.charAt(i); + } + + // Tidy up + output = output.replace(/^-,/, '-'); + + // Reappend the decimal + if (decimal.length) { + output = output + decimal_seperator + decimal; + decimal = ''; + RegExp.$1 = ''; + } + + // Minor bugette + if (output.charAt(0) == '-') { + output *= -1; + prepend = '-' + prepend; + } + + return prepend + output + append; + } + + + /** + * Draws horizontal coloured bars on something like the bar, line or scatter + */ + RGraph.DrawBars = function (obj) + { + var hbars = obj.Get('chart.background.hbars'); + + /** + * Draws a horizontal bar + */ + obj.context.beginPath(); + + for (i=0; i obj.max) { + hbars[i][1] = obj.max - hbars[i][0]; + } + + + // If height is negative, and the abs() value is greater than .max, use a negative max instead + if (Math.abs(hbars[i][1]) > obj.max) { + hbars[i][1] = -1 * obj.max; + } + + + // If start point is greater than max, change it to max + if (Math.abs(hbars[i][0]) > obj.max) { + hbars[i][0] = obj.max; + } + + // If start point plus height is less than negative max, use the negative max plus the start point + if (hbars[i][0] + hbars[i][1] < (-1 * obj.max) ) { + hbars[i][1] = -1 * (obj.max + hbars[i][0]); + } + + // If the X axis is at the bottom, and a negative max is given, warn the user + if (obj.Get('chart.xaxispos') == 'bottom' && (hbars[i][0] < 0 || (hbars[i][1] + hbars[i][1] < 0)) ) { + alert('[' + obj.type.toUpperCase() + ' (ID: ' + obj.id + ') BACKGROUND HBARS] You have a negative value in one of your background hbars values, whilst the X axis is in the center'); + } + + var ystart = (obj.grapharea - ((hbars[i][0] / obj.max) * obj.grapharea)); + var height = (Math.min(hbars[i][1], obj.max - hbars[i][0]) / obj.max) * obj.grapharea; + + // Account for the X axis being in the center + if (obj.Get('chart.xaxispos') == 'center') { + ystart /= 2; + height /= 2; + } + + ystart += obj.Get('chart.gutter') + + var x = obj.Get('chart.gutter'); + var y = ystart - height; + var w = obj.canvas.width - (2 * obj.Get('chart.gutter')); + var h = height; + + // Accommodate Opera :-/ + if (navigator.userAgent.indexOf('Opera') != -1 && obj.Get('chart.xaxispos') == 'center' && h < 0) { + h *= -1; + y = y - h; + } + + obj.context.fillStyle = hbars[i][2]; + obj.context.fillRect(x, y, w, h); + } + + obj.context.fill(); + } + + + /** + * Draws in-graph labels. + * + * @param object obj The graph object + */ + RGraph.DrawInGraphLabels = function (obj) + { + var canvas = obj.canvas; + var context = obj.context; + var labels = obj.Get('chart.labels.ingraph'); + var labels_processed = []; + + // Defaults + var fgcolor = 'black'; + var bgcolor = 'white'; + var direction = 1; + + if (!labels) { + return; + } + + /** + * Preprocess the labels array. Numbers are expanded + */ + for (var i=0; i 0) { + + for (var i=0; i 0) { + var x = (obj.type == 'bar' ? coords[0] + (coords[2] / 2) : coords[0]); + var y = (obj.type == 'bar' ? coords[1] + (coords[3] / 2) : coords[1]); + var length = typeof(labels_processed[i][4]) == 'number' ? labels_processed[i][4] : 25; + + context.beginPath(); + context.fillStyle = 'black'; + context.strokeStyle = 'black'; + + + if (obj.type == 'bar') { + + if (obj.Get('chart.variant') == 'dot') { + context.moveTo(x, obj.coords[i][1] - 5); + context.lineTo(x, obj.coords[i][1] - 5 - length); + + var text_x = x; + var text_y = obj.coords[i][1] - 5 - length; + + } else if (obj.Get('chart.variant') == 'arrow') { + context.moveTo(x, obj.coords[i][1] - 5); + context.lineTo(x, obj.coords[i][1] - 5 - length); + + var text_x = x; + var text_y = obj.coords[i][1] - 5 - length; + + } else { + + context.arc(x, y, 2.5, 0, 6.28, 0); + context.moveTo(x, y); + context.lineTo(x, y - length); + + var text_x = x; + var text_y = y - length; + } + + context.stroke(); + context.fill(); + + + } else if (obj.type == 'line') { + + if ( + typeof(labels_processed[i]) == 'object' && + typeof(labels_processed[i][3]) == 'number' && + labels_processed[i][3] == -1 + ) { + + context.moveTo(x, y + 5); + context.lineTo(x, y + 5 + length); + + context.stroke(); + context.beginPath(); + + // This draws the arrow + context.moveTo(x, y + 5); + context.lineTo(x - 3, y + 10); + context.lineTo(x + 3, y + 10); + context.closePath(); + + var text_x = x; + var text_y = y + 5 + length; + + } else { + + var text_x = x; + var text_y = y - 5 - length; + + context.moveTo(x, y - 5); + context.lineTo(x, y - 5 - length); + + context.stroke(); + context.beginPath(); + + // This draws the arrow + context.moveTo(x, y - 5); + context.lineTo(x - 3, y - 10); + context.lineTo(x + 3, y - 10); + context.closePath(); + } + + context.fill(); + } + + + // Taken out on the 10th Nov 2010 - unnecessary + //var width = context.measureText(labels[i]).width; + + context.beginPath(); + + // Fore ground color + context.fillStyle = (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][1]) == 'string') ? labels_processed[i][1] : 'black'; + + RGraph.Text(context, + obj.Get('chart.text.font'), + obj.Get('chart.text.size'), + text_x, + text_y, + (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][0]) == 'string') ? labels_processed[i][0] : labels_processed[i], + 'bottom', + 'center', + true, + null, + (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][2]) == 'string') ? labels_processed[i][2] : 'white'); + context.fill(); + } + } + } + } + } + + + /** + * This function "fills in" key missing properties that various implementations lack + * + * @param object e The event object + */ + RGraph.FixEventObject = function (e) + { + if (RGraph.isIE8()) { + + var e = event; + + e.pageX = (event.clientX + document.body.scrollLeft); + e.pageY = (event.clientY + document.body.scrollTop); + e.target = event.srcElement; + + if (!document.body.scrollTop && document.documentElement.scrollTop) { + e.pageX += parseInt(document.documentElement.scrollLeft); + e.pageY += parseInt(document.documentElement.scrollTop); + } + } + + // This is mainly for FF which doesn't provide offsetX + if (typeof(e.offsetX) == 'undefined' && typeof(e.offsetY) == 'undefined') { + var coords = RGraph.getMouseXY(e); + e.offsetX = coords[0]; + e.offsetY = coords[1]; + } + + // Any browser that doesn't implement stopPropagation() (MSIE) + if (!e.stopPropagation) { + e.stopPropagation = function () {window.event.cancelBubble = true;} + } + + return e; + } + + + /** + * Draw crosshairs if enabled + * + * @param object obj The graph object (from which we can get the context and canvas as required) + */ + RGraph.DrawCrosshairs = function (obj) + { + if (obj.Get('chart.crosshairs')) { + var canvas = obj.canvas; + var context = obj.context; + + // 5th November 2010 - removed now that tooltips are DOM2 based. + //if (obj.Get('chart.tooltips') && obj.Get('chart.tooltips').length > 0) { + //alert('[' + obj.type.toUpperCase() + '] Sorry - you cannot have crosshairs enabled with tooltips! Turning off crosshairs...'); + //obj.Set('chart.crosshairs', false); + //return; + //} + + canvas.onmousemove = function (e) + { + var e = RGraph.FixEventObject(e); + var canvas = obj.canvas; + var context = obj.context; + var gutter = obj.Get('chart.gutter'); + var width = canvas.width; + var height = canvas.height; + var adjustments = obj.Get('chart.tooltips.coords.adjust'); + + var mouseCoords = RGraph.getMouseXY(e); + var x = mouseCoords[0]; + var y = mouseCoords[1]; + + if (typeof(adjustments) == 'object' && adjustments[0] && adjustments[1]) { + x = x - adjustments[0]; + y = y - adjustments[1]; + } + + RGraph.Clear(canvas); + obj.Draw(); + + if ( x >= gutter + && y >= gutter + && x <= (width - gutter) + && y <= (height - gutter) + ) { + + var linewidth = obj.Get('chart.crosshairs.linewidth'); + context.lineWidth = linewidth ? linewidth : 1; + + context.beginPath(); + context.strokeStyle = obj.Get('chart.crosshairs.color'); + + // Draw a top vertical line + context.moveTo(x, gutter); + context.lineTo(x, height - gutter); + + // Draw a horizontal line + context.moveTo(gutter, y); + context.lineTo(width - gutter, y); + + context.stroke(); + + /** + * Need to show the coords? + */ + if (obj.Get('chart.crosshairs.coords')) { + if (obj.type == 'scatter') { + + var xCoord = (((x - obj.Get('chart.gutter')) / (obj.canvas.width - (2 * obj.Get('chart.gutter')))) * (obj.Get('chart.xmax') - obj.Get('chart.xmin'))) + obj.Get('chart.xmin'); + xCoord = xCoord.toFixed(obj.Get('chart.scale.decimals')); + var yCoord = obj.max - (((y - obj.Get('chart.gutter')) / (obj.canvas.height - (2 * obj.Get('chart.gutter')))) * obj.max); + + if (obj.type == 'scatter' && obj.Get('chart.xaxispos') == 'center') { + yCoord = (yCoord - (obj.max / 2)) * 2; + } + + yCoord = yCoord.toFixed(obj.Get('chart.scale.decimals')); + var div = RGraph.Registry.Get('chart.coordinates.coords.div'); + var mouseCoords = RGraph.getMouseXY(e); + var canvasXY = RGraph.getCanvasXY(canvas); + + if (!div) { + + div = document.createElement('DIV'); + div.__object__ = obj; + div.style.position = 'absolute'; + div.style.backgroundColor = 'white'; + div.style.border = '1px solid black'; + div.style.fontFamily = 'Arial, Verdana, sans-serif'; + div.style.fontSize = '10pt' + div.style.padding = '2px'; + div.style.opacity = 1; + div.style.WebkitBorderRadius = '3px'; + div.style.borderRadius = '3px'; + div.style.MozBorderRadius = '3px'; + document.body.appendChild(div); + + RGraph.Registry.Set('chart.coordinates.coords.div', div); + } + + // Convert the X/Y pixel coords to correspond to the scale + + div.style.opacity = 1; + div.style.display = 'inline'; + + if (!obj.Get('chart.crosshairs.coords.fixed')) { + div.style.left = Math.max(2, (e.pageX - div.offsetWidth - 3)) + 'px'; + div.style.top = Math.max(2, (e.pageY - div.offsetHeight - 3)) + 'px'; + } else { + div.style.left = canvasXY[0] + obj.Get('chart.gutter') + 3 + 'px'; + div.style.top = canvasXY[1] + obj.Get('chart.gutter') + 3 + 'px'; + } + + div.innerHTML = '' + obj.Get('chart.crosshairs.coords.labels.x') + ': ' + xCoord + '
' + obj.Get('chart.crosshairs.coords.labels.y') + ': ' + yCoord; + + canvas.addEventListener('mouseout', RGraph.HideCrosshairCoords, false); + + } else { + alert('[RGRAPH] Showing crosshair coordinates is only supported on the Scatter chart'); + } + } + } else { + RGraph.HideCrosshairCoords(); + } + } + } + } + + /** + * Thisz function hides the crosshairs coordinates + */ + RGraph.HideCrosshairCoords = function () + { + var div = RGraph.Registry.Get('chart.coordinates.coords.div'); + + if ( div + && div.style.opacity == 1 + && div.__object__.Get('chart.crosshairs.coords.fadeout') + ) { + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.9;}, 50); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.8;}, 100); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.7;}, 150); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.6;}, 200); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.5;}, 250); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.4;}, 300); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.3;}, 350); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.2;}, 400); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.1;}, 450); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.opacity = 0;}, 500); + setTimeout(function() {RGraph.Registry.Get('chart.coordinates.coords.div').style.display = 'none';}, 550); + } + } + + + /** + * Trims the right hand side of a string. Removes SPACE, TAB + * CR and LF. + * + * @param string str The string to trim + */ + RGraph.rtrim = function (str) + { + return str.replace(/( |\n|\r|\t)+$/, ''); + } + + + /** + * Draws the3D axes/background + */ + RGraph.Draw3DAxes = function (obj) + { + var gutter = obj.Get('chart.gutter'); + var context = obj.context; + var canvas = obj.canvas; + + context.strokeStyle = '#aaa'; + context.fillStyle = '#ddd'; + + // Draw the vertical left side + context.beginPath(); + context.moveTo(gutter, gutter); + context.lineTo(gutter + 10, gutter - 5); + context.lineTo(gutter + 10, canvas.height - gutter - 5); + context.lineTo(gutter, canvas.height - gutter); + context.closePath(); + + context.stroke(); + context.fill(); + + // Draw the bottom floor + context.beginPath(); + context.moveTo(gutter, canvas.height - gutter); + context.lineTo(gutter + 10, canvas.height - gutter - 5); + context.lineTo(canvas.width - gutter + 10, canvas.height - gutter - 5); + context.lineTo(canvas.width - gutter, canvas.height - gutter); + context.closePath(); + + context.stroke(); + context.fill(); + } + + /** + * Turns off any shadow + * + * @param object obj The graph object + */ + RGraph.NoShadow = function (obj) + { + obj.context.shadowColor = 'rgba(0,0,0,0)'; + obj.context.shadowBlur = 0; + obj.context.shadowOffsetX = 0; + obj.context.shadowOffsetY = 0; + } + + + /** + * Sets the four shadow properties - a shortcut function + * + * @param object obj Your graph object + * @param string color The shadow color + * @param number offsetx The shadows X offset + * @param number offsety The shadows Y offset + * @param number blur The blurring effect applied to the shadow + */ + RGraph.SetShadow = function (obj, color, offsetx, offsety, blur) + { + obj.context.shadowColor = color; + obj.context.shadowOffsetX = offsetx; + obj.context.shadowOffsetY = offsety; + obj.context.shadowBlur = blur; + } + + + /** + * This function attempts to "fill in" missing functions from the canvas + * context object. Only two at the moment - measureText() nd fillText(). + * + * @param object context The canvas 2D context + */ + RGraph.OldBrowserCompat = function (context) + { + if (!context.measureText) { + + // This emulates the measureText() function + context.measureText = function (text) + { + var textObj = document.createElement('DIV'); + textObj.innerHTML = text; + textObj.style.backgroundColor = 'white'; + textObj.style.position = 'absolute'; + textObj.style.top = -100 + textObj.style.left = 0; + document.body.appendChild(textObj); + + var width = {width: textObj.offsetWidth}; + + textObj.style.display = 'none'; + + return width; + } + } + + if (!context.fillText) { + // This emulates the fillText() method + context.fillText = function (text, targetX, targetY) + { + return false; + } + } + + // If IE8, add addEventListener() + if (!context.canvas.addEventListener) { + window.addEventListener = function (ev, func, bubble) + { + return this.attachEvent('on' + ev, func); + } + + context.canvas.addEventListener = function (ev, func, bubble) + { + return this.attachEvent('on' + ev, func); + } + } + } + + + /** + * This function is for use with circular graph types, eg the Pie or Radar. Pass it your event object + * and it will pass you back the corresponding segment details as an array: + * + * [x, y, r, startAngle, endAngle] + * + * Angles are measured in degrees, and are measured from the "east" axis (just like the canvas). + * + * @param object e Your event object + */ + RGraph.getSegment = function (e) + { + RGraph.FixEventObject(e); + + // The optional arg provides a way of allowing some accuracy (pixels) + var accuracy = arguments[1] ? arguments[1] : 0; + + var obj = e.target.__object__; + var canvas = obj.canvas; + var context = obj.context; + var mouseCoords = RGraph.getMouseXY(e); + var x = mouseCoords[0] - obj.centerx; + var y = mouseCoords[1] - obj.centery; + var r = obj.radius; + var theta = Math.atan(y / x); // RADIANS + var hyp = y / Math.sin(theta); + var angles = obj.angles; + var ret = []; + var hyp = (hyp < 0) ? hyp + accuracy : hyp - accuracy; + + + // Put theta in DEGREES + theta *= 57.3 + + // hyp should not be greater than radius if it's a Rose chart + if (obj.type == 'rose') { + if ( (isNaN(hyp) && Math.abs(mouseCoords[0]) < (obj.centerx - r) ) + || (isNaN(hyp) && Math.abs(mouseCoords[0]) > (obj.centerx + r)) + || (!isNaN(hyp) && Math.abs(hyp) > r)) { + return; + } + } + + /** + * Account for the correct quadrant + */ + if (x < 0 && y >= 0) { + theta += 180; + } else if (x < 0 && y < 0) { + theta += 180; + } else if (x > 0 && y < 0) { + theta += 360; + } + + /** + * Account for the rose chart + */ + if (obj.type == 'rose') { + theta += 90; + } + + if (theta > 360) { + theta -= 360; + } + + for (var i=0; i= angles[i][0] && theta < angles[i][1]) { + + hyp = Math.abs(hyp); + + if (obj.type == 'rose' && hyp > angles[i][2]) { + return null; + } + + if (!hyp || (obj.type == 'pie' && obj.radius && hyp > obj.radius) ) { + return null; + } + + if (obj.type == 'pie' && obj.Get('chart.variant') == 'donut' && (hyp > obj.radius || hyp < (obj.radius / 2) ) ) { + return null; + } + + ret[0] = obj.centerx; + ret[1] = obj.centery; + ret[2] = (obj.type == 'rose') ? angles[i][2] : obj.radius; + ret[3] = angles[i][0]; + ret[4] = angles[i][1]; + ret[5] = i; + + if (obj.type == 'rose') { + + ret[3] -= 90; + ret[4] -= 90; + + if (x > 0 && y < 0) { + ret[3] += 360; + ret[4] += 360; + } + } + + if (ret[3] < 0) ret[3] += 360; + if (ret[4] > 360) ret[4] -= 360; + + return ret; + } + } + + return null; + } + + + /** + * This is a function that can be used to run code asynchronously, which can + * be used to speed up the loading of you pages. + * + * @param string func This is the code to run. It can also be a function pointer. + * The front page graphs show this function in action. Basically + * each graphs code is made in a function, and that function is + * passed to this function to run asychronously. + */ + RGraph.Async = function (func) + { + return setTimeout(func, arguments[1] ? arguments[1] : 1); + } + + + /** + * A custom random number function + * + * @param number min The minimum that the number should be + * @param number max The maximum that the number should be + * @param number How many decimal places there should be. Default for this is 0 + */ + RGraph.random = function (min, max) + { + var dp = arguments[2] ? arguments[2] : 0; + var r = Math.random(); + + return Number((((max - min) * r) + min).toFixed(dp)); + } + + + /** + * Draws a rectangle with curvy corners + * + * @param context object The context + * @param x number The X coordinate (top left of the square) + * @param y number The Y coordinate (top left of the square) + * @param w number The width of the rectangle + * @param h number The height of the rectangle + * @param number The radius of the curved corners + * @param boolean Whether the top left corner is curvy + * @param boolean Whether the top right corner is curvy + * @param boolean Whether the bottom right corner is curvy + * @param boolean Whether the bottom left corner is curvy + */ + RGraph.strokedCurvyRect = function (context, x, y, w, h) + { + // The corner radius + var r = arguments[5] ? arguments[5] : 3; + + // The corners + var corner_tl = (arguments[6] || arguments[6] == null) ? true : false; + var corner_tr = (arguments[7] || arguments[7] == null) ? true : false; + var corner_br = (arguments[8] || arguments[8] == null) ? true : false; + var corner_bl = (arguments[9] || arguments[9] == null) ? true : false; + + context.beginPath(); + + // Top left side + context.moveTo(x + (corner_tl ? r : 0), y); + context.lineTo(x + w - (corner_tr ? r : 0), y); + + // Top right corner + if (corner_tr) { + context.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2, false); + } + + // Top right side + context.lineTo(x + w, y + h - (corner_br ? r : 0) ); + + // Bottom right corner + if (corner_br) { + context.arc(x + w - r, y - r + h, r, Math.PI * 2, Math.PI * 0.5, false); + } + + // Bottom right side + context.lineTo(x + (corner_bl ? r : 0), y + h); + + // Bottom left corner + if (corner_bl) { + context.arc(x + r, y - r + h, r, Math.PI * 0.5, Math.PI, false); + } + + // Bottom left side + context.lineTo(x, y + (corner_tl ? r : 0) ); + + // Top left corner + if (corner_tl) { + context.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5, false); + } + + context.stroke(); + } + + + /** + * Draws a filled rectangle with curvy corners + * + * @param context object The context + * @param x number The X coordinate (top left of the square) + * @param y number The Y coordinate (top left of the square) + * @param w number The width of the rectangle + * @param h number The height of the rectangle + * @param number The radius of the curved corners + * @param boolean Whether the top left corner is curvy + * @param boolean Whether the top right corner is curvy + * @param boolean Whether the bottom right corner is curvy + * @param boolean Whether the bottom left corner is curvy + */ + RGraph.filledCurvyRect = function (context, x, y, w, h) + { + // The corner radius + var r = arguments[5] ? arguments[5] : 3; + + // The corners + var corner_tl = (arguments[6] || arguments[6] == null) ? true : false; + var corner_tr = (arguments[7] || arguments[7] == null) ? true : false; + var corner_br = (arguments[8] || arguments[8] == null) ? true : false; + var corner_bl = (arguments[9] || arguments[9] == null) ? true : false; + + context.beginPath(); + + // First draw the corners + + // Top left corner + if (corner_tl) { + context.moveTo(x + r, y + r); + context.arc(x + r, y + r, r, Math.PI, 1.5 * Math.PI, false); + } else { + context.fillRect(x, y, r, r); + } + + // Top right corner + if (corner_tr) { + context.moveTo(x + w - r, y + r); + context.arc(x + w - r, y + r, r, 1.5 * Math.PI, 0, false); + } else { + context.moveTo(x + w - r, y); + context.fillRect(x + w - r, y, r, r); + } + + + // Bottom right corner + if (corner_br) { + context.moveTo(x + w - r, y + h - r); + context.arc(x + w - r, y - r + h, r, 0, Math.PI / 2, false); + } else { + context.moveTo(x + w - r, y + h - r); + context.fillRect(x + w - r, y + h - r, r, r); + } + + // Bottom left corner + if (corner_bl) { + context.moveTo(x + r, y + h - r); + context.arc(x + r, y - r + h, r, Math.PI / 2, Math.PI, false); + } else { + context.moveTo(x, y + h - r); + context.fillRect(x, y + h - r, r, r); + } + + // Now fill it in + context.fillRect(x + r, y, w - r - r, h); + context.fillRect(x, y + r, r + 1, h - r - r); + context.fillRect(x + w - r - 1, y + r, r + 1, h - r - r); + + context.fill(); + } + + + /** + * A crude timing function + * + * @param string label The label to use for the time + */ + RGraph.Timer = function (label) + { + var d = new Date(); + + // This uses the Firebug console + console.log(label + ': ' + d.getSeconds() + '.' + d.getMilliseconds()); + } + + + /** + * Hides the palette if it's visible + */ + RGraph.HidePalette = function () + { + var div = RGraph.Registry.Get('palette'); + + if (typeof(div) == 'object' && div) { + div.style.visibility = 'hidden'; + div.style.display = 'none'; + RGraph.Registry.Set('palette', null); + } + } + + + /** + * Hides the zoomed canvas + */ + RGraph.HideZoomedCanvas = function () + { + if (typeof(__zoomedimage__) == 'object') { + obj = __zoomedimage__.obj; + } else { + return; + } + + if (obj.Get('chart.zoom.fade.out')) { + for (var i=10,j=1; i>=0; --i, ++j) { + if (typeof(__zoomedimage__) == 'object') { + setTimeout("__zoomedimage__.style.opacity = " + String(i / 10), j * 30); + } + } + + if (typeof(__zoomedbackground__) == 'object') { + setTimeout("__zoomedbackground__.style.opacity = " + String(i / 10), j * 30); + } + } + + if (typeof(__zoomedimage__) == 'object') { + setTimeout("__zoomedimage__.style.display = 'none'", obj.Get('chart.zoom.fade.out') ? 310 : 0); + } + + if (typeof(__zoomedbackground__) == 'object') { + setTimeout("__zoomedbackground__.style.display = 'none'", obj.Get('chart.zoom.fade.out') ? 310 : 0); + } + } + + + /** + * Adds an event handler + * + * @param object obj The graph object + * @param string event The name of the event, eg ontooltip + * @param object func The callback function + */ + RGraph.AddCustomEventListener = function (obj, name, func) + { + if (typeof(RGraph.events[obj.id]) == 'undefined') { + RGraph.events[obj.id] = []; + } + + RGraph.events[obj.id].push([obj, name, func]); + } + + + /** + * Used to fire one of the RGraph custom events + * + * @param object obj The graph object that fires the event + * @param string event The name of the event to fire + */ + RGraph.FireCustomEvent = function (obj, name) + { + for (i in RGraph.events) { + if (typeof(i) == 'string' && i == obj.id && RGraph.events[i].length > 0) { + for(var j=0; j 0; + } + + + /** + * Checks the browser for traces of MSIE9 + */ + RGraph.isIE9 = function () + { + return navigator.userAgent.indexOf('MSIE 9') > 0; + } + + + /** + * Checks the browser for traces of MSIE9 + */ + RGraph.isIE9up = function () + { + navigator.userAgent.match(/MSIE (\d+)/); + + return Number(RegExp.$1) >= 9; + } + + + /** + * This clears a canvases event handlers. + * + * @param string id The ID of the canvas whose event handlers will be cleared + */ + RGraph.ClearEventListeners = function (id) + { + for (var i=0; i str.length ? obj.Get('chart.labels')[i] : str); + } + } + + obj.context.font = obj.Get('chart.text.size') + 'pt ' + obj.Get('chart.text.font'); + + len = obj.context.measureText(str).width + 5; + + return (obj.type == 'hbar' ? len / 3 : len); + } + + + /** + * A basic Array shift gunction + * + * @param object The numerical array to work on + * @return The new array + */ + RGraph.array_shift = function (arr) + { + var ret = []; + + for (var i=1; i (canvas.__original_width__ / 2)) RGraph.Resizing.div.style.width = newWidth + 'px'; + if (newHeight > (canvas.__original_height__ / 2)) RGraph.Resizing.div.style.height = newHeight + 'px'; + } + } + + /** + * The window onmouseup function + */ + var MouseupFunc = function (e) + { + if (!RGraph.Resizing || !RGraph.Resizing.div || !RGraph.Resizing.mousedown) { + return; + } + + if (RGraph.Resizing.div) { + + var div = RGraph.Resizing.div; + var canvas = div.__canvas__; + var coords = RGraph.getCanvasXY(div.__canvas__); + + var parentNode = canvas.parentNode; + + if (canvas.style.position != 'absolute') { + // Create a DIV to go in the canvases place + var placeHolderDIV = document.createElement('DIV'); + placeHolderDIV.style.width = RGraph.Resizing.originalw + 'px'; + placeHolderDIV.style.height = RGraph.Resizing.originalh + 'px'; + //placeHolderDIV.style.backgroundColor = 'red'; + placeHolderDIV.style.display = 'inline-block'; // Added 5th Nov 2010 + placeHolderDIV.style.position = canvas.style.position; + placeHolderDIV.style.left = canvas.style.left; + placeHolderDIV.style.top = canvas.style.top; + placeHolderDIV.style.cssFloat = canvas.style.cssFloat; + parentNode.insertBefore(placeHolderDIV, canvas); + } + + + // Now set the canvas to be positioned absolutely + canvas.style.backgroundColor = 'white'; + canvas.style.position = 'absolute'; + canvas.style.border = '1px dashed gray'; + canvas.style.left = (RGraph.Resizing.originalCanvasX - 1) + 'px'; + canvas.style.top = (RGraph.Resizing.originalCanvasY - 1) + 'px'; + + canvas.width = parseInt(div.style.width); + canvas.height = parseInt(div.style.height); + canvas.__object__.Draw(); + + // Get rid of transparent semi-opaque DIV + RGraph.Resizing.mousedown = false; + div.style.left = '-1000px'; + div.style.top = '-1000px'; + } + + /** + * Fire the onresize event + */ + RGraph.FireCustomEvent(canvas.__object__, 'onresize'); + } + + + window.onmouseup = MouseupFunc; + + + canvas.onmousemove = function (e) + { + e = RGraph.FixEventObject(e); + + var coords = RGraph.getMouseXY(e); + var canvas = e.target; + var context = canvas.getContext('2d'); + + RGraph.Resizing.title = canvas.title; + + if ( (coords[0] > (canvas.width - resizeHandle) + && coords[0] < canvas.width + && coords[1] > (canvas.height - resizeHandle) + && coords[1] < canvas.height)) { + + canvas.title = 'Resize the graph'; + canvas.style.cursor = 'move'; + + } else if ( coords[0] > (canvas.width - resizeHandle - resizeHandle) + && coords[0] < canvas.width - resizeHandle + && coords[1] > (canvas.height - resizeHandle) + && coords[1] < canvas.height) { + + canvas.style.cursor = 'pointer'; + canvas.title = 'Reset graph to original size'; + + } else { + + canvas.style.cursor = 'default'; + canvas.title = ''; + } + } + + + canvas.onmousedown = function (e) + { + e = RGraph.FixEventObject(e); + + var coords = RGraph.getMouseXY(e); + var canvasCoords = RGraph.getCanvasXY(e.target); + + if ( coords[0] > (obj.canvas.width - resizeHandle) + && coords[0] < obj.canvas.width + && coords[1] > (obj.canvas.height - resizeHandle) + && coords[1] < obj.canvas.height) { + + RGraph.Resizing.mousedown = true; + + + /** + * Create the semi-opaque DIV + */ + var div = document.createElement('DIV'); + div.style.position = 'absolute'; + div.style.left = canvasCoords[0] + 'px'; + div.style.top = canvasCoords[1] + 'px'; + div.style.width = canvas.width + 'px'; + div.style.height = canvas.height + 'px'; + div.style.border = '1px dotted black'; + div.style.backgroundColor = 'gray'; + div.style.opacity = 0.5; + div.__canvas__ = e.target; + + document.body.appendChild(div); + RGraph.Resizing.div = div; + + // This is a repetition of the window.onmouseup function + div.onmouseup = function (e) + { + MouseupFunc(e); + } + + + RGraph.Resizing.div.onmouseover = function (e) + { + e = RGraph.FixEventObject(e); + e.stopPropagation(); + } + + // The mouse + RGraph.Resizing.originalx = e.pageX; + RGraph.Resizing.originaly = e.pageY; + + //The canvas + RGraph.Resizing.originalw = obj.canvas.width; + RGraph.Resizing.originalh = obj.canvas.height; + + RGraph.Resizing.originalCanvasX = RGraph.getCanvasXY(obj.canvas)[0]; + RGraph.Resizing.originalCanvasY = RGraph.getCanvasXY(obj.canvas)[1]; + } + } + + + /** + * This function facilitates the reset button + */ + canvas.onclick = function (e) + { + var coords = RGraph.getMouseXY(e); + var canvas = e.target; + + if ( coords[0] > (canvas.width - resizeHandle - resizeHandle) + && coords[0] < canvas.width - resizeHandle + && coords[1] > (canvas.height - resizeHandle) + && coords[1] < canvas.height) { + + // Restore the original width and height + canvas.width = canvas.__original_width__; + canvas.height = canvas.__original_height__; + + // Lose the border + canvas.style.border = ''; + + // Add 1 pixel to the top/left because the border is going + canvas.style.left = (parseInt(canvas.style.left) + 1) + 'px'; + canvas.style.top = (parseInt(canvas.style.top) + 1) + 'px'; + + // Redraw the canvas + canvas.__object__.Draw(); + + // Set the width and height on the DIV + RGraph.Resizing.div.style.width = canvas.__original_width__ + 'px'; + RGraph.Resizing.div.style.height = canvas.__original_height__ + 'px'; + + /** + * Fire the resize event + */ + RGraph.FireCustomEvent(canvas.__object__, 'onresize'); + } + } + } + } \ No newline at end of file diff --git a/libraries/RGraph.common.tooltips.js b/libraries/RGraph.common.tooltips.js new file mode 100644 index 0000000..e636073 --- /dev/null +++ b/libraries/RGraph.common.tooltips.js @@ -0,0 +1,502 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'}; + + /** + * This is used in two functions, hence it's here + */ + RGraph.tooltips = {}; + RGraph.tooltips.padding = '3px'; + RGraph.tooltips.font_face = 'Tahoma'; + RGraph.tooltips.font_size = '10pt'; + + + /** + * Shows a tooltip next to the mouse pointer + * + * @param canvas object The canvas element object + * @param text string The tooltip text + * @param int x The X position that the tooltip should appear at. Combined with the canvases offsetLeft + * gives the absolute X position + * @param int y The Y position the tooltip should appear at. Combined with the canvases offsetTop + * gives the absolute Y position + * @param int idx The index of the tooltip in the graph objects tooltip array + */ + RGraph.Tooltip = function (canvas, text, x, y, idx) + { + /** + * chart.tooltip.override allows you to totally take control of rendering the tooltip yourself + */ + if (typeof(canvas.__object__.Get('chart.tooltips.override')) == 'function') { + return canvas.__object__.Get('chart.tooltips.override')(canvas, text, x, y, idx); + } + + /** + * This facilitates the "id:xxx" format + */ + text = RGraph.getTooltipText(text); + + /** + * First clear any exising timers + */ + var timers = RGraph.Registry.Get('chart.tooltip.timers'); + + if (timers && timers.length) { + for (i=0; i document.body.offsetWidth ? RGraph.Registry.Get('chart.tooltip').offsetWidth : 0); + var diffy = y - currenty - RGraph.Registry.Get('chart.tooltip').offsetHeight; + + // Position the tooltip + setTimeout('RGraph.Registry.Get("chart.tooltip").style.left = "' + (currentx + (diffx * 0.2)) + 'px"', 25); + setTimeout('RGraph.Registry.Get("chart.tooltip").style.left = "' + (currentx + (diffx * 0.4)) + 'px"', 50); + setTimeout('RGraph.Registry.Get("chart.tooltip").style.left = "' + (currentx + (diffx * 0.6)) + 'px"', 75); + setTimeout('RGraph.Registry.Get("chart.tooltip").style.left = "' + (currentx + (diffx * 0.8)) + 'px"', 100); + setTimeout('RGraph.Registry.Get("chart.tooltip").style.left = "' + (currentx + (diffx * 1.0)) + 'px"', 125); + + setTimeout('RGraph.Registry.Get("chart.tooltip").style.top = "' + (currenty + (diffy * 0.2)) + 'px"', 25); + setTimeout('RGraph.Registry.Get("chart.tooltip").style.top = "' + (currenty + (diffy * 0.4)) + 'px"', 50); + setTimeout('RGraph.Registry.Get("chart.tooltip").style.top = "' + (currenty + (diffy * 0.6)) + 'px"', 75); + setTimeout('RGraph.Registry.Get("chart.tooltip").style.top = "' + (currenty + (diffy * 0.8)) + 'px"', 100); + setTimeout('RGraph.Registry.Get("chart.tooltip").style.top = "' + (currenty + (diffy * 1.0)) + 'px"', 125); + + } else { + + alert('[TOOLTIPS] The "snap" effect is only supported on the Line, Rscatter, Scatter and Tradar charts'); + } + + /** + * Fire the tooltip event + */ + RGraph.FireCustomEvent(canvas.__object__, 'ontooltip'); + + return; + } + + /** + * Hide any currently shown tooltip + */ + RGraph.HideTooltip(); + + + /** + * Show a tool tip + */ + var tooltipObj = document.createElement('DIV'); + tooltipObj.className = canvas.__object__.Get('chart.tooltips.css.class'); + tooltipObj.style.display = 'none'; + tooltipObj.style.position = 'absolute'; + tooltipObj.style.left = 0; + tooltipObj.style.top = 0; + tooltipObj.style.backgroundColor = '#ffe'; + tooltipObj.style.color = 'black'; + if (!document.all) tooltipObj.style.border = '1px solid rgba(0,0,0,0)'; + tooltipObj.style.visibility = 'visible'; + tooltipObj.style.paddingLeft = RGraph.tooltips.padding; + tooltipObj.style.paddingRight = RGraph.tooltips.padding; + tooltipObj.style.fontFamily = RGraph.tooltips.font_face; + tooltipObj.style.fontSize = RGraph.tooltips.font_size; + tooltipObj.style.zIndex = 3; + tooltipObj.style.borderRadius = '5px'; + tooltipObj.style.MozBorderRadius = '5px'; + tooltipObj.style.WebkitBorderRadius = '5px'; + tooltipObj.style.WebkitBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; + tooltipObj.style.MozBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; + tooltipObj.style.boxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; + tooltipObj.style.filter = 'progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135)'; + tooltipObj.style.opacity = 0; + tooltipObj.style.overflow = 'hidden'; + tooltipObj.innerHTML = text; + tooltipObj.__text__ = text; // This is set because the innerHTML can change when it's set + tooltipObj.__canvas__ = canvas; + tooltipObj.style.display = 'inline'; + + if (typeof(idx) == 'number') { + tooltipObj.__index__ = idx; + } + + document.body.appendChild(tooltipObj); + + var width = tooltipObj.offsetWidth; + var height = tooltipObj.offsetHeight - (RGraph.isIE9up() ? 7 : 0); + + if ((y - height - 2) > 0) { + y = y - height - 2; + } else { + y = y + 2; + } + + /** + * Set the width on the tooltip so it doesn't resize if the window is resized + */ + tooltipObj.style.width = width + 'px'; + //tooltipObj.style.height = 0; // Initially set the tooltip height to nothing + + /** + * If the mouse is towards the right of the browser window and the tooltip would go outside of the window, + * move it left + */ + if ( (x + width) > document.body.offsetWidth ) { + x = x - width - 7; + var placementLeft = true; + + if (canvas.__object__.Get('chart.tooltips.effect') == 'none') { + x = x - 3; + } + + tooltipObj.style.left = x + 'px'; + tooltipObj.style.top = y + 'px'; + + } else { + x += 5; + + tooltipObj.style.left = x + 'px'; + tooltipObj.style.top = y + 'px'; + } + + + if (effect == 'expand') { + + tooltipObj.style.left = (x + (width / 2)) + 'px'; + tooltipObj.style.top = (y + (height / 2)) + 'px'; + leftDelta = (width / 2) / 10; + topDelta = (height / 2) / 10; + + tooltipObj.style.width = 0; + tooltipObj.style.height = 0; + tooltipObj.style.boxShadow = ''; + tooltipObj.style.MozBoxShadow = ''; + tooltipObj.style.WebkitBoxShadow = ''; + tooltipObj.style.borderRadius = 0; + tooltipObj.style.MozBorderRadius = 0; + tooltipObj.style.WebkitBorderRadius = 0; + tooltipObj.style.opacity = 1; + + // Progressively move the tooltip to where it should be (the x position) + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 25)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 50)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 75)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 100)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 125)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 150)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 175)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 200)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 225)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) - leftDelta) + 'px' }", 250)); + + // Progressively move the tooltip to where it should be (the Y position) + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 25)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 50)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 75)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 100)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 125)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 150)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 175)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 200)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 225)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) - topDelta) + 'px' }", 250)); + + // Progressively grow the tooltip width + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.1) + "px'; }", 25)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.2) + "px'; }", 50)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.3) + "px'; }", 75)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.4) + "px'; }", 100)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.5) + "px'; }", 125)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.6) + "px'; }", 150)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.7) + "px'; }", 175)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.8) + "px'; }", 200)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 0.9) + "px'; }", 225)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + width + "px'; }", 250)); + + // Progressively grow the tooltip height + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.1) + "px'; }", 25)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.2) + "px'; }", 50)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.3) + "px'; }", 75)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.4) + "px'; }", 100)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.5) + "px'; }", 125)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.6) + "px'; }", 150)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.7) + "px'; }", 175)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.8) + "px'; }", 200)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 0.9) + "px'; }", 225)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + height + "px'; }", 250)); + + // When the animation is finished, set the tooltip HTML + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').innerHTML = RGraph.Registry.Get('chart.tooltip').__text__; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.boxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.MozBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.WebkitBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.borderRadius = '5px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.MozBorderRadius = '5px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.WebkitBorderRadius = '5px'; }", 250)); + + } else if (effect == 'contract') { + + tooltipObj.style.left = (x - width) + 'px'; + tooltipObj.style.top = (y - (height * 2)) + 'px'; + tooltipObj.style.cursor = 'pointer'; + + leftDelta = width / 10; + topDelta = height / 10; + + tooltipObj.style.width = (width * 5) + 'px'; + tooltipObj.style.height = (height * 5) + 'px'; + + tooltipObj.style.opacity = 0.2; + + // Progressively move the tooltip to where it should be (the x position) + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 25)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 50)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 75)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 100)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 125)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 150)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 175)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 200)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 225)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.left = (parseInt(RGraph.Registry.Get('chart.tooltip').style.left) + leftDelta) + 'px' }", 250)); + + // Progressively move the tooltip to where it should be (the Y position) + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 25)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 50)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 75)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 100)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 125)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 150)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 175)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 200)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 225)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.top = (parseInt(RGraph.Registry.Get('chart.tooltip').style.top) + (topDelta*2)) + 'px' }", 250)); + + // Progressively shrink the tooltip width + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 5.5) + "px'; }", 25)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 5.0) + "px'; }", 50)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 4.5) + "px'; }", 75)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 4.0) + "px'; }", 100)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 3.5) + "px'; }", 125)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 3.0) + "px'; }", 150)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 2.5) + "px'; }", 175)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 2.0) + "px'; }", 200)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + (width * 1.5) + "px'; }", 225)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.width = '" + width + "px'; }", 250)); + + // Progressively shrink the tooltip height + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 5.5) + "px'; }", 25)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 5.0) + "px'; }", 50)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 4.5) + "px'; }", 75)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 4.0) + "px'; }", 100)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 3.5) + "px'; }", 125)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 3.0) + "px'; }", 150)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 2.5) + "px'; }", 175)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 2.0) + "px'; }", 200)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + (height * 1.5) + "px'; }", 225)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.height = '" + height + "px'; }", 250)); + + // When the animation is finished, set the tooltip HTML + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').innerHTML = RGraph.Registry.Get('chart.tooltip').__text__; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.boxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.MozBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.WebkitBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.borderRadius = '5px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.MozBorderRadius = '5px'; }", 250)); + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.WebkitBorderRadius = '5px'; }", 250)); + + /** + * This resets the pointer + */ + RGraph.Registry.Get('chart.tooltip.timers').push(setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.cursor = 'default'; }", 275)); + + + + } else if (effect != 'fade' && effect != 'expand' && effect != 'none' && effect != 'snap' && effect != 'contract') { + alert('[COMMON] Unknown tooltip effect: ' + effect); + } + + if (effect != 'none') { + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.1; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.2)'; }", 25); + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.2; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.2)'; }", 50); + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.3; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.2)'; }", 75); + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.4; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.2)'; }", 100); + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.5; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.2)'; }", 125); + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.6; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.2)'; }", 150); + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.7; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.4)'; }", 175); + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.8; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.6)'; }", 200); + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 0.9; RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgba(96,96,96,0.8)'; }", 225); + } + + setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 1;RGraph.Registry.Get('chart.tooltip').style.border = '1px solid rgb(96,96,96)';}", effect == 'none' ? 50 : 250); + + /** + * If the tooltip it self is clicked, cancel it + */ + tooltipObj.onmousedown = function (e) + { + e = RGraph.FixEventObject(e) + e.stopPropagation(); + } + + tooltipObj.onclick = function (e) + { + if (e.button == 0) { + e = RGraph.FixEventObject(e); + e.stopPropagation(); + } + } + + /** + * Install the function for hiding the tooltip. + */ + document.body.onmousedown = function (event) + { + var tooltip = RGraph.Registry.Get('chart.tooltip'); + + if (tooltip) { + RGraph.HideTooltip(); + + // Redraw if highlighting is enabled + if (tooltip.__canvas__.__object__.Get('chart.tooltips.highlight')) { + RGraph.Redraw(); + } + } + } + + /** + * If the window is resized, hide the tooltip + */ + window.onresize = function () + { + var tooltip = RGraph.Registry.Get('chart.tooltip'); + + if (tooltip) { + tooltip.parentNode.removeChild(tooltip); + tooltip.style.display = 'none'; + tooltip.style.visibility = 'hidden'; + RGraph.Registry.Set('chart.tooltip', null); + + // Redraw the graph if necessary + if (canvas.__object__.Get('chart.tooltips.highlight')) { + RGraph.Clear(canvas); + canvas.__object__.Draw(); + } + } + } + + /** + * Keep a reference to the tooltip + */ + RGraph.Registry.Set('chart.tooltip', tooltipObj); + + /** + * Fire the tooltip event + */ + RGraph.FireCustomEvent(canvas.__object__, 'ontooltip'); + } + + + /** + * + */ + RGraph.getTooltipText = function (text) + { + var result = /^id:(.*)/.exec(text); + + if (result) { + text = document.getElementById(result[1]).innerHTML; + } + + return text; + } + + + /** + * + */ + RGraph.getTooltipWidth = function (text, obj) + { + var div = document.createElement('DIV'); + div.className = obj.Get('chart.tooltips.css.class'); + div.style.paddingLeft = RGraph.tooltips.padding; + div.style.paddingRight = RGraph.tooltips.padding; + div.style.fontFamily = RGraph.tooltips.font_face; + div.style.fontSize = RGraph.tooltips.font_size; + div.style.visibility = 'hidden'; + div.style.position = 'absolute'; + div.style.top = '300px'; + div.style.left = 0; + div.style.display = 'inline'; + div.innerHTML = RGraph.getTooltipText(text); + document.body.appendChild(div); + + return div.offsetWidth; + } + + + /** + * Hides the currently shown tooltip + */ + RGraph.HideTooltip = function () + { + var tooltip = RGraph.Registry.Get('chart.tooltip'); + + if (tooltip) { + tooltip.parentNode.removeChild(tooltip); + tooltip.style.display = 'none'; + tooltip.style.visibility = 'hidden'; + RGraph.Registry.Set('chart.tooltip', null); + } + } \ No newline at end of file diff --git a/libraries/RGraph.common.zoom.js b/libraries/RGraph.common.zoom.js new file mode 100644 index 0000000..ee07dd7 --- /dev/null +++ b/libraries/RGraph.common.zoom.js @@ -0,0 +1,867 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'}; + + + /** + * Installs the event handlers for zooming an area of the graph + * + * @param object obj Your graph object + */ + RGraph.ZoomArea = function (obj) + { + if (obj.Get('chart.zoom.mode') == 'area') { + + var canvas = obj.canvas; + var context = obj.context; + + obj.canvas.style.cursor = 'crosshair'; + + RGraph.Register(obj); + + + canvas.onmousedown = function(e) + { + var canvas = e.target; + var coords = RGraph.getMouseXY(e); + var obj = canvas.__object__; + + if (RGraph.Registry.Get('chart.zoomed.area.div')) { + RGraph.Registry.Get('chart.zoomed.area.div').style.display = 'none'; + } + + if (typeof(RGraph.Registry.Get('chart.zoomed.area.divs')) == null) { + RGraph.Registry.Set('chart.zoomed.area.divs', []); + + } else { + + var divs = RGraph.Registry.Get('chart.zoomed.area.divs'); + + if (divs && divs.length) { + for (var i=0; i= 0 && height >= 0) { + + if (width > 5 && height > 5) { + areaDiv.style.width = (width - 15) + 'px'; + areaDiv.style.height = (height - 15) + 'px'; + areaDiv.style.display = 'inline'; + } else { + areaDiv.style.display = 'none'; + } + + } else if (width < -5 || height < -5) { + + var canvasCoords = RGraph.getCanvasXY(canvas); + var noticeDiv = document.createElement('DIV'); + + noticeDiv.style.position = 'absolute'; + noticeDiv.style.top = 0; + noticeDiv.style.left = 0; + noticeDiv.style.zIndex = 99; + noticeDiv.style.border = '1px dashed black'; + noticeDiv.style.backgroundColor = '#ffc1c1'; + noticeDiv.style.MozBoxShadow = '0 0 5px #999'; + noticeDiv.style.WebkitBoxShadow = '0 0 5px #999'; + noticeDiv.style.boxShadow = '0 0 5px #999'; + noticeDiv.style.padding = '2px'; + noticeDiv.innerHTML = 'Zoom goes right and down'; + document.body.appendChild(noticeDiv); + + // Reposition the warning + noticeDiv.style.top = canvasCoords[1] + startCoords[1] - noticeDiv.offsetHeight + 'px'; + noticeDiv.style.left = canvasCoords[0] + startCoords[0] - (noticeDiv.offsetWidth / 2) + 'px'; + noticeDiv.style.width = noticeDiv.offsetWidth + 'px'; + + setTimeout(function () {noticeDiv.style.opacity = 0.8;}, 2100); + setTimeout(function () {noticeDiv.style.opacity = 0.6;}, 2200); + setTimeout(function () {noticeDiv.style.opacity = 0.4;}, 2300); + setTimeout(function () {noticeDiv.style.opacity = 0.2;}, 2400); + setTimeout(function () {noticeDiv.style.display = 'none';}, 2500); + setTimeout(function () {noticeDiv = null;}, 2600); + } + } + } + + + canvas.onmouseup = function (e) + { + RGraph.FixEventObject(e); + + var startCoords = RGraph.Registry.Get('chart.zoomed.area.mousedown'); + var coords = RGraph.getMouseXY(e); + + // Do the zooming here + if (RGraph.Registry.Get('chart.zoomed.area.mousedown')) { + + //RGraph.Redraw(); + + RGraph.Registry.Get('chart.zoomed.area.areadiv').style.display = 'none'; + RGraph.Registry.Get('chart.zoomed.area.areadiv').style.left = '-1000px'; + RGraph.Registry.Get('chart.zoomed.area.areadiv').style.top = '-1000px'; + RGraph.Registry.Set('chart.zoomed.area.areadiv', null); + + if (coords[0] < startCoords[0] || coords[1] < startCoords[1]) { + RGraph.Registry.Set('chart.zoomed.area.mousedown', false); + return; + } + + var canvas = e.target; + var obj = canvas.__object__; + var context = obj.context; + var canvasCoords = RGraph.getCanvasXY(e.target); + var coords = RGraph.getMouseXY(e); + var startCoords = RGraph.Registry.Get('chart.zoomed.area.mousedown'); + var startx = startCoords[0]; + var starty = startCoords[1]; + var endx = coords[0] - 15; + var endy = coords[1] - 15; + var width = Math.abs(endx - startx); + var height = Math.abs(endy - starty); + var factor = obj.Get('chart.zoom.factor') - 1; + + var img = document.createElement('IMG'); + img.src = canvas.toDataURL(); + img.style.position = 'relative'; + img.style.left = (factor + 1) * -1 * startx + 'px'; + img.style.top = (factor + 1) * -1 * starty + 'px'; + img.width = (factor + 1) * canvas.width; + img.height = (factor + 1) * canvas.height; + + var div = document.createElement('DIV'); + div.__object__ = obj; + div.className = 'RGraph_zoomed_area'; + div.style.position = 'absolute'; + div.style.backgroundColor = 'white'; + div.style.cursor = 'move'; + + div.style.top = e.pageY + 'px'; + div.style.left = e.pageX + 'px'; + div.origWidth = width; + div.origHeight = height; + div.style.width = width + 'px'; + div.style.height = height + 'px'; + div.style.border = '1px solid black'; + div.style.boxShadow = '0 0 15px black'; + div.style.MozBoxShadow = '0 0 15px black'; + div.style.WebkitBoxShadow = '0 0 15px black'; + div.style.overflow = 'hidden'; + div.style.opacity = 0; + div.style.zIndex = 99; + + document.body.appendChild(div); + div.appendChild(img); + + + /** + * This facilitates expanding the zoomed area once visible (the double click) + */ + div.ondblclick = function (event) + { + var event = RGraph.FixEventObject(event); + var img = event.target; + var div = event.target.parentNode; + + var current_width = div.offsetWidth + var current_height = div.offsetHeight + var target_width = img.offsetWidth; + var target_height = img.offsetHeight; + var diff_width = target_width - current_width; + var diff_height = target_height - current_height; + + var img_offset_left = parseInt(img.offsetLeft); + var img_offset_top = parseInt(img.offsetTop); + + // Global vars on purpose so the timers can access them + __zoomed_div_style__ = div.style; + __zoomed_img_style__ = img.style; + + setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 50); + setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 100); + setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 150); + setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 200); + setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 250); + + setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 50); + setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 100); + setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 150); + setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 200); + setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 250); + + setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 50); + setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 100); + setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 150); + setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 200); + setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 250); + + setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 50); + setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 100); + setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 150); + setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 200); + setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 250); + + // Move the image within the div + setTimeout("__zoomed_img_style__.left = " + (img_offset_left * 0.8) + " + 'px'", 50); + setTimeout("__zoomed_img_style__.left = " + (img_offset_left * 0.6) + " + 'px'", 100); + setTimeout("__zoomed_img_style__.left = " + (img_offset_left * 0.4) + " + 'px'", 150); + setTimeout("__zoomed_img_style__.left = " + (img_offset_left * 0.2) + " + 'px'", 200); + setTimeout("__zoomed_img_style__.left = 0", 250); + + setTimeout("__zoomed_img_style__.top = " + (img_offset_top * 0.8) + " + 'px'", 50); + setTimeout("__zoomed_img_style__.top = " + (img_offset_top * 0.6) + " + 'px'", 100); + setTimeout("__zoomed_img_style__.top = " + (img_offset_top * 0.4) + " + 'px'", 150); + setTimeout("__zoomed_img_style__.top = " + (img_offset_top * 0.2) + " + 'px'", 200); + setTimeout("__zoomed_img_style__.top = 0", 250); + + div.ondblclick = null; + } + /** + * Make the zoomed bit draggable + */ + div.onmousedown = function (e) + { + e = RGraph.FixEventObject(e); + + var div = e.target.parentNode; + var img = div.childNodes[0]; + + if (e.button == 0 || e.button == 1 ) { + + div.__offsetx__ = e.offsetX + img.offsetLeft; + div.__offsety__ = e.offsetY + img.offsetTop; + + RGraph.Registry.Set('chart.mousedown', div); + RGraph.Registry.Set('chart.button', 0); + + } else { + + img.__startx__ = e.pageX; + img.__starty__ = e.pageY; + + img.__originalx__ = img.offsetLeft; + img.__originaly__ = img.offsetTop; + + RGraph.Registry.Set('chart.mousedown', img); + RGraph.Registry.Set('chart.button', 2); + + /** + * Don't show a context menu when the zoomed area is right-clicked on + */ + window.oncontextmenu = function (e) + { + e = RGraph.FixEventObject(e); + + e.stopPropagation(); + + // [18th July 2010] Is this reallly necessary? + window.oncontextmenu = function (e) + { + return true; + } + + + return false; + } + } + + e.stopPropagation(); + + return false; + } + + window.onmouseup = function (e) + { + RGraph.Registry.Set('chart.mousedown', false); + } + + window.onmousemove = function (e) + { + if (RGraph.Registry.Get('chart.mousedown') && RGraph.Registry.Get('chart.button') == 0) { + + var div = RGraph.Registry.Get('chart.mousedown'); + + var x = e.pageX - div.__offsetx__; + var y = e.pageY - div.__offsety__; + + div.style.left = x + 'px'; + div.style.top = y + 'px'; + + } else if (RGraph.Registry.Get('chart.mousedown') && RGraph.Registry.Get('chart.button') == 2) { + + var img = RGraph.Registry.Get('chart.mousedown'); + + var x = img.__originalx__ + e.pageX - img.__startx__; + var y = img.__originaly__ + e.pageY - img.__starty__; + + img.style.left = x + 'px'; + img.style.top = y + 'px'; + } + } + // End dragging code + + + var divs = RGraph.Registry.Get('chart.zoomed.area.divs'); + if (typeof(divs) == 'object') { + divs.push(div); + } else { + RGraph.Registry.Set('chart.zoomed.area.divs', [div]) + } + + // Create the background + var bg = document.createElement('DIV'); + bg.style.position = 'fixed' + bg.style.zIndex = 98; + bg.style.top = 0; + bg.style.left = 0; + bg.style.backgroundColor = '#999'; + bg.style.opacity = 0; + bg.style.width = (screen.width + 100) + 'px'; + bg.style.height = (screen.height + 100) + 'px'; + document.body.appendChild(bg); + + bg.onclick = function (e) + { + div.style.display = 'none'; + bg.style.display = 'none'; + div = null; + bg = null; + } + + + setTimeout(function (){div.style.opacity = 0.2;}, 50); + setTimeout(function (){div.style.opacity = 0.4;}, 100); + setTimeout(function (){div.style.opacity = 0.6;}, 150); + setTimeout(function (){div.style.opacity = 0.8;}, 200); + setTimeout(function (){div.style.opacity = 1.0;}, 250); + + setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.1) + 'px'}, 50); + setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.2) + 'px'}, 100); + setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.3) + 'px'}, 150); + setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.4) + 'px'}, 200); + setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.5) + 'px'}, 250); + + setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.1) + 'px'}, 50); + setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.2) + 'px'}, 100); + setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.3) + 'px'}, 150); + setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.4) + 'px'}, 200); + setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.5) + 'px'}, 250); + + setTimeout(function () {div.style.width = width + (width * factor * 0.2) + 'px'}, 50); + setTimeout(function () {div.style.width = width + (width * factor * 0.4) + 'px'}, 100); + setTimeout(function () {div.style.width = width + (width * factor * 0.6) + 'px'}, 150); + setTimeout(function () {div.style.width = width + (width * factor * 0.8) + 'px'}, 200); + setTimeout(function () {div.style.width = width + (width * factor * 1.0) + 'px'}, 250); + + setTimeout(function () {div.style.height = height + (height * factor * 0.2) + 'px'}, 50); + setTimeout(function () {div.style.height = height + (height * factor * 0.4) + 'px'}, 100); + setTimeout(function () {div.style.height = height + (height * factor * 0.6) + 'px'}, 150); + setTimeout(function () {div.style.height = height + (height * factor * 0.8) + 'px'}, 200); + setTimeout(function () {div.style.height = height + (height * factor * 1.0) + 'px'}, 250); + + setTimeout(function (){bg.style.opacity = 0.1;}, 50); + setTimeout(function (){bg.style.opacity = 0.2;}, 100); + setTimeout(function (){bg.style.opacity = 0.3;}, 150); + setTimeout(function (){bg.style.opacity = 0.4;}, 200); + setTimeout(function (){bg.style.opacity = 0.5;}, 250); + + RGraph.Registry.Set('chart.zoomed.area.bg', bg); + RGraph.Registry.Set('chart.zoomed.area.img', img); + RGraph.Registry.Set('chart.zoomed.area.div', div); + RGraph.Registry.Set('chart.zoomed.area.mousedown', null); + } + + /** + * Fire the zoom event + */ + RGraph.FireCustomEvent(obj, 'onzoom'); + } + + canvas.onmouseout = function (e) + { + RGraph.Registry.Set('chart.zoomed.area.areadiv', null); + RGraph.Registry.Set('chart.zoomed.area.mousedown', null); + RGraph.Registry.Set('chart.zoomed.area.div', null); + } + } + } + + + /** + * This function sets up the zoom window if requested + * + * @param obj object The graph object + */ + RGraph.ShowZoomWindow = function (obj) + { + var gutter = obj.Get('chart.gutter'); + + if (obj.Get('chart.zoom.mode') == 'thumbnail') { + RGraph.ZoomWindow(obj.canvas); + } + + if (obj.Get('chart.zoom.mode') == 'area') { + RGraph.ZoomArea(obj); + } + } + + + /** + * Installs the evnt handler for the zoom window/THUMBNAIL + */ + RGraph.ZoomWindow = function (canvas) + { + canvas.onmousemove = function (e) + { + e = RGraph.FixEventObject(e); + + var obj = e.target.__object__; + var canvas = obj.canvas; + var context = obj.context; + var coords = RGraph.getMouseXY(e); + + /** + * Create the DIV + */ + if (!RGraph.Registry.Get('chart.zoomed.div')) { + + var div = document.createElement('div'); + div.className = 'RGraph_zoom_window'; + div.style.width = obj.Get('chart.zoom.thumbnail.width') + 'px'; + div.style.height = obj.Get('chart.zoom.thumbnail.height') + 'px'; + + // Added back in on the 17th December + div.style.border = '2px dashed gray'; + + div.style.position = 'absolute'; + div.style.overflow = 'hidden'; + div.style.backgroundColor = 'white'; + + // Initially the zoomed layer should be off-screen + div.style.left = '-1000px'; + div.style.top = '-1000px'; + + // Should these be 0? No. + div.style.borderRadius = '5px'; + div.style.MozBorderRadius = '5px'; + div.style.WebkitBorderRadius = '5px'; + + if (obj.Get('chart.zoom.shadow')) { + div.style.boxShadow = 'rgba(0,0,0,0.5) 3px 3px 3px'; + div.style.MozBoxShadow = 'rgba(0,0,0,0.5) 3px 3px 3px'; + div.style.WebkitBoxShadow = 'rgba(0,0,0,0.5) 3px 3px 3px'; + } + + //div.style.opacity = 0.2; + div.__object__ = obj; + document.body.appendChild(div); + + /** + * Get the canvas as an image + */ + var img = document.createElement('img'); + img.width = obj.canvas.width * obj.Get('chart.zoom.factor'); + img.height = obj.canvas.height * obj.Get('chart.zoom.factor'); + img.style.position = 'relative'; + img.style.backgroundColor = 'white'; + img.__object__ = obj; + + div.appendChild(img); + + RGraph.Registry.Set('chart.zoomed.div', div); + RGraph.Registry.Set('chart.zoomed.img', img); + + // Fade the zoom in + setTimeout("RGraph.Registry.Get('chart.zoomed.div').__object__.canvas.onmouseover()", 5); + + } else { + + div = RGraph.Registry.Get('chart.zoomed.div'); + img = RGraph.Registry.Get('chart.zoomed.img'); + } + + // Make sure the image is up-to-date + img.src = canvas.toDataURL(); + + /** + * Ensure the div is visible + */ + if (div && div.style.opacity < 1) { + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 1", 400); + } + + /** + * Get the canvas x/y coords + */ + var c = RGraph.getCanvasXY(obj.canvas); + var x = c[0]; + var y = c[1]; + + /** + * Position the div and img + */ + var offset = 7; + + div.style.left = (e.pageX - obj.Get('chart.zoom.thumbnail.width') - offset) + 'px'; + div.style.top = (e.pageY - obj.Get('chart.zoom.thumbnail.height') - offset) + 'px'; + + var l = (obj.Get('chart.zoom.thumbnail.width') / 2) - (coords[0] * obj.Get('chart.zoom.factor')); + var t = (obj.Get('chart.zoom.thumbnail.height') / 2) - (coords[1] * obj.Get('chart.zoom.factor')); + + // More positioning + img.style.left = (l + ((obj.Get('chart.zoom.thumbnail.width') / 2) * obj.Get('chart.zoom.factor'))) + 'px'; + img.style.top = (t + ((obj.Get('chart.zoom.thumbnail.height') / 2) * obj.Get('chart.zoom.factor'))) + 'px'; + + /** + * Fire the onzoom event + */ + RGraph.FireCustomEvent(obj, 'onzoom'); + } + + /** + * The onmouseover event. Evidently. Fades the zoom window in + */ + canvas.onmouseover = function (e) + { + var div = RGraph.Registry.Get('chart.zoomed.div'); + + // ??? + if (!div) return; + + var obj = div.__object__; + + // Used for the enlargement animation + var targetWidth = obj.Get('chart.zoom.thumbnail.width'); + var targetHeight = obj.Get('chart.zoom.thumbnail.height'); + + div.style.width = 0; + div.style.height = 0; + + if (obj.Get('chart.zoom.fade.in')) { + + RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.2; + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.4", 100); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.6", 200); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.8", 300); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 1", 400); + + } else { + + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 1", 1); + } + + // The enlargement animation frames + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (1/5) ) + "px'", 75); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (2/5) ) + "px'", 150); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (3/5) ) + "px'", 225); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (4/5) ) + "px'", 300); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (5/5) ) + "px'", 325); + + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (1/5) ) + "px'", 75); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (2/5) ) + "px'", 150); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (3/5) ) + "px'", 225); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (4/5) ) + "px'", 300); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (5/5) ) + "px'", 375); + } + + canvas.onmouseout = function (e) + { + if (RGraph.Registry.Get('chart.zoomed.div') && RGraph.Registry.Get('chart.zoomed.div').__object__.Get('chart.zoom.fade.out')) { + + RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.8; + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.6", 100); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.4", 200); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.2", 300); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0", 400); + + // Get rid of the zoom window + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.left = '-400px'", 400); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.top = '-400px'", 400); + + } else { + // Get rid of the zoom window + if (RGraph.Registry.Get('chart.zoomed.div')) { + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.left = '-400px'", 1); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.top = '-400px'", 41); + } } + } + } + + + /** + * A zoom in function + * + * @param e object The event object + */ + RGraph.Zoom = function (e) + { + e = RGraph.FixEventObject(e); + + /** + * Show the zoom window + */ + //if ((e.target.__canvas__ && e.target.__canvas__.__object__.Get('chart.zoom.mode') == 'thumbnail') || (e.target.parentNode.__canvas__ && e.target.parentNode.__canvas__.__object__.Get('chart.zoom.mode') == 'thumbnail') ) { + // return RGraph.ZoomWindow(e); + //} + + var canvas = e.target.__canvas__; + var context = canvas.getContext('2d'); + var obj = canvas.__object__; + var dataurl = canvas.toDataURL(); + var tmp = canvas; + var coords = RGraph.getCanvasXY(canvas); + var factor = obj.Get('chart.zoom.factor') - 1; + + var x = coords[0]; + var y = coords[1]; + + var img = document.createElement('img'); + img.className = 'RGraph_zoomed_canvas'; + img.style.border = '3px solid gray'; + img.style.width = canvas.width + 'px'; + img.style.height = canvas.height + 'px'; + img.style.position = 'absolute'; + img.style.left = x + 'px'; + img.style.top = y + 'px'; + img.style.backgroundColor = 'white'; + img.style.opacity = obj.Get('chart.zoom.fade.in') ? 0 : 1; + img.style.zIndex = 99; + img.src = dataurl; + document.body.appendChild(img); + + //RGraph.Registry.Set('chart.zoomedimage', img); + // Store the zoomed image in a global var - NOT the registry + __zoomedimage__ = img; + __zoomedimage__.obj = obj; + + // Image onclick should not hide the image + img.onclick = function (e) + { + e = RGraph.FixEventObject(e); + e.stopPropagation(); + return false; + } + + setTimeout(function () {window.onclick = RGraph.HideZoomedCanvas;}, 1); + + var width = parseInt(canvas.width); + var height = parseInt(canvas.height); + var frames = obj.Get('chart.zoom.frames'); + var delay = obj.Get('chart.zoom.delay'); + + // Increase the width over 10 frames - center + if (obj.Get('chart.zoom.hdir') == 'center') { + + for (var i=1; i<=frames; ++i) { + var newWidth = width * factor * (i/frames) + width; + var rightHandEdge = x + canvas.width; + var newLeft = (x + (canvas.width / 2)) - (newWidth / 2); + + setTimeout("__zoomedimage__.style.width = '" + String(newWidth) + "px'; __zoomedimage__.style.left = '" + newLeft + "px'", i * delay); + } + + // Left + } else if (obj.Get('chart.zoom.hdir') == 'left') { + for (var i=1; i<=frames; ++i) { + var newWidth = width * factor * (i/frames) + width; + var rightHandEdge = x + canvas.width; + var newLeft = rightHandEdge - newWidth; + + setTimeout("__zoomedimage__.style.width = '" + String(newWidth) + "px'; __zoomedimage__.style.left = '" + newLeft + "px'", i * delay); + } + + // Right (default) + } else { + for (var i=1; i<=frames; ++i) { + var newWidth = width * factor * (i/frames) + width; + setTimeout("__zoomedimage__.style.width = '" + String(newWidth) + "px'", i * delay); + } + } + + // Increase the height over 10 frames - up + if (obj.Get('chart.zoom.vdir') == 'up') { + for (var i=1; i<=frames; ++i) { + var newHeight = (height * factor * (i/frames)) + height; + var bottomEdge = y + canvas.height; + var newTop = bottomEdge - newHeight; + + setTimeout("__zoomedimage__.style.height = '" + String(newHeight) + "px'; __zoomedimage__.style.top = '" + newTop + "px'", i * delay); + } + + // center + } else if (obj.Get('chart.zoom.vdir') == 'center') { + for (var i=1; i<=frames; ++i) { + var newHeight = (height * factor * (i/frames)) + height; + var bottomEdge = (y + (canvas.height / 2)) + (newHeight / 2); + var newTop = bottomEdge - newHeight; + + setTimeout("__zoomedimage__.style.height = '" + String(newHeight) + "px'; __zoomedimage__.style.top = '" + newTop + "px'", i * delay); + } + + // Down (default + } else { + for (var i=1; i<=frames; ++i) { + setTimeout("__zoomedimage__.style.height = '" + String(height * factor * (i/frames) + height) + "px'", i * delay); + } + } + + // If enabled, increase the opactity over 10 frames + if (obj.Get('chart.zoom.fade.in')) { + for (var i=1; i<=frames; ++i) { + setTimeout("__zoomedimage__.style.opacity = " + String(i / frames), i * delay); + } + } + + // If stipulated, produce a shadow + if (obj.Get('chart.zoom.shadow')) { + for (var i=1; i<=frames; ++i) { + setTimeout("__zoomedimage__.style.boxShadow = 'rgba(128,128,128," + Number(i / frames) / 2 + ") 0 0 15px'", i * delay); + setTimeout("__zoomedimage__.style.MozBoxShadow = 'rgba(128,128,128," + Number(i / frames) / 2 + ") 0 0 15px'", i * delay); + setTimeout("__zoomedimage__.style.WebkitBoxShadow = 'rgba(128,128,128," + Number(i / frames) / 2 + ") 0 0 15px'", i * delay); + } + } + + /** + * The onmouseout event. Hides the zoom window. Fades the zoom out + */ + canvas.onmouseout = function (e) + { + if (RGraph.Registry.Get('chart.zoomed.div') && RGraph.Registry.Get('chart.zoomed.div').__object__.Get('chart.zoom.fade.out')) { + + RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.8; + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.6", 100); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.4", 200); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.2", 300); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0", 400); + + // Get rid of the zoom window + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.left = '-400px'", 400); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.top = '-400px'", 400); + + } else { + + // Get rid of the zoom window + if (RGraph.Registry.Get('chart.zoomed.div')) { + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.left = '-400px'", 1); + setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.top = '-400px'", 1); + } + } + } + + // The background + if (obj.Get('chart.zoom.background')) { + var div = document.createElement('DIV'); + div.style.backgroundColor = '#999'; + div.style.opacity = 0; + div.style.position = 'fixed'; + div.style.top = 0; + div.style.left = 0; + div.style.width = (screen.width + 100) + 'px'; + div.style.height = (screen.height + 100) + 'px'; + div.style.zIndex = 98; + + // Hides the zoomed caboodle + div.oncontextmenu = function (e) + { + return RGraph.HideZoomedCanvas(e); + } + + // 30th July 2010 - Is this necessary? + //for (var i=1; i<=frames; ++i) { + // setTimeout('__zoomedbackground__.style.opacity = ' + Number(0.04 * i), i * delay); + // + // // MSIE doesn't support zoom + // //setTimeout('__zoomedbackground__.style.filter = "progid:DXImageTransform.Microsoft.Shadow(color=#aaaaaa,direction=135); Alpha(opacity=10)"', 50); + //} + + div.origHeight = div.style.height; + + document.body.appendChild(div); + + __zoomedbackground__ = div; + + // If the window is resized, hide the zoom + //window.onresize = RGraph.HideZoomedCanvas; + + for (var i=1; i<=frames; ++i) { + setTimeout("__zoomedbackground__.style.opacity = " + (Number(i / frames) * 0.5), i * delay); + } + } + + /** + * Fire the onzoom event + */ + RGraph.FireCustomEvent(obj, 'onzoom'); + } \ No newline at end of file diff --git a/libraries/RGraph.funnel.js b/libraries/RGraph.funnel.js new file mode 100644 index 0000000..fd274c3 --- /dev/null +++ b/libraries/RGraph.funnel.js @@ -0,0 +1,603 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The bar chart constructor + * + * @param object canvas The canvas object + * @param array data The chart data + */ + RGraph.Funnel = function (id, data) + { + // Get the canvas and context objects + this.id = id; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null; + this.canvas.__object__ = this; + this.type = 'funnel'; + this.coords = []; + this.isRGraph = true; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + + // Check for support + if (!this.canvas) { + alert('[FUNNEL] No canvas support'); + return; + } + + // Check the common library has been included + if (typeof(RGraph) == 'undefined') { + alert('[FUNNEL] Fatal error: The common library does not appear to have been included'); + } + + /** + * The funnel charts properties + */ + this.properties = { + 'chart.strokestyle': 'black', + 'chart.gutter': 25, + 'chart.labels': null, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.colors': ['red', 'green', 'gray', 'blue', 'black', 'gray'], + 'chart.text.size': 10, + 'chart.text.boxed': true, + 'chart.text.halign': 'left', + 'chart.text.color': 'black', + 'chart.text.font': 'Verdana', + 'chart.contextmenu': null, + 'chart.shadow': false, + 'chart.shadow.color': '#666', + 'chart.shadow.blur': 3, + 'chart.shadow.offsetx': 3, + 'chart.shadow.offsety': 3, + + + 'chart.key': [], + 'chart.key.background': 'white', + 'chart.key.position': 'graph', + 'chart.key.shadow': false, + 'chart.key.shadow.color': '#666', + 'chart.key.shadow.blur': 3, + 'chart.key.shadow.offsetx': 2, + 'chart.key.shadow.offsety': 2, + 'chart.key.position.gutter.boxed': true, + 'chart.key.position.x': null, + 'chart.key.position.y': null, + 'chart.key.color.shape': 'square', + 'chart.key.rounded': true, + + 'chart.tooltips': null, + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.highlight': true, + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 10, + 'chart.zoom.delay': 50, + 'chart.zoom.shadow': true, + 'chart.zoom.mode': 'canvas', + 'chart.zoom.thumbnail.width': 75, + 'chart.zoom.thumbnail.height': 75, + 'chart.zoom.background': true, + 'chart.zoom.action': 'zoom', + 'chart.resizable': false + } + + // Store the data + this.data = data; + } + + + /** + * A setter + * + * @param name string The name of the property to set + * @param value mixed The value of the property + */ + RGraph.Funnel.prototype.Set = function (name, value) + { + this.properties[name.toLowerCase()] = value; + } + + + /** + * A getter + * + * @param name string The name of the property to get + */ + RGraph.Funnel.prototype.Get = function (name) + { + return this.properties[name.toLowerCase()]; + } + + + /** + * The function you call to draw the bar chart + */ + RGraph.Funnel.prototype.Draw = function () + { + /** + * Fire the onbeforedraw event + */ + RGraph.FireCustomEvent(this, 'onbeforedraw'); + + /** + * Clear all of this canvases event handlers (the ones installed by RGraph) + */ + RGraph.ClearEventListeners(this.id); + + // This stops the coords array from growing + this.coords = []; + + RGraph.DrawTitle(this.canvas, this.Get('chart.title'), this.Get('chart.gutter'), null, this.Get('chart.text.size') + 2); + this.DrawFunnel(); + + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + /** + * The tooltip handler + */ + if (this.Get('chart.tooltips')) { + + RGraph.Register(this); + + var canvas_onclick_func = function (e) + { + RGraph.Redraw(); + + var e = RGraph.FixEventObject(e); + var canvas = e.target; + var context = canvas.getContext('2d'); + var obj = canvas.__object__; + + var mouseCoords = RGraph.getMouseXY(e); + var coords = obj.coords; + var x = mouseCoords[0]; + var y = mouseCoords[1]; + + for (i=0; i coords[i][0] + && x < coords[i][2] + && y > coords[i][1] + && y < coords[i][5] + ) { + + /** + * Handle the right corner + */ + if (x > coords[i][4]) { + var w1 = coords[i][2] - coords[i][4]; + var h1 = coords[i][5] - coords[i][3];; + var a1 = Math.atan(h1 / w1) * 57.3; // DEGREES + + var w2 = coords[i][2] - mouseCoords[0]; + var h2 = mouseCoords[1] - coords[i][1]; + var a2 = Math.atan(h2 / w2) * 57.3; // DEGREES + + if (a2 > a1) { + continue; + } + + /** + * Handle the left corner + */ + } else if (x < coords[i][6]) { + var w1 = coords[i][6] - coords[i][0]; + var h1 = coords[i][7] - coords[i][1];; + var a1 = Math.atan(h1 / w1) * 57.3; // DEGREES + + var w2 = mouseCoords[0] - coords[i][0]; + var h2 = mouseCoords[1] - coords[i][1]; + var a2 = Math.atan(h2 / w2) * 57.3; // DEGREES + + if (a2 > a1) { + continue; + } + } + + // Is there a tooltip defined? + if (!obj.Get('chart.tooltips')[i] && typeof(obj.Get('chart.tooltips')) != 'function') { + break; + } + + context.beginPath(); + + RGraph.NoShadow(obj); + + context.fillStyle = 'rgba(255,255,255,0.5)'; + context.moveTo(coords[i][0], coords[i][1]); + context.lineTo(coords[i][2], coords[i][3]); + context.lineTo(coords[i][4], coords[i][5]); + context.lineTo(coords[i][6], coords[i][7]); + context.closePath(); + + context.stroke(); + context.fill(); + + /** + * Draw the key again for in-graph keys so they don't appear "under" the highlight + */ + if (obj.Get('chart.key').length && obj.Get('chart.key.position') == 'graph') { + RGraph.DrawKey(obj, obj.Get('chart.key'), obj.Get('chart.colors')); + } + + /** + * Redraw the labels if necessary + */ + if (obj.Get('chart.labels')) { + obj.DrawLabels(); + } + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = obj.Get('chart.tooltips')(i); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[i]) == 'function') { + var text = obj.Get('chart.tooltips')[i](i); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object') { + var text = obj.Get('chart.tooltips')[i]; + + } else { + var text = ''; + } + + // Show the tooltip + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i); + + // Stop the event propagating + e.stopPropagation(); + + break; + } + } + } + this.canvas.addEventListener('click', canvas_onclick_func, false); + RGraph.AddEventListener(this.id, 'click', canvas_onclick_func); + + /** + * Onmousemove event handler + */ + var canvas_onmousemove_func = function (e) + { + var e = RGraph.FixEventObject(e); + + var canvas = e.target; + var context = canvas.getContext('2d'); + var obj = canvas.__object__; + var overFunnel = false; + var coords = obj.coords; + + var mouseCoords = RGraph.getMouseXY(e); + var x = mouseCoords[0]; + var y = mouseCoords[1]; + + for (i=0; i coords[i][0] + && x < coords[i][2] + && y > coords[i][1] + && y < coords[i][5] + ) { + + /** + * Handle the right corner + */ + if (x > coords[i][4]) { + var w1 = coords[i][2] - coords[i][4]; + var h1 = coords[i][5] - coords[i][3];; + var a1 = Math.atan(h1 / w1) * 57.3; // DEGREES + + var w2 = coords[i][2] - mouseCoords[0]; + var h2 = mouseCoords[1] - coords[i][1]; + var a2 = Math.atan(h2 / w2) * 57.3; // DEGREES + + if (a2 > a1) { + continue; + } + + /** + * Handle the left corner + */ + } else if (x < coords[i][6]) { + var w1 = coords[i][6] - coords[i][0]; + var h1 = coords[i][7] - coords[i][1];; + var a1 = Math.atan(h1 / w1) * 57.3; // DEGREES + + var w2 = mouseCoords[0] - coords[i][0]; + var h2 = mouseCoords[1] - coords[i][1]; + var a2 = Math.atan(h2 / w2) * 57.3; // DEGREES + + if (a2 > a1) { + continue; + } + } + + // Is there a tooltip defined? + if (!obj.Get('chart.tooltips')[i] && typeof(obj.Get('chart.tooltips')) != 'function') { + break; + } + + overFunnel = true; + canvas.style.cursor = 'pointer'; + + // Stop the event propagating + e.stopPropagation(); + + break; + } + } + + if (!overFunnel) { + canvas.style.cursor = 'default'; + canvas.style.cursor = 'default'; + } + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + } + + + /** + * Draw the labels on the chart + */ + this.DrawLabels(); + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail'|| this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * This function actually draws the chart + */ + RGraph.Funnel.prototype.DrawFunnel = function () + { + var context = this.context; + var canvas = this.canvas; + var width = this.canvas.width - (2 * this.Get('chart.gutter')); + var height = this.canvas.height - (2 * this.Get('chart.gutter')); + var total = RGraph.array_max(this.data); + var accheight = this.Get('chart.gutter'); + + + /** + * Loop through each segment to draw + */ + + // Set a shadow if it's been requested + if (this.Get('chart.shadow')) { + context.shadowColor = this.Get('chart.shadow.color'); + context.shadowBlur = this.Get('chart.shadow.blur'); + context.shadowOffsetX = this.Get('chart.shadow.offsetx'); + context.shadowOffsetY = this.Get('chart.shadow.offsety'); + } + + for (i=0; i 0 && this.Get('chart.shadow.offsety') < 0); + } + + context.strokeStyle = this.Get('chart.strokestyle'); + context.fillStyle = this.Get('chart.colors')[i]; + + context.beginPath(); + context.moveTo(x1, y1); + context.lineTo(x2, y2); + context.lineTo(x3, y3); + context.lineTo(x4, y4); + context.closePath(); + + /** + * Store the coordinates + */ + this.coords.push([x1, y1, x2, y2, x3, y3, x4, y4]); + + // The redrawing if the shadow is on will do the stroke + if (!this.Get('chart.shadow')) { + context.stroke(); + } + + context.fill(); + + accheight += curheight; + } + + /** + * If the shadow is enabled, redraw every segment, in order to allow for shadows going upwards + */ + if (this.Get('chart.shadow')) { + + RGraph.NoShadow(this); + + for (i=0; i 0) { + + var context = this.context; + + for (var j=0; j this.Get('chart.xmax')) { + this.Get('chart.vbars')[i][1] = 364 - this.Get('chart.vbars')[i][0]; + } + + var barX = (3 * gutter) + ( (this.Get('chart.vbars')[i][0] - this.Get('chart.xmin')) / (this.Get('chart.xmax') - this.Get('chart.xmin')) ) * (this.graphArea - (2 * gutter) ); + var barY = gutter; + var width = ( (this.graphArea - (2 * gutter)) / (this.Get('chart.xmax') - this.Get('chart.xmin')) ) * this.Get('chart.vbars')[i][1]; + var height = canvas.height - (2 * gutter); + + // Right hand bounds checking + if ( (barX + width) > (this.canvas.width - gutter) ) { + width = this.canvas.width - gutter - barX; + } + + context.fillStyle = this.Get('chart.vbars')[i][2]; + context.fillRect(barX, barY, width, height); + } + } + + + /** + * Draw the events + */ + for (i=0; i (canvas.width - gutter) ) { + barWidth = canvas.width - gutter - barStartX; + } + + // draw the border around the bar + if (this.Get('chart.borders')) { + context.strokeStyle = 'black'; + context.beginPath(); + context.strokeRect(barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin')) ); + } + + /** + * Draw the actual bar storing store the coordinates + */ + this.coords.push([barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin'))]); + context.fillRect(barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin')) ); + + // Work out the completeage indicator + var complete = (ev[2] / 100) * barWidth; + + // Draw the % complete indicator. If it's greater than 0 + if (typeof(ev[2]) == 'number') { + context.beginPath(); + context.fillStyle = ev[5] ? ev[5] : '#0c0'; + context.fillRect(barStartX, + barStartY + this.Get('chart.margin'), + (ev[2] / 100) * barWidth, + this.barHeight - (2 * this.Get('chart.margin')) ); + + context.beginPath(); + context.fillStyle = this.Get('chart.text.color'); + RGraph.Text(context, this.Get('chart.text.font'), this.Get('chart.text.size'), barStartX + barWidth + 5, barStartY + this.halfBarHeight, String(ev[2]) + '%', 'center'); + } + } + + + /** + * If tooltips are defined, handle them + */ + if (this.Get('chart.tooltips')) { + + // Register the object for redrawing + RGraph.Register(this); + + /** + * If the cursor is over a hotspot, change the cursor to a hand + */ + var canvas_onmousemove_func = function (eventObj) + { + eventObj = RGraph.FixEventObject(eventObj); + var canvas = eventObj.target; + var obj = canvas.__object__; + var len = obj.coords.length; + + /** + * Get the mouse X/Y coordinates + */ + var mouseCoords = RGraph.getMouseXY(eventObj); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0; i= left + && mouseX <= (left + width) + && mouseY >= top + && mouseY <= (top + height) + && (typeof(obj.Get('chart.tooltips')) == 'function' || obj.Get('chart.tooltips')[i]) ) { + + canvas.style.cursor = 'pointer'; + return; + } + } + + canvas.style.cursor = 'default'; + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + + + var canvas_onclick_func = function (eventObj) + { + eventObj = RGraph.FixEventObject(eventObj); + + var canvas = eventObj.target; + var context = canvas.getContext('2d'); + var obj = canvas.__object__; + + var mouseCoords = RGraph.getMouseXY(eventObj); + var mouseX = mouseCoords[0]; + var mouseY = mouseCoords[1]; + + + for (i=0; i= xCoord + && (mouseX <= xCoord + width) + && mouseY >= yCoord + && (mouseY <= yCoord + height) + && obj.Get('chart.tooltips') + ) { + + // Redraw the graph + RGraph.Redraw(); + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = obj.Get('chart.tooltips')(idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') { + var text = obj.Get('chart.tooltips')[idx](idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object') { + var text = obj.Get('chart.tooltips')[idx]; + + } else { + var text = null; + } + + if (String(text).length && text != null) { + + // SHOW THE CORRECT TOOLTIP + RGraph.Tooltip(canvas, text, eventObj.pageX, eventObj.pageY, idx); + + /** + * Draw a rectangle around the correct bar, in effect highlighting it + */ + context.strokeStyle = 'black'; + context.fillStyle = 'rgba(255,255,255,0.8)'; + context.strokeRect(xCoord, yCoord, width, height); + context.fillRect(xCoord, yCoord, width, height); + + eventObj.stopPropagation(); + } + return; + } + } + } + this.canvas.addEventListener('click', canvas_onclick_func, false); + RGraph.AddEventListener(this.id, 'click', canvas_onclick_func); + } + } \ No newline at end of file diff --git a/libraries/RGraph.hbar.js b/libraries/RGraph.hbar.js new file mode 100644 index 0000000..6c18ad7 --- /dev/null +++ b/libraries/RGraph.hbar.js @@ -0,0 +1,893 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The horizontal bar chart constructor. The horizontal bar is a minor variant + * on the bar chart. If you have big labels, this may be useful as there is usually + * more space available for them. + * + * @param object canvas The canvas object + * @param array data The chart data + */ + RGraph.HBar = function (id, data) + { + // Get the canvas and context objects + this.id = id; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null; + this.canvas.__object__ = this; + this.data = data; + this.type = 'hbar'; + this.coords = []; + this.isRGraph = true; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + + this.max = 0; + this.stackedOrGrouped = false; + + // Default properties + this.properties = { + 'chart.gutter': 25, + 'chart.background.grid': true, + 'chart.background.grid.color': '#ddd', + 'chart.background.grid.width': 1, + 'chart.background.grid.hsize': 25, + 'chart.background.grid.vsize': 25, + 'chart.background.barcolor1': 'white', + 'chart.background.barcolor2': 'white', + 'chart.background.grid.hlines': true, + 'chart.background.grid.vlines': true, + 'chart.background.grid.border': true, + 'chart.background.grid.autofit':false, + 'chart.background.grid.autofit.numhlines': 14, + 'chart.background.grid.autofit.numvlines': 20, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.xaxis': '', + 'chart.title.yaxis': '', + 'chart.title.xaxis.pos': 0.25, + 'chart.title.yaxis.pos': 0.5, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.text.size': 10, + 'chart.text.color': 'black', + 'chart.text.font': 'Verdana', + 'chart.colors': ['rgb(0,0,255)', '#0f0', '#00f', '#ff0', '#0ff', '#0f0'], + 'chart.labels': [], + 'chart.labels.above': false, + 'chart.labels.above.decimals': 0, + 'chart.contextmenu': null, + 'chart.key': [], + 'chart.key.background': 'white', + 'chart.key.position': 'graph', + 'chart.key.shadow': false, + 'chart.key.shadow.color': '#666', + 'chart.key.shadow.blur': 3, + 'chart.key.shadow.offsetx': 2, + 'chart.key.shadow.offsety': 2, + 'chart.key.position.gutter.boxed': true, + 'chart.key.position.x': null, + 'chart.key.position.y': null, + 'chart.key.color.shape': 'square', + 'chart.key.rounded': true, + 'chart.units.pre': '', + 'chart.units.post': '', + 'chart.units.ingraph': false, + 'chart.strokestyle': 'black', + 'chart.xmax': 0, + 'chart.axis.color': 'black', + 'chart.shadow': false, + 'chart.shadow.color': '#666', + 'chart.shadow.blur': 3, + 'chart.shadow.offsetx': 3, + 'chart.shadow.offsety': 3, + 'chart.vmargin': 3, + 'chart.grouping': 'grouped', + 'chart.tooltips': null, + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.highlight': true, + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 10, + 'chart.zoom.delay': 50, + 'chart.zoom.shadow': true, + 'chart.zoom.mode': 'canvas', + 'chart.zoom.thumbnail.width': 75, + 'chart.zoom.thumbnail.height': 75, + 'chart.zoom.background': true, + 'chart.zoom.action': 'zoom', + 'chart.resizable': false, + 'chart.scale.point': '.', + 'chart.scale.thousand': ',', + 'chart.scale.decimals': null + } + + // Check for support + if (!this.canvas) { + alert('[HBAR] No canvas support'); + return; + } + + // Check the canvasText library has been included + if (typeof(RGraph) == 'undefined') { + alert('[HBAR] Fatal error: The common library does not appear to have been included'); + } + + for (i=0; i= (left) + && mouseX <= (left + width) + && mouseY >= top + && mouseY <= (top + height) + && ( typeof(obj.Get('chart.tooltips')) == 'function' + || obj.Get('chart.tooltips')[i] + ) ) { + + canvas.style.cursor = 'pointer'; + return; + } + + canvas.style.cursor = 'default'; + } + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + + + /** + * Install the onclick event handler for the tooltips + */ + //this.canvas.onclick = function (e) + var canvas_onclick_func = function (e) + { + e = RGraph.FixEventObject(e); + + //var canvas = document.getElementById(this.id); + var canvas = e.target; + var obj = canvas.__object__; + + /** + * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn + * This "deselects" any already selected bar + */ + RGraph.Redraw(); + + /** + * Get the mouse X/Y coordinates + */ + var mouseCoords = RGraph.getMouseXY(e); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0,len=obj.coords.length; i= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) { + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = obj.Get('chart.tooltips')(idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') { + var text = obj.Get('chart.tooltips')[idx](idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object') { + var text = obj.Get('chart.tooltips')[idx]; + + } else { + var text = null; + } + + /** + * Show a tooltip if it's defined + */ + if (String(text).length && text != null) { + + obj.context.beginPath(); + obj.context.strokeStyle = 'black'; + obj.context.fillStyle = 'rgba(255,255,255,0.5)'; + obj.context.strokeRect(left, top, width, height); + obj.context.fillRect(left, top, width, height); + + obj.context.stroke(); + obj.context.fill(); + + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i); + } + } + } + + /** + * Stop the event bubbling + */ + e.stopPropagation(); + } + this.canvas.addEventListener('click', canvas_onclick_func, false); + RGraph.AddEventListener(this.id, 'click', canvas_onclick_func); + + // This resets the bar graph + if (RGraph.Registry.Get('chart.tooltip')) { + RGraph.Registry.Get('chart.tooltip').style.display = 'none'; + RGraph.Registry.Set('chart.tooltip', null) + } + } + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + + /** + * Draw "in graph" labels + */ + RGraph.DrawInGraphLabels(this); + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + /** + * This draws the axes + */ + RGraph.HBar.prototype.DrawAxes = function () + { + var gutter = this.Get('chart.gutter'); + var halfway = ((this.canvas.width - (4 * gutter)) / 2) + (3 * gutter); + + this.context.beginPath(); + this.context.lineWidth = 1; + this.context.strokeStyle = this.Get('chart.axis.color'); + + // Draw the Y axis + if (this.Get('chart.yaxispos') == 'center') { + this.context.moveTo(halfway, gutter); + this.context.lineTo(halfway, this.canvas.height - gutter); + } else { + this.context.moveTo(gutter * 3, gutter); + this.context.lineTo(gutter * 3, this.canvas.height - gutter); + } + + // Draw the X axis + this.context.moveTo(gutter * 3, this.canvas.height - gutter); + this.context.lineTo(this.canvas.width - gutter, this.canvas.height - gutter); + + // Draw the Y tickmarks + var yTickGap = (this.canvas.height - (2 * gutter)) / this.data.length; + + for (y=gutter; y<(this.canvas.height - gutter); y+=yTickGap) { + if (this.Get('chart.yaxispos') == 'center') { + this.context.moveTo(halfway + 3, y); + this.context.lineTo(halfway - 3, y); + } else { + this.context.moveTo(gutter * 3, y); + this.context.lineTo( (gutter * 3) - 3, y); + } + } + + + // Draw the X tickmarks + xTickGap = (this.canvas.width - (4 * gutter) ) / 10; + yStart = this.canvas.height - gutter; + yEnd = (this.canvas.height - gutter) + 3; + + for (x=(this.canvas.width - gutter), i=0; this.Get('chart.yaxispos') == 'center' ? x>=(3 * gutter) : x>(3*gutter); x-=xTickGap) { + + if (this.Get('chart.yaxispos') != 'center' || i != 5) { + this.context.moveTo(x, yStart); + this.context.lineTo(x, yEnd); + } + i++; + } + + this.context.stroke(); + } + + + /** + * This function draws the background. The common function isn't used because the left gutter is + * three times as big. + * + * @param object obj The graph object + */ + RGraph.HBar.prototype.DrawBackground = function () + { + var gutter = this.Get('chart.gutter'); + var size = this.Get('chart.text.size'); + var font = this.Get('chart.text.font'); + var canvas = this.canvas; + var context = this.context; + + this.context.beginPath(); + + // Draw the horizontal bars + this.context.fillStyle = this.Get('chart.background.barcolor1'); + for (var i=gutter; i < (canvas.height - gutter); i+=80) { + context.fillRect (gutter * 3, i, canvas.width - (gutter * 4), Math.min(40, canvas.height - gutter - i) ); + } + + this.context.fillStyle = this.Get('chart.background.barcolor2'); + for (var i= (40 + gutter); i < (canvas.height - gutter); i+=80) { + context.fillRect (gutter * 3, i, canvas.width - (gutter * 4), i + 40 > (canvas.height - gutter) ? canvas.height - (gutter + i) : 40); + } + + this.context.stroke(); + + // Draw the background grid + if (this.Get('chart.background.grid')) { + + // If autofit is specified, use the .numhlines and .numvlines along with the width to work + // out the hsize and vsize + if (this.Get('chart.background.grid.autofit')) { + var vsize = (canvas.width - (4 * gutter)) / this.Get('chart.background.grid.autofit.numvlines'); + var hsize = (canvas.height - (4 * gutter)) / this.Get('chart.background.grid.autofit.numhlines'); + + this.Set('chart.background.grid.vsize', vsize); + this.Set('chart.background.grid.hsize', hsize); + } + + context.beginPath(); + context.lineWidth = this.Get('chart.background.grid.width'); + context.strokeStyle = this.Get('chart.background.grid.color'); + + // Draw the horizontal lines + if (this.Get('chart.background.grid.hlines')) { + for (y=gutter; y < (canvas.height - gutter); y+=this.Get('chart.background.grid.hsize')) { + context.moveTo(gutter * 3, y); + context.lineTo(canvas.width - gutter, y); + } + } + + // Draw the vertical lines + if (this.Get('chart.background.grid.vlines')) { + for (x=gutter * 3; x <= (canvas.width - gutter); x+=this.Get('chart.background.grid.vsize')) { + context.moveTo(x, gutter); + context.lineTo(x, canvas.height - gutter); + } + } + + if (this.Get('chart.background.grid.border')) { + // Make sure a rectangle, the same colour as the grid goes around the graph + context.strokeStyle = this.Get('chart.background.grid.color'); + context.strokeRect(gutter * 3, gutter, canvas.width - (4 * gutter), canvas.height - (2 * gutter)); + } + } + + context.stroke(); + + + // Draw the title if one is set + if ( typeof(this.Get('chart.title')) == 'string') { + + RGraph.DrawTitle(canvas, + this.Get('chart.title'), + gutter, + (3 * gutter) + ((canvas.width - (4 * gutter)) / 2), + size + 2); + } + + context.stroke(); + + + // X axis title + if (typeof(this.Get('chart.title.xaxis')) == 'string' && this.Get('chart.title.xaxis').length) { + context.beginPath(); + RGraph.Text(context, font, size + 2, canvas.width / 2, canvas.height - (gutter * this.Get('chart.title.xaxis.pos')), this.Get('chart.title.xaxis'), 'center', 'center', false, false, false, true); + context.fill(); + } + + + // Y axis title + if (typeof(this.Get('chart.title.yaxis')) == 'string' && this.Get('chart.title.yaxis').length) { + context.beginPath(); + RGraph.Text(context, font, size + 2, gutter * this.Get('chart.title.yaxis.pos'), canvas.height / 2, this.Get('chart.title.yaxis'), 'center', 'center', false, 270, false, true); + context.fill(); + } + } + + + /** + * This draws the labels for the graph + */ + RGraph.HBar.prototype.DrawLabels = function () + { + var gutter = this.Get('chart.gutter'); + var context = this.context; + var canvas = this.canvas; + var units_pre = this.Get('chart.units.pre'); + var units_post = this.Get('chart.units.post'); + var text_size = this.Get('chart.text.size'); + var font = this.Get('chart.text.font'); + + + /** + * Set the units to blank if they're to be used for ingraph labels only + */ + if (this.Get('chart.units.ingraph')) { + units_pre = ''; + units_post = ''; + } + + + /** + * Draw the X axis labels + */ + this.context.beginPath(); + this.context.fillStyle = this.Get('chart.text.color'); + + //var interval = (this.canvas.width - (4 * gutter)) / (t ? 10 : 5); + + if (this.Get('chart.yaxispos') == 'center') { + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (10/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[4], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (9/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (8/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (7/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (6/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', 'center'); + + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (4/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, -1 * this.scale[0], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (3/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, -1 * this.scale[1], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (2/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, -1 * this.scale[2], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (1/10)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, -1 * this.scale[3], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (0)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, -1 * this.scale[4], units_pre, units_post), 'center', 'center'); + + } else { + + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (5/5)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[4], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (4/5)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (3/5)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (2/5)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', 'center'); + RGraph.Text(context, font, text_size, (gutter * 3) + (this.graphwidth * (1/5)), gutter + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', 'center'); + } + + this.context.fill(); + this.context.stroke(); + + /** + * The Y axis labels + */ + if (typeof(this.Get('chart.labels')) == 'object') { + + var xOffset = 5; + var font = this.Get('chart.text.font'); + + // Draw the X axis labels + this.context.fillStyle = this.Get('chart.text.color'); + + // How wide is each bar + var barHeight = (this.canvas.height - (2 * gutter) ) / this.Get('chart.labels').length; + + // Reset the xTickGap + yTickGap = (this.canvas.height - (2 * gutter)) / this.Get('chart.labels').length + + // Draw the X tickmarks + var i=0; + for (y=gutter + (yTickGap / 2); y<=this.canvas.height - gutter; y+=yTickGap) { + RGraph.Text(this.context, font, + this.Get('chart.text.size'), + (gutter * 3) - xOffset, + y, + String(this.Get('chart.labels')[i++]), + 'center', + 'right'); + } + } + } + + + /** + * This function draws the actual bars + */ + RGraph.HBar.prototype.Drawbars = function () + { + this.context.lineWidth = 1; + this.context.strokeStyle = this.Get('chart.strokestyle'); + this.context.fillStyle = this.Get('chart.colors')[0]; + var prevX = 0; + var prevY = 0; + + /** + * Work out the max value + */ + if (this.Get('chart.xmax')) { + this.scale = [ + (this.Get('chart.xmax') * 0.2).toFixed(this.Get('chart.scale.decimals')), + (this.Get('chart.xmax') * 0.4).toFixed(this.Get('chart.scale.decimals')), + (this.Get('chart.xmax') * 0.6).toFixed(this.Get('chart.scale.decimals')), + (this.Get('chart.xmax') * 0.8).toFixed(this.Get('chart.scale.decimals')), + (this.Get('chart.xmax')).toFixed(this.Get('chart.scale.decimals')) + ]; + this.max = this.scale[4]; + } else { + var grouping = this.Get('chart.grouping'); + + for (i=0; i this.canvas.width ? true : false; + + RGraph.Text(this.context,this.Get('chart.text.font'),this.Get('chart.text.size'),coords[i][0] + coords[i][2] + (border ? -5 : 5),coords[i][1] + (coords[i][3] / 2),RGraph.number_format(this, (this.coords[i][5]).toFixed(this.Get('chart.labels.above.decimals')), this.Get('chart.units.pre'), this.Get('chart.units.post')),'center',border ? 'right' : 'left',border,null,border ? 'rgba(255,255,255,0.9)' : null); + + } + } + } diff --git a/libraries/RGraph.hprogress.js b/libraries/RGraph.hprogress.js new file mode 100644 index 0000000..15f9276 --- /dev/null +++ b/libraries/RGraph.hprogress.js @@ -0,0 +1,545 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The progress bar constructor + * + * @param int id The ID of the canvas tag + * @param int value The indicated value of the meter. + * @param int max The end value (the upper most) of the meter + */ + RGraph.HProgress = function (id, value, max) + { + this.id = id; + this.max = max; + this.value = value; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext('2d'); + this.canvas.__object__ = this; + this.type = 'hprogress'; + this.coords = []; + this.isRGraph = true; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + this.properties = { + 'chart.min': 0, + 'chart.colors': ['#0c0'], + 'chart.tickmarks': true, + 'chart.tickmarks.color': 'black', + 'chart.tickmarks.inner': false, + 'chart.gutter': 25, + 'chart.numticks': 10, + 'chart.numticks.inner': 50, + 'chart.background.color': '#eee', + 'chart.shadow': false, + 'chart.shadow.color': 'rgba(0,0,0,0.5)', + 'chart.shadow.blur': 3, + 'chart.shadow.offsetx': 3, + 'chart.shadow.offsety': 3, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.width': 0, + 'chart.height': 0, + 'chart.text.size': 10, + 'chart.text.color': 'black', + 'chart.text.font': 'Verdana', + 'chart.contextmenu': null, + 'chart.units.pre': '', + 'chart.units.post': '', + 'chart.tooltips': [], + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.highlight': true, + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.zoom.mode': 'canvas', + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 10, + 'chart.zoom.delay': 50, + 'chart.zoom.shadow': true, + 'chart.zoom.background': true, + 'chart.zoom.thumbnail.width': 100, + 'chart.zoom.thumbnail.height': 100, + 'chart.arrows': false, + 'chart.margin': 0, + 'chart.resizable': false, + 'chart.label.inner': false, + 'chart.adjustable': false, + 'chart.scale.decimals': 0 + } + + // Check for support + if (!this.canvas) { + alert('[PROGRESS] No canvas support'); + return; + } + + // Check the common library has been included + if (typeof(RGraph) == 'undefined') { + alert('[PROGRESS] Fatal error: The common library does not appear to have been included'); + } + } + + + /** + * A generic setter + * + * @param string name The name of the property to set + * @param string value The value of the poperty + */ + RGraph.HProgress.prototype.Set = function (name, value) + { + this.properties[name.toLowerCase()] = value; + } + + + /** + * A generic getter + * + * @param string name The name of the property to get + */ + RGraph.HProgress.prototype.Get = function (name) + { + return this.properties[name.toLowerCase()]; + } + + + /** + * Draws the progress bar + */ + RGraph.HProgress.prototype.Draw = function () + { + /** + * Fire the onbeforedraw event + */ + RGraph.FireCustomEvent(this, 'onbeforedraw'); + + /** + * Clear all of this canvases event handlers (the ones installed by RGraph) + */ + RGraph.ClearEventListeners(this.id); + + // Figure out the width and height + this.width = this.canvas.width - (2 * this.Get('chart.gutter')); + this.height = this.canvas.height - (2 * this.Get('chart.gutter')); + this.coords = []; + + this.Drawbar(); + this.DrawTickMarks(); + this.DrawLabels(); + + this.context.stroke(); + this.context.fill(); + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + /** + * Alternatively, show the tooltip if requested + */ + if (typeof(this.Get('chart.tooltips')) == 'function' || this.Get('chart.tooltips').length) { + + // Need to register this object for redrawing + RGraph.Register(this); + + /** + * Install the window onclick handler + */ + window.onclick = function () + { + RGraph.Redraw(); + } + + + /** + * Install the onclick event handler for the tooltips + */ + var canvas_onclick_func = function (e) + { + e = RGraph.FixEventObject(e); + + var canvas = document.getElementById(this.id); + var obj = canvas.__object__; + + /** + * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn + * This "deselects" any already selected bar + */ + RGraph.Redraw(); + + /** + * Get the mouse X/Y coordinates + */ + var mouseCoords = RGraph.getMouseXY(e); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0; i= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) { + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = obj.Get('chart.tooltips')(idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') { + var text = obj.Get('chart.tooltips')[idx](idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object') { + var text = obj.Get('chart.tooltips')[idx]; + + } else { + var text = null; + } + + /** + * Show a tooltip if it's defined + */ + if (text) { + + obj.context.beginPath(); + obj.context.strokeStyle = 'black'; + obj.context.fillStyle = 'rgba(255,255,255,0.5)'; + obj.context.strokeRect(left, top, width, height); + obj.context.fillRect(left, top, width, height); + + obj.context.stroke(); + obj.context.fill(); + + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i); + } + } + } + + /** + * Stop the event bubbling + */ + e.stopPropagation(); + } + this.canvas.addEventListener('click', canvas_onclick_func, false); + RGraph.AddEventListener(this.id, 'click', canvas_onclick_func); + + /** + * If the cursor is over a hotspot, change the cursor to a hand + */ + var canvas_onmousemove_func = function (e) + { + e = RGraph.FixEventObject(e); + + var canvas = document.getElementById(this.id); + var obj = canvas.__object__; + + /** + * Get the mouse X/Y coordinates + */ + var mouseCoords = RGraph.getMouseXY(e); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0; i= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) { + canvas.style.cursor = 'pointer'; + break; + } + + canvas.style.cursor = 'default'; + } + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + } + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + /** + * Instead of using RGraph.common.adjusting.js, handle them here + */ + if (this.Get('chart.adjustable')) { + RGraph.AllowAdjusting(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + /** + * Draws the bar + */ + RGraph.HProgress.prototype.Drawbar = function () + { + // Set a shadow if requested + if (this.Get('chart.shadow')) { + RGraph.SetShadow(this, this.Get('chart.shadow.color'), this.Get('chart.shadow.offsetx'), this.Get('chart.shadow.offsety'), this.Get('chart.shadow.blur')); + } + + // Draw the shadow for MSIE + if (RGraph.isIE8() && this.Get('chart.shadow')) { + this.context.fillStyle = this.Get('chart.shadow.color'); + this.context.fillRect(this.Get('chart.gutter') + this.Get('chart.shadow.offsetx'), this.Get('chart.gutter') + this.Get('chart.shadow.offsety'), this.width, this.height); + } + + // Draw the outline + this.context.fillStyle = this.Get('chart.background.color'); + this.context.strokeStyle = 'black'; + this.context.strokeRect(this.Get('chart.gutter'), this.Get('chart.gutter'), this.width, this.height); + this.context.fillRect(this.Get('chart.gutter'), this.Get('chart.gutter'), this.width, this.height); + + // Turn off any shadow + RGraph.NoShadow(this); + + this.context.fillStyle = this.Get('chart.color'); + this.context.strokeStyle = 'black'; + + var margin = this.Get('chart.margin'); + + // Draw the actual bar itself + var barWidth = Math.min(this.width, ((RGraph.array_sum(this.value) - this.Get('chart.min')) / (this.max - this.Get('chart.min')) ) * this.width); + + if (this.Get('chart.tickmarks.inner')) { + + var spacing = (this.canvas.width - this.Get('chart.gutter') - this.Get('chart.gutter')) / this.Get('chart.numticks.inner'); + + this.context.lineWidth = 1; + this.context.strokeStyle = '#999'; + + this.context.beginPath(); + for (var x = this.Get('chart.gutter'); x 0) { + alert('[RGRAPH WARNING] Chrome 6 has a shadow bug, meaning you should increase the linewidth to at least 1.01'); + } + + + // Cache the gutter as an object variable + this.gutter = this.Get('chart.gutter'); + + // Reset the data back to that which was initially supplied + this.data = RGraph.array_clone(this.original_data); + + + // Reset the max value + this.max = 0; + + /** + * Reverse the datasets so that the data and the labels tally + */ + this.data = RGraph.array_reverse(this.data); + + if (this.Get('chart.filled') && !this.Get('chart.filled.range') && this.data.length > 1) { + + var accumulation = []; + + for (var set=0; set 0) { + RGraph.DrawBars(this); + } + + if (this.Get('chart.axesontop') == false) { + this.DrawAxes(); + } + + /** + * Handle the appropriate shadow color. This now facilitates an array of differing + * shadow colors + */ + var shadowColor = this.Get('chart.shadow.color'); + + if (typeof(shadowColor) == 'object') { + shadowColor = RGraph.array_reverse(RGraph.array_clone(this.Get('chart.shadow.color'))); + } + + for (var i=(this.data.length - 1), j=0; i>=0; i--, j++) { + + this.context.beginPath(); + + /** + * Turn on the shadow if required + */ + if (this.Get('chart.shadow') && !this.Get('chart.filled')) { + + /** + * Accommodate an array of shadow colors as well as a single string + */ + if (typeof(shadowColor) == 'object' && shadowColor[i - 1]) { + this.context.shadowColor = shadowColor[i]; + } else if (typeof(shadowColor) == 'object') { + this.context.shadowColor = shadowColor[0]; + } else if (typeof(shadowColor) == 'string') { + this.context.shadowColor = shadowColor; + } + + this.context.shadowBlur = this.Get('chart.shadow.blur'); + this.context.shadowOffsetX = this.Get('chart.shadow.offsetx'); + this.context.shadowOffsetY = this.Get('chart.shadow.offsety'); + + } else if (this.Get('chart.filled') && this.Get('chart.shadow')) { + alert('[LINE] Shadows are not permitted when the line is filled'); + } + + /** + * Draw the line + */ + + if (this.Get('chart.fillstyle')) { + if (typeof(this.Get('chart.fillstyle')) == 'object' && this.Get('chart.fillstyle')[j]) { + var fill = this.Get('chart.fillstyle')[j]; + + } else if (typeof(this.Get('chart.fillstyle')) == 'string') { + var fill = this.Get('chart.fillstyle'); + + } else { + alert('[LINE] Warning: chart.fillstyle must be either a string or an array with the same number of elements as you have sets of data'); + } + } else if (this.Get('chart.filled')) { + var fill = this.Get('chart.colors')[j]; + + } else { + var fill = null; + } + + /** + * Figure out the tickmark to use + */ + if (this.Get('chart.tickmarks') && typeof(this.Get('chart.tickmarks')) == 'object') { + var tickmarks = this.Get('chart.tickmarks')[i]; + } else if (this.Get('chart.tickmarks') && typeof(this.Get('chart.tickmarks')) == 'string') { + var tickmarks = this.Get('chart.tickmarks'); + } else if (this.Get('chart.tickmarks') && typeof(this.Get('chart.tickmarks')) == 'function') { + var tickmarks = this.Get('chart.tickmarks'); + } else { + var tickmarks = null; + } + + + this.DrawLine(this.data[i], + this.Get('chart.colors')[j], + fill, + this.GetLineWidth(j), + tickmarks); + + this.context.stroke(); + } + + + + + + + + + + + + + /** + * If tooltips are defined, handle them + */ + if (this.Get('chart.tooltips') && (this.Get('chart.tooltips').length || typeof(this.Get('chart.tooltips')) == 'function')) { + + // Need to register this object for redrawing + if (this.Get('chart.tooltips.highlight')) { + RGraph.Register(this); + } + + canvas_onmousemove_func = function (e) + { + e = RGraph.FixEventObject(e); + + var canvas = e.target; + var context = canvas.getContext('2d'); + var obj = canvas.__object__; + var point = obj.getPoint(e); + + if (obj.Get('chart.tooltips.highlight')) { + RGraph.Register(obj); + } + + if ( point + && typeof(point[0]) == 'object' + && typeof(point[1]) == 'number' + && typeof(point[2]) == 'number' + && typeof(point[3]) == 'number' + ) { + + // point[0] is the graph object + var xCoord = point[1]; + var yCoord = point[2]; + var idx = point[3]; + + if ((obj.Get('chart.tooltips')[idx] || typeof(obj.Get('chart.tooltips')) == 'function')) { + + // Get the tooltip text + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = obj.Get('chart.tooltips')(idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') { + var text = obj.Get('chart.tooltips')[idx](idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object') { + var text = String(obj.Get('chart.tooltips')[idx]); + + } else { + var text = ''; + } + + // Chnage the pointer to a hand + canvas.style.cursor = 'pointer'; + + /** + * If the tooltip is the same one as is currently visible (going by the array index), don't do squat and return. + */ + if (RGraph.Registry.Get('chart.tooltip') && RGraph.Registry.Get('chart.tooltip').__index__ == idx && RGraph.Registry.Get('chart.tooltip').__canvas__.id == canvas.id) { + return; + } + + /** + * Redraw the graph + */ + if (obj.Get('chart.tooltips.highlight')) { + // Redraw the graph + RGraph.Redraw(); + } + + // SHOW THE CORRECT TOOLTIP + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, idx); + + // Store the tooltip index on the tooltip object + RGraph.Registry.Get('chart.tooltip').__index__ = Number(idx); + + /** + * Highlight the graph + */ + if (obj.Get('chart.tooltips.highlight')) { + context.beginPath(); + context.moveTo(xCoord, yCoord); + context.arc(xCoord, yCoord, 2, 0, 6.28, 0); + context.strokeStyle = '#999'; + context.fillStyle = 'white'; + context.stroke(); + context.fill(); + } + + e.stopPropagation(); + return; + } + } + + /** + * Not over a hotspot? + */ + canvas.style.cursor = 'default'; + } + + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + } + + + + + + + + + + + + + + + /** + * If the axes have been requested to be on top, do that + */ + if (this.Get('chart.axesontop')) { + this.DrawAxes(); + } + + /** + * Draw the labels + */ + this.DrawLabels(); + + /** + * Draw the range if necessary + */ + this.DrawRange(); + + // Draw a key if necessary + if (this.Get('chart.key').length) { + RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.colors')); + } + + /** + * Draw " above" labels if enabled + */ + if (this.Get('chart.labels.above')) { + this.DrawAboveLabels(); + } + + /** + * Draw the "in graph" labels + */ + RGraph.DrawInGraphLabels(this); + + /** + * Draw crosschairs + */ + RGraph.DrawCrosshairs(this); + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * Redraw the lines if a filled range is on the cards + */ + if (this.Get('chart.filled') && this.Get('chart.filled.range') && this.data.length == 2) { + + this.context.beginPath(); + var len = this.coords.length / 2; + this.context.lineWidth = this.Get('chart.linewidth'); + this.context.strokeStyle = this.Get('chart.colors')[0]; + + for (var i=0; i=len; --i) { + if (i == (this.coords.length - 1) ) { + this.context.moveTo(this.coords[i][0], this.coords[i][1]); + } else { + this.context.lineTo(this.coords[i][0], this.coords[i][1]); + } + } + + this.context.stroke(); + } else if (this.Get('chart.filled') && this.Get('chart.filled.range')) { + alert('[LINE] You must have only two sets of data for a filled range chart'); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail') { + RGraph.ShowZoomWindow(this); + } + + /** + * This function enables the zoom in area mode + */ + if (this.Get('chart.zoom.mode') == 'area') { + RGraph.ZoomArea(this); + } + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + /** + * This function enables adjustments + */ + if (this.Get('chart.adjustable')) { + RGraph.AllowAdjusting(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * Draws the axes + */ + RGraph.Line.prototype.DrawAxes = function () + { + var gutter = this.gutter; + + // Don't draw the axes? + if (this.Get('chart.noaxes')) { + return; + } + + // Turn any shadow off + RGraph.NoShadow(this); + + this.context.lineWidth = 1; + this.context.strokeStyle = this.Get('chart.axis.color'); + this.context.beginPath(); + + // Draw the X axis + if (this.Get('chart.noxaxis') == false) { + if (this.Get('chart.xaxispos') == 'center') { + this.context.moveTo(gutter, this.grapharea / 2 + gutter); + this.context.lineTo(this.canvas.width - gutter, this.grapharea / 2 + gutter); + } else { + this.context.moveTo(gutter, this.canvas.height - gutter); + this.context.lineTo(this.canvas.width - gutter, this.canvas.height - gutter); + } + } + + // Draw the Y axis + if (this.Get('chart.noyaxis') == false) { + if (this.Get('chart.yaxispos') == 'left') { + this.context.moveTo(gutter, gutter); + this.context.lineTo(gutter, this.canvas.height - (gutter) ); + } else { + this.context.moveTo(this.canvas.width - gutter, gutter); + this.context.lineTo(this.canvas.width - gutter, this.canvas.height - gutter ); + } + } + + /** + * Draw the X tickmarks + */ + if (this.Get('chart.noxaxis') == false) { + var xTickInterval = (this.canvas.width - (2 * gutter)) / (this.Get('chart.xticks') ? this.Get('chart.xticks') : this.data[0].length); + + for (x=gutter + (this.Get('chart.yaxispos') == 'left' ? xTickInterval : 0); x<=(this.canvas.width - gutter + 1 ); x+=xTickInterval) { + + if (this.Get('chart.yaxispos') == 'right' && x >= (this.canvas.width - gutter - 1) ) { + break; + } + + // If the last tick is not desired... + if (this.Get('chart.noendxtick')) { + if (this.Get('chart.yaxispos') == 'left' && x >= (this.canvas.width - gutter)) { + break; + } else if (this.Get('chart.yaxispos') == 'right' && x == gutter) { + continue; + } + } + + var yStart = this.Get('chart.xaxispos') == 'center' ? (this.canvas.height / 2) - 3 : this.canvas.height - gutter; + var yEnd = this.Get('chart.xaxispos') == 'center' ? yStart + 6 : this.canvas.height - gutter - (x % 60 == 0 ? this.Get('chart.largexticks') * this.Get('chart.tickdirection') : this.Get('chart.smallxticks') * this.Get('chart.tickdirection')); + + this.context.moveTo(x, yStart); + this.context.lineTo(x, yEnd); + } + + // Draw an extra tickmark if there is no X axis, but there IS a Y axis + } else if (this.Get('chart.noyaxis') == false) { + + if (this.Get('chart.yaxispos') == 'left') { + this.context.moveTo(this.Get('chart.gutter'), this.canvas.height - this.Get('chart.gutter')); + this.context.lineTo(this.Get('chart.gutter') - this.Get('chart.smallyticks'), this.canvas.height - this.Get('chart.gutter')); + } else { + this.context.moveTo(this.canvas.width - this.Get('chart.gutter'), this.canvas.height - this.Get('chart.gutter')); + this.context.lineTo(this.canvas.width - this.Get('chart.gutter') + this.Get('chart.smallyticks'), this.canvas.height - this.Get('chart.gutter')); + } + } + + /** + * Draw the Y tickmarks + */ + if (this.Get('chart.noyaxis') == false) { + var counter = 0; + var adjustment = 0; + + if (this.Get('chart.yaxispos') == 'right') { + adjustment = (this.canvas.width - (2 * gutter)); + } + + if (this.Get('chart.xaxispos') == 'center') { + var interval = (this.grapharea / 10); + var lineto = (this.Get('chart.yaxispos') == 'left' ? gutter : this.canvas.width - gutter + this.Get('chart.smallyticks')); + + // Draw the upper halves Y tick marks + for (y=gutter; y < (this.grapharea / 2) + gutter; y+=interval) { + this.context.moveTo((this.Get('chart.yaxispos') == 'left' ? gutter - this.Get('chart.smallyticks') : this.canvas.width - gutter), y); + this.context.lineTo(lineto, y); + } + + // Draw the lower halves Y tick marks + for (y=gutter + (this.halfgrapharea) + interval; y <= this.grapharea + gutter; y+=interval) { + this.context.moveTo((this.Get('chart.yaxispos') == 'left' ? gutter - this.Get('chart.smallyticks') : this.canvas.width - gutter), y); + this.context.lineTo(lineto, y); + } + + } else { + var lineto = (this.Get('chart.yaxispos') == 'left' ? gutter - this.Get('chart.smallyticks') : this.canvas.width - gutter + this.Get('chart.smallyticks')); + + for (y=gutter; y < (this.canvas.height - gutter) && counter < 10; y+=( (this.canvas.height - (2 * gutter)) / 10) ) { + + this.context.moveTo(gutter + adjustment, y); + this.context.lineTo(lineto, y); + + var counter = counter +1; + } + } + + // Draw an extra X tickmark + } else if (this.Get('chart.noxaxis') == false) { + if (this.Get('chart.yaxispos') == 'left') { + this.context.moveTo(this.Get('chart.gutter'), this.canvas.height - this.Get('chart.gutter')); + this.context.lineTo(this.Get('chart.gutter'), this.canvas.height - this.Get('chart.gutter') + this.Get('chart.smallxticks')); + } else { + this.context.moveTo(this.canvas.width - this.Get('chart.gutter'), this.canvas.height - this.Get('chart.gutter')); + this.context.lineTo(this.canvas.width - this.Get('chart.gutter'), this.canvas.height - this.Get('chart.gutter') + this.Get('chart.smallxticks')); + } + } + + this.context.stroke(); + } + + + /** + * Draw the text labels for the axes + */ + RGraph.Line.prototype.DrawLabels = function () + { + this.context.strokeStyle = 'black'; + this.context.fillStyle = this.Get('chart.text.color'); + this.context.lineWidth = 1; + + // Turn off any shadow + RGraph.NoShadow(this); + + // This needs to be here + var font = this.Get('chart.text.font'); + var gutter = this.Get('chart.gutter'); + var text_size = this.Get('chart.text.size'); + var context = this.context; + var canvas = this.canvas; + + // Draw the Y axis labels + if (this.Get('chart.ylabels') && this.Get('chart.ylabels.specific') == null) { + + var units_pre = this.Get('chart.units.pre'); + var units_post = this.Get('chart.units.post'); + var xpos = this.Get('chart.yaxispos') == 'left' ? gutter - 5 : this.canvas.width - gutter + 5; + var align = this.Get('chart.yaxispos') == 'left' ? 'right' : 'left'; + + var numYLabels = this.Get('chart.ylabels.count'); + var bounding = false; + var bgcolor = this.Get('chart.ylabels.inside') ? this.Get('chart.ylabels.inside.color') : null; + + + /** + * If the Y labels are inside the Y axis, invert the alignment + */ + if (this.Get('chart.ylabels.inside') == true && align == 'left') { + xpos -= 10; + align = 'right'; + bounding = true; + + + } else if (this.Get('chart.ylabels.inside') == true && align == 'right') { + xpos += 10; + align = 'left'; + bounding = true; + } + + + + if (this.Get('chart.xaxispos') == 'center') { + var half = this.grapharea / 2; + + if (numYLabels == 1 || numYLabels == 3 || numYLabels == 5) { + // Draw the upper halves labels + RGraph.Text(context, font, text_size, xpos, gutter + ( (0/5) * half ) + this.halfTextHeight, RGraph.number_format(this, this.scale[4], units_pre, units_post), null, align, bounding, null, bgcolor); + + if (numYLabels == 5) { + RGraph.Text(context, font, text_size, xpos, gutter + ( (1/5) * half ) + this.halfTextHeight, RGraph.number_format(this, this.scale[3], units_pre, units_post), null, align, bounding, null, bgcolor); + RGraph.Text(context, font, text_size, xpos, gutter + ( (3/5) * half ) + this.halfTextHeight, RGraph.number_format(this, this.scale[1], units_pre, units_post), null, align, bounding, null, bgcolor); + } + + if (numYLabels >= 3) { + RGraph.Text(context, font, text_size, xpos, gutter + ( (2/5) * half ) + this.halfTextHeight, RGraph.number_format(this, this.scale[2], units_pre, units_post), null, align, bounding, null, bgcolor); + RGraph.Text(context, font, text_size, xpos, gutter + ( (4/5) * half ) + this.halfTextHeight, RGraph.number_format(this, this.scale[0], units_pre, units_post), null, align, bounding, null, bgcolor); + } + + // Draw the lower halves labels + if (numYLabels >= 3) { + RGraph.Text(context, font, text_size, xpos, gutter + ( (6/5) * half ) + this.halfTextHeight, '-' + RGraph.number_format(this, this.scale[0], units_pre, units_post), null, align, bounding, null, bgcolor); + RGraph.Text(context, font, text_size, xpos, gutter + ( (8/5) * half ) + this.halfTextHeight, '-' + RGraph.number_format(this, this.scale[2], units_pre, units_post), null, align, bounding, null, bgcolor); + } + + if (numYLabels == 5) { + RGraph.Text(context, font, text_size, xpos, gutter + ( (7/5) * half ) + this.halfTextHeight, '-' + RGraph.number_format(this, this.scale[1], units_pre, units_post), null, align, bounding, null, bgcolor); + RGraph.Text(context, font, text_size, xpos, gutter + ( (9/5) * half ) + this.halfTextHeight, '-' + RGraph.number_format(this, this.scale[3], units_pre, units_post), null, align, bounding, null, bgcolor); + } + + RGraph.Text(context, font, text_size, xpos, gutter + ( (10/5) * half ) + this.halfTextHeight, '-' + RGraph.number_format(this, (this.scale[4] == '1.0' ? '1.0' : this.scale[4]), units_pre, units_post), null, align, bounding, null, bgcolor); + + } else if (numYLabels == 10) { + + // 10 Y labels + var interval = (this.grapharea / numYLabels) / 2; + + for (var i=0; i= 3) { + RGraph.Text(context, font, text_size, xpos, gutter + this.halfTextHeight + ((2/5) * (this.grapharea ) ), RGraph.number_format(this, this.scale[2], units_pre, units_post), null, align, bounding, null, bgcolor); + RGraph.Text(context, font, text_size, xpos, gutter + this.halfTextHeight + ((4/5) * (this.grapharea) ), RGraph.number_format(this, this.scale[0], units_pre, units_post), null, align, bounding, null, bgcolor); + } + + } else if (numYLabels == 10) { + + // 10 Y labels + var interval = (this.grapharea / numYLabels) / 2; + + for (var i=0; i 0) { + + var yOffset = 13; + var bordered = false; + var bgcolor = null; + + if (this.Get('chart.xlabels.inside')) { + yOffset = -5; + bordered = true; + bgcolor = this.Get('chart.xlabels.inside.color'); + } + + /** + * Text angle + */ + var angle = 0; + var valign = null; + var halign = 'center'; + + if (typeof(this.Get('chart.text.angle')) == 'number' && this.Get('chart.text.angle') > 0) { + angle = -1 * this.Get('chart.text.angle'); + valign = 'center'; + halign = 'right'; + yOffset = 5 + } + + this.context.fillStyle = this.Get('chart.text.color'); + var numLabels = this.Get('chart.labels').length; + + for (i=0; i 0 ? this.Get('chart.ymin') : (-1 * this.Get('chart.ymin')) ) ) / (this.max - this.min) ) * ((this.canvas.height - (2 * this.gutter)) )); + + if (this.Get('chart.ylabels.invert')) { + yPos -= gutter; + yPos -= gutter; + yPos = this.canvas.height - yPos; + } + + // Make adjustments depending on the X axis position + if (this.Get('chart.xaxispos') == 'center') { + yPos /= 2; + } else if (this.Get('chart.xaxispos') == 'bottom') { + yPos -= this.gutter; // Without this the line is out of place due to the gutter + } + + // Null data points + if (lineData[i] == null) { + yPos = null; + } + + // Not always very noticeable, but it does have an effect + // with thick lines + this.context.lineCap = 'round'; + this.context.lineJoin = 'round'; + + // Plot the line if we're at least on the second iteration + if (i > 0) { + xPos = xPos + xInterval; + } else { + xPos = this.Get('chart.hmargin') + gutter; // Might need to be this.gutter - 27th August 2010 + } + + /** + * Add the coords to an array + */ + this.coords.push([xPos, yPos]); + lineCoords.push([xPos, yPos]); + } + + this.context.stroke(); + + /** + * For IE only: Draw the shadow ourselves as ExCanvas doesn't produce shadows + */ + if (RGraph.isIE8() && this.Get('chart.shadow')) { + this.DrawIEShadow(lineCoords, this.context.shadowColor); + } + + /** + * Now draw the actual line [FORMERLY SECOND] + */ + this.context.beginPath(); + this.context.strokeStyle = 'rgba(240,240,240,0.9)'; // Almost transparent - changed on 10th May 2010 + //this.context.strokeStyle = fill; + if (fill) this.context.fillStyle = fill; + + var isStepped = this.Get('chart.stepped'); + var isFilled = this.Get('chart.filled'); + + + for (var i=0; i (this.canvas.height - this.Get('chart.gutter')) ) { + penUp = true; + } + + if (i == 0 || penUp || !yPos || !prevY || prevY < this.gutter) { + if (this.Get('chart.filled') && !this.Get('chart.filled.range')) { + this.context.moveTo(xPos + 1, this.canvas.height - this.gutter - (this.Get('chart.xaxispos') == 'center' ? (this.canvas.height - (2 * this.gutter)) / 2 : 0) -1); + this.context.lineTo(xPos + 1, yPos); + + } else { + this.context.moveTo(xPos, yPos); + } + + penUp = false; + + } else { + + // Draw the stepped part of stepped lines + if (isStepped) { + this.context.lineTo(xPos, lineCoords[i - 1][1]); + } + + if ((yPos >= this.gutter && yPos <= (this.canvas.height - this.gutter)) || this.Get('chart.outofbounds')) { + + if (isLast && this.Get('chart.filled') && !this.Get('chart.filled.range') && this.Get('chart.yaxispos') == 'right') { + xPos -= 1; + } + + + // Added 8th September 2009 + if (!isStepped || !isLast) { + this.context.lineTo(xPos, yPos); + + if (isFilled && lineCoords[i+1] && lineCoords[i+1][1] == null) { + this.context.lineTo(xPos, this.canvas.height - this.gutter); + } + + // Added August 2010 + } else if (isStepped && isLast) { + this.context.lineTo(xPos,yPos); + } + + + penUp = false; + } else { + penUp = true; + } + } + } + + if (this.Get('chart.filled') && !this.Get('chart.filled.range')) { + var fillStyle = this.Get('chart.fillstyle'); + + this.context.lineTo(xPos, this.canvas.height - this.gutter - 1 - + (this.Get('chart.xaxispos') == 'center' ? (this.canvas.height - (2 * this.gutter)) / 2 : 0)); + this.context.fillStyle = fill; + + this.context.fill(); + this.context.beginPath(); + } + + /** + * FIXME this may need removing when Chrome is fixed + * SEARCH TAGS: CHROME SHADOW BUG + */ + if (navigator.userAgent.match(/Chrome/) && this.Get('chart.shadow') && this.Get('chart.chromefix') && this.Get('chart.shadow.blur') > 0) { + + for (var i=lineCoords.length - 1; i>=0; --i) { + if ( + typeof(lineCoords[i][1]) != 'number' + || (typeof(lineCoords[i+1]) == 'object' && typeof(lineCoords[i+1][1]) != 'number') + ) { + this.context.moveTo(lineCoords[i][0],lineCoords[i][1]); + } else { + this.context.lineTo(lineCoords[i][0],lineCoords[i][1]); + } + } + } + + this.context.stroke(); + + + if (this.Get('chart.backdrop')) { + this.DrawBackdrop(lineCoords, color); + } + + // Now redraw the lines with the correct line width + this.RedrawLine(lineCoords, color, linewidth); + + this.context.stroke(); + + // Draw the tickmarks + for (var i=0; i (this.canvas.height - gutter) || yPos < gutter) && !this.Get('chart.outofbounds')) { + return; + } + + this.context.beginPath(); + + var offset = 0; + + // Reset the stroke and lineWidth back to the same as what they were when the line was drawm + this.context.lineWidth = this.Get('chart.linewidth'); + this.context.strokeStyle = isShadow ? this.Get('chart.shadow.color') : this.context.strokeStyle; + this.context.fillStyle = isShadow ? this.Get('chart.shadow.color') : this.context.strokeStyle; + + // Cicular tick marks + if ( tickmarks == 'circle' + || tickmarks == 'filledcircle' + || tickmarks == 'endcircle') { + + if (tickmarks == 'circle'|| tickmarks == 'filledcircle' || (tickmarks == 'endcircle') ) { + this.context.beginPath(); + this.context.arc(xPos + offset, yPos + offset, this.Get('chart.ticksize'), 0, 360 / (180 / Math.PI), false); + + if (tickmarks == 'filledcircle') { + this.context.fillStyle = isShadow ? this.Get('chart.shadow.color') : this.context.strokeStyle; + } else { + this.context.fillStyle = isShadow ? this.Get('chart.shadow.color') : 'white'; + } + + this.context.fill(); + this.context.stroke(); + } + + // Halfheight "Line" style tick marks + } else if (tickmarks == 'halftick') { + this.context.beginPath(); + this.context.moveTo(xPos, yPos); + this.context.lineTo(xPos, yPos + this.Get('chart.ticksize')); + + this.context.stroke(); + + // Tick style tickmarks + } else if (tickmarks == 'tick') { + this.context.beginPath(); + this.context.moveTo(xPos, yPos - this.Get('chart.ticksize')); + this.context.lineTo(xPos, yPos + this.Get('chart.ticksize')); + + this.context.stroke(); + + // Endtick style tickmarks + } else if (tickmarks == 'endtick') { + this.context.beginPath(); + this.context.moveTo(xPos, yPos - this.Get('chart.ticksize')); + this.context.lineTo(xPos, yPos + this.Get('chart.ticksize')); + + this.context.stroke(); + + // "Cross" style tick marks + } else if (tickmarks == 'cross') { + this.context.beginPath(); + this.context.moveTo(xPos - this.Get('chart.ticksize'), yPos - this.Get('chart.ticksize')); + this.context.lineTo(xPos + this.Get('chart.ticksize'), yPos + this.Get('chart.ticksize')); + this.context.moveTo(xPos + this.Get('chart.ticksize'), yPos - this.Get('chart.ticksize')); + this.context.lineTo(xPos - this.Get('chart.ticksize'), yPos + this.Get('chart.ticksize')); + + this.context.stroke(); + + // A white bordered circle + } else if (tickmarks == 'borderedcircle' || tickmarks == 'dot') { + this.context.lineWidth = 1; + this.context.strokeStyle = this.Get('chart.tickmarks.dot.color'); + this.context.fillStyle = this.Get('chart.tickmarks.dot.color'); + + // The outer white circle + this.context.beginPath(); + this.context.arc(xPos, yPos, this.Get('chart.ticksize'), 0, 360 / (180 / Math.PI), false); + this.context.closePath(); + + + this.context.fill(); + this.context.stroke(); + + // Now do the inners + this.context.beginPath(); + this.context.fillStyle = color; + this.context.strokeStyle = color; + this.context.arc(xPos, yPos, this.Get('chart.ticksize') - 2, 0, 360 / (180 / Math.PI), false); + + this.context.closePath(); + + this.context.fill(); + this.context.stroke(); + + } else if ( tickmarks == 'square' + || tickmarks == 'filledsquare' + || (tickmarks == 'endsquare') + || (tickmarks == 'filledendsquare') ) { + + this.context.fillStyle = 'white'; + this.context.strokeStyle = this.context.strokeStyle; // FIXME Is this correct? + + this.context.beginPath(); + this.context.strokeRect(xPos - this.Get('chart.ticksize'), yPos - this.Get('chart.ticksize'), this.Get('chart.ticksize') * 2, this.Get('chart.ticksize') * 2); + + // Fillrect + if (tickmarks == 'filledsquare' || tickmarks == 'filledendsquare') { + this.context.fillStyle = isShadow ? this.Get('chart.shadow.color') : this.context.strokeStyle; + this.context.fillRect(xPos - this.Get('chart.ticksize'), yPos - this.Get('chart.ticksize'), this.Get('chart.ticksize') * 2, this.Get('chart.ticksize') * 2); + + } else if (tickmarks == 'square' || tickmarks == 'endsquare') { + this.context.fillStyle = isShadow ? this.Get('chart.shadow.color') : 'white'; + this.context.fillRect((xPos - this.Get('chart.ticksize')) + 1, (yPos - this.Get('chart.ticksize')) + 1, (this.Get('chart.ticksize') * 2) - 2, (this.Get('chart.ticksize') * 2) - 2); + } + + this.context.stroke(); + this.context.fill(); + + /** + * FILLED arrowhead + */ + } else if (tickmarks == 'filledarrow') { + + var x = Math.abs(xPos - prevX); + var y = Math.abs(yPos - prevY); + + if (yPos < prevY) { + var a = Math.atan(x / y) + 1.57; + } else { + var a = Math.atan(y / x) + 3.14; + } + + this.context.beginPath(); + this.context.moveTo(xPos, yPos); + this.context.arc(xPos, yPos, 7, a - 0.5, a + 0.5, false); + this.context.closePath(); + + this.context.stroke(); + this.context.fill(); + + /** + * Arrow head, NOT filled + */ + } else if (tickmarks == 'arrow') { + + var x = Math.abs(xPos - prevX); + var y = Math.abs(yPos - prevY); + + if (yPos < prevY) { + var a = Math.atan(x / y) + 1.57; + } else { + var a = Math.atan(y / x) + 3.14; + } + + this.context.beginPath(); + this.context.moveTo(xPos, yPos); + this.context.arc(xPos, yPos, 7, a - 0.5 - (document.all ? 0.1 : 0.01), a - 0.4, false); + + this.context.moveTo(xPos, yPos); + this.context.arc(xPos, yPos, 7, a + 0.5 + (document.all ? 0.1 : 0.01), a + 0.5, true); + + + this.context.stroke(); + + /** + * Custom tick drawing function + */ + } else if (typeof(tickmarks) == 'function') { + tickmarks(this, lineData, lineData[index], index, xPos, yPos, color, prevX, prevY); + } + } + + + /** + * Draws a filled range if necessary + */ + RGraph.Line.prototype.DrawRange = function () + { + /** + * Fill the range if necessary + */ + if (this.Get('chart.filled.range') && this.Get('chart.filled')) { + this.context.beginPath(); + this.context.fillStyle = this.Get('chart.fillstyle'); + this.context.strokeStyle = this.Get('chart.fillstyle'); + this.context.lineWidth = 1; + var len = (this.coords.length / 2); + + for (var i=0; i=len; --i) { + this.context.lineTo(this.coords[i][0], this.coords[i][1]) + } + this.context.stroke(); + this.context.fill(); + } + } + + + /** + * Redraws the line with the correct line width etc + * + * @param array coords The coordinates of the line + */ + RGraph.Line.prototype.RedrawLine = function (coords, color, linewidth) + { + if (this.Get('chart.noredraw')) { + return; + } + + this.context.beginPath(); + this.context.strokeStyle = (typeof(color) == 'object' && color ? color[0] : color); + this.context.lineWidth = linewidth; + + var len = coords.length; + var gutter = this.gutter; + var width = this.canvas.width; + var height = this.canvas.height; + var penUp = false; + + for (var i=0; i 0) { + var prevX = coords[i - 1][0]; + var prevY = coords[i - 1][1]; + } + + + if (( + (i == 0 && coords[i]) + || (yPos < gutter) + || (prevY < gutter) + || (yPos > (height - gutter)) + || (i > 0 && prevX > (width - gutter)) + || (i > 0 && prevY > (height - gutter)) + || prevY == null + || penUp == true + ) && !this.Get('chart.outofbounds')) { + + this.context.moveTo(coords[i][0], coords[i][1]); + + penUp = false; + + } else { + + if (this.Get('chart.stepped') && i > 0) { + this.context.lineTo(coords[i][0], coords[i - 1][1]); + } + + // Don't draw the last bit of a stepped chart. Now DO + //if (!this.Get('chart.stepped') || i < (coords.length - 1)) { + this.context.lineTo(coords[i][0], coords[i][1]); + //} + penUp = false; + } + } + + /** + * If two colors are specified instead of one, go over the up bits + */ + if (this.Get('chart.colors.alternate') && typeof(color) == 'object' && color[0] && color[1]) { + for (var i=1; i= (xCoord - 5 + obj.Get('chart.tooltips.coords.adjust')[0]) + && mouseY <= (yCoord + 5 + obj.Get('chart.tooltips.coords.adjust')[1]) + && mouseY >= (yCoord - 5 + obj.Get('chart.tooltips.coords.adjust')[1])) { + + return [obj, xCoord, yCoord, i]; + } + } + } + + + /** + * Draws the above line labels + */ + RGraph.Line.prototype.DrawAboveLabels = function () + { + var context = this.context; + var size = this.Get('chart.labels.above.size'); + var font = this.Get('chart.text.font'); + var units_pre = this.Get('chart.units.pre'); + var units_post = this.Get('chart.units.post'); + + context.beginPath(); + + // Don't need to check that chart.labels.above is enabled here, it's been done already + for (var i=0; i this.max) this.value = this.max; + if (this.value < this.min) this.value = this.min; + } + + + /** + * A setter + * + * @param name string The name of the property to set + * @param value mixed The value of the property + */ + RGraph.Meter.prototype.Set = function (name, value) + { + this.properties[name.toLowerCase()] = value; + } + + + /** + * A getter + * + * @param name string The name of the property to get + */ + RGraph.Meter.prototype.Get = function (name) + { + return this.properties[name]; + } + + + /** + * The function you call to draw the bar chart + */ + RGraph.Meter.prototype.Draw = function () + { + /** + * Fire the onbeforedraw event + */ + RGraph.FireCustomEvent(this, 'onbeforedraw'); + + + // Cache the gutter as a object variable because it's used a lot + this.gutter = this.Get('chart.gutter'); + + this.centerx = this.canvas.width / 2; + this.centery = this.canvas.height - this.gutter; + this.radius = Math.min(this.canvas.width - (2 * this.gutter), this.canvas.height - (2 * this.gutter)); + + this.DrawBackground(); + this.DrawNeedle(); + this.DrawLabels(); + + /** + * Draw the title + */ + RGraph.DrawTitle(this.canvas, this.Get('chart.title'), this.gutter); + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + + /** + * For MSIE only, to cover the spurious lower ends of the circle + */ + if (document.all) { + // Cover the left tail + this.context.beginPath(); + this.context.moveTo(this.gutter, this.canvas.height - this.gutter); + this.context.fillStyle = 'white'; + this.context.fillRect(this.centerx - this.radius - 5, this.canvas.height - this.gutter + 1, 10, this.gutter); + this.context.fill(); + + // Cover the right tail + this.context.beginPath(); + this.context.moveTo(this.canvas.width - this.gutter, this.canvas.height - this.gutter); + this.context.fillStyle = 'white'; + this.context.fillRect(this.centerx + this.radius - 5, this.canvas.height - this.gutter + 1, 10, this.gutter); + this.context.fill(); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * Draws the background of the chart + */ + RGraph.Meter.prototype.DrawBackground = function () + { + // Draw the shadow + if (this.Get('chart.shadow')) { + this.context.beginPath(); + this.context.fillStyle = 'white'; + this.context.shadowColor = this.Get('chart.shadow.color'); + this.context.shadowBlur = this.Get('chart.shadow.blur'); + this.context.shadowOffsetX = this.Get('chart.shadow.offsetx'); + this.context.shadowOffsetY = this.Get('chart.shadow.offsety'); + + this.context.arc(this.centerx, this.centery, this.radius, 3.14, 6.28, false); + //this.context.arc(this.centerx, this.centery, , 0, 6.28, false); + this.context.fill(); + + + this.context.beginPath(); + var r = (this.radius * 0.06) > 40 ? 40 : (this.radius * 0.06); + this.context.arc(this.centerx, this.centery, r, 0, 6.28, 0); + this.context.fill(); + + RGraph.NoShadow(this); + } + + // First, draw the grey tickmarks + this.context.beginPath(); + this.context.strokeStyle = '#bbb' + for (var i=0; i<3.14; i+=(0.13/3)) { + this.context.arc(this.centerx, this.centery, this.radius, 3.14 + i, 3.1415 + i, 0); + this.context.lineTo(this.centerx, this.centery); + } + this.context.stroke(); + + + // First, draw the tickmarks + for (var i=0; i<3.14; i+=0.13) { + this.context.beginPath(); + this.context.strokeStyle = this.Get('chart.border.color'); + this.context.arc(this.centerx, this.centery, this.radius, 3.14 + i, 3.1415 + i, 0); + this.context.lineTo(this.centerx, this.centery) + this.context.stroke(); + } + + // Draw the white circle that makes the tickmarks + this.context.beginPath(); + this.context.fillStyle = 'white' + this.context.arc(this.centerx, this.centery, this.radius - 4, 3.1415927, 6.28, false); + this.context.closePath(); + this.context.fill(); + + // Draw the green area + this.context.strokeStyle = this.Get('chart.green.color'); + this.context.fillStyle = this.Get('chart.green.color'); + this.context.beginPath(); + this.context.arc(this.centerx,this.centery,this.radius * 0.85,(((this.Get('chart.green.start') - this.min) / (this.max - this.min)) * 3.1415927) + 3.1415927,(((this.Get('chart.green.end') - this.min) / (this.max - this.min)) * 3.1415927) + 3.1415927,false); + this.context.lineTo(this.centerx, this.centery); + this.context.closePath(); + this.context.stroke(); + this.context.fill(); + + // Draw the yellow area + this.context.strokeStyle = this.Get('chart.yellow.color'); + this.context.fillStyle = this.Get('chart.yellow.color'); + this.context.beginPath(); this.context.arc(this.centerx,this.centery,this.radius * 0.85,(((this.Get('chart.yellow.start') - this.min) / (this.max - this.min)) * 3.1415927) + 3.1415927,(((this.Get('chart.yellow.end') - this.min) / (this.max - this.min)) * 3.1415927) + 3.1415927,false) + this.context.lineTo(this.centerx, this.centery); + this.context.closePath(); + this.context.stroke(); + this.context.fill(); + + // Draw the yellow area + this.context.strokeStyle = this.Get('chart.red.color'); + this.context.fillStyle = this.Get('chart.red.color'); + this.context.beginPath(); + this.context.arc(this.centerx,this.centery,this.radius * 0.85,(((this.Get('chart.red.start') - this.min) / (this.max - this.min)) * 3.1415927) + 3.1415927,(((this.Get('chart.red.end') - this.min) / (this.max - this.min)) * 3.1415927) + 3.1415927,false); + this.context.lineTo(this.centerx, this.centery); + this.context.closePath(); + this.context.stroke(); + this.context.fill(); + + // Draw the outline + this.context.strokeStyle = this.Get('chart.border.color'); + this.context.lineWidth = this.Get('chart.linewidth'); + + this.context.beginPath(); + this.context.moveTo(this.centerx, this.centery); + this.context.arc(this.centerx, this.centery, this.radius, 3.1415927, 6.2831854, false); + this.context.closePath(); + + this.context.stroke(); + + // Reset the linewidth back to 1 + this.context.lineWidth = 1; + } + + + /** + * Draws the pointer + */ + RGraph.Meter.prototype.DrawNeedle = function () + { + // First draw the circle at the bottom + this.context.fillStyle = 'black'; + this.context.lineWidth = this.radius >= 200 ? 7 : 3; + this.context.lineCap = 'round'; + + // Now, draw the pointer + this.context.beginPath(); + this.context.strokeStyle = 'black'; + var a = (((this.value - this.min) / (this.max - this.min)) * 3.14) + 3.14; + this.context.arc(this.centerx, this.centery, this.radius * 0.7, a, a + 0.001, false); + this.context.lineTo(this.centerx, this.centery); + this.context.stroke(); + + // Draw the triangular needle head + this.context.beginPath(); + this.context.lineWidth = 1; + //this.context.moveTo(this.centerx, this.centery); + this.context.arc(this.centerx, this.centery, (this.radius * 0.7) + 15, a, a + 0.001, 0); + this.context.arc(this.centerx, this.centery, (this.radius * 0.7) - 15, a + 0.087, a + 0.087999, 0); + this.context.arc(this.centerx, this.centery, (this.radius * 0.7) - 15, a - 0.087, a - 0.087999, 1); + this.context.fill(); + + // Draw the center circle + var r = (this.radius * 0.06) > 40 ? 40 : (this.radius * 0.06); + + this.context.beginPath(); + this.context.arc(this.centerx, this.centery, r, 0, 6.28, 0); + this.context.fill(); + + // Draw the centre bit of the circle + this.context.fillStyle = 'white'; + this.context.beginPath(); + this.context.arc(this.centerx, this.centery, r - 2, 0, 6.28, 0); + this.context.fill(); + } + + + /** + * Draws the labels + */ + RGraph.Meter.prototype.DrawLabels = function () + { + var context = this.context; + var radius = this.radius; + var text_size = this.Get('chart.text.size'); + var text_font = this.Get('chart.text.font'); + var units_post = this.Get('chart.units.post'); + var units_pre = this.Get('chart.units.pre'); + var centerx = this.centerx; + var centery = this.centery; + var min = this.min; + var max = this.max; + + context.fillStyle = this.Get('chart.text.color'); + context.lineWidth = 1; + + context.beginPath(); + + + RGraph.Text(context, text_font, text_size, centerx - radius + (0.075 * radius), centery - 10, units_pre + min + units_post, 'center', 'left', false, 270); + RGraph.Text(context,text_font,text_size,centerx - (Math.cos(0.62819 / 2) * (radius - (0.085 * radius)) ),centery - (Math.sin(0.682819 / 2) * (radius - (0.085 * radius)) ),units_pre + (((max - min) * (1/10)) + min) + units_post,'center','center', false, 288); + RGraph.Text(context,text_font,text_size,centerx - (Math.cos(0.62819) * (radius - (0.085 * radius)) ),centery - (Math.sin(0.682819) * (radius - (0.085 * radius)) ),units_pre + (((max - min) * (2/10)) + min) + units_post,'center','center', false, 306); + RGraph.Text(context, text_font, text_size,centerx - (Math.cos(0.95) * (radius - (0.085 * radius)) ),centery - (Math.sin(0.95) * (radius - (0.0785 * radius)) ),units_pre + (((max - min) * (3/10)) + min) + units_post,'center', 'center', false, 320); + RGraph.Text(context, text_font, text_size,centerx - (Math.cos(1.2566) * (radius - (0.085 * radius)) ),centery - (Math.sin(1.2566) * (radius - (0.0785 * radius)) ),units_pre + (((max - min) * (4/10)) + min) + units_post,'center', 'center', false, 342); + RGraph.Text(context,text_font,text_size,centerx - (Math.cos(1.57) * (radius - (0.075 * radius)) ),centery - (Math.sin(1.57) * (radius - (0.075 * radius)) ),units_pre + (((max - min) * (5/10)) + min) + units_post,'center','center', false, 0); + RGraph.Text(context,text_font,text_size,centerx - (Math.cos(1.88495562) * (radius - (0.075 * radius)) ),centery - (Math.sin(1.88495562) * (radius - (0.075 * radius)) ),units_pre + (((max - min)* (6/10)) + min) + units_post,'center','center', false, 18); + RGraph.Text(context,text_font,text_size,centerx - (Math.cos(2.1989) * (radius - (0.075 * radius)) ),centery - (Math.sin(2.1989) * (radius - (0.075 * radius)) ),units_pre + (((max - min)* (7/10)) + min) + units_post,'center','center', false, 36); + RGraph.Text(context,text_font,text_size,centerx - (Math.cos(2.51327416) * (radius - (0.075 * radius)) ),centery - (Math.sin(2.51327416) * (radius - (0.075 * radius)) ), units_pre + (((max - min) * (8/10)) + min) + units_post,'center','center', false, 54); + RGraph.Text(context,text_font,text_size,centerx - (Math.cos(2.82764832) * (radius - (0.075 * radius)) ),centery - (Math.sin(2.82764832) * (radius - (0.075 * radius)) ),units_pre + (((max - min) * (9/10)) + min) + units_post,'center','center', false, 72); + RGraph.Text(context, text_font, text_size,centerx + radius - (0.075 * radius),centery - 10,units_pre + (max) + units_post, 'center', 'right', false, 90); + + context.fill(); + context.stroke(); + } diff --git a/libraries/RGraph.modaldialog.js b/libraries/RGraph.modaldialog.js new file mode 100644 index 0000000..2d4cc88 --- /dev/null +++ b/libraries/RGraph.modaldialog.js @@ -0,0 +1,244 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + ModalDialog = {} + ModalDialog.dialog = null; + ModalDialog.background = null; + ModalDialog.offset = 50; + ModalDialog.events = []; + + /** + * Shows the dialog with the supplied DIV acting as the contents + * + * @param string id The ID of the DIV to use as the dialogs contents + * @param int width The width of the dialog + */ + ModalDialog.Show = function (id, width) + { + ModalDialog.id = id; + ModalDialog.width = width; + + ModalDialog.ShowBackground(); + ModalDialog.ShowDialog(); + + // Install the event handlers + window.onresize = ModalDialog.Resize; + + + // Call them initially + ModalDialog.Resize(); + + ModalDialog.FireCustomEvent('onmodaldialog'); + } + + + /** + * Shows the background semi-transparent darkened DIV + */ + ModalDialog.ShowBackground = function () + { + // Create the background if neccessary + ModalDialog.background = document.createElement('DIV'); + ModalDialog.background.className = 'ModalDialog_background'; + ModalDialog.background.style.position = 'fixed'; + ModalDialog.background.style.top = 0; + ModalDialog.background.style.left = 0; + ModalDialog.background.style.width = (screen.width + 100) + 'px'; + ModalDialog.background.style.height = (screen.height + 100) + 'px'; + ModalDialog.background.style.backgroundColor = 'rgb(204,204,204)'; + ModalDialog.background.style.opacity = 0; + ModalDialog.background.style.zIndex = 3276; + ModalDialog.background.style.filter = "Alpha(opacity=50)"; + + document.body.appendChild(ModalDialog.background); + + ModalDialog.background.style.visibility = 'visible'; + } + + + /** + * Shows the dialog itself + */ + ModalDialog.ShowDialog = function () + { + // Create the DIV if necessary + if (!ModalDialog.dialog) { + ModalDialog.dialog = document.createElement('DIV'); + + ModalDialog.dialog.id = 'ModalDialog_dialog'; + ModalDialog.dialog.className = 'ModalDialog_dialog'; + + var borderRadius = '15px'; + + ModalDialog.dialog.style.borderRadius = borderRadius; + ModalDialog.dialog.style.MozBorderRadius = borderRadius; + ModalDialog.dialog.style.WebkitBorderRadius = borderRadius; + + ModalDialog.dialog.style.boxShadow = '3px 3px 3px rgba(96,96,96,0.5)'; + ModalDialog.dialog.style.MozBoxShadow = '3px 3px 3px rgba(96,96,96,0.5)'; + ModalDialog.dialog.style.WebkitBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px'; + + ModalDialog.dialog.style.position = 'fixed'; + ModalDialog.dialog.style.backgroundColor = 'white'; + ModalDialog.dialog.style.width = parseInt(ModalDialog.width) + 'px'; + ModalDialog.dialog.style.border = '2px solid #999'; + ModalDialog.dialog.style.zIndex = 32767; + ModalDialog.dialog.style.padding = '5px'; + ModalDialog.dialog.style.paddingTop = '25px'; + ModalDialog.dialog.style.opacity = 0; + + if (document.all) { + ModalDialog.dialog.style.zIndex = 32767; + } + + + + // Accomodate various browsers + if (navigator.userAgent.indexOf('Opera') != -1) { + ModalDialog.dialog.style.paddingTop = '25px'; + + } else if (navigator.userAgent.indexOf('MSIE') != -1) { + ModalDialog.dialog.style.paddingTop = '25px'; + + } else if (navigator.userAgent.indexOf('Safari') != -1) { + ModalDialog.dialog.style.paddingTop = '25px'; + } + + document.body.appendChild(ModalDialog.dialog); + + + // Now create the grey bar at the top of the dialog + var bar = document.createElement('DIV'); + bar.className = 'ModalDialog_topbar'; + bar.style.top = 0; + bar.style.left = 0; + bar.style.width = '100%';//(ModalDialog.dialog.offsetWidth - 4) + 'px'; + bar.style.height = '20px'; + bar.style.backgroundColor = '#bbb'; + bar.style.borderBottom = '2px solid #999'; + //bar.style.zIndex = 50000; + bar.style.position = 'absolute'; + var borderRadius = '11px'; + bar.style.WebkitBorderTopLeftRadius = borderRadius; + bar.style.WebkitBorderTopRightRadius = borderRadius; + bar.style.MozBorderRadiusTopleft = borderRadius; + bar.style.MozBorderRadiusTopright = borderRadius; + bar.style.borderTopRightRadius = borderRadius; + bar.style.borderTopLeftRadius = borderRadius; + ModalDialog.dialog.appendChild(bar); + + // Add the content div + var content = document.createElement('DIV'); + //content.style.paddingTop = '20px'; + content.style.width = '100%'; + content.style.height = '100%'; + ModalDialog.dialog.appendChild(content); + + content.innerHTML = document.getElementById(ModalDialog.id).innerHTML; + + // Now reposition the dialog in the center + ModalDialog.dialog.style.left = (document.body.offsetWidth / 2) - (ModalDialog.dialog.offsetWidth / 2) + 'px'; + ModalDialog.dialog.style.top = '30%'; + } + + // Show the dialog + ModalDialog.dialog.style.visibility = 'visible'; + + // A simple fade-in effect + setTimeout('ModalDialog.dialog.style.opacity = 0.2', 50); + setTimeout('ModalDialog.dialog.style.opacity = 0.4', 100); + setTimeout('ModalDialog.dialog.style.opacity = 0.6', 150); + setTimeout('ModalDialog.dialog.style.opacity = 0.8', 200); + setTimeout('ModalDialog.dialog.style.opacity = 1', 250); + + setTimeout('ModalDialog.background.style.opacity = 0.1', 50); + setTimeout('ModalDialog.background.style.opacity = 0.2', 100); + setTimeout('ModalDialog.background.style.opacity = 0.3', 150); + setTimeout('ModalDialog.background.style.opacity = 0.4', 200); + setTimeout('ModalDialog.background.style.opacity = 0.5', 250); + } + + + /** + * Hides everything + */ + ModalDialog.Close = function () + { + if (ModalDialog.dialog) { + ModalDialog.dialog.style.visibility = 'hidden'; + ModalDialog.dialog.style.opacity = 0; + } + + if (ModalDialog.background) { + ModalDialog.background.style.visibility = 'hidden'; + ModalDialog.background.style.opacity = 0; + } + } + + // An alias + ModalDialog.Hide = ModalDialog.Close + + + /** + * Accommodate the window being resized + */ + ModalDialog.Resize = function () + { + if (ModalDialog.dialog) { + ModalDialog.dialog.style.left = (document.body.offsetWidth / 2) - (ModalDialog.dialog.offsetWidth / 2) + 'px'; + } + + ModalDialog.background.style.width = '2500px'; + ModalDialog.background.style.height = '2500px'; + } + + + /** + * Returns the page height + * + * @return int The page height + */ + ModalDialog.AddCustomEventListener = function (name, func) + { + if (typeof(ModalDialog.events) == 'undefined') { + ModalDialog.events = []; + } + + ModalDialog.events.push([name, func]); + } + + + /** + * Used to fire the ModalDialog custom event + * + * @param object obj The graph object that fires the event + * @param string event The name of the event to fire + */ + ModalDialog.FireCustomEvent = function (name) + { + for (var i=0; i 0); + } \ No newline at end of file diff --git a/libraries/RGraph.odo.js b/libraries/RGraph.odo.js new file mode 100644 index 0000000..779d07a --- /dev/null +++ b/libraries/RGraph.odo.js @@ -0,0 +1,653 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The odometer constructor. Pass it the ID of the canvas tag, the start value of the odo, + * the end value, and the value that the pointer should point to. + * + * @param string id The ID of the canvas tag + * @param int start The start value of the Odo + * @param int end The end value of the odo + * @param int value The indicated value (what the needle points to) + */ + RGraph.Odometer = function (id, start, end, value) + { + this.id = id + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext('2d'); + this.canvas.__object__ = this; + this.type = 'odo'; + this.isRGraph = true; + this.start = start; + this.end = end; + this.value = value; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + + this.properties = { + 'chart.value.text': false, + 'chart.needle.color': 'black', + 'chart.needle.width': 2, + 'chart.needle.head': true, + 'chart.needle.tail': true, + 'chart.needle.type': 'pointer', + 'chart.needle.extra': [], + 'chart.text.size': 10, + 'chart.text.color': 'black', + 'chart.text.font': 'Verdana', + 'chart.green.max': end * 0.75, + 'chart.red.min': end * 0.9, + 'chart.green.color': 'green', + 'chart.yellow.color': 'yellow', + 'chart.red.color': 'red', + 'chart.label.area': 35, + 'chart.gutter': 25, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.contextmenu': null, + 'chart.linewidth': 1, + 'chart.shadow.inner': false, + 'chart.shadow.inner.color': 'black', + 'chart.shadow.inner.offsetx': 3, + 'chart.shadow.inner.offsety': 3, + 'chart.shadow.inner.blur': 6, + 'chart.shadow.outer': false, + 'chart.shadow.outer.color': '#666', + 'chart.shadow.outer.offsetx': 0, + 'chart.shadow.outer.offsety': 0, + 'chart.shadow.outer.blur': 15, + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.scale.decimals': 0, + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 10, + 'chart.zoom.delay': 50, + 'chart.zoom.shadow': true, + 'chart.zoom.mode': 'canvas', + 'chart.zoom.thumbnail.width': 75, + 'chart.zoom.thumbnail.height': 75, + 'chart.zoom.background': true, + 'chart.zoom.action': 'zoom', + 'chart.resizable': false, + 'chart.units.pre': '', + 'chart.units.post': '', + 'chart.border': false, + 'chart.tickmarks.highlighted': false, + 'chart.zerostart': false, + 'chart.labels': null, + 'chart.units.pre': '', + 'chart.units.post': '', + 'chart.value.units.pre': '', + 'chart.value.units.post': '' + } + + // Check the common library has been included + if (typeof(RGraph) == 'undefined') { + alert('[ODO] Fatal error: The common library does not appear to have been included'); + } + } + + + /** + * A peudo setter + * + * @param name string The name of the property to set + * @param value mixed The value of the property + */ + RGraph.Odometer.prototype.Set = function (name, value) + { + if (name == 'chart.needle.style') { + alert('[RGRAPH] The RGraph property chart.needle.style has changed to chart.needle.color'); + } + + if (name == 'chart.needle.thickness') { + name = 'chart.needle.width'; + } + + this.properties[name.toLowerCase()] = value; + } + + + /** + * A getter + * + * @param name string The name of the property to get + */ + RGraph.Odometer.prototype.Get = function (name) + { + return this.properties[name.toLowerCase()]; + } + + + /** + * Draws the odometer + */ + RGraph.Odometer.prototype.Draw = function () + { + /** + * Fire the onbeforedraw event + */ + RGraph.FireCustomEvent(this, 'onbeforedraw'); + + // Work out a few things + this.radius = Math.min(this.canvas.width / 2, this.canvas.height / 2) - this.Get('chart.gutter') - (this.Get('chart.border') ? 25 : 0); + this.diameter = 2 * this.radius; + this.centerx = this.canvas.width / 2; + this.centery = this.canvas.height / 2; + this.range = this.end - this.start; + + this.context.lineWidth = this.Get('chart.linewidth'); + + // Draw the background + this.DrawBackground(); + + // And lastly, draw the labels + this.DrawLabels(); + + // Draw the needle + this.DrawNeedle(this.value, this.Get('chart.needle.color')); + + /** + * Draw any extra needles + */ + if (this.Get('chart.needle.extra').length > 0) { + for (var i=0; i 0) { + this.context.beginPath(); + this.context.lineWidth = this.Get('chart.linewidth'); + this.context.strokeStyle = this.Get('chart.strokestyle'); + + for (var i=0,len=this.angles.length; i 270 ? 2 : -2) : 0), + this.centery + (((this.radius + 10) * Math.sin(a / 57.3))), + labels[i], + vAlignment, + hAlignment); + } + + context.fill(); + } + } + + + /** + * This function draws the pie chart sticks (for the labels) + */ + RGraph.Pie.prototype.DrawSticks = function () + { + var context = this.context; + var segments = this.Get('chart.segments'); + var offset = this.Get('chart.linewidth') / 2; + + for (var i=0; i 0 && this.Get('chart.key').length >= 3) { + this.centerx = this.centerx - this.Get('chart.gutter') + 5; + } + + this.DrawBackground(); + this.DrawRose(); + this.DrawLabels(); + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + /** + * Tooltips + */ + if (this.Get('chart.tooltips')) { + + /** + * Register this object for redrawing + */ + RGraph.Register(this); + + /** + * The onclick event + */ + var canvas_onclick_func = function (e) + { + var obj = e.target.__object__; + var canvas = e.target; + var context = canvas.getContext('2d'); + + e = RGraph.FixEventObject(e); + + RGraph.Redraw(); + + var segment = RGraph.getSegment(e); + if (segment && obj.Get('chart.tooltips')[segment[5]]) { + context.beginPath(); + context.strokeStyle = 'black'; + context.fillStyle = 'rgba(255,255,255,0.5)'; + context.arc(segment[0], segment[1], segment[2], segment[3] / 57.3, segment[4] / 57.3, false); + context.lineTo(obj.centerx, obj.centery); + context.closePath(); + context.fill(); + context.stroke(); + + context.strokeStyle = 'rgba(0,0,0,0)'; + obj.DrawLabels(); + + /** + * Show the tooltip + */ + RGraph.Tooltip(canvas, obj.Get('chart.tooltips')[segment[5]], e.pageX, e.pageY, segment[5]); + + e.stopPropagation(); + + return; + } + } + this.canvas.addEventListener('click', canvas_onclick_func, false); + RGraph.AddEventListener(this.id, 'click', canvas_onclick_func); + + + /** + * The onmousemove event + */ + var canvas_onmousemove_func = function (e) + { + var obj = e.target.__object__; + var canvas = e.target; + var context = canvas.getContext('2d'); + + e = RGraph.FixEventObject(e); + + var segment = RGraph.getSegment(e); + + if (segment && obj.Get('chart.tooltips')[segment[5]]) { + canvas.style.cursor = 'pointer'; + return; + } + + canvas.style.cursor = 'default'; + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + } + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + + /** + * This function enables adjusting + */ + if (this.Get('chart.adjustable')) { + RGraph.AllowAdjusting(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + /** + * This method draws the rose charts background + */ + RGraph.Rose.prototype.DrawBackground = function () + { + this.context.lineWidth = 1; + + // Draw the background grey circles + this.context.strokeStyle = '#ccc'; + for (var i=15; i -1) { + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - ((r - this.Get('chart.gutter')) * 0.2), String(Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - ((r - this.Get('chart.gutter')) * 0.4), String(Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - ((r - this.Get('chart.gutter')) * 0.6), String(Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - ((r - this.Get('chart.gutter')) * 0.8), String(Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - r + this.Get('chart.gutter'), String(Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + } + + // The "South" axis labels + if (axes.indexOf('s') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + ((r - this.Get('chart.gutter')) * 0.2), String(Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + ((r - this.Get('chart.gutter')) * 0.4), String(Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + ((r - this.Get('chart.gutter')) * 0.6), String(Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + ((r - this.Get('chart.gutter')) * 0.8), String(Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + r - this.Get('chart.gutter'), String(Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + } + + // The "East" axis labels + if (axes.indexOf('e') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx + ((r - this.Get('chart.gutter')) * 0.2), this.centery, String(Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + ((r - this.Get('chart.gutter')) * 0.4), this.centery, String(Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + ((r - this.Get('chart.gutter')) * 0.6), this.centery, String(Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + ((r - this.Get('chart.gutter')) * 0.8), this.centery, String(Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + r - this.Get('chart.gutter'), this.centery, String(Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + } + + // The "West" axis labels + if (axes.indexOf('w') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx - ((r - this.Get('chart.gutter')) * 0.2), this.centery, String(Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - ((r - this.Get('chart.gutter')) * 0.4), this.centery, String(Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - ((r - this.Get('chart.gutter')) * 0.6), this.centery, String(Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - ((r - this.Get('chart.gutter')) * 0.8), this.centery, String(Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - r + this.Get('chart.gutter'), this.centery, String(Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color); + } + + RGraph.Text(context, font_face, font_size, this.centerx, this.centery, typeof(this.Get('chart.ymin')) == 'number' ? String(Number(this.Get('chart.ymin')).toFixed(this.Get('chart.scale.decimals'))) : '0', 'center', 'center', true, false, color); + } + + + /** + * Draws the circular labels that go around the charts + * + * @param labels array The labels that go around the chart + */ + RGraph.Rose.prototype.DrawCircularLabels = function (context, labels, font_face, font_size, r) + { + var position = this.Get('chart.labels.position'); + var r = r - this.Get('chart.gutter') + 10; + + for (var i=0; i 0 && this.Get('chart.key').length >= 3) { + this.centerx = this.centerx - this.Get('chart.gutter') + 5; + } + + /** + * Populate the colors array for the purposes of generating the key + */ + if (typeof(this.Get('chart.key')) == 'object' && RGraph.is_array(this.Get('chart.key')) && this.Get('chart.key')[0]) { + for (var i=0; i (xCoord - offset) && + mouseY < (yCoord + offset) && + mouseY > (yCoord - offset) && + typeof(tooltip) == 'string' && + tooltip.length > 0 + ) { + + overHotspot = true; + canvas.style.cursor = 'pointer'; + + if (!RGraph.Registry.Get('chart.tooltip') || RGraph.Registry.Get('chart.tooltip').__text__ != tooltip) { + + if (obj.Get('chart.tooltips.highlight')) { + RGraph.Redraw(); + } + + /** + * Get the tooltip text + */ + if (typeof(tooltip) == 'function') { + var text = String(tooltip(i)); + + } else { + var text = String(tooltip); + } + + RGraph.Tooltip(canvas, text, event.pageX + 5, event.pageY - 5, i); + + /** + * Highlight the tickmark + */ + if (obj.Get('chart.tooltips.highlight')) { + context.beginPath(); + context.fillStyle = 'rgba(255,255,255,0.5)'; + context.arc(xCoord, yCoord, 3, 0, 6.2830, 0); + context.fill(); + } + } + } + } + + if (!overHotspot) { + canvas.style.cursor = 'default'; + } + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + } + + // Draw the title if any has been set + if (this.Get('chart.title')) { + RGraph.DrawTitle(this.canvas, this.Get('chart.title'), this.Get('chart.gutter'), this.centerx, this.Get('chart.text.size') + 2); + } + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + /** + * This method draws the rose charts background + */ + RGraph.Rscatter.prototype.DrawBackground = function () + { + this.context.lineWidth = 1; + + // Draw the background grey circles + this.context.strokeStyle = '#ccc'; + for (var i=15; i -1) { + RGraph.Text(context,font_face,font_size,this.centerx,this.centery - ((r) * 0.2),String(this.scale[0]),'center','center',true,false,color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - ((r) * 0.4), String(this.scale[1]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - ((r) * 0.6), String(this.scale[2]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - ((r) * 0.8), String(this.scale[3]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - r, String(this.scale[4]), 'center', 'center', true, false, color); + } + + // The "South" axis labels + if (axes.indexOf('s') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + ((r) * 0.2), String(this.scale[0]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + ((r) * 0.4), String(this.scale[1]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + ((r) * 0.6), String(this.scale[2]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + ((r) * 0.8), String(this.scale[3]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + r, String(this.scale[4]), 'center', 'center', true, false, color); + } + + // The "East" axis labels + if (axes.indexOf('e') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx + ((r) * 0.2), this.centery, String(this.scale[0]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + ((r) * 0.4), this.centery, String(this.scale[1]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + ((r) * 0.6), this.centery, String(this.scale[2]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + ((r) * 0.8), this.centery, String(this.scale[3]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + r, this.centery, String(this.scale[4]), 'center', 'center', true, false, color); + } + + // The "West" axis labels + if (axes.indexOf('w') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx - ((r) * 0.2), this.centery, String(this.scale[0]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - ((r) * 0.4), this.centery, String(this.scale[1]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - ((r) * 0.6), this.centery, String(this.scale[2]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - ((r) * 0.8), this.centery, String(this.scale[3]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - r, this.centery, String(this.scale[4]), 'center', 'center', true, false, color); + } + + // Draw the center minimum value (but only if there's at least one axes labels stipulated) + if (this.Get('chart.labels.axes').length > 0) { + RGraph.Text(context, font_face, font_size, this.centerx, this.centery, this.Get('chart.ymin') > 0 ? String(this.Get('chart.ymin').toFixed(this.Get('chart.scale.decimals'))) : '0', 'center', 'center', true, false, color); + } + + /** + * Draw the key + */ + if (key && key.length) { + RGraph.DrawKey(this, key, this.Get('chart.colors')); + } + } + + + /** + * Draws the circular labels that go around the charts + * + * @param labels array The labels that go around the chart + */ + RGraph.Rscatter.prototype.DrawCircularLabels = function (context, labels, font_face, font_size, r) + { + var position = this.Get('chart.labels.position'); + var r = r + 10; + + for (var i=0; i 0) { + + this.scale = []; + this.max = this.Get('chart.ymax'); + this.min = this.Get('chart.ymin') ? this.Get('chart.ymin') : 0; + + this.scale[0] = ((this.max - this.min) * (1/5)) + this.min; + this.scale[1] = ((this.max - this.min) * (2/5)) + this.min; + this.scale[2] = ((this.max - this.min) * (3/5)) + this.min; + this.scale[3] = ((this.max - this.min) * (4/5)) + this.min; + this.scale[4] = ((this.max - this.min) * (5/5)) + this.min; + + var decimals = this.Get('chart.scale.decimals'); + + this.scale = [ + Number(this.scale[0]).toFixed(decimals), + Number(this.scale[1]).toFixed(decimals), + Number(this.scale[2]).toFixed(decimals), + Number(this.scale[3]).toFixed(decimals), + Number(this.scale[4]).toFixed(decimals) + ]; + + } else { + + var i = 0; + var j = 0; + + for (i=0; i= (xCoord - offset) && + mouseCoords[1] <= (yCoord + offset) && + mouseCoords[1] >= (yCoord - offset) && + tooltip && + tooltip.length > 0) { + + overHotspot = true; + canvas.style.cursor = 'pointer'; + + if ( + !RGraph.Registry.Get('chart.tooltip') || + RGraph.Registry.Get('chart.tooltip').__text__ != tooltip || + RGraph.Registry.Get('chart.tooltip').__index__ != i || + RGraph.Registry.Get('chart.tooltip').__dataset__ != set + ) { + + if (obj.Get('chart.tooltips.highlight')) { + RGraph.Redraw(); + } + + /** + * Get the tooltip text + */ + if (typeof(tooltip) == 'function') { + var text = String(tooltip(i)); + + } else { + var text = String(tooltip); + } + + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i); + RGraph.Registry.Get('chart.tooltip').__dataset__ = set; + + /** + * Draw a circle around the mark + */ + if (obj.Get('chart.tooltips.highlight')) { + context.beginPath(); + context.fillStyle = 'rgba(255,255,255,0.5)'; + context.arc(xCoord, yCoord, 3, 0, 6.28, 0); + context.fill(); + } + } + } + } + } + + /** + * Reset the pointer + */ + if (!overHotspot) { + canvas.style.cursor = 'default'; + } + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + } + + + /** + * Draw the key if necessary + */ + if (this.Get('chart.key') && this.Get('chart.key').length) { + RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.line.colors')); + } + + + /** + * Draw crosschairs + */ + RGraph.DrawCrosshairs(this); + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * Draws the axes of the scatter graph + */ + RGraph.Scatter.prototype.DrawAxes = function () + { + var canvas = this.canvas; + var context = this.context; + var graphHeight = this.canvas.height - (this.Get('chart.gutter') * 2); + var gutter = this.Get('chart.gutter'); + + context.beginPath(); + context.strokeStyle = this.Get('chart.axis.color'); + context.lineWidth = 1; + + // Draw the Y axis + if (this.Get('chart.yaxispos') == 'left') { + context.moveTo(gutter, gutter); + context.lineTo(gutter, this.canvas.height - gutter); + } else { + context.moveTo(canvas.width - gutter, gutter); + context.lineTo(canvas.width - gutter, canvas.height - gutter); + } + + + // Draw the X axis + if (this.Get('chart.xaxis')) { + if (this.Get('chart.xaxispos') == 'center') { + context.moveTo(gutter, canvas.height / 2); + context.lineTo(canvas.width - gutter, canvas.height / 2); + } else { + context.moveTo(gutter, canvas.height - gutter); + context.lineTo(canvas.width - gutter, canvas.height - gutter); + } + } + + /** + * Draw the Y tickmarks + */ + for (y=gutter; y < canvas.height - gutter + (this.Get('chart.xaxispos') == 'center' ? 1 : 0) ; y+=(graphHeight / 5) / 2) { + + // This is here to accomodate the X axis being at the center + if (y == (canvas.height / 2) ) continue; + + if (this.Get('chart.yaxispos') == 'left') { + context.moveTo(gutter, y); + context.lineTo(gutter - 3, y); + } else { + context.moveTo(canvas.width - gutter +3, y); + context.lineTo(canvas.width - gutter, y); + } + } + + + /** + * Draw the X tickmarks + */ + if (this.Get('chart.xticks') && this.Get('chart.xaxis')) { + + var x = 0; + var y = (this.Get('chart.xaxispos') == 'center') ? (this.canvas.height / 2) : (this.canvas.height - gutter); + this.xTickGap = (this.canvas.width - (2 * gutter) ) / this.Get('chart.labels').length; + + for (x = (gutter + (this.Get('chart.yaxispos') == 'left' ? this.xTickGap / 2 : 0) ); x<=(canvas.width - gutter - (this.Get('chart.yaxispos') == 'left' ? 0 : 1)); x += this.xTickGap / 2) { + + if (this.Get('chart.yaxispos') == 'left' && this.Get('chart.noendxtick') == true && x == (canvas.width - gutter) ) { + continue; + + } else if (this.Get('chart.yaxispos') == 'right' && this.Get('chart.noendxtick') == true && x == gutter) { + continue; + } + + context.moveTo(x, y - (this.Get('chart.xaxispos') == 'center' ? 3 : 0)); + context.lineTo(x, y + 3); + } + } + + context.stroke(); + } + + + /** + * Draws the labels on the scatter graph + */ + RGraph.Scatter.prototype.DrawLabels = function () + { + this.context.fillStyle = this.Get('chart.text.color'); + var font = this.Get('chart.text.font'); + var xMin = this.Get('chart.xmin'); + var xMax = this.Get('chart.xmax'); + var yMax = this.scale[4]; + var gutter = this.Get('chart.gutter'); + var text_size = this.Get('chart.text.size'); + var units_pre = this.Get('chart.units.pre'); + var units_post = this.Get('chart.units.post'); + var numYLabels = this.Get('chart.ylabels.count'); + var context = this.context; + var canvas = this.canvas; + + this.halfTextHeight = text_size / 2; + + + this.halfGraphHeight = (this.canvas.height - (2 * this.Get('chart.gutter'))) / 2; + + /** + * Draw the Y yaxis labels, be it at the top or center + */ + if (this.Get('chart.ylabels')) { + + var xPos = this.Get('chart.yaxispos') == 'left' ? gutter - 5 : canvas.width - gutter + 5; + var align = this.Get('chart.yaxispos') == 'right' ? 'left' : 'right'; + + if (this.Get('chart.xaxispos') == 'center') { + + + /** + * Specific Y labels + */ + if (typeof(this.Get('chart.ylabels.specific')) == 'object') { + + var labels = this.Get('chart.ylabels.specific'); + + for (var i=0; i= 5) { + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (1/10) ), RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', align); + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (3/10) ), RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', align); + } + + if (numYLabels >= 3) { + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (2/10) ), RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', align); + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (4/10) ), RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', align); + } + + // Draw the bottom halves labels + if (numYLabels >= 3) { + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (1/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', align); + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (3/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', align); + } + + if (numYLabels == 5) { + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (2/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', align); + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (4/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', align); + } + + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (5/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[4], units_pre, units_post), 'center', align); + + } else if (numYLabels == 10) { + // 10 Y labels + var interval = (this.grapharea / numYLabels) / 2; + + for (var i=0; i= 5) { + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (1/5) ), RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', align); + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (3/5) ), RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', align); + } + + if (numYLabels >= 3) { + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (2/5) ), RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', align); + RGraph.Text(context, font, text_size, xPos, gutter + ((canvas.height - (2 * gutter)) * (4/5) ), RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', align); + } + } else if (numYLabels == 10) { + + // 10 Y labels + var interval = (this.grapharea / numYLabels) / 2; + + for (var i=0; i 0) { + angle = -1 * this.Get('chart.text.angle'); + valign = 'center'; + halign = 'right'; + yPos -= 10; + } + + for (i=0; i= 2) { + + this.context.lineCap = 'round'; + this.context.lineJoin = 'round'; + this.context.lineWidth = this.GetLineWidth(i);// i is the index of the set of coordinates + this.context.strokeStyle = this.Get('chart.line.colors')[i]; + this.context.beginPath(); + + var len = this.coords[i].length; + + for (var j=0; j (xCoord - 5) + && y > (yCoord - 5) + && y < (yCoord + 5) + ) { + + if (!RGraph.Registry.Get('chart.tooltip') || RGraph.Registry.Get('chart.tooltip').__index__ != idx) { + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = String(obj.Get('chart.tooltips')(i)); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[i]) == 'function') { + var text = String(obj.Get('chart.tooltips')[i](i)); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[i]) == 'string') { + var text = String(obj.Get('chart.tooltips')[i]); + + } else { + var text = null; + } + + if (typeof(text) == 'string' && text.length) { + + overHotspot = true; + obj.canvas.style.cursor = 'pointer'; + + RGraph.Clear(obj.canvas); + obj.Draw(); + + if (obj.Get('chart.tooltips.highlight')) { + obj.context.beginPath(); + obj.context.strokeStyle = 'gray'; + obj.context.fillStyle = 'white'; + obj.context.arc(xCoord, yCoord, 2, 0, 6.28, 0); + obj.context.fill(); + obj.context.stroke(); + } + + RGraph.Tooltip(obj.canvas, text, e.pageX, e.pageY, idx); + } + } else if (RGraph.Registry.Get('chart.tooltip') && RGraph.Registry.Get('chart.tooltip').__index__ == idx) { + overHotspot = true; + obj.canvas.style.cursor = 'pointer'; + } + } + } + + if (!overHotspot) { + obj.canvas.style.cursor = 'default'; + } + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + } + } + + + /** + * Gets the coordinates for a particular mark + * + * @param number i The index of the data (ie which one it is) + * @return array A two element array of the coordinates + */ + RGraph.Tradar.prototype.GetCoordinates = function (i) + { + // The number of data points + var len = this.data.length; + + // The magnitude of the data (NOT the x/y coords) + var mag = (this.data[i] / this.max) * (this.size / 2); + + /** + * Get the angle + */ + var angle = (6.28 / len) * i; // In radians + + /** + * Work out the X/Y coordinates + */ + var x = Math.cos(angle) * mag; + var y = Math.sin(angle) * mag; + + /** + * Put the coordinate in the right quadrant + */ + x = this.centerx + x; + y = this.centery + (i == 0 ? 0 : y); + + return [x,y]; + } + + + /** + * This function adds the labels to the chart + */ + RGraph.Tradar.prototype.DrawLabels = function () + { + var labels = this.Get('chart.labels'); + + if (labels && labels.length > 0) { + + this.context.lineWidth = 1; + this.context.fillStyle = this.Get('chart.text.color'); + + var offsetx = this.Get('chart.labels.offsetx'); // Not used yet + var offsety = this.Get('chart.labels.offsety'); // Not used yet + + for (var i=0; i -1) { + RGraph.Text(context,font_face,font_size,this.centerx,this.centery - (r * 0.2),String(this.scale[0]),'center','center',true,false,color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.4), String(this.scale[1]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.6), String(this.scale[2]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.8), String(this.scale[3]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery - r, String(this.scale[4]), 'center', 'center', true, false, color); + } + + // The "South" axis labels + if (axes.indexOf('s') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.2), String(this.scale[0]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.4), String(this.scale[1]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.6), String(this.scale[2]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.8), String(this.scale[3]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx, this.centery + r, String(this.scale[4]), 'center', 'center', true, false, color); + } + + // The "East" axis labels + if (axes.indexOf('e') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.2), this.centery, String(this.scale[0]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.4), this.centery, String(this.scale[1]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.6), this.centery, String(this.scale[2]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.8), this.centery, String(this.scale[3]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx + r, this.centery, String(this.scale[4]), 'center', 'center', true, false, color); + } + + // The "West" axis labels + if (axes.indexOf('w') > -1) { + RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.2), this.centery, String(this.scale[0]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.4), this.centery, String(this.scale[1]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.6), this.centery, String(this.scale[2]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.8), this.centery, String(this.scale[3]), 'center', 'center', true, false, color); + RGraph.Text(context, font_face, font_size, this.centerx - r, this.centery, String(this.scale[4]), 'center', 'center', true, false, color); + } + + RGraph.Text(context, font_face, font_size, this.centerx, this.centery, '0', 'center', 'center', true, false, color); + } \ No newline at end of file diff --git a/libraries/RGraph.vprogress.js b/libraries/RGraph.vprogress.js new file mode 100644 index 0000000..1003d9b --- /dev/null +++ b/libraries/RGraph.vprogress.js @@ -0,0 +1,554 @@ + /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The progress bar constructor + * + * @param int id The ID of the canvas tag + * @param int value The indicated value of the meter. + * @param int max The end value (the upper most) of the meter + */ + RGraph.VProgress = function (id, value, max) + { + this.id = id; + this.max = max; + this.value = value; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext('2d'); + this.canvas.__object__ = this; + this.type = 'vprogress'; + this.coords = []; + this.isRGraph = true; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + this.properties = { + 'chart.colors': ['#0c0'], + 'chart.tickmarks': true, + 'chart.tickmarks.color': 'black', + 'chart.tickmarks.inner': false, + 'chart.gutter': 25, + 'chart.numticks': 10, + 'chart.numticks.inner': 50, + 'chart.background.color': '#eee', + 'chart.shadow': false, + 'chart.shadow.color': 'rgba(0,0,0,0.5)', + 'chart.shadow.blur': 3, + 'chart.shadow.offsetx': 3, + 'chart.shadow.offsety': 3, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.width': 0, + 'chart.height': 0, + 'chart.text.size': 10, + 'chart.text.color': 'black', + 'chart.text.font': 'Verdana', + 'chart.contextmenu': null, + 'chart.units.pre': '', + 'chart.units.post': '', + 'chart.tooltips': [], + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.highlight': true, + 'chart.tooltips.coords.adjust': [0,0], + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.zoom.mode': 'canvas', + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 10, + 'chart.zoom.delay': 50, + 'chart.zoom.shadow': true, + 'chart.zoom.background': true, + 'chart.zoom.action': 'zoom', + 'chart.arrows': false, + 'chart.margin': 0, + 'chart.resizable': false, + 'chart.label.inner': false, + 'chart.labels.count': 10, + 'chart.labels.position': 'right', + 'chart.adjustable': false, + 'chart.min': 0, + 'chart.scale.decimals': 0 + } + + // Check for support + if (!this.canvas) { + alert('[PROGRESS] No canvas support'); + return; + } + + // Check the common library has been included + if (typeof(RGraph) == 'undefined') { + alert('[PROGRESS] Fatal error: The common library does not appear to have been included'); + } + } + + + /** + * A generic setter + * + * @param string name The name of the property to set + * @param string value The value of the poperty + */ + RGraph.VProgress.prototype.Set = function (name, value) + { + this.properties[name.toLowerCase()] = value; + } + + + /** + * A generic getter + * + * @param string name The name of the property to get + */ + RGraph.VProgress.prototype.Get = function (name) + { + return this.properties[name.toLowerCase()]; + } + + + /** + * Draws the progress bar + */ + RGraph.VProgress.prototype.Draw = function () + { + /** + * Fire the onbeforedraw event + */ + RGraph.FireCustomEvent(this, 'onbeforedraw'); + + /** + * Clear all of this canvases event handlers (the ones installed by RGraph) + */ + RGraph.ClearEventListeners(this.id); + + // Figure out the width and height + this.width = this.canvas.width - (2 * this.Get('chart.gutter')); + this.height = this.canvas.height - (2 * this.Get('chart.gutter')); + this.coords = []; + + this.Drawbar(); + this.DrawTickMarks(); + this.DrawLabels(); + + this.context.stroke(); + this.context.fill(); + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + /** + * Alternatively, show the tooltip if requested + */ + if (typeof(this.Get('chart.tooltips')) == 'function' || this.Get('chart.tooltips').length) { + + // Need to register this object for redrawing + RGraph.Register(this); + + /** + * Install the window onclick handler + */ + window.onclick = function () + { + RGraph.Redraw(); + } + + + /** + * Install the onclick event handler for the tooltips + */ + //this.canvas.onclick = function (e) + var canvas_onclick_func = function (e) + { + e = RGraph.FixEventObject(e); + + var canvas = document.getElementById(this.id); + var obj = canvas.__object__; + + /** + * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn + * This "deselects" any already selected bar + */ + RGraph.Redraw(); + + /** + * Get the mouse X/Y coordinates + */ + var mouseCoords = RGraph.getMouseXY(e); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0; i= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) { + + /** + * Get the tooltip text + */ + if (typeof(obj.Get('chart.tooltips')) == 'function') { + var text = obj.Get('chart.tooltips')(idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') { + var text = obj.Get('chart.tooltips')[idx](idx); + + } else if (typeof(obj.Get('chart.tooltips')) == 'object') { + var text = obj.Get('chart.tooltips')[idx]; + + } else { + var text = null; + } + + /** + * Show a tooltip if it's defined + */ + if (text) { + + obj.context.beginPath(); + obj.context.strokeStyle = 'black'; + obj.context.fillStyle = 'rgba(255,255,255,0.5)'; + obj.context.strokeRect(left, top, width, height); + obj.context.fillRect(left, top, width, height); + + obj.context.stroke(); + obj.context.fill(); + + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i); + } + } + } + + /** + * Stop the event bubbling + */ + e.stopPropagation(); + } + this.canvas.addEventListener('click', canvas_onclick_func, false); + RGraph.AddEventListener(this.id, 'click', canvas_onclick_func); + + + /** + * If the cursor is over a hotspot, change the cursor to a hand + */ + //this.canvas.onmousemove = function (e) + var canvas_onmousemove_func = function (e) + { + e = RGraph.FixEventObject(e); + + var canvas = document.getElementById(this.id); + var obj = canvas.__object__; + + /** + * Get the mouse X/Y coordinates + */ + var mouseCoords = RGraph.getMouseXY(e); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0; i= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) { + canvas.style.cursor = 'pointer'; + break; + } + + canvas.style.cursor = 'default'; + } + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + } + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + /** + * Instead of using RGraph.common.adjusting.js, handle them here + */ + if (this.Get('chart.adjustable')) { + RGraph.AllowAdjusting(this); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * Draw the bar itself + */ + RGraph.VProgress.prototype.Drawbar = function () + { + // Set a shadow if requested + if (this.Get('chart.shadow')) { + RGraph.SetShadow(this, this.Get('chart.shadow.color'), this.Get('chart.shadow.offsetx'), this.Get('chart.shadow.offsety'), this.Get('chart.shadow.blur')); + } + + // Draw the shadow for MSIE + if (document.all && this.Get('chart.shadow')) { + this.context.fillStyle = this.Get('chart.shadow.color'); + this.context.fillRect(this.Get('chart.gutter') + this.Get('chart.shadow.offsetx'), this.Get('chart.gutter') + this.Get('chart.shadow.offsety'), this.width, this.height); + } + + // Draw the outline + this.context.fillStyle = this.Get('chart.background.color'); + this.context.strokeStyle = 'black'; + this.context.strokeRect(this.Get('chart.gutter'), this.Get('chart.gutter'), this.width, this.height); + this.context.fillRect(this.Get('chart.gutter'), this.Get('chart.gutter'), this.width, this.height); + + // Turn off any shadow + RGraph.NoShadow(this); + + this.context.strokeStyle = 'black'; + this.context.fillStyle = this.Get('chart.colors')[0]; + var margin = this.Get('chart.margin'); + var barHeight = this.canvas.height - this.Get('chart.gutter') - this.Get('chart.gutter'); + + // Draw the actual bar itself + if (typeof(this.value) == 'number') { + + this.context.lineWidth = 1; + this.context.strokeStyle = '#999'; + + } else if (typeof(this.value) == 'object') { + + this.context.beginPath(); + this.context.strokeStyle = '#999'; + + var startPoint = this.canvas.height - this.Get('chart.gutter'); + + for (var i=0; i + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+Weather  + +Lighting  + +Music  + +Cameras  + +Security  + +Climate  + +News  + +Receipes  + +Groceries  + +Traffic  + +Power  +
+
\ No newline at end of file diff --git a/middle.html b/middle.html new file mode 100644 index 0000000..a55a07f --- /dev/null +++ b/middle.html @@ -0,0 +1 @@ +MIDDLE ACTIONS diff --git a/news.html b/news.html new file mode 100644 index 0000000..16dda0d --- /dev/null +++ b/news.html @@ -0,0 +1,11 @@ + + +
+ + + + + + + +
diff --git a/news.php b/news.php new file mode 100644 index 0000000..5552d8c --- /dev/null +++ b/news.php @@ -0,0 +1,47 @@ +"; +$array=xml2array($output); +$array2=xml2array($output2); +$array3=xml2array($output3); +$array4=xml2array($output4); +#print_r($array4); + +#exit(); + +#echo "
"; +echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; +echo "
".$array['rss']['channel']['title']."".$array2['rdf:RDF']['channel']['title']."".$array3['rss']['channel']['title']."".$array4['rss']['channel']['title']."
".$array['rss']['channel']['item']['0']['title']."".$array2['rdf:RDF']['item']['0']['title']."".$array3['rss']['channel']['item']['0']['title']."".$array4['rss']['channel']['item']['0']['title']."
".$array['rss']['channel']['item']['1']['title']."".$array2['rdf:RDF']['item']['1']['title']."".$array3['rss']['channel']['item']['1']['title']."".$array4['rss']['channel']['item']['1']['title']."
".$array['rss']['channel']['item']['2']['title']."".$array2['rdf:RDF']['item']['2']['title']."".$array3['rss']['channel']['item']['2']['title']."".$array4['rss']['channel']['item']['2']['title']."
".$array['rss']['channel']['item']['3']['title']."".$array2['rdf:RDF']['item']['3']['title']."".$array3['rss']['channel']['item']['3']['title']."".$array4['rss']['channel']['item']['3']['title']."
".$array['rss']['channel']['item']['4']['title']."".$array2['rdf:RDF']['item']['4']['title']."".$array3['rss']['channel']['item']['4']['title']."".$array4['rss']['channel']['item']['4']['title']."
"; +#echo "
"; +?> diff --git a/other_icons/Security.jpg b/other_icons/Security.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9d17359baecde4d2e0d41caa0f3c1353c06ed319 GIT binary patch literal 14632 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 ZM>sEIGx&s?fIkl*%JS-R)v{(G{{wel0Qmp_ literal 0 HcmV?d00001 diff --git a/other_icons/cameras.jpg b/other_icons/cameras.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da1510260ba2a101af95b28a17fc80810cc9785f GIT binary patch literal 10825 zcmeH~YdD)(yT{X-Y3H5Jw3Bg~whr&;lxdx+p^D(08HXMm#t=#!rqKpbln|Oo%&Aoj z*~XMgN~W|9QORgZDiIk&no&ZD2qIBU(Ig^>1c}5p@7~vY?Q4JB?=|~V*YjnqYu(TP ze%5cT^}p_Cdt&Om80|KC%jlhb z``-UEZr9G>?LEM~AHVaV%ioMY3p25~^sec_lNU0-EkE)J$m1(S)t!6e%OAO(36Dtn zuI)*W!0hO!pZf(u6SK0vuNxWN5&h`DR`aivI~}84yWiTGIRV^Bx0C&CBcr$fdwSPy zpwVYxAG&0Id#}g%jkF@_l>Of3K2m1D+_?vBW5^%=>GbIc=VtgdZxu zb7l1s6}4NBNrsGW6Q)_w$zy`Ofk+gNB&f1@6P|7A&9G^6Z`@4tzzK-<%CK>;bWH9jr6kfQDd@SvTsF zC&2p#OXsT#bB$5hk!?WW@Vi(hYcQh#mqAm@wmb}zGXv)+^SasdhCLlFHd&<8eaLE? zYLce^=r5%L!4xBpYzvETT^`qQCaQ5r4{v2 z_cqC4Hy-5>+@+;nPWJdWZMLZSq41&6iB&~`%%^F8- z7K58^sTVZoQY4bi?l9-ir*h9Dw*iGBosY5Ba(4Ll;V(U_d2!$J-j}?j^%a)H|C~}& zz$_mV*IoV5QH^`#>G3P=X!xV-Qs%F&OjIeWh$0eJuG`MnFylm_xsZ&L>|7m`4n8k@ z+L^Tt__E9V0^yWiEqjOt<=efQYD?6x6n9J3uR-}gM&BL8o}@$tfc^V%*L9XNM^C8c zL~KY<%(&`$SxbC-s08ANkjmvN#Iy5BthKHCjS1A)ARffJk!!4NIKq=i4P?+{>&DMw z{HfTNadOJ{qL3%7wF|5c@1JURi(|511?p={FQzPtGR~9NL2hU|$hJGL%&yjglc>Jf zg88fyVGYlr_4r^hC1zQa*OT!B#C>?H7wtF7&3#IVx#@DcQ#Co7w+b8blgP|nwbxdC ziU?*D{+a^?A*w&KR%i-wi`fLL0-7VZ5o~$*97QAm#R1LcJ+yoQ$YiR0*q0hhB7nBs z3icg82}@}=ohA`6O2?_Xxq%Le75{FDc$I6yeRiCdbmWjaEY3s))f2k7=4sscAJ*qH z5|Hy#5$Ew zNs1RS?eZ%K_hD)jnHv$}l%JlRdLMltZw*0WzBQUt+Wwqqq6Z3@$cZ@bY19og(f2`h z!YVaOVW}S7haz8=PTi!?kdgX{n6ayA8BVzSaN+qd;RdQzN-;X_uu@dz!*&aH@5sDz zFHpE@s7+L1ScZHkksQ-jaSy)Xaq1YEt@oT8cnmQaIyzWl!JeQ6qC2)&zvGWJT(7l# zfOOzNd{8NPM!~Ei6uT9KkQ#4xb!l*+-$%EZNMmk80{Qhu5#;8D(OVmuon80tToBya z3_b^+Vk%z!v~L2!PZN%3T;_booMW!8Almg_jp&kwu-io?A(rN@PDMG+`Pm66;V2Qv zN9Qxnn>ci|Ce*VTul5cQN7f@WL8R*BOYTeAl7Yo*%imgW8f+TX8?Ex6w*gGTQAzeS z+~vmn72>r$zy2jA^OjfK2X!Kp=D!X%RGWG(E98;_B)EW|KwOc`f$z{^;2(I!cT*%>uRHCIA?5GV}m-N=;vrW;% z&g(v}t=pkZjVpPILChJ2`oY%*5PiMzHIfz};;XV0S25+dMn3a(A4!94XXNf_O*B5T z7kcS3B!K8Dt#W{SWzm<+j*ZGLwDtd7Y7XEd>?g&6tdUu>Tlc z&WIaLzKd_xdOw-MKY;LqKRS3jx_ifQ8+Xp{kZ{uHZ(Yf1Rvo&4ZT51-a<-}`=?uLb z9n&MNtP+GU);RYL9v1owue-jK$J{I;GCLxv50~`z`&%|9qnuKOxX*-D*;@}SqYkIV zj;b=LCmoM8TEb?8pk^~v4!=~85jE5!$Vk&4XgU-u>O{v+dH-WnmCRdXOqDfvsM_DJ zVPprRK~@B}^s5+apK-sJmtqC3+<~OX@znMfvOZg8SL|)y+cCo#p{1w$-em13fa*5z zd&&bE;|a9aLJwUTx0U+<`a0KKxh*GhlDT-|N(9?zP!-+tL|TTiSTbL!!kkZ6}AV-4E&7 z`Z2Xb-cgrvR&+w<6BtI1YK2d(3E9(lw^sB&rZrc?+`@8Wd+YZYP6bqj8vEbHod0a> z*GF9fTY`%@{Ap+0!BZz4rk+wt=yl3M>nnYH*G#MT-2+h#cuannT508>TCqSceJWYw zTZO1{yAP&afhvZczy&s}U#`fqXJ3XT@Hr$6j_P{8;2ek4RP2oLTzY`z=B5Q_2Lx1M z**QG46(b_r`A5e@r{SB*E01RrFEontTt%kg2g8)M*H=;nPb4z`FyPen`NT5xKexQO zG4&_j!Gj_JA_vg|*$vLXqU13O1pPgCT833s{a~%<++t~3zkfBBjX&P5hA*&oN}l}g zDQs*|rX?e2%TUlwHGsAOtqD5??pMySi}yCbGjB(+o=28Z zLuUaiDjXMh`%q!wd(T#&jLh2^A9jDE5V~CvKb?1;Vz)uUBVqmn5z#$VxFO&Q(joCx zZ2M^K-?hMmFEfu%$L#m9g1vq^VwVArv1&;llM;lf*JG@%i1u2|Pds~`CO^cC)SY4(cU#%5 zhr;&;7leLu07&&V7<0a~Q)!f{wHSN@L3o;Kdxs=oRm~OZXJ-*dVDdG7NA42yx$aKq zxbbVl}Zw& zd18%rX`^yko>1AOxxdy+C}E zNar9bQd1ES>=}upsdWO7a-}>t=f&4o!m67ti>YpG^uI8UnRv^dx{3L~JR*|0i(wQVowQE3oMNC+}|C$qYs_+ZXU2W>EF0i8a z-Wm;>D58B|-bKxpEnR|NT+fwjZ@!ulvLH_x*r%|0!KcjlIC;k-r=S&kqT}RT@9IQ@ zO@?`PO^wqqU6}w@4Ga4)7xWmN%BRck7^CDvysP);bSRkkg#zR{Olfo(9JZ>dJFV;s z(mtN#ch(Oq%#)`%raM>D4`H!l{plS;*;s4Rm*l0}HR-9`7AiH_FVkd2Se9g< z-4ASZ@qPdahfpf+7qbv8x}o?F3UDi?27XNzjQxYMldoTJe#e)yQM?U+4|Rf|ny|HS zecR#>%39D8K>E#JVnQF+OdhPj-Glb==ZY1&XV4=nO_G)R;=H2yyq8JbVPoK+E%b}M z_e2!qAa)y~B-bHE>!^jV(aH_BB*uuj9kEXpYCKn6^mArPaYsgh{nD#{{&SftOAC5& z3hm)2gz{C)orYI_L4%mQ&d@wkQ>{3LX>03!qzeKB?zdbMVswEi21{=Pm?P9%sAhOI zbhl%*u%g=32EMK$0pC(l;Kc137(v?D;!|k|+m_gHNTjTeZ^{FiZjx$T+3p?rUY|Zp zcsj@ga~BKl>QlD?&Q+bY)0w^ph{oRY1jL!4mQjP^AY=eg<0w3 zNHT>ic)fa%2lTnC0s?17_hbH!Ikna`QQXNY5!-r2l}qJ@Pz$Z!u&Rs=6AVM5}C)EX>@(QE>@XE|W};F_kMX7Gdq|x}xpGNnw4d-ac(SDXO8|HDr_7h zc_@C{MpYS#)NDAta&)Y{G&103Nk^-gmc^B4 z$5D~Rinw-Uar#9@`Wz@2xfB)=>^2eyauxW8x$=VsgMxy3kC*iI1ve(lYj|FuY)9)5 z-sY-)jlEEoM=+NVsYC=2oU6)okwzI?HXvnVCz>1h43v1U$>2q5FgHNs?+TR&8^msR zg|us*_A|5vAJrNL=_lP{pl-ET=?9*)3!r54+)2cX__=II;7#B6HOCrpZj5*n zunpHdj|pAW^|PLP369_$ra8piIMzfKg>P{=ytKe7-V()=`X0|KzrW_!d^Y#dQ4!P1Mb>}DrkfOV1$I@pA)_&{mvYwVWLgi*9VHtwe0lEr(&SJbA1i;2 zN4i(+Cp?Ktw4Y%|<8Qi-MB<7XraRr9@iq>6*CbRFhWJ((@C9ET_^p3YwsqGtbBnmf z)BeX*XhG;#E3MdHi=pFf5s37hG|x{-YI9h#_KI6f9sdF~_e1{F39`TLdc4HOrz-bD zwmc!RD03dcbhxsKluW2Z z>glrfESt0$DkMC~hMnu89LZt}E9H4P@}R8hCI2w%>=i=YXYJLEBfb|SdB<>)M^BW- z7J+7Z8;_UX*K5(vh#tFd4*stgi$19REFxp`r@9n5hqGmz?QfJM**kbcfc84mr50)+I$I`i;9Xu|NnR3K|Ha!X^%m{Da@2BokG)tFz8!RGkup z3ecbu2WIv+NjEz0(ej;#3Epc_T&nS*WnpA%t-A8s^4Et-7aij`rGK+Di<@5Y6#K!e ztIy3!Q;}1MP)jJXW6LU*&xtpVg^c2UC2kM(lhX;suuC%R$YEwECQUfTV%4kP3sSPT z*T**eiW%ZF+vo)Oc$dceYIX`V(}7q~Vj~ z3MVoc!OY1y2Ukg+qO{wb9p~)_t8>ruLJc8Pt1L+$uO+9CT57kOcb-Z!tdO&|M4)Rt$?MP;WqDK^VZ z#PfU(Co_{GU3s_U^kG|@+GiE@%_cs3?YzonQ&!G`zkD%M~Y=y(HKI-FB3z>2X$9dA@l{m1bX?EA}cQ`ja zPR5q_hB#S{`K<_5RL8Pc#@d(4v_I7U&bNOX>A<3)lX&Lrl1%1+5OkVsBSVsev)np0 zqJEVia&>y)Fv<83&(=7*TAnf9zOR*e?<;nD8k|9WQ4L97ZAhTKX<^a}|M2HYRXqiu z!5wh~MKe6pB)HP{Wmu_FW$(}TP(EaO_7v9|Na^(SsXVMAgq!!Im&j%*3$(jajcVi7 z>%x927APhFkm*d)@UO&CJIicN+3{Wp#;bD*C|jJ1c+UG&)|^q~j0XwQf@VNr>&!># zW7CS#@6)W`U&-T~pK2EHP-VqCRM=ecs?tvepU9J|DA}x>S`tqoNW)qDmLm?XWG&Q7 zrw(O_b8>Q$L>G9|>`Aaqas?%zRzNw z1lyg9zzDY%jf)=K*BX$B%iHX3aL#M1uA1>MtwT9Gy?kly=}DzpK8@r}!z`wVM>A&( zcf(;FB521Q!#P9U6)P>x?X57nGgGu*JFhXNSaMaT7-6V#<#r1Z2_|nQ`I(gIjJ1r) zyNpb0P-^X|LjD%i{?V5mNg~j)6}#3B$KGRb`U$5;|7H2GhAPi%bmdP#krT7e`%8Bo z_#E{zWBd`_lm4wl<|G#*JsV;>u;@Y^kA9EZcRMcKm4@|3Ztx6*eAJId)6_V(KJ^`8 zjYAf6nG0nMS2^cgVIZL`9T9=yhrLiG(pq@K!#)2EcbcWOE4h|MLD_M1Wi3~0LdEX& zgN?1$MZq4pGG|KArq3&rjOU(vOO`Y}9*Y4dtg^PNzIk}PaDb5JdzLZwG`QKLcI@_Z z_o^`BtxHuM{_X7WW{+}y-$umKO9eaDN55&0M;1UjH$%0jLM>^oTeBbxgHiXEh_OQ7 zA7V0Lqs++Yg16@O6O!14Y<=xK!JRSJ5|e4<5w9VXjwa&Lblu7H{6r?e6Xx8XGGW81`Wi z%fhMta=m;u$6v;Z3)ym)9@;#H21APV?s*+7h3&TZ1vNA_x}I!3+A}s(s5ijco|~DT zelpuYh-yg7D&S>fD0vl59~qP9KZ_kMMell)tAhvlA%d7`U~P>x@68U6-~J18rBBb1 zJyi!5a!-xq2d+}}nkw!WIJFRsA0JMtF|GbR-Ss{mT}FRP)UdkViVkYfpovBMXi%Mx)LmI?6?t1i2*_Q%as#v3TqDD5PY2t8~D77qfbi}j+$8>b!rKoqs~tX$g>xK#5WJv)U*#y;(> zwU;c5ii%45p7H-1G=8~yI%BT(QNL$zkAGux)Ajnob#|M7{Ik1hLRO+7?pzLx-21zs zO_=386*k7%*;!RXLpZ39L3x;JQ4rJh3ZD0V{mkKy$GWSf@;5vsB_)ZP#S`1^0I#cO ztYmXs4>d86?=>{DKSbhANxKGH?Fh)wQ*yEl^zl1c6P(OiCn!q5+OCg=XJ==-j*dh+ z{+(8`WelsZ7!fN_7tsqlCgS8%+GXs>+lg9V-Fr)Jtr@Xw} z`{s1!&;HA|_vLRd$0uDHS0#y#E@gSs@I|slChS=qyoL{Gk0M~bE7i<7?Bv(&l57ns zOmeQ6GnJ;jKYvnzztzc?8!a$Q@4!@OT~w_$RBkp2cgO}(7ly=$M_W99j`!lli`n^k zTJq8cW*-7Qe!UON2QpJsM5Gc&u`5@dsAynb7}d`W%K zc`Mg(`sL+nK?Gw@1XBQ1dun3eQ_6xp8~ZFpK-yOqQO&vFHNGnqNq$NRNluCizqD=;jAf<`1&X1^8`7 zPZHsMJ9t5iu{uyK{GWufW4@^k}Ofd_{q3%AGZ|-|cHcZ>#=p4$<5|r0^*>zfyw+t69&} zjz*8HXBL(zXvwl^#|aOHOFzbr1N7NGYIbQ!l`}uDb`(nii}x|38&ECU0n+eoCtX2 zo!L%h`$K|(J=VF}Rf>-HNI3TN-U_*>Bb8d)0`okefyxRT| z8@MxxgWcX=0%}2vfB;6Y&0h=%nEVbgAk4WsA$rmIH+#>$FIFR@T>Q2sSb&fM_tJLs zjgK2R0e*tVj~@fdlweyE6m!XfBmurN(=PbrE!>{m?o~OE_Yfx%Hr=( zAZr)|s+BV5O4y>a(n2JiOXQyW3|GJ{d`~GA7pn9ieUZmn1BdpJJ7b{|shHuvoU8<$ zQmpag#Nl6ndEdn53p$}xX~HkYygEX{!f+s6ug4!mls~QPai#bByIp!m{D2#SnH7pA z6?oHv9kM}#l!60^^RWqMElJo{n*ID&t8EeS7%NNeiO3IrAxbKF&;$@>rM zw_hTFCl1pp{cxxSO(4Y-Sz6%JcjsIiXi6Lg zY}kJrQngFQV-31`+pt+HtCIEcusR5nnG-{-dVYF1cV$KPq+9B`PWHgD!v@HS?8X}# z8oVFG&n*H5Ub((J_RH`;n|sbpfe+UvPq%dy1u#j}DJ^iIyR#wdL!_A{_cVDxL5LWn z5rJRqgC9@^32Y#&ZN*rs3lWi0nptAQTAxL5GLF6NjOPgZ^Fv7t(?_Y13s$V@qnCYp zA{72!`t-nQ)905Nl!NWgE-BFG4bqEVzWsOJ_W30ZF3^`jHOG27PA)EC35f`|=8?f_ zuu!ExhWm*Q-ZbG8#oQX7)joN)8j2Gr$)~Ty#Pn3e$=&Z0Ga^FS$Y#$ma$a+zj__)_ z*$?2G*w#J+xw4zpwNV6Luv}Q=U1;1>$|U=2(#OiKmVH-Pft=a+lMdAa?9#$gaE~z1u5KKu+SN9l0boEW%U{U(=zq3aAN7fsKb51?y{va+{RY#f# z;tkha=oF?}Sy~1id}D?_l{()Pv>Ehbtz-@!x0lpG#k?4%_M#o7!ET6Xe0V1GJ zY%VawqC4)=ujuiBHQcZZAqkF(x;Ms2#)DIMY~>BRGNpPK?OWROU*F;)ij+>5$(B8) zKVxkts=RDoXYaq+K-&mbX<9qMS&J+$b0ed*l;_wEiTZ|RTD!(0|NV}w-?4#2V zs|bL8h#P$ppOI_NYWm;rpg;ahY6*<}plA}GKYxC2R*CM$W9s{2+*sAtMt?N|WR!?e zcE~jbq=(V&(Hx0O);vj9OmcE^AnRa(=6}CutoSgFBjzfSz3MXCqc4%lx5dIM<~S-t zov)`99UuyikztdgJ<2uAF?2S4d@T`-AsxN&b=l{btdhMXfUnfz7ZUiMRunFJT4eLc zo=hkKYPw^jO5t$JNaIEqOJCpn$H&J&NM{!p`@tt`DiMwt@cgfQI{4s9GT>Tr{ERM6 zm1$|;17{+XRjk;kZ#msqndFEnhJ8UG8D|^ow)c&GIDt>1%X@qRsfGg5hjGkMBvB1O zh8AatlR@ufky>?qeb~p3JQOiLey8Q;{m=9L!+}VA}=2 zCIdGp%iVMY4x)x*J^qYG()ebQPATwq5>XA#TzVAxZtBqkg)_L7NnT+|`VTs&J(FQW zLm$0aH!%Ypc7PbZPqp}U;cC+1M_X@1sJLPYydyVN3~+TIik!Y-XmCD8`C{Jb#}( z=GP0Zboop!|o2gPA)Em zdOX0BtpEh~g4zNN(#e(XuN9^e7pcXBfTcIR-XsF#7n+tvnHLb_p|KH2TN(fKcd=DJ z$l8^$Mp^~Q7l8v!vHw2ciITE5uweb_&Ah00q&$92P$sq`t9WsQWsYedSb^#u`_1@i zn%C$H6_kaZ?o^hz-zo`p>sbG7bm-&b(mOBEdn{`h9`&X^9Du^J979vdOuW`PCgYEx z4P~4JQiRQUx;ZP+OM=B;X9P}u4-!tp79BYa&tb#5TGNa+gtAfF)jnhNtR5>yHNHf5 z1z~}i)~G@I3@?mCTdi2HyTktqE-#-jI;y?U=0pCX90km{Lbc&~Yl&HT*SUY{ux*`@ z0H87Sa;^^r9ua+@?G6-+cv}lU?;x0U#ana5tKfw~`J8gS-oV}otfeAGYd}>xH`-N` zbv3NLq{JpZKl5o>bVv9n4@-TS%r=Ndn-w(==UaSaL=I&cG}1t6v+~4Ogq9oA z%^oj$E%#69%8%C8=H@bJX=|^J<;nnKy!|4M@wBMQxEhhuod?j|Ha>9f510-l3ov6j zhSg0wx^fL@8mz^8(BlEh2Lry=*48HXZ8DfrZwRqmBpeEqd6XrBhMB#7HZs1NPe!bnwbm!X8yD`Tn`3*w7h6Fj ziEu{A+K$`Rn)uQ>|J+sG?~QfemL$^5@d6XDom0*{pAA}*&Vbz7f5u;^YUcQvhDX-Slx_{DVqh8L>yV9F$)m8hw#PWTm`2o?}+YYif zC(CRS!a)*C-XSxj&(s2=Uvej8ST4H_&MCOK*<3_^EPjoNV(FuQg2!vLEHN7)aF*g{My@&E5U$kG*fR4zhr!G`TFM>H_1k=rynrv8y=RO_R7|i-dOeC#R-)x1o zn5tby))zbEbD|WFIuS)ME$Hu885tX0{oen!KSrn{5(vY4L;fRJ&7#Y33F{L@WyV^2 zBbtpKh`@}8Vmzai`m|LCYZ~`L($0qA(mwA<;yP z*5HCfNmdxslCsdC9B0M@?H=NrwNhoKG-nor`j1kF^PbN;nAk^aPyJmJz1BtU!gl)k zkI0q2GNn495D5m{zvK|oJb|~{k}QReff_yP(ca2UdN^&w>sb0BE+@{PD%9?&4}Jah zdB!)9m2*s+(m002&ClgQN%A|lm^w`E%U!J@QUQJ#R`EU=UJre`y=pRdE&8|M^ro%n zlh{t}`bg9^7PFJzmL=`l^|N^fp_=FiVj5hf9H*1_Z=eOs@0CIyS0!shpH$S*FLBJR zKFWUgLsZhqc=&K{#S3R5Qn(8Khhb8_N>d+^)o`Cz=K)O#%|O-J${!+vJuY!xX9EoW z-cRCgc#6pz!&S7Xs%f#+i*E8ym^GC-Ju;y0D3o?!;oO3Ms8+g| zZKgy+jcmnjFk(m}xE0bY`oG41)BFW9XqfTO;mzAuOcn4b4F5EefG9c9UgG1HSvTy3rK+GtCt__VIn#s?)#V6H>$PB1&kX zO3YBdG1tf!Ps+49RkT)@#x9s2l#24Q?7XnLhBjKpBm~UytOl(4KZ#L>TF@B8&WzG? z@(m4SL6SJ2m`NVx!&{5Yw00z;Y|+p2|M80aJy790;EztbzY0c|iCxT$VS9rr{y)V`drIr0!xX+_F74 zy>&~N3vJN0E;5ivXsqU}j{OUR2mO3I)IHTM;p(4cmVgXyu-JQ|-66W?88p2$d9Df^ zp798!@5$NgPxh^jl%E(0n3s}mmA%mS9<18U?9tZN{*#<(a-SiCQKIW2!+PaU)t21b zc!oy!o@5?-jqi8Q$NSKq!vtK#%?i#(2>!!gmsl3wqTSo!PvP!X-e?jvQv`kLq;TLI4D(q3CQ@VDQ~JK z@TyfGP~b?&$Pg?OkX}#(=~_Fpu4T<0tu8xNg9D9{QUwGX{=sauOl+4k4K9){?eZ%W zWdIU^+8R5~VGUMVW1&5!ex9jZur^HP33+-D&m`^e^Qn*OS)n8WeO&uNE+VB5#e+U$ z4^Z`bnA*JdxnAdzk9xNnMb6dq#n~%+!u>=?`RVD;s3s5hU>LbNI1ch7P)#mKwes+w zoO7be)rs)ZYpx(DbbxD-pQ>WT?-uU*KzYJY`#s10b@R>$V}aRigweiuFgz5sA8b#j zX>5Gx$K;!a-`RndWX=wE{1T3=j?}D=uGkF1GJW`A$H8mGtB!FV zg0*{fVEkfdhr92YL;Tt33%EEy$gP~}T#e}V*1{v@(rr7DJ6&Y}vIAmw#^L!s3Qv2g zs;Vjw_%j*%tST_fDGb2^T1hzR${=Z)@s_KI3k>Dky%yw-#n!S)v?lxPbeqL=Dth3s zp&F;_zcZcjk9z`ulmCNt!CDwSEOY!UBWKq)UrfPC5?e%K?1V-u+KNSW9oF{1iOSp+(glbW@OcikA39*^446V7?ifYk*vr+f>Lr!HA zBm(sEoTjCUGbW>H2ieGK($%FbQpFkwW^b5o=4soGgl>_Bah5Cc1P^YQ{>7U$yWzx7 z#h*gHmEMm;8Z_{n{G&pRBnNU$YJ8<*%TI*61SwFua4@ueDO?m8F`oHlrPB6((n zzHyI&e`-K`tWq)`)%;9? z{FBtk2rYkjtM(tpUX{`&@#N;^4G`R3n7=w&XTxIBye_qYJe*(nkRfQ=^Y^dx&zYI( z=H{r=)6<|sm&_{suqYw+51=Nu5($zuPq`_)d+iZ}ihgX^{olUfr&FDyzjEcTV;cN^ zH%T{@U@IXZu?>cMP?p(+g+4HO*2$BVI+>ytGP_1j37!5+_`3OXgY+O@)F zuplNa?oxKW{}q!_QBz+ct9Jk0zUkZi&;o{#Nj&)b2j4BW+QYN*ZV6S41+rSn`AosT OLNru#lq--H!T$rz!3F*R literal 0 HcmV?d00001 diff --git a/other_icons/climate.jpg b/other_icons/climate.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b597f9eb920fafb102fb5544cb96206eff4ff729 GIT binary patch literal 11250 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 OiNGfU|6>RkrT-47FGbV< literal 0 HcmV?d00001 diff --git a/other_icons/climate.png b/other_icons/climate.png new file mode 100644 index 0000000000000000000000000000000000000000..5f465bb86b9fd6744f30c94a47946e689690113c GIT binary patch literal 7070 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 KKOtac8U8P0L;I!x literal 0 HcmV?d00001 diff --git a/other_icons/events.png b/other_icons/events.png new file mode 100644 index 0000000000000000000000000000000000000000..c388cfaa9a13ed340ba294df384da6f46abdbfa9 GIT binary patch literal 7807 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 literal 0 HcmV?d00001 diff --git a/other_icons/lighting.jpg b/other_icons/lighting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3b09c4a4e93cde0c432dbb25516e4de1e16edf6e GIT binary patch literal 11580 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 literal 0 HcmV?d00001 diff --git a/other_icons/lighting.png b/other_icons/lighting.png new file mode 100644 index 0000000000000000000000000000000000000000..c39cb88228ea62b23257c92b1b626491c4a264b8 GIT binary patch literal 8304 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 HY5Knar#7c| literal 0 HcmV?d00001 diff --git a/other_icons/power.png b/other_icons/power.png new file mode 100644 index 0000000000000000000000000000000000000000..23d0c7e34a5d89e40381834373afcdada651bf8f GIT binary patch literal 7883 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 literal 0 HcmV?d00001 diff --git a/other_icons/status.jpg b/other_icons/status.jpg new file mode 100644 index 0000000000000000000000000000000000000000..451a25e2c1f2f852883474d904658214245bdb4a GIT binary patch literal 10434 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 literal 0 HcmV?d00001 diff --git a/other_icons/status.png b/other_icons/status.png new file mode 100644 index 0000000000000000000000000000000000000000..306509c22c5b2ca538ad8bb7f2122309f1467d1b GIT binary patch literal 7300 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 literal 0 HcmV?d00001 diff --git a/pxweather.class.php b/pxweather.class.php new file mode 100644 index 0000000..fef3ff1 --- /dev/null +++ b/pxweather.class.php @@ -0,0 +1,257 @@ +_city = $city; + $this->_force = $force; + + } + + function setOption($option, $value) { + + switch($option) { + case EASYWEATHER_URL: + $this->_url = $value; + break; + case EASYWEATHER_CACHE: + $this->_cache = $value; + break; + case EASYWEATHER_CACHEFOR: + $this->_age = $value; + break; + case EASYWEATHER_CACHEAT: + $this->_cachepath = $value; + break; + } + + } + + /* + ** Return a pretty-printed version of the XML array + */ + function toString($array = null) { + + if ($array == null) { + $array = $this->_xml; + } + + echo "

";
+		 print_r($array);
+		 echo "
"; + } + + /* + ** Return a specific field from the current weather report + */ + function getCurrent($field) { + $o = $this->_getObservation(); + + if (array_key_exists($field, $o)) { + return $o[$field]; + } + else { + return null; + } + } + + function getSunrise() { + $a = $this->_getAlmanac(); + + return $a["sunrise"]; + } + + function getSunset() { + $a = $this->_getAlmanac(); + + return $a["sunset"]; + } + + function getForecasts() { + + // need to remove a layer of separation + + $forecasts = $this->_xml["forexml"]["#"]["forecast"]; + + $returnArray = array(); + + $i = 0; + + foreach ($forecasts as $forecast) { + $returnArray[$i] = $forecast["@"]; + $i++; + } + + return $returnArray; + + } + + function getDaycasts() { + + // need to remove a layer of separation + + $daycasts = $this->_xml["forexml"]["#"]["daycast"]; + + $returnArray = array(); + + $i = 0; + + foreach ($daycasts as $daycast) { + $returnArray[$i] = $daycast["@"]; + $i++; + } + + return $returnArray; + } + + /* + ** Returns a weather condition string given a code (i.e 'TS') + */ + function weatherString($code) { + + switch($code) { + case "TS": + return "Thunderstorms"; + break; + case "RA": + return "Rain"; + break; + case "MC": + return "Mostly cloudy"; + break; + case "SU": + return "Sunny"; + break; + case "MO": + return "Mostly clear"; + break; + case "PC": + return "Partly cloudy"; + break; + case "SN": + return "Snow"; + break; + case "CL": + return "Overcast"; + break; + case "FG": + return "Fog"; + break; + } + + return null; + + } + + function load() { + + $filename = "$this->_cachepath/weather.$this->_city.cache"; + + // if not force, check cache for valid file + if (!$this->_force && $this->_cache) { + + if (file_exists($filename) + && filemtime($filename) > (time() - ($this->_age * 60))) { + + $file = fopen($filename, "r"); + $this->_xml = unserialize(fread($file, filesize($filename))); + fclose($file); + + return; + } + } + + // if force, or no valid cache file, get XML fresh + + $this->_xml = $this->_getXML(); + + if ($this->_cache) { + $file = fopen($filename, "w"); + fwrite($file, serialize($this->_xml)); + fclose($file); + } + + } + + function _getXML() { + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $this->_url . "?" . $this->_city); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + #echo $this->_url . "?" . $this->_city; + #exit; + + $xml = curl_exec($ch); + + #print_r($xml); + #exit; + + if (curl_errno($ch)) { + trigger_error("cURL Error in Weather._getXML: " . curl_error($ch), E_WARNING); + return null; + } + + curl_close($ch); + + return xmlize($xml); + + } + + function _getObservation() { + + return $this->_xml["forexml"]["#"]["observation"][0]["@"]; + + } + + // array with keys "sunrise" and "sunset" + function _getAlmanac() { + + return $this->_xml["forexml"]["#"]["almanac"][0]["@"]; + } + +} + +?> diff --git a/pxweather/LICENSE.txt b/pxweather/LICENSE.txt new file mode 100755 index 0000000..b860267 --- /dev/null +++ b/pxweather/LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, 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 Library 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/pxweather/README.txt b/pxweather/README.txt new file mode 100755 index 0000000..eb99501 --- /dev/null +++ b/pxweather/README.txt @@ -0,0 +1,302 @@ +pxWeather - Readme +================== + + A PHP class to retrieve, parse, and organize weather data for easy + access. + + Version 0.1 + ----------- + http://pxweather.abbett.org/ + + + Copyright (C) 2005 Jonathan M. Abbett + + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2, as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA + + + Requirements: + PHP 4.1.0 or later, installed with cURL support + + + Summary: + pxWeather gives you easy access to National Weather Service forecasts + and current conditions for integration into your PHP application. To + improve performance and decrease load on the data source, pxWeather + can cache weather data locally. + + + Download: + The latest version will always be available at + https://sourceforge.net/projects/pxweather/ + + + Credits: + Many thanks go to Hans Anderson for his XMLize utility, which makes + short work of XML parsing. XMLize, which is included in this + distribution, can be found at http://www.hansanderson.com/php/xml/ + + + Installation: + - Decompress your .zip or .tar.gz file. + - Copy pxweather.inc.php to your PHP-enabled website. + - If you use PHP5, copy xmlize-php5.inc.php to the same directory + on your website. If you use PHP4, copy xmlize-php4.inc.php. + - If you intend to use caching, create a new directory for cache + files to live. Make sure it has proper read/write permissions set. + + (NOTE: by default, pxWeather will use the local subdirectory + "cache" to read/write cache files. You may use pxWeather's + setOption method to set a different directory.) + + + Testing Your Installation: + Test your installation with the following bit of code. This code + assumes it's running in the same directory as pxweather/xmlize and + that caching uses the default settings. + + load(); + echo $w->getCurrent("temp.string"); + + ?> + + When you run it, you should see the current temperature for + Boston, MA in degrees Farenheit and Celsius. + + + Configuring pxWeather: + All pxWeather configuration is done through the class constructor + and the class's setOption method. The examples below assume you've + already loaded pxweather.class.php, as above. + + To set a city other than Boston, MA, call the constructor with the + $city variable set: + + + + Sometimes, two cities (i.e. Portland, ME and Portland, OR) have the + same name. So, in any case where there might be ambiguity, consider + using the ICAO location code for your city. The FAA maintains a + list of codes for the USA at + https://pilotweb.nas.faa.gov/qryhtml/icao/USA.html + + + + To force pxWeather to ignore its cache, and retrieve data directly + from the source, you can call the constructor with the $force + variable set to true: + + + + Other, less-common settings can be changed with the setOption method. + For example, to disable caching: + + setOption("PXWEATHER_CACHE", false); + + ?> + + Four options may be set this way: + + PXWEATHER_URL (URL) + The URL used to retrieve XML weather data. + + PXWEATHER_CACHE (true/false) + Enable/disable caching; enabled by default. + + PXWEATHER_CACHEFOR (number) + Number of minutes to keep cached data; 60 by default. + + PXWEATHER_CACHEAT (path) + The directory where cache files should be stored; 'cache' by + default. + + + Accessing Data: + pxWeather extracts four kinds of data from the XML feed: + + 1. Current conditions + 2. Almanac times + 3. Forecasts + 4. Daycasts + + Current conditions can be retrieved with the getCurrent() + method, which takes a field name as argument. The following are + valid field names: + + FIELD NAME EXAMPLE VALUE + ----------------- --------------------- + city Boston, MA + longname Boston, MA + ident KBOS + latitude 42.37 + longitude -71.03 + timezone -5 + daylight_saving 1 + night 0 + weather_code PC + observation_name KBOS (Boston, MA) + time 5 PM EDT 24 JUN 05 + temp.string 86 F (30 C) + temp.F 86 + temp.C 30 + dewpt.string 53 F (11 C) + dewpt.F 53 + dewpt.C 11 + rel_hum.string 32 % + rel_hum.percent 32 + wind.string SW at 17 knt + wind_direct SW + wind_speed.knt 17 + heat_index.F 84 + pressure.string 1016.7 mb (30.03 in) + pressure.mb 1016.7 + pressure.in 30.03 + skies mostly cloudy + text_weather haze + + The example from above: + + load(); + echo $w->getCurrent('temp.string'); + + ?> + + Almanac times (sunrise, sunset) can be retrieved with the methods + getSunrise() and getSunset(). They take no arguments, and return + time strings in 12-hour format (i.e. 5:08 AM). + + Forecasts include a day name, a weather code, a low or high + temperature, and a text description of the forecast. Forecasts for + approximately the next six days and nights can be retrieved with the + getForecasts() method, which takes no arguments. The method returns + an array containing all forecasts. The example below cycles through + each forecast, translates its weather code into a readable string + with the weatherString() method, and prints high/low temperatures + and text forecast. + + load(); + + echo "
";
+            
+            foreach($w->getForecasts() as $forecast)
+            {
+                echo "FORECAST FOR " . $forecast['day']. ":\n";
+                echo $w->weatherString($forecast['weather']) . "\n";
+            	
+                if (isset($forecast['low_temp']))
+                    echo "Low temperature: " . $forecast['low_temp'] . "\n";
+
+                if (isset($forecast['high_temp']))
+                    echo "High temperature: " . $forecast['high_temp'] . "\n";
+            	    
+                echo "Description: " . $forecast['text'] . "\n\n";
+            	
+            }
+            
+            echo "
"; + + ?> + + Daycasts are very similar to forecasts, but are not split into + individual day and night reports and do not have text forecast + descriptions. An example like above: + + load(); + + echo "
";
+            
+            foreach($w->getDaycasts() as $daycast)
+            {
+                echo "DAYCAST FOR " . $daycast['day']. ":\n";
+                echo $w->weatherString($daycast['weather']) . "\n";
+
+                if (isset($daycast['low_temp']))
+                    echo "Low temperature: " . $daycast['low_temp'] . "\n";
+
+                if (isset($daycast['high_temp']))
+                    echo "High temperature: " . $daycast['high_temp'] . "\n\n";
+            }
+            
+            echo "
"; + + + ?> + + If you want to inspect the entire weather data structure, use the + toString() method: + + load(); + + $w->toString(); + + ?> + + + Feedback and Requests: + SourceForge hosts a variety of forums to express your constructive + feedback: + + - Feature Requests + http://sourceforge.net/tracker/?atid=753105&group_id=142667 + - Support Requests + http://sourceforge.net/tracker/?atid=753103&group_id=142667 + - Open Discussion + http://sourceforge.net/forum/forum.php?forum_id=477711 + + All feedback and requests should be channeled through those outlets, + and not sent by e-mail. + + + Thank you for using pxWeather! diff --git a/pxweather/pxweather.class.php b/pxweather/pxweather.class.php new file mode 100755 index 0000000..1ec7697 --- /dev/null +++ b/pxweather/pxweather.class.php @@ -0,0 +1,251 @@ +_city = strtoupper($city); + $this->_force = $force; + + } + + function setOption($option, $value) { + + switch($option) { + case EASYWEATHER_URL: + $this->_url = $value; + break; + case EASYWEATHER_CACHE: + $this->_cache = $value; + break; + case EASYWEATHER_CACHEFOR: + $this->_age = $value; + break; + case EASYWEATHER_CACHEAT: + $this->_cachepath = $value; + break; + } + + } + + /* + ** Return a pretty-printed version of the XML array + */ + function toString($array = null) { + + if ($array == null) { + $array = $this->_xml; + } + + echo "
";
+		 print_r($array);
+		 echo "
"; + } + + /* + ** Return a specific field from the current weather report + */ + function getCurrent($field) { + $o = $this->_getObservation(); + + if (array_key_exists($field, $o)) { + return $o[$field]; + } + else { + return null; + } + } + + function getSunrise() { + $a = $this->_getAlmanac(); + + return $a["sunrise"]; + } + + function getSunset() { + $a = $this->_getAlmanac(); + + return $a["sunset"]; + } + + function getForecasts() { + + // need to remove a layer of separation + + $forecasts = $this->_xml["forexml"]["#"]["forecast"]; + + $returnArray = array(); + + $i = 0; + + foreach ($forecasts as $forecast) { + $returnArray[$i] = $forecast["@"]; + $i++; + } + + return $returnArray; + + } + + function getDaycasts() { + + // need to remove a layer of separation + + $daycasts = $this->_xml["forexml"]["#"]["daycast"]; + + $returnArray = array(); + + $i = 0; + + foreach ($daycasts as $daycast) { + $returnArray[$i] = $daycast["@"]; + $i++; + } + + return $returnArray; + } + + /* + ** Returns a weather condition string given a code (i.e 'TS') + */ + function weatherString($code) { + + switch($code) { + case "TS": + return "Thunderstorms"; + break; + case "RA": + return "Rain"; + break; + case "MC": + return "Mostly cloudy"; + break; + case "SU": + return "Sunny"; + break; + case "MO": + return "Mostly clear"; + break; + case "PC": + return "Partly cloudy"; + break; + case "SN": + return "Snow"; + break; + case "CL": + return "Overcast"; + break; + case "FG": + return "Fog"; + break; + } + + return null; + + } + + function load() { + + $filename = "$this->_cachepath/weather.$this->_city.cache"; + + // if not force, check cache for valid file + if (!$this->_force && $this->_cache) { + + if (file_exists($filename) + && filemtime($filename) > (time() - ($this->_age * 60))) { + + $file = fopen($filename, "r"); + $this->_xml = unserialize(fread($file, filesize($filename))); + fclose($file); + + return; + } + } + + // if force, or no valid cache file, get XML fresh + + $this->_xml = $this->_getXML(); + + if ($this->_cache) { + $file = fopen($filename, "w"); + fwrite($file, serialize($this->_xml)); + fclose($file); + } + + } + + function _getXML() { + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $this->_url . "?" . $this->_city); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $xml = curl_exec($ch); + + if (curl_errno($ch)) { + trigger_error("cURL Error in Weather._getXML: " . curl_error($ch), E_WARNING); + return null; + } + + curl_close($ch); + + return xmlize($xml); + + } + + function _getObservation() { + + return $this->_xml["forexml"]["#"]["observation"][0]["@"]; + + } + + // array with keys "sunrise" and "sunset" + function _getAlmanac() { + + return $this->_xml["forexml"]["#"]["almanac"][0]["@"]; + } + +} + +?> \ No newline at end of file diff --git a/pxweather/xmlize-php4.inc.php b/pxweather/xmlize-php4.inc.php new file mode 100755 index 0000000..f73aaa3 --- /dev/null +++ b/pxweather/xmlize-php4.inc.php @@ -0,0 +1,168 @@ +' . implode("", $traverse_array . '
'; + * + * + */ + +function traverse_xmlize($array, $arrName = "array", $level = 0) { + + foreach($array as $key=>$val) + { + if ( is_array($val) ) + { + traverse_xmlize($val, $arrName . "[" . $key . "]", $level + 1); + } else { + $GLOBALS['traverse_array'][] = '$' . $arrName . '[' . $key . '] = "' . $val . "\"\n"; + } + } + + return 1; + +} + +?> \ No newline at end of file diff --git a/pxweather/xmlize-php5.inc.php b/pxweather/xmlize-php5.inc.php new file mode 100755 index 0000000..42e509c --- /dev/null +++ b/pxweather/xmlize-php5.inc.php @@ -0,0 +1,174 @@ + attached is the modified script. Basically it has a new optional parameter + > to specify an OUTPUT encoding. If not specified, it defaults to UTF-8. + > I recommend you to read this PHP bug. There you can see how PHP4, PHP5.0.0 + > and PHP5.0.2 will handle this. + > http://bugs.php.net/bug.php?id=29711 + > Ciao, Eloy :-) + ## + * + */ + +function xmlize($data, $WHITE=1, $encoding='UTF-8') { + + $data = trim($data); + $vals = $index = $array = array(); + $parser = xml_parser_create($encoding); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $WHITE); + xml_parse_into_struct($parser, $data, $vals, $index); + xml_parser_free($parser); + + $i = 0; + + $tagname = $vals[$i]['tag']; + if ( isset ($vals[$i]['attributes'] ) ) + { + $array[$tagname]['@'] = $vals[$i]['attributes']; + } else { + $array[$tagname]['@'] = array(); + } + + $array[$tagname]["#"] = xml_depth($vals, $i); + + + return $array; +} + +/* + * + * You don't need to do anything with this function, it's called by + * xmlize. It's a recursive function, calling itself as it goes deeper + * into the xml levels. If you make any improvements, please let me know. + * + * + */ + +function xml_depth($vals, &$i) { + $children = array(); + + if ( isset($vals[$i]['value']) ) + { + array_push($children, $vals[$i]['value']); + } + + while (++$i < count($vals)) { + + switch ($vals[$i]['type']) { + + case 'open': + + if ( isset ( $vals[$i]['tag'] ) ) + { + $tagname = $vals[$i]['tag']; + } else { + $tagname = ''; + } + + if ( isset ( $children[$tagname] ) ) + { + $size = sizeof($children[$tagname]); + } else { + $size = 0; + } + + if ( isset ( $vals[$i]['attributes'] ) ) { + $children[$tagname][$size]['@'] = $vals[$i]["attributes"]; + + } + + $children[$tagname][$size]['#'] = xml_depth($vals, $i); + + break; + + + case 'cdata': + array_push($children, $vals[$i]['value']); + break; + + case 'complete': + $tagname = $vals[$i]['tag']; + + if( isset ($children[$tagname]) ) + { + $size = sizeof($children[$tagname]); + } else { + $size = 0; + } + + if( isset ( $vals[$i]['value'] ) ) + { + $children[$tagname][$size]["#"] = $vals[$i]['value']; + } else { + $children[$tagname][$size]["#"] = ''; + } + + if ( isset ($vals[$i]['attributes']) ) { + $children[$tagname][$size]['@'] + = $vals[$i]['attributes']; + } + + break; + + case 'close': + return $children; + break; + } + + } + + return $children; + + +} + + +/* function by acebone@f2s.com, a HUGE help! + * + * this helps you understand the structure of the array xmlize() outputs + * + * usage: + * traverse_xmlize($xml, 'xml_'); + * print '
' . implode("", $traverse_array . '
'; + * + * + */ + +function traverse_xmlize($array, $arrName = "array", $level = 0) { + + foreach($array as $key=>$val) + { + if ( is_array($val) ) + { + traverse_xmlize($val, $arrName . "[" . $key . "]", $level + 1); + } else { + $GLOBALS['traverse_array'][] = '$' . $arrName . '[' . $key . '] = "' . $val . "\"\n"; + } + } + + return 1; + +} + +?> \ No newline at end of file diff --git a/right-arrow.html b/right-arrow.html new file mode 100644 index 0000000..efc1ff2 --- /dev/null +++ b/right-arrow.html @@ -0,0 +1,46 @@ + + + + + diff --git a/rotate-weather.php b/rotate-weather.php new file mode 100644 index 0000000..bcb4868 --- /dev/null +++ b/rotate-weather.php @@ -0,0 +1,6 @@ +
+ + + +
diff --git a/russ.txt b/russ.txt new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/russ.txt @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/security1.html b/security1.html new file mode 100644 index 0000000..f92965e --- /dev/null +++ b/security1.html @@ -0,0 +1,19 @@ + + + + +
+CAM1 + +CAM2 + +CAM3 + +CAM4 + +CAM5 + +CAM6 + +CAM7 +
diff --git a/set_climate_status.php b/set_climate_status.php new file mode 100644 index 0000000..b60de24 --- /dev/null +++ b/set_climate_status.php @@ -0,0 +1,35 @@ +$device, + 'submit'=>$state +); + +foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; } +rtrim($fields_string,'&'); + + +$ch = curl_init(); + +curl_setopt($ch, CURLOPT_URL,"http://isy99/change"); + +curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); +curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); +curl_setopt($ch, CURLOPT_USERPWD, 'admin:admin'); +curl_setopt($ch,CURLOPT_POST,count($fields)); +curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string); + + + + +$output = curl_exec($ch); + +#echo "
";
+
+#print_r($output);
+
+exit;
+
+?>
diff --git a/set_isy99i_status.php b/set_isy99i_status.php
new file mode 100644
index 0000000..dc54072
--- /dev/null
+++ b/set_isy99i_status.php
@@ -0,0 +1,48 @@
+$device,
+  'submit'=>$state
+);
+
+foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
+rtrim($fields_string,'&');
+
+$ch = curl_init();
+
+if ("nodes"==substr($device,0,5)) {
+  $string="http://isy99/rest/nodes/".rawurlencode(substr($device,-10))."/cmd/$state";
+} else  {
+  if ($state=="DON") {
+    $state="runThen";
+  } else {
+    $state="runElse";
+  }
+  $string="http://isy99/rest/programs/".rawurlencode(substr($device,-4))."/$state";
+}
+curl_setopt($ch, CURLOPT_URL,"$string");
+
+#echo "-$string-";
+#exit;
+
+#echo "http://isy99/rest/nodes/$device/cmd/$state";
+
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+curl_setopt($ch, CURLOPT_USERPWD, 'admin:admin');
+curl_setopt($ch, CURLOPT_HEADER, 0);
+#curl_setopt($ch,CURLOPT_POST,count($fields));
+#curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
+
+
+
+$output = curl_exec($ch);
+
+#echo "
";
+
+#print_r($output);
+
+#curl_close($ch);
+?>
diff --git a/set_summon_status.php b/set_summon_status.php
new file mode 100644
index 0000000..9850723
--- /dev/null
+++ b/set_summon_status.php
@@ -0,0 +1,10 @@
+
diff --git a/thermometer-blank-black.png b/thermometer-blank-black.png
new file mode 100644
index 0000000000000000000000000000000000000000..584c4b884dcaa8adcabece192f1426c0d290343c
GIT binary patch
literal 1753
zcmeAS@N?(olHy`uVBq!ia0vp^WDRtAP128KRK$*Bwsa~T-sX=yEGU|7Szu$6&fA0y*VPR>SG*A{Q@
z{a#+%LPGY3h3!dCKg7avkb~n02geCP!84MQM->z?i{Ri_5fN{qqhFVlysNDIkevJ}J^gE5-mmiV_V)I9
z&CL@gOqe-y=F+80SFc{ZfB*h_O-=7RJKs&6`f>K`W522z=q2d=r?b7)pZtf`RE_Bm;)v@9e6;w7^;55m^i@S|)=q
z*ARs=V?ATDmCqjmH8Qbzx;TbpIKQ2h
z8GOhf%#K%z&pz|&{&b&Ka!>YnX8T&+izVCV_-+6D<3URS)0@p#-!hd|%O3i2l_QfJlh+|$ONPj3ImNuATr
z>@PZ5W7~Ga*X7umlhY3`Zf>4yxUv6v)Yc$9(Qo1TPxe2au>5q|<2_YjTF;7KUS9Bi
z@x8L5i+i%nvKFvKq}hrdsGQ}w_hL$tgQ!GWZujq(2VY%fbMWC_p_5P*dxAIl$r`SY
zzBi}YslQpqt{twW#}cKGHhY(sYti8wo-1SYcFLYfYuLo&dsC)!VvS&vcdA9|tCJBW
zCeySXo)jl2a^E&FnHqHQLE9}4Gj^|8ks@0sk=J1Sf7DqIE
z=PoO$dvc>n^Y$~2W}fMbgoGV@yW2CR4D_Z?n)%N3FmJ5)v4gxFx}8s6O^obyHCm??
z({-+6dPDxhBO;-pNqWvNr`$Qz_3rksd?NIu5p_HS3
l*#wJX*04t(F2BxCieFnO&=_!o{WYjq@pScbS?83{1OWYrnsWdE

literal 0
HcmV?d00001

diff --git a/thermometer-blank.png b/thermometer-blank.png
new file mode 100644
index 0000000000000000000000000000000000000000..0242c0e009a3d74d399095fe865eea8c921b9a52
GIT binary patch
literal 1292
zcmV+n1@roeP)kR~Q3GBPqz006!L0mKLhwEzIE007Jx8ORY4o&W&UDJjq)
zA=ol9i~s=KIy#jA0N_GGr2qivQ&V&R0OU$a@MB|z003+N0QGKe{P*`-007JY0Am0E
zgGov3TU&*Nh1Gj|KEARwHa
zoOX70nQ3YAXJ>LSFun%|nngvxqN3Emz`_Is?~99z8XCC<2K3L*J0T(MI4gy!4Z*Poy4l9KiC@Y=w@*2BY)kdTj$kB*Lxjg5_rjEswmi;9YhiHV7bh=_-W
zhlYlRg@uKLgoJ~GgMxyBfq{X5fPjC0e|~;`eSLj=e0+O*dwP0$d3kwwczAbrcXoDm
zb#--gbaZobb8>QWadB~QaBy#LZ*FdGZEbCAY;0?5Yieq0X=!O_XlQ3=XJ%$*Wo2b#
zWMpGwV`5@rVPRolU|?TgUtV5bU0q#VTwGgQTUuILSy@?FSXftAS5{V5RaI3~R8&(_
zQ&Lh=QBhG)P*6`#PfkuwO-)TqOiW8lOG-*gNl8gaNJvLVM@B|QMMXtKL_|YFLqbAA
zK|w)4KtMk~KR!M_Jv}`h+H$dDmJh78$1V#6KKsx&K%-}d((O0w!kUm_Wg>2sSq;woEQ%A~pyl~}Ybyi!mF
z)!0eqER*VkHDCdMPgZPeI+dYgpmfSYMIrW@NC8T^Dgw;B6j0Sl0&1vW$h;GH=21ME
zbP*`ZEYmLY*?ue@kGWHk03Fi|r<1F0+M|nsrgObqwjI`Wir^E{f|h33guL0+}o6%V2}}tG*^*D
zK6|l3EX&g1E~dx_pQ*E&n`xx$^e#g9zYTgHGHB_#?XW2_&@IB0a?Y`BC+8YyN=PZn
zS}$odur8<+rMvT6UF-=f=xSu*fh<2hJ
+//
+// New with version 1.01 - $autoScale = true; enables autoranging on output scale.  The program will
+// add majortick values to maximum or substract majortick values from minimum to always show the
+// scale, current, minimum, maximum on the graphic.
+//------------ settings ------------------
+$wxSoftware         = 'WD';                           // 'WD' for Weather-Display, 'VWS' for Virtual Weather Station,
+                                                      // 'CU' for Cumulus
+//
+$UOM = 'F';                                           // set to 'C' for Celsius/Centigrade, 'F'=Fahrenheit
+//
+$autoScale = true;                                    // set to false to disable autoscale.
+//
+// you only have to set one of these correctly based on the $useWD selection
+// $wxSoftware = 'WD' : set the $clientrawfile
+// $wxSoftware = 'VWS': set the $wflashDir
+// $wxSoftware = 'CU': set the $realtimefile
+//
+$clientrawfile = './clientraw.txt';                // relative file address for WD clientraw.txt
+$wflashDir     = './wflash/Data/';                 // directory for the the VWS wflash.txt and wflash2.txt files
+//                                                 // relative to directory location of this script (include
+//                                                 // trailing '/' in the specification
+$realtimefile  = './realtime.txt';                 // relative file location for Cumulus realtime.txt file
+//
+// settings for ranges -- adjust for your climate :-)
+// Fahrenheit settings
+$TmaxF = 105;     // maximum °F temperature on thermometer
+$TminF = 10;      // minimum °F temperature on thermometer
+$TincrF = 5;      // increment number of degrees °F for major/minor ticks on thermometer
+$TMajTickF = 10;  // major tick with value when °F scale number divisible by this
+// Centigrade settings
+$TmaxC = 40;      // maximum °C temperature on thermometer
+$TminC = -10;     // minimum °C temperature on thermometer
+$TincrC = 2;      // increment number of degrees °C for major/minor ticks on thermometer
+$TMajTickC = 10;  // major tick with value when °C scale number divisible by this
+//
+$invertColor = true; // set to true if thermometer display is over black background
+$BlankGraphic  = './thermometer-blank.png'; // relative file address for thermometer blank image PNG
+$BlankGraphicBlack = './thermometer-blank-black.png'; // for black background use
+//------------ end settings --------------
+// overrides from Settings.php if available
+if(file_exists("Settings.php")) { include_once("Settings.php"); }
+global $SITE;
+if (isset($SITE['uomTemp'])) 	{
+  $UOM = preg_replace('|°|is','',$SITE['uomTemp']);
+  if ($UOM <> 'F' and $UOM <> 'C') { $UOM = 'F'; }
+}
+if (isset($SITE['clientrawfile']) ) {$clientrawfile = $SITE['clientrawfile']; }
+if (isset($SITE['wflashdir']) ) {$wflashDir = $SITE['wflashdir']; }
+if (isset($SITE['realtimefile']) ) {$realtimefile = $SITE['realtimefile']; }
+$CSSstyle = '';
+# was there a style selected from the form input
+if (isset($_COOKIE['CSSstyle'])) {
+       $_SESSION['CSSstyle'] = $_COOKIE['CSSstyle'];
+       $CSSstyle = $_COOKIE['CSSstyle'];
+  } else if (isset($_SESSION['CSSstyle']) and $_SESSION['CSSstyle'] <> '' ) {
+       $CSSstyle = $_SESSION['CSSstyle'];
+  }
+if (preg_match('|black|i',$CSSstyle) ) {
+	$invertColor = true; 
+}
+// end of overrides from Settings.php
+
+// -------------------begin code ------------------------------------------
+if (isset($_REQUEST['sce']) && strtolower($_REQUEST['sce']) == 'view' ) {
+   //--self downloader --
+   $filenameReal = __FILE__;
+   $download_size = filesize($filenameReal);
+   header('Pragma: public');
+   header('Cache-Control: private');
+   header('Cache-Control: no-cache, must-revalidate');
+   header("Content-type: text/plain");
+   header("Accept-Ranges: bytes");
+   header("Content-Length: $download_size");
+   header('Connection: close');
+   
+   readfile($filenameReal);
+   exit;
+}
+
+if( ! function_exists("gd_info")){
+  die("Sorry.. this script requires the GD library in PHP to function.");
+}
+
+
+if (isset($_REQUEST['sw']) and strtolower($_REQUEST['sw']) == 'wd') { $wxSoftware = 'WD'; } // testing
+if (isset($_REQUEST['sw']) and strtolower($_REQUEST['sw']) == 'vws') { $wxSoftware = 'VWS'; } // testing
+if (isset($_REQUEST['sw']) and strtolower($_REQUEST['sw']) == 'cu') { $wxSoftware = 'CU'; } // testing
+
+if (isset($_REQUEST['uom']) and strtolower($_REQUEST['uom']) == 'c') { $UOM = 'C'; }
+if (isset($_REQUEST['uom']) and strtolower($_REQUEST['uom']) == 'f') { $UOM = 'F'; }
+if (isset($_REQUEST['dark'])) {$invertColor = strtolower($_REQUEST['dark'])=='y'; }
+
+if ($wxSoftware == 'WD') { // Get the Weather-Display clientraw.txt data file
+
+      //$dataraw = file_get_contents($clientrawfile);
+
+      // clean up any blank lines
+      
+      #$dataraw = trim($dataraw);
+      $dataraw = preg_replace("/[\r\n]+[\s\t]*[\r\n]+/","\n",$dataraw);
+      $data = explode(" ", $dataraw);
+	  
+	  //$curtemp = CtoF('50',1);
+	  //$mintemp = CtoF('20',1);
+	  //$maxtemp = CtoF('80',1);
+	  #$curtemp = '';
+	  $curtemp = $_GET['t'];
+	  $mintemp = $_GET['mint'];
+	  $maxtemp = $_GET['maxt'];
+	  
+  } // end Weather Display data
+  
+if ($wxSoftware == 'VWS') { // Get the VWS Weather Flash data files
+  
+      $filename = "${wflashDir}wflash.txt";
+      $file = file($filename);
+      $file = implode('',$file);
+      $data = explode(",",$file);;
+  
+	  $curtemp = FtoC($data[9],1);
+	  
+      $filename = "${wflashDir}wflash2.txt";
+      $file = file($filename);
+      $file = implode('',$file);
+      $data = explode(",",$file);;
+	  
+	  $mintemp = FtoC($data[92],1);
+	  $maxtemp = FtoC($data[36],1);
+   }
+
+if ($wxSoftware == 'CU') { // Get the Cumulus realtime.txt file
+  
+      $dataraw = file_get_contents($realtimefile);
+
+      // clean up any blank lines
+      $dataraw = trim($dataraw);
+      $dataraw = preg_replace("/[\r\n]+[\s\t]*[\r\n]+/","\n",$dataraw);
+      $data = explode(" ", $dataraw);
+	  $inUOM = $data[14];
+      if ($inUOM == 'F' and $UOM == 'C') {
+		$curtemp = FtoC($data[2],1);
+		$mintemp = FtoC($data[28],1);
+		$maxtemp = FtoC($data[26],1);
+	  } elseif ($inUOM == 'C' and $UOM == 'F') {
+		$curtemp = CtoF($data[2],1);
+		$mintemp = CtoF($data[28],1);
+		$maxtemp = CtoF($data[26],1);
+	  } else {
+		$curtemp = $data[2];
+		$mintemp = $data[28];
+		$maxtemp = $data[26];
+		$UOM = $inUOM;
+	  }
+   }
+
+if (isset($_REQUEST['current'])) { $curtemp = $_REQUEST['current']; } // for testing
+if (isset($_REQUEST['min'])) { $mintemp = $_REQUEST['min']; } // for testing
+if (isset($_REQUEST['max'])) { $maxtemp = $_REQUEST['max']; } // for testing
+
+
+if ($UOM == 'F') { // use Fahrenheit settings
+    $Tmax = $TmaxF;   // maximum temperature on thermometer
+    $Tmin = $TminF;    // minimum temperature on thermometer
+    $Tincr = $TincrF;    // increment number of degrees for major/minor ticks on thermometer
+    $TMajTick = $TMajTickF;// major tick with value when scale number divisible by this
+  } else { // use Centigrade settings
+    $Tmax = $TmaxC;    // maximum temperature on thermometer
+    $Tmin = $TminC;   // minimum temperature on thermometer
+    $Tincr = $TincrC;    // increment number of degrees for major/minor ticks on thermometer
+    $TMajTick = $TMajTickC;// major tick with value when scale number divisible by this
+}
+
+      if($autoScale) { autoscale($curtemp,$mintemp,$maxtemp); }
+	  
+      genThermometer($curtemp, $mintemp,$maxtemp); // make graphic!
+	  
+return;
+	  
+// ----------- functions ----------------------------------------------------------
+//
+function genThermometer( $current,$min,$max ) {
+
+   global $UOM,$BlankGraphic,$BlankGraphicBlack,$wxSoftware,$invertColor;
+   global  $Tmax,$Tmin,$Tincr,$TMajTick;
+
+// draw a filled thermometer with scale, min max on a blank thermometer image
+ $BGfile = $invertColor?$BlankGraphicBlack:$BlankGraphic;
+ $image = LoadPNG($BGfile);
+ 
+ // settings relative to the thermometer image file defines the drawing area
+ // for the thermometer filling
+ // these settings are SPECIFICALLY for the thermometer-blank.png image background
+ 
+ $minX = 20; // left
+ $maxX = 24; // right
+ $minY = 20; // top
+ $maxY = 140;// bottom
+ 
+
+ $width = imagesx($image);
+ $height = imagesy($image);
+ $font = 1;
+
+ $bg    = imagecolorallocate($image,255,255,255 );
+ $tx    = imagecolorallocate($image,0,0,0);
+ $blue  = imagecolorallocate($image,0,0,255);
+ $red   = imagecolorallocate($image,255,0,0);
+ if ($invertColor) {
+   $tx    = imagecolorallocate($image,255,255,255);
+   $blue  = imagecolorallocate($image,0,192,255);
+   $red   = imagecolorallocate($image,255,32,32);
+ }
+  
+ $Trange = $Tmax - $Tmin; // total temperature range
+ 
+ $Tpct = ($current-$Tmin)/($Trange); // percent for current temperature of range
+  
+ $Y = (1-$Tpct)*($maxY-$minY)+$minY; // upper location for fill
+  
+// fill the thermometer with a red bar from bottom to $Y 
+  imagefilledrectangle( $image,
+                 $minX,
+                 $Y,
+                 $maxX,
+                 $maxY,
+                 $red );
+				 
+// Draw tick marks and scale values on right
+			 
+ for ($T=$Tmin;$T<=$Tmax;$T+=$Tincr) {
+   
+     $Tpct = ($T-$Tmin)/($Trange);
+     $Y = (1-$Tpct)*($maxY-$minY)+$minY;
+	 
+	 if ($T == 0 or ($T % $TMajTick) == 0) { // Major Tick
+	 
+	    imagefilledrectangle( $image,
+            $maxX+7 ,
+            $Y ,
+            $maxX+12,
+            $Y +1, $tx );
+
+        imagestring($image, $font,
+            $maxX + 14,
+            $Y - (ImageFontHeight($font)/2),
+            sprintf( "%2d", $T),$tx);
+	 } else { // Minor tick
+     	imagefilledrectangle( $image,
+            $maxX+7,
+            $Y ,
+            $maxX+9,
+            $Y +1, $tx );
+	 }
+
+ 
+ } // end do ticks legend
+ 
+ if(isset($min)) { // put on minimum temp bar/value
+ 
+//     $Tpct = ($min-$Tmin)/($Trange);
+     $Tpct = ( ( (float)$min-$Tmin )/ $Trange );
+     $Y = (1-$Tpct)*($maxY-$minY)+$minY;
+	 imagefilledrectangle( $image,
+            $minX - 18,
+            $Y ,
+            $minX - 5,
+           $Y +1, $blue );
+      $tstr = sprintf('%2d',round($min,0));
+	  $tsize = strlen($tstr)*imagefontwidth($font+1);
+      imagestring($image, $font+1,
+            $minX - $tsize - 3 ,
+            $Y + 2 ,
+            $tstr,$blue);
+
+ }
+ 
+ if(isset($max)) { // put on maximum temp bar/value
+ 
+     $Tpct = ($max-$Tmin)/($Trange);
+     $Y = (1-$Tpct)*($maxY-$minY)+$minY;
+	 imagefilledrectangle( $image,
+            $minX - 18,
+            $Y ,
+            $minX - 5,
+            $Y +1, $red );
+ 
+      $tstr = sprintf('%2d',round($max,0));
+	  $tsize = strlen($tstr)*imagefontwidth($font+1);
+
+      imagestring($image, $font+1,
+            $minX - $tsize - 3 ,
+            $Y - imagefontheight($font+1),
+            $tstr,$red);
+ }
+
+ // put legend on top with UOM
+ 
+    $cnt = '°' . $UOM;
+    imagestring( $image, $font+2, ($width/2)-((strlen($cnt)/2)*ImageFontWidth($font+2)),
+       (10-(ImageFontHeight($font+2) / 2)),
+       $cnt, $tx);
+
+// write current temperature on thermometer bulb	
+//    $tstr = sprintf('%2d',round($current,0));
+//	$tsize = strlen($cnt)*imagefontwidth($font);
+
+//    imagestring($image, $font,
+//            ($minX+$maxX)/2 - $tsize/2 -2 ,
+//            $maxY+6,
+//            $tstr,$bg);
+
+	
+//imagestring( $image, $font, ($width/2)-((strlen($wxSoftware)/2)*imagefontwidth($font)),
+//   $height-imagefontheight($font),
+//	$wxSoftware,$tx);
+
+ // send the image
+ header("content-type: image/png");
+ imagepng($image);
+ imagedestroy($image);
+
+} // end genThermometer
+
+// load PNG image 
+function LoadPNG ($imgname) { 
+   $im = @imagecreatefrompng ($imgname); /* Attempt to open */ 
+   if (!$im) { /* See if it failed */ 
+       $im  = imagecreate (150, 30); /* Create a blank image */ 
+       $bgc = imagecolorallocate ($im, 255, 255, 255); 
+       $tc  = imagecolorallocate ($im, 0, 0, 0); 
+       imagefilledrectangle ($im, 0, 0, 150, 30, $bgc); 
+       /* Output an errmsg */ 
+       imagestring ($im, 1, 5, 5, "Error loading $imgname", $tc); 
+   } 
+   return $im; 
+} 
+
+// CtoF: converts degrees Celcius to degress Farenheight (from Anolecomputing.com)
+function CtoF($value, $precision) {
+  global $UOM;
+  if ($UOM <> 'F') { 
+    return round($value,$precision); 
+  } else { 
+    return round($value = (($value * 9 / 5) + 32),$precision); 
+  }
+} // end function C_to_F
+
+// FtoC: converts degress Farenheight to degrees Celcius  (from Anolecomputing.com)
+function FtoC($value, $precision) {
+  global $UOM;
+  if ($UOM == 'F') { 
+    return round($value,$precision); 
+  } else { 
+    return round(($value - 32) * (5/9),$precision); 
+  }
+} // end function F to C
+
+// autoscale function .. adjust scale to fit current conditions if need be.
+
+function autoscale($curtemp,$mintemp,$maxtemp) {
+
+   global  $Tmax,$Tmin,$Tincr,$TMajTick;
+   
+   $highest = max($curtemp,$Tmax,$maxtemp);
+   $lowest = min($curtemp,$Tmin,$mintemp);
+   
+   
+   while ($Tmax < $highest) {
+     $Tmax += $TMajTick;
+   }
+  
+   while ($Tmin > $lowest) {
+     $Tmin = $Tmin - $TMajTick;
+   }
+   
+   return;
+
+
+}
+?>
diff --git a/title_status.php b/title_status.php
new file mode 100644
index 0000000..83aef8a
--- /dev/null
+++ b/title_status.php
@@ -0,0 +1,22 @@
+Inside:";
+  $ch = curl_init();
+  curl_setopt($ch, CURLOPT_URL,"http://isy99/rest/nodes/2C%20B%202B%201");
+
+  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+  curl_setopt($ch, CURLOPT_USERPWD, 'admin:admin');
+
+  $output = curl_exec($ch);
+  $array=xml2array($output);
+  #echo "
";
+  #print_r($array);
+  #exit;
+  echo substr(($array['nodeInfo']['node']['property']['0_attr']['formatted']),0,-1)." F";
+?>
diff --git a/top.html b/top.html
new file mode 100644
index 0000000..f929fdc
--- /dev/null
+++ b/top.html
@@ -0,0 +1 @@
+
diff --git a/traffic-iframe.html b/traffic-iframe.html
new file mode 100644
index 0000000..4f7111f
--- /dev/null
+++ b/traffic-iframe.html
@@ -0,0 +1,46 @@
+
+
+  
+    
+    Google Maps JavaScript API Example: Traffic Overlays
+    
+    
+  
+
+  
+    
+
+
+ +
+ + + diff --git a/traffic.html b/traffic.html new file mode 100644 index 0000000..f499ec6 --- /dev/null +++ b/traffic.html @@ -0,0 +1 @@ +