diff --git a/sample_for_plotting/css/finance.css b/sample_for_plotting/css/finance.css new file mode 100644 index 0000000..60cc0eb --- /dev/null +++ b/sample_for_plotting/css/finance.css @@ -0,0 +1,105 @@ +.title { + text-align: center; +} +.subTitle { + font-size: 16px; +} + +#finance { + position: relative; + margin: 40px 0px; + border: 1px solid #99CCFF; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +#labels { + position: absolute; + width: 800px; + z-index: 10; +} +#financeTitle { + position: absolute; + top: -20px; +} +#time { + position: absolute; + left: 4px; + top: 4px; + font-size: 10px; + z-index: 10; +} +#time a { + background: #ffffff; + cursor: pointer; + border-right: 2px solid transparent; + color: #4499FF; + text-decoration: underline; +} +#dateRange { + position: absolute; + right: 4px; + top: -14px; + font-size: 10px; +} +.handle { + position: absolute; + z-index: 10; + cursor: pointer; + background: #eeeeee; + border: 1px solid #bbbbbb; + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; +} +.zoomHandle { + width: 5px; + height: 20px; +} +.scrollHandle { + width: 100px; + height: 12px; +} +.flag { + border: 1px solid #4499FF; + background: white; + padding: 1px 2px 1px 2px; +} +.flagpole { + border-left: 1px solid #4499FF; +} +.flotr-grid-label { + font-size: 11px; + background: #ffffff; + margin: 2px 0px 0px 4px; +} +.flotr-mouse-value { + font-size: 10px; +} +#summaryGraph .flotr-grid-label { + margin-top: -16px; + background: transparent; + text-align: left; +} +.documentation p { + font-size: 14px; + padding-left: 20px; + padding-right: 8px; +} +.documentation ol { + font-size: 14px; +} +.documentation h3 { + padding-top: 12px; +} +.documentation h4 { + padding-left: 20px; + font-size: 14px; +} +.documentation p code { + font-size: 12px; +} +.documentation .snippet { + margin-left: 20px; +} diff --git a/sample_for_plotting/css/hsd.css b/sample_for_plotting/css/hsd.css new file mode 100644 index 0000000..d4c2312 --- /dev/null +++ b/sample_for_plotting/css/hsd.css @@ -0,0 +1 @@ +@CHARSET "UTF-8";body,html{height:100%}body{background:#fff;color:#333;font-family:'Lucida Grande','Lucida Sans Unicode',Helvetica,Arial,Verdana,sans-serif;padding:0;margin:0}a{border:none;color:#333}a:hover{color:#000}a:focus{outline:none}ul{margin:0;padding:0}li{list-style:none}h2{font-size:1.2em}h3{font-size:1em}table{border-spacing:0}fieldset{padding:0;margin:0;border:none}#header-container,#links-container,#content-container,#footer-container{width:800px;margin:0 auto}#header{font-size:32px;text-shadow:2px 2px 0 #e0e0e0;border-bottom:2px solid #333;padding:16px 4px 0 4px}#links{font-size:14px;text-align:right;font-weight:bold}#links a{text-decoration:none}#links li{display:inline-block;padding:4px 9px 5px 9px;margin:0 4px;*display:inline}#links li.current-page{background:#3a3a3a;border-bottom-left-radius:2px;border-bottom-right-radius:2px}#links li.current-page span{color:#f5f5f5}#content{margin:0 0 22px 0;margin-top:24px}#footer-container{border-top:2px solid #333;z-index:100;clear:both;bottom:0;left:0}#footer{padding:6px 8px;font-size:.8em;text-align:center}#footer a{text-decoration:none}#footer .footer-text{float:left}#footer .footer-links{float:right}#footer .footer-links li{display:inline-block;padding-left:10px}.home p.summary{text-indent:2em;font-size:17px}.home .project{width:360px;float:right;margin:0 6px 28px 20px;position:relative;overflow:hidden}.home .project .title{position:absolute;left:0;top:0}.home .project .icon{margin-left:8px;float:right}.home .project .icon img{border:1px solid #ddd}.home .project .description{display:block;margin-top:32px;font-size:14px}.home .footer{clear:both}.home .projects-list{overflow:hidden;background-position:center 0}.projects .project{overflow:hidden;margin:0 0 40px 16px}.projects .project .title{font-size:18px;font-weight:bold}.projects .project .description{display:block;border-left:2px solid #444;padding-left:16px;margin-left:2px;margin-top:12px}.projects .icon img{border:1px solid #ddd}.projects .icon{float:right;width:200px;text-align:center}a.project-flotr-demo-link{border:0;text-decoration:none}.project.feature{width:auto;float:none;margin-bottom:32px}.project.feature .title{position:static;font-weight:bold}.project.feature .title span{font-weight:normal;float:right}.project.feature .description{margin-top:8px}#envision-demo{height:379px}#envision-demo .envision-finance{margin:14px auto 0 auto}.project.wide .description{border:none;padding-left:0}.project.wide li{margin-left:40px;list-style:circle}.project.wide .features{float:left}.project-flotr-demo{cursor:pointer!important}.projects .project.wide{position:relative;height:400px}.projects .project-flotr-demo{width:480px;height:320px;position:absolute;right:0;margin:20px 24px 0 0}.projects .project-flotr-demo>div{position:absolute!important;width:480px;height:320px}.home .project-flotr-demo{width:328px;height:224px;position:absolute;left:50%;margin:14px 0 2px -164px}.home .project-flotr-demo>div{position:absolute!important;width:328px;height:224px}.home .project-flotr-demo-link{display:block;margin:14px 0;height:224px}.home .project.wide{padding-bottom:12px;float:left;overflow:visible}.home .project.wide li{font-size:14px}.project.wide .flotr-mouse-value{font-size:14px}form{margin-left:16px}.contact h3.feedback{margin-top:36px}.contact .label,label{float:left;display:block;margin-top:2px;width:90px;float:left}input{margin-bottom:8px;width:240px}textarea{width:600px;height:320px}#submit{border:1px solid #333;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;background:#fff;font-size:18px;width:auto;margin:6px 0 0 90px;padding:6px 9px 4px 9px}span.label{margin-left:16px}.errors{color:#e00}#recaptcha_widget_div{margin-left:90px}#recaptcha_widget_div .recaptchatable{border:1px solid #000!important}.listing .toggle{font-weight:normal;font-size:12px;color:#777;float:right;cursor:pointer}.listing .file{font-family:monospace;font-size:1.2em}.snippet{padding:0 0 3px 6px;padding-left:20px;margin-left:16px;background:url(../home/cesutherland/HSD/images/leftshadow.gif) repeat-y}.snippet code{white-space:pre;text-align:left}.summary{padding:16px 24px;margin:20px 60px;border:1px solid #acf;border-radius:24px;-moz-border-radius:24px;-webkit-border-radius:24px;text-align:justify}@media screen and (max-width:1000px){#github-ribbon{display:none}}@media screen and (max-width:800px){input{width:auto}textarea{width:100%}#header-container,#links-container,#content-container,#footer-container{width:auto}#header{text-align:center;padding:0 4px}#links{text-align:center;font-size:10px}#links li{margin:0;padding:4px 5px 5px 5px}#content{padding:4px;margin:0}#footer .footer-text,#footer .footer-links{float:center}#footer .footer-links li{padding:0 5px}.summary{margin:12px 4px 4px;padding:10px;border-radius:24px;-moz-border-radius:12px;-webkit-border-radius:12px}#envision-demo{padding:0 30px;height:auto;margin-bottom:20px}.home .project{float:none;margin:10px 0 20px 0;width:auto}.project.feature .title{text-align:center}.project.feature .title span{display:block;float:none}.home .project.wide{float:none}.project.wide .features{margin-top:24px;float:none}.home .project.wide .description{margin-top:8px}.home p.summary{font-size:14px}.home .project-flotr-demo{width:100%;height:224px;left:0;margin:14px 0 2px 0;padding:0 20px}.home .project-flotr-demo>div{width:80%;height:224px}.home .project.wide .title{position:static}.projects .project{margin:10px 0 20px 0}#flotr-demo{padding:0 40px}.projects .project-flotr-demo{left:0;width:100%;height:224px;margin:16px 0 0 0;padding:0 20px}.projects .project-flotr-demo>div{height:224px}.projects .project.wide{height:auto}.projects .project-flotr-demo-link{display:block;height:240px}}.btn.danger,.alert-message.danger,.btn.danger:hover,.alert-message.danger:hover,.btn.error,.alert-message.error,.btn.error:hover,.alert-message.error:hover,.btn.success,.alert-message.success,.btn.success:hover,.alert-message.success:hover,.btn.info,.alert-message.info,.btn.info:hover,.alert-message.info:hover{color:#fff}.btn .close,.alert-message .close{font-family:Arial,sans-serif;line-height:18px}.btn.danger,.alert-message.danger,.btn.error,.alert-message.error{background-color:#c43c35;background-repeat:repeat-x;background-image:-khtml-gradient(linear,left top,left bottom,from(#ee5f5b),to(#c43c35));background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-ms-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ee5f5b),color-stop(100%,#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(top,#ee5f5b,#c43c35);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35',GradientType=0);text-shadow:0 -1px 0 rgba(0,0,0,0.25);border-color:#c43c35 #c43c35 #882a25;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.btn.success,.alert-message.success{background-color:#57a957;background-repeat:repeat-x;background-image:-khtml-gradient(linear,left top,left bottom,from(#62c462),to(#57a957));background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-ms-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#62c462),color-stop(100%,#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(top,#62c462,#57a957);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462',endColorstr='#57a957',GradientType=0);text-shadow:0 -1px 0 rgba(0,0,0,0.25);border-color:#57a957 #57a957 #3d773d;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.btn.info,.alert-message.info{background-color:#339bb9;background-repeat:repeat-x;background-image:-khtml-gradient(linear,left top,left bottom,from(#5bc0de),to(#339bb9));background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-ms-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#5bc0de),color-stop(100%,#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(top,#5bc0de,#339bb9);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de',endColorstr='#339bb9',GradientType=0);text-shadow:0 -1px 0 rgba(0,0,0,0.25);border-color:#339bb9 #339bb9 #22697d;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.btn{cursor:pointer;display:inline-block;background-color:#e6e6e6;background-repeat:no-repeat;background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),color-stop(25%,#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(#fff,#fff 25%,#e6e6e6);background-image:-moz-linear-gradient(top,#fff,#fff 25%,#e6e6e6);background-image:-ms-linear-gradient(#fff,#fff 25%,#e6e6e6);background-image:-o-linear-gradient(#fff,#fff 25%,#e6e6e6);background-image:linear-gradient(#fff,#fff 25%,#e6e6e6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#e6e6e6',GradientType=0);padding:5px 14px 6px;text-shadow:0 1px 1px rgba(255,255,255,0.75);color:#333;font-size:13px;line-height:normal;border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-webkit-transition:.1s linear all;-moz-transition:.1s linear all;-ms-transition:.1s linear all;-o-transition:.1s linear all;transition:.1s linear all}.btn:hover{background-position:0 -15px;color:#333;text-decoration:none}.btn:focus{outline:1px dotted #666}.btn.primary{color:#fff;background-color:#0064cd;background-repeat:repeat-x;background-image:-khtml-gradient(linear,left top,left bottom,from(#049cdb),to(#0064cd));background-image:-moz-linear-gradient(top,#049cdb,#0064cd);background-image:-ms-linear-gradient(top,#049cdb,#0064cd);background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#049cdb),color-stop(100%,#0064cd));background-image:-webkit-linear-gradient(top,#049cdb,#0064cd);background-image:-o-linear-gradient(top,#049cdb,#0064cd);background-image:linear-gradient(top,#049cdb,#0064cd);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb',endColorstr='#0064cd',GradientType=0);text-shadow:0 -1px 0 rgba(0,0,0,0.25);border-color:#0064cd #0064cd #003f81;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.btn.active,.btn:active{-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.25),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.25),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-khtml-opacity:.65;-moz-opacity:.65;opacity:.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn[disabled]{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-khtml-opacity:.65;-moz-opacity:.65;opacity:.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn.large{font-size:15px;line-height:normal;padding:9px 14px 9px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn.small{padding:7px 9px 7px;font-size:11px}:root .alert-message,:root .btn{border-radius:0 \0}button.btn::-moz-focus-inner,input[type=submit].btn::-moz-focus-inner{padding:0;border:0}.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file diff --git a/sample_for_plotting/index.html b/sample_for_plotting/index.html new file mode 100644 index 0000000..f875a15 --- /dev/null +++ b/sample_for_plotting/index.html @@ -0,0 +1,50 @@ + + + +HTML5互动股票图形数据 - 站长素材 + + + + + + + + +
+
+
+
+
+ NASDAQ:GOOG
+
+ 1w + 1m + 3m + 6m + 1y + 5y
+
+
+
+
+
+
+ + + + + + + + + + + + +
+

适用浏览器:IE8、360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗.

+

来源:站长素材

+
+ + + diff --git a/sample_for_plotting/js/Finance.js b/sample_for_plotting/js/Finance.js new file mode 100644 index 0000000..121a1a9 --- /dev/null +++ b/sample_for_plotting/js/Finance.js @@ -0,0 +1,25 @@ +/* +(function () { + +var HSD = { + +*/ + function toggleSnippet(button, snippet) { + + + if (Element.visible(snippet)) { + Element.update(button, '(show)'); + } else { + Element.update(button, '(hide)'); + } + + Element.toggle(snippet); + } +prettyPrint(); +/* +} + +window.HSD = HSD; + +})(); +*/ diff --git a/sample_for_plotting/js/HumbleFinance.js b/sample_for_plotting/js/HumbleFinance.js new file mode 100644 index 0000000..b2c5872 --- /dev/null +++ b/sample_for_plotting/js/HumbleFinance.js @@ -0,0 +1,701 @@ +//////////////////////////////////////////////////////////////////// +// Copyright (c) 2010 Humble Software Development +// +// 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. +//////////////////////////////////////////////////////////////////// + +/** + * HumbleFinance Flotr Financial Charts + * + * @license MIT License + * @author Carl Sutherland + * @version 1.1.0 + */ +var HumbleFinance = { + + /** + * ID of element to attach chart + * + * @member String + */ + id: null, + /** + * Graphs used to display data + * + * @member Object + */ + graphs: {price: null, volume: null, summary: null}, + /** + * Div containers for graphs + * + * @member Object + */ + containers: {price: null, volume: null, summary: null, flags: null}, + /** + * Div handles for interaction with graphs + * + * @member Object + */ + handles: {left: null, right: null, scroll: null}, + /** + * Bounds on data + * + * @member Object + */ + bounds: {xmin: null, xmax: null, ymin: null, ymax: null}, + /** + * Array of data displayed in first graph. + * + * @member Array + */ + priceData: [], + /** + * Array of data displayed in second graph + * + * @member Array + */ + volumeData: [], + /** + * Array of data to serve as a visual summary of the above graphs + * + * @member Array + */ + summaryData: [], + /** + * An array of data to be used to display flags. + * + * @member Array + */ + flagData: [], + /** + * Formatter for x axis ticks + * + * @member function + */ + xTickFormatter: Flotr.defaultTickFormatter, + /** + * Formatter for y axis ticks + * + * @member function + */ + yTickFormatter: Flotr.defaultTickFormatter, + /** + * Formatter for mouse tracking + * + * @member function + */ + trackFormatter: Flotr.defaultTrackFormatter, + + + /** + * Initialization function + * + * @param String id + * @param Array priceData + * @param Array volumeData + * @param Array summaryData + */ + init: function(id, priceData, volumeData, summaryData) { + + // Set members + this.id = id; + this.priceData = priceData; + this.volumeData = volumeData; + this.summaryData = summaryData; + + // Set bounds to scale automatically in the y direction + this.bounds.xmin = 0; + this.bounds.xmax = this.priceData.length - 1; + this.bounds.ymin = null; + this.bounds.ymax = null; + + // Set up DOM + this.buildDOM(); + this.attachEventObservers(); + + // Initialize graphs, setting selection on summary + var area = { + x1: this.bounds.xmin, + y1: this.bounds.ymin, + x2: Math.min(this.bounds.xmax, 100), + y2: this.bounds.ymax + }; + this.graphs.summary = this.summaryGraph(this.summaryData, this.bounds); + this.graphs.summary.setSelection(area); + }, + + /** + * Build DOM elements and insert into container. + */ + buildDOM: function () { + + var container = $(this.id); + + // Build DOM element + this.containers.price = new Element('div', {id: 'priceGraph', style: 'width: 100%; height: 240px;'}); + this.containers.volume = new Element('div', {id: 'volumeGraph', style: 'width: 100%; height: 80px;'}); + this.containers.summary = new Element('div', {id: 'summaryGraph', style: 'width: 100%; height: 60px;'}); + this.containers.flags = new Element('div', {id: 'flagContainer'/*, style: 'width: 0px; height: 0px;'*/}); + this.handles.left = new Element('div', {id: 'leftHandle', 'class': 'handle zoomHandle', style: 'display: none;'}); + this.handles.right = new Element('div', {id: 'rightHandle', 'class': 'handle zoomHandle', style: 'display: none;'}); + this.handles.scroll = new Element('div', {id: 'scrollHandle', 'class': 'handle scrollHandle', style: 'display: none;'}); + + this.handles.left.onselectstart = function () { return false; }; + this.handles.right.onselectstart = function () { return false; }; + this.handles.scroll.onselectstart = function () { return false; }; + + // Insert into container + container.insert(this.containers.price); + container.insert(this.containers.volume); + container.insert(this.containers.summary); + container.insert(this.containers.flags); + container.insert(this.handles.left); + container.insert(this.handles.right); + container.insert(this.handles.scroll); + }, + + /** + * Attach event observers + */ + attachEventObservers: function() { + + // Attach summary click event to clear selection + Event.observe(this.containers.summary, 'flotr:click', this.reset.bind(this)); + + // Attach observers for hit tracking on price and volume points + Event.observe(this.containers.volume, 'flotr:hit', this.volumeHitObserver.bind(this)); + Event.observe(this.containers.volume, 'flotr:clearhit', this.clearHit.bind(this)); + Event.observe(this.containers.price, 'flotr:hit', this.priceHitObserver.bind(this)); + Event.observe(this.containers.price, 'flotr:clearhit', this.clearHit.bind(this)); + + // Handle observers + Event.observe(this.containers.summary, 'flotr:select', this.positionScrollHandle.bind(this)); + Event.observe(this.containers.summary, 'flotr:select', this.positionZoomHandles.bind(this)); + Event.observe(this.handles.left, 'mousedown', this.zoomObserver.bind(this)); + Event.observe(this.handles.right, 'mousedown', this.zoomObserver.bind(this)); + Event.observe(this.handles.scroll, 'mousedown', this.scrollObserver.bind(this)); + + // On manual selection, hide zoom and scroll handles + Event.observe(this.containers.summary, 'mousedown', this.hideSelection.bind(this)); + + // Attach summary selection event to redraw price and volume charts + Event.observe(this.containers.summary, 'flotr:select', this.selectObserver.bind(this)); + }, + + /** + * Summary Graph Selection Observer + * + * @param e MouseEvent + */ + selectObserver: function (e) { + + var area = e.memo[0]; + xmin = Math.floor(area.x1); + xmax = Math.ceil(area.x2); + + var newBounds = {'xmin': xmin, 'xmax': xmax, 'ymin': null, 'ymax': null}; + + this.graphs.price = this.priceGraph(this.priceData.slice(xmin, xmax+1), newBounds); + this.graphs.volume = this.volumeGraph(this.volumeData.slice(xmin, xmax+1), newBounds); + + this.drawFlags(); + }, + + /** + * Reset to null selection + */ + reset: function () { + this.graphs.price = this.priceGraph(this.priceData, this.bounds); + this.graphs.volume = this.volumeGraph(this.volumeData, this.bounds); + this.handles.left.hide(); + this.handles.right.hide(); + this.handles.scroll.hide(); + + this.drawFlags(); + }, + + /** + * Hide selection and handles + */ + hideSelection: function () { + + // Hide handles + this.handles.left.hide(); + this.handles.right.hide(); + this.handles.scroll.hide(); + + // Clear selection + this.graphs.summary.clearSelection(); + }, + + /** + * Set the position of the scroll handle + * + * @param e MouseEvent + */ + positionScrollHandle: function (e) { + + var x1 = e.memo[0].x1; + var x2 = e.memo[0].x2; + var xaxis = e.memo[1].axes.x; + var plotOffset = e.memo[1].plotOffset; + var graphOffset = this.containers.summary.positionedOffset(); + var graphHeight = this.containers.summary.getHeight(); + var height = this.handles.scroll.getHeight(); + + // Set width + var width = Math.floor(xaxis.d2p(x2) - xaxis.d2p(x1)) + 8; + width = (width < 10) ? 18 : width; + + // Set positions + var xPosLeft = Math.floor(graphOffset[0] + plotOffset.left + xaxis.d2p(x1) + (xaxis.d2p(x2) - xaxis.d2p(x1) - width)/2); + var yPos = Math.ceil(graphOffset[1] + graphHeight - 2); + + this.handles.scroll.setStyle({position: 'absolute', left: xPosLeft+'px', top: yPos+'px', width: width+'px'}); + this.handles.scroll.show(); + }, + + /** + * Begin scrolling observer + * + * @param e MouseEvent + */ + scrollObserver: function (e) { + + var x = e.clientX; + var offset = this.handles.scroll.cumulativeOffset(); + var prevSelection = this.graphs.summary.prevSelection; + + /** + * Perform scroll on handle move, observer + * + * @param e MouseEvent + */ + var handleObserver = function (e) { + + Event.stopObserving(document, 'mousemove', handleObserver); + + var deltaX = e.clientX - x; + var xAxis = this.graphs.summary.axes.x; + + var x1 = xAxis.p2d(Math.min(prevSelection.first.x, prevSelection.second.x) + deltaX); + var x2 = xAxis.p2d(Math.max(prevSelection.first.x, prevSelection.second.x) + deltaX); + + // Check and handle boundary conditions + if (x1 < this.bounds.xmin) { + x2 = this.bounds.xmin + (x2 - x1); + x1 = this.bounds.xmin; + } + if (x2 > this.bounds.xmax) { + x1 = this.bounds.xmax - (x2 - x1); + x2 = this.bounds.xmax; + } + + // Set selection area object + var area = { + x1: x1, + y1: prevSelection.first.y, + x2: x2, + y2: prevSelection.second.y + }; + + // If selection varies from previous, set new selection + if (area.x1 != prevSelection.first.x) { + this.graphs.summary.setSelection(area); + } + + Event.observe(document, 'mousemove', handleObserver); + }.bind(this); + + /** + * End scroll observer to detach event listeners + * + * @param e MouseEvent + */ + function handleEndObserver (e) { + Event.stopObserving(document, 'mousemove', handleObserver); + Event.stopObserving(document, 'mouseup', handleEndObserver); + }; + + // Attach scroll handle observers + Event.observe(document, 'mousemove', handleObserver); + Event.observe(document, 'mouseup', handleEndObserver); + }, + + /** + * Begin zooming observer + * + * @param e MouseEvent + */ + zoomObserver: function (e) { + + var zoomHandle = e.element(); + var x = e.clientX; + var offset = zoomHandle.cumulativeOffset(); + var prevSelection = this.graphs.summary.prevSelection; + + /** + * Perform zoom on handle move, observer + * + * @param e MouseEvent + */ + var handleObserver = function (e) { + + Event.stopObserving(document, 'mousemove', handleObserver); + + var deltaX = e.clientX - x; + var xAxis = this.graphs.summary.axes.x; + + // Set initial new x bounds + var x1, x2; + if (Element.identify(zoomHandle) == 'rightHandle') { + x1 = xAxis.p2d(Math.min(prevSelection.first.x, prevSelection.second.x)); + x2 = xAxis.p2d(Math.max(prevSelection.first.x, prevSelection.second.x) + deltaX); + } else if (Element.identify(zoomHandle) == 'leftHandle') { + x1 = xAxis.p2d(Math.min(prevSelection.first.x, prevSelection.second.x) + deltaX); + x2 = xAxis.p2d(Math.max(prevSelection.first.x, prevSelection.second.x)); + } + + // Check and handle boundary conditions + if (x1 < this.bounds.xmin) { + x1 = this.bounds.xmin; + } + if (x2 > this.bounds.xmax) { + x2 = this.bounds.xmax; + } + if (x1 > this.bounds.xmax) { + x1 = this.bounds.xmax; + } + if (x2 < this.bounds.xmin) { + x2 = this.bounds.xmin; + } + + // Set selection area object + var area = { + x1: x1, + y1: prevSelection.first.y, + x2: x2, + y2: prevSelection.second.y + }; + + // If selection varies from previous, set new selection + if (area.x1 != prevSelection.first.x || area.x2 != prevSelection.second.x) { + this.graphs.summary.setSelection(area); + } + + Event.observe(document, 'mousemove', handleObserver); + }.bind(this); + + /** + * End zoom observer to detach event listeners + * + * @param e MouseEvent + */ + function handleEndObserver (e) { + Event.stopObserving(document, 'mousemove', handleObserver); + Event.stopObserving(document, 'mouseup', handleEndObserver); + }; + + // Attach handler slide event listeners + Event.observe(document, 'mousemove', handleObserver); + Event.observe(document, 'mouseup', handleEndObserver); + }, + + /** + * Perform a manual zoom. + * + * Zoom backwards from the right zoom handle. If no selection or handles + * are present, zoom backwards from the right hand side. + * + * @param integer x + */ + zoom: function (x) { + + var prevSelection = this.graphs.summary.prevSelection; + var xAxis = this.graphs.summary.axes.x; + var x1, x2, y1, y2; + + // Check for previous selection + if (!prevSelection) { + x1 = Math.max(this.bounds.xmax - Number(x), this.bounds.xmin); + x2 = this.bounds.xmax; + y1 = 0; + y2 = 0; + } else { + x2 = xAxis.p2d(Math.max(prevSelection.first.x, prevSelection.second.x)); + x1 = Math.max(x2 - Number(x), this.bounds.xmin); + y1 = prevSelection.first.y; + y2 = prevSelection.second.y; + } + + var area = { + x1: x1, + y1: y1, + x2: x2, + y2: y2 + }; + + this.graphs.summary.setSelection(area); + }, + + /** + * Set the position of the zoom handles + * + * @param e MouseEvent + */ + positionZoomHandles: function (e) { + + var x1 = e.memo[0].x1; + var x2 = e.memo[0].x2; + var xaxis = e.memo[1].axes.x; + var plotOffset = e.memo[1].plotOffset; + var height = this.containers.summary.getHeight(); + var offset = this.containers.summary.positionedOffset(); + this.handles.left.show(); + var dimensions = this.handles.left.getDimensions(); + + // Set positions + var xPosOne = Math.floor(offset[0]+plotOffset.left+xaxis.d2p(x1)-dimensions.width/2+1); + var xPosTwo = Math.ceil(offset[0]+plotOffset.left+xaxis.d2p(x2)-dimensions.width/2); + var xPosLeft = Math.min(xPosOne, xPosTwo); + var xPosRight = Math.max(xPosOne, xPosTwo); + var yPos = Math.floor(offset[1]+height/2 - dimensions.height/2); + + this.handles.left.setStyle({position: 'absolute', left: xPosLeft+'px', top: yPos+'px'}); + this.handles.right.setStyle({position: 'absolute', left: xPosRight+'px', top: yPos+'px'}); + this.handles.left.show(); + this.handles.right.show(); + }, + + /** + * Clear point hits for price and volume graphs. + * + * @param e MouseEvent + */ + clearHit: function(e) { + this.graphs.price.clearHit();//.mouseTrack.hide(); + this.graphs.volume.clearHit(); + }, + + /** + * Observer for volume hit to set price hit + * + * @param e MouseEvent + */ + volumeHitObserver: function (e) { + + // Hide mouse track on volume graph + this.graphs.volume.mouseTrack.hide(); + + // Display hit on price graph + var point = this.priceData[e.memo[0].x]; + Event.stopObserving(this.containers.volume, 'flotr:hit'); + this.doHit(this.graphs.price, point, this.containers.volume); + Event.observe(this.containers.volume, 'flotr:hit', this.volumeHitObserver.bind(this)); + }, + + /** + * Observer for price hit to set volume hit + * + * @param e MouseEvent + */ + priceHitObserver: function (e) { + + // Display hit on volume graph + var point = this.volumeData[e.memo[0].x]; + Event.stopObserving(this.containers.price, 'flotr:hit'); + this.doHit(this.graphs.volume, point, this.containers.price); + Event.observe(this.containers.price, 'flotr:hit', this.priceHitObserver.bind(this)); + + // Hide mouse track on volume graph + this.graphs.volume.mouseTrack.hide(); + }, + + /** + * Calculate hit location from one graph and perform hit on another + * + * @param Flotr.Graph graph Destination graph. + * @param Array point The coordinates of the hit as [x, y]. + * @param Element container The container of the source graph. + */ + doHit: function (graph, point, container) { + + var offset = container.cumulativeOffset(); + + var xaxis = graph.axes.x; + var yaxis = graph.axes.y; + + var relX = xaxis.d2p(point[0]); + var relY = yaxis.d2p(point[1]); + + var absX = offset[0]+relX; + var absY = offset[1]+relY; + + var mouse = {'relX': relX, 'relY': relY, 'absX': absX, 'absY': absY}; + + graph.hit(mouse); + }, + + /** + * Add flags to the graph. + * + * @param Array An array of flags. + */ + setFlags: function (flags) { + this.flagData = flags; + this.drawFlags(); + }, + + /** + * Draw flags on top of the graph. + */ + drawFlags: function () { + + var xAxis = this.graphs.price.axes.x; + var yAxis = this.graphs.price.axes.y; + var min = xAxis.datamin; + var max = xAxis.datamax; + + this.containers.flags.update(''); + + for (var i = 0; i < this.flagData.length; i++) { + + var x = this.flagData[i][0]; + + if (x < min) { + continue; + } else if (x >= min && x <= xmax) { + // Draw the flag + var point = this.priceData[x]; + var flagContent = this.flagData[i][1]; + var xPos = xAxis.d2p(point[0]); + var yPos = yAxis.d2p(point[1]); + var offset = this.containers.price.cumulativeOffset(); + + var left = Math.floor(xPos + this.graphs.price.plotOffset.left); + var top = Math.floor(yPos - 40 + this.graphs.price.plotOffset.top); + + flag = new Element('div', {'class': 'flag', 'style': 'position: absolute; top: '+top+'px; left: '+left+'px; z-index: 10;'}); + flag.update(flagContent); + flagpole = new Element('div', {'class': 'flagpole', 'style': 'position: absolute; top: '+top+'px; left: '+left+'px; z-index: 10; height: 40px;'}); + this.containers.flags.insert(flag); + this.containers.flags.insert(flagpole); + + } else if (x >= xmax) { + break; + } + } + }, + + /** + * Draw the price graph + * + * @param Array data + * @param Array bounds + * @return Flotr.Graph + */ + priceGraph: function (data, bounds) { + + var xmin = bounds.xmin; + var xmax = bounds.xmax; + var ymin = bounds.ymin; + var ymax = bounds.ymax; + + var p = Flotr.draw( + $('priceGraph'), + [data], + { + lines: {show: true, fill: true, fillOpacity: .1, lineWidth: 1}, + yaxis: {min: ymin, max: ymax, tickFormatter: this.yTickFormatter, noTicks: 3, autoscaleMargin: .5, tickDecimals: 0}, + xaxis: {min: xmin, max: xmax, showLabels: false}, + grid: {outlineWidth: 0, labelMargin: 0}, + mouse: {track: true, sensibility: 1, trackDecimals: 4, trackFormatter: this.trackFormatter, position: 'ne'}, + shadowSize: false, + HtmlText: true + } + ); + + return p; + }, + + /** + * Draw the volume graph + * + * @param Array data + * @param Array bounds + * @return Flotr.Graph + */ + volumeGraph: function (data, bounds) { + + var xmin = bounds.xmin; + var xmax = bounds.xmax; + var ymin = bounds.ymin; + var ymax = bounds.ymax; + + var v = Flotr.draw( + $('volumeGraph'), + [data], + { + bars: {show: true, 'barWidth': .5, 'fill': true, 'lineWidth': 2, 'fillOpacity': 1}, + yaxis: {min: ymin, max: ymax, autoscaleMargin: .5, showLabels: false, tickDecimals: 0}, + xaxis: {min: xmin, max: xmax, showLabels: false, labelsAngle: 60}, + grid: {verticalLines: false, horizontalLines: false, outlineWidth: 0, labelMargin: 0}, + mouse: {track: true, sensibility: .3, position: 'ne', trackDecimals: 0}, + shadowSize: false, + HtmlText: true + } + ); + + return v; + }, + + /** + * Draw the summary graph + * + * @param Array data + * @param Array bounds + * @return Flotr.Graph + */ + summaryGraph: function (data, bounds) { + + var xmin = bounds.xmin; + var xmax = bounds.xmax; + var ymin = bounds.ymin; + var ymax = bounds.ymax; + + var p = Flotr.draw( + $('summaryGraph'), + [data], + { + lines: {show: true, fill: true, fillOpacity: .1, lineWidth: 1}, + yaxis: {min: ymin, max: ymax, autoscaleMargin: .5, showLabels: false, tickDecimals: 1}, + xaxis: {min: xmin, max: xmax, noTicks: 5, tickFormatter: this.xTickFormatter, labelsAngle: 60}, + grid: {verticalLines: false, horizontalLines: false, labelMargin: 0, outlineWidth: 0}, + selection: {mode: 'x'}, + shadowSize: false, + HtmlText: true + } + ); + + return p; + } +} \ No newline at end of file diff --git a/sample_for_plotting/js/base64.js b/sample_for_plotting/js/base64.js new file mode 100644 index 0000000..3306e49 --- /dev/null +++ b/sample_for_plotting/js/base64.js @@ -0,0 +1,113 @@ +/* Copyright (C) 1999 Masanao Izumo + * Version: 1.0 + * LastModified: Dec 25 1999 + * This library is free. You can redistribute it and/or modify it. + */ + +/* + * Interfaces: + * b64 = base64encode(data); + * data = base64decode(b64); + */ + +(function() { + +var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +var base64DecodeChars = [ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1]; + +function base64encode(str) { + var out, i, len; + var c1, c2, c3; + + len = str.length; + i = 0; + out = ""; + while(i < len) { + c1 = str.charCodeAt(i++) & 0xff; + if(i == len) + { + out += base64EncodeChars.charAt(c1 >> 2); + out += base64EncodeChars.charAt((c1 & 0x3) << 4); + out += "=="; + break; + } + c2 = str.charCodeAt(i++); + if(i == len) + { + out += base64EncodeChars.charAt(c1 >> 2); + out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); + out += base64EncodeChars.charAt((c2 & 0xF) << 2); + out += "="; + break; + } + c3 = str.charCodeAt(i++); + out += base64EncodeChars.charAt(c1 >> 2); + out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); + out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)); + out += base64EncodeChars.charAt(c3 & 0x3F); + } + return out; +} + +function base64decode(str) { + var c1, c2, c3, c4; + var i, len, out; + + len = str.length; + i = 0; + out = ""; + while(i < len) { + /* c1 */ + do { + c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; + } while(i < len && c1 == -1); + if(c1 == -1) + break; + + /* c2 */ + do { + c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; + } while(i < len && c2 == -1); + if(c2 == -1) + break; + + out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); + + /* c3 */ + do { + c3 = str.charCodeAt(i++) & 0xff; + if(c3 == 61) + return out; + c3 = base64DecodeChars[c3]; + } while(i < len && c3 == -1); + if(c3 == -1) + break; + + out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); + + /* c4 */ + do { + c4 = str.charCodeAt(i++) & 0xff; + if(c4 == 61) + return out; + c4 = base64DecodeChars[c4]; + } while(i < len && c4 == -1); + if(c4 == -1) + break; + out += String.fromCharCode(((c3 & 0x03) << 6) | c4); + } + return out; +} + +if (!window.btoa) window.btoa = base64encode; +if (!window.atob) window.atob = base64decode; + +})(); \ No newline at end of file diff --git a/sample_for_plotting/js/canvas2image.js b/sample_for_plotting/js/canvas2image.js new file mode 100644 index 0000000..148b430 --- /dev/null +++ b/sample_for_plotting/js/canvas2image.js @@ -0,0 +1,230 @@ +/* + * Canvas2Image v0.1 + * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com + * MIT License [http://www.opensource.org/licenses/mit-license.php] + */ + +var Canvas2Image = (function() { + // check if we have canvas support + var oCanvas = document.createElement("canvas"); + + // no canvas, bail out. + if (!oCanvas.getContext) { + return { + saveAsBMP : function(){}, + saveAsPNG : function(){}, + saveAsJPEG : function(){} + } + } + + var bHasImageData = !!(oCanvas.getContext("2d").getImageData); + var bHasDataURL = !!(oCanvas.toDataURL); + var bHasBase64 = !!(window.btoa); + + var strDownloadMime = "image/octet-stream"; + + // ok, we're good + var readCanvasData = function(oCanvas) { + var iWidth = parseInt(oCanvas.width); + var iHeight = parseInt(oCanvas.height); + return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight); + } + + // base64 encodes either a string or an array of charcodes + var encodeData = function(data) { + var strData = ""; + if (typeof data == "string") { + strData = data; + } else { + var aData = data; + for (var i = 0; i < aData.length; i++) { + strData += String.fromCharCode(aData[i]); + } + } + return btoa(strData); + } + + // creates a base64 encoded string containing BMP data + // takes an imagedata object as argument + var createBMP = function(oData) { + var aHeader = []; + + var iWidth = oData.width; + var iHeight = oData.height; + + aHeader.push(0x42); // magic 1 + aHeader.push(0x4D); + + var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes + aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); + aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); + aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); + aHeader.push(iFileSize % 256); + + aHeader.push(0); // reserved + aHeader.push(0); + aHeader.push(0); // reserved + aHeader.push(0); + + aHeader.push(54); // data offset + aHeader.push(0); + aHeader.push(0); + aHeader.push(0); + + var aInfoHeader = []; + aInfoHeader.push(40); // info header size + aInfoHeader.push(0); + aInfoHeader.push(0); + aInfoHeader.push(0); + + var iImageWidth = iWidth; + aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); + aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); + aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); + aInfoHeader.push(iImageWidth % 256); + + var iImageHeight = iHeight; + aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); + aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); + aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); + aInfoHeader.push(iImageHeight % 256); + + aInfoHeader.push(1); // num of planes + aInfoHeader.push(0); + + aInfoHeader.push(24); // num of bits per pixel + aInfoHeader.push(0); + + aInfoHeader.push(0); // compression = none + aInfoHeader.push(0); + aInfoHeader.push(0); + aInfoHeader.push(0); + + var iDataSize = iWidth*iHeight*3; + aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); + aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); + aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); + aInfoHeader.push(iDataSize % 256); + + for (var i = 0; i < 16; i++) { + aInfoHeader.push(0); // these bytes not used + } + + var iPadding = (4 - ((iWidth * 3) % 4)) % 4; + + var aImgData = oData.data; + + var strPixelData = ""; + var y = iHeight; + do { + var iOffsetY = iWidth*(y-1)*4; + var strPixelRow = ""; + for (var x=0;x object containing the imagedata + var makeImageObject = function(strSource) { + var oImgElement = document.createElement("img"); + oImgElement.src = strSource; + return oImgElement; + } + + var scaleCanvas = function(oCanvas, iWidth, iHeight) { + if (iWidth && iHeight) { + var oSaveCanvas = document.createElement("canvas"); + + oSaveCanvas.width = iWidth; + oSaveCanvas.height = iHeight; + oSaveCanvas.style.width = iWidth+"px"; + oSaveCanvas.style.height = iHeight+"px"; + + var oSaveCtx = oSaveCanvas.getContext("2d"); + + oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iWidth); + + return oSaveCanvas; + } + return oCanvas; + } + + return { + saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) { + if (!bHasDataURL) { + return false; + } + var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight); + var strData = oScaledCanvas.toDataURL("image/png"); + if (bReturnImg) { + return makeImageObject(strData); + } else { + saveFile(strData.replace("image/png", strDownloadMime)); + } + return true; + }, + + saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) { + if (!bHasDataURL) { + return false; + } + + var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight); + var strMime = "image/jpeg"; + var strData = oScaledCanvas.toDataURL(strMime); + + // check if browser actually supports jpeg by looking for the mime type in the data uri. + // if not, return false + if (strData.indexOf(strMime) != 5) { + return false; + } + + if (bReturnImg) { + return makeImageObject(strData); + } else { + saveFile(strData.replace(strMime, strDownloadMime)); + } + return true; + }, + + saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) { + if (!(bHasImageData && bHasBase64)) { + return false; + } + + var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight); + + var oData = readCanvasData(oScaledCanvas); + var strImgData = createBMP(oData); + if (bReturnImg) { + return makeImageObject(makeDataURI(strImgData, "image/bmp")); + } else { + saveFile(makeDataURI(strImgData, strDownloadMime)); + } + return true; + } + }; + +})(); \ No newline at end of file diff --git a/sample_for_plotting/js/canvastext.js b/sample_for_plotting/js/canvastext.js new file mode 100644 index 0000000..e29768d --- /dev/null +++ b/sample_for_plotting/js/canvastext.js @@ -0,0 +1,449 @@ +/** + * This code is released to the public domain by Jim Studt, 2007. + * He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/ + * It as been modified by Fabien Mnager to handle font style like size, weight, color and rotation. + * A partial support for special characters has been added too. + */ +var CanvasText = { + /** The letters definition. It is a list of letters, + * with their width, and the coordinates of points compositing them. + * The syntax for the points is : [x, y], null value means "pen up" + */ + letters: { + '\n':{ width: -1, points: [] }, + ' ': { width: 10, points: [] }, + '!': { width: 10, points: [[5,21],[5,7],null,[5,2],[4,1],[5,0],[6,1],[5,2]] }, + '"': { width: 16, points: [[4,21],[4,14],null,[12,21],[12,14]] }, + '#': { width: 21, points: [[11,25],[4,-7],null,[17,25],[10,-7],null,[4,12],[18,12],null,[3,6],[17,6]] }, + '$': { width: 20, points: [[8,25],[8,-4],null,[12,25],[12,-4],null,[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] }, + '%': { width: 24, points: [[21,21],[3,0],null,[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],null,[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]] }, + '&': { width: 26, points: [[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]] }, + '\'':{ width: 10, points: [[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]] }, + '(': { width: 14, points: [[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]] }, + ')': { width: 14, points: [[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]] }, + '*': { width: 16, points: [[8,21],[8,9],null,[3,18],[13,12],null,[13,18],[3,12]] }, + '+': { width: 26, points: [[13,18],[13,0],null,[4,9],[22,9]] }, + ',': { width: 10, points: [[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] }, + '-': { width: 26, points: [[4,9],[22,9]] }, + '.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] }, + '/': { width: 22, points: [[20,25],[2,-7]] }, + '0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] }, + '1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] }, + '2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] }, + '3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] }, + '4': { width: 20, points: [[13,21],[3,7],[18,7],null,[13,21],[13,0]] }, + '5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] }, + '6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] }, + '7': { width: 20, points: [[17,21],[7,0],null,[3,21],[17,21]] }, + '8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] }, + '9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] }, + ':': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],null,[5,2],[4,1],[5,0],[6,1],[5,2]] }, + ';': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],null,[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] }, + '<': { width: 24, points: [[20,18],[4,9],[20,0]] }, + '=': { width: 26, points: [[4,12],[22,12],null,[4,6],[22,6]] }, + '>': { width: 24, points: [[4,18],[20,9],[4,0]] }, + '?': { width: 18, points: [[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],null,[9,2],[8,1],[9,0],[10,1],[9,2]] }, + '@': { width: 27, points: [[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],null,[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],null,[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],null,[19,16],[18,8],[18,6],[19,5]] }, + 'A': { width: 18, points: [[9,21],[1,0],null,[9,21],[17,0],null,[4,7],[14,7]] }, + 'B': { width: 21, points: [[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],null,[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]] }, + 'C': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]] }, + 'D': { width: 21, points: [[4,21],[4,0],null,[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]] }, + 'E': { width: 19, points: [[4,21],[4,0],null,[4,21],[17,21],null,[4,11],[12,11],null,[4,0],[17,0]] }, + 'F': { width: 18, points: [[4,21],[4,0],null,[4,21],[17,21],null,[4,11],[12,11]] }, + 'G': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],null,[13,8],[18,8]] }, + 'H': { width: 22, points: [[4,21],[4,0],null,[18,21],[18,0],null,[4,11],[18,11]] }, + 'I': { width: 8, points: [[4,21],[4,0]] }, + 'J': { width: 16, points: [[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]] }, + 'K': { width: 21, points: [[4,21],[4,0],null,[18,21],[4,7],null,[9,12],[18,0]] }, + 'L': { width: 17, points: [[4,21],[4,0],null,[4,0],[16,0]] }, + 'M': { width: 24, points: [[4,21],[4,0],null,[4,21],[12,0],null,[20,21],[12,0],null,[20,21],[20,0]] }, + 'N': { width: 22, points: [[4,21],[4,0],null,[4,21],[18,0],null,[18,21],[18,0]] }, + 'O': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]] }, + 'P': { width: 21, points: [[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]] }, + 'Q': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],null,[12,4],[18,-2]] }, + 'R': { width: 21, points: [[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],null,[11,11],[18,0]] }, + 'S': { width: 20, points: [[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] }, + 'T': { width: 16, points: [[8,21],[8,0],null,[1,21],[15,21]] }, + 'U': { width: 22, points: [[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]] }, + 'V': { width: 18, points: [[1,21],[9,0],null,[17,21],[9,0]] }, + 'W': { width: 24, points: [[2,21],[7,0],null,[12,21],[7,0],null,[12,21],[17,0],null,[22,21],[17,0]] }, + 'X': { width: 20, points: [[3,21],[17,0],null,[17,21],[3,0]] }, + 'Y': { width: 18, points: [[1,21],[9,11],[9,0],null,[17,21],[9,11]] }, + 'Z': { width: 20, points: [[17,21],[3,0],null,[3,21],[17,21],null,[3,0],[17,0]] }, + '[': { width: 14, points: [[4,25],[4,-7],null,[5,25],[5,-7],null,[4,25],[11,25],null,[4,-7],[11,-7]] }, + '\\':{ width: 14, points: [[0,21],[14,-3]] }, + ']': { width: 14, points: [[9,25],[9,-7],null,[10,25],[10,-7],null,[3,25],[10,25],null,[3,-7],[10,-7]] }, + '^': { width: 14, points: [[3,10],[8,18],[13,10]] }, + '_': { width: 16, points: [[0,-2],[16,-2]] }, + '`': { width: 10, points: [[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]] }, + 'a': { width: 19, points: [[15,14],[15,0],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'b': { width: 19, points: [[4,21],[4,0],null,[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] }, + 'c': { width: 18, points: [[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'd': { width: 19, points: [[15,21],[15,0],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'e': { width: 18, points: [[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'f': { width: 12, points: [[10,21],[8,21],[6,20],[5,17],[5,0],null,[2,14],[9,14]] }, + 'g': { width: 19, points: [[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'h': { width: 19, points: [[4,21],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] }, + 'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],null,[4,14],[4,0]] }, + 'j': { width: 10, points: [[5,21],[6,20],[7,21],[6,22],[5,21],null,[6,14],[6,-3],[5,-6],[3,-7],[1,-7]] }, + 'k': { width: 17, points: [[4,21],[4,0],null,[14,14],[4,4],null,[8,8],[15,0]] }, + 'l': { width: 8, points: [[4,21],[4,0]] }, + 'm': { width: 30, points: [[4,14],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],null,[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]] }, + 'n': { width: 19, points: [[4,14],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] }, + 'o': { width: 19, points: [[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]] }, + 'p': { width: 19, points: [[4,14],[4,-7],null,[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] }, + 'q': { width: 19, points: [[15,14],[15,-7],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'r': { width: 13, points: [[4,14],[4,0],null,[4,8],[5,11],[7,13],[9,14],[12,14]] }, + 's': { width: 17, points: [[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]] }, + 't': { width: 12, points: [[5,21],[5,4],[6,1],[8,0],[10,0],null,[2,14],[9,14]] }, + 'u': { width: 19, points: [[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],null,[15,14],[15,0]] }, + 'v': { width: 16, points: [[2,14],[8,0],null,[14,14],[8,0]] }, + 'w': { width: 22, points: [[3,14],[7,0],null,[11,14],[7,0],null,[11,14],[15,0],null,[19,14],[15,0]] }, + 'x': { width: 17, points: [[3,14],[14,0],null,[14,14],[3,0]] }, + 'y': { width: 16, points: [[2,14],[8,0],null,[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]] }, + 'z': { width: 17, points: [[14,14],[3,0],null,[3,14],[14,14],null,[3,0],[14,0]] }, + '{': { width: 14, points: [[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],null,[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],null,[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]] }, + '|': { width: 8, points: [[4,25],[4,-7]] }, + '}': { width: 14, points: [[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],null,[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],null,[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]] }, + '~': { width: 24, points: [[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],null,[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]] }, + + // Lower case Latin-1 + '': { diacritic: '`', letter: 'a' }, + '': { diacritic: '', letter: 'a' }, + '': { diacritic: '^', letter: 'a' }, + '': { diacritic: '', letter: 'a' }, + + '': { diacritic: '`', letter: 'e' }, + '': { diacritic: '', letter: 'e' }, + '': { diacritic: '^', letter: 'e' }, + '': { diacritic: '', letter: 'e' }, + + '': { diacritic: '`', letter: 'i' }, + '': { diacritic: '', letter: 'i' }, + '': { diacritic: '^', letter: 'i' }, + '': { diacritic: '', letter: 'i' }, + + '': { diacritic: '`', letter: 'o' }, + '': { diacritic: '', letter: 'o' }, + '': { diacritic: '^', letter: 'o' }, + '': { diacritic: '', letter: 'o' }, + '': { diacritic: '~', letter: 'o' }, + + '': { diacritic: '`', letter: 'u' }, + '': { diacritic: '', letter: 'u' }, + '': { diacritic: '^', letter: 'u' }, + '': { diacritic: '', letter: 'u' }, + + '': { diacritic: '', letter: 'y' }, + '': { diacritic: '', letter: 'y' }, + + '': { diacritic: '', letter: 'c' }, + '': { diacritic: '~', letter: 'n' }, + + // Upper case Latin-1 + '': { diacritic: '`', letter: 'A' }, + '': { diacritic: '', letter: 'A' }, + '': { diacritic: '^', letter: 'A' }, + '': { diacritic: '', letter: 'A' }, + + '': { diacritic: '`', letter: 'E' }, + '': { diacritic: '', letter: 'E' }, + '': { diacritic: '^', letter: 'E' }, + '': { diacritic: '', letter: 'E' }, + + '': { diacritic: '`', letter: 'I' }, + '': { diacritic: '', letter: 'I' }, + '': { diacritic: '^', letter: 'I' }, + '': { diacritic: '', letter: 'I' }, + + '': { diacritic: '`', letter: 'O' }, + '': { diacritic: '', letter: 'O' }, + '': { diacritic: '^', letter: 'O' }, + '': { diacritic: '', letter: 'O' }, + '': { diacritic: '~', letter: 'O' }, + + '': { diacritic: '`', letter: 'U' }, + '': { diacritic: '', letter: 'U' }, + '': { diacritic: '^', letter: 'U' }, + '': { diacritic: '', letter: 'U' }, + + '': { diacritic: '', letter: 'Y' }, + + '': { diacritic: '', letter: 'C' }, + '': { diacritic: '~', letter: 'N' } + }, + + specialchars: { + 'pi': { width: 19, points: [[6,14],[6,0],null,[14,14],[14,0],null,[2,13],[6,16],[13,13],[17,16]] } + }, + + /** Diacritics, used to draw accentuated letters */ + diacritics: { + '': { entity: 'cedil', points: [[6,-4],[4,-6],[2,-7],[1,-7]] }, + '': { entity: 'acute', points: [[8,19],[13,22]] }, + '`': { entity: 'grave', points: [[7,22],[12,19]] }, + '^': { entity: 'circ', points: [[5.5,19],[9.5,23],[12.5,19]] }, + '': { entity: 'trema', points: [[5,21],[6,20],[7,21],[6,22],[5,21],null,[12,21],[13,20],[14,21],[13,22],[12,21]] }, + '~': { entity: 'tilde', points: [[4,18],[7,22],[10,18],[13,22]] } + }, + + /** The default font styling */ + style: { + size: 8, // font height in pixels + font: null, // not yet implemented + color: '#000000', // font color + weight: 1, // float, 1 for 'normal' + halign: 'l', // l: left, r: right, c: center + valign: 'b', // t: top, m: middle, b: bottom + adjustAlign: false, // modifies the alignments if the angle is different from 0 to make the spin point always at the good position + angle: 0, // in radians, anticlockwise + tracking: 1, // space between the letters, float, 1 for 'normal' + boundingBoxColor: '#ff0000', // color of the bounding box (null to hide), can be used for debug and font drawing + originPointColor: '#000000' // color of the bounding box (null to hide), can be used for debug and font drawing + }, + + debug: false, + _bufferLexemes: {}, + + /** Get the letter data corresponding to a char + * @param {String} ch - The char + */ + letter: function(ch) { + return CanvasText.letters[ch]; + }, + + parseLexemes: function(str) { + if (CanvasText._bufferLexemes[str]) + return CanvasText._bufferLexemes[str]; + + var i, c, matches = str.match(/&[A-Za-z]{2,5};|\s|./g); + var result = [], chars = []; + for (i = 0; i < matches.length; i++) { + c = matches[i]; + if (c.length == 1) + chars.push(c); + else { + var entity = c.substring(1, c.length-1); + if (CanvasText.specialchars[entity]) + chars.push(entity); + else + chars = chars.concat(c.toArray()); + } + } + for (i = 0; i < chars.length; i++) { + c = chars[i]; + if (c = CanvasText.letters[c] || CanvasText.specialchars[c]) result.push(c); + } + for(i = 0; i < result.length; i++) { + if (result === null || typeof result === 'undefined') + delete result[i]; + } + return CanvasText._bufferLexemes[str] = result; + }, + + /** Get the font ascent for a given style + * @param {Object} style - The reference style + */ + ascent: function(style) { + style = style || CanvasText.style; + return (style.size || CanvasText.style.size); + }, + + /** Get the font descent for a given style + * @param {Object} style - The reference style + * */ + descent: function(style) { + style = style || CanvasText.style; + return 7.0*(style.size || CanvasText.style.size)/25.0; + }, + + /** Measure the text horizontal size + * @param {String} str - The text + * @param {Object} style - Text style + * */ + measure: function(str, style) { + if (!str) return; + style = style || CanvasText.style; + + var i, width, lexemes = CanvasText.parseLexemes(str), + total = 0; + + for (i = lexemes.length-1; i > -1; --i) { + c = lexemes[i]; + width = (c.diacritic) ? CanvasText.letter(c.letter).width : c.width; + total += width * (style.tracking || CanvasText.style.tracking) * (style.size || CanvasText.style.size) / 25.0; + } + return total; + }, + + getDimensions: function(str, style) { + style = style || CanvasText.style; + var width = CanvasText.measure(str, style), + height = style.size || CanvasText.style.size, + angle = style.angle || CanvasText.style.angle; + + if (style.angle == 0) return {width: width, height: height}; + return { + width: Math.abs(Math.cos(angle) * width) + Math.abs(Math.sin(angle) * height), + height: Math.abs(Math.sin(angle) * width) + Math.abs(Math.cos(angle) * height) + } + }, + + getBestAlign: function(angle, style) { + style = style || CanvasText.style; + angle += CanvasText.getAngleFromAlign(style.halign, style.valign); + var a = {h:'c', v:'m'}; + if (Math.round(Math.cos(angle)*1000)/1000 != 0) + a.h = (Math.cos(angle) > 0 ? 'r' : 'l'); + + if (Math.round(Math.sin(angle)*1000)/1000 != 0) + a.v = (Math.sin(angle) > 0 ? 't' : 'b'); + return a; + }, + + getAngleFromAlign: function(halign, valign) { + var pi = Math.PI, table = { + 'rm': 0, + 'rt': pi/4, + 'ct': pi/2, + 'lt': 3*(pi/4), + 'lm': pi, + 'lb': -3*(pi/4), + 'cb': -pi/2, + 'rb': -pi/4, + 'cm': 0 + } + return table[halign+valign]; + }, + + /** Draws serie of points at given coordinates + * @param {Canvas context} ctx - The canvas context + * @param {Array} points - The points to draw + * @param {Number} x - The X coordinate + * @param {Number} y - The Y coordinate + * @param {Number} mag - The scale + */ + drawPoints: function (ctx, points, x, y, mag, offset) { + var i, a, penUp = true, needStroke = 0; + offset = offset || {x:0, y:0}; + + ctx.beginPath(); + for (i = 0; i < points.length; i++) { + a = points[i]; + if (!a) { + penUp = true; + continue; + } + if (penUp) { + ctx.moveTo(x + a[0]*mag + offset.x, y - a[1]*mag + offset.y); + penUp = false; + } + else { + ctx.lineTo(x + a[0]*mag + offset.x, y - a[1]*mag + offset.y); + } + } + ctx.stroke(); + ctx.closePath(); + }, + + /** Draws a text at given coordinates and with a given style + * @param {String} str - The text to draw + * @param {Number} xOrig - The X coordinate + * @param {Number} yOrig - The Y coordinate + * @param {Object} style - The font style + */ + draw: function(str, xOrig, yOrig, style) { + if (!str) return; + style = style || CanvasText.style; + style.halign = style.halign || CanvasText.style.halign; + style.valign = style.valign || CanvasText.style.valign; + style.angle = style.angle || CanvasText.style.angle; + style.size = style.size || CanvasText.style.size; + style.adjustAlign = style.adjustAlign || CanvasText.style.adjustAlign; + + var i, c, total = 0, + mag = style.size / 25.0, + x = 0, y = 0, + lexemes = CanvasText.parseLexemes(str), + offset = {x:0, y:0}, + measure = CanvasText.measure(str, style), + align; + + if (style.adjustAlign) { + align = CanvasText.getBestAlign(style.angle, style); + style.halign = align.h; + style.valign = align.v; + } + + switch (style.halign) { + case 'l': break; + case 'c': offset.x = -measure / 2; break; + case 'r': offset.x = -measure; break; + } + + switch (style.valign) { + case 'b': break; + case 'm': offset.y = style.size / 2; break; + case 't': offset.y = style.size; break; + } + + this.save(); + this.translate(xOrig, yOrig); + this.rotate(style.angle); + this.lineCap = "round"; + this.lineWidth = 2.0 * mag * (style.weight || CanvasText.style.weight); + this.strokeStyle = style.color || CanvasText.style.color; + + for (i = 0; i < lexemes.length; i++) { + c = lexemes[i]; + if (c.width == -1) { + x = 0; + y = style.size * 1.4; + continue; + } + + var points = c.points, + width = c.width; + + if (c.diacritic) { + var dia = CanvasText.diacritics[c.diacritic], + character = CanvasText.letter(c.letter); + + CanvasText.drawPoints(this, dia.points, x, y - (c.letter.toUpperCase() == c.letter ? 3 : 0), mag, offset); + points = character.points; + width = character.width; + } + + CanvasText.drawPoints(this, points, x, y, mag, offset); + + if (CanvasText.debug) { + this.save(); + this.lineJoin = "miter"; + this.lineWidth = 0.5; + this.strokeStyle = (style.boundingBoxColor || CanvasText.style.boundingBoxColor); + this.strokeRect(x+offset.x, y+offset.y, width*mag, -style.size); + + this.fillStyle = (style.originPointColor || CanvasText.style.originPointColor); + this.beginPath(); + this.arc(0, 0, 1.5, 0, Math.PI*2, true); + this.fill(); + this.closePath(); + this.restore(); + } + + x += width*mag*(style.tracking || CanvasText.style.tracking); + } + this.restore(); + return total; + } +}; + +/** The text functions are bound to the CanvasRenderingContext2D prototype */ +CanvasText.proto = window.CanvasRenderingContext2D ? window.CanvasRenderingContext2D.prototype : document.createElement('canvas').getContext('2d').__proto__; +if (CanvasText.proto) { + CanvasText.proto.drawText = CanvasText.draw; + CanvasText.proto.measureText = CanvasText.measure; + CanvasText.proto.getTextBounds = CanvasText.getDimensions; + CanvasText.proto.fontAscent = CanvasText.ascent; + CanvasText.proto.fontDescent = CanvasText.descent; +} \ No newline at end of file diff --git a/sample_for_plotting/js/data.js b/sample_for_plotting/js/data.js new file mode 100644 index 0000000..41fbe13 --- /dev/null +++ b/sample_for_plotting/js/data.js @@ -0,0 +1,5 @@ +var jsonData = [{date:'August 19, 2004',open:100.01,high:104.06,low:95.96,close:100.34,volume:22088000},{date:'August 20, 2004',open:101.48,high:109.08,low:100.50,close:108.31,volume:11377000},{date:'August 23, 2004',open:110.76,high:113.48,low:109.05,close:109.40,volume:9090700},{date:'August 24, 2004',open:111.24,high:111.60,low:103.57,close:104.87,volume:7599100},{date:'August 25, 2004',open:104.96,high:108.00,low:103.88,close:106.00,volume:4565900},{date:'August 26, 2004',open:104.95,high:107.95,low:104.66,close:107.91,volume:3527900},{date:'August 27, 2004',open:108.10,high:108.62,low:105.69,close:106.15,volume:3102400},{date:'August 30, 2004',open:105.49,high:105.49,low:102.01,close:102.01,volume:2585600},{date:'August 31, 2004',open:102.32,high:103.71,low:102.16,close:102.37,volume:2455900},{date:'September 1, 2004',open:102.70,high:102.97,low:99.67,close:100.25,volume:4525000},{date:'September 2, 2004',open:99.09,high:102.37,low:98.94,close:101.51,volume:7477500},{date:'September 3, 2004',open:100.95,high:101.74,low:99.32,close:100.01,volume:2572600},{date:'September 7, 2004',open:100.76,high:102.00,low:99.61,close:101.58,volume:2948400},{date:'September 8, 2004',open:100.74,high:103.03,low:100.50,close:102.30,volume:2493900},{date:'September 9, 2004',open:102.44,high:102.71,low:101.00,close:102.31,volume:2061500},{date:'September 10, 2004',open:101.60,high:106.56,low:101.30,close:105.33,volume:4736800},{date:'September 13, 2004',open:106.63,high:108.41,low:106.46,close:107.50,volume:3915300},{date:'September 14, 2004',open:107.44,high:112.00,low:106.79,close:111.49,volume:5402900},{date:'September 15, 2004',open:110.56,high:114.23,low:110.20,close:112.00,volume:5288000},{date:'September 16, 2004',open:112.34,high:115.80,low:111.65,close:113.97,volume:4619500},{date:'September 17, 2004',open:114.42,high:117.49,low:113.55,close:117.49,volume:4535800},{date:'September 20, 2004',open:116.95,high:121.60,low:116.77,close:119.36,volume:5310000},{date:'September 21, 2004',open:120.20,high:120.42,low:117.51,close:117.84,volume:3610000},{date:'September 22, 2004',open:117.45,high:119.67,low:116.81,close:118.38,volume:3781000},{date:'September 23, 2004',open:118.84,high:122.63,low:117.02,close:120.82,volume:4254000},{date:'September 24, 2004',open:120.97,high:124.10,low:119.76,close:119.83,volume:4494400},{date:'September 27, 2004',open:119.56,high:120.88,low:117.80,close:118.26,volume:3523200},{date:'September 28, 2004',open:121.15,high:127.40,low:120.21,close:126.86,volume:8421200},{date:'September 29, 2004',open:126.53,high:135.02,low:126.23,close:131.08,volume:15175600},{date:'September 30, 2004',open:129.90,high:132.30,low:129.00,close:129.60,volume:6696200},{date:'October 1, 2004',open:130.80,high:134.24,low:128.90,close:132.58,volume:7515600},{date:'October 4, 2004',open:135.82,high:136.87,low:134.03,close:135.06,volume:6488900},{date:'October 5, 2004',open:134.66,high:138.53,low:132.24,close:138.37,volume:7359700},{date:'October 6, 2004',open:137.67,high:138.45,low:136.00,close:137.08,volume:6648600},{date:'October 7, 2004',open:136.56,high:139.88,low:136.55,close:138.85,volume:7036400},{date:'October 8, 2004',open:138.73,high:139.68,low:137.02,close:137.73,volume:5509700},{date:'October 11, 2004',open:137.01,high:138.86,low:133.85,close:135.26,volume:5210700},{date:'October 12, 2004',open:134.49,high:137.61,low:133.40,close:137.40,volume:5488100},{date:'October 13, 2004',open:143.32,high:143.55,low:140.08,close:140.90,volume:9846300},{date:'October 14, 2004',open:141.02,high:142.38,low:138.56,close:142.00,volume:5200700},{date:'October 15, 2004',open:144.95,high:145.50,low:141.95,close:144.11,volume:6477600},{date:'October 18, 2004',open:143.20,high:149.20,low:141.21,close:149.16,volume:6888900},{date:'October 19, 2004',open:150.50,high:152.40,low:147.35,close:147.94,volume:9029600},{date:'October 20, 2004',open:147.94,high:148.99,low:139.60,close:140.49,volume:11201800},{date:'October 21, 2004',open:144.13,high:150.13,low:141.62,close:149.38,volume:11329000},{date:'October 22, 2004',open:170.44,high:180.17,low:164.08,close:172.43,volume:36716300},{date:'October 25, 2004',open:175.89,high:194.43,low:172.55,close:187.40,volume:32608400},{date:'October 26, 2004',open:186.45,high:192.64,low:180.00,close:181.80,volume:22195200},{date:'October 27, 2004',open:182.29,high:189.52,low:181.77,close:185.97,volume:13199900},{date:'October 28, 2004',open:186.50,high:194.39,low:185.60,close:193.30,volume:14593000},{date:'October 29, 2004',open:198.87,high:199.95,low:190.60,close:190.64,volume:20986500},{date:'November 1, 2004',open:193.50,high:197.67,low:191.27,close:196.03,volume:12136100},{date:'November 2, 2004',open:198.73,high:199.25,low:193.34,close:194.87,volume:11281900},{date:'November 3, 2004',open:198.19,high:201.60,low:190.75,close:191.67,volume:13775600},{date:'November 4, 2004',open:188.25,high:190.40,low:183.35,close:184.70,volume:14031000},{date:'November 5, 2004',open:182.00,high:182.30,low:168.55,close:169.35,volume:19671800},{date:'November 8, 2004',open:170.93,high:175.44,low:169.40,close:172.55,volume:11116600},{date:'November 9, 2004',open:174.10,high:175.20,low:165.27,close:168.70,volume:10916400},{date:'November 10, 2004',open:170.67,high:172.52,low:166.33,close:167.86,volume:10507800},{date:'November 11, 2004',open:169.53,high:183.75,low:167.57,close:183.02,volume:14850400},{date:'November 12, 2004',open:185.23,high:189.80,low:177.40,close:182.00,volume:16677500},{date:'November 15, 2004',open:180.45,high:188.32,low:178.75,close:184.87,volume:11831700},{date:'November 16, 2004',open:177.50,high:179.47,low:170.83,close:172.54,volume:20774500},{date:'November 17, 2004',open:169.02,high:177.50,low:169.00,close:172.50,volume:17958800},{date:'November 18, 2004',open:170.40,high:174.42,low:165.73,close:167.54,volume:16150000},{date:'November 19, 2004',open:169.06,high:169.98,low:166.52,close:169.40,volume:8637600},{date:'November 22, 2004',open:168.64,high:169.50,low:161.31,close:165.10,volume:12216300},{date:'November 23, 2004',open:167.92,high:170.83,low:166.50,close:167.52,volume:10591100},{date:'November 24, 2004',open:174.84,high:177.21,low:172.51,close:174.76,volume:15167800},{date:'November 26, 2004',open:175.80,high:180.03,low:175.32,close:179.39,volume:6423400},{date:'November 29, 2004',open:180.26,high:182.95,low:177.51,close:181.05,volume:10562200},{date:'November 30, 2004',open:180.70,high:183.00,low:180.25,close:181.98,volume:7553600},{date:'December 1, 2004',open:181.77,high:182.50,low:179.55,close:179.96,volume:7801200},{date:'December 2, 2004',open:179.90,high:181.51,low:178.55,close:179.40,volume:6118100},{date:'December 3, 2004',open:179.78,high:181.06,low:177.60,close:180.40,volume:5807500},{date:'December 6, 2004',open:179.13,high:180.70,low:176.02,close:176.29,volume:6208700},{date:'December 7, 2004',open:176.00,high:176.20,low:170.55,close:171.43,volume:6838800},{date:'December 8, 2004',open:170.57,high:173.68,low:168.73,close:169.98,volume:7313000},{date:'December 9, 2004',open:170.25,high:173.50,low:168.47,close:173.43,volume:7587500},{date:'December 10, 2004',open:173.43,high:174.88,low:171.29,close:171.65,volume:4221600},{date:'December 13, 2004',open:172.03,high:173.18,low:169.45,close:170.45,volume:4758500},{date:'December 14, 2004',open:171.00,high:178.82,low:169.60,close:178.69,volume:10951700},{date:'December 15, 2004',open:177.99,high:180.69,low:176.66,close:179.78,volume:11302700},{date:'December 16, 2004',open:177.22,high:180.49,low:175.95,close:176.47,volume:8450200},{date:'December 17, 2004',open:176.76,high:180.50,low:176.55,close:180.08,volume:7117900},{date:'December 20, 2004',open:182.00,high:188.46,low:181.87,close:185.02,volume:9689600},{date:'December 21, 2004',open:186.28,high:187.88,low:183.40,close:183.75,volume:5471400},{date:'December 22, 2004',open:183.90,high:186.85,low:183.01,close:186.30,volume:3855300},{date:'December 23, 2004',open:187.45,high:188.60,low:186.00,close:187.90,volume:3590000},{date:'December 27, 2004',open:189.15,high:193.30,low:189.10,close:191.91,volume:6079400},{date:'December 28, 2004',open:192.11,high:193.55,low:191.01,close:192.76,volume:4126200},{date:'December 29, 2004',open:191.97,high:193.52,low:191.78,close:192.90,volume:2640200},{date:'December 30, 2004',open:192.97,high:198.23,low:191.85,close:197.60,volume:5832200},{date:'December 31, 2004',open:199.23,high:199.88,low:192.56,close:192.79,volume:7590200},{date:'January 3, 2005',open:197.40,high:203.64,low:195.46,close:202.71,volume:15649600},{date:'January 4, 2005',open:201.33,high:202.93,low:193.48,close:194.50,volume:13676500},{date:'January 5, 2005',open:193.45,high:196.90,low:192.23,close:193.51,volume:8194600},{date:'January 6, 2005',open:195.25,high:195.90,low:187.72,close:188.55,volume:10326000},{date:'January 7, 2005',open:190.64,high:194.25,low:188.78,close:193.85,volume:9508700},{date:'January 10, 2005',open:194.50,high:198.10,low:191.83,close:195.06,volume:7418600},{date:'January 11, 2005',open:195.62,high:197.71,low:193.18,close:193.54,volume:6920000},{date:'January 12, 2005',open:194.33,high:195.93,low:190.50,close:195.38,volume:8104700},{date:'January 13, 2005',open:195.38,high:197.39,low:194.05,close:195.33,volume:6814300},{date:'January 14, 2005',open:196.00,high:200.01,low:194.13,close:199.97,volume:9528700},{date:'January 18, 2005',open:200.89,high:205.02,low:198.66,close:203.90,volume:12656800},{date:'January 19, 2005',open:204.64,high:205.30,low:196.71,close:197.30,volume:10714400},{date:'January 20, 2005',open:192.58,high:196.25,low:192.00,close:193.92,volume:8957500},{date:'January 21, 2005',open:194.44,high:195.36,low:188.12,close:188.28,volume:9024100},{date:'January 24, 2005',open:188.69,high:189.33,low:180.32,close:180.72,volume:13881100},{date:'January 25, 2005',open:182.20,high:182.24,low:176.29,close:177.12,volume:10559300},{date:'January 26, 2005',open:179.27,high:189.41,low:179.15,close:189.24,volume:12225200},{date:'January 27, 2005',open:188.76,high:188.86,low:185.20,close:188.08,volume:6577800},{date:'January 28, 2005',open:190.02,high:194.70,low:186.34,close:190.34,volume:12126900},{date:'January 31, 2005',open:193.69,high:196.36,low:191.72,close:195.62,volume:9513600},{date:'February 1, 2005',open:194.38,high:203.75,low:190.63,close:191.90,volume:11985700},{date:'February 2, 2005',open:215.55,high:216.80,low:203.66,close:205.96,volume:32475300},{date:'February 3, 2005',open:205.99,high:213.37,low:205.81,close:210.86,volume:12873100},{date:'February 4, 2005',open:206.47,high:207.75,low:202.60,close:204.36,volume:14741600},{date:'February 7, 2005',open:205.26,high:206.40,low:195.51,close:196.03,volume:12853700},{date:'February 8, 2005',open:196.96,high:200.02,low:194.53,close:198.64,volume:11406000},{date:'February 9, 2005',open:200.76,high:201.60,low:189.46,close:191.58,volume:16922400},{date:'February 10, 2005',open:191.97,high:192.21,low:185.25,close:187.98,volume:18912700},{date:'February 11, 2005',open:186.66,high:192.32,low:186.07,close:187.40,volume:13048300},{date:'February 14, 2005',open:182.85,high:193.08,low:181.00,close:192.99,volume:38258000},{date:'February 15, 2005',open:193.60,high:199.84,low:193.08,close:195.23,volume:25721600},{date:'February 16, 2005',open:194.70,high:199.33,low:194.30,close:198.41,volume:16443100},{date:'February 17, 2005',open:197.83,high:199.75,low:196.81,close:197.90,volume:10367600},{date:'February 18, 2005',open:198.51,high:198.84,low:196.66,close:197.95,volume:8434100},{date:'February 22, 2005',open:196.50,high:198.90,low:190.39,close:191.37,volume:13404600},{date:'February 23, 2005',open:193.30,high:194.48,low:188.66,close:193.95,volume:15216400},{date:'February 24, 2005',open:183.37,high:189.85,low:182.23,close:188.89,volume:25572200},{date:'February 25, 2005',open:189.15,high:189.92,low:185.51,close:185.87,volume:9853900},{date:'February 28, 2005',open:186.00,high:189.87,low:185.85,close:187.99,volume:7756600},{date:'March 1, 2005',open:189.29,high:189.75,low:185.39,close:186.06,volume:9271000},{date:'March 2, 2005',open:185.95,high:187.67,low:184.36,close:185.18,volume:7260700},{date:'March 3, 2005',open:186.13,high:187.75,low:184.31,close:187.00,volume:7563400},{date:'March 4, 2005',open:186.70,high:187.25,low:185.07,close:185.90,volume:6725900},{date:'March 7, 2005',open:187.78,high:189.60,low:187.03,close:188.81,volume:8427800},{date:'March 8, 2005',open:189.10,high:189.85,low:184.97,close:185.20,volume:7975700},{date:'March 9, 2005',open:184.21,high:184.65,low:180.16,close:181.35,volume:11179700},{date:'March 10, 2005',open:181.01,high:181.20,low:177.40,close:179.98,volume:10673700},{date:'March 11, 2005',open:180.44,high:180.95,low:177.15,close:177.80,volume:7973600},{date:'March 14, 2005',open:178.33,high:178.40,low:172.57,close:174.99,volume:10972200},{date:'March 15, 2005',open:175.30,high:180.00,low:174.21,close:178.61,volume:10376100},{date:'March 16, 2005',open:176.70,high:178.61,low:175.01,close:175.60,volume:6877400},{date:'March 17, 2005',open:177.13,high:179.64,low:175.80,close:179.29,volume:8078000},{date:'March 18, 2005',open:178.81,high:180.40,low:178.31,close:180.04,volume:6682900},{date:'March 21, 2005',open:179.27,high:182.17,low:177.25,close:180.88,volume:7411000},{date:'March 22, 2005',open:181.18,high:181.94,low:177.85,close:178.60,volume:5563900},{date:'March 23, 2005',open:177.97,high:180.24,low:177.97,close:178.98,volume:4794100},{date:'March 24, 2005',open:180.70,high:180.86,low:179.20,close:179.25,volume:3680200},{date:'March 28, 2005',open:181.68,high:184.80,low:180.95,close:181.42,volume:8661900},{date:'March 29, 2005',open:181.05,high:183.28,low:178.07,close:179.57,volume:6452700},{date:'March 30, 2005',open:180.64,high:181.45,low:179.60,close:180.45,volume:6206800},{date:'March 31, 2005',open:177.95,high:181.39,low:177.64,close:180.51,volume:6696900},{date:'April 1, 2005',open:181.76,high:182.95,low:179.99,close:180.04,volume:6159800},{date:'April 4, 2005',open:179.95,high:185.32,low:179.84,close:185.29,volume:8038300},{date:'April 5, 2005',open:187.73,high:190.26,low:187.57,close:188.57,volume:8636900},{date:'April 6, 2005',open:189.24,high:189.65,low:187.58,close:189.22,volume:5198900},{date:'April 7, 2005',open:188.78,high:194.62,low:188.64,close:193.76,volume:9650000},{date:'April 8, 2005',open:193.69,high:195.10,low:191.45,close:192.05,volume:5087700},{date:'April 11, 2005',open:193.09,high:194.80,low:192.32,close:193.23,volume:5344500},{date:'April 12, 2005',open:193.00,high:194.42,low:189.41,close:193.96,volume:7292600},{date:'April 13, 2005',open:193.47,high:194.32,low:189.73,close:192.93,volume:6492000},{date:'April 14, 2005',open:193.27,high:194.36,low:190.10,close:191.45,volume:6103700},{date:'April 15, 2005',open:190.10,high:190.34,low:184.66,close:185.00,volume:11351400},{date:'April 18, 2005',open:184.58,high:187.88,low:183.49,close:186.97,volume:6528000},{date:'April 19, 2005',open:189.33,high:192.00,low:188.03,close:191.40,volume:7307800},{date:'April 20, 2005',open:198.58,high:200.50,low:195.91,close:198.10,volume:15251300},{date:'April 21, 2005',open:200.42,high:205.00,low:199.32,close:204.22,volume:12997100},{date:'April 22, 2005',open:222.90,high:224.00,low:214.26,close:215.81,volume:32759000},{date:'April 25, 2005',open:217.82,high:224.74,low:217.52,close:223.53,volume:19715800},{date:'April 26, 2005',open:220.22,high:222.00,low:218.29,close:218.75,volume:17152000},{date:'April 27, 2005',open:217.99,high:220.85,low:216.74,close:219.78,volume:10229600},{date:'April 28, 2005',open:219.50,high:222.08,low:217.71,close:219.45,volume:8641600},{date:'April 29, 2005',open:221.91,high:222.25,low:217.82,close:220.00,volume:9082200},{date:'May 2, 2005',open:222.05,high:223.70,low:220.21,close:222.29,volume:9671300},{date:'May 3, 2005',open:221.85,high:228.15,low:221.32,close:226.19,volume:17684300},{date:'May 4, 2005',open:227.23,high:229.88,low:227.00,close:228.50,volume:11920300},{date:'May 5, 2005',open:228.62,high:228.62,low:225.88,close:226.98,volume:7484900},{date:'May 6, 2005',open:228.40,high:229.25,low:226.47,close:228.02,volume:6693200},{date:'May 9, 2005',open:228.00,high:228.50,low:225.43,close:226.02,volume:5513800},{date:'May 10, 2005',open:225.47,high:227.80,low:224.72,close:227.80,volume:6117500},{date:'May 11, 2005',open:228.97,high:231.98,low:227.93,close:231.29,volume:10858300},{date:'May 12, 2005',open:230.81,high:232.23,low:228.20,close:228.72,volume:8902800},{date:'May 13, 2005',open:229.18,high:231.09,low:227.32,close:229.24,volume:7381500},{date:'May 16, 2005',open:229.68,high:231.62,low:228.57,close:231.05,volume:5630900},{date:'May 17, 2005',open:230.56,high:233.45,low:230.20,close:233.13,volume:7762700},{date:'May 18, 2005',open:233.61,high:239.97,low:233.52,close:239.16,volume:12223900},{date:'May 19, 2005',open:240.34,high:241.17,low:238.27,close:239.18,volume:9640100},{date:'May 20, 2005',open:241.21,high:241.67,low:239.65,close:241.61,volume:7895800},{date:'May 23, 2005',open:243.16,high:258.10,low:242.71,close:255.45,volume:21223600},{date:'May 24, 2005',open:256.96,high:265.44,low:253.50,close:256.00,volume:28948500},{date:'May 25, 2005',open:252.73,high:260.98,low:250.63,close:260.81,volume:17743400},{date:'May 26, 2005',open:260.96,high:263.76,low:258.30,close:259.20,volume:13402700},{date:'May 27, 2005',open:260.46,high:266.05,low:259.25,close:266.00,volume:12088600},{date:'May 31, 2005',open:269.43,high:278.40,low:269.37,close:277.27,volume:21497800},{date:'June 1, 2005',open:283.20,high:292.89,low:282.02,close:288.00,volume:34900300},{date:'June 2, 2005',open:288.73,high:289.78,low:284.60,close:287.90,volume:17704500},{date:'June 3, 2005',open:286.79,high:289.30,low:277.41,close:280.26,volume:18703400},{date:'June 6, 2005',open:282.39,high:293.75,low:281.83,close:290.94,volume:22406100},{date:'June 7, 2005',open:297.10,high:299.59,low:290.30,close:293.12,volume:24206200},{date:'June 8, 2005',open:292.85,high:293.19,low:278.00,close:279.56,volume:25191400},{date:'June 9, 2005',open:284.72,high:288.50,low:280.56,close:286.31,volume:16319900},{date:'June 10, 2005',open:286.99,high:287.28,low:280.02,close:282.50,volume:12509400},{date:'June 13, 2005',open:279.82,high:284.19,low:276.52,close:282.75,volume:12683500},{date:'June 14, 2005',open:278.59,high:281.24,low:277.75,close:278.35,volume:9985700},{date:'June 15, 2005',open:275.00,high:277.30,low:267.43,close:274.80,volume:20776300},{date:'June 16, 2005',open:274.26,high:278.30,low:273.07,close:277.44,volume:12206800},{date:'June 17, 2005',open:279.00,high:280.30,low:275.90,close:280.30,volume:9951200},{date:'June 20, 2005',open:276.09,high:287.67,low:271.73,close:286.70,volume:20910500},{date:'June 21, 2005',open:288.07,high:290.30,low:284.97,close:287.84,volume:15069700},{date:'June 22, 2005',open:289.67,high:292.32,low:288.67,close:289.30,volume:10277000},{date:'June 23, 2005',open:288.00,high:294.81,low:286.50,close:289.71,volume:13929300},{date:'June 24, 2005',open:290.90,high:298.00,low:289.58,close:297.25,volume:16652500},{date:'June 27, 2005',open:298.90,high:304.47,low:293.86,close:304.10,volume:17619200},{date:'June 28, 2005',open:306.28,high:309.25,low:302.00,close:302.00,volume:18812000},{date:'June 29, 2005',open:302.50,high:304.38,low:292.15,close:292.72,volume:18143700},{date:'June 30, 2005',open:294.34,high:298.93,low:291.04,close:294.15,volume:14820100},{date:'July 1, 2005',open:295.04,high:296.24,low:289.22,close:291.25,volume:9089900},{date:'July 5, 2005',open:292.10,high:295.98,low:290.23,close:295.71,volume:7433800},{date:'July 6, 2005',open:297.30,high:297.60,low:291.38,close:291.52,volume:7918000},{date:'July 7, 2005',open:289.39,high:295.80,low:288.51,close:295.54,volume:10583500},{date:'July 8, 2005',open:296.25,high:297.50,low:294.05,close:296.23,volume:7407700},{date:'July 11, 2005',open:296.40,high:296.60,low:291.02,close:293.35,volume:8311300},{date:'July 12, 2005',open:293.39,high:294.40,low:290.93,close:291.78,volume:5832800},{date:'July 13, 2005',open:292.51,high:299.24,low:292.10,close:298.86,volume:11284700},{date:'July 14, 2005',open:305.34,high:306.75,low:300.07,close:300.89,volume:10553100},{date:'July 15, 2005',open:301.24,high:303.40,low:299.78,close:301.19,volume:8026300},{date:'July 18, 2005',open:300.00,high:301.90,low:297.75,close:299.54,volume:6129600},{date:'July 19, 2005',open:302.10,high:310.35,low:301.80,close:309.90,volume:11233100},{date:'July 20, 2005',open:305.57,high:312.61,low:301.80,close:312.00,volume:13732700},{date:'July 21, 2005',open:314.05,high:317.80,low:311.21,close:313.94,volume:13611400},{date:'July 22, 2005',open:306.37,high:309.25,low:296.33,close:302.40,volume:23178900},{date:'July 25, 2005',open:302.39,high:303.29,low:294.96,close:295.85,volume:9585500},{date:'July 26, 2005',open:295.01,high:298.00,low:292.09,close:296.09,volume:9743400},{date:'July 27, 2005',open:297.74,high:298.23,low:292.40,close:296.93,volume:7164700},{date:'July 28, 2005',open:297.41,high:297.41,low:293.28,close:293.50,volume:5864300},{date:'July 29, 2005',open:292.14,high:292.84,low:286.99,close:287.76,volume:8269500},{date:'August 1, 2005',open:288.12,high:292.50,low:288.10,close:291.61,volume:5643900},{date:'August 2, 2005',open:291.60,high:299.52,low:291.12,close:299.19,volume:7244800},{date:'August 3, 2005',open:298.00,high:299.72,low:295.60,close:297.30,volume:5888700},{date:'August 4, 2005',open:295.55,high:299.00,low:295.25,close:297.73,volume:5209400},{date:'August 5, 2005',open:297.50,high:298.51,low:291.31,close:292.35,volume:5902500},{date:'August 8, 2005',open:293.60,high:295.65,low:290.49,close:291.25,volume:4441500},{date:'August 9, 2005',open:291.96,high:292.68,low:288.51,close:291.57,volume:5734800},{date:'August 10, 2005',open:291.30,high:292.33,low:284.88,close:285.68,volume:6827600},{date:'August 11, 2005',open:285.89,high:286.58,low:280.62,close:284.05,volume:7410400},{date:'August 12, 2005',open:283.36,high:290.20,low:281.64,close:289.72,volume:6540900},{date:'August 15, 2005',open:289.80,high:292.77,low:283.77,close:284.00,volume:8042700},{date:'August 16, 2005',open:284.88,high:287.79,low:283.34,close:285.65,volume:7051100},{date:'August 17, 2005',open:285.51,high:286.57,low:284.00,close:285.10,volume:3825300},{date:'August 18, 2005',open:275.91,high:280.50,low:275.00,close:279.99,volume:11788700},{date:'August 19, 2005',open:280.99,high:281.45,low:279.62,close:280.00,volume:5510400},{date:'August 22, 2005',open:281.24,high:281.47,low:273.35,close:274.01,volume:6784100},{date:'August 23, 2005',open:276.16,high:279.74,low:274.12,close:279.58,volume:5796600},{date:'August 24, 2005',open:277.57,high:284.75,low:276.45,close:282.57,volume:8504900},{date:'August 25, 2005',open:282.55,high:284.00,low:279.97,close:282.59,volume:4347100},{date:'August 26, 2005',open:283.48,high:285.02,low:282.66,close:283.58,volume:3735100},{date:'August 29, 2005',open:282.24,high:289.12,low:282.24,close:288.45,volume:5863400},{date:'August 30, 2005',open:287.39,high:289.51,low:285.88,close:287.27,volume:4757600},{date:'August 31, 2005',open:288.23,high:288.50,low:284.36,close:286.00,volume:4959300},{date:'September 1, 2005',open:285.91,high:287.50,low:285.00,close:286.25,volume:2720000},{date:'September 2, 2005',open:286.51,high:289.99,low:286.44,close:288.45,volume:3391200},{date:'September 6, 2005',open:289.00,high:289.39,low:286.80,close:287.11,volume:4184900},{date:'September 7, 2005',open:285.89,high:295.50,low:285.28,close:294.87,volume:7452800},{date:'September 8, 2005',open:294.83,high:299.28,low:293.36,close:295.39,volume:6594100},{date:'September 9, 2005',open:297.28,high:299.10,low:296.56,close:299.09,volume:4351700},{date:'September 12, 2005',open:301.75,high:311.42,low:301.00,close:309.74,volume:10310100},{date:'September 13, 2005',open:309.00,high:315.53,low:306.17,close:311.68,volume:10256300},{date:'September 14, 2005',open:308.73,high:313.28,low:300.30,close:303.00,volume:11185000},{date:'September 15, 2005',open:299.52,high:306.75,low:297.91,close:302.62,volume:15377000},{date:'September 16, 2005',open:304.02,high:304.50,low:299.87,close:300.20,volume:7349700},{date:'September 19, 2005',open:301.00,high:306.00,low:300.71,close:303.79,volume:5742900},{date:'September 20, 2005',open:306.15,high:311.30,low:305.23,close:307.91,volume:9346400},{date:'September 21, 2005',open:308.41,high:313.76,low:305.96,close:311.90,volume:9776500},{date:'September 22, 2005',open:311.50,high:319.22,low:310.17,close:311.37,volume:12619900},{date:'September 23, 2005',open:313.00,high:317.21,low:312.59,close:315.36,volume:8339700},{date:'September 26, 2005',open:319.50,high:320.95,low:312.56,close:314.28,volume:9731600},{date:'September 27, 2005',open:314.95,high:318.41,low:313.38,close:313.94,volume:6819700},{date:'September 28, 2005',open:314.22,high:315.10,low:305.60,close:306.00,volume:7918200},{date:'September 29, 2005',open:306.68,high:310.72,low:306.08,close:309.62,volume:5542800},{date:'September 30, 2005',open:314.22,high:317.50,low:312.29,close:316.46,volume:8761600},{date:'October 3, 2005',open:313.63,high:320.11,low:312.79,close:318.68,volume:9117400},{date:'October 4, 2005',open:319.95,high:321.28,low:310.74,close:311.00,volume:9092600},{date:'October 5, 2005',open:312.69,high:314.90,low:308.00,close:310.71,volume:8279000},{date:'October 6, 2005',open:314.14,high:314.48,low:310.09,close:312.75,volume:7929500},{date:'October 7, 2005',open:314.79,high:316.67,low:310.54,close:312.99,volume:6742900},{date:'October 10, 2005',open:313.31,high:314.82,low:309.15,close:310.65,volume:5517400},{date:'October 11, 2005',open:310.61,high:312.65,low:304.86,close:306.10,volume:8484300},{date:'October 12, 2005',open:305.20,high:307.19,low:299.00,close:300.97,volume:9151200},{date:'October 13, 2005',open:302.00,high:302.00,low:290.68,close:297.44,volume:10544100},{date:'October 14, 2005',open:299.90,high:300.23,low:292.54,close:296.14,volume:8499100},{date:'October 17, 2005',open:297.50,high:305.20,low:294.56,close:305.00,volume:7507600},{date:'October 18, 2005',open:304.96,high:307.96,low:302.74,close:303.28,volume:6896400},{date:'October 19, 2005',open:304.00,high:309.87,low:303.96,close:308.70,volume:6872000},{date:'October 20, 2005',open:309.99,high:311.13,low:301.21,close:303.20,volume:7902100},{date:'October 21, 2005',open:345.80,high:346.43,low:333.00,close:339.90,volume:22440600},{date:'October 24, 2005',open:343.37,high:349.30,low:342.19,close:348.65,volume:9404400},{date:'October 25, 2005',open:345.78,high:347.40,low:342.86,close:346.91,volume:6847000},{date:'October 26, 2005',open:346.28,high:356.00,low:346.19,close:355.44,volume:8841700},{date:'October 27, 2005',open:356.60,high:357.09,low:351.68,close:353.06,volume:5101500},{date:'October 28, 2005',open:355.27,high:358.95,low:355.02,close:358.17,volume:5861900},{date:'October 31, 2005',open:360.24,high:374.75,low:359.51,close:372.14,volume:14245000},{date:'November 1, 2005',open:371.86,high:383.90,low:369.01,close:379.38,volume:16247000},{date:'November 2, 2005',open:381.70,high:385.00,low:377.17,close:379.68,volume:10526800},{date:'November 3, 2005',open:382.41,high:386.58,low:381.38,close:385.95,volume:7355100},{date:'November 4, 2005',open:389.98,high:391.79,low:385.45,close:390.43,volume:8744100},{date:'November 7, 2005',open:395.10,high:397.47,low:392.15,close:395.03,volume:9489300},{date:'November 8, 2005',open:394.25,high:395.59,low:388.58,close:389.90,volume:7857200},{date:'November 9, 2005',open:386.67,high:388.29,low:378.03,close:379.15,volume:10361600},{date:'November 10, 2005',open:378.36,high:391.35,low:377.43,close:391.10,volume:8973200},{date:'November 11, 2005',open:395.12,high:396.90,low:388.85,close:390.40,volume:6998300},{date:'November 14, 2005',open:392.12,high:398.22,low:391.53,close:396.97,volume:7642700},{date:'November 15, 2005',open:394.38,high:397.00,low:390.95,close:392.80,volume:8569500},{date:'November 16, 2005',open:396.20,high:398.85,low:394.11,close:398.15,volume:8561300},{date:'November 17, 2005',open:401.80,high:403.81,low:399.53,close:403.45,volume:9058400},{date:'November 18, 2005',open:403.49,high:404.50,low:399.85,close:400.21,volume:6845700},{date:'November 21, 2005',open:399.17,high:409.98,low:393.49,close:409.36,volume:10237000},{date:'November 22, 2005',open:408.65,high:417.31,low:406.23,close:416.47,volume:9539800},{date:'November 23, 2005',open:417.04,high:424.72,low:415.78,close:422.86,volume:9923900},{date:'November 25, 2005',open:425.78,high:428.75,low:425.30,close:428.62,volume:4791900},{date:'November 28, 2005',open:429.82,high:431.24,low:422.44,close:423.48,volume:10869500},{date:'November 29, 2005',open:424.46,high:426.40,low:402.14,close:403.54,volume:21200600},{date:'November 30, 2005',open:404.26,high:408.45,low:395.56,close:404.91,volume:15456200},{date:'December 1, 2005',open:409.20,high:415.44,low:408.29,close:414.09,volume:9480400},{date:'December 2, 2005',open:416.94,high:419.53,low:413.86,close:417.70,volume:7444000},{date:'December 5, 2005',open:417.00,high:417.50,low:404.28,close:405.85,volume:10095800},{date:'December 6, 2005',open:408.70,high:416.41,low:401.70,close:404.54,volume:15020200},{date:'December 7, 2005',open:406.16,high:406.70,low:399.01,close:404.22,volume:11428800},{date:'December 8, 2005',open:405.30,high:410.65,low:402.64,close:410.65,volume:8818100},{date:'December 9, 2005',open:415.00,high:415.78,low:408.56,close:409.20,volume:7538200},{date:'December 12, 2005',open:414.63,high:415.21,low:409.95,close:412.61,volume:6882800},{date:'December 13, 2005',open:412.50,high:418.00,low:411.64,close:417.49,volume:8059600},{date:'December 14, 2005',open:417.04,high:419.73,low:415.49,close:418.96,volume:6512200},{date:'December 15, 2005',open:419.11,high:423.14,low:416.50,close:422.53,volume:5932000},{date:'December 16, 2005',open:425.34,high:432.50,low:422.75,close:430.15,volume:13740500},{date:'December 19, 2005',open:432.20,high:446.21,low:420.11,close:424.60,volume:21815600},{date:'December 20, 2005',open:427.86,high:432.20,low:424.67,close:429.74,volume:9972900},{date:'December 21, 2005',open:433.55,high:436.86,low:420.71,close:426.33,volume:11167600},{date:'December 22, 2005',open:431.77,high:432.86,low:425.93,close:432.04,volume:7495600},{date:'December 23, 2005',open:432.15,high:432.50,low:428.78,close:430.93,volume:4552200},{date:'December 27, 2005',open:431.86,high:431.86,low:422.76,close:424.64,volume:6656900},{date:'December 28, 2005',open:424.34,high:427.78,low:421.26,close:426.69,volume:7207400},{date:'December 29, 2005',open:427.98,high:428.73,low:419.17,close:420.15,volume:6891300},{date:'December 30, 2005',open:417.27,high:418.21,low:413.74,close:414.86,volume:7499100},{date:'January 3, 2006',open:422.52,high:435.67,low:418.22,close:435.23,volume:12905700},{date:'January 4, 2006',open:443.90,high:448.96,low:439.75,close:445.24,volume:15100400},{date:'January 5, 2006',open:446.00,high:451.55,low:441.50,close:451.24,volume:10665200},{date:'January 6, 2006',open:456.87,high:470.50,low:453.24,close:465.66,volume:17622300},{date:'January 9, 2006',open:466.41,high:473.40,low:460.94,close:466.90,volume:12743900},{date:'January 10, 2006',open:464.42,high:470.25,low:462.04,close:469.76,volume:9034700},{date:'January 11, 2006',open:471.27,high:475.11,low:469.18,close:471.63,volume:8857000},{date:'January 12, 2006',open:473.72,high:474.99,low:461.50,close:463.63,volume:10041500},{date:'January 13, 2006',open:464.31,high:466.89,low:461.61,close:466.25,volume:7621900},{date:'January 17, 2006',open:463.06,high:469.90,low:462.53,close:467.11,volume:7176400},{date:'January 18, 2006',open:447.30,high:457.36,low:443.25,close:444.91,volume:20032100},{date:'January 19, 2006',open:451.17,high:453.49,low:433.00,close:436.45,volume:14451300},{date:'January 20, 2006',open:438.70,high:440.03,low:394.74,close:399.46,volume:40548700},{date:'January 23, 2006',open:407.38,high:428.39,low:405.73,close:427.50,volume:22482600},{date:'January 24, 2006',open:436.03,high:444.95,low:434.48,close:443.03,volume:15369100},{date:'January 25, 2006',open:451.26,high:454.23,low:429.22,close:433.00,volume:18596300},{date:'January 26, 2006',open:439.54,high:439.99,low:423.56,close:434.27,volume:12809100},{date:'January 27, 2006',open:435.00,high:438.22,low:428.98,close:433.49,volume:8395500},{date:'January 30, 2006',open:429.23,high:433.28,low:425.00,close:426.82,volume:8490800},{date:'January 31, 2006',open:430.57,high:439.60,low:423.97,close:432.66,volume:14396900},{date:'February 1, 2006',open:389.03,high:402.00,low:387.52,close:401.78,volume:26608600},{date:'February 2, 2006',open:403.82,high:406.50,low:395.98,close:396.04,volume:11503000},{date:'February 3, 2006',open:393.62,high:393.90,low:372.57,close:381.56,volume:18172500},{date:'February 6, 2006',open:385.31,high:389.90,low:379.56,close:385.10,volume:8851800},{date:'February 7, 2006',open:382.99,high:383.70,low:363.34,close:367.92,volume:16486500},{date:'February 8, 2006',open:368.48,high:370.69,low:354.67,close:369.08,volume:20686200},{date:'February 9, 2006',open:371.20,high:374.40,low:356.11,close:358.77,volume:11700100},{date:'February 10, 2006',open:361.95,high:364.50,low:353.14,close:362.61,volume:14751100},{date:'February 13, 2006',open:346.64,high:350.60,low:341.89,close:345.70,volume:19453100},{date:'February 14, 2006',open:345.33,high:351.69,low:342.40,close:343.32,volume:14522100},{date:'February 15, 2006',open:341.27,high:346.00,low:337.83,close:342.38,volume:12621400},{date:'February 16, 2006',open:345.67,high:367.00,low:344.49,close:366.46,volume:21105400},{date:'February 17, 2006',open:369.86,high:372.14,low:363.62,close:368.75,volume:14019100},{date:'February 21, 2006',open:366.44,high:373.54,low:365.11,close:366.59,volume:8367200},{date:'February 22, 2006',open:367.15,high:368.95,low:363.86,close:365.49,volume:6448600},{date:'February 23, 2006',open:365.61,high:381.24,low:365.39,close:378.07,volume:12498800},{date:'February 24, 2006',open:377.30,high:380.07,low:373.49,close:377.40,volume:6456400},{date:'February 27, 2006',open:381.27,high:391.70,low:380.28,close:390.38,volume:10130300},{date:'February 28, 2006',open:393.20,high:397.54,low:338.51,close:362.62,volume:39204500},{date:'March 1, 2006',open:368.56,high:369.45,low:361.30,close:364.80,volume:11967900},{date:'March 2, 2006',open:364.28,high:381.10,low:362.20,close:376.45,volume:17950400},{date:'March 3, 2006',open:384.30,high:387.24,low:375.76,close:378.18,volume:11797700},{date:'March 6, 2006',open:380.91,high:383.40,low:367.14,close:368.10,volume:8869400},{date:'March 7, 2006',open:364.59,high:368.45,low:358.15,close:364.45,volume:9812500},{date:'March 8, 2006',open:353.94,high:360.03,low:350.54,close:353.88,volume:11503400},{date:'March 9, 2006',open:355.59,high:358.53,low:341.50,close:343.00,volume:13794600},{date:'March 10, 2006',open:343.50,high:344.50,low:331.55,close:337.50,volume:19241200},{date:'March 13, 2006',open:340.93,high:346.10,low:335.45,close:337.06,volume:13589100},{date:'March 14, 2006',open:337.14,high:352.37,low:332.62,close:351.16,volume:18324300},{date:'March 15, 2006',open:350.77,high:352.30,low:340.53,close:344.50,volume:12633300},{date:'March 16, 2006',open:348.61,high:348.75,low:337.90,close:338.77,volume:9906700},{date:'March 17, 2006',open:338.80,high:341.78,low:334.93,close:339.79,volume:8426600},{date:'March 20, 2006',open:342.34,high:350.09,low:341.54,close:348.19,volume:10359500},{date:'March 21, 2006',open:350.01,high:351.66,low:339.08,close:339.92,volume:9762300},{date:'March 22, 2006',open:339.75,high:344.10,low:337.50,close:340.22,volume:7569000},{date:'March 23, 2006',open:342.35,high:345.75,low:340.20,close:341.89,volume:6117700},{date:'March 24, 2006',open:368.62,high:370.09,low:362.51,close:365.80,volume:14948200},{date:'March 27, 2006',open:367.09,high:371.71,low:365.00,close:369.69,volume:6973300},{date:'March 28, 2006',open:371.71,high:377.86,low:371.17,close:377.20,volume:8885500},{date:'March 29, 2006',open:379.94,high:399.00,low:379.51,close:394.98,volume:17942800},{date:'March 30, 2006',open:389.19,high:393.50,low:383.61,close:388.44,volume:14607200},{date:'March 31, 2006',open:388.74,high:391.87,low:384.03,close:390.00,volume:27961300},{date:'April 3, 2006',open:389.53,high:392.47,low:387.93,close:389.70,volume:8035300},{date:'April 4, 2006',open:389.90,high:404.90,low:388.14,close:404.34,volume:15606700},{date:'April 5, 2006',open:408.20,high:414.57,low:402.82,close:407.99,volume:13212500},{date:'April 6, 2006',open:406.49,high:413.89,low:405.43,close:411.18,volume:8558900},{date:'April 7, 2006',open:412.41,high:412.85,low:404.02,close:406.16,volume:6983200},{date:'April 10, 2006',open:407.08,high:417.17,low:405.25,close:416.38,volume:9241500},{date:'April 11, 2006',open:416.42,high:419.10,low:406.22,close:409.66,volume:11043400},{date:'April 12, 2006',open:409.00,high:411.33,low:405.19,close:408.95,volume:5993200},{date:'April 13, 2006',open:408.63,high:409.76,low:400.50,close:402.16,volume:6518100},{date:'April 17, 2006',open:403.45,high:412.50,low:400.84,close:406.82,volume:8236500},{date:'April 18, 2006',open:407.93,high:409.83,low:401.50,close:404.24,volume:7035700},{date:'April 19, 2006',open:412.57,high:413.64,low:406.73,close:410.50,volume:6677800},{date:'April 20, 2006',open:411.01,high:416.00,low:408.20,close:415.00,volume:7535900},{date:'April 21, 2006',open:448.90,high:450.72,low:436.17,close:437.10,volume:22234100},{date:'April 24, 2006',open:439.40,high:444.70,low:436.52,close:440.50,volume:8386900},{date:'April 25, 2006',open:439.63,high:441.04,low:426.00,close:427.16,volume:9469400},{date:'April 26, 2006',open:427.74,high:430.04,low:423.53,close:425.97,volume:7199000},{date:'April 27, 2006',open:422.91,high:426.91,low:419.39,close:420.03,volume:8197000},{date:'April 28, 2006',open:418.62,high:425.73,low:416.30,close:417.94,volume:7372400},{date:'May 1, 2006',open:418.47,high:419.44,low:398.55,close:398.90,volume:10222000},{date:'May 2, 2006',open:401.08,high:402.49,low:388.40,close:394.80,volume:13009200},{date:'May 3, 2006',open:396.35,high:401.50,low:390.88,close:394.17,volume:7764800},{date:'May 4, 2006',open:395.03,high:398.87,low:392.21,close:394.75,volume:4611300},{date:'May 5, 2006',open:397.60,high:400.68,low:391.78,close:394.30,volume:5990300},{date:'May 8, 2006',open:395.11,high:397.12,low:390.05,close:394.78,volume:5068000},{date:'May 9, 2006',open:395.70,high:409.00,low:393.75,close:408.80,volume:9001900},{date:'May 10, 2006',open:408.31,high:411.71,low:401.86,close:402.98,volume:6161100},{date:'May 11, 2006',open:403.42,high:404.71,low:384.98,close:387.00,volume:8870600},{date:'May 12, 2006',open:383.54,high:384.87,low:373.55,close:374.13,volume:10029800},{date:'May 15, 2006',open:375.93,high:380.15,low:368.25,close:376.20,volume:8554800},{date:'May 16, 2006',open:375.99,high:376.86,low:369.89,close:371.30,volume:5245200},{date:'May 17, 2006',open:370.61,high:379.84,low:370.22,close:374.50,volume:10418300},{date:'May 18, 2006',open:378.78,high:381.81,low:370.71,close:370.99,volume:5803600},{date:'May 19, 2006',open:373.28,high:374.50,low:360.57,close:370.02,volume:11293500},{date:'May 22, 2006',open:367.85,high:373.03,low:365.25,close:370.95,volume:8567000},{date:'May 23, 2006',open:374.21,high:383.88,low:373.56,close:375.58,volume:8925200},{date:'May 24, 2006',open:377.35,high:383.44,low:371.61,close:381.25,volume:9520100},{date:'May 25, 2006',open:379.08,high:383.00,low:372.31,close:382.99,volume:8133300},{date:'May 26, 2006',open:384.55,high:385.88,low:380.03,close:381.35,volume:3632300},{date:'May 30, 2006',open:378.28,high:381.00,low:371.45,close:371.94,volume:4273200},{date:'May 31, 2006',open:373.80,high:378.25,low:366.78,close:371.82,volume:7915700},{date:'June 1, 2006',open:373.54,high:382.99,low:371.60,close:382.62,volume:6239000},{date:'June 2, 2006',open:386.84,high:387.08,low:377.45,close:379.44,volume:6342600},{date:'June 5, 2006',open:376.18,high:381.45,low:374.15,close:374.44,volume:5524200},{date:'June 6, 2006',open:376.58,high:390.00,low:376.30,close:389.99,volume:10165700},{date:'June 7, 2006',open:393.24,high:394.86,low:386.50,close:386.51,volume:8464000},{date:'June 8, 2006',open:387.75,high:394.27,low:378.59,close:393.30,volume:10328800},{date:'June 9, 2006',open:392.19,high:395.43,low:385.35,close:386.57,volume:6123300},{date:'June 12, 2006',open:388.34,high:390.49,low:381.00,close:381.54,volume:4988500},{date:'June 13, 2006',open:380.90,high:387.00,low:378.12,close:386.52,volume:7628500},{date:'June 14, 2006',open:389.83,high:391.10,low:378.52,close:384.39,volume:7737200},{date:'June 15, 2006',open:386.62,high:392.25,low:383.00,close:391.00,volume:6738700},{date:'June 16, 2006',open:389.10,high:390.93,low:388.00,close:390.70,volume:5153100},{date:'June 19, 2006',open:390.85,high:394.80,low:386.98,close:388.14,volume:6985300},{date:'June 20, 2006',open:388.03,high:391.87,low:386.51,close:387.17,volume:4008800},{date:'June 21, 2006',open:391.06,high:404.00,low:389.75,close:402.13,volume:8625500},{date:'June 22, 2006',open:401.58,high:406.00,low:388.00,close:399.95,volume:5980100},{date:'June 23, 2006',open:402.76,high:409.75,low:400.74,close:404.86,volume:5282500},{date:'June 26, 2006',open:406.75,high:408.30,low:403.25,close:404.22,volume:3524800},{date:'June 27, 2006',open:405.71,high:408.00,low:401.01,close:402.32,volume:4085100},{date:'June 28, 2006',open:404.01,high:406.48,low:401.13,close:406.11,volume:3687000},{date:'June 29, 2006',open:407.99,high:418.20,low:405.82,close:417.81,volume:6617900},{date:'June 30, 2006',open:415.60,high:419.33,low:412.33,close:419.33,volume:5577200},{date:'July 3, 2006',open:420.04,high:423.77,low:419.45,close:423.20,volume:2132400},{date:'July 5, 2006',open:421.52,high:422.80,low:415.64,close:421.46,volume:4932600},{date:'July 6, 2006',open:423.38,high:425.38,low:421.98,close:423.19,volume:3653800},{date:'July 7, 2006',open:426.05,high:427.89,low:415.88,close:420.45,volume:5964900},{date:'July 10, 2006',open:423.44,high:425.23,low:416.38,close:418.20,volume:4420400},{date:'July 11, 2006',open:418.50,high:425.05,low:413.03,close:424.56,volume:5949400},{date:'July 12, 2006',open:422.09,high:422.74,low:416.73,close:417.25,volume:4867700},{date:'July 13, 2006',open:414.00,high:418.34,low:406.83,close:408.83,volume:6894400},{date:'July 14, 2006',open:410.33,high:411.49,low:398.61,close:403.50,volume:7430500},{date:'July 17, 2006',open:404.62,high:411.00,low:403.72,close:407.89,volume:5798600},{date:'July 18, 2006',open:409.75,high:410.57,low:397.74,close:403.05,volume:7373500},{date:'July 19, 2006',open:395.01,high:401.14,low:394.66,close:399.00,volume:8180600},{date:'July 20, 2006',open:404.28,high:404.44,low:385.66,close:387.12,volume:9075200},{date:'July 21, 2006',open:386.14,high:391.75,low:377.69,close:390.11,volume:11524300},{date:'July 24, 2006',open:392.82,high:393.89,low:381.21,close:390.90,volume:7857100},{date:'July 25, 2006',open:385.02,high:391.31,low:383.80,close:389.36,volume:5722200},{date:'July 26, 2006',open:388.20,high:391.91,low:383.00,close:385.50,volume:5401700},{date:'July 27, 2006',open:387.37,high:387.49,low:377.95,close:382.40,volume:5617900},{date:'July 28, 2006',open:382.00,high:389.56,low:381.73,close:388.12,volume:4075700},{date:'July 31, 2006',open:388.00,high:389.17,low:383.31,close:386.60,volume:4477200},{date:'August 1, 2006',open:385.11,high:385.77,low:375.51,close:375.51,volume:5397400},{date:'August 2, 2006',open:375.60,high:377.17,low:365.20,close:367.23,volume:7008100},{date:'August 3, 2006',open:364.98,high:377.91,low:363.36,close:375.39,volume:6303500},{date:'August 4, 2006',open:379.56,high:380.68,low:371.75,close:373.85,volume:5080700},{date:'August 7, 2006',open:371.50,high:379.73,low:371.15,close:377.95,volume:3789100},{date:'August 8, 2006',open:382.82,high:384.50,low:379.09,close:381.00,volume:5690900},{date:'August 9, 2006',open:383.71,high:384.68,low:376.36,close:376.94,volume:4249100},{date:'August 10, 2006',open:374.36,high:377.67,low:372.46,close:374.20,volume:4247000},{date:'August 11, 2006',open:374.40,high:375.28,low:368.00,close:368.50,volume:3744300},{date:'August 14, 2006',open:371.50,high:375.13,low:368.67,close:369.43,volume:4946400},{date:'August 15, 2006',open:374.11,high:381.67,low:372.60,close:380.97,volume:6607100},{date:'August 16, 2006',open:383.48,high:388.45,low:382.12,close:387.72,volume:5814600},{date:'August 17, 2006',open:386.99,high:390.00,low:383.92,close:385.80,volume:5060200},{date:'August 18, 2006',open:386.31,high:387.09,low:380.75,close:383.36,volume:4911000},{date:'August 21, 2006',open:378.10,high:379.00,low:375.22,close:377.30,volume:4000900},{date:'August 22, 2006',open:377.73,high:379.26,low:374.84,close:378.29,volume:4144500},{date:'August 23, 2006',open:377.64,high:378.27,low:372.66,close:373.43,volume:3611300},{date:'August 24, 2006',open:374.44,high:376.40,low:372.26,close:373.73,volume:3466200},{date:'August 25, 2006',open:373.08,high:375.32,low:372.50,close:373.26,volume:2461300},{date:'August 28, 2006',open:375.61,high:380.95,low:375.00,close:380.95,volume:4151800},{date:'August 29, 2006',open:380.78,high:382.32,low:377.20,close:378.95,volume:4007800},{date:'August 30, 2006',open:379.21,high:384.65,low:378.51,close:380.75,volume:4069100},{date:'August 31, 2006',open:381.49,high:382.15,low:378.20,close:378.53,volume:2916400},{date:'September 1, 2006',open:381.00,high:381.28,low:377.19,close:378.60,volume:2660000},{date:'September 5, 2006',open:379.87,high:385.40,low:377.44,close:384.36,volume:4062400},{date:'September 6, 2006',open:382.10,high:383.19,low:379.66,close:380.14,volume:3712600},{date:'September 7, 2006',open:379.39,high:381.75,low:377.40,close:378.49,volume:3719600},{date:'September 8, 2006',open:376.72,high:380.79,low:376.72,close:377.85,volume:3066000},{date:'September 11, 2006',open:378.26,high:384.69,low:377.77,close:384.09,volume:4500000},{date:'September 12, 2006',open:385.00,high:392.73,low:384.88,close:391.90,volume:5427400},{date:'September 13, 2006',open:395.15,high:406.76,low:395.10,close:406.57,volume:9644400},{date:'September 14, 2006',open:404.30,high:406.28,low:401.93,close:403.98,volume:5337400},{date:'September 15, 2006',open:407.48,high:410.05,low:406.74,close:409.88,volume:7488000},{date:'September 18, 2006',open:409.78,high:418.69,low:409.47,close:414.69,volume:7076700},{date:'September 19, 2006',open:415.46,high:415.49,low:392.74,close:403.81,volume:14181600},{date:'September 20, 2006',open:407.10,high:407.39,low:394.62,close:397.00,volume:9086800},{date:'September 21, 2006',open:400.35,high:408.45,low:399.86,close:406.85,volume:10653500},{date:'September 22, 2006',open:404.98,high:407.45,low:401.36,close:403.78,volume:4638400},{date:'September 25, 2006',open:405.58,high:409.45,low:402.50,close:403.98,volume:5588200},{date:'September 26, 2006',open:405.50,high:407.68,low:401.77,close:406.87,volume:5250300},{date:'September 27, 2006',open:406.30,high:411.22,low:402.37,close:402.92,volume:5805700},{date:'September 28, 2006',open:404.08,high:406.98,low:400.54,close:403.58,volume:5061400},{date:'September 29, 2006',open:405.12,high:405.62,low:401.41,close:401.90,volume:3275600},{date:'October 2, 2006',open:401.90,high:406.00,low:400.80,close:401.44,volume:3629800},{date:'October 3, 2006',open:401.29,high:406.46,low:398.19,close:404.04,volume:5432700},{date:'October 4, 2006',open:404.97,high:415.77,low:403.05,close:415.70,volume:6493200},{date:'October 5, 2006',open:414.70,high:418.24,low:410.86,close:411.81,volume:5533400},{date:'October 6, 2006',open:410.22,high:421.91,low:409.75,close:420.50,volume:7271300},{date:'October 9, 2006',open:424.80,high:431.95,low:423.42,close:429.00,volume:7013200},{date:'October 10, 2006',open:431.56,high:437.85,low:422.39,close:426.65,volume:9524400},{date:'October 11, 2006',open:425.02,high:429.91,low:423.76,close:426.50,volume:5586000},{date:'October 12, 2006',open:428.56,high:429.68,low:424.00,close:427.44,volume:4801800},{date:'October 13, 2006',open:427.76,high:429.50,low:425.56,close:427.30,volume:3594100},{date:'October 16, 2006',open:427.70,high:429.20,low:421.34,close:421.75,volume:4271100},{date:'October 17, 2006',open:420.30,high:423.75,low:416.70,close:420.64,volume:4763600},{date:'October 18, 2006',open:423.00,high:424.75,low:417.50,close:419.31,volume:5880800},{date:'October 19, 2006',open:420.23,high:454.91,low:419.57,close:426.06,volume:7594600},{date:'October 20, 2006',open:458.99,high:460.10,low:453.59,close:459.67,volume:10872800},{date:'October 23, 2006',open:462.28,high:484.64,low:460.37,close:480.78,volume:14367700},{date:'October 24, 2006',open:476.28,high:477.86,low:471.41,close:473.31,volume:8349200},{date:'October 25, 2006',open:477.49,high:488.50,low:475.11,close:486.60,volume:8973900},{date:'October 26, 2006',open:487.68,high:491.96,low:484.20,close:485.10,volume:6894000},{date:'October 27, 2006',open:483.90,high:485.24,low:472.49,close:475.20,volume:6495900},{date:'October 30, 2006',open:474.82,high:480.46,low:470.01,close:476.57,volume:6484600},{date:'October 31, 2006',open:478.06,high:482.16,low:473.84,close:476.39,volume:6197200},{date:'November 1, 2006',open:478.76,high:479.13,low:465.26,close:467.50,volume:5318200},{date:'November 2, 2006',open:467.50,high:473.73,low:466.38,close:469.91,volume:5040900},{date:'November 3, 2006',open:472.23,high:473.75,low:465.06,close:471.80,volume:4844200},{date:'November 6, 2006',open:473.77,high:479.66,low:472.33,close:476.95,volume:4934600},{date:'November 7, 2006',open:476.96,high:479.02,low:471.77,close:472.57,volume:4833900},{date:'November 8, 2006',open:470.35,high:481.74,low:468.60,close:475.00,volume:7872700},{date:'November 9, 2006',open:476.50,high:479.49,low:471.86,close:472.63,volume:4811700},{date:'November 10, 2006',open:473.78,high:474.72,low:470.29,close:473.55,volume:2742300},{date:'November 13, 2006',open:474.90,high:481.17,low:474.14,close:481.03,volume:4293600},{date:'November 14, 2006',open:480.70,high:489.95,low:480.50,close:489.30,volume:7053200},{date:'November 15, 2006',open:493.43,high:499.85,low:491.93,close:491.93,volume:8056600},{date:'November 16, 2006',open:495.00,high:497.68,low:492.56,close:495.90,volume:4893900},{date:'November 17, 2006',open:493.25,high:499.66,low:493.00,close:498.79,volume:5237900},{date:'November 20, 2006',open:498.40,high:498.40,low:492.65,close:495.05,volume:5002600},{date:'November 21, 2006',open:496.54,high:510.00,low:495.83,close:509.65,volume:8317200},{date:'November 22, 2006',open:510.97,high:513.00,low:505.78,close:508.01,volume:4381300},{date:'November 24, 2006',open:504.50,high:507.50,low:504.00,close:505.00,volume:1657700},{date:'November 27, 2006',open:501.37,high:501.78,low:484.75,close:484.75,volume:7194200},{date:'November 28, 2006',open:481.13,high:489.86,low:477.03,close:489.50,volume:7654400},{date:'November 29, 2006',open:494.24,high:494.74,low:482.25,close:484.65,volume:6157200},{date:'November 30, 2006',open:484.19,high:490.40,low:481.55,close:484.81,volume:5493900},{date:'December 1, 2006',open:485.98,high:488.39,low:478.50,close:480.80,volume:5545900},{date:'December 4, 2006',open:483.00,high:487.43,low:479.35,close:484.85,volume:4822600},{date:'December 5, 2006',open:487.40,high:489.44,low:484.89,close:487.00,volume:4020300},{date:'December 6, 2006',open:486.96,high:492.40,low:484.52,close:488.71,volume:4390200},{date:'December 7, 2006',open:490.23,high:491.80,low:482.42,close:482.64,volume:4597500},{date:'December 8, 2006',open:481.94,high:488.60,low:480.00,close:484.11,volume:3889900},{date:'December 11, 2006',open:484.92,high:488.90,low:483.80,close:483.93,volume:3215200},{date:'December 12, 2006',open:483.85,high:486.36,low:480.28,close:481.78,volume:4169900},{date:'December 13, 2006',open:484.69,high:485.50,low:477.02,close:478.99,volume:4591400},{date:'December 14, 2006',open:480.25,high:483.75,low:477.26,close:482.12,volume:4638000},{date:'December 15, 2006',open:482.64,high:484.11,low:479.84,close:480.30,volume:4244900},{date:'December 18, 2006',open:482.51,high:482.74,low:460.72,close:462.80,volume:7820000},{date:'December 19, 2006',open:461.72,high:469.31,low:458.50,close:468.63,volume:6428300},{date:'December 20, 2006',open:470.00,high:471.50,low:462.33,close:462.90,volume:4189500},{date:'December 21, 2006',open:464.18,high:465.25,low:452.34,close:456.20,volume:6864800},{date:'December 22, 2006',open:457.50,high:458.64,low:452.73,close:455.58,volume:3941900},{date:'December 26, 2006',open:456.52,high:459.47,low:454.59,close:457.53,volume:2024900},{date:'December 27, 2006',open:460.00,high:468.08,low:459.10,close:468.03,volume:4123500},{date:'December 28, 2006',open:467.12,high:468.58,low:462.25,close:462.56,volume:3063100},{date:'December 29, 2006',open:462.10,high:464.47,low:459.86,close:460.48,volume:2507700},{date:'January 3, 2007',open:466.00,high:476.66,low:461.11,close:467.59,volume:7527500},{date:'January 4, 2007',open:469.00,high:483.95,low:468.35,close:483.26,volume:7787700},{date:'January 5, 2007',open:482.50,high:487.50,low:478.11,close:487.19,volume:6769400},{date:'January 8, 2007',open:487.69,high:489.87,low:482.20,close:483.58,volume:4686900},{date:'January 9, 2007',open:485.45,high:488.25,low:481.20,close:485.50,volume:5339800},{date:'January 10, 2007',open:484.43,high:493.55,low:482.04,close:489.46,volume:5857600},{date:'January 11, 2007',open:497.20,high:501.75,low:496.18,close:499.72,volume:7001500},{date:'January 12, 2007',open:501.99,high:505.00,low:500.00,close:505.00,volume:4333000},{date:'January 16, 2007',open:507.55,high:513.00,low:503.30,close:504.28,volume:7446800},{date:'January 17, 2007',open:503.40,high:507.77,low:494.38,close:497.28,volume:6574900},{date:'January 18, 2007',open:494.52,high:496.48,low:487.43,close:487.83,volume:5858800},{date:'January 19, 2007',open:487.98,high:490.76,low:486.74,close:489.75,volume:4809500},{date:'January 22, 2007',open:492.50,high:492.65,low:478.50,close:480.84,volume:5305200},{date:'January 23, 2007',open:480.79,high:484.75,low:477.29,close:479.05,volume:4539600},{date:'January 24, 2007',open:484.45,high:499.54,low:483.29,close:499.07,volume:5862000},{date:'January 25, 2007',open:501.00,high:504.50,low:485.66,close:488.09,volume:6253100},{date:'January 26, 2007',open:490.93,high:497.90,low:487.03,close:495.84,volume:5415600},{date:'January 29, 2007',open:498.00,high:498.75,low:490.50,close:492.47,volume:4679300},{date:'January 30, 2007',open:494.00,high:498.00,low:491.22,close:494.32,volume:4112000},{date:'January 31, 2007',open:496.49,high:505.00,low:495.51,close:501.50,volume:8642900},{date:'February 1, 2007',open:506.00,high:506.01,low:481.53,close:481.75,volume:14373800},{date:'February 2, 2007',open:482.61,high:485.00,low:477.81,close:481.50,volume:6195000},{date:'February 5, 2007',open:477.50,high:478.00,low:466.19,close:467.16,volume:7117800},{date:'February 6, 2007',open:468.10,high:473.30,low:467.26,close:471.48,volume:5231700},{date:'February 7, 2007',open:473.82,high:474.35,low:468.78,close:470.01,volume:3781100},{date:'February 8, 2007',open:468.05,high:473.75,low:465.15,close:471.03,volume:4037100},{date:'February 9, 2007',open:471.65,high:472.68,low:461.50,close:461.89,volume:4825300},{date:'February 12, 2007',open:460.68,high:462.39,low:455.02,close:458.29,volume:5706700},{date:'February 13, 2007',open:459.16,high:462.78,low:457.26,close:459.10,volume:4008400},{date:'February 14, 2007',open:460.00,high:469.13,low:459.22,close:465.93,volume:5547300},{date:'February 15, 2007',open:466.00,high:466.13,low:460.72,close:461.47,volume:3996300},{date:'February 16, 2007',open:462.80,high:470.15,low:462.06,close:469.94,volume:5987000},{date:'February 20, 2007',open:468.47,high:472.75,low:464.71,close:472.10,volume:3978200},{date:'February 21, 2007',open:469.84,high:478.68,low:467.74,close:475.86,volume:5581000},{date:'February 22, 2007',open:478.69,high:484.24,low:474.39,close:475.85,volume:5668500},{date:'February 23, 2007',open:475.75,high:476.95,low:467.80,close:470.62,volume:3838200},{date:'February 26, 2007',open:472.83,high:475.25,low:463.75,close:464.93,volume:3911300},{date:'February 27, 2007',open:455.00,high:459.80,low:447.17,close:448.77,volume:9134700},{date:'February 28, 2007',open:450.41,high:453.67,low:443.04,close:449.45,volume:7884600},{date:'March 1, 2007',open:442.67,high:452.42,low:440.00,close:448.23,volume:8536200},{date:'March 2, 2007',open:445.11,high:448.70,low:438.68,close:438.68,volume:6527600},{date:'March 5, 2007',open:437.02,high:445.50,low:437.00,close:440.95,volume:6116300},{date:'March 6, 2007',open:447.47,high:459.00,low:447.38,close:457.55,volume:7311100},{date:'March 7, 2007',open:462.69,high:463.14,low:454.29,close:455.64,volume:6332900},{date:'March 8, 2007',open:459.22,high:465.50,low:454.10,close:454.72,volume:5271300},{date:'March 9, 2007',open:458.00,high:458.40,low:450.10,close:452.96,volume:4812300},{date:'March 12, 2007',open:452.57,high:455.25,low:451.11,close:454.75,volume:3366500},{date:'March 13, 2007',open:450.11,high:451.93,low:442.83,close:443.03,volume:6240700},{date:'March 14, 2007',open:443.23,high:448.66,low:439.00,close:448.00,volume:7882300},{date:'March 15, 2007',open:447.86,high:449.82,low:443.94,close:446.19,volume:3740000},{date:'March 16, 2007',open:445.65,high:446.70,low:439.89,close:440.85,volume:5252200},{date:'March 19, 2007',open:443.25,high:448.50,low:440.63,close:447.23,volume:5049000},{date:'March 20, 2007',open:445.79,high:447.60,low:443.60,close:445.28,volume:3291000},{date:'March 21, 2007',open:445.30,high:456.57,low:445.22,close:456.55,volume:5711000},{date:'March 22, 2007',open:455.61,high:462.17,low:452.53,close:462.04,volume:5528300},{date:'March 23, 2007',open:461.45,high:463.39,low:457.08,close:461.83,volume:4025500},{date:'March 26, 2007',open:460.55,high:465.00,low:455.62,close:465.00,volume:4633100},{date:'March 27, 2007',open:463.55,high:465.23,low:460.34,close:463.62,volume:3201200},{date:'March 28, 2007',open:461.87,high:465.44,low:460.15,close:461.88,volume:4450800},{date:'March 29, 2007',open:464.55,high:466.00,low:455.00,close:460.92,volume:3884400},{date:'March 30, 2007',open:462.10,high:463.40,low:456.14,close:458.16,volume:3264400},{date:'April 2, 2007',open:457.76,high:458.53,low:452.12,close:458.53,volume:3394400},{date:'April 3, 2007',open:464.05,high:474.25,low:464.00,close:472.60,volume:6328700},{date:'April 4, 2007',open:472.14,high:473.00,low:469.58,close:471.02,volume:3703800},{date:'April 5, 2007',open:471.30,high:472.09,low:469.62,close:471.51,volume:2679600},{date:'April 9, 2007',open:472.98,high:473.00,low:465.59,close:468.21,volume:2997000},{date:'April 10, 2007',open:467.09,high:470.79,low:465.16,close:466.50,volume:2946100},{date:'April 11, 2007',open:466.06,high:469.40,low:462.61,close:464.53,volume:3751400},{date:'April 12, 2007',open:464.00,high:468.00,low:462.24,close:467.39,volume:2670000},{date:'April 13, 2007',open:468.45,high:468.77,low:463.36,close:466.29,volume:2652800},{date:'April 16, 2007',open:468.46,high:476.99,low:468.15,close:474.27,volume:4980400},{date:'April 17, 2007',open:473.80,high:476.39,low:471.60,close:472.80,volume:3064500},{date:'April 18, 2007',open:471.26,high:479.90,low:469.53,close:476.01,volume:5495900},{date:'April 19, 2007',open:474.50,high:481.95,low:469.59,close:471.65,volume:7656400},{date:'April 20, 2007',open:490.52,high:492.50,low:482.02,close:482.48,volume:11352600},{date:'April 23, 2007',open:480.10,high:485.00,low:478.26,close:479.08,volume:5440400},{date:'April 24, 2007',open:478.61,high:479.98,low:475.55,close:477.53,volume:3648500},{date:'April 25, 2007',open:480.00,high:481.37,low:476.11,close:477.99,volume:3860800},{date:'April 26, 2007',open:478.10,high:484.45,low:477.11,close:481.18,volume:4010900},{date:'April 27, 2007',open:480.07,high:482.40,low:478.33,close:479.01,volume:2890800},{date:'April 30, 2007',open:479.15,high:481.35,low:471.38,close:471.38,volume:3538700},{date:'May 1, 2007',open:472.19,high:472.81,low:464.17,close:469.00,volume:3571300},{date:'May 2, 2007',open:468.65,high:471.08,low:465.73,close:465.78,volume:2981100},{date:'May 3, 2007',open:466.22,high:474.07,low:465.29,close:473.23,volume:3528800},{date:'May 4, 2007',open:470.12,high:474.84,low:465.88,close:471.12,volume:3769300},{date:'May 7, 2007',open:472.14,high:472.82,low:466.47,close:467.27,volume:2994900},{date:'May 8, 2007',open:466.13,high:468.17,low:464.73,close:466.81,volume:2869700},{date:'May 9, 2007',open:466.15,high:471.73,low:463.88,close:469.25,volume:3867800},{date:'May 10, 2007',open:467.04,high:469.49,low:461.02,close:461.47,volume:3654800},{date:'May 11, 2007',open:461.83,high:467.00,low:461.00,close:466.74,volume:2793400},{date:'May 14, 2007',open:465.48,high:467.51,low:460.00,close:461.78,volume:3014400},{date:'May 15, 2007',open:461.96,high:462.54,low:457.41,close:458.00,volume:4063800},{date:'May 16, 2007',open:462.00,high:473.14,low:459.02,close:472.61,volume:6296800},{date:'May 17, 2007',open:472.46,high:475.22,low:470.81,close:470.96,volume:4570400},{date:'May 18, 2007',open:472.03,high:472.70,low:469.75,close:470.32,volume:3297900},{date:'May 21, 2007',open:469.53,high:479.20,low:466.72,close:470.60,volume:6065000},{date:'May 22, 2007',open:473.00,high:479.01,low:473.00,close:475.86,volume:3770000},{date:'May 23, 2007',open:480.82,high:483.41,low:473.75,close:473.97,volume:4842400},{date:'May 24, 2007',open:475.15,high:479.20,low:471.50,close:474.33,volume:4117800},{date:'May 25, 2007',open:479.70,high:484.95,low:477.27,close:483.52,volume:5246400},{date:'May 29, 2007',open:485.00,high:491.80,low:484.00,close:487.11,volume:5147500},{date:'May 30, 2007',open:484.50,high:498.84,low:483.00,close:498.60,volume:6862700},{date:'May 31, 2007',open:500.56,high:508.78,low:497.06,close:497.91,volume:8599800},{date:'June 1, 2007',open:501.00,high:505.02,low:497.93,close:500.40,volume:4657400},{date:'June 4, 2007',open:497.91,high:510.51,low:497.59,close:507.07,volume:7036300},{date:'June 5, 2007',open:509.75,high:519.00,low:506.61,close:518.84,volume:10149600},{date:'June 6, 2007',open:516.75,high:520.78,low:515.26,close:518.25,volume:7690300},{date:'June 7, 2007',open:519.75,high:526.50,low:512.51,close:515.06,volume:10488400},{date:'June 8, 2007',open:516.20,high:519.64,low:509.46,close:515.49,volume:6232600},{date:'June 11, 2007',open:514.02,high:518.25,low:510.00,close:511.34,volume:4539500},{date:'June 12, 2007',open:508.71,high:511.67,low:503.17,close:504.77,volume:6147700},{date:'June 13, 2007',open:507.09,high:508.54,low:498.69,close:505.24,volume:6943300},{date:'June 14, 2007',open:505.38,high:505.88,low:501.70,close:502.84,volume:4523500},{date:'June 15, 2007',open:508.19,high:509.00,low:501.23,close:505.89,volume:5944900},{date:'June 18, 2007',open:506.18,high:516.00,low:504.24,close:515.20,volume:4763800},{date:'June 19, 2007',open:514.01,high:517.25,low:511.54,close:514.31,volume:4263400},{date:'June 20, 2007',open:516.96,high:518.75,low:509.06,close:509.97,volume:4256300},{date:'June 21, 2007',open:510.98,high:515.29,low:506.28,close:514.11,volume:4350100},{date:'June 22, 2007',open:516.42,high:524.99,low:516.10,close:524.98,volume:6768200},{date:'June 25, 2007',open:528.98,high:534.99,low:523.38,close:527.42,volume:7791000},{date:'June 26, 2007',open:532.73,high:533.20,low:526.24,close:530.26,volume:5488700},{date:'June 27, 2007',open:525.00,high:527.99,low:519.56,close:526.29,volume:6023400},{date:'June 28, 2007',open:524.88,high:529.50,low:523.80,close:525.01,volume:3814400},{date:'June 29, 2007',open:526.02,high:527.40,low:519.46,close:522.70,volume:3813400},{date:'July 2, 2007',open:525.49,high:531.85,low:524.20,close:530.38,volume:3362800},{date:'July 3, 2007',open:531.06,high:534.40,low:527.50,close:534.34,volume:1827000},{date:'July 5, 2007',open:535.56,high:544.40,low:532.15,close:541.63,volume:4867300},{date:'July 6, 2007',open:541.25,high:543.87,low:538.73,close:539.40,volume:2705900},{date:'July 9, 2007',open:543.00,high:548.74,low:540.26,close:542.56,volume:3617000},{date:'July 10, 2007',open:543.79,high:547.00,low:541.65,close:543.34,volume:3760000},{date:'July 11, 2007',open:543.61,high:546.50,low:540.01,close:544.47,volume:3267200},{date:'July 12, 2007',open:545.86,high:547.32,low:540.22,close:545.33,volume:3404000},{date:'July 13, 2007',open:547.91,high:552.67,low:547.25,close:552.16,volume:5033300},{date:'July 16, 2007',open:550.30,high:558.58,low:549.31,close:552.99,volume:6550000},{date:'July 17, 2007',open:555.04,high:557.73,low:552.38,close:555.00,volume:4211200},{date:'July 18, 2007',open:553.89,high:554.50,low:543.81,close:549.50,volume:5973900},{date:'July 19, 2007',open:553.46,high:553.52,low:542.24,close:548.59,volume:6477800},{date:'July 20, 2007',open:511.90,high:523.18,low:509.50,close:520.12,volume:16026500},{date:'July 23, 2007',open:519.01,high:520.00,low:512.15,close:512.51,volume:6227900},{date:'July 24, 2007',open:509.30,high:518.69,low:507.11,close:514.00,volume:5346600},{date:'July 25, 2007',open:516.98,high:517.02,low:505.56,close:509.76,volume:5453500},{date:'July 26, 2007',open:508.74,high:512.59,low:498.88,close:508.00,volume:6779400},{date:'July 27, 2007',open:508.53,high:516.62,low:505.50,close:511.89,volume:5361400},{date:'July 30, 2007',open:512.92,high:519.34,low:510.50,close:516.11,volume:3798800},{date:'July 31, 2007',open:520.23,high:520.44,low:510.00,close:510.00,volume:4159100},{date:'August 1, 2007',open:510.50,high:516.51,low:508.14,close:512.94,volume:4329800},{date:'August 2, 2007',open:513.72,high:514.99,low:509.00,close:511.01,volume:3117100},{date:'August 3, 2007',open:510.05,high:513.20,low:503.00,close:503.00,volume:3090600},{date:'August 6, 2007',open:503.00,high:510.15,low:502.50,close:510.00,volume:3582100},{date:'August 7, 2007',open:509.75,high:519.88,low:509.04,close:516.02,volume:4191400},{date:'August 8, 2007',open:519.34,high:525.78,low:517.09,close:525.78,volume:3955500},{date:'August 9, 2007',open:520.80,high:526.82,low:514.63,close:514.73,volume:4764500},{date:'August 10, 2007',open:510.18,high:518.72,low:505.63,close:515.75,volume:5000100},{date:'August 13, 2007',open:519.54,high:519.75,low:513.03,close:515.50,volume:3022500},{date:'August 14, 2007',open:515.17,high:517.40,low:508.00,close:508.60,volume:3574300},{date:'August 15, 2007',open:509.00,high:511.69,low:496.71,close:497.55,volume:5337100},{date:'August 16, 2007',open:492.02,high:496.43,low:480.46,close:491.52,volume:8438400},{date:'August 17, 2007',open:497.44,high:501.00,low:491.65,close:500.04,volume:5236600},{date:'August 20, 2007',open:502.46,high:502.56,low:496.00,close:497.92,volume:2589800},{date:'August 21, 2007',open:498.94,high:508.16,low:497.77,close:506.61,volume:3546200},{date:'August 22, 2007',open:509.96,high:516.25,low:509.25,close:512.75,volume:3076000},{date:'August 23, 2007',open:516.00,high:516.13,low:507.00,close:512.19,volume:2995400},{date:'August 24, 2007',open:512.61,high:515.55,low:508.50,close:515.00,volume:2447200},{date:'August 27, 2007',open:514.43,high:517.45,low:511.40,close:513.26,volume:2271800},{date:'August 28, 2007',open:511.53,high:514.98,low:505.79,close:506.40,volume:2889400},{date:'August 29, 2007',open:507.84,high:513.30,low:507.23,close:512.88,volume:2476800},{date:'August 30, 2007',open:512.36,high:515.40,low:510.58,close:511.40,volume:2583400},{date:'August 31, 2007',open:513.10,high:516.50,low:511.47,close:515.25,volume:2681700},{date:'September 4, 2007',open:515.02,high:528.00,low:514.62,close:525.15,volume:3633900},{date:'September 5, 2007',open:523.40,high:529.48,low:522.25,close:527.80,volume:3241700},{date:'September 6, 2007',open:529.36,high:529.83,low:518.24,close:523.52,volume:3576700},{date:'September 7, 2007',open:517.86,high:521.24,low:516.80,close:519.35,volume:3590700},{date:'September 10, 2007',open:521.28,high:522.07,low:510.88,close:514.48,volume:3198900},{date:'September 11, 2007',open:516.99,high:521.65,low:515.73,close:521.33,volume:2680300},{date:'September 12, 2007',open:520.53,high:527.98,low:519.00,close:522.65,volume:2946000},{date:'September 13, 2007',open:524.06,high:527.21,low:523.22,close:524.78,volume:1873300},{date:'September 14, 2007',open:523.20,high:530.27,low:522.22,close:528.75,volume:2723500},{date:'September 17, 2007',open:526.53,high:529.28,low:524.07,close:525.30,volume:2140600},{date:'September 18, 2007',open:526.52,high:537.25,low:524.27,close:535.27,volume:4107700},{date:'September 19, 2007',open:539.27,high:549.45,low:538.86,close:546.85,volume:5477500},{date:'September 20, 2007',open:547.00,high:556.80,low:546.03,close:552.83,volume:5485600},{date:'September 21, 2007',open:556.34,high:560.79,low:552.83,close:560.10,volume:6957000},{date:'September 24, 2007',open:561.00,high:571.46,low:560.00,close:568.02,volume:5210800},{date:'September 25, 2007',open:564.00,high:569.56,low:562.86,close:569.00,volume:2647400},{date:'September 26, 2007',open:570.40,high:571.79,low:563.81,close:568.16,volume:3234400},{date:'September 27, 2007',open:571.73,high:571.74,low:565.78,close:567.50,volume:1980100},{date:'September 28, 2007',open:567.00,high:569.55,low:564.12,close:567.27,volume:2448000},{date:'October 1, 2007',open:569.97,high:584.35,low:569.61,close:582.55,volume:4640000},{date:'October 2, 2007',open:583.38,high:596.81,low:580.01,close:584.39,volume:6838000},{date:'October 3, 2007',open:586.25,high:588.99,low:580.36,close:584.02,volume:3806000},{date:'October 4, 2007',open:585.09,high:585.09,low:577.06,close:579.03,volume:2931500},{date:'October 5, 2007',open:587.11,high:596.00,low:587.01,close:594.05,volume:4895400},{date:'October 8, 2007',open:595.00,high:610.26,low:593.95,close:609.62,volume:4980400},{date:'October 9, 2007',open:615.11,high:623.78,low:608.39,close:615.18,volume:8533500},{date:'October 10, 2007',open:621.36,high:625.68,low:616.80,close:625.39,volume:5190300},{date:'October 11, 2007',open:633.64,high:641.41,low:609.00,close:622.00,volume:11509700},{date:'October 12, 2007',open:623.98,high:638.40,low:618.24,close:637.39,volume:6652800},{date:'October 15, 2007',open:638.47,high:639.86,low:615.55,close:620.11,volume:6838600},{date:'October 16, 2007',open:618.49,high:625.92,low:611.99,close:616.00,volume:5661300},{date:'October 17, 2007',open:630.45,high:634.00,low:621.59,close:633.48,volume:5784700},{date:'October 18, 2007',open:635.41,high:641.37,low:628.50,close:639.62,volume:8650500},{date:'October 19, 2007',open:654.56,high:658.49,low:643.23,close:644.71,volume:14154000},{date:'October 22, 2007',open:638.67,high:655.00,low:636.28,close:650.75,volume:6490000},{date:'October 23, 2007',open:661.25,high:677.60,low:660.00,close:675.77,volume:6575800},{date:'October 24, 2007',open:672.71,high:677.47,low:659.56,close:675.82,volume:7324000},{date:'October 25, 2007',open:678.68,high:678.97,low:663.55,close:668.51,volume:5687900},{date:'October 26, 2007',open:674.03,high:676.54,low:668.06,close:674.60,volume:3258600},{date:'October 29, 2007',open:677.77,high:680.00,low:672.09,close:679.23,volume:3008400},{date:'October 30, 2007',open:677.51,high:699.91,low:677.51,close:694.77,volume:6798600},{date:'October 31, 2007',open:700.69,high:707.00,low:696.04,close:707.00,volume:6525900},{date:'November 1, 2007',open:702.59,high:713.72,low:701.78,close:703.21,volume:6407200},{date:'November 2, 2007',open:710.51,high:713.58,low:697.34,close:711.25,volume:5639100},{date:'November 5, 2007',open:706.99,high:730.23,low:706.07,close:725.65,volume:8778300},{date:'November 6, 2007',open:737.56,high:741.79,low:725.00,close:741.79,volume:8267700},{date:'November 7, 2007',open:741.13,high:747.24,low:723.14,close:732.94,volume:7997400},{date:'November 8, 2007',open:734.60,high:734.89,low:677.18,close:693.84,volume:15612500},{date:'November 9, 2007',open:675.78,high:681.88,low:661.21,close:663.97,volume:10487700},{date:'November 12, 2007',open:657.74,high:669.93,low:626.21,close:632.07,volume:10060700},{date:'November 13, 2007',open:644.99,high:660.92,low:642.00,close:660.55,volume:8181000},{date:'November 14, 2007',open:673.28,high:675.49,low:636.27,close:641.68,volume:7739800},{date:'November 15, 2007',open:638.57,high:647.50,low:624.00,close:629.65,volume:6871200},{date:'November 16, 2007',open:633.94,high:635.49,low:616.02,close:633.63,volume:8813800},{date:'November 19, 2007',open:629.59,high:636.77,low:618.50,close:625.85,volume:5459400},{date:'November 20, 2007',open:636.48,high:659.10,low:632.87,close:648.54,volume:9527300},{date:'November 21, 2007',open:643.77,high:669.97,low:642.08,close:660.52,volume:6931900},{date:'November 23, 2007',open:670.00,high:678.28,low:668.11,close:676.70,volume:2558000},{date:'November 26, 2007',open:680.20,high:693.40,low:665.00,close:666.00,volume:6420500},{date:'November 27, 2007',open:674.80,high:676.43,low:650.26,close:673.57,volume:8805500},{date:'November 28, 2007',open:682.11,high:694.30,low:672.14,close:692.26,volume:7750600},{date:'November 29, 2007',open:690.75,high:702.79,low:687.77,close:697.00,volume:6167400},{date:'November 30, 2007',open:711.00,high:711.06,low:682.11,close:693.00,volume:7697600},{date:'December 3, 2007',open:691.01,high:695.00,low:681.14,close:681.53,volume:4269900},{date:'December 4, 2007',open:678.31,high:692.00,low:677.12,close:684.16,volume:4157500},{date:'December 5, 2007',open:692.73,high:698.93,low:687.50,close:698.51,volume:4117400},{date:'December 6, 2007',open:697.80,high:716.56,low:697.01,close:715.26,volume:4850900},{date:'December 7, 2007',open:714.99,high:718.00,low:710.50,close:714.87,volume:3785200},{date:'December 10, 2007',open:715.99,high:724.80,low:714.00,close:718.42,volume:3184500},{date:'December 11, 2007',open:719.94,high:720.99,low:698.78,close:699.20,volume:5414700},{date:'December 12, 2007',open:714.00,high:714.32,low:688.50,close:699.35,volume:5991000},{date:'December 13, 2007',open:696.31,high:697.62,low:681.21,close:694.05,volume:5013900},{date:'December 14, 2007',open:687.51,high:699.70,low:687.26,close:689.96,volume:3636600},{date:'December 17, 2007',open:688.00,high:695.42,low:663.67,close:669.23,volume:5453000},{date:'December 18, 2007',open:674.16,high:676.71,low:652.50,close:673.35,volume:7029600},{date:'December 19, 2007',open:674.21,high:679.50,low:669.00,close:677.37,volume:4397100},{date:'December 20, 2007',open:685.83,high:691.00,low:680.61,close:689.69,volume:4295200},{date:'December 21, 2007',open:697.88,high:699.26,low:693.24,close:696.69,volume:5103700},{date:'December 24, 2007',open:694.99,high:700.73,low:693.06,close:700.73,volume:1503500},{date:'December 26, 2007',open:698.99,high:713.22,low:698.21,close:710.84,volume:2500600},{date:'December 27, 2007',open:707.07,high:716.00,low:700.74,close:700.74,volume:2921800},{date:'December 28, 2007',open:704.93,high:707.95,low:696.54,close:702.53,volume:2503100},{date:'December 31, 2007',open:698.57,high:702.49,low:690.58,close:691.48,volume:2336300},{date:'January 2, 2008',open:692.87,high:697.37,low:677.73,close:685.19,volume:4247000},{date:'January 3, 2008',open:685.26,high:686.85,low:676.52,close:685.33,volume:3202600},{date:'January 4, 2008',open:679.69,high:680.96,low:655.00,close:657.00,volume:5273500},{date:'January 7, 2008',open:653.94,high:662.28,low:637.35,close:649.25,volume:6282100},{date:'January 8, 2008',open:653.00,high:659.96,low:631.00,close:631.68,volume:5248700},{date:'January 9, 2008',open:630.04,high:653.34,low:622.51,close:653.20,volume:6677200},{date:'January 10, 2008',open:645.01,high:657.20,low:640.11,close:646.73,volume:6207900},{date:'January 11, 2008',open:642.70,high:649.47,low:630.11,close:638.25,volume:4946700},{date:'January 14, 2008',open:651.14,high:657.40,low:645.25,close:653.82,volume:4355600},{date:'January 15, 2008',open:645.90,high:649.05,low:635.38,close:637.65,volume:5290800},{date:'January 16, 2008',open:628.97,high:639.99,low:601.93,close:615.95,volume:10478800},{date:'January 17, 2008',open:620.76,high:625.74,low:598.01,close:600.79,volume:8104500},{date:'January 18, 2008',open:608.36,high:609.99,low:598.45,close:600.25,volume:8265800},{date:'January 22, 2008',open:562.03,high:597.50,low:561.20,close:584.35,volume:9000100},{date:'January 23, 2008',open:560.71,high:568.00,low:519.00,close:548.62,volume:16687700},{date:'January 24, 2008',open:558.80,high:579.69,low:554.14,close:574.49,volume:9156200},{date:'January 25, 2008',open:591.81,high:595.00,low:566.18,close:566.40,volume:6831100},{date:'January 28, 2008',open:570.97,high:572.24,low:548.60,close:555.98,volume:5752900},{date:'January 29, 2008',open:560.47,high:561.33,low:540.67,close:550.52,volume:6028300},{date:'January 30, 2008',open:549.19,high:560.43,low:543.51,close:548.27,volume:7817400},{date:'January 31, 2008',open:539.01,high:573.00,low:534.29,close:564.30,volume:10447200},{date:'February 1, 2008',open:528.67,high:536.67,low:510.00,close:515.90,volume:16711900},{date:'February 4, 2008',open:509.07,high:512.78,low:492.55,close:495.43,volume:12923200},{date:'February 5, 2008',open:489.43,high:509.00,low:488.52,close:506.80,volume:11023400},{date:'February 6, 2008',open:511.14,high:511.17,low:497.93,close:501.71,volume:7492300},{date:'February 7, 2008',open:496.86,high:514.19,low:494.76,close:504.95,volume:7830900},{date:'February 8, 2008',open:509.41,high:517.73,low:508.70,close:516.69,volume:6739400},{date:'February 11, 2008',open:520.52,high:523.71,low:513.40,close:521.16,volume:5758900},{date:'February 12, 2008',open:523.39,high:530.60,low:513.03,close:518.09,volume:6576800},{date:'February 13, 2008',open:522.50,high:534.99,low:518.69,close:534.62,volume:6090200},{date:'February 14, 2008',open:538.35,high:541.04,low:531.00,close:532.25,volume:6400800},{date:'February 15, 2008',open:528.31,high:532.66,low:524.33,close:529.64,volume:5080100},{date:'February 19, 2008',open:534.94,high:535.06,low:506.50,close:508.95,volume:6259400},{date:'February 20, 2008',open:503.51,high:511.01,low:498.82,close:509.00,volume:6556700},{date:'February 21, 2008',open:512.85,high:513.21,low:499.50,close:502.86,volume:5527300},{date:'February 22, 2008',open:502.06,high:509.00,low:497.55,close:507.80,volume:5445500},{date:'February 25, 2008',open:505.95,high:506.50,low:485.74,close:486.44,volume:8188300},{date:'February 26, 2008',open:461.20,high:466.47,low:446.85,close:464.19,volume:22296900},{date:'February 27, 2008',open:460.13,high:475.49,low:459.64,close:472.86,volume:9992200},{date:'February 28, 2008',open:470.50,high:479.09,low:467.36,close:475.39,volume:6308700},{date:'February 29, 2008',open:471.87,high:479.74,low:464.65,close:471.18,volume:9281700},{date:'March 3, 2008',open:471.51,high:472.72,low:450.11,close:457.02,volume:7495200},{date:'March 4, 2008',open:450.95,high:453.36,low:435.78,close:444.60,volume:13472400},{date:'March 5, 2008',open:445.25,high:454.17,low:444.00,close:447.70,volume:7288500},{date:'March 6, 2008',open:447.69,high:453.30,low:431.18,close:432.70,volume:7348000},{date:'March 7, 2008',open:428.88,high:440.00,low:426.24,close:433.35,volume:7930200},{date:'March 10, 2008',open:428.83,high:431.00,low:413.04,close:413.62,volume:7871400},{date:'March 11, 2008',open:425.26,high:440.15,low:424.65,close:439.84,volume:8520100},{date:'March 12, 2008',open:440.01,high:447.88,low:438.07,close:440.18,volume:6481500},{date:'March 13, 2008',open:432.67,high:446.98,low:428.78,close:443.01,volume:7647300},{date:'March 14, 2008',open:442.98,high:449.34,low:430.62,close:437.92,volume:6448000},{date:'March 17, 2008',open:427.99,high:433.71,low:412.11,close:419.87,volume:7794500},{date:'March 18, 2008',open:428.98,high:440.84,low:425.53,close:439.16,volume:7103700},{date:'March 19, 2008',open:441.11,high:447.50,low:431.67,close:432.00,volume:6062400},{date:'March 20, 2008',open:427.32,high:435.70,low:417.50,close:433.55,volume:9522900},{date:'March 24, 2008',open:438.43,high:465.78,low:437.72,close:460.56,volume:6714900},{date:'March 25, 2008',open:457.46,high:457.47,low:446.00,close:450.78,volume:5710500},{date:'March 26, 2008',open:452.59,high:462.87,low:449.29,close:458.19,volume:4919500},{date:'March 27, 2008',open:446.00,high:448.61,low:440.49,close:444.08,volume:5665800},{date:'March 28, 2008',open:447.46,high:453.57,low:434.31,close:438.08,volume:4322700},{date:'March 31, 2008',open:435.64,high:442.69,low:432.01,close:440.47,volume:4368800},{date:'April 1, 2008',open:447.74,high:466.50,low:446.87,close:465.71,volume:6027000},{date:'April 2, 2008',open:469.90,high:475.74,low:460.39,close:465.70,volume:5940600},{date:'April 3, 2008',open:461.73,high:463.29,low:448.13,close:455.12,volume:6391200},{date:'April 4, 2008',open:457.01,high:477.83,low:456.20,close:471.09,volume:5843300},{date:'April 7, 2008',open:477.03,high:485.44,low:473.53,close:476.82,volume:5800900},{date:'April 8, 2008',open:473.04,high:474.14,low:462.01,close:467.81,volume:4493800},{date:'April 9, 2008',open:469.13,high:472.00,low:457.54,close:464.19,volume:5961200},{date:'April 10, 2008',open:464.96,high:473.86,low:461.85,close:469.08,volume:5049400},{date:'April 11, 2008',open:464.07,high:467.26,low:455.01,close:457.45,volume:3791600},{date:'April 14, 2008',open:457.16,high:457.45,low:450.15,close:451.66,volume:3766400},{date:'April 15, 2008',open:458.13,high:459.72,low:443.72,close:446.84,volume:4436400},{date:'April 16, 2008',open:444.40,high:458.28,low:441.00,close:455.03,volume:7453000},{date:'April 17, 2008',open:455.63,high:459.37,low:446.52,close:449.54,volume:7133100},{date:'April 18, 2008',open:535.21,high:547.70,low:524.77,close:539.41,volume:16860300},{date:'April 21, 2008',open:539.39,high:542.59,low:530.29,close:537.79,volume:7254200},{date:'April 22, 2008',open:537.57,high:560.83,low:537.56,close:555.00,volume:7843800},{date:'April 23, 2008',open:557.94,high:559.31,low:540.95,close:546.49,volume:4798100},{date:'April 24, 2008',open:551.29,high:554.49,low:540.02,close:543.04,volume:4068400},{date:'April 25, 2008',open:549.02,high:553.00,low:542.73,close:544.06,volume:4022900},{date:'April 28, 2008',open:545.88,high:556.81,low:539.00,close:552.12,volume:3954200},{date:'April 29, 2008',open:550.83,high:563.40,low:550.01,close:558.47,volume:4276200},{date:'April 30, 2008',open:562.21,high:584.86,low:558.47,close:574.29,volume:7784100},{date:'May 1, 2008',open:578.31,high:594.93,low:576.97,close:593.08,volume:6555200},{date:'May 2, 2008',open:598.49,high:602.45,low:579.30,close:581.29,volume:6879300},{date:'May 5, 2008',open:598.86,high:599.00,low:587.13,close:594.90,volume:6091000},{date:'May 6, 2008',open:591.00,high:592.00,low:583.00,close:586.36,volume:4537100},{date:'May 7, 2008',open:590.27,high:599.49,low:576.43,close:579.00,volume:6541200},{date:'May 8, 2008',open:586.20,high:589.30,low:578.91,close:583.01,volume:5051200},{date:'May 9, 2008',open:579.00,high:585.00,low:571.30,close:573.20,volume:4446100},{date:'May 12, 2008',open:574.75,high:586.75,low:568.91,close:584.94,volume:4821300},{date:'May 13, 2008',open:586.23,high:587.95,low:578.55,close:583.00,volume:5061600},{date:'May 14, 2008',open:586.49,high:591.19,low:575.25,close:576.30,volume:4326600},{date:'May 15, 2008',open:579.00,high:582.95,low:575.61,close:581.00,volume:4296000},{date:'May 16, 2008',open:581.43,high:584.68,low:578.32,close:580.07,volume:4022100},{date:'May 19, 2008',open:578.55,high:588.88,low:573.52,close:577.52,volume:5565300},{date:'May 20, 2008',open:574.63,high:582.48,low:572.91,close:578.60,volume:3246600},{date:'May 21, 2008',open:578.52,high:581.41,low:547.89,close:549.99,volume:6301600},{date:'May 22, 2008',open:551.95,high:554.21,low:540.25,close:549.46,volume:4312200},{date:'May 23, 2008',open:546.96,high:553.00,low:537.81,close:544.62,volume:4394600},{date:'May 27, 2008',open:544.96,high:562.60,low:543.85,close:560.90,volume:3610700},{date:'May 28, 2008',open:567.94,high:571.49,low:561.10,close:568.24,volume:3976800},{date:'May 29, 2008',open:574.79,high:585.88,low:573.20,close:583.00,volume:4754900},{date:'May 30, 2008',open:583.47,high:589.92,low:581.30,close:585.80,volume:3136900},{date:'June 2, 2008',open:582.50,high:583.89,low:571.27,close:575.00,volume:3615700},{date:'June 3, 2008',open:576.50,high:580.50,low:560.61,close:567.30,volume:4268700},{date:'June 4, 2008',open:565.33,high:578.00,low:564.55,close:572.22,volume:3344000},{date:'June 5, 2008',open:577.08,high:588.04,low:576.21,close:586.30,volume:3897400},{date:'June 6, 2008',open:579.75,high:580.72,low:567.00,close:567.00,volume:4679900},{date:'June 9, 2008',open:568.06,high:570.00,low:545.40,close:557.87,volume:5267200},{date:'June 10, 2008',open:549.56,high:558.82,low:546.78,close:554.17,volume:3620100},{date:'June 11, 2008',open:556.24,high:557.34,low:544.46,close:545.20,volume:3776700},{date:'June 12, 2008',open:548.76,high:558.00,low:546.88,close:552.95,volume:5390700},{date:'June 13, 2008',open:561.49,high:575.70,low:561.34,close:571.51,volume:6060500},{date:'June 16, 2008',open:566.50,high:579.10,low:566.50,close:572.81,volume:3506400},{date:'June 17, 2008',open:576.35,high:578.07,low:568.38,close:569.46,volume:3434600},{date:'June 18, 2008',open:564.51,high:568.99,low:559.16,close:562.38,volume:3285800},{date:'June 19, 2008',open:555.35,high:563.78,low:550.81,close:560.20,volume:5587600},{date:'June 20, 2008',open:556.98,high:556.98,low:544.51,close:546.43,volume:5830600},{date:'June 23, 2008',open:545.36,high:553.15,low:542.02,close:545.21,volume:3597200},{date:'June 24, 2008',open:545.14,high:551.19,low:535.10,close:542.30,volume:4637000},{date:'June 25, 2008',open:544.97,high:557.80,low:543.67,close:551.00,volume:3911100},{date:'June 26, 2008',open:544.10,high:544.93,low:528.26,close:528.82,volume:5549400},{date:'June 27, 2008',open:527.68,high:530.00,low:515.09,close:528.07,volume:5073700},{date:'June 30, 2008',open:532.47,high:538.00,low:523.06,close:526.42,volume:3683000},{date:'July 1, 2008',open:519.58,high:536.72,low:517.00,close:534.73,volume:4874800},{date:'July 2, 2008',open:536.51,high:540.38,low:526.06,close:527.04,volume:4148700},{date:'July 3, 2008',open:530.88,high:539.23,low:527.50,close:537.00,volume:2368800},{date:'July 7, 2008',open:542.30,high:549.00,low:535.60,close:543.91,volume:4198600},{date:'July 8, 2008',open:545.99,high:555.19,low:540.00,close:554.53,volume:4406200},{date:'July 9, 2008',open:550.76,high:555.68,low:540.73,close:541.55,volume:4081100},{date:'July 10, 2008',open:545.00,high:549.50,low:530.72,close:540.57,volume:4263500},{date:'July 11, 2008',open:536.50,high:539.50,low:519.43,close:533.80,volume:4822900},{date:'July 14, 2008',open:539.00,high:540.06,low:515.45,close:521.62,volume:4398500},{date:'July 15, 2008',open:516.28,high:527.50,low:501.10,close:516.09,volume:6015000},{date:'July 16, 2008',open:514.04,high:536.50,low:510.60,close:535.60,volume:4674700},{date:'July 17, 2008',open:534.16,high:537.05,low:524.50,close:533.44,volume:5491200},{date:'July 18, 2008',open:498.35,high:498.98,low:478.19,close:481.32,volume:10783800},{date:'July 21, 2008',open:480.88,high:484.09,low:465.70,close:468.80,volume:5802900},{date:'July 22, 2008',open:466.72,high:480.25,low:465.60,close:477.11,volume:4619400},{date:'July 23, 2008',open:481.61,high:497.23,low:478.10,close:489.22,volume:4695400},{date:'July 24, 2008',open:496.70,high:496.87,low:475.62,close:475.62,volume:3466300},{date:'July 25, 2008',open:486.49,high:493.13,low:481.50,close:491.98,volume:3064300},{date:'July 28, 2008',open:492.09,high:492.09,low:475.13,close:477.12,volume:3121800},{date:'July 29, 2008',open:479.30,high:487.26,low:478.00,close:483.11,volume:2711800},{date:'July 30, 2008',open:485.50,high:486.02,low:472.81,close:482.70,volume:3459200},{date:'July 31, 2008',open:474.56,high:480.89,low:471.44,close:473.75,volume:2827400},{date:'August 1, 2008',open:472.51,high:473.22,low:462.50,close:467.86,volume:2969000},{date:'August 4, 2008',open:468.12,high:473.01,low:461.90,close:463.00,volume:2459100},{date:'August 5, 2008',open:467.59,high:480.08,low:466.33,close:479.85,volume:3510200},{date:'August 6, 2008',open:478.37,high:489.77,low:472.51,close:486.34,volume:3346000},{date:'August 7, 2008',open:482.00,high:484.00,low:476.41,close:479.12,volume:2711600},{date:'August 8, 2008',open:480.15,high:495.75,low:475.69,close:495.01,volume:3700900},{date:'August 11, 2008',open:492.47,high:508.88,low:491.78,close:500.84,volume:4199600},{date:'August 12, 2008',open:502.00,high:506.13,low:498.00,close:502.61,volume:2731100},{date:'August 13, 2008',open:501.60,high:503.54,low:493.88,close:500.03,volume:3602700},{date:'August 14, 2008',open:497.70,high:507.61,low:496.29,close:505.49,volume:2888200},{date:'August 15, 2008',open:506.99,high:510.66,low:505.50,close:510.15,volume:3487200},{date:'August 18, 2008',open:509.84,high:510.00,low:495.51,close:498.30,volume:3264000},{date:'August 19, 2008',open:490.43,high:498.28,low:486.63,close:490.50,volume:2970000},{date:'August 20, 2008',open:494.72,high:496.69,low:482.57,close:485.00,volume:3969700},{date:'August 21, 2008',open:482.92,high:489.90,low:479.27,close:486.53,volume:3437900},{date:'August 22, 2008',open:491.50,high:494.88,low:489.48,close:490.59,volume:2264900},{date:'August 25, 2008',open:486.11,high:497.00,low:481.50,close:483.01,volume:1975500},{date:'August 26, 2008',open:483.46,high:483.46,low:470.59,close:474.16,volume:3182200},{date:'August 27, 2008',open:473.73,high:474.83,low:464.84,close:468.58,volume:4354700},{date:'August 28, 2008',open:472.49,high:476.45,low:470.33,close:473.78,volume:3004500},{date:'August 29, 2008',open:469.75,high:471.01,low:462.33,close:463.29,volume:3768100},{date:'September 2, 2008',open:476.77,high:482.18,low:461.42,close:465.25,volume:6020400},{date:'September 3, 2008',open:468.73,high:474.29,low:459.58,close:464.41,volume:4281600},{date:'September 4, 2008',open:460.00,high:463.24,low:449.40,close:450.26,volume:4792700},{date:'September 5, 2008',open:445.49,high:452.46,low:440.08,close:444.25,volume:4470900},{date:'September 8, 2008',open:452.02,high:452.94,low:417.55,close:419.95,volume:8890500},{date:'September 9, 2008',open:423.17,high:432.38,low:415.00,close:418.66,volume:7143600},{date:'September 10, 2008',open:424.47,high:424.48,low:409.68,close:414.16,volume:6141100},{date:'September 11, 2008',open:408.35,high:435.09,low:406.38,close:433.75,volume:6401000},{date:'September 12, 2008',open:430.21,high:441.99,low:429.00,close:437.66,volume:5983600},{date:'September 15, 2008',open:424.00,high:441.97,low:423.71,close:433.86,volume:6490000},{date:'September 16, 2008',open:425.96,high:449.28,low:425.49,close:442.93,volume:6888400},{date:'September 17, 2008',open:438.48,high:439.14,low:413.44,close:414.49,volume:8953200},{date:'September 18, 2008',open:422.64,high:439.18,low:410.50,close:439.08,volume:8395600},{date:'September 19, 2008',open:461.00,high:462.07,low:443.28,close:449.15,volume:9552700},{date:'September 22, 2008',open:454.13,high:454.13,low:429.00,close:430.14,volume:4321000},{date:'September 23, 2008',open:433.25,high:440.79,low:425.72,close:429.27,volume:5106300},{date:'September 24, 2008',open:430.34,high:445.00,low:430.11,close:435.11,volume:4186300},{date:'September 25, 2008',open:438.84,high:450.00,low:435.98,close:439.60,volume:4919500},{date:'September 26, 2008',open:428.00,high:437.16,low:421.03,close:431.04,volume:5252400},{date:'September 29, 2008',open:419.51,high:423.51,low:380.71,close:381.00,volume:10623400},{date:'September 30, 2008',open:396.00,high:489.36,low:392.32,close:400.52,volume:9451900},{date:'October 1, 2008',open:411.15,high:416.98,low:403.10,close:411.72,volume:6082700},{date:'October 2, 2008',open:409.79,high:409.98,low:386.00,close:390.49,volume:5936400},{date:'October 3, 2008',open:397.35,high:412.50,low:383.07,close:386.91,volume:7925900},{date:'October 6, 2008',open:373.98,high:375.99,low:357.16,close:371.21,volume:11084200},{date:'October 7, 2008',open:373.33,high:374.98,low:345.37,close:346.01,volume:10807000},{date:'October 8, 2008',open:330.16,high:358.99,low:326.11,close:338.11,volume:11668000},{date:'October 9, 2008',open:344.52,high:348.57,low:321.67,close:328.98,volume:7982100},{date:'October 10, 2008',open:313.16,high:341.89,low:310.30,close:332.00,volume:10402000},{date:'October 13, 2008',open:355.79,high:381.95,low:345.75,close:381.02,volume:8733100},{date:'October 14, 2008',open:393.53,high:394.50,low:357.00,close:362.71,volume:7515800},{date:'October 15, 2008',open:354.65,high:359.00,low:338.83,close:339.17,volume:6614000},{date:'October 16, 2008',open:332.76,high:356.50,low:309.44,close:353.02,volume:13980400},{date:'October 17, 2008',open:378.96,high:386.00,low:363.55,close:372.54,volume:13881200},{date:'October 20, 2008',open:379.75,high:380.98,low:359.59,close:379.32,volume:6649600},{date:'October 21, 2008',open:372.39,high:383.78,low:362.00,close:362.75,volume:5628300},{date:'October 22, 2008',open:356.99,high:369.69,low:344.00,close:355.67,volume:6445200},{date:'October 23, 2008',open:353.65,high:358.00,low:337.99,close:352.32,volume:6404700},{date:'October 24, 2008',open:326.47,high:350.47,low:324.74,close:339.29,volume:7221800},{date:'October 27, 2008',open:334.81,high:343.00,low:325.60,close:329.49,volume:6134700},{date:'October 28, 2008',open:339.05,high:369.31,low:328.51,close:368.75,volume:7964800},{date:'October 29, 2008',open:365.79,high:371.00,low:352.37,close:358.00,volume:9656600},{date:'October 30, 2008',open:368.46,high:372.00,low:358.37,close:359.69,volume:7894700},{date:'October 31, 2008',open:356.16,high:371.96,low:354.27,close:359.36,volume:7299400},{date:'November 3, 2008',open:357.58,high:362.99,low:341.43,close:346.49,volume:5642900},{date:'November 4, 2008',open:353.44,high:372.36,low:345.50,close:366.94,volume:7277700},{date:'November 5, 2008',open:362.15,high:368.88,low:341.31,close:342.24,volume:6902100},{date:'November 6, 2008',open:339.97,high:344.42,low:325.81,close:331.22,volume:8186900},{date:'November 7, 2008',open:333.12,high:341.15,low:325.33,close:331.14,volume:4622900},{date:'November 10, 2008',open:328.00,high:329.44,low:309.47,close:318.78,volume:8097595},{date:'November 11, 2008',open:308.69,high:316.30,low:300.52,close:311.46,volume:10148785},{date:'November 12, 2008',open:302.05,high:312.49,low:287.76,close:291.00,volume:10054453},{date:'November 13, 2008',open:291.77,high:313.00,low:280.00,close:312.08,volume:13239068},{date:'November 14, 2008',open:303.25,high:324.99,low:302.56,close:310.02,volume:9518466},{date:'November 17, 2008',open:303.00,high:310.16,low:297.95,close:300.12,volume:7544451},{date:'November 18, 2008',open:301.57,high:303.73,low:285.35,close:297.42,volume:8348791},{date:'November 19, 2008',open:295.39,high:300.19,low:278.58,close:280.18,volume:7841605},{date:'November 20, 2008',open:274.89,high:282.94,low:259.04,close:259.56,volume:9780746},{date:'November 21, 2008',open:262.51,high:269.37,low:247.30,close:262.43,volume:10246338},{date:'November 24, 2008',open:269.26,high:269.95,low:249.01,close:257.44,volume:10059557},{date:'November 25, 2008',open:268.68,high:286.66,low:267.32,close:282.05,volume:10774259},{date:'November 26, 2008',open:280.28,high:295.46,low:276.20,close:292.09,volume:6359179},{date:'November 27, 2008',open:292.09,high:292.09,low:292.09,close:292.09,volume:0},{date:'November 28, 2008',open:290.58,high:296.45,low:288.28,close:292.96,volume:2566368},{date:'December 1, 2008',open:286.68,high:287.38,low:265.98,close:265.99,volume:5711464},{date:'December 2, 2008',open:269.73,high:277.78,low:262.58,close:275.11,volume:5841927},{date:'December 3, 2008',open:269.85,high:281.36,low:265.34,close:279.43,volume:5906616},{date:'December 4, 2008',open:276.53,high:283.49,low:268.77,close:274.34,volume:4887799},{date:'December 5, 2008',open:271.02,high:284.24,low:264.02,close:283.99,volume:6523543},{date:'December 8, 2008',open:289.99,high:309.44,low:282.00,close:302.11,volume:8145300},{date:'December 9, 2008',open:297.69,high:318.00,low:297.01,close:305.97,volume:6891773},{date:'December 10, 2008',open:309.24,high:314.90,low:304.51,close:308.82,volume:5239603},{date:'December 11, 2008',open:304.17,high:312.88,low:297.80,close:300.22,volume:6181078},{date:'December 12, 2008',open:295.71,high:316.47,low:294.00,close:315.76,volume:5722856},{date:'December 15, 2008',open:314.01,high:318.49,low:305.11,close:310.67,volume:6738806},{date:'December 16, 2008',open:314.52,high:329.50,low:311.27,close:325.28,volume:7199994},{date:'December 17, 2008',open:318.64,high:322.13,low:312.42,close:315.24,volume:5789689},{date:'December 18, 2008',open:316.70,high:320.35,low:309.11,close:310.28,volume:4764056},{date:'December 19, 2008',open:310.99,high:317.79,low:309.00,close:310.17,volume:5670140},{date:'December 22, 2008',open:308.56,high:309.50,low:290.63,close:297.11,volume:3919429},{date:'December 23, 2008',open:300.43,high:303.31,low:296.67,close:298.02,volume:3783790},{date:'December 24, 2008',open:301.48,high:306.34,low:298.38,close:302.95,volume:1921757},{date:'December 25, 2008',open:302.95,high:302.95,low:302.95,close:302.95,volume:0},{date:'December 26, 2008',open:304.07,high:305.26,low:298.31,close:300.36,volume:1961122},{date:'December 29, 2008',open:300.22,high:301.38,low:291.58,close:297.42,volume:3702166},{date:'December 30, 2008',open:300.80,high:306.81,low:298.71,close:303.11,volume:3845369},{date:'December 31, 2008',open:304.20,high:311.00,low:302.61,close:307.65,volume:2887334},{date:'January 1, 2009',open:307.65,high:307.65,low:307.65,close:307.65,volume:0},{date:'January 2, 2009',open:308.60,high:321.82,low:305.50,close:321.32,volume:3617574},{date:'January 5, 2009',open:321.00,high:331.24,low:315.00,close:328.05,volume:4891063},{date:'January 6, 2009',open:332.98,high:340.80,low:326.39,close:334.06,volume:6426845},{date:'January 7, 2009',open:328.32,high:330.91,low:318.75,close:322.01,volume:4495295},{date:'January 8, 2009',open:318.28,high:325.19,low:317.34,close:325.19,volume:3601466},{date:'January 9, 2009',open:327.50,high:327.50,low:313.40,close:315.07,volume:4341085},{date:'January 12, 2009',open:316.31,high:318.95,low:310.23,close:312.69,volume:3304863},{date:'January 13, 2009',open:311.77,high:320.60,low:310.39,close:314.32,volume:4433603},{date:'January 14, 2009',open:310.00,high:313.80,low:297.75,close:300.97,volume:5577379},{date:'January 15, 2009',open:297.57,high:303.58,low:286.79,close:298.99,volume:5936381},{date:'January 16, 2009',open:305.02,high:308.25,low:295.70,close:299.67,volume:5225959},{date:'January 20, 2009',open:299.14,high:299.50,low:282.75,close:282.75,volume:5050088},{date:'January 21, 2009',open:288.35,high:303.50,low:288.35,close:303.08,volume:4927534},{date:'January 22, 2009',open:298.04,high:309.35,low:295.15,close:306.50,volume:8266320},{date:'January 23, 2009',open:309.27,high:331.96,low:304.22,close:324.70,volume:10732775},{date:'January 26, 2009',open:324.85,high:328.00,low:320.56,close:323.87,volume:4611581},{date:'January 27, 2009',open:326.45,high:333.87,low:324.27,close:331.48,volume:4929544},{date:'January 28, 2009',open:337.98,high:352.33,low:336.31,close:348.67,volume:7693202},{date:'January 29, 2009',open:344.54,high:345.05,low:340.11,close:343.32,volume:7284342},{date:'January 30, 2009',open:344.69,high:348.80,low:336.00,close:338.53,volume:4672843},{date:'February 2, 2009',open:334.29,high:345.00,low:332.00,close:340.57,volume:5206915},{date:'February 3, 2009',open:342.57,high:343.00,low:333.83,close:340.45,volume:6561634},{date:'February 4, 2009',open:340.07,high:354.44,low:339.17,close:343.00,volume:6817851},{date:'February 5, 2009',open:340.91,high:355.38,low:337.00,close:353.72,volume:7265283},{date:'February 6, 2009',open:356.46,high:373.81,low:355.44,close:371.28,volume:7041797},{date:'February 9, 2009',open:371.28,high:381.00,low:367.30,close:378.77,volume:4983224},{date:'February 10, 2009',open:375.98,high:377.50,low:357.89,close:358.51,volume:7105831},{date:'February 11, 2009',open:358.95,high:365.00,low:353.00,close:358.04,volume:5232088},{date:'February 12, 2009',open:353.16,high:363.62,low:351.48,close:363.05,volume:5551383},{date:'February 13, 2009',open:362.19,high:362.99,low:355.23,close:357.68,volume:4147107},{date:'February 17, 2009',open:346.51,high:347.09,low:339.69,close:342.66,volume:5680732},{date:'February 18, 2009',open:347.24,high:353.38,low:340.52,close:353.11,volume:6025999},{date:'February 19, 2009',open:357.47,high:359.80,low:341.41,close:342.64,volume:4989553},{date:'February 20, 2009',open:338.05,high:348.92,low:335.00,close:346.45,volume:6217692},{date:'February 23, 2009',open:347.00,high:349.80,low:329.55,close:330.06,volume:5220506},{date:'February 24, 2009',open:331.02,high:349.62,low:330.89,close:345.45,volume:6101985},{date:'February 25, 2009',open:342.15,high:352.30,low:338.92,close:341.64,volume:6440776},{date:'February 26, 2009',open:345.96,high:352.49,low:337.16,close:337.18,volume:5607758},{date:'February 27, 2009',open:332.95,high:343.82,low:331.11,close:337.99,volume:5420892},{date:'March 2, 2009',open:333.33,high:340.70,low:326.00,close:327.16,volume:5789674},{date:'March 3, 2009',open:330.07,high:333.69,low:322.35,close:325.48,volume:6524207},{date:'March 4, 2009',open:323.16,high:329.00,low:315.38,close:318.92,volume:7820133},{date:'March 5, 2009',open:316.48,high:319.08,low:302.64,close:305.64,volume:6530631},{date:'March 6, 2009',open:307.22,high:310.19,low:294.25,close:308.57,volume:7238087},{date:'March 9, 2009',open:299.98,high:306.57,low:289.45,close:290.89,volume:6929592},{date:'March 10, 2009',open:298.25,high:310.50,low:294.25,close:308.17,volume:6731733},{date:'March 11, 2009',open:310.10,high:320.00,low:305.71,close:317.91,volume:5927178},{date:'March 12, 2009',open:317.54,high:325.00,low:313.65,close:323.53,volume:5026330},{date:'March 13, 2009',open:326.10,high:327.46,low:319.03,close:324.42,volume:3907609},{date:'March 16, 2009',open:325.99,high:329.73,low:318.59,close:319.69,volume:4947256},{date:'March 17, 2009',open:320.18,high:335.34,low:319.09,close:335.34,volume:4715786},{date:'March 18, 2009',open:334.81,high:340.00,low:328.05,close:333.10,volume:5013619},{date:'March 19, 2009',open:331.68,high:336.00,low:327.38,close:329.94,volume:4111476},{date:'March 20, 2009',open:330.30,high:332.99,low:326.34,close:330.16,volume:4738590},{date:'March 23, 2009',open:333.56,high:349.45,low:333.03,close:348.60,volume:4272085},{date:'March 24, 2009',open:346.50,high:353.84,low:344.00,close:347.16,volume:3821808},{date:'March 25, 2009',open:350.40,high:351.34,low:336.25,close:344.07,volume:4337117},{date:'March 26, 2009',open:353.13,high:359.16,low:348.50,close:353.29,volume:6004769},{date:'March 27, 2009',open:350.00,high:352.00,low:345.47,close:347.70,volume:3323401},{date:'March 30, 2009',open:342.55,high:343.81,low:336.06,close:342.69,volume:3096702},{date:'March 31, 2009',open:348.93,high:353.51,low:346.18,close:348.06,volume:3658421},{date:'April 1, 2009',open:343.78,high:355.24,low:340.61,close:354.09,volume:3303042},{date:'April 2, 2009',open:363.31,high:369.76,low:360.32,close:362.50,volume:4489367},{date:'April 3, 2009',open:364.50,high:371.72,low:358.00,close:369.78,volume:3770328},{date:'April 6, 2009',open:367.00,high:369.82,low:361.40,close:368.24,volume:3281760},{date:'April 7, 2009',open:362.60,high:363.75,low:355.31,close:358.65,volume:3681433},{date:'April 8, 2009',open:363.50,high:365.00,low:356.21,close:362.00,volume:2765142},{date:'April 9, 2009',open:369.50,high:374.35,low:366.25,close:372.50,volume:3383146},{date:'April 10, 2009',open:372.50,high:372.50,low:372.50,close:372.50,volume:0},{date:'April 13, 2009',open:371.33,high:379.10,low:370.30,close:378.11,volume:3050081},{date:'April 14, 2009',open:376.94,high:376.99,low:365.60,close:368.91,volume:3429359},{date:'April 15, 2009',open:367.10,high:381.06,low:364.16,close:379.50,volume:4935003},{date:'April 16, 2009',open:381.50,high:392.90,low:381.02,close:388.74,volume:10185094},{date:'April 17, 2009',open:386.02,high:399.82,low:384.81,close:392.24,volume:10734963},{date:'April 20, 2009',open:386.15,high:390.65,low:375.89,close:379.30,volume:4429555},{date:'April 21, 2009',open:376.17,high:384.30,low:376.10,close:381.47,volume:3697301},{date:'April 22, 2009',open:381.75,high:390.00,low:379.01,close:383.86,volume:3503616},{date:'April 23, 2009',open:387.51,high:389.75,low:381.11,close:384.69,volume:2611240},{date:'April 24, 2009',open:386.05,high:393.18,low:380.50,close:389.49,volume:3386147},{date:'April 27, 2009',open:384.34,high:389.49,low:382.75,close:385.95,volume:2291125},{date:'April 28, 2009',open:383.75,high:389.05,low:381.54,close:383.71,volume:2943938},{date:'April 29, 2009',open:385.97,high:394.97,low:385.83,close:391.47,volume:3610160},{date:'April 30, 2009',open:395.76,high:403.75,low:394.80,close:395.97,volume:4361069},{date:'May 1, 2009',open:395.03,high:397.59,low:391.55,close:393.69,volume:2428611},{date:'May 4, 2009',open:398.17,high:402.40,low:394.79,close:401.98,volume:3204843},{date:'May 5, 2009',open:399.98,high:405.00,low:397.25,close:402.99,volume:2401096},{date:'May 6, 2009',open:406.79,high:408.28,low:401.00,close:403.47,volume:2633743},{date:'May 7, 2009',open:404.10,high:404.99,low:392.50,close:396.61,volume:3000724},{date:'May 8, 2009',open:402.85,high:410.13,low:395.00,close:407.33,volume:3865597},{date:'May 11, 2009',open:402.80,high:412.00,low:401.20,close:407.98,volume:2560736},{date:'May 12, 2009',open:410.01,high:410.99,low:395.11,close:399.01,volume:3796453},{date:'May 13, 2009',open:394.09,high:396.39,low:388.35,close:389.54,volume:2852384},{date:'May 14, 2009',open:388.80,high:392.21,low:384.69,close:387.50,volume:2937904},{date:'May 15, 2009',open:391.10,high:394.11,low:389.09,close:390.00,volume:3016859},{date:'May 18, 2009',open:394.73,high:397.31,low:385.40,close:396.84,volume:3352055},{date:'May 19, 2009',open:396.10,high:401.64,low:393.00,close:398.88,volume:2837823},{date:'May 20, 2009',open:402.09,high:405.67,low:395.00,close:397.18,volume:2284191},{date:'May 21, 2009',open:396.30,high:402.84,low:393.84,close:396.50,volume:2720300},{date:'May 22, 2009',open:396.66,high:398.65,low:392.00,close:393.50,volume:1718843},{date:'May 26, 2009',open:391.95,high:405.00,low:390.00,close:404.36,volume:3104776},{date:'May 27, 2009',open:405.64,high:411.86,low:404.81,close:405.56,volume:3035892},{date:'May 28, 2009',open:408.68,high:411.62,low:404.61,close:410.40,volume:2668993},{date:'May 29, 2009',open:412.11,high:417.23,low:410.70,close:417.23,volume:2649405},{date:'June 1, 2009',open:418.73,high:429.60,low:418.53,close:426.56,volume:3323431},{date:'June 2, 2009',open:426.25,high:429.96,low:423.40,close:428.40,volume:2626012},{date:'June 3, 2009',open:426.00,high:432.46,low:424.00,close:431.65,volume:3535593},{date:'June 4, 2009',open:435.30,high:441.24,low:434.50,close:440.28,volume:3639434},{date:'June 5, 2009',open:445.07,high:447.34,low:439.46,close:444.32,volume:3681002},{date:'June 8, 2009',open:439.50,high:440.92,low:434.12,close:438.77,volume:3098931},{date:'June 9, 2009',open:438.58,high:440.50,low:431.76,close:435.62,volume:3255945},{date:'June 10, 2009',open:436.23,high:437.89,low:426.67,close:432.60,volume:3358870},{date:'June 11, 2009',open:431.77,high:433.73,low:428.37,close:429.00,volume:2866040},{date:'June 12, 2009',open:426.86,high:427.70,low:421.21,close:424.84,volume:2918429},{date:'June 15, 2009',open:421.50,high:421.50,low:414.00,close:416.77,volume:3737299},{date:'June 16, 2009',open:419.31,high:421.09,low:415.42,close:416.00,volume:3050261},{date:'June 17, 2009',open:416.19,high:419.72,low:411.56,close:415.16,volume:3490947},{date:'June 18, 2009',open:415.68,high:418.69,low:413.00,close:414.06,volume:3087653},{date:'June 19, 2009',open:418.21,high:420.46,low:414.58,close:420.09,volume:4261008},{date:'June 22, 2009',open:416.95,high:417.49,low:401.89,close:407.35,volume:4124360},{date:'June 23, 2009',open:406.65,high:408.99,low:402.55,close:405.68,volume:2899710},{date:'June 24, 2009',open:408.74,high:412.23,low:406.56,close:409.29,volume:2457992},{date:'June 25, 2009',open:407.00,high:415.90,low:406.51,close:415.77,volume:3042038},{date:'June 26, 2009',open:413.68,high:428.23,low:413.11,close:425.32,volume:3257482},{date:'June 29, 2009',open:426.00,high:427.80,low:422.24,close:424.14,volume:2169518},{date:'June 30, 2009',open:424.00,high:427.21,low:418.22,close:421.59,volume:2594683},{date:'July 1, 2009',open:424.20,high:426.40,low:418.15,close:418.99,volume:2310768},{date:'July 2, 2009',open:415.41,high:415.41,low:406.81,close:408.49,volume:2517630},{date:'July 3, 2009',open:408.49,high:408.49,low:408.49,close:408.49,volume:0},{date:'July 6, 2009',open:406.50,high:410.64,low:401.66,close:409.61,volume:2262557},{date:'July 7, 2009',open:408.24,high:409.19,low:395.98,close:396.63,volume:3260307},{date:'July 8, 2009',open:400.00,high:406.00,low:398.06,close:402.49,volume:3441854},{date:'July 9, 2009',open:406.12,high:414.45,low:405.80,close:410.39,volume:3275816},{date:'July 10, 2009',open:409.58,high:417.37,low:408.70,close:414.40,volume:2929559},{date:'July 13, 2009',open:416.17,high:424.52,low:415.18,close:424.30,volume:4047557},{date:'July 14, 2009',open:423.71,high:426.73,low:420.87,close:424.69,volume:2896461},{date:'July 15, 2009',open:429.66,high:438.68,low:428.49,close:438.17,volume:3779342},{date:'July 16, 2009',open:436.68,high:445.75,low:434.10,close:442.60,volume:6554412},{date:'July 17, 2009',open:433.00,high:435.48,low:426.70,close:430.25,volume:6854734},{date:'July 20, 2009',open:429.88,high:432.85,low:426.25,close:430.17,volume:3154002},{date:'July 21, 2009',open:430.94,high:431.90,low:425.72,close:427.90,volume:2969146},{date:'July 22, 2009',open:428.00,high:430.20,low:423.50,close:427.69,volume:2586960},{date:'July 23, 2009',open:428.68,high:441.21,low:425.50,close:437.34,volume:3479378},{date:'July 24, 2009',open:435.81,high:450.49,low:435.00,close:446.72,volume:3629454},{date:'July 27, 2009',open:446.04,high:446.75,low:437.61,close:444.80,volume:2505329},{date:'July 28, 2009',open:441.00,high:442.81,low:436.10,close:439.85,volume:2541052},{date:'July 29, 2009',open:437.23,high:437.80,low:431.88,close:436.24,volume:1987216},{date:'July 30, 2009',open:442.61,high:451.47,low:442.61,close:445.64,volume:3200547},{date:'July 31, 2009',open:449.98,high:452.70,low:442.43,close:443.05,volume:2861550},{date:'August 3, 2009',open:448.74,high:453.90,low:447.64,close:452.21,volume:2591173},{date:'August 4, 2009',open:449.37,high:454.00,low:448.43,close:453.73,volume:2390098},{date:'August 5, 2009',open:456.00,high:456.91,low:447.88,close:451.14,volume:2342227},{date:'August 6, 2009',open:454.30,high:454.88,low:448.53,close:450.36,volume:2111395},{date:'August 7, 2009',open:455.67,high:459.42,low:454.99,close:457.10,volume:2543392},{date:'August 10, 2009',open:455.14,high:458.41,low:453.79,close:456.61,volume:1741979},{date:'August 12, 2009',open:455.41,high:461.75,low:454.92,close:458.58,volume:2341768},{date:'August 13, 2009',open:462.15,high:464.72,low:458.91,close:462.28,volume:1995640},{date:'August 14, 2009',open:462.78,high:463.18,low:456.89,close:460.00,volume:1676559},{date:'August 17, 2009',open:451.50,high:451.99,low:443.12,close:444.89,volume:2620304},{date:'August 18, 2009',open:445.10,high:447.70,low:442.32,close:445.28,volume:2357493},{date:'August 19, 2009',open:439.99,high:445.00,low:438.56,close:443.97,volume:2260091},{date:'August 20, 2009',open:452.00,high:462.18,low:451.23,close:460.41,volume:4002454},{date:'August 21, 2009',open:465.54,high:466.09,low:462.65,close:465.24,volume:3564367},{date:'August 24, 2009',open:467.35,high:470.09,low:464.42,close:468.73,volume:2459325},{date:'August 25, 2009',open:469.13,high:474.35,low:468.72,close:471.37,volume:2343030},{date:'August 26, 2009',open:472.76,high:473.00,low:466.70,close:468.00,volume:1988449},{date:'August 27, 2009',open:468.58,high:468.58,low:460.73,close:466.06,volume:2000000},{date:'August 28, 2009',open:469.26,high:472.37,low:463.38,close:464.75,volume:1771808},{date:'August 31, 2009',open:459.79,high:461.86,low:458.00,close:461.67,volume:1957955},{date:'September 1, 2009',open:459.68,high:466.82,low:454.42,close:455.76,volume:2595091},{date:'September 2, 2009',open:455.82,high:458.33,low:452.59,close:453.01,volume:1806518},{date:'September 3, 2009',open:455.82,high:458.25,low:455.00,close:457.52,volume:1646354},{date:'September 4, 2009',open:457.57,high:462.60,low:455.78,close:461.30,volume:1499873},{date:'September 8, 2009',open:464.29,high:466.99,low:455.84,close:458.62,volume:2656609},{date:'September 9, 2009',open:459.06,high:466.27,low:458.80,close:463.97,volume:2195496},{date:'September 10, 2009',open:466.65,high:470.94,low:462.00,close:470.94,volume:2535304},{date:'September 11, 2009',open:470.40,high:473.30,low:467.63,close:472.14,volume:1902811},{date:'September 14, 2009',open:470.51,high:476.80,low:470.05,close:475.12,volume:1977667},{date:'September 15, 2009',open:475.08,high:478.91,low:472.71,close:477.54,volume:2398607},{date:'September 16, 2009',open:479.80,high:489.37,low:478.48,close:488.29,volume:2587367},{date:'September 17, 2009',open:490.57,high:497.37,low:487.15,close:491.72,volume:4483447},{date:'September 18, 2009',open:496.77,high:496.98,low:491.23,close:491.46,volume:3284248},{date:'September 21, 2009',open:487.74,high:498.90,low:486.22,close:497.00,volume:2117567},{date:'September 22, 2009',open:500.92,high:501.99,low:497.81,close:499.06,volume:3041830},{date:'September 23, 2009',open:500.78,high:507.00,low:497.71,close:498.81,volume:2700820},{date:'September 24, 2009',open:500.47,high:501.41,low:493.00,close:496.77,volume:2528646},{date:'September 25, 2009',open:494.29,high:499.93,low:492.00,close:492.48,volume:2052014},{date:'September 28, 2009',open:494.84,high:501.50,low:493.30,close:498.53,volume:1843168},{date:'September 29, 2009',open:499.53,high:499.75,low:493.01,close:498.53,volume:2099379},{date:'September 30, 2009',open:500.00,high:500.14,low:487.24,close:495.85,volume:3141701},{date:'October 1, 2009',open:493.00,high:496.47,low:487.00,close:487.20,volume:2816234},{date:'October 2, 2009',open:483.74,high:491.74,low:482.60,close:484.58,volume:2600805},{date:'October 5, 2009',open:487.65,high:492.43,low:483.34,close:488.52,volume:2144652},{date:'October 6, 2009',open:491.70,high:499.37,low:491.70,close:498.74,volume:2732977},{date:'October 7, 2009',open:499.00,high:518.99,low:497.81,close:517.54,volume:4877683},{date:'October 8, 2009',open:519.57,high:523.25,low:513.34,close:514.18,volume:4306504},{date:'October 9, 2009',open:516.65,high:521.51,low:514.50,close:516.25,volume:2739892},{date:'October 12, 2009',open:523.42,high:525.76,low:519.32,close:524.04,volume:3324320},{date:'October 13, 2009',open:524.39,high:527.46,low:521.38,close:526.11,volume:3042242},{date:'October 14, 2009',open:532.46,high:535.58,low:530.00,close:535.32,volume:3265055},{date:'October 15, 2009',open:533.75,high:536.90,low:527.27,close:529.91,volume:6100353},{date:'October 16, 2009',open:547.33,high:554.75,low:544.53,close:549.85,volume:8845714},{date:'October 19, 2009',open:552.69,high:553.60,low:548.73,close:552.09,volume:3220167},{date:'October 20, 2009',open:551.64,high:552.95,low:540.70,close:551.72,volume:4044439},{date:'October 21, 2009',open:549.91,high:559.35,low:549.00,close:551.10,volume:3673168},{date:'October 22, 2009',open:550.00,high:555.00,low:548.00,close:554.09,volume:2337087},{date:'October 23, 2009',open:555.25,high:557.89,low:551.20,close:553.69,volume:2393191},{date:'October 26, 2009',open:555.75,high:561.64,low:550.89,close:554.21,volume:2973706},{date:'October 27, 2009',open:550.97,high:554.56,low:544.16,close:548.29,volume:3218033},{date:'October 28, 2009',open:547.87,high:550.00,low:538.25,close:540.30,volume:2568660},{date:'October 29, 2009',open:543.01,high:551.83,low:541.00,close:551.05,volume:2518762},{date:'October 30, 2009',open:550.00,high:550.17,low:534.24,close:536.12,volume:3469738},{date:'November 2, 2009',open:537.08,high:539.46,low:528.24,close:533.99,volume:3202875},{date:'November 3, 2009',open:530.01,high:537.50,low:528.30,close:537.29,volume:2382892},{date:'November 4, 2009',open:540.80,high:545.50,low:536.42,close:540.33,volume:2333629},{date:'November 5, 2009',open:543.49,high:549.77,low:542.66,close:548.65,volume:1848039},{date:'November 6, 2009',open:547.72,high:551.78,low:545.50,close:551.10,volume:1826705},{date:'November 9, 2009',open:555.45,high:562.58,low:554.23,close:562.51,volume:2651426},{date:'November 10, 2009',open:562.73,high:568.78,low:562.00,close:566.76,volume:2231476},{date:'November 11, 2009',open:570.48,high:573.50,low:565.86,close:570.56,volume:2321856},{date:'November 12, 2009',open:569.56,high:572.90,low:565.50,close:567.85,volume:1886395},{date:'November 13, 2009',open:569.29,high:572.51,low:566.61,close:572.05,volume:1668092},{date:'November 16, 2009',open:575.00,high:576.99,low:572.78,close:576.28,volume:2199136},{date:'November 17, 2009',open:574.87,high:577.50,low:573.72,close:577.49,volume:1920765},{date:'November 18, 2009',open:576.65,high:578.78,low:572.07,close:576.65,volume:1550127},{date:'November 19, 2009',open:573.77,high:574.00,low:570.00,close:572.99,volume:2168302},{date:'November 20, 2009',open:569.50,high:571.60,low:569.40,close:569.96,volume:2006202},{date:'November 23, 2009',open:576.49,high:586.60,low:575.86,close:582.35,volume:2548562},{date:'November 24, 2009',open:582.50,high:584.29,low:576.54,close:583.09,volume:1608648},{date:'November 25, 2009',open:586.41,high:587.06,low:582.69,close:585.74,volume:1461405},{date:'November 26, 2009',open:585.74,high:585.74,low:585.74,close:585.74,volume:0},{date:'November 27, 2009',open:572.00,high:582.46,low:570.97,close:579.76,volume:1384523},{date:'November 30, 2009',open:580.63,high:583.67,low:577.11,close:583.00,volume:1725231},{date:'December 1, 2009',open:588.13,high:591.22,low:583.00,close:589.87,volume:2321273},{date:'December 2, 2009',open:590.98,high:593.01,low:586.22,close:587.51,volume:1665225},{date:'December 3, 2009',open:589.04,high:591.45,low:585.00,close:585.74,volume:1429399},{date:'December 4, 2009',open:593.02,high:594.83,low:579.18,close:585.01,volume:2514042},{date:'December 7, 2009',open:584.23,high:588.69,low:581.00,close:586.25,volume:1636587},{date:'December 8, 2009',open:583.50,high:590.66,low:582.00,close:587.05,volume:1525524},{date:'December 9, 2009',open:587.50,high:589.33,low:583.58,close:589.02,volume:1781288},{date:'December 10, 2009',open:590.44,high:594.71,low:590.41,close:591.50,volume:1669525},{date:'December 11, 2009',open:594.68,high:594.75,low:587.73,close:590.51,volume:1723378},{date:'December 14, 2009',open:595.24,high:597.31,low:592.61,close:595.73,volume:1913572},{date:'December 15, 2009',open:593.30,high:596.38,low:590.99,close:593.14,volume:2280340},{date:'December 16, 2009',open:598.91,high:600.37,low:596.64,close:597.76,volume:2809751},{date:'December 17, 2009',open:596.44,high:597.64,low:593.76,close:593.94,volume:2640762},{date:'December 18, 2009',open:596.03,high:598.93,low:595.00,close:596.42,volume:3532540},{date:'December 21, 2009',open:597.95,high:599.84,low:595.67,close:598.68,volume:2571981},{date:'December 22, 2009',open:601.34,high:601.50,low:598.85,close:601.12,volume:1884290},{date:'December 23, 2009',open:603.50,high:612.87,low:602.85,close:611.68,volume:2075311},{date:'December 24, 2009',open:612.93,high:619.52,low:612.27,close:618.48,volume:858620},{date:'December 25, 2009',open:618.48,high:618.48,low:618.48,close:618.48,volume:0},{date:'December 28, 2009',open:621.66,high:625.99,low:618.48,close:622.87,volume:1698015},{date:'December 29, 2009',open:624.74,high:624.84,low:618.29,close:619.40,volume:1427712},{date:'December 30, 2009',open:618.50,high:622.73,low:618.01,close:622.73,volume:1466379},{date:'December 31, 2009',open:624.75,high:625.40,low:619.98,close:619.98,volume:1220214},{date:'January 1, 2010',open:619.98,high:619.98,low:619.98,close:619.98,volume:0},{date:'January 4, 2010',open:626.95,high:629.51,low:624.24,close:626.75,volume:1957963},{date:'January 5, 2010',open:627.18,high:627.84,low:621.54,close:623.99,volume:3007857},{date:'January 6, 2010',open:625.86,high:625.86,low:606.36,close:608.26,volume:3980628},{date:'January 7, 2010',open:609.40,high:610.00,low:592.65,close:594.10,volume:6418020},{date:'January 8, 2010',open:592.00,high:603.25,low:589.11,close:602.02,volume:4724735},{date:'January 11, 2010',open:604.46,high:604.46,low:594.04,close:601.11,volume:7216804},{date:'January 12, 2010',open:598.08,high:598.16,low:588.00,close:590.48,volume:4853249},{date:'January 13, 2010',open:576.49,high:588.38,low:573.90,close:587.09,volume:6499074},{date:'January 14, 2010',open:583.90,high:594.20,low:582.81,close:589.85,volume:4241570},{date:'January 15, 2010',open:591.59,high:593.56,low:578.04,close:580.00,volume:5437698},{date:'January 18, 2010',open:580.00,high:580.00,low:580.00,close:580.00,volume:0},{date:'January 19, 2010',open:581.49,high:590.42,low:576.29,close:587.62,volume:4317143},{date:'January 20, 2010',open:585.98,high:585.98,low:575.29,close:580.41,volume:3253498},{date:'January 21, 2010',open:583.44,high:586.82,low:572.25,close:582.98,volume:6307634},{date:'January 22, 2010',open:564.50,high:570.60,low:534.86,close:550.01,volume:6807653},{date:'January 25, 2010',open:546.59,high:549.88,low:535.51,close:540.00,volume:4421012},{date:'January 26, 2010',open:537.97,high:549.60,low:536.29,close:542.42,volume:4356767},{date:'January 27, 2010',open:541.27,high:547.65,low:535.31,close:542.10,volume:3965467},{date:'January 28, 2010',open:544.49,high:547.00,low:530.60,close:534.29,volume:3231041},{date:'January 29, 2010',open:538.49,high:540.99,low:525.61,close:529.94,volume:4141196},{date:'February 1, 2010',open:534.60,high:535.81,low:530.30,close:533.02,volume:2253021},{date:'February 2, 2010',open:534.96,high:534.96,low:527.61,close:531.12,volume:4096305},{date:'February 3, 2010',open:528.67,high:542.10,low:528.23,close:540.82,volume:2999890},{date:'February 4, 2010',open:537.00,high:538.00,low:525.56,close:526.78,volume:3382732},{date:'February 5, 2010',open:528.40,high:533.50,low:522.46,close:531.29,volume:3157048},{date:'February 8, 2010',open:532.50,high:542.00,low:531.53,close:533.47,volume:2695412},{date:'February 9, 2010',open:539.54,high:541.53,low:535.07,close:536.44,volume:2828685},{date:'February 10, 2010',open:534.07,high:537.79,low:527.69,close:534.44,volume:2675794},{date:'February 11, 2010',open:532.25,high:540.49,low:529.50,close:536.40,volume:2411090},{date:'February 12, 2010',open:532.97,high:537.15,low:530.50,close:533.12,volume:2280371},{date:'February 15, 2010',open:533.12,high:533.12,low:533.12,close:533.12,volume:0},{date:'February 16, 2010',open:537.14,high:544.13,low:534.30,close:541.30,volume:3654824},{date:'February 17, 2010',open:542.00,high:543.40,low:537.61,close:538.21,volume:2030680},{date:'February 18, 2010',open:537.54,high:545.01,low:536.14,close:543.22,volume:2339250},{date:'February 19, 2010',open:541.00,high:544.03,low:539.70,close:540.76,volume:2555348},{date:'February 22, 2010',open:547.35,high:547.50,low:541.00,close:542.80,volume:2144741},{date:'February 23, 2010',open:543.00,high:543.63,low:532.29,close:535.07,volume:2874790},{date:'February 24, 2010',open:534.39,high:538.44,low:530.51,close:531.47,volume:2326901},{date:'February 25, 2010',open:527.12,high:528.49,low:520.00,close:526.43,volume:3309373},{date:'February 26, 2010',open:527.42,high:531.75,low:523.48,close:526.80,volume:2049372},{date:'March 1, 2010',open:529.20,high:533.29,low:527.74,close:532.69,volume:2238334},{date:'March 2, 2010',open:535.48,high:545.66,low:535.01,close:541.06,volume:4357461},{date:'March 3, 2010',open:542.36,high:548.12,low:539.25,close:545.32,volume:3090124},{date:'March 4, 2010',open:546.50,high:556.13,low:546.20,close:554.59,volume:3184077}]; +var priceData = [[0,100.34],[1,108.31],[2,109.40],[3,104.87],[4,106.00],[5,107.91],[6,106.15],[7,102.01],[8,102.37],[9,100.25],[10,101.51],[11,100.01],[12,101.58],[13,102.30],[14,102.31],[15,105.33],[16,107.50],[17,111.49],[18,112.00],[19,113.97],[20,117.49],[21,119.36],[22,117.84],[23,118.38],[24,120.82],[25,119.83],[26,118.26],[27,126.86],[28,131.08],[29,129.60],[30,132.58],[31,135.06],[32,138.37],[33,137.08],[34,138.85],[35,137.73],[36,135.26],[37,137.40],[38,140.90],[39,142.00],[40,144.11],[41,149.16],[42,147.94],[43,140.49],[44,149.38],[45,172.43],[46,187.40],[47,181.80],[48,185.97],[49,193.30],[50,190.64],[51,196.03],[52,194.87],[53,191.67],[54,184.70],[55,169.35],[56,172.55],[57,168.70],[58,167.86],[59,183.02],[60,182.00],[61,184.87],[62,172.54],[63,172.50],[64,167.54],[65,169.40],[66,165.10],[67,167.52],[68,174.76],[69,179.39],[70,181.05],[71,181.98],[72,179.96],[73,179.40],[74,180.40],[75,176.29],[76,171.43],[77,169.98],[78,173.43],[79,171.65],[80,170.45],[81,178.69],[82,179.78],[83,176.47],[84,180.08],[85,185.02],[86,183.75],[87,186.30],[88,187.90],[89,191.91],[90,192.76],[91,192.90],[92,197.60],[93,192.79],[94,202.71],[95,194.50],[96,193.51],[97,188.55],[98,193.85],[99,195.06],[100,193.54],[101,195.38],[102,195.33],[103,199.97],[104,203.90],[105,197.30],[106,193.92],[107,188.28],[108,180.72],[109,177.12],[110,189.24],[111,188.08],[112,190.34],[113,195.62],[114,191.90],[115,205.96],[116,210.86],[117,204.36],[118,196.03],[119,198.64],[120,191.58],[121,187.98],[122,187.40],[123,192.99],[124,195.23],[125,198.41],[126,197.90],[127,197.95],[128,191.37],[129,193.95],[130,188.89],[131,185.87],[132,187.99],[133,186.06],[134,185.18],[135,187.00],[136,185.90],[137,188.81],[138,185.20],[139,181.35],[140,179.98],[141,177.80],[142,174.99],[143,178.61],[144,175.60],[145,179.29],[146,180.04],[147,180.88],[148,178.60],[149,178.98],[150,179.25],[151,181.42],[152,179.57],[153,180.45],[154,180.51],[155,180.04],[156,185.29],[157,188.57],[158,189.22],[159,193.76],[160,192.05],[161,193.23],[162,193.96],[163,192.93],[164,191.45],[165,185.00],[166,186.97],[167,191.40],[168,198.10],[169,204.22],[170,215.81],[171,223.53],[172,218.75],[173,219.78],[174,219.45],[175,220.00],[176,222.29],[177,226.19],[178,228.50],[179,226.98],[180,228.02],[181,226.02],[182,227.80],[183,231.29],[184,228.72],[185,229.24],[186,231.05],[187,233.13],[188,239.16],[189,239.18],[190,241.61],[191,255.45],[192,256.00],[193,260.81],[194,259.20],[195,266.00],[196,277.27],[197,288.00],[198,287.90],[199,280.26],[200,290.94],[201,293.12],[202,279.56],[203,286.31],[204,282.50],[205,282.75],[206,278.35],[207,274.80],[208,277.44],[209,280.30],[210,286.70],[211,287.84],[212,289.30],[213,289.71],[214,297.25],[215,304.10],[216,302.00],[217,292.72],[218,294.15],[219,291.25],[220,295.71],[221,291.52],[222,295.54],[223,296.23],[224,293.35],[225,291.78],[226,298.86],[227,300.89],[228,301.19],[229,299.54],[230,309.90],[231,312.00],[232,313.94],[233,302.40],[234,295.85],[235,296.09],[236,296.93],[237,293.50],[238,287.76],[239,291.61],[240,299.19],[241,297.30],[242,297.73],[243,292.35],[244,291.25],[245,291.57],[246,285.68],[247,284.05],[248,289.72],[249,284.00],[250,285.65],[251,285.10],[252,279.99],[253,280.00],[254,274.01],[255,279.58],[256,282.57],[257,282.59],[258,283.58],[259,288.45],[260,287.27],[261,286.00],[262,286.25],[263,288.45],[264,287.11],[265,294.87],[266,295.39],[267,299.09],[268,309.74],[269,311.68],[270,303.00],[271,302.62],[272,300.20],[273,303.79],[274,307.91],[275,311.90],[276,311.37],[277,315.36],[278,314.28],[279,313.94],[280,306.00],[281,309.62],[282,316.46],[283,318.68],[284,311.00],[285,310.71],[286,312.75],[287,312.99],[288,310.65],[289,306.10],[290,300.97],[291,297.44],[292,296.14],[293,305.00],[294,303.28],[295,308.70],[296,303.20],[297,339.90],[298,348.65],[299,346.91],[300,355.44],[301,353.06],[302,358.17],[303,372.14],[304,379.38],[305,379.68],[306,385.95],[307,390.43],[308,395.03],[309,389.90],[310,379.15],[311,391.10],[312,390.40],[313,396.97],[314,392.80],[315,398.15],[316,403.45],[317,400.21],[318,409.36],[319,416.47],[320,422.86],[321,428.62],[322,423.48],[323,403.54],[324,404.91],[325,414.09],[326,417.70],[327,405.85],[328,404.54],[329,404.22],[330,410.65],[331,409.20],[332,412.61],[333,417.49],[334,418.96],[335,422.53],[336,430.15],[337,424.60],[338,429.74],[339,426.33],[340,432.04],[341,430.93],[342,424.64],[343,426.69],[344,420.15],[345,414.86],[346,435.23],[347,445.24],[348,451.24],[349,465.66],[350,466.90],[351,469.76],[352,471.63],[353,463.63],[354,466.25],[355,467.11],[356,444.91],[357,436.45],[358,399.46],[359,427.50],[360,443.03],[361,433.00],[362,434.27],[363,433.49],[364,426.82],[365,432.66],[366,401.78],[367,396.04],[368,381.56],[369,385.10],[370,367.92],[371,369.08],[372,358.77],[373,362.61],[374,345.70],[375,343.32],[376,342.38],[377,366.46],[378,368.75],[379,366.59],[380,365.49],[381,378.07],[382,377.40],[383,390.38],[384,362.62],[385,364.80],[386,376.45],[387,378.18],[388,368.10],[389,364.45],[390,353.88],[391,343.00],[392,337.50],[393,337.06],[394,351.16],[395,344.50],[396,338.77],[397,339.79],[398,348.19],[399,339.92],[400,340.22],[401,341.89],[402,365.80],[403,369.69],[404,377.20],[405,394.98],[406,388.44],[407,390.00],[408,389.70],[409,404.34],[410,407.99],[411,411.18],[412,406.16],[413,416.38],[414,409.66],[415,408.95],[416,402.16],[417,406.82],[418,404.24],[419,410.50],[420,415.00],[421,437.10],[422,440.50],[423,427.16],[424,425.97],[425,420.03],[426,417.94],[427,398.90],[428,394.80],[429,394.17],[430,394.75],[431,394.30],[432,394.78],[433,408.80],[434,402.98],[435,387.00],[436,374.13],[437,376.20],[438,371.30],[439,374.50],[440,370.99],[441,370.02],[442,370.95],[443,375.58],[444,381.25],[445,382.99],[446,381.35],[447,371.94],[448,371.82],[449,382.62],[450,379.44],[451,374.44],[452,389.99],[453,386.51],[454,393.30],[455,386.57],[456,381.54],[457,386.52],[458,384.39],[459,391.00],[460,390.70],[461,388.14],[462,387.17],[463,402.13],[464,399.95],[465,404.86],[466,404.22],[467,402.32],[468,406.11],[469,417.81],[470,419.33],[471,423.20],[472,421.46],[473,423.19],[474,420.45],[475,418.20],[476,424.56],[477,417.25],[478,408.83],[479,403.50],[480,407.89],[481,403.05],[482,399.00],[483,387.12],[484,390.11],[485,390.90],[486,389.36],[487,385.50],[488,382.40],[489,388.12],[490,386.60],[491,375.51],[492,367.23],[493,375.39],[494,373.85],[495,377.95],[496,381.00],[497,376.94],[498,374.20],[499,368.50],[500,369.43],[501,380.97],[502,387.72],[503,385.80],[504,383.36],[505,377.30],[506,378.29],[507,373.43],[508,373.73],[509,373.26],[510,380.95],[511,378.95],[512,380.75],[513,378.53],[514,378.60],[515,384.36],[516,380.14],[517,378.49],[518,377.85],[519,384.09],[520,391.90],[521,406.57],[522,403.98],[523,409.88],[524,414.69],[525,403.81],[526,397.00],[527,406.85],[528,403.78],[529,403.98],[530,406.87],[531,402.92],[532,403.58],[533,401.90],[534,401.44],[535,404.04],[536,415.70],[537,411.81],[538,420.50],[539,429.00],[540,426.65],[541,426.50],[542,427.44],[543,427.30],[544,421.75],[545,420.64],[546,419.31],[547,426.06],[548,459.67],[549,480.78],[550,473.31],[551,486.60],[552,485.10],[553,475.20],[554,476.57],[555,476.39],[556,467.50],[557,469.91],[558,471.80],[559,476.95],[560,472.57],[561,475.00],[562,472.63],[563,473.55],[564,481.03],[565,489.30],[566,491.93],[567,495.90],[568,498.79],[569,495.05],[570,509.65],[571,508.01],[572,505.00],[573,484.75],[574,489.50],[575,484.65],[576,484.81],[577,480.80],[578,484.85],[579,487.00],[580,488.71],[581,482.64],[582,484.11],[583,483.93],[584,481.78],[585,478.99],[586,482.12],[587,480.30],[588,462.80],[589,468.63],[590,462.90],[591,456.20],[592,455.58],[593,457.53],[594,468.03],[595,462.56],[596,460.48],[597,467.59],[598,483.26],[599,487.19],[600,483.58],[601,485.50],[602,489.46],[603,499.72],[604,505.00],[605,504.28],[606,497.28],[607,487.83],[608,489.75],[609,480.84],[610,479.05],[611,499.07],[612,488.09],[613,495.84],[614,492.47],[615,494.32],[616,501.50],[617,481.75],[618,481.50],[619,467.16],[620,471.48],[621,470.01],[622,471.03],[623,461.89],[624,458.29],[625,459.10],[626,465.93],[627,461.47],[628,469.94],[629,472.10],[630,475.86],[631,475.85],[632,470.62],[633,464.93],[634,448.77],[635,449.45],[636,448.23],[637,438.68],[638,440.95],[639,457.55],[640,455.64],[641,454.72],[642,452.96],[643,454.75],[644,443.03],[645,448.00],[646,446.19],[647,440.85],[648,447.23],[649,445.28],[650,456.55],[651,462.04],[652,461.83],[653,465.00],[654,463.62],[655,461.88],[656,460.92],[657,458.16],[658,458.53],[659,472.60],[660,471.02],[661,471.51],[662,468.21],[663,466.50],[664,464.53],[665,467.39],[666,466.29],[667,474.27],[668,472.80],[669,476.01],[670,471.65],[671,482.48],[672,479.08],[673,477.53],[674,477.99],[675,481.18],[676,479.01],[677,471.38],[678,469.00],[679,465.78],[680,473.23],[681,471.12],[682,467.27],[683,466.81],[684,469.25],[685,461.47],[686,466.74],[687,461.78],[688,458.00],[689,472.61],[690,470.96],[691,470.32],[692,470.60],[693,475.86],[694,473.97],[695,474.33],[696,483.52],[697,487.11],[698,498.60],[699,497.91],[700,500.40],[701,507.07],[702,518.84],[703,518.25],[704,515.06],[705,515.49],[706,511.34],[707,504.77],[708,505.24],[709,502.84],[710,505.89],[711,515.20],[712,514.31],[713,509.97],[714,514.11],[715,524.98],[716,527.42],[717,530.26],[718,526.29],[719,525.01],[720,522.70],[721,530.38],[722,534.34],[723,541.63],[724,539.40],[725,542.56],[726,543.34],[727,544.47],[728,545.33],[729,552.16],[730,552.99],[731,555.00],[732,549.50],[733,548.59],[734,520.12],[735,512.51],[736,514.00],[737,509.76],[738,508.00],[739,511.89],[740,516.11],[741,510.00],[742,512.94],[743,511.01],[744,503.00],[745,510.00],[746,516.02],[747,525.78],[748,514.73],[749,515.75],[750,515.50],[751,508.60],[752,497.55],[753,491.52],[754,500.04],[755,497.92],[756,506.61],[757,512.75],[758,512.19],[759,515.00],[760,513.26],[761,506.40],[762,512.88],[763,511.40],[764,515.25],[765,525.15],[766,527.80],[767,523.52],[768,519.35],[769,514.48],[770,521.33],[771,522.65],[772,524.78],[773,528.75],[774,525.30],[775,535.27],[776,546.85],[777,552.83],[778,560.10],[779,568.02],[780,569.00],[781,568.16],[782,567.50],[783,567.27],[784,582.55],[785,584.39],[786,584.02],[787,579.03],[788,594.05],[789,609.62],[790,615.18],[791,625.39],[792,622.00],[793,637.39],[794,620.11],[795,616.00],[796,633.48],[797,639.62],[798,644.71],[799,650.75],[800,675.77],[801,675.82],[802,668.51],[803,674.60],[804,679.23],[805,694.77],[806,707.00],[807,703.21],[808,711.25],[809,725.65],[810,741.79],[811,732.94],[812,693.84],[813,663.97],[814,632.07],[815,660.55],[816,641.68],[817,629.65],[818,633.63],[819,625.85],[820,648.54],[821,660.52],[822,676.70],[823,666.00],[824,673.57],[825,692.26],[826,697.00],[827,693.00],[828,681.53],[829,684.16],[830,698.51],[831,715.26],[832,714.87],[833,718.42],[834,699.20],[835,699.35],[836,694.05],[837,689.96],[838,669.23],[839,673.35],[840,677.37],[841,689.69],[842,696.69],[843,700.73],[844,710.84],[845,700.74],[846,702.53],[847,691.48],[848,685.19],[849,685.33],[850,657.00],[851,649.25],[852,631.68],[853,653.20],[854,646.73],[855,638.25],[856,653.82],[857,637.65],[858,615.95],[859,600.79],[860,600.25],[861,584.35],[862,548.62],[863,574.49],[864,566.40],[865,555.98],[866,550.52],[867,548.27],[868,564.30],[869,515.90],[870,495.43],[871,506.80],[872,501.71],[873,504.95],[874,516.69],[875,521.16],[876,518.09],[877,534.62],[878,532.25],[879,529.64],[880,508.95],[881,509.00],[882,502.86],[883,507.80],[884,486.44],[885,464.19],[886,472.86],[887,475.39],[888,471.18],[889,457.02],[890,444.60],[891,447.70],[892,432.70],[893,433.35],[894,413.62],[895,439.84],[896,440.18],[897,443.01],[898,437.92],[899,419.87],[900,439.16],[901,432.00],[902,433.55],[903,460.56],[904,450.78],[905,458.19],[906,444.08],[907,438.08],[908,440.47],[909,465.71],[910,465.70],[911,455.12],[912,471.09],[913,476.82],[914,467.81],[915,464.19],[916,469.08],[917,457.45],[918,451.66],[919,446.84],[920,455.03],[921,449.54],[922,539.41],[923,537.79],[924,555.00],[925,546.49],[926,543.04],[927,544.06],[928,552.12],[929,558.47],[930,574.29],[931,593.08],[932,581.29],[933,594.90],[934,586.36],[935,579.00],[936,583.01],[937,573.20],[938,584.94],[939,583.00],[940,576.30],[941,581.00],[942,580.07],[943,577.52],[944,578.60],[945,549.99],[946,549.46],[947,544.62],[948,560.90],[949,568.24],[950,583.00],[951,585.80],[952,575.00],[953,567.30],[954,572.22],[955,586.30],[956,567.00],[957,557.87],[958,554.17],[959,545.20],[960,552.95],[961,571.51],[962,572.81],[963,569.46],[964,562.38],[965,560.20],[966,546.43],[967,545.21],[968,542.30],[969,551.00],[970,528.82],[971,528.07],[972,526.42],[973,534.73],[974,527.04],[975,537.00],[976,543.91],[977,554.53],[978,541.55],[979,540.57],[980,533.80],[981,521.62],[982,516.09],[983,535.60],[984,533.44],[985,481.32],[986,468.80],[987,477.11],[988,489.22],[989,475.62],[990,491.98],[991,477.12],[992,483.11],[993,482.70],[994,473.75],[995,467.86],[996,463.00],[997,479.85],[998,486.34],[999,479.12],[1000,495.01],[1001,500.84],[1002,502.61],[1003,500.03],[1004,505.49],[1005,510.15],[1006,498.30],[1007,490.50],[1008,485.00],[1009,486.53],[1010,490.59],[1011,483.01],[1012,474.16],[1013,468.58],[1014,473.78],[1015,463.29],[1016,465.25],[1017,464.41],[1018,450.26],[1019,444.25],[1020,419.95],[1021,418.66],[1022,414.16],[1023,433.75],[1024,437.66],[1025,433.86],[1026,442.93],[1027,414.49],[1028,439.08],[1029,449.15],[1030,430.14],[1031,429.27],[1032,435.11],[1033,439.60],[1034,431.04],[1035,381.00],[1036,400.52],[1037,411.72],[1038,390.49],[1039,386.91],[1040,371.21],[1041,346.01],[1042,338.11],[1043,328.98],[1044,332.00],[1045,381.02],[1046,362.71],[1047,339.17],[1048,353.02],[1049,372.54],[1050,379.32],[1051,362.75],[1052,355.67],[1053,352.32],[1054,339.29],[1055,329.49],[1056,368.75],[1057,358.00],[1058,359.69],[1059,359.36],[1060,346.49],[1061,366.94],[1062,342.24],[1063,331.22],[1064,331.14],[1065,318.78],[1066,311.46],[1067,291.00],[1068,312.08],[1069,310.02],[1070,300.12],[1071,297.42],[1072,280.18],[1073,259.56],[1074,262.43],[1075,257.44],[1076,282.05],[1077,292.09],[1078,292.09],[1079,292.96],[1080,265.99],[1081,275.11],[1082,279.43],[1083,274.34],[1084,283.99],[1085,302.11],[1086,305.97],[1087,308.82],[1088,300.22],[1089,315.76],[1090,310.67],[1091,325.28],[1092,315.24],[1093,310.28],[1094,310.17],[1095,297.11],[1096,298.02],[1097,302.95],[1098,302.95],[1099,300.36],[1100,297.42],[1101,303.11],[1102,307.65],[1103,307.65],[1104,321.32],[1105,328.05],[1106,334.06],[1107,322.01],[1108,325.19],[1109,315.07],[1110,312.69],[1111,314.32],[1112,300.97],[1113,298.99],[1114,299.67],[1115,282.75],[1116,303.08],[1117,306.50],[1118,324.70],[1119,323.87],[1120,331.48],[1121,348.67],[1122,343.32],[1123,338.53],[1124,340.57],[1125,340.45],[1126,343.00],[1127,353.72],[1128,371.28],[1129,378.77],[1130,358.51],[1131,358.04],[1132,363.05],[1133,357.68],[1134,342.66],[1135,353.11],[1136,342.64],[1137,346.45],[1138,330.06],[1139,345.45],[1140,341.64],[1141,337.18],[1142,337.99],[1143,327.16],[1144,325.48],[1145,318.92],[1146,305.64],[1147,308.57],[1148,290.89],[1149,308.17],[1150,317.91],[1151,323.53],[1152,324.42],[1153,319.69],[1154,335.34],[1155,333.10],[1156,329.94],[1157,330.16],[1158,348.60],[1159,347.16],[1160,344.07],[1161,353.29],[1162,347.70],[1163,342.69],[1164,348.06],[1165,354.09],[1166,362.50],[1167,369.78],[1168,368.24],[1169,358.65],[1170,362.00],[1171,372.50],[1172,372.50],[1173,378.11],[1174,368.91],[1175,379.50],[1176,388.74],[1177,392.24],[1178,379.30],[1179,381.47],[1180,383.86],[1181,384.69],[1182,389.49],[1183,385.95],[1184,383.71],[1185,391.47],[1186,395.97],[1187,393.69],[1188,401.98],[1189,402.99],[1190,403.47],[1191,396.61],[1192,407.33],[1193,407.98],[1194,399.01],[1195,389.54],[1196,387.50],[1197,390.00],[1198,396.84],[1199,398.88],[1200,397.18],[1201,396.50],[1202,393.50],[1203,404.36],[1204,405.56],[1205,410.40],[1206,417.23],[1207,426.56],[1208,428.40],[1209,431.65],[1210,440.28],[1211,444.32],[1212,438.77],[1213,435.62],[1214,432.60],[1215,429.00],[1216,424.84],[1217,416.77],[1218,416.00],[1219,415.16],[1220,414.06],[1221,420.09],[1222,407.35],[1223,405.68],[1224,409.29],[1225,415.77],[1226,425.32],[1227,424.14],[1228,421.59],[1229,418.99],[1230,408.49],[1231,408.49],[1232,409.61],[1233,396.63],[1234,402.49],[1235,410.39],[1236,414.40],[1237,424.30],[1238,424.69],[1239,438.17],[1240,442.60],[1241,430.25],[1242,430.17],[1243,427.90],[1244,427.69],[1245,437.34],[1246,446.72],[1247,444.80],[1248,439.85],[1249,436.24],[1250,445.64],[1251,443.05],[1252,452.21],[1253,453.73],[1254,451.14],[1255,450.36],[1256,457.10],[1257,456.61],[1258,458.58],[1259,462.28],[1260,460.00],[1261,444.89],[1262,445.28],[1263,443.97],[1264,460.41],[1265,465.24],[1266,468.73],[1267,471.37],[1268,468.00],[1269,466.06],[1270,464.75],[1271,461.67],[1272,455.76],[1273,453.01],[1274,457.52],[1275,461.30],[1276,458.62],[1277,463.97],[1278,470.94],[1279,472.14],[1280,475.12],[1281,477.54],[1282,488.29],[1283,491.72],[1284,491.46],[1285,497.00],[1286,499.06],[1287,498.81],[1288,496.77],[1289,492.48],[1290,498.53],[1291,498.53],[1292,495.85],[1293,487.20],[1294,484.58],[1295,488.52],[1296,498.74],[1297,517.54],[1298,514.18],[1299,516.25],[1300,524.04],[1301,526.11],[1302,535.32],[1303,529.91],[1304,549.85],[1305,552.09],[1306,551.72],[1307,551.10],[1308,554.09],[1309,553.69],[1310,554.21],[1311,548.29],[1312,540.30],[1313,551.05],[1314,536.12],[1315,533.99],[1316,537.29],[1317,540.33],[1318,548.65],[1319,551.10],[1320,562.51],[1321,566.76],[1322,570.56],[1323,567.85],[1324,572.05],[1325,576.28],[1326,577.49],[1327,576.65],[1328,572.99],[1329,569.96],[1330,582.35],[1331,583.09],[1332,585.74],[1333,585.74],[1334,579.76],[1335,583.00],[1336,589.87],[1337,587.51],[1338,585.74],[1339,585.01],[1340,586.25],[1341,587.05],[1342,589.02],[1343,591.50],[1344,590.51],[1345,595.73],[1346,593.14],[1347,597.76],[1348,593.94],[1349,596.42],[1350,598.68],[1351,601.12],[1352,611.68],[1353,618.48],[1354,618.48],[1355,622.87],[1356,619.40],[1357,622.73],[1358,619.98],[1359,619.98],[1360,626.75],[1361,623.99],[1362,608.26],[1363,594.10],[1364,602.02],[1365,601.11],[1366,590.48],[1367,587.09],[1368,589.85],[1369,580.00],[1370,580.00],[1371,587.62],[1372,580.41],[1373,582.98],[1374,550.01],[1375,540.00],[1376,542.42],[1377,542.10],[1378,534.29],[1379,529.94],[1380,533.02],[1381,531.12],[1382,540.82],[1383,526.78],[1384,531.29],[1385,533.47],[1386,536.44],[1387,534.44],[1388,536.40],[1389,533.12],[1390,533.12],[1391,541.30],[1392,538.21],[1393,543.22],[1394,540.76],[1395,542.80],[1396,535.07],[1397,531.47],[1398,526.43],[1399,526.80],[1400,532.69],[1401,541.06],[1402,545.32],[1403,554.59]]; +var volumeData = [[0,22088000],[1,11377000],[2,9090700],[3,7599100],[4,4565900],[5,3527900],[6,3102400],[7,2585600],[8,2455900],[9,4525000],[10,7477500],[11,2572600],[12,2948400],[13,2493900],[14,2061500],[15,4736800],[16,3915300],[17,5402900],[18,5288000],[19,4619500],[20,4535800],[21,5310000],[22,3610000],[23,3781000],[24,4254000],[25,4494400],[26,3523200],[27,8421200],[28,15175600],[29,6696200],[30,7515600],[31,6488900],[32,7359700],[33,6648600],[34,7036400],[35,5509700],[36,5210700],[37,5488100],[38,9846300],[39,5200700],[40,6477600],[41,6888900],[42,9029600],[43,11201800],[44,11329000],[45,36716300],[46,32608400],[47,22195200],[48,13199900],[49,14593000],[50,20986500],[51,12136100],[52,11281900],[53,13775600],[54,14031000],[55,19671800],[56,11116600],[57,10916400],[58,10507800],[59,14850400],[60,16677500],[61,11831700],[62,20774500],[63,17958800],[64,16150000],[65,8637600],[66,12216300],[67,10591100],[68,15167800],[69,6423400],[70,10562200],[71,7553600],[72,7801200],[73,6118100],[74,5807500],[75,6208700],[76,6838800],[77,7313000],[78,7587500],[79,4221600],[80,4758500],[81,10951700],[82,11302700],[83,8450200],[84,7117900],[85,9689600],[86,5471400],[87,3855300],[88,3590000],[89,6079400],[90,4126200],[91,2640200],[92,5832200],[93,7590200],[94,15649600],[95,13676500],[96,8194600],[97,10326000],[98,9508700],[99,7418600],[100,6920000],[101,8104700],[102,6814300],[103,9528700],[104,12656800],[105,10714400],[106,8957500],[107,9024100],[108,13881100],[109,10559300],[110,12225200],[111,6577800],[112,12126900],[113,9513600],[114,11985700],[115,32475300],[116,12873100],[117,14741600],[118,12853700],[119,11406000],[120,16922400],[121,18912700],[122,13048300],[123,38258000],[124,25721600],[125,16443100],[126,10367600],[127,8434100],[128,13404600],[129,15216400],[130,25572200],[131,9853900],[132,7756600],[133,9271000],[134,7260700],[135,7563400],[136,6725900],[137,8427800],[138,7975700],[139,11179700],[140,10673700],[141,7973600],[142,10972200],[143,10376100],[144,6877400],[145,8078000],[146,6682900],[147,7411000],[148,5563900],[149,4794100],[150,3680200],[151,8661900],[152,6452700],[153,6206800],[154,6696900],[155,6159800],[156,8038300],[157,8636900],[158,5198900],[159,9650000],[160,5087700],[161,5344500],[162,7292600],[163,6492000],[164,6103700],[165,11351400],[166,6528000],[167,7307800],[168,15251300],[169,12997100],[170,32759000],[171,19715800],[172,17152000],[173,10229600],[174,8641600],[175,9082200],[176,9671300],[177,17684300],[178,11920300],[179,7484900],[180,6693200],[181,5513800],[182,6117500],[183,10858300],[184,8902800],[185,7381500],[186,5630900],[187,7762700],[188,12223900],[189,9640100],[190,7895800],[191,21223600],[192,28948500],[193,17743400],[194,13402700],[195,12088600],[196,21497800],[197,34900300],[198,17704500],[199,18703400],[200,22406100],[201,24206200],[202,25191400],[203,16319900],[204,12509400],[205,12683500],[206,9985700],[207,20776300],[208,12206800],[209,9951200],[210,20910500],[211,15069700],[212,10277000],[213,13929300],[214,16652500],[215,17619200],[216,18812000],[217,18143700],[218,14820100],[219,9089900],[220,7433800],[221,7918000],[222,10583500],[223,7407700],[224,8311300],[225,5832800],[226,11284700],[227,10553100],[228,8026300],[229,6129600],[230,11233100],[231,13732700],[232,13611400],[233,23178900],[234,9585500],[235,9743400],[236,7164700],[237,5864300],[238,8269500],[239,5643900],[240,7244800],[241,5888700],[242,5209400],[243,5902500],[244,4441500],[245,5734800],[246,6827600],[247,7410400],[248,6540900],[249,8042700],[250,7051100],[251,3825300],[252,11788700],[253,5510400],[254,6784100],[255,5796600],[256,8504900],[257,4347100],[258,3735100],[259,5863400],[260,4757600],[261,4959300],[262,2720000],[263,3391200],[264,4184900],[265,7452800],[266,6594100],[267,4351700],[268,10310100],[269,10256300],[270,11185000],[271,15377000],[272,7349700],[273,5742900],[274,9346400],[275,9776500],[276,12619900],[277,8339700],[278,9731600],[279,6819700],[280,7918200],[281,5542800],[282,8761600],[283,9117400],[284,9092600],[285,8279000],[286,7929500],[287,6742900],[288,5517400],[289,8484300],[290,9151200],[291,10544100],[292,8499100],[293,7507600],[294,6896400],[295,6872000],[296,7902100],[297,22440600],[298,9404400],[299,6847000],[300,8841700],[301,5101500],[302,5861900],[303,14245000],[304,16247000],[305,10526800],[306,7355100],[307,8744100],[308,9489300],[309,7857200],[310,10361600],[311,8973200],[312,6998300],[313,7642700],[314,8569500],[315,8561300],[316,9058400],[317,6845700],[318,10237000],[319,9539800],[320,9923900],[321,4791900],[322,10869500],[323,21200600],[324,15456200],[325,9480400],[326,7444000],[327,10095800],[328,15020200],[329,11428800],[330,8818100],[331,7538200],[332,6882800],[333,8059600],[334,6512200],[335,5932000],[336,13740500],[337,21815600],[338,9972900],[339,11167600],[340,7495600],[341,4552200],[342,6656900],[343,7207400],[344,6891300],[345,7499100],[346,12905700],[347,15100400],[348,10665200],[349,17622300],[350,12743900],[351,9034700],[352,8857000],[353,10041500],[354,7621900],[355,7176400],[356,20032100],[357,14451300],[358,40548700],[359,22482600],[360,15369100],[361,18596300],[362,12809100],[363,8395500],[364,8490800],[365,14396900],[366,26608600],[367,11503000],[368,18172500],[369,8851800],[370,16486500],[371,20686200],[372,11700100],[373,14751100],[374,19453100],[375,14522100],[376,12621400],[377,21105400],[378,14019100],[379,8367200],[380,6448600],[381,12498800],[382,6456400],[383,10130300],[384,39204500],[385,11967900],[386,17950400],[387,11797700],[388,8869400],[389,9812500],[390,11503400],[391,13794600],[392,19241200],[393,13589100],[394,18324300],[395,12633300],[396,9906700],[397,8426600],[398,10359500],[399,9762300],[400,7569000],[401,6117700],[402,14948200],[403,6973300],[404,8885500],[405,17942800],[406,14607200],[407,27961300],[408,8035300],[409,15606700],[410,13212500],[411,8558900],[412,6983200],[413,9241500],[414,11043400],[415,5993200],[416,6518100],[417,8236500],[418,7035700],[419,6677800],[420,7535900],[421,22234100],[422,8386900],[423,9469400],[424,7199000],[425,8197000],[426,7372400],[427,10222000],[428,13009200],[429,7764800],[430,4611300],[431,5990300],[432,5068000],[433,9001900],[434,6161100],[435,8870600],[436,10029800],[437,8554800],[438,5245200],[439,10418300],[440,5803600],[441,11293500],[442,8567000],[443,8925200],[444,9520100],[445,8133300],[446,3632300],[447,4273200],[448,7915700],[449,6239000],[450,6342600],[451,5524200],[452,10165700],[453,8464000],[454,10328800],[455,6123300],[456,4988500],[457,7628500],[458,7737200],[459,6738700],[460,5153100],[461,6985300],[462,4008800],[463,8625500],[464,5980100],[465,5282500],[466,3524800],[467,4085100],[468,3687000],[469,6617900],[470,5577200],[471,2132400],[472,4932600],[473,3653800],[474,5964900],[475,4420400],[476,5949400],[477,4867700],[478,6894400],[479,7430500],[480,5798600],[481,7373500],[482,8180600],[483,9075200],[484,11524300],[485,7857100],[486,5722200],[487,5401700],[488,5617900],[489,4075700],[490,4477200],[491,5397400],[492,7008100],[493,6303500],[494,5080700],[495,3789100],[496,5690900],[497,4249100],[498,4247000],[499,3744300],[500,4946400],[501,6607100],[502,5814600],[503,5060200],[504,4911000],[505,4000900],[506,4144500],[507,3611300],[508,3466200],[509,2461300],[510,4151800],[511,4007800],[512,4069100],[513,2916400],[514,2660000],[515,4062400],[516,3712600],[517,3719600],[518,3066000],[519,4500000],[520,5427400],[521,9644400],[522,5337400],[523,7488000],[524,7076700],[525,14181600],[526,9086800],[527,10653500],[528,4638400],[529,5588200],[530,5250300],[531,5805700],[532,5061400],[533,3275600],[534,3629800],[535,5432700],[536,6493200],[537,5533400],[538,7271300],[539,7013200],[540,9524400],[541,5586000],[542,4801800],[543,3594100],[544,4271100],[545,4763600],[546,5880800],[547,7594600],[548,10872800],[549,14367700],[550,8349200],[551,8973900],[552,6894000],[553,6495900],[554,6484600],[555,6197200],[556,5318200],[557,5040900],[558,4844200],[559,4934600],[560,4833900],[561,7872700],[562,4811700],[563,2742300],[564,4293600],[565,7053200],[566,8056600],[567,4893900],[568,5237900],[569,5002600],[570,8317200],[571,4381300],[572,1657700],[573,7194200],[574,7654400],[575,6157200],[576,5493900],[577,5545900],[578,4822600],[579,4020300],[580,4390200],[581,4597500],[582,3889900],[583,3215200],[584,4169900],[585,4591400],[586,4638000],[587,4244900],[588,7820000],[589,6428300],[590,4189500],[591,6864800],[592,3941900],[593,2024900],[594,4123500],[595,3063100],[596,2507700],[597,7527500],[598,7787700],[599,6769400],[600,4686900],[601,5339800],[602,5857600],[603,7001500],[604,4333000],[605,7446800],[606,6574900],[607,5858800],[608,4809500],[609,5305200],[610,4539600],[611,5862000],[612,6253100],[613,5415600],[614,4679300],[615,4112000],[616,8642900],[617,14373800],[618,6195000],[619,7117800],[620,5231700],[621,3781100],[622,4037100],[623,4825300],[624,5706700],[625,4008400],[626,5547300],[627,3996300],[628,5987000],[629,3978200],[630,5581000],[631,5668500],[632,3838200],[633,3911300],[634,9134700],[635,7884600],[636,8536200],[637,6527600],[638,6116300],[639,7311100],[640,6332900],[641,5271300],[642,4812300],[643,3366500],[644,6240700],[645,7882300],[646,3740000],[647,5252200],[648,5049000],[649,3291000],[650,5711000],[651,5528300],[652,4025500],[653,4633100],[654,3201200],[655,4450800],[656,3884400],[657,3264400],[658,3394400],[659,6328700],[660,3703800],[661,2679600],[662,2997000],[663,2946100],[664,3751400],[665,2670000],[666,2652800],[667,4980400],[668,3064500],[669,5495900],[670,7656400],[671,11352600],[672,5440400],[673,3648500],[674,3860800],[675,4010900],[676,2890800],[677,3538700],[678,3571300],[679,2981100],[680,3528800],[681,3769300],[682,2994900],[683,2869700],[684,3867800],[685,3654800],[686,2793400],[687,3014400],[688,4063800],[689,6296800],[690,4570400],[691,3297900],[692,6065000],[693,3770000],[694,4842400],[695,4117800],[696,5246400],[697,5147500],[698,6862700],[699,8599800],[700,4657400],[701,7036300],[702,10149600],[703,7690300],[704,10488400],[705,6232600],[706,4539500],[707,6147700],[708,6943300],[709,4523500],[710,5944900],[711,4763800],[712,4263400],[713,4256300],[714,4350100],[715,6768200],[716,7791000],[717,5488700],[718,6023400],[719,3814400],[720,3813400],[721,3362800],[722,1827000],[723,4867300],[724,2705900],[725,3617000],[726,3760000],[727,3267200],[728,3404000],[729,5033300],[730,6550000],[731,4211200],[732,5973900],[733,6477800],[734,16026500],[735,6227900],[736,5346600],[737,5453500],[738,6779400],[739,5361400],[740,3798800],[741,4159100],[742,4329800],[743,3117100],[744,3090600],[745,3582100],[746,4191400],[747,3955500],[748,4764500],[749,5000100],[750,3022500],[751,3574300],[752,5337100],[753,8438400],[754,5236600],[755,2589800],[756,3546200],[757,3076000],[758,2995400],[759,2447200],[760,2271800],[761,2889400],[762,2476800],[763,2583400],[764,2681700],[765,3633900],[766,3241700],[767,3576700],[768,3590700],[769,3198900],[770,2680300],[771,2946000],[772,1873300],[773,2723500],[774,2140600],[775,4107700],[776,5477500],[777,5485600],[778,6957000],[779,5210800],[780,2647400],[781,3234400],[782,1980100],[783,2448000],[784,4640000],[785,6838000],[786,3806000],[787,2931500],[788,4895400],[789,4980400],[790,8533500],[791,5190300],[792,11509700],[793,6652800],[794,6838600],[795,5661300],[796,5784700],[797,8650500],[798,14154000],[799,6490000],[800,6575800],[801,7324000],[802,5687900],[803,3258600],[804,3008400],[805,6798600],[806,6525900],[807,6407200],[808,5639100],[809,8778300],[810,8267700],[811,7997400],[812,15612500],[813,10487700],[814,10060700],[815,8181000],[816,7739800],[817,6871200],[818,8813800],[819,5459400],[820,9527300],[821,6931900],[822,2558000],[823,6420500],[824,8805500],[825,7750600],[826,6167400],[827,7697600],[828,4269900],[829,4157500],[830,4117400],[831,4850900],[832,3785200],[833,3184500],[834,5414700],[835,5991000],[836,5013900],[837,3636600],[838,5453000],[839,7029600],[840,4397100],[841,4295200],[842,5103700],[843,1503500],[844,2500600],[845,2921800],[846,2503100],[847,2336300],[848,4247000],[849,3202600],[850,5273500],[851,6282100],[852,5248700],[853,6677200],[854,6207900],[855,4946700],[856,4355600],[857,5290800],[858,10478800],[859,8104500],[860,8265800],[861,9000100],[862,16687700],[863,9156200],[864,6831100],[865,5752900],[866,6028300],[867,7817400],[868,10447200],[869,16711900],[870,12923200],[871,11023400],[872,7492300],[873,7830900],[874,6739400],[875,5758900],[876,6576800],[877,6090200],[878,6400800],[879,5080100],[880,6259400],[881,6556700],[882,5527300],[883,5445500],[884,8188300],[885,22296900],[886,9992200],[887,6308700],[888,9281700],[889,7495200],[890,13472400],[891,7288500],[892,7348000],[893,7930200],[894,7871400],[895,8520100],[896,6481500],[897,7647300],[898,6448000],[899,7794500],[900,7103700],[901,6062400],[902,9522900],[903,6714900],[904,5710500],[905,4919500],[906,5665800],[907,4322700],[908,4368800],[909,6027000],[910,5940600],[911,6391200],[912,5843300],[913,5800900],[914,4493800],[915,5961200],[916,5049400],[917,3791600],[918,3766400],[919,4436400],[920,7453000],[921,7133100],[922,16860300],[923,7254200],[924,7843800],[925,4798100],[926,4068400],[927,4022900],[928,3954200],[929,4276200],[930,7784100],[931,6555200],[932,6879300],[933,6091000],[934,4537100],[935,6541200],[936,5051200],[937,4446100],[938,4821300],[939,5061600],[940,4326600],[941,4296000],[942,4022100],[943,5565300],[944,3246600],[945,6301600],[946,4312200],[947,4394600],[948,3610700],[949,3976800],[950,4754900],[951,3136900],[952,3615700],[953,4268700],[954,3344000],[955,3897400],[956,4679900],[957,5267200],[958,3620100],[959,3776700],[960,5390700],[961,6060500],[962,3506400],[963,3434600],[964,3285800],[965,5587600],[966,5830600],[967,3597200],[968,4637000],[969,3911100],[970,5549400],[971,5073700],[972,3683000],[973,4874800],[974,4148700],[975,2368800],[976,4198600],[977,4406200],[978,4081100],[979,4263500],[980,4822900],[981,4398500],[982,6015000],[983,4674700],[984,5491200],[985,10783800],[986,5802900],[987,4619400],[988,4695400],[989,3466300],[990,3064300],[991,3121800],[992,2711800],[993,3459200],[994,2827400],[995,2969000],[996,2459100],[997,3510200],[998,3346000],[999,2711600],[1000,3700900],[1001,4199600],[1002,2731100],[1003,3602700],[1004,2888200],[1005,3487200],[1006,3264000],[1007,2970000],[1008,3969700],[1009,3437900],[1010,2264900],[1011,1975500],[1012,3182200],[1013,4354700],[1014,3004500],[1015,3768100],[1016,6020400],[1017,4281600],[1018,4792700],[1019,4470900],[1020,8890500],[1021,7143600],[1022,6141100],[1023,6401000],[1024,5983600],[1025,6490000],[1026,6888400],[1027,8953200],[1028,8395600],[1029,9552700],[1030,4321000],[1031,5106300],[1032,4186300],[1033,4919500],[1034,5252400],[1035,10623400],[1036,9451900],[1037,6082700],[1038,5936400],[1039,7925900],[1040,11084200],[1041,10807000],[1042,11668000],[1043,7982100],[1044,10402000],[1045,8733100],[1046,7515800],[1047,6614000],[1048,13980400],[1049,13881200],[1050,6649600],[1051,5628300],[1052,6445200],[1053,6404700],[1054,7221800],[1055,6134700],[1056,7964800],[1057,9656600],[1058,7894700],[1059,7299400],[1060,5642900],[1061,7277700],[1062,6902100],[1063,8186900],[1064,4622900],[1065,8097595],[1066,10148785],[1067,10054453],[1068,13239068],[1069,9518466],[1070,7544451],[1071,8348791],[1072,7841605],[1073,9780746],[1074,10246338],[1075,10059557],[1076,10774259],[1077,6359179],[1078,0],[1079,2566368],[1080,5711464],[1081,5841927],[1082,5906616],[1083,4887799],[1084,6523543],[1085,8145300],[1086,6891773],[1087,5239603],[1088,6181078],[1089,5722856],[1090,6738806],[1091,7199994],[1092,5789689],[1093,4764056],[1094,5670140],[1095,3919429],[1096,3783790],[1097,1921757],[1098,0],[1099,1961122],[1100,3702166],[1101,3845369],[1102,2887334],[1103,0],[1104,3617574],[1105,4891063],[1106,6426845],[1107,4495295],[1108,3601466],[1109,4341085],[1110,3304863],[1111,4433603],[1112,5577379],[1113,5936381],[1114,5225959],[1115,5050088],[1116,4927534],[1117,8266320],[1118,10732775],[1119,4611581],[1120,4929544],[1121,7693202],[1122,7284342],[1123,4672843],[1124,5206915],[1125,6561634],[1126,6817851],[1127,7265283],[1128,7041797],[1129,4983224],[1130,7105831],[1131,5232088],[1132,5551383],[1133,4147107],[1134,5680732],[1135,6025999],[1136,4989553],[1137,6217692],[1138,5220506],[1139,6101985],[1140,6440776],[1141,5607758],[1142,5420892],[1143,5789674],[1144,6524207],[1145,7820133],[1146,6530631],[1147,7238087],[1148,6929592],[1149,6731733],[1150,5927178],[1151,5026330],[1152,3907609],[1153,4947256],[1154,4715786],[1155,5013619],[1156,4111476],[1157,4738590],[1158,4272085],[1159,3821808],[1160,4337117],[1161,6004769],[1162,3323401],[1163,3096702],[1164,3658421],[1165,3303042],[1166,4489367],[1167,3770328],[1168,3281760],[1169,3681433],[1170,2765142],[1171,3383146],[1172,0],[1173,3050081],[1174,3429359],[1175,4935003],[1176,10185094],[1177,10734963],[1178,4429555],[1179,3697301],[1180,3503616],[1181,2611240],[1182,3386147],[1183,2291125],[1184,2943938],[1185,3610160],[1186,4361069],[1187,2428611],[1188,3204843],[1189,2401096],[1190,2633743],[1191,3000724],[1192,3865597],[1193,2560736],[1194,3796453],[1195,2852384],[1196,2937904],[1197,3016859],[1198,3352055],[1199,2837823],[1200,2284191],[1201,2720300],[1202,1718843],[1203,3104776],[1204,3035892],[1205,2668993],[1206,2649405],[1207,3323431],[1208,2626012],[1209,3535593],[1210,3639434],[1211,3681002],[1212,3098931],[1213,3255945],[1214,3358870],[1215,2866040],[1216,2918429],[1217,3737299],[1218,3050261],[1219,3490947],[1220,3087653],[1221,4261008],[1222,4124360],[1223,2899710],[1224,2457992],[1225,3042038],[1226,3257482],[1227,2169518],[1228,2594683],[1229,2310768],[1230,2517630],[1231,0],[1232,2262557],[1233,3260307],[1234,3441854],[1235,3275816],[1236,2929559],[1237,4047557],[1238,2896461],[1239,3779342],[1240,6554412],[1241,6854734],[1242,3154002],[1243,2969146],[1244,2586960],[1245,3479378],[1246,3629454],[1247,2505329],[1248,2541052],[1249,1987216],[1250,3200547],[1251,2861550],[1252,2591173],[1253,2390098],[1254,2342227],[1255,2111395],[1256,2543392],[1257,1741979],[1258,2341768],[1259,1995640],[1260,1676559],[1261,2620304],[1262,2357493],[1263,2260091],[1264,4002454],[1265,3564367],[1266,2459325],[1267,2343030],[1268,1988449],[1269,2000000],[1270,1771808],[1271,1957955],[1272,2595091],[1273,1806518],[1274,1646354],[1275,1499873],[1276,2656609],[1277,2195496],[1278,2535304],[1279,1902811],[1280,1977667],[1281,2398607],[1282,2587367],[1283,4483447],[1284,3284248],[1285,2117567],[1286,3041830],[1287,2700820],[1288,2528646],[1289,2052014],[1290,1843168],[1291,2099379],[1292,3141701],[1293,2816234],[1294,2600805],[1295,2144652],[1296,2732977],[1297,4877683],[1298,4306504],[1299,2739892],[1300,3324320],[1301,3042242],[1302,3265055],[1303,6100353],[1304,8845714],[1305,3220167],[1306,4044439],[1307,3673168],[1308,2337087],[1309,2393191],[1310,2973706],[1311,3218033],[1312,2568660],[1313,2518762],[1314,3469738],[1315,3202875],[1316,2382892],[1317,2333629],[1318,1848039],[1319,1826705],[1320,2651426],[1321,2231476],[1322,2321856],[1323,1886395],[1324,1668092],[1325,2199136],[1326,1920765],[1327,1550127],[1328,2168302],[1329,2006202],[1330,2548562],[1331,1608648],[1332,1461405],[1333,0],[1334,1384523],[1335,1725231],[1336,2321273],[1337,1665225],[1338,1429399],[1339,2514042],[1340,1636587],[1341,1525524],[1342,1781288],[1343,1669525],[1344,1723378],[1345,1913572],[1346,2280340],[1347,2809751],[1348,2640762],[1349,3532540],[1350,2571981],[1351,1884290],[1352,2075311],[1353,858620],[1354,0],[1355,1698015],[1356,1427712],[1357,1466379],[1358,1220214],[1359,0],[1360,1957963],[1361,3007857],[1362,3980628],[1363,6418020],[1364,4724735],[1365,7216804],[1366,4853249],[1367,6499074],[1368,4241570],[1369,5437698],[1370,0],[1371,4317143],[1372,3253498],[1373,6307634],[1374,6807653],[1375,4421012],[1376,4356767],[1377,3965467],[1378,3231041],[1379,4141196],[1380,2253021],[1381,4096305],[1382,2999890],[1383,3382732],[1384,3157048],[1385,2695412],[1386,2828685],[1387,2675794],[1388,2411090],[1389,2280371],[1390,0],[1391,3654824],[1392,2030680],[1393,2339250],[1394,2555348],[1395,2144741],[1396,2874790],[1397,2326901],[1398,3309373],[1399,2049372],[1400,2238334],[1401,4357461],[1402,3090124],[1403,3184077]]; +var summaryData = [[0,100.34],[14,102.31],[28,131.08],[42,147.94],[56,172.55],[70,181.05],[84,180.08],[98,193.85],[112,190.34],[126,197.90],[140,179.98],[154,180.51],[168,198.10],[182,227.80],[196,277.27],[210,286.70],[224,293.35],[238,287.76],[252,279.99],[266,295.39],[280,306.00],[294,303.28],[308,395.03],[322,423.48],[336,430.15],[351,469.76],[365,432.66],[379,366.59],[393,337.06],[407,390.00],[421,437.10],[435,387.00],[449,382.62],[463,402.13],[477,417.25],[491,375.51],[505,377.30],[519,384.09],[533,401.90],[547,426.06],[561,475.00],[575,484.65],[589,468.63],[603,499.72],[617,481.75],[631,475.85],[645,448.00],[659,472.60],[673,477.53],[687,461.78],[702,518.84],[716,527.42],[730,552.99],[744,503.00],[758,512.19],[772,524.78],[786,584.02],[800,675.77],[814,632.07],[828,681.53],[842,696.69],[856,653.82],[870,495.43],[884,486.44],[898,437.92],[912,471.09],[926,543.04],[940,576.30],[954,572.22],[968,542.30],[982,516.09],[996,463.00],[1010,490.59],[1024,437.66],[1038,390.49],[1053,352.32],[1067,291.00],[1081,275.11],[1095,297.11],[1109,315.07],[1123,338.53],[1137,346.45],[1151,323.53],[1165,354.09],[1179,381.47],[1193,407.98],[1207,426.56],[1221,420.09],[1235,410.39],[1249,436.24],[1263,443.97],[1277,463.97],[1291,498.53],[1305,552.09],[1319,551.10],[1333,585.74],[1347,597.76],[1361,623.99],[1375,540.00],[1403,554.59]]; +var flagData = [[28, 'Sample Flag']]; \ No newline at end of file diff --git a/sample_for_plotting/js/demo.js b/sample_for_plotting/js/demo.js new file mode 100644 index 0000000..049343c --- /dev/null +++ b/sample_for_plotting/js/demo.js @@ -0,0 +1,57 @@ +Event.observe(document, 'dom:loaded', function() { + + prettyPrint(); + + HumbleFinance.trackFormatter = function (obj) { + + var x = Math.floor(obj.x); + var data = jsonData[x]; + var text = data.date + " Price: " + data.close + " Vol: " + data.volume; + + return text; + }; + + HumbleFinance.yTickFormatter = function (n) { + + if (n == this.axes.y.max) { + return false; + } + + return '$'+n; + }; + + HumbleFinance.xTickFormatter = function (n) { + + if (n == 0) { + return false; + } + + var date = jsonData[n].date; + date = date.split(' '); + date = date[2]; + + return date; + } + + HumbleFinance.init('finance', priceData, volumeData, summaryData); + HumbleFinance.setFlags(flagData); + + var xaxis = HumbleFinance.graphs.summary.axes.x; + var prevSelection = HumbleFinance.graphs.summary.prevSelection; + var xmin = xaxis.p2d(prevSelection.first.x); + var xmax = xaxis.p2d(prevSelection.second.x); + + $('dateRange').update(jsonData[xmin].date + ' - ' + jsonData[xmax].date); + + Event.observe(HumbleFinance.containers.summary, 'flotr:select', function (e) { + + var area = e.memo[0]; + xmin = Math.floor(area.x1); + xmax = Math.ceil(area.x2); + + var date1 = jsonData[xmin].date; + var date2 = jsonData[xmax].date; + + $('dateRange').update(jsonData[xmin].date + ' - ' + jsonData[xmax].date); + }); +}); \ No newline at end of file diff --git a/sample_for_plotting/js/excanvas.js b/sample_for_plotting/js/excanvas.js new file mode 100644 index 0000000..73963d8 --- /dev/null +++ b/sample_for_plotting/js/excanvas.js @@ -0,0 +1,884 @@ +// 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 are not implemented. +// * 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; + + /** + * 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))); + }; + } + + var G_vmlCanvasManager_ = { + init: function(opt_doc) { + if (/MSIE/.test(navigator.userAgent) && !window.opera) { + 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) { + // create xmlns + if (!doc.namespaces['g_vml_']) { + doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml', + '#default#VML'); + + } + if (!doc.namespaces['g_o_']) { + doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office', + '#default#VML'); + } + + // 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}' + + 'g_vml_\\:*{behavior:url(#default#VML)}' + + 'g_o_\\:*{behavior:url(#default#VML)}'; + + } + + // 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; + + // 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.style.width = el.attributes.width.nodeValue + 'px'; + el.getContext().clearRect(); + break; + case 'height': + el.style.height = el.attributes.height.nodeValue + 'px'; + el.getContext().clearRect(); + 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 dec2hex = []; + for (var i = 0; i < 16; i++) { + for (var j = 0; j < 16; j++) { + dec2hex[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.arcScaleX_ = o1.arcScaleX_; + o2.arcScaleY_ = o1.arcScaleY_; + o2.lineScale_ = o1.lineScale_; + } + + function processStyle(styleString) { + var str, alpha = 1; + + styleString = String(styleString); + if (styleString.substring(0, 3) == 'rgb') { + var start = styleString.indexOf('(', 3); + var end = styleString.indexOf(')', start + 1); + var guts = styleString.substring(start + 1, end).split(','); + + str = '#'; + for (var i = 0; i < 3; i++) { + str += dec2hex[Number(guts[i])]; + } + + if (guts.length == 4 && styleString.substr(3, 1) == 'a') { + alpha = guts[3]; + } + } else { + str = styleString; + } + + return {color: str, alpha: alpha}; + } + + 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} surfaceElement The element that the 2D context should + * be associated with + */ + function CanvasRenderingContext2D_(surfaceElement) { + 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.canvas = surfaceElement; + + var el = surfaceElement.ownerDocument.createElement('div'); + el.style.width = surfaceElement.clientWidth + 'px'; + el.style.height = surfaceElement.clientHeight + 'px'; + el.style.overflow = 'hidden'; + el.style.position = 'absolute'; + surfaceElement.appendChild(el); + + this.element_ = el; + this.arcScaleX_ = 1; + this.arcScaleY_ = 1; + this.lineScale_ = 1; + } + + var contextPrototype = CanvasRenderingContext2D_.prototype; + contextPrototype.clearRect = function() { + 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 a = processStyle(aFill ? this.fillStyle : this.strokeStyle); + var color = a.color; + var opacity = a.alpha * this.globalAlpha; + + var W = 10; + var H = 10; + + lineStr.push(''); + + if (!aFill) { + var lineWidth = this.lineScale_ * this.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( + '' + ); + } else if (typeof this.fillStyle == 'object') { + var fillStyle = this.fillStyle; + 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_ / this.arcScaleX_; + var y0 = fillStyle.y0_ / this.arcScaleY_; + var x1 = fillStyle.x1_ / this.arcScaleX_; + var y1 = fillStyle.y1_ / this.arcScaleY_; + var p0 = this.getCoords_(x0, y0); + var p1 = this.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 = this.getCoords_(fillStyle.x0_, fillStyle.y0_); + var width = max.x - min.x; + var height = max.y - min.y; + focus = { + x: (p0.x - min.x) / width, + y: (p0.y - min.y) / height + }; + + width /= this.arcScaleX_ * Z; + height /= this.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 * this.globalAlpha; + var opacity2 = stops[length - 1].alpha * this.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 { + lineStr.push(''); + } + + lineStr.push(''); + + this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); + }; + + 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() { + copyState(this.aStack_.pop(), this); + this.m_ = this.mStack_.pop(); + }; + + contextPrototype.translate = function(aX, aY) { + var m1 = [ + [1, 0, 0], + [0, 1, 0], + [aX, aY, 1] + ]; + + this.m_ = matrixMultiply(m1, this.m_); + }; + + contextPrototype.rotate = function(aRot) { + var c = mc(aRot); + var s = ms(aRot); + + var m1 = [ + [c, s, 0], + [-s, c, 0], + [0, 0, 1] + ]; + + this.m_ = matrixMultiply(m1, this.m_); + }; + + contextPrototype.scale = function(aX, aY) { + this.arcScaleX_ *= aX; + this.arcScaleY_ *= aY; + var m1 = [ + [aX, 0, 0], + [0, aY, 0], + [0, 0, 1] + ]; + + var m = this.m_ = matrixMultiply(m1, this.m_); + + // 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]; + this.lineScale_ = sqrt(abs(det)); + }; + + /******** STUBS ********/ + contextPrototype.clip = function() { + // TODO: Implement + }; + + contextPrototype.arcTo = function() { + // TODO: Implement + }; + + contextPrototype.createPattern = function() { + return new CanvasPattern_; + }; + + // 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_() {} + + // set up externs + G_vmlCanvasManager = G_vmlCanvasManager_; + CanvasRenderingContext2D = CanvasRenderingContext2D_; + CanvasGradient = CanvasGradient_; + CanvasPattern = CanvasPattern_; + +})(); + +} // if diff --git a/sample_for_plotting/js/flotr.js b/sample_for_plotting/js/flotr.js new file mode 100644 index 0000000..5301dad --- /dev/null +++ b/sample_for_plotting/js/flotr.js @@ -0,0 +1,3835 @@ +/* $Id: flotr.js 147 2009-08-21 10:23:33Z fabien.menager $ */ + +/** + * @projectDescription Flotr is a javascript plotting library based on the Prototype Javascript Framework. + * @author Bas Wenneker + * @license MIT License + * @version 0.2.0 + */ +var Flotr = { + version: '%version%', + author: 'Bas Wenneker', + website: 'http://www.solutoire.com', + /** + * An object of the registered graph types. Use Flotr.addType(type, object) + * to add your own type. + */ + graphTypes: {}, + /** + * The list of the registered plugins + */ + plugins: {}, + /** + * Can be used to add your own chart type. + * @param {String} name - Type of chart, like 'pies', 'bars' etc. + * @param {String} graphType - The object containing the basic drawing functions (draw, etc) + */ + addType: function(name, graphType){ + Flotr.graphTypes[name] = graphType; + Flotr.defaultOptions[name] = graphType.options || {}; + Flotr.defaultOptions.defaultType = Flotr.defaultOptions.defaultType || name; + }, + /** + * Can be used to add a plugin + * @param {String} name - The name of the plugin + * @param {String} plugin - The object containing the plugin's data (callbacks, options, function1, function2, ...) + */ + addPlugin: function(name, plugin){ + Flotr.plugins[name] = plugin; + Flotr.defaultOptions[name] = plugin.options || {}; + }, + /** + * Draws the graph. This function is here for backwards compatibility with Flotr version 0.1.0alpha. + * You could also draw graphs by directly calling Flotr.Graph(element, data, options). + * @param {Element} el - element to insert the graph into + * @param {Object} data - an array or object of dataseries + * @param {Object} options - an object containing options + * @param {Class} _GraphKlass_ - (optional) Class to pass the arguments to, defaults to Flotr.Graph + * @return {Object} returns a new graph object and of course draws the graph. + */ + draw: function(el, data, options, GraphKlass){ + GraphKlass = GraphKlass || Flotr.Graph; + return new GraphKlass(el, data, options); + }, + /** + * Collects dataseries from input and parses the series into the right format. It returns an Array + * of Objects each having at least the 'data' key set. + * @param {Array, Object} data - Object or array of dataseries + * @return {Array} Array of Objects parsed into the right format ({(...,) data: [[x1,y1], [x2,y2], ...] (, ...)}) + */ + getSeries: function(data){ + return data.collect(function(serie){ + var i; + serie = (serie.data) ? Object.clone(serie) : {data: serie}; + for (i = serie.data.length-1; i > -1; --i) { + serie.data[i][1] = (serie.data[i][1] === null ? null : parseFloat(serie.data[i][1])); + } + return serie; + }); + }, + /** + * Recursively merges two objects. + * @param {Object} src - source object (likely the object with the least properties) + * @param {Object} dest - destination object (optional, object with the most properties) + * @return {Object} recursively merged Object + */ + merge: function(src, dest){ + var i, v, result = dest || {}; + for(i in src){ + v = src[i]; + result[i] = (v && typeof(v) === 'object' && !(v.constructor === Array || v.constructor === RegExp) && !Object.isElement(v)) ? Flotr.merge(v, dest[i]) : result[i] = v; + } + return result; + }, + /** + * Recursively clones an object. + * @param {Object} object - The object to clone + * @return {Object} the clone + */ + clone: function(object){ + var i, v, clone = {}; + for(i in object){ + v = object[i]; + clone[i] = (v && typeof(v) === 'object' && !(v.constructor === Array || v.constructor === RegExp) && !Object.isElement(v)) ? Flotr.clone(v) : v; + } + return clone; + }, + /** + * Function calculates the ticksize and returns it. + * @param {Integer} noTicks - number of ticks + * @param {Integer} min - lower bound integer value for the current axis + * @param {Integer} max - upper bound integer value for the current axis + * @param {Integer} decimals - number of decimals for the ticks + * @return {Integer} returns the ticksize in pixels + */ + getTickSize: function(noTicks, min, max, decimals){ + var delta = (max - min) / noTicks, + magn = Flotr.getMagnitude(delta), + tickSize = 10, + norm = delta / magn; // Norm is between 1.0 and 10.0. + + if(norm < 1.5) tickSize = 1; + else if(norm < 2.25) tickSize = 2; + else if(norm < 3) tickSize = ((decimals == 0) ? 2 : 2.5); + else if(norm < 7.5) tickSize = 5; + + return tickSize * magn; + }, + /** + * Default tick formatter. + * @param {String, Integer} val - tick value integer + * @return {String} formatted tick string + */ + defaultTickFormatter: function(val){ + return val+''; + }, + /** + * Formats the mouse tracker values. + * @param {Object} obj - Track value Object {x:..,y:..} + * @return {String} Formatted track string + */ + defaultTrackFormatter: function(obj){ + return '('+obj.x+', '+obj.y+')'; + }, + /** + * Utility function to convert file size values in bytes to kB, MB, ... + * @param value {Number} - The value to convert + * @param precision {Number} - The number of digits after the comma (default: 2) + * @param base {Number} - The base (default: 1000) + */ + engineeringNotation: function(value, precision, base){ + var sizes = ['Y','Z','E','P','T','G','M','k',''], + fractionSizes = ['y','z','a','f','p','n','�','m',''], + total = sizes.length; + + base = base || 1000; + precision = Math.pow(10, precision || 2); + + if (value == 0) return 0; + + if (value > 1) { + while (total-- && (value >= base)) value /= base; + } + else { + sizes = fractionSizes; + total = sizes.length; + while (total-- && (value < 1)) value *= base; + } + + return (Math.round(value * precision) / precision) + sizes[total]; + }, + /** + * Returns the magnitude of the input value. + * @param {Integer, Float} x - integer or float value + * @return {Integer, Float} returns the magnitude of the input value + */ + getMagnitude: function(x){ + return Math.pow(10, Math.floor(Math.log(x) / Math.LN10)); + }, + toPixel: function(val){ + return Math.floor(val)+0.5;//((val-Math.round(val) < 0.4) ? (Math.floor(val)-0.5) : val); + }, + toRad: function(angle){ + return -angle * (Math.PI/180); + }, + floorInBase: function(n, base) { + return base * Math.floor(n / base); + } +}; + +Flotr.defaultOptions = { + colors: ['#00A8F0', '#C0D800', '#CB4B4B', '#4DA74D', '#9440ED'], //=> The default colorscheme. When there are > 5 series, additional colors are generated. + title: null, // => The graph's title + subtitle: null, // => The graph's subtitle + shadowSize: 4, // => size of the 'fake' shadow + defaultType: null, // => default series type + HtmlText: true, // => wether to draw the text using HTML or on the canvas + fontSize: 7.5, // => canvas' text font size + resolution: 1, // => resolution of the graph, to have printer-friendly graphs ! + legend: { + show: true, // => setting to true will show the legend, hide otherwise + noColumns: 1, // => number of colums in legend table // @todo: doesn't work for HtmlText = false + labelFormatter: function(v){return v}, // => fn: string -> string + labelBoxBorderColor: '#CCCCCC', // => border color for the little label boxes + labelBoxWidth: 14, + labelBoxHeight: 10, + labelBoxMargin: 5, + container: null, // => container (as jQuery object) to put legend in, null means default on top of graph + position: 'nw', // => position of default legend container within plot + margin: 5, // => distance from grid edge to default legend container within plot + backgroundColor: null, // => null means auto-detect + backgroundOpacity: 0.85// => set to 0 to avoid background, set to 1 for a solid background + }, + xaxis: { + ticks: null, // => format: either [1, 3] or [[1, 'a'], 3] + showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise + labelsAngle: 0, // => labels' angle, in degrees + title: null, // => axis title + titleAngle: 0, // => axis title's angle, in degrees + noTicks: 5, // => number of ticks for automagically generated ticks + tickFormatter: Flotr.defaultTickFormatter, // => fn: number -> string + tickDecimals: null, // => no. of decimals, null means auto + min: null, // => min. value to show, null means set automatically + max: null, // => max. value to show, null means set automatically + autoscaleMargin: 0, // => margin in % to add if auto-setting min/max + color: null, // => color of the ticks + mode: 'normal', // => can be 'time' or 'normal' + timeFormat: null, + scaling: 'linear', // => Scaling, can be 'linear' or 'logarithmic' + base: Math.E + }, + x2axis: {}, + yaxis: { + ticks: null, // => format: either [1, 3] or [[1, 'a'], 3] + showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise + labelsAngle: 0, // => labels' angle, in degrees + title: null, // => axis title + titleAngle: 90, // => axis title's angle, in degrees + noTicks: 5, // => number of ticks for automagically generated ticks + tickFormatter: Flotr.defaultTickFormatter, // => fn: number -> string + tickDecimals: null, // => no. of decimals, null means auto + min: null, // => min. value to show, null means set automatically + max: null, // => max. value to show, null means set automatically + autoscaleMargin: 0, // => margin in % to add if auto-setting min/max + color: null, // => The color of the ticks + scaling: 'linear', // => Scaling, can be 'linear' or 'logarithmic' + base: Math.E + }, + y2axis: { + titleAngle: 270 + }, + grid: { + color: '#545454', // => primary color used for outline and labels + backgroundColor: null, // => null for transparent, else color + tickColor: '#DDDDDD', // => color used for the ticks + labelMargin: 3, // => margin in pixels + verticalLines: true, // => whether to show gridlines in vertical direction + horizontalLines: true, // => whether to show gridlines in horizontal direction + outlineWidth: 2, // => width of the grid outline/border in pixels + circular: false // => if set to true, the grid will be circular, must be used when radars are drawn + }, + selection: { + mode: null, // => one of null, 'x', 'y' or 'xy' + color: '#B6D9FF', // => selection box color + fps: 20 // => frames-per-second + }, + crosshair: { + mode: null, // => one of null, 'x', 'y' or 'xy' + color: '#FF0000', // => crosshair color + hideCursor: true // => hide the cursor when the crosshair is shown + }, + mouse: { + track: false, // => true to track the mouse, no tracking otherwise + position: 'se', // => position of the value box (default south-east) + relative: false, // => next to the mouse cursor + trackFormatter: Flotr.defaultTrackFormatter, // => formats the values in the value box + margin: 5, // => margin in pixels of the valuebox + lineColor: '#FF3F19', // => line color of points that are drawn when mouse comes near a value of a series + trackDecimals: 1, // => decimals for the track values + sensibility: 2, // => the lower this number, the more precise you have to aim to show a value + radius: 3, // => radius of the track point + fillColor: null, // => color to fill our select bar with only applies to bar and similar graphs (only bars for now) + fillOpacity: 0.4 // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill + } +}; + +/** + * Flotr Graph class that plots a graph on creation. + */ +Flotr.Graph = Class.create({ + /** + * Flotr Graph constructor. + * @param {Element} el - element to insert the graph into + * @param {Object} data - an array or object of dataseries + * @param {Object} options - an object containing options + */ + initialize: function(el, data, options){ + this.el = $(el); + + if (!this.el) throw 'The target container doesn\'t exist'; + if (!this.el.clientWidth) throw 'The target container must be visible'; + + this.registerPlugins(); + + this.el.fire('flotr:beforeinit', [this]); + + // Initialize some variables + this.el.graph = this; + this.data = data; + this.lastMousePos = { pageX: null, pageY: null }; + this.selection = { first: { x: -1, y: -1}, second: { x: -1, y: -1} }; + this.plotOffset = {left: 0, right: 0, top: 0, bottom: 0}; + this.prevSelection = null; + this.selectionInterval = null; + this.ignoreClick = false; + this.prevHit = null; + this.series = Flotr.getSeries(data); + this.setOptions(options); + + var type, p; + for (type in Flotr.graphTypes) { + this[type] = Object.clone(Flotr.graphTypes[type]); + for (p in this[type]) { + if (Object.isFunction(this[type][p])) + this[type][p] = this[type][p].bind(this); + } + } + + // Create and prepare canvas. + this.constructCanvas(); + + this.el.fire('flotr:afterconstruct', [this]); + + // Add event handlers for mouse tracking, clicking and selection + this.initEvents(); + + this.findDataRanges(); + this.calculateTicks(this.axes.x); + this.calculateTicks(this.axes.x2); + this.calculateTicks(this.axes.y); + this.calculateTicks(this.axes.y2); + + this.calculateSpacing(); + this.setupAxes(); + + this.draw(); + this.insertLegend(); + + this.el.fire('flotr:afterinit', [this]); + }, + /** + * Sets options and initializes some variables and color specific values, used by the constructor. + * @param {Object} opts - options object + */ + setOptions: function(opts){ + var options = Flotr.clone(Flotr.defaultOptions); + options.x2axis = Object.extend(Object.clone(options.xaxis), options.x2axis); + options.y2axis = Object.extend(Object.clone(options.yaxis), options.y2axis); + this.options = Flotr.merge(opts || {}, options); + + // The 4 axes of the plot + this.axes = { + x: {options: this.options.xaxis, n: 1}, + x2: {options: this.options.x2axis, n: 2}, + y: {options: this.options.yaxis, n: 1}, + y2: {options: this.options.y2axis, n: 2} + }; + + // Initialize some variables used throughout this function. + var assignedColors = [], + colors = [], + ln = this.series.length, + neededColors = this.series.length, + oc = this.options.colors, + usedColors = [], + variation = 0, + c, i, j, s; + + // Collect user-defined colors from series. + for(i = neededColors - 1; i > -1; --i){ + c = this.series[i].color; + if(c){ + --neededColors; + if(Object.isNumber(c)) assignedColors.push(c); + else usedColors.push(Flotr.Color.parse(c)); + } + } + + // Calculate the number of colors that need to be generated. + for(i = assignedColors.length - 1; i > -1; --i) + neededColors = Math.max(neededColors, assignedColors[i] + 1); + + // Generate needed number of colors. + for(i = 0; colors.length < neededColors;){ + c = (oc.length == i) ? new Flotr.Color(100, 100, 100) : Flotr.Color.parse(oc[i]); + + // Make sure each serie gets a different color. + var sign = variation % 2 == 1 ? -1 : 1, + factor = 1 + sign * Math.ceil(variation / 2) * 0.2; + c.scale(factor, factor, factor); + + /** + * @todo if we're getting too close to something else, we should probably skip this one + */ + colors.push(c); + + if(++i >= oc.length){ + i = 0; + ++variation; + } + } + + // Fill the options with the generated colors. + for(i = 0, j = 0; i < ln; ++i){ + s = this.series[i]; + + // Assign the color. + if(s.color == null){ + s.color = colors[j++].toString(); + }else if(Object.isNumber(s.color)){ + s.color = colors[s.color].toString(); + } + + // Every series needs an axis + if (!s.xaxis) s.xaxis = this.axes.x; + if (s.xaxis == 1) s.xaxis = this.axes.x; + else if (s.xaxis == 2) s.xaxis = this.axes.x2; + + if (!s.yaxis) s.yaxis = this.axes.y; + if (s.yaxis == 1) s.yaxis = this.axes.y; + else if (s.yaxis == 2) s.yaxis = this.axes.y2; + + // Apply missing options to the series. + for (var t in Flotr.graphTypes){ + s[t] = Object.extend(Object.clone(this.options[t]), s[t]); + } + s.mouse = Object.extend(Object.clone(this.options.mouse), s.mouse); + + if(s.shadowSize == null) s.shadowSize = this.options.shadowSize; + } + }, + setupAxes: function(){ + /** + * Translates data number to pixel number + * @param {Number} v - data number + * @return {Number} translated pixel number + */ + function d2p(v, o){ + if (o.scaling === 'logarithmic') { + v = Math.log(Math.max(v, Number.MIN_VALUE)); + if (o.base !== Math.E) + v /= Math.log(o.base); + } + return v; + } + + /** + * Translates pixel number to data number + * @param {Number} v - pixel data + * @return {Number} translated data number + */ + function p2d(v, o){ + if (o.scaling === 'logarithmic') + v = (o.base === Math.E) ? Math.exp(v) : Math.pow(o.base, v); + return v; + } + + this.axes.x.d2p = this.axes.x2.d2p = function(x){ + return (d2p(x, this.options) - this.min) * this.scale; + }; + + this.axes.x.p2d = this.axes.x2.p2d = function(x){ + return (p2d(x, this.options) / this.scale + this.min); + }; + + var ph = this.plotHeight; + this.axes.y.d2p = this.axes.y2.d2p = function(y){ + return ph - (d2p(y, this.options) - this.min) * this.scale; + }; + + this.axes.y.p2d = this.axes.y2.p2d = function(y){ + return p2d(this.max -y / this.scale, this.options); + }; + }, + /** + * Initializes the canvas and it's overlay canvas element. When the browser is IE, this makes use + * of excanvas. The overlay canvas is inserted for displaying interactions. After the canvas elements + * are created, the elements are inserted into the container element. + */ + constructCanvas: function(){ + var el = this.el, + size, c, oc; + + // The old canvases are retrieved to avoid memory leaks ... + this.canvas = el.select('.flotr-canvas')[0]; + this.overlay = el.select('.flotr-overlay')[0]; + + // ... and all the child elements are removed + el.childElements().invoke('remove'); + + // For positioning labels and overlay. + el.style.position = 'relative'; + el.style.cursor = el.style.cursor || 'default'; + + size = el.getDimensions(); + this.canvasWidth = size.width; + this.canvasHeight = size.height; + + var style = { + width: size.width+'px', + height: size.height+'px' + }; + + var o = this.options; + size.width *= o.resolution; + size.height *= o.resolution; + + if(this.canvasWidth <= 0 || this.canvasHeight <= 0){ + throw 'Invalid dimensions for plot, width = ' + this.canvasWidth + ', height = ' + this.canvasHeight; + } + + // Insert main canvas. + if (!this.canvas) { + c = this.canvas = $(document.createElement('canvas')); // Do NOT use new Element() + c.className = 'flotr-canvas'; + c.style.cssText = 'position:absolute;left:0px;top:0px;'; + } + c = this.canvas.writeAttribute(size).show().setStyle(style); + c.context_ = null; // Reset the ExCanvas context + el.insert(c); + + // Insert overlay canvas for interactive features. + if (!this.overlay) { + oc = this.overlay = $(document.createElement('canvas')); // Do NOT use new Element() + oc.className = 'flotr-overlay'; + oc.style.cssText = 'position:absolute;left:0px;top:0px;'; + } + oc = this.overlay.writeAttribute(size).show().setStyle(style); + oc.context_ = null; // Reset the ExCanvas context + el.insert(oc); + + if(Prototype.Browser.IE){ + window.G_vmlCanvasManager.initElement(c); + window.G_vmlCanvasManager.initElement(oc); + } + this.ctx = c.getContext('2d'); + this.octx = oc.getContext('2d'); + + if(!Prototype.Browser.IE){ + this.ctx.scale(o.resolution, o.resolution); + this.octx.scale(o.resolution, o.resolution); + } + + // Enable text functions + this.textEnabled = !!this.ctx.drawText; + }, + processColor: function(color, options){ + if (!color) return 'rgba(0, 0, 0, 0)'; + + options = Object.extend({ + x1: 0, y1: 0, x2: this.plotWidth, y2: this.plotHeight, opacity: 1, ctx: this.ctx + }, options); + + if (color instanceof Flotr.Color) return color.adjust(null, null, null, options.opacity).toString(); + if (Object.isString(color)) return Flotr.Color.parse(color).scale(null, null, null, options.opacity).toString(); + + var grad = color.colors ? color : {colors: color}; + + if (!options.ctx) { + if (!Object.isArray(grad.colors)) return 'rgba(0, 0, 0, 0)'; + return Flotr.Color.parse(Object.isArray(grad.colors[0]) ? grad.colors[0][1] : grad.colors[0]).scale(null, null, null, options.opacity).toString(); + } + grad = Object.extend({start: 'top', end: 'bottom'}, grad); + + if (/top/i.test(grad.start)) options.x1 = 0; + if (/left/i.test(grad.start)) options.y1 = 0; + if (/bottom/i.test(grad.end)) options.x2 = 0; + if (/right/i.test(grad.end)) options.y2 = 0; + + var i, c, stop, gradient = options.ctx.createLinearGradient(options.x1, options.y1, options.x2, options.y2); + for (i = 0; i < grad.colors.length; i++) { + c = grad.colors[i]; + if (Object.isArray(c)) { + stop = c[0]; + c = c[1]; + } + else stop = i / (grad.colors.length-1); + gradient.addColorStop(stop, Flotr.Color.parse(c).scale(null, null, null, options.opacity)); + } + return gradient; + }, + registerPlugins: function(){ + var name, plugin, c; + for (name in Flotr.plugins) { + plugin = Flotr.plugins[name]; + for (c in plugin.callbacks) { + this.el.observe(c, plugin.callbacks[c].bindAsEventListener(this)); + } + this[name] = Object.clone(plugin); + for (p in this[name]) { + if (Object.isFunction(this[name][p])) + this[name][p] = this[name][p].bind(this); + } + } + }, + /** + * Calculates a text box dimensions, wether it is drawn on the canvas or inserted into the DOM + * @param {String} text - The text in the box + * @param {Object} canvasStyle - An object containing the style for the text if drawn on the canvas + * @param {String} HtmlStyle - A CSS style for the text if inserted into the DOM + * @param {Object} className - A CSS className for the text if inserted into the DOM + */ + getTextDimensions: function(text, canvasStyle, HtmlStyle, className) { + if (!text) return {width:0, height:0}; + + if (!this.options.HtmlText && this.textEnabled) { + var bounds = this.ctx.getTextBounds(text, canvasStyle); + return { + width: bounds.width+2, + height: bounds.height+6 + }; + } + else { + var dummyDiv = this.el.insert('
' + text + '
').select(".flotr-dummy-div")[0], + dim = dummyDiv.getDimensions(); + dummyDiv.remove(); + return dim; + } + }, + /** + * Builds a matrix of the data to make the correspondance between the x values and the y values : + * X value => Y values from the axes + * @return {Array} The data grid + */ + loadDataGrid: function(){ + if (this.seriesData) return this.seriesData; + + var s = this.series, + dg = []; + + /* The data grid is a 2 dimensions array. There is a row for each X value. + * Each row contains the x value and the corresponding y value for each serie ('undefined' if there isn't one) + **/ + for(i = 0; i < s.length; ++i){ + s[i].data.each(function(v) { + var x = v[0], + y = v[1], + r = dg.find(function(row) {return row[0] == x}); + if (r) r[i+1] = y; + else { + var newRow = []; + newRow[0] = x; + newRow[i+1] = y; + dg.push(newRow); + } + }); + } + + // The data grid is sorted by x value + return this.seriesData = dg.sortBy(function(v){return v[0]}); + }, + /** + * Initializes event some handlers. + */ + initEvents: function () { + //@todo: maybe stopObserving with only flotr functions + this.overlay.stopObserving() + .observe('mousedown', this.mouseDownHandler.bindAsEventListener(this)) + .observe('mousemove', this.mouseMoveHandler.bindAsEventListener(this)) + .observe('click', this.clickHandler.bindAsEventListener(this)); + }, + /** + * Function determines the min and max values for the xaxis and yaxis. + */ + findDataRanges: function(){ + var s = this.series, + a = this.axes; + + a.x.datamin = a.x2.datamin = a.y.datamin = a.y2.datamin = Number.MAX_VALUE; + a.x.datamax = a.x2.datamax = a.y.datamax = a.y2.datamax = -Number.MAX_VALUE; + + if(s.length > 0){ + var i, j, h, x, y, data, xaxis, yaxis; + + // Get datamin, datamax start values + for(i = 0; i < s.length; ++i) { + data = s[i].data, + xaxis = s[i].xaxis, + yaxis = s[i].yaxis; + + if (data.length > 0 && !s[i].hide) { + if (!xaxis.used) xaxis.datamin = xaxis.datamax = data[0][0]; + if (!yaxis.used) yaxis.datamin = yaxis.datamax = data[0][1]; + xaxis.used = true; + yaxis.used = true; + + for(h = data.length - 1; h > -1; --h){ + x = data[h][0]; + if(x < xaxis.datamin) xaxis.datamin = x; + else if(x > xaxis.datamax) xaxis.datamax = x; + + for(j = 1; j < data[h].length; j++){ + y = data[h][j]; + if(y < yaxis.datamin) yaxis.datamin = y; + else if(y > yaxis.datamax) yaxis.datamax = y; + } + } + } + } + } + + this.findXAxesValues(); + + this.calculateRange(a.x, 'x'); + + if (a.x2.used) { + this.calculateRange(a.x2, 'x'); + } + + this.calculateRange(a.y, 'y'); + + if (a.y2.used) { + this.calculateRange(a.y2, 'y'); + } + }, + extendRange: function(axis, type) { + var f = (type === 'y') ? 'extendYRange' : 'extendXRange' + for (var t in Flotr.graphTypes) { + if (this[t][f]) this[t][f](axis); + } + }, + /** + * Calculates the range of an axis to apply autoscaling. + * @param {Object} axis - The axis for what the range will be calculated + */ + calculateRange: function(axis, type){ + var o = axis.options, + min = o.min != null ? o.min : axis.datamin, + max = o.max != null ? o.max : axis.datamax, + margin = o.autoscaleMargin; + + if(max - min == 0.0){ + var widen = (max == 0.0) ? 1.0 : 0.01; + min -= widen; + max += widen; + } + axis.tickSize = Flotr.getTickSize(o.noTicks, min, max, o.tickDecimals); + + // Autoscaling. + if(o.min == null && margin != 0){ + min -= axis.tickSize * margin; + // Make sure we don't go below zero if all values are positive. + if(min < 0 && axis.datamin >= 0) min = 0; + min = axis.tickSize * Math.floor(min / axis.tickSize); + } + + if(o.max == null && margin != 0){ + max += axis.tickSize * margin; + if(max > 0 && axis.datamax <= 0) max = 0; + max = axis.tickSize * Math.ceil(max / axis.tickSize); + } + axis.min = min; + axis.max = max; + + this.extendRange(axis, type); + }, + /** + * Find every values of the x axes + */ + findXAxesValues: function(){ + var i, j, s; + for(i = this.series.length-1; i > -1 ; --i){ + s = this.series[i]; + s.xaxis.values = s.xaxis.values || {}; + for (j = s.data.length-1; j > -1 ; --j){ + s.xaxis.values[s.data[j][0]+''] = {}; + } + } + }, + /** + * Calculate axis ticks. + * @param {Object} axis - The axis for what the ticks will be calculated + */ + calculateTicks: function(axis){ + var o = axis.options, i, v; + + axis.ticks = []; + if(o.ticks){ + var ticks = o.ticks, t, label; + + if(Object.isFunction(ticks)){ + ticks = ticks({min: axis.min, max: axis.max}); + } + + // Clean up the user-supplied ticks, copy them over. + for(i = 0; i < ticks.length; ++i){ + t = ticks[i]; + if(typeof(t) == 'object'){ + v = t[0]; + label = (t.length > 1) ? t[1] : o.tickFormatter.bind(this)(v); + }else{ + v = t; + label = o.tickFormatter.bind(this)(v); + } + axis.ticks[i] = { v: v, label: label }; + } + } + else { + if (o.mode == 'time') { + var tu = Flotr.Date.timeUnits, + spec = Flotr.Date.spec, + delta = (axis.max - axis.min) / axis.options.noTicks, + size, unit; + + for (i = 0; i < spec.length - 1; ++i) { + var d = spec[i][0] * tu[spec[i][1]]; + if (delta < (d + spec[i+1][0] * tu[spec[i+1][1]]) / 2 && d >= axis.tickSize) + break; + } + size = spec[i][0]; + unit = spec[i][1]; + + // special-case the possibility of several years + if (unit == "year") { + size = Flotr.getTickSize(axis.options.noTicks*tu.year, axis.min, axis.max, 0); + } + + axis.tickSize = size; + axis.tickUnit = unit; + axis.ticks = Flotr.Date.generator(axis); + } + else { + // Round to nearest multiple of tick size. + var start = axis.tickSize * Math.ceil(axis.min / axis.tickSize), + decimals; + + // Then store all possible ticks. + for(i = 0; start + i * axis.tickSize <= axis.max; ++i){ + v = start + i * axis.tickSize; + + // Round (this is always needed to fix numerical instability). + decimals = o.tickDecimals; + if(decimals == null) decimals = 1 - Math.floor(Math.log(axis.tickSize) / Math.LN10); + if(decimals < 0) decimals = 0; + + v = v.toFixed(decimals); + axis.ticks.push({ v: v, label: o.tickFormatter.bind(this)(v) }); + } + } + } + }, + /** + * Calculates axis label sizes. + */ + calculateSpacing: function(){ + var a = this.axes, + options = this.options, + series = this.series, + margin = options.grid.labelMargin, + x = a.x, + x2 = a.x2, + y = a.y, + y2 = a.y2, + maxOutset = 2, + i, j, l, dim; + + // Labels width and height + [x, x2, y, y2].each(function(axis) { + var maxLabel = ''; + + if (axis.options.showLabels) { + for(i = 0; i < axis.ticks.length; ++i){ + l = axis.ticks[i].label.length; + if(l > maxLabel.length){ + maxLabel = axis.ticks[i].label; + } + } + } + axis.maxLabel = this.getTextDimensions(maxLabel, {size:options.fontSize, angle: Flotr.toRad(axis.options.labelsAngle)}, 'font-size:smaller;', 'flotr-grid-label'); + axis.titleSize = this.getTextDimensions(axis.options.title, {size: options.fontSize*1.2, angle: Flotr.toRad(axis.options.titleAngle)}, 'font-weight:bold;', 'flotr-axis-title'); + }, this); + + // Title height + dim = this.getTextDimensions(options.title, {size: options.fontSize*1.5}, 'font-size:1em;font-weight:bold;', 'flotr-title'); + this.titleHeight = dim.height; + + // Subtitle height + dim = this.getTextDimensions(options.subtitle, {size: options.fontSize}, 'font-size:smaller;', 'flotr-subtitle'); + this.subtitleHeight = dim.height; + + // Grid outline line width. + if(options.show){ + maxOutset = Math.max(maxOutset, options.points.radius + options.points.lineWidth/2); + } + for(j = 0; j < options.length; ++j){ + if (series[j].points.show){ + maxOutset = Math.max(maxOutset, series[j].points.radius + series[j].points.lineWidth/2); + } + } + + var p = this.plotOffset; + p.bottom += (options.grid.circular ? 0 : (x.options.showLabels ? (x.maxLabel.height + margin) : 0)) + + (x.options.title ? (x.titleSize.height + margin) : 0) + maxOutset; + + p.top += (options.grid.circular ? 0 : (x2.options.showLabels ? (x2.maxLabel.height + margin) : 0)) + + (x2.options.title ? (x2.titleSize.height + margin) : 0) + this.subtitleHeight + this.titleHeight + maxOutset; + + p.left += (options.grid.circular ? 0 : (y.options.showLabels ? (y.maxLabel.width + margin) : 0)) + + (y.options.title ? (y.titleSize.width + margin) : 0) + maxOutset; + + p.right += (options.grid.circular ? 0 : (y2.options.showLabels ? (y2.maxLabel.width + margin) : 0)) + + (y2.options.title ? (y2.titleSize.width + margin) : 0) + maxOutset; + + p.top = Math.floor(p.top); // In order the outline not to be blured + p.bottom = 0; + p.top = 0; + p.left = 0; + p.right = 0; + this.plotWidth = this.canvasWidth - p.left - p.right; + this.plotHeight = this.canvasHeight - p.bottom - p.top; + + x.scale = this.plotWidth / (x.max - x.min); + x2.scale = this.plotWidth / (x2.max - x2.min); + y.scale = this.plotHeight / (y.max - y.min); + y2.scale = this.plotHeight / (y2.max - y2.min); + }, + /** + * Draws grid, labels, series and outline. + */ + draw: function() { + this.drawGrid(); + this.drawLabels(); + this.drawTitles(); + + if(this.series.length){ + this.el.fire('flotr:beforedraw', [this.series, this]); + for(var i = 0; i < this.series.length; i++){ + if (!this.series[i].hide) + this.drawSeries(this.series[i]); + } + } + this.drawOutline(); + this.el.fire('flotr:afterdraw', [this.series, this]); + }, + /** + * Draws a grid for the graph. + */ + drawGrid: function(){ + var v, o = this.options, + ctx = this.ctx, a; + + if(o.grid.verticalLines || o.grid.horizontalLines){ + this.el.fire('flotr:beforegrid', [this.axes.x, this.axes.y, o, this]); + } + ctx.save(); + ctx.lineWidth = 1; + ctx.strokeStyle = o.grid.tickColor; + + if (o.grid.circular) { + ctx.translate(this.plotOffset.left+this.plotWidth/2, this.plotOffset.top+this.plotHeight/2); + var radius = Math.min(this.plotHeight, this.plotWidth)*o.radar.radiusRatio/2, + sides = this.axes.x.ticks.length, + coeff = 2*(Math.PI/sides), + angle = -Math.PI/2; + + // Draw grid lines in vertical direction. + ctx.beginPath(); + + if(o.grid.horizontalLines){ + a = this.axes.y; + for(var i = 0; i < a.ticks.length; ++i){ + v = a.ticks[i].v; + var ratio = v / a.max; + + for(var j = 0; j <= sides; ++j){ + ctx[j == 0 ? 'moveTo' : 'lineTo'](Math.cos(j*coeff+angle)*radius*ratio, Math.sin(j*coeff+angle)*radius*ratio); + } + //ctx.moveTo(radius*ratio, 0); + //ctx.arc(0, 0, radius*ratio, 0, Math.PI*2, true); + } + } + + if(o.grid.verticalLines){ + for(var i = 0; i < sides; ++i){ + ctx.moveTo(0, 0); + ctx.lineTo(Math.cos(i*coeff+angle)*radius, Math.sin(i*coeff+angle)*radius); + } + } + ctx.stroke(); + } + else { + ctx.translate(this.plotOffset.left, this.plotOffset.top); + + // Draw grid background, if present in options. + if(o.grid.backgroundColor != null){ + ctx.fillStyle = this.processColor(o.grid.backgroundColor, {x1: 0, y1: 0, x2: this.plotWidth, y2: this.plotHeight}); + ctx.fillRect(0, 0, this.plotWidth, this.plotHeight); + } + + // Draw grid lines in vertical direction. + ctx.beginPath(); + if(o.grid.verticalLines){ + a = this.axes.x; + for(var i = 0; i < a.ticks.length; ++i){ + v = a.ticks[i].v; + // Don't show lines on upper and lower bounds. + if ((v <= a.min || v >= a.max) || + (v == a.min || v == a.max) && o.grid.outlineWidth != 0) + continue; + + ctx.moveTo(Math.floor(a.d2p(v)) + ctx.lineWidth/2, 0); + ctx.lineTo(Math.floor(a.d2p(v)) + ctx.lineWidth/2, this.plotHeight); + } + } + + // Draw grid lines in horizontal direction. + if(o.grid.horizontalLines){ + a = this.axes.y; + for(var j = 0; j < a.ticks.length; ++j){ + v = a.ticks[j].v; + // Don't show lines on upper and lower bounds. + if ((v <= a.min || v >= a.max) || + (v == a.min || v == a.max) && o.grid.outlineWidth != 0) + continue; + + ctx.moveTo(0, Math.floor(a.d2p(v)) + ctx.lineWidth/2); + ctx.lineTo(this.plotWidth, Math.floor(a.d2p(v)) + ctx.lineWidth/2); + } + } + ctx.stroke(); + } + + ctx.restore(); + if(o.grid.verticalLines || o.grid.horizontalLines){ + this.el.fire('flotr:aftergrid', [this.axes.x, this.axes.y, o, this]); + } + }, + /** + * Draws a outline for the graph. + */ + drawOutline: function(){ + var v, o = this.options, + ctx = this.ctx; + + if (o.grid.outlineWidth == 0) return; + + ctx.save(); + + if (o.grid.circular) { + ctx.translate(this.plotOffset.left+this.plotWidth/2, this.plotOffset.top+this.plotHeight/2); + var radius = Math.min(this.plotHeight, this.plotWidth)*o.radar.radiusRatio/2, + sides = this.axes.x.ticks.length, + coeff = 2*(Math.PI/sides), + angle = -Math.PI/2; + + // Draw axis/grid border. + ctx.beginPath(); + ctx.lineWidth = o.grid.outlineWidth; + ctx.strokeStyle = o.grid.color; + ctx.lineJoin = 'round'; + + for(var i = 0; i <= sides; ++i){ + ctx[i == 0 ? 'moveTo' : 'lineTo'](Math.cos(i*coeff+angle)*radius, Math.sin(i*coeff+angle)*radius); + } + //ctx.arc(0, 0, radius, 0, Math.PI*2, true); + + ctx.stroke(); + } + else { + ctx.translate(this.plotOffset.left, this.plotOffset.top); + + // Draw axis/grid border. + var lw = o.grid.outlineWidth, + orig = 0.5-lw+((lw+1)%2/2); + ctx.lineWidth = lw; + ctx.strokeStyle = o.grid.color; + ctx.lineJoin = 'miter'; + ctx.strokeRect(orig, orig, this.plotWidth, this.plotHeight); + } + + ctx.restore(); + }, + /** + * Draws labels for x and y axis. + */ + drawLabels: function(){ + // Construct fixed width label boxes, which can be styled easily. + var noLabels = 0, axis, + xBoxWidth, i, html, tick, left, top, + options = this.options, + ctx = this.ctx, + a = this.axes; + + for(i = 0; i < a.x.ticks.length; ++i){ + if (a.x.ticks[i].label) { + ++noLabels; + } + } + xBoxWidth = this.plotWidth / noLabels; + + if (options.grid.circular) { + ctx.save(); + ctx.translate(this.plotOffset.left+this.plotWidth/2, this.plotOffset.top+this.plotHeight/2); + var radius = this.plotHeight*options.radar.radiusRatio/2 + options.fontSize, + sides = this.axes.x.ticks.length, + coeff = 2*(Math.PI/sides), + angle = -Math.PI/2; + + var style = { + size: options.fontSize + }; + + // Add x labels. + axis = a.x; + style.color = axis.options.color || options.grid.color; + for(i = 0; i < axis.ticks.length && axis.options.showLabels; ++i){ + tick = axis.ticks[i]; + tick.label += ''; + if(!tick.label || tick.label.length == 0) continue; + + var x = Math.cos(i*coeff+angle) * radius, + y = Math.sin(i*coeff+angle) * radius; + + style.angle = Flotr.toRad(axis.options.labelsAngle); + style.valign = 'm'; + style.halign = (Math.abs(x) < 0.1 ? 'c' : (x < 0 ? 'r' : 'l')); + + ctx.drawText(tick.label, x, y, style); + } + + // Add y labels. + axis = a.y; + style.color = axis.options.color || options.grid.color; + for(i = 0; i < axis.ticks.length && axis.options.showLabels; ++i){ + tick = axis.ticks[i]; + tick.label += ''; + if(!tick.label || tick.label.length == 0) continue; + + style.angle = Flotr.toRad(axis.options.labelsAngle); + style.valign = 'm'; + style.halign = 'l'; + + ctx.drawText(tick.label, 3, -(axis.ticks[i].v / axis.max) * (radius - options.fontSize), style); + } + ctx.restore(); + return; + } + + if (!options.HtmlText && this.textEnabled) { + var style = { + size: options.fontSize, + adjustAlign: true + }; + + // Add x labels. + axis = a.x; + style.color = axis.options.color || options.grid.color; + for(i = 0; i < axis.ticks.length && axis.options.showLabels && axis.used; ++i){ + tick = axis.ticks[i]; + if(!tick.label || tick.label.length == 0) continue; + + left = axis.d2p(tick.v); + if (left < 0 || left > this.plotWidth) continue; + + style.angle = Flotr.toRad(axis.options.labelsAngle); + style.halign = 'c'; + style.valign = 't'; + + ctx.drawText( + tick.label, + this.plotOffset.left + left, + this.plotOffset.top + this.plotHeight + options.grid.labelMargin, + style + ); + } + + // Add x2 labels. + axis = a.x2; + style.color = axis.options.color || options.grid.color; + for(i = 0; i < axis.ticks.length && axis.options.showLabels && axis.used; ++i){ + tick = axis.ticks[i]; + if(!tick.label || tick.label.length == 0) continue; + + left = axis.d2p(tick.v); + if(left < 0 || left > this.plotWidth) continue; + + style.angle = Flotr.toRad(axis.options.labelsAngle); + style.halign = 'c'; + style.valign = 'b'; + + ctx.drawText( + tick.label, + this.plotOffset.left + left, + this.plotOffset.top + options.grid.labelMargin, + style + ); + } + + // Add y labels. + axis = a.y; + style.color = axis.options.color || options.grid.color; + for(i = 0; i < axis.ticks.length && axis.options.showLabels && axis.used; ++i){ + tick = axis.ticks[i]; + if (!tick.label || tick.label.length == 0) continue; + + top = axis.d2p(tick.v); + if(top < 0 || top > this.plotHeight) continue; + + style.angle = Flotr.toRad(axis.options.labelsAngle); + style.halign = 'r'; + style.valign = 'm'; + + ctx.drawText( + tick.label, + this.plotOffset.left - options.grid.labelMargin, + this.plotOffset.top + top, + style + ); + } + + // Add y2 labels. + axis = a.y2; + style.color = axis.options.color || options.grid.color; + for(i = 0; i < axis.ticks.length && axis.options.showLabels && axis.used; ++i){ + tick = axis.ticks[i]; + if (!tick.label || tick.label.length == 0) continue; + + top = axis.d2p(tick.v); + if(top < 0 || top > this.plotHeight) continue; + + style.angle = Flotr.toRad(axis.options.labelsAngle); + style.halign = 'l'; + style.valign = 'm'; + + ctx.drawText( + tick.label, + this.plotOffset.left + this.plotWidth + options.grid.labelMargin, + this.plotOffset.top + top, + style + ); + + ctx.save(); + ctx.strokeStyle = style.color; + ctx.beginPath(); + ctx.moveTo(this.plotOffset.left + this.plotWidth - 8, this.plotOffset.top + axis.d2p(tick.v)); + ctx.lineTo(this.plotOffset.left + this.plotWidth, this.plotOffset.top + axis.d2p(tick.v)); + ctx.stroke(); + ctx.restore(); + } + } + else if (a.x.options.showLabels || a.x2.options.showLabels || a.y.options.showLabels || a.y2.options.showLabels) { + html = ['
']; + + // Add x labels. + axis = a.x; + if (axis.options.showLabels){ + for(i = 0; i < axis.ticks.length; ++i){ + tick = axis.ticks[i]; + if(!tick.label || tick.label.length == 0 || + (this.plotOffset.left + axis.d2p(tick.v) < 0) || + (this.plotOffset.left + axis.d2p(tick.v) > this.canvasWidth)) continue; + html.push('
' + tick.label + '
'); + } + } + + // Add x2 labels. + axis = a.x2; + if (axis.options.showLabels && axis.used){ + for(i = 0; i < axis.ticks.length; ++i){ + tick = axis.ticks[i]; + if(!tick.label || tick.label.length == 0 || + (this.plotOffset.left + axis.d2p(tick.v) < 0) || + (this.plotOffset.left + axis.d2p(tick.v) > this.canvasWidth)) continue; + html.push('
' + tick.label + '
'); + } + } + + // Add y labels. + axis = a.y; + if (axis.options.showLabels){ + for(i = 0; i < axis.ticks.length; ++i){ + tick = axis.ticks[i]; + if (!tick.label || tick.label.length == 0 || + (this.plotOffset.top + axis.d2p(tick.v) < 0) || + (this.plotOffset.top + axis.d2p(tick.v) > this.canvasHeight)) continue; + html.push('
' + tick.label + '
'); + } + } + + // Add y2 labels. + axis = a.y2; + if (axis.options.showLabels && axis.used){ + ctx.save(); + ctx.strokeStyle = axis.options.color || options.grid.color; + ctx.beginPath(); + + for(i = 0; i < axis.ticks.length; ++i){ + tick = axis.ticks[i]; + if (!tick.label || tick.label.length == 0 || + (this.plotOffset.top + axis.d2p(tick.v) < 0) || + (this.plotOffset.top + axis.d2p(tick.v) > this.canvasHeight)) continue; + html.push('
' + tick.label + '
'); + + ctx.moveTo(this.plotOffset.left + this.plotWidth - 8, this.plotOffset.top + axis.d2p(tick.v)); + ctx.lineTo(this.plotOffset.left + this.plotWidth, this.plotOffset.top + axis.d2p(tick.v)); + } + ctx.stroke(); + ctx.restore(); + } + + html.push('
'); + this.el.insert(html.join('')); + } + }, + /** + * Draws the title and the subtitle + */ + drawTitles: function(){ + var html, + options = this.options, + margin = options.grid.labelMargin, + ctx = this.ctx, + a = this.axes; + + if (!options.HtmlText && this.textEnabled) { + var style = { + size: options.fontSize, + color: options.grid.color, + halign: 'c' + }; + + // Add subtitle + if (options.subtitle){ + ctx.drawText( + options.subtitle, + this.plotOffset.left + this.plotWidth/2, + this.titleHeight + this.subtitleHeight - 2, + style + ); + } + + style.weight = 1.5; + style.size *= 1.5; + + // Add title + if (options.title){ + ctx.drawText( + options.title, + this.plotOffset.left + this.plotWidth/2, + this.titleHeight - 2, + style + ); + } + + style.weight = 1.8; + style.size *= 0.8; + style.adjustAlign = true; + + // Add x axis title + if (a.x.options.title && a.x.used){ + style.halign = 'c'; + style.valign = 't'; + style.angle = Flotr.toRad(a.x.options.titleAngle); + ctx.drawText( + a.x.options.title, + this.plotOffset.left + this.plotWidth/2, + this.plotOffset.top + a.x.maxLabel.height + this.plotHeight + 2 * margin, + style + ); + } + + // Add x2 axis title + if (a.x2.options.title && a.x2.used){ + style.halign = 'c'; + style.valign = 'b'; + style.angle = Flotr.toRad(a.x2.options.titleAngle); + ctx.drawText( + a.x2.options.title, + this.plotOffset.left + this.plotWidth/2, + this.plotOffset.top - a.x2.maxLabel.height - 2 * margin, + style + ); + } + + // Add y axis title + if (a.y.options.title && a.y.used){ + style.halign = 'r'; + style.valign = 'm'; + style.angle = Flotr.toRad(a.y.options.titleAngle); + ctx.drawText( + a.y.options.title, + this.plotOffset.left - a.y.maxLabel.width - 2 * margin, + this.plotOffset.top + this.plotHeight / 2, + style + ); + } + + // Add y2 axis title + if (a.y2.options.title && a.y2.used){ + style.halign = 'l'; + style.valign = 'm'; + style.angle = Flotr.toRad(a.y2.options.titleAngle); + ctx.drawText( + a.y2.options.title, + this.plotOffset.left + this.plotWidth + a.y2.maxLabel.width + 2 * margin, + this.plotOffset.top + this.plotHeight / 2, + style + ); + } + } + else { + html = ['
']; + + // Add title + if (options.title) + html.push('
'+options.title+'
'); + + // Add subtitle + if (options.subtitle) + html.push('
'+options.subtitle+'
'); + + html.push('
'); + + html.push('
'); + + // Add x axis title + if (a.x.options.title && a.x.used) + html.push('
' + a.x.options.title + '
'); + + // Add x2 axis title + if (a.x2.options.title && a.x2.used) + html.push('
' + a.x2.options.title + '
'); + + // Add y axis title + if (a.y.options.title && a.y.used) + html.push('
' + a.y.options.title + '
'); + + // Add y2 axis title + if (a.y2.options.title && a.y2.used) + html.push('
' + a.y2.options.title + '
'); + + html.push('
'); + + this.el.insert(html.join('')); + } + }, + /** + * Actually draws the graph. + * @param {Object} series - series to draw + */ + drawSeries: function(series){ + series = series || this.series; + + var drawn = false; + for(type in Flotr.graphTypes){ + if(series[type] && series[type].show){ + drawn = true; + this[type].draw(series); + } + } + + if(!drawn){ + this[this.options.defaultType].draw(series); + } + }, + /** + * Adds a legend div to the canvas container or draws it on the canvas. + */ + insertLegend: function(){ + if(!this.options.legend.show) + return; + + var series = this.series, + plotOffset = this.plotOffset, + options = this.options, + legend = options.legend, + fragments = [], + rowStarted = false, + ctx = this.ctx, + i; + + var noLegendItems = series.findAll(function(s) {return (s.label && !s.hide)}).length; + + if (noLegendItems) { + if (!options.HtmlText && this.textEnabled && !$(legend.container)) { + var style = { + size: options.fontSize*1.1, + color: options.grid.color + }; + + var p = legend.position, + m = legend.margin, + lbw = legend.labelBoxWidth, + lbh = legend.labelBoxHeight, + lbm = legend.labelBoxMargin, + offsetX = plotOffset.left + m, + offsetY = plotOffset.top + m; + + // We calculate the labels' max width + var labelMaxWidth = 0; + for(i = series.length - 1; i > -1; --i){ + if(!series[i].label || series[i].hide) continue; + var label = legend.labelFormatter(series[i].label); + labelMaxWidth = Math.max(labelMaxWidth, ctx.measureText(label, style)); + } + + var legendWidth = Math.round(lbw + lbm*3 + labelMaxWidth), + legendHeight = Math.round(noLegendItems*(lbm+lbh) + lbm); + + if(p.charAt(0) == 's') offsetY = plotOffset.top + this.plotHeight - (m + legendHeight); + if(p.charAt(1) == 'e') offsetX = plotOffset.left + this.plotWidth - (m + legendWidth); + + // Legend box + var color = this.processColor(options.legend.backgroundColor || 'rgb(240,240,240)', {opacity: options.legend.backgroundOpacity || 0.1}); + + ctx.fillStyle = color; + ctx.fillRect(offsetX, offsetY, legendWidth, legendHeight); + ctx.strokeStyle = options.legend.labelBoxBorderColor; + ctx.strokeRect(Flotr.toPixel(offsetX), Flotr.toPixel(offsetY), legendWidth, legendHeight); + + // Legend labels + var x = offsetX + lbm; + var y = offsetY + lbm; + for(i = 0; i < series.length; i++){ + if(!series[i].label || series[i].hide) continue; + var label = legend.labelFormatter(series[i].label); + + ctx.fillStyle = series[i].color; + ctx.fillRect(x, y, lbw-1, lbh-1); + + ctx.strokeStyle = legend.labelBoxBorderColor; + ctx.lineWidth = 1; + ctx.strokeRect(Math.ceil(x)-1.5, Math.ceil(y)-1.5, lbw+2, lbh+2); + + // Legend text + ctx.drawText( + label, + x + lbw + lbm, + y + (lbh + style.size - ctx.fontDescent(style))/2, + style + ); + + y += lbh + lbm; + } + } + else { + for(i = 0; i < series.length; ++i){ + if(!series[i].label || series[i].hide) continue; + + if(i % options.legend.noColumns == 0){ + fragments.push(rowStarted ? '' : ''); + rowStarted = true; + } + + var s = series[i], + label = legend.labelFormatter(s.label), + boxWidth = legend.labelBoxWidth, + boxHeight = legend.labelBoxHeight, + opacity = 'opacity:' + s.bars.fillOpacity + ';filter:alpha(opacity=' + s.bars.fillOpacity*100 + ');', + color = 'background-color:' + ((s.bars.show && s.bars.fillColor && s.bars.fill) ? s.bars.fillColor : s.color) + ';'; + + fragments.push( + '', + '
', + '
', // Border + '
', // Background + '
', + '
', + '', + '', label, '' + ); + } + if(rowStarted) fragments.push(''); + + if(fragments.length > 0){ + var table = '' + fragments.join('') + '
'; + if(options.legend.container != null){ + $(options.legend.container).innerHTML = table; + } + else { + var pos = '', p = options.legend.position, m = options.legend.margin; + + if(p.charAt(0) == 'n') pos += 'top:' + (m + plotOffset.top) + 'px;bottom:auto;'; + else if(p.charAt(0) == 's') pos += 'bottom:' + (m + plotOffset.bottom) + 'px;top:auto;'; + if(p.charAt(1) == 'e') pos += 'right:' + (m + plotOffset.right) + 'px;left:auto;'; + else if(p.charAt(1) == 'w') pos += 'left:' + (m + plotOffset.left) + 'px;right:auto;'; + + var div = this.el.insert('
' + table + '
').select('div.flotr-legend').first(); + + if(options.legend.backgroundOpacity != 0.0){ + /** + * Put in the transparent background separately to avoid blended labels and + * label boxes. + */ + var c = options.legend.backgroundColor; + if(c == null){ + var tmp = (options.grid.backgroundColor != null) ? options.grid.backgroundColor : Flotr.Color.extract(div); + c = this.processColor(tmp, null, {opacity: 1}); + } + this.el.insert('
') + .select('div.flotr-legend-bg').first().setOpacity(options.legend.backgroundOpacity); + } + } + } + } + } + }, + /** + * Calculates the coordinates from a mouse event object. + * @param {Event} event - Mouse Event object. + * @return {Object} Object with coordinates of the mouse. + */ + getEventPosition: function (event){ + var offset = this.overlay.cumulativeOffset(), + pointer = Event.pointer(event), + rx = (pointer.x - offset.left - this.plotOffset.left), + ry = (pointer.y - offset.top - this.plotOffset.top); + + return { + x: this.axes.x.p2d(rx), + x2: this.axes.x2.p2d(rx), + y: this.axes.y.p2d(ry), + y2: this.axes.y2.p2d(ry), + relX: rx, + relY: ry, + absX: pointer.x, + absY: pointer.y + }; + }, + /** + * Observes the 'click' event and fires the 'flotr:click' event. + * @param {Event} event - 'click' Event object. + */ + clickHandler: function(event){ + if(this.ignoreClick){ + return this.ignoreClick = false; + } + this.el.fire('flotr:click', [this.getEventPosition(event), this]); + }, + /** + * Observes mouse movement over the graph area. Fires the 'flotr:mousemove' event. + * @param {Event} event - 'mousemove' Event object. + */ + mouseMoveHandler: function(event){ + var pos = this.getEventPosition(event); + + this.lastMousePos.pageX = pos.absX; + this.lastMousePos.pageY = pos.absY; + + //@todo Add another overlay for the crosshair + if (this.options.crosshair.mode) + this.clearCrosshair(); + + if(this.selectionInterval == null && (this.options.mouse.track || this.series.any(function(s){return s.mouse && s.mouse.track;}))) + this.hit(pos); + + if (this.options.crosshair.mode) + this.drawCrosshair(pos); + + this.el.fire('flotr:mousemove', [event, pos, this]); + }, + /** + * Observes the 'mousedown' event. + * @param {Event} event - 'mousedown' Event object. + */ + mouseDownHandler: function (event){ + if(event.isRightClick()) { + event.stop(); + var overlay = this.overlay; + + overlay.hide(); + + function cancelContextMenu () { + overlay.show(); + $(document).stopObserving('mousemove', cancelContextMenu); + } + $(document).observe('mousemove', cancelContextMenu); + return; + } + + if(!this.options.selection.mode || !event.isLeftClick()) return; + + this.setSelectionPos(this.selection.first, event); + if(this.selectionInterval != null){ + clearInterval(this.selectionInterval); + } + this.lastMousePos.pageX = null; + this.selectionInterval = setInterval(this.updateSelection.bindAsEventListener(this), 1000/this.options.selection.fps); + + this.mouseUpHandler = this.mouseUpHandler.bindAsEventListener(this); + $(document).observe('mouseup', this.mouseUpHandler); + }, + /** + * Fires the 'flotr:select' event when the user made a selection. + */ + fireSelectEvent: function(){ + var a = this.axes, s = this.selection, + x1, x2, y1, y2; + + x1 = a.x.p2d(s.first.x); + x2 = a.x.p2d(s.second.x); + y1 = a.y.p2d(s.first.y); + y2 = a.y.p2d(s.second.y); + + this.el.fire('flotr:select', [{ + x1:Math.min(x1, x2), + y1:Math.min(y1, y2), + x2:Math.max(x1, x2), + y2:Math.max(y1, y2), + xfirst:x1, xsecond:x2, yfirst:y1, ysecond:y2 + }, this]); + }, + /** + * Observes the mouseup event for the document. + * @param {Event} event - 'mouseup' Event object. + */ + mouseUpHandler: function(event){ + $(document).stopObserving('mouseup', this.mouseUpHandler); + event.stop(); + + if(this.selectionInterval != null){ + clearInterval(this.selectionInterval); + this.selectionInterval = null; + } + + this.setSelectionPos(this.selection.second, event); + this.clearSelection(); + + if(this.selectionIsSane()){ + this.drawSelection(); + this.fireSelectEvent(); + this.ignoreClick = true; + } + }, + /** + * Calculates the position of the selection. + * @param {Object} pos - Position object. + * @param {Event} event - Event object. + */ + setSelectionPos: function(pos, event) { + var options = this.options, + offset = $(this.overlay).cumulativeOffset(); + + if(options.selection.mode.indexOf('x') == -1){ + pos.x = (pos == this.selection.first) ? 0 : this.plotWidth; + }else{ + pos.x = event.pageX - offset.left - this.plotOffset.left; + pos.x = Math.min(Math.max(0, pos.x), this.plotWidth); + } + + if (options.selection.mode.indexOf('y') == -1){ + pos.y = (pos == this.selection.first) ? 0 : this.plotHeight; + }else{ + pos.y = event.pageY - offset.top - this.plotOffset.top; + pos.y = Math.min(Math.max(0, pos.y), this.plotHeight); + } + }, + /** + * Updates (draws) the selection box. + */ + updateSelection: function(){ + if(this.lastMousePos.pageX == null) return; + + this.setSelectionPos(this.selection.second, this.lastMousePos); + this.clearSelection(); + + if(this.selectionIsSane()) this.drawSelection(); + }, + /** + * Removes the selection box from the overlay canvas. + */ + clearSelection: function() { + if(this.prevSelection == null) return; + + var prevSelection = this.prevSelection, + lw = this.octx.lineWidth, + plotOffset = this.plotOffset, + x = Math.min(prevSelection.first.x, prevSelection.second.x), + y = Math.min(prevSelection.first.y, prevSelection.second.y), + w = Math.abs(prevSelection.second.x - prevSelection.first.x), + h = Math.abs(prevSelection.second.y - prevSelection.first.y); + + this.octx.clearRect(x + plotOffset.left - lw/2+0.5, + y + plotOffset.top - lw/2+0.5, + w + lw, + h + lw); + + this.prevSelection = null; + }, + /** + * Allows the user the manually select an area. + * @param {Object} area - Object with coordinates to select. + */ + setSelection: function(area, preventEvent){ + var options = this.options, + xa = this.axes.x, + ya = this.axes.y, + vertScale = ya.scale, + hozScale = xa.scale, + selX = options.selection.mode.indexOf('x') != -1, + selY = options.selection.mode.indexOf('y') != -1; + + this.clearSelection(); + + this.selection.first.y = (selX && !selY) ? 0 : (ya.max - area.y1) * vertScale; + this.selection.second.y = (selX && !selY) ? this.plotHeight : (ya.max - area.y2) * vertScale; + this.selection.first.x = (selY && !selX) ? 0 : (area.x1 - xa.min) * hozScale; + this.selection.second.x = (selY && !selX) ? this.plotWidth : (area.x2 - xa.min) * hozScale; + + this.drawSelection(); + if (!preventEvent) + this.fireSelectEvent(); + }, + /** + * Draws the selection box. + */ + drawSelection: function() { + var prevSelection = this.prevSelection, + s = this.selection, + octx = this.octx, + options = this.options, + plotOffset = this.plotOffset; + + if(prevSelection != null && + s.first.x == prevSelection.first.x && + s.first.y == prevSelection.first.y && + s.second.x == prevSelection.second.x && + s.second.y == prevSelection.second.y) + return; + + octx.save(); + octx.strokeStyle = this.processColor(options.selection.color, {opacity: 0.8}); + octx.lineWidth = 1; + octx.lineJoin = 'miter'; + octx.fillStyle = this.processColor(options.selection.color, {opacity: 0.4}); + + this.prevSelection = { + first: { x: s.first.x, y: s.first.y }, + second: { x: s.second.x, y: s.second.y } + }; + + var x = Math.min(s.first.x, s.second.x), + y = Math.min(s.first.y, s.second.y), + w = Math.abs(s.second.x - s.first.x), + h = Math.abs(s.second.y - s.first.y); + + octx.fillRect(x + plotOffset.left+0.5, y + plotOffset.top+0.5, w, h); + octx.strokeRect(x + plotOffset.left+0.5, y + plotOffset.top+0.5, w, h); + octx.restore(); + }, + /** + * Draws the selection box. + */ + drawCrosshair: function(pos) { + var octx = this.octx, + options = this.options, + plotOffset = this.plotOffset, + x = plotOffset.left+pos.relX+0.5, + y = plotOffset.top+pos.relY+0.5; + + if (pos.relX < 0 || pos.relY < 0 || pos.relX > this.plotWidth || pos.relY > this.plotHeight) { + this.el.style.cursor = null; + this.el.removeClassName('flotr-crosshair'); + return; + } + + this.lastMousePos.relX = null; + this.lastMousePos.relY = null; + + if (options.crosshair.hideCursor) { + this.el.style.cursor = Prototype.Browser.Gecko ? 'none' :'url(blank.cur),crosshair'; + this.el.addClassName('flotr-crosshair'); + } + + octx.save(); + octx.strokeStyle = options.crosshair.color; + octx.lineWidth = 1; + octx.beginPath(); + + if (options.crosshair.mode.indexOf('x') != -1) { + octx.moveTo(x, plotOffset.top); + octx.lineTo(x, plotOffset.top + this.plotHeight); + this.lastMousePos.relX = x; + } + + if (options.crosshair.mode.indexOf('y') != -1) { + octx.moveTo(plotOffset.left, y); + octx.lineTo(plotOffset.left + this.plotWidth, y); + this.lastMousePos.relY = y; + } + + octx.stroke(); + octx.restore(); + }, + /** + * Removes the selection box from the overlay canvas. + */ + clearCrosshair: function() { + if (this.lastMousePos.relX != null) + this.octx.clearRect(this.lastMousePos.relX-0.5, this.plotOffset.top, 1,this.plotHeight+1); + + if (this.lastMousePos.relY != null) + this.octx.clearRect(this.plotOffset.left, this.lastMousePos.relY-0.5, this.plotWidth+1, 1); + }, + /** + * Determines whether or not the selection is sane and should be drawn. + * @return {Boolean} - True when sane, false otherwise. + */ + selectionIsSane: function(){ + return Math.abs(this.selection.second.x - this.selection.first.x) >= 5 && + Math.abs(this.selection.second.y - this.selection.first.y) >= 5; + }, + /** + * Removes the mouse tracking point from the overlay. + */ + clearHit: function(){ + if(!this.prevHit) return; + + var prevHit = this.prevHit, + plotOffset = this.plotOffset, + s = prevHit.series, + lw = s.bars.lineWidth, + xa = prevHit.xaxis, + ya = prevHit.yaxis; + + if(!s.bars.show){ + var r = s.points.radius; + this.octx.clearRect( + xa.d2p(prevHit.x) + plotOffset.left - r*2, + ya.d2p(prevHit.y) + plotOffset.top - r*2, + r*3 + s.points.lineWidth*3, + r*3 + s.points.lineWidth*3 + ); + } + + else { + var bw = s.bars.barWidth; + + /** + * HACK TO FIX BAR HIT CLEARING + */ + var x2pre = xa.d2p(prevHit.x + bw/2); + + var x1 = xa.d2p(prevHit.x - bw/2) + plotOffset.left - lw; + var y1 = ya.d2p(prevHit.y >= 0 ? prevHit.y : 0) + plotOffset.top - lw; + var x2 = x2pre - x1 + lw * 2; + var y2 = ya.d2p(prevHit.y < 0 ? prevHit.y : 0) + lw * 2; + + this.octx.clearRect(x1, y1, x2, y2); + } + }, + /** + * Updates the mouse tracking point on the overlay. + */ + drawHit: function(n){ + var octx = this.octx, + s = n.series, + xa = n.xaxis, + ya = n.yaxis; + + if(s.mouse.lineColor != null){ + octx.save(); + octx.lineWidth = s.points.lineWidth; + octx.strokeStyle = s.mouse.lineColor; + octx.fillStyle = this.processColor(s.mouse.fillColor || '#ffffff', {opacity: s.mouse.fillOpacity}); + + if(!s.bars.show){ + octx.translate(this.plotOffset.left, this.plotOffset.top); + octx.beginPath(); + octx.arc(xa.d2p(n.x), ya.d2p(n.y), s.mouse.radius, 0, 2 * Math.PI, true); + octx.fill(); + octx.stroke(); + } + + else { + var bw = s.bars.barWidth; + + octx.save(); + octx.translate(this.plotOffset.left, this.plotOffset.top); + octx.beginPath(); + octx.moveTo(xa.d2p(n.x-(bw/2)), ya.d2p(0)); + octx.lineTo(xa.d2p(n.x-(bw/2)), ya.d2p(n.y)); + octx.lineTo(xa.d2p(n.x+(bw/2)), ya.d2p(n.y)); + octx.lineTo(xa.d2p(n.x+(bw/2)), ya.d2p(0)); + + if(s.mouse.fillColor){ + octx.fill(); + } + octx.stroke(); + octx.closePath(); + + octx.restore(); + } + octx.restore(); + } + this.prevHit = n; + }, + /** + * Retrieves the nearest data point from the mouse cursor. If it's within + * a certain range, draw a point on the overlay canvas and display the x and y + * value of the data. + * @param {Object} mouse - Object that holds the relative x and y coordinates of the cursor. + */ + hit: function(mouse){ + var series = this.series, + options = this.options, + prevHit = this.prevHit, + plotOffset = this.plotOffset, + octx = this.octx, + data, xsens, ysens, x, y, xa, ya, mx, my, + /** + * Nearest data element. + */ + i, n = { + dist:Number.MAX_VALUE, + x:null, + y:null, + relX:mouse.relX, + relY:mouse.relY, + absX:mouse.absX, + absY:mouse.absY, + mouse:null, + xaxis:null, + yaxis:null, + series:null, + index:null + }; + + for(i = 0; i < series.length; i++){ + s = series[i]; + if(!s.mouse.track) continue; + data = s.data; + xa = s.xaxis; + ya = s.yaxis; + var xsens = (2*options.points.lineWidth)/xa.scale * s.mouse.sensibility; + var ysens = (2*options.points.lineWidth)/ya.scale * s.mouse.sensibility; + mx = xa.p2d(mouse.relX); + my = ya.p2d(mouse.relY); + + for(var j = 0, xpow, ypow; j < data.length; j++){ + x = data[j][0]; + y = data[j][1]; + + if (y === null || + xa.min > x || xa.max < x || + ya.min > y || ya.max < y) continue; + + var xdiff = Math.abs(x - mx), + ydiff = Math.abs(y - my); + + // we use a different set of criteria to determin if there has been a hit + // depending on what type of graph we have + if(((!s.bars.show) && xdiff < xsens /*&& ydiff < ysens*/) || // Hacked to enable mouseover sensitivity, following mouse in the xaxis + (s.bars.show && xdiff < s.bars.barWidth/2 + xsens /*&& ((y > 0 && my > 0 && my < y + ysens) || (y < 0 && my < 0 && my > y - ysens))*/)){ // Hacked for more sensible bar sensitivity + var distance = Math.sqrt(xdiff*xdiff + ydiff*ydiff); + if(distance < n.dist){ + n.dist = distance; + n.x = x; + n.y = y; + n.xaxis = xa; + n.yaxis = ya; + n.mouse = s.mouse; + n.series = s; + n.index = j; + } + } + } + } + + if(n.series && (n.mouse && n.mouse.track && !prevHit || (prevHit /*&& (n.x != prevHit.x || n.y != prevHit.y)*/))){ + var mt = this.mouseTrack || this.el.select(".flotr-mouse-value")[0], + pos = '', + s = n.series, + p = n.mouse.position, + m = n.mouse.margin, + elStyle = 'opacity:0.7;background-color:#000;color:#fff;display:none;position:absolute;padding:2px 8px;-moz-border-radius:4px;border-radius:4px;white-space:nowrap;'; + + if (!n.mouse.relative) { // absolute to the canvas + if(p.charAt(0) == 'n') pos += 'top:' + (m + plotOffset.top) + 'px;bottom:auto;'; + else if(p.charAt(0) == 's') pos += 'bottom:' + (m + plotOffset.bottom) + 'px;top:auto;'; + if(p.charAt(1) == 'e') pos += 'right:' + (m + plotOffset.right) + 'px;left:auto;'; + else if(p.charAt(1) == 'w') pos += 'left:' + (m + plotOffset.left) + 'px;right:auto;'; + } + else { // relative to the mouse or in the case of bar like graphs to the bar + if(!s.bars.show){ + if(p.charAt(0) == 'n') pos += 'bottom:' + (m - plotOffset.top - n.yaxis.d2p(n.y) + this.canvasHeight) + 'px;top:auto;'; + else if(p.charAt(0) == 's') pos += 'top:' + (m + plotOffset.top + n.yaxis.d2p(n.y)) + 'px;bottom:auto;'; + if(p.charAt(1) == 'e') pos += 'left:' + (m + plotOffset.left + n.xaxis.d2p(n.x)) + 'px;right:auto;'; + else if(p.charAt(1) == 'w') pos += 'right:' + (m - plotOffset.left - n.xaxis.d2p(n.x) + this.canvasWidth) + 'px;left:auto;'; + } + + else { + pos += 'bottom:' + (m - plotOffset.top - n.yaxis.d2p(n.y/2) + this.canvasHeight) + 'px;top:auto;'; + pos += 'left:' + (m + plotOffset.left + n.xaxis.d2p(n.x - options.bars.barWidth/2)) + 'px;right:auto;'; + } + } + elStyle += pos; + + if(!mt){ + this.el.insert('
'); + mt = this.mouseTrack = this.el.select('.flotr-mouse-value').first(); + } + else { + mt.style.cssText = elStyle; + this.mouseTrack = mt; + } + + if(n.x !== null && n.y !== null){ + mt.show(); + + this.clearHit(); + this.drawHit(n); + + var decimals = n.mouse.trackDecimals; + if(decimals == null || decimals < 0) decimals = 0; + + mt.innerHTML = n.mouse.trackFormatter({x: n.x.toFixed(decimals), y: n.y.toFixed(decimals), series: n.series, index: n.index}); + mt.fire('flotr:hit', [n, this]); + } + else if(prevHit){ + mt.hide(); + + // Event + mt.fire('flotr:clearhit', [this, this]); + + this.clearHit(); + } + } + else if(this.prevHit) { + this.mouseTrack.hide(); + + // Event + this.mouseTrack.fire('flotr:clearhit', [this, this]); + + this.clearHit(); + } + }, + saveImage: function (type, width, height, replaceCanvas) { + var image = null; + if (Prototype.Browser.IE) { + image = ''+this.canvas.firstChild.innerHTML+''; + return window.open().document.write(image); + } + + switch (type) { + case 'jpeg': + case 'jpg': image = Canvas2Image.saveAsJPEG(this.canvas, replaceCanvas, width, height); break; + default: + case 'png': image = Canvas2Image.saveAsPNG(this.canvas, replaceCanvas, width, height); break; + case 'bmp': image = Canvas2Image.saveAsBMP(this.canvas, replaceCanvas, width, height); break; + } + if (Object.isElement(image) && replaceCanvas) { + this.restoreCanvas(); + this.canvas.hide(); + this.overlay.hide(); + this.el.insert(image.setStyle({position: 'absolute'})); + } + }, + restoreCanvas: function() { + this.canvas.show(); + this.overlay.show(); + this.el.select('img').invoke('remove'); + } +}); + +Flotr.Color = Class.create({ + initialize: function(r, g, b, a){ + this.rgba = ['r','g','b','a']; + var x = 4; + while(-1<--x){ + this[this.rgba[x]] = arguments[x] || ((x==3) ? 1.0 : 0); + } + this.normalize(); + }, + adjust: function(rd, gd, bd, ad) { + var x = 4; + while(-1<--x){ + if(arguments[x] != null) + this[this.rgba[x]] += arguments[x]; + } + return this.normalize(); + }, + scale: function(rf, gf, bf, af){ + var x = 4; + while(-1<--x){ + if(arguments[x] != null) + this[this.rgba[x]] *= arguments[x]; + } + return this.normalize(); + }, + clone: function(){ + return new Flotr.Color(this.r, this.b, this.g, this.a); + }, + limit: function(val,minVal,maxVal){ + return Math.max(Math.min(val, maxVal), minVal); + }, + normalize: function(){ + var limit = this.limit; + this.r = limit(parseInt(this.r), 0, 255); + this.g = limit(parseInt(this.g), 0, 255); + this.b = limit(parseInt(this.b), 0, 255); + this.a = limit(this.a, 0, 1); + return this; + }, + distance: function(color){ + if (!color) return; + color = new Flotr.Color.parse(color); + var dist = 0, x = 3; + while(-1<--x){ + dist += Math.abs(this[this.rgba[x]] - color[this.rgba[x]]); + } + return dist; + }, + toString: function(){ + return (this.a >= 1.0) ? 'rgb('+[this.r,this.g,this.b].join(',')+')' : 'rgba('+[this.r,this.g,this.b,this.a].join(',')+')'; + } +}); + +Object.extend(Flotr.Color, { + /** + * Parses a color string and returns a corresponding Color. + * The different tests are in order of probability to improve speed. + * @param {String, Color} str - string thats representing a color + * @return {Color} returns a Color object or false + */ + parse: function(color){ + if (color instanceof Flotr.Color) return color; + + var result, Color = Flotr.Color; + + // #a0b1c2 + if((result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))) + return new Color(parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)); + + // rgb(num,num,num) + if((result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))) + return new Color(parseInt(result[1]), parseInt(result[2]), parseInt(result[3])); + + // #fff + if((result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))) + return new Color(parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)); + + // rgba(num,num,num,num) + if((result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(color))) + return new Color(parseInt(result[1]), parseInt(result[2]), parseInt(result[3]), parseFloat(result[4])); + + // rgb(num%,num%,num%) + if((result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))) + return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55); + + // rgba(num%,num%,num%,num) + if((result = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(color))) + return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55, parseFloat(result[4])); + + // Otherwise, we're most likely dealing with a named color. + var name = (color+'').strip().toLowerCase(); + if(name == 'transparent'){ + return new Color(255, 255, 255, 0); + } + return (result = Color.names[name]) ? new Color(result[0], result[1], result[2]) : new Color(0, 0, 0, 0); + }, + + /** + * Extracts the background-color of the passed element. + * @param {Element} element - The element from what the background color is extracted + * @return {String} color string + */ + extract: function(element){ + var color; + // Loop until we find an element with a background color and stop when we hit the body element. + do { + color = element.getStyle('background-color').toLowerCase(); + if(!(color == '' || color == 'transparent')) break; + element = element.up(); + } while(!element.nodeName.match(/^body$/i)); + + // Catch Safari's way of signaling transparent. + return new Flotr.Color(color == 'rgba(0, 0, 0, 0)' ? 'transparent' : color); + }, + + names: { + aqua:[0,255,255], + azure:[240,255,255], + beige:[245,245,220], + black:[0,0,0], + blue:[0,0,255], + brown:[165,42,42], + cyan:[0,255,255], + darkblue:[0,0,139], + darkcyan:[0,139,139], + darkgrey:[169,169,169], + darkgreen:[0,100,0], + darkkhaki:[189,183,107], + darkmagenta:[139,0,139], + darkolivegreen:[85,107,47], + darkorange:[255,140,0], + darkorchid:[153,50,204], + darkred:[139,0,0], + darksalmon:[233,150,122], + darkviolet:[148,0,211], + fuchsia:[255,0,255], + gold:[255,215,0], + green:[0,128,0], + indigo:[75,0,130], + khaki:[240,230,140], + lightblue:[173,216,230], + lightcyan:[224,255,255], + lightgreen:[144,238,144], + lightgrey:[211,211,211], + lightpink:[255,182,193], + lightyellow:[255,255,224], + lime:[0,255,0], + magenta:[255,0,255], + maroon:[128,0,0], + navy:[0,0,128], + olive:[128,128,0], + orange:[255,165,0], + pink:[255,192,203], + purple:[128,0,128], + violet:[128,0,128], + red:[255,0,0], + silver:[192,192,192], + white:[255,255,255], + yellow:[255,255,0] + } +}); + +Flotr.Date = { + format: function(d, format) { + if (!d) return; + + // We should maybe use an "official" date format spec, like PHP date() or ColdFusion + // http://fr.php.net/manual/en/function.date.php + // http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_c-d_29.html + var tokens = { + h: d.getUTCHours().toString(), + H: leftPad(d.getUTCHours()), + M: leftPad(d.getUTCMinutes()), + S: leftPad(d.getUTCSeconds()), + s: d.getUTCMilliseconds(), + d: d.getUTCDate().toString(), + m: (d.getUTCMonth() + 1).toString(), + y: d.getUTCFullYear().toString(), + b: Flotr.Date.monthNames[d.getUTCMonth()] + }; + + function leftPad(n){ + n += ''; + return n.length == 1 ? "0" + n : n; + } + + var r = [], c, + escape = false; + + for (var i = 0; i < format.length; ++i) { + c = format.charAt(i); + + if (escape) { + r.push(tokens[c] || c); + escape = false; + } + else if (c == "%") + escape = true; + else + r.push(c); + } + return r.join(''); + }, + getFormat: function(time, span) { + var tu = Flotr.Date.timeUnits; + if (time < tu.second) return "%h:%M:%S.%s"; + else if (time < tu.minute) return "%h:%M:%S"; + else if (time < tu.day) return (span < 2 * tu.day) ? "%h:%M" : "%b %d %h:%M"; + else if (time < tu.month) return "%b %d"; + else if (time < tu.year) return (span < tu.year) ? "%b" : "%b %y"; + else return "%y"; + }, + formatter: function (v, axis) { + var d = new Date(v); + + // first check global format + if (axis.options.timeFormat != null) + return Flotr.Date.format(d, axis.options.timeFormat); + + var span = axis.max - axis.min, + t = axis.tickSize * Flotr.Date.timeUnits[axis.tickUnit]; + + return Flotr.Date.format(d, Flotr.Date.getFormat(t, span)); + }, + generator: function(axis) { + var ticks = [], + d = new Date(axis.min), + tu = Flotr.Date.timeUnits; + + var step = axis.tickSize * tu[axis.tickUnit]; + + switch (axis.tickUnit) { + case "millisecond": d.setUTCMilliseconds(Flotr.floorInBase(d.getUTCMilliseconds(), axis.tickSize)); break; + case "second": d.setUTCSeconds(Flotr.floorInBase(d.getUTCSeconds(), axis.tickSize)); break; + case "minute": d.setUTCMinutes(Flotr.floorInBase(d.getUTCMinutes(), axis.tickSize)); break; + case "hour": d.setUTCHours(Flotr.floorInBase(d.getUTCHours(), axis.tickSize)); break; + case "month": d.setUTCMonth(Flotr.floorInBase(d.getUTCMonth(), axis.tickSize)); break; + case "year": d.setUTCFullYear(Flotr.floorInBase(d.getUTCFullYear(), axis.tickSize));break; + } + + // reset smaller components + if (step >= tu.second) d.setUTCMilliseconds(0); + if (step >= tu.minute) d.setUTCSeconds(0); + if (step >= tu.hour) d.setUTCMinutes(0); + if (step >= tu.day) d.setUTCHours(0); + if (step >= tu.day * 4) d.setUTCDate(1); + if (step >= tu.year) d.setUTCMonth(0); + + var carry = 0, v = Number.NaN, prev; + do { + prev = v; + v = d.getTime(); + ticks.push({ v:v, label:Flotr.Date.formatter(v, axis) }); + if (axis.tickUnit == "month") { + if (axis.tickSize < 1) { + /* a bit complicated - we'll divide the month up but we need to take care of fractions + so we don't end up in the middle of a day */ + d.setUTCDate(1); + var start = d.getTime(); + d.setUTCMonth(d.getUTCMonth() + 1); + var end = d.getTime(); + d.setTime(v + carry * tu.hour + (end - start) * axis.tickSize); + carry = d.getUTCHours(); + d.setUTCHours(0); + } + else + d.setUTCMonth(d.getUTCMonth() + axis.tickSize); + } + else if (axis.tickUnit == "year") { + d.setUTCFullYear(d.getUTCFullYear() + axis.tickSize); + } + else + d.setTime(v + step); + + } while (v < axis.max && v != prev); + + return ticks; + }, + timeUnits: { + millisecond: 1, + second: 1000, + minute: 1000 * 60, + hour: 1000 * 60 * 60, + day: 1000 * 60 * 60 * 24, + month: 1000 * 60 * 60 * 24 * 30, + year: 1000 * 60 * 60 * 24 * 365.2425 + }, + // the allowed tick sizes, after 1 year we use an integer algorithm + spec: [ + [1, "millisecond"], [20, "millisecond"], [50, "millisecond"], [100, "millisecond"], [200, "millisecond"], [500, "millisecond"], + [1, "second"], [2, "second"], [5, "second"], [10, "second"], [30, "second"], + [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], [30, "minute"], + [1, "hour"], [2, "hour"], [4, "hour"], [8, "hour"], [12, "hour"], + [1, "day"], [2, "day"], [3, "day"], + [0.25, "month"], [0.5, "month"], [1, "month"], [2, "month"], [3, "month"], [6, "month"], + [1, "year"] + ], + monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] +}; + + + + +/** Lines **/ +Flotr.addType('lines', { + options: { + show: false, // => setting to true will show lines, false will hide + lineWidth: 2, // => line width in pixels + fill: false, // => true to fill the area from the line to the x axis, false for (transparent) no fill + fillColor: null, // => fill color + fillOpacity: 0.4 // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill + }, + /** + * Draws lines series in the canvas element. + * @param {Object} series - Series with options.lines.show = true. + */ + draw: function(series){ + series = series || this.series; + var ctx = this.ctx; + ctx.save(); + ctx.translate(this.plotOffset.left, this.plotOffset.top); + ctx.lineJoin = 'round'; + + var lw = series.lines.lineWidth; + var sw = series.shadowSize; + + if(sw > 0){ + ctx.lineWidth = sw / 2; + + var offset = lw/2 + ctx.lineWidth/2; + + ctx.strokeStyle = "rgba(0,0,0,0.1)"; + this.lines.plot(series, offset + sw/2); + + ctx.strokeStyle = "rgba(0,0,0,0.2)"; + this.lines.plot(series, offset); + + if(series.lines.fill) { + ctx.fillStyle = "rgba(0,0,0,0.05)"; + this.lines.plotArea(series, offset + sw/2); + } + } + + ctx.lineWidth = lw; + ctx.strokeStyle = series.color; + if(series.lines.fill){ + ctx.fillStyle = this.processColor(series.lines.fillColor || series.color, {opacity: series.lines.fillOpacity}); + this.lines.plotArea(series, 0); + } + + this.lines.plot(series, 0); + ctx.restore(); + }, + plot: function(series, offset){ + var ctx = this.ctx, + xa = series.xaxis, + ya = series.yaxis, + data = series.data; + + if(data.length < 2) return; + + var prevx = xa.d2p(data[0][0]), + prevy = ya.d2p(data[0][1]) + offset; + + ctx.beginPath(); + ctx.moveTo(prevx, prevy); + for(var i = 0; i < data.length - 1; ++i){ + var x1 = data[i][0], y1 = data[i][1], + x2 = data[i+1][0], y2 = data[i+1][1]; + + // To allow empty values + if (y1 === null || y2 === null) continue; + + /** + * Clip with ymin. + */ + if(y1 <= y2 && y1 < ya.min){ + /** + * Line segment is outside the drawing area. + */ + if(y2 < ya.min) continue; + + /** + * Compute new intersection point. + */ + x1 = (ya.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = ya.min; + } + else if(y2 <= y1 && y2 < ya.min){ + if(y1 < ya.min) continue; + x2 = (ya.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = ya.min; + } + + /** + * Clip with ymax. + */ + if(y1 >= y2 && y1 > ya.max) { + if(y2 > ya.max) continue; + x1 = (ya.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = ya.max; + } + else if(y2 >= y1 && y2 > ya.max){ + if(y1 > ya.max) continue; + x2 = (ya.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = ya.max; + } + + /** + * Clip with xmin. + */ + if(x1 <= x2 && x1 < xa.min){ + if(x2 < xa.min) continue; + y1 = (xa.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = xa.min; + } + else if(x2 <= x1 && x2 < xa.min){ + if(x1 < xa.min) continue; + y2 = (xa.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = xa.min; + } + + /** + * Clip with xmax. + */ + if(x1 >= x2 && x1 > xa.max){ + if (x2 > xa.max) continue; + y1 = (xa.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = xa.max; + } + else if(x2 >= x1 && x2 > xa.max){ + if(x1 > xa.max) continue; + y2 = (xa.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = xa.max; + } + + if(prevx != xa.d2p(x1) || prevy != ya.d2p(y1) + offset) + ctx.moveTo(xa.d2p(x1), ya.d2p(y1) + offset); + + prevx = xa.d2p(x2); + prevy = ya.d2p(y2) + offset; + ctx.lineTo(prevx, prevy); + } + ctx.stroke(); + }, + /** + * Function used to fill + * @param {Object} series - The series to draw + * @param {Object} offset + */ + plotArea: function(series, offset){ + var data = series.data; + if(data.length < 2) return; + + var top, lastX = 0, + ctx = this.ctx, + xa = series.xaxis, + ya = series.yaxis, + bottom = Math.min(Math.max(0, ya.min), ya.max), + first = true; + + ctx.beginPath(); + for(var i = 0; i < data.length - 1; ++i){ + + var x1 = data[i][0], y1 = data[i][1], + x2 = data[i+1][0], y2 = data[i+1][1]; + + if(x1 <= x2 && x1 < xa.min){ + if(x2 < xa.min) continue; + y1 = (xa.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = xa.min; + } + else if(x2 <= x1 && x2 < xa.min){ + if(x1 < xa.min) continue; + y2 = (xa.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = xa.min; + } + + if(x1 >= x2 && x1 > xa.max){ + if(x2 > xa.max) continue; + y1 = (xa.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = xa.max; + } + else if(x2 >= x1 && x2 > xa.max){ + if (x1 > xa.max) continue; + y2 = (xa.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = xa.max; + } + + if(first){ + ctx.moveTo(xa.d2p(x1), ya.d2p(bottom) + offset); + first = false; + } + + /** + * Now check the case where both is outside. + */ + if(y1 >= ya.max && y2 >= ya.max){ + ctx.lineTo(xa.d2p(x1), ya.d2p(ya.max) + offset); + ctx.lineTo(xa.d2p(x2), ya.d2p(ya.max) + offset); + continue; + } + else if(y1 <= ya.min && y2 <= ya.min){ + ctx.lineTo(xa.d2p(x1), ya.d2p(ya.min) + offset); + ctx.lineTo(xa.d2p(x2), ya.d2p(ya.min) + offset); + continue; + } + + /** + * Else it's a bit more complicated, there might + * be two rectangles and two triangles we need to fill + * in; to find these keep track of the current x values. + */ + var x1old = x1, x2old = x2; + + /** + * And clip the y values, without shortcutting. + * Clip with ymin. + */ + if(y1 <= y2 && y1 < ya.min && y2 >= ya.min){ + x1 = (ya.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = ya.min; + } + else if(y2 <= y1 && y2 < ya.min && y1 >= ya.min){ + x2 = (ya.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = ya.min; + } + + /** + * Clip with ymax. + */ + if(y1 >= y2 && y1 > ya.max && y2 <= ya.max){ + x1 = (ya.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = ya.max; + } + else if(y2 >= y1 && y2 > ya.max && y1 <= ya.max){ + x2 = (ya.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = ya.max; + } + + /** + * If the x value was changed we got a rectangle to fill. + */ + if(x1 != x1old){ + top = (y1 <= ya.min) ? top = ya.min : ya.max; + ctx.lineTo(xa.d2p(x1old), ya.d2p(top) + offset); + ctx.lineTo(xa.d2p(x1), ya.d2p(top) + offset); + } + + /** + * Fill the triangles. + */ + ctx.lineTo(xa.d2p(x1), ya.d2p(y1) + offset); + ctx.lineTo(xa.d2p(x2), ya.d2p(y2) + offset); + + /** + * Fill the other rectangle if it's there. + */ + if(x2 != x2old){ + top = (y2 <= ya.min) ? ya.min : ya.max; + ctx.lineTo(xa.d2p(x2old), ya.d2p(top) + offset); + ctx.lineTo(xa.d2p(x2), ya.d2p(top) + offset); + } + + lastX = Math.max(x2, x2old); + } + + ctx.lineTo(xa.d2p(xa.max), ya.d2p(bottom) + offset); + ctx.closePath(); + ctx.fill(); + } +}); + +/** Bars **/ +Flotr.addType('bars', { + options: { + show: false, // => setting to true will show bars, false will hide + lineWidth: 2, // => in pixels + barWidth: 1, // => in units of the x axis + fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill + fillColor: null, // => fill color + fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill + horizontal: false, // => horizontal bars (x and y inverted) @todo: needs fix + stacked: false, // => stacked bar charts + centered: true // => center the bars to their x axis value + }, + /** + * Draws bar series in the canvas element. + * @param {Object} series - Series with options.bars.show = true. + */ + draw: function(series) { + var ctx = this.ctx, + bw = series.bars.barWidth, + lw = Math.min(series.bars.lineWidth, bw); + + ctx.save(); + ctx.translate(this.plotOffset.left, this.plotOffset.top); + ctx.lineJoin = 'miter'; + + /** + * @todo linewidth not interpreted the right way. + */ + ctx.lineWidth = lw; + ctx.strokeStyle = series.color; + + this.bars.plotShadows(series, bw, 0, series.bars.fill); + + if(series.bars.fill){ + var color = series.bars.fillColor || series.color; + ctx.fillStyle = this.processColor(color, {opacity: series.bars.fillOpacity}); + } + + this.bars.plot(series, bw, 0, series.bars.fill); + ctx.restore(); + }, + plot: function(series, barWidth, offset, fill){ + var data = series.data; + if(data.length < 1) return; + + var xa = series.xaxis, + ya = series.yaxis, + ctx = this.ctx; + + for(var i = 0; i < data.length; i++){ + var x = data[i][0], + y = data[i][1], + drawLeft = true, drawTop = true, drawRight = true; + + if (y === null) continue; + + // Stacked bars + var stackOffset = 0; + if(series.bars.stacked) { + $H(xa.values).each(function(pair) { + if (pair.key == x) { + stackOffset = pair.value.stack || 0; + pair.value.stack = stackOffset + y; + } + }); + } + + // @todo: fix horizontal bars support + // Horizontal bars + if(series.bars.horizontal) + var left = stackOffset, right = x + stackOffset, bottom = y, top = y + barWidth; + else + var left = x - (series.bars.centered ? barWidth/2 : 0), right = x + barWidth - (series.bars.centered ? barWidth/2 : 0), bottom = stackOffset, top = y + stackOffset; + + if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max) + continue; + + if(left < xa.min){ + left = xa.min; + drawLeft = false; + } + + if(right > xa.max){ + right = xa.max; + if (xa.lastSerie != series && series.bars.horizontal) + drawTop = false; + } + + if(bottom < ya.min) + bottom = ya.min; + + if(top > ya.max){ + top = ya.max; + if (ya.lastSerie != series && !series.bars.horizontal) + drawTop = false; + } + + /** + * Fill the bar. + */ + if(fill){ + ctx.beginPath(); + ctx.moveTo(xa.d2p(left), ya.d2p(bottom) + offset); + ctx.lineTo(xa.d2p(left), ya.d2p(top) + offset); + ctx.lineTo(xa.d2p(right), ya.d2p(top) + offset); + ctx.lineTo(xa.d2p(right), ya.d2p(bottom) + offset); + ctx.fill(); + } + + /** + * Draw bar outline/border. + */ + if(series.bars.lineWidth != 0 && (drawLeft || drawRight || drawTop)){ + ctx.beginPath(); + ctx.moveTo(xa.d2p(left), ya.d2p(bottom) + offset); + + ctx[drawLeft ?'lineTo':'moveTo'](xa.d2p(left), ya.d2p(top) + offset); + ctx[drawTop ?'lineTo':'moveTo'](xa.d2p(right), ya.d2p(top) + offset); + ctx[drawRight?'lineTo':'moveTo'](xa.d2p(right), ya.d2p(bottom) + offset); + + ctx.stroke(); + } + } + }, + plotShadows: function(series, barWidth, offset){ + var data = series.data; + if(data.length < 1) return; + + var xa = series.xaxis, + ya = series.yaxis, + ctx = this.ctx, + sw = this.options.shadowSize; + + for(var i = 0; i < data.length; i++){ + var x = data[i][0], + y = data[i][1]; + + if (y === null) continue; + + // Stacked bars + var stackOffset = 0; + if(series.bars.stacked) { + $H(xa.values).each(function(pair) { + if (pair.key == x) { + stackOffset = pair.value.stackShadow || 0; + pair.value.stackShadow = stackOffset + y; + } + }); + } + + // Horizontal bars + if(series.bars.horizontal) + var left = stackOffset, right = x + stackOffset, bottom = y, top = y + barWidth; + else + var left = x - (series.bars.centered ? barWidth/2 : 0), right = x + barWidth - (series.bars.centered ? barWidth/2 : 0), bottom = stackOffset, top = y + stackOffset; + + if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max) + continue; + + if(left < xa.min) left = xa.min; + if(right > xa.max) right = xa.max; + if(bottom < ya.min) bottom = ya.min; + if(top > ya.max) top = ya.max; + + var width = xa.d2p(right)-xa.d2p(left)-((xa.d2p(right)+sw <= this.plotWidth) ? 0 : sw); + var height = Math.max(0, ya.d2p(bottom)-ya.d2p(top)-((ya.d2p(bottom)+sw <= this.plotHeight) ? 0 : sw)); + + ctx.fillStyle = 'rgba(0,0,0,0.05)'; + ctx.fillRect(Math.min(xa.d2p(left)+sw, this.plotWidth), Math.min(ya.d2p(top)+sw, this.plotWidth), width, height); + } + }, + extendXRange: function(axis) { + if(axis.options.max == null){ + var newmin = axis.min, + newmax = axis.max, + i, s, b, + stackedSums = [], + lastSerie = null; + + for(i = 0; i < this.series.length; ++i){ + s = this.series[i]; + b = s.bars; + if(b.show && s.xaxis == axis) { + if (b.centered) { + newmax = Math.max(axis.datamax + 0.5, newmax); + newmin = Math.min(axis.datamin - 0.5, newmin); + } + + // For normal vertical bars + if (!b.horizontal && (b.barWidth + axis.datamax > newmax)) + newmax = axis.max + (b.centered ? b.barWidth/2 : b.barWidth); + + // For horizontal stacked bars + if(b.stacked && b.horizontal){ + for (j = 0; j < s.data.length; j++) { + if (b.show && b.stacked) { + var x = s.data[j][0]+''; + stackedSums[x] = (stackedSums[x] || 0) + s.data[j][1]; + lastSerie = s; + } + } + + for (var j in stackedSums) { + newmax = Math.max(stackedSums[j], newmax); + } + } + } + } + axis.lastSerie = lastSerie; + axis.max = newmax; + axis.min = newmin; + } + }, + extendYRange: function(axis){ + if(axis.options.max == null){ + var newmax = axis.max, + i, s, b, + stackedSums = {}, + lastSerie = null; + + for(i = 0; i < this.series.length; ++i){ + s = this.series[i]; + b = s.bars; + if (b.show && !s.hide && s.yaxis == axis) { + // For normal horizontal bars + if (b.horizontal && (b.barWidth + axis.datamax > newmax)){ + newmax = axis.max + b.barWidth; + } + + // For vertical stacked bars + if(b.stacked && !b.horizontal){ + for (j = 0; j < s.data.length; j++) { + if (s.bars.show && s.bars.stacked) { + var x = s.data[j][0]+''; + stackedSums[x] = (stackedSums[x] || 0) + s.data[j][1]; + lastSerie = s; + } + } + + for (var j in stackedSums) { + newmax = Math.max(stackedSums[j], newmax); + } + } + } + } + axis.lastSerie = lastSerie; + axis.max = newmax; + } + } +}); + +/** Points **/ +Flotr.addType('points', { + options: { + show: false, // => setting to true will show points, false will hide + radius: 3, // => point radius (pixels) + lineWidth: 2, // => line width in pixels + fill: true, // => true to fill the points with a color, false for (transparent) no fill + fillColor: '#FFFFFF', // => fill color + fillOpacity: 0.4 // => opacity of color inside the points + }, + /** + * Draws point series in the canvas element. + * @param {Object} series - Series with options.points.show = true. + */ + draw: function(series) { + var ctx = this.ctx; + + ctx.save(); + ctx.translate(this.plotOffset.left, this.plotOffset.top); + + var lw = series.lines.lineWidth; + var sw = series.shadowSize; + + if(sw > 0){ + ctx.lineWidth = sw / 2; + + ctx.strokeStyle = 'rgba(0,0,0,0.1)'; + this.points.plotShadows(series, sw/2 + ctx.lineWidth/2, series.points.radius); + + ctx.strokeStyle = 'rgba(0,0,0,0.2)'; + this.points.plotShadows(series, ctx.lineWidth/2, series.points.radius); + } + + ctx.lineWidth = series.points.lineWidth; + ctx.strokeStyle = series.color; + ctx.fillStyle = series.points.fillColor != null ? series.points.fillColor : series.color; + this.points.plot(series, series.points.radius, series.points.fill); + ctx.restore(); + }, + plot: function (series, radius, fill) { + var xa = series.xaxis, + ya = series.yaxis, + ctx = this.ctx, i, + data = series.data; + + for(i = data.length - 1; i > -1; --i){ + var x = data[i][0], y = data[i][1]; + // To allow empty values + if(y === null || x < xa.min || x > xa.max || y < ya.min || y > ya.max) + continue; + + ctx.beginPath(); + ctx.arc(xa.d2p(x), ya.d2p(y), radius, 0, 2 * Math.PI, true); + if(fill) ctx.fill(); + ctx.stroke(); + } + }, + plotShadows: function(series, offset, radius){ + var xa = series.xaxis, + ya = series.yaxis, + ctx = this.ctx, i, + data = series.data; + + for(i = data.length - 1; i > -1; --i){ + var x = data[i][0], y = data[i][1]; + if (y === null || x < xa.min || x > xa.max || y < ya.min || y > ya.max) + continue; + ctx.beginPath(); + ctx.arc(xa.d2p(x), ya.d2p(y) + offset, radius, 0, Math.PI, false); + ctx.stroke(); + } + } +}); + + +/** Pie **/ +/** + * Formats the pies labels. + * @param {Object} slice - Slice object + * @return {String} Formatted pie label string + */ +Flotr.defaultPieLabelFormatter = function(slice) { + return (slice.fraction*100).toFixed(2)+'%'; +}; + +Flotr.addType('pie', { + options: { + show: false, // => setting to true will show bars, false will hide + lineWidth: 1, // => in pixels + fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill + fillColor: null, // => fill color + fillOpacity: 0.6, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill + explode: 6, // => the number of pixels the splices will be far from the center + sizeRatio: 0.6, // => the size ratio of the pie relative to the plot + startAngle: Math.PI/4, // => the first slice start angle + labelFormatter: Flotr.defaultPieLabelFormatter, + pie3D: false, // => whether to draw the pie in 3 dimenstions or not (ineffective) + pie3DviewAngle: (Math.PI/2 * 0.8), + pie3DspliceThickness: 20 + }, + /** + * Draws a pie in the canvas element. + * @param {Object} series - Series with options.pie.show = true. + */ + draw: function(series) { + if (this.options.pie.drawn) return; + var ctx = this.ctx, + options = this.options, + lw = series.pie.lineWidth, + sw = series.shadowSize, + data = series.data, + plotOffset = this.plotOffset, + radius = (Math.min(this.canvasWidth, this.canvasHeight) * series.pie.sizeRatio) / 2, + html = [], + vScale = 1,//Math.cos(series.pie.viewAngle); + plotTickness = Math.sin(series.pie.viewAngle)*series.pie.spliceThickness / vScale, + + style = { + size: options.fontSize*1.2, + color: options.grid.color, + weight: 1.5 + }, + + center = { + x: plotOffset.left + (this.plotWidth)/2, + y: plotOffset.top + (this.plotHeight)/2 + }, + + // Pie portions + portions = this.series.collect(function(hash, index){ + if (hash.pie.show && hash.data[0][1] !== null) + return { + name: (hash.label || hash.data[0][1]), + value: [index, hash.data[0][1]], + options: hash.pie, + series: hash + }; + }), + + // Sum of the portions' angles + sum = portions.pluck('value').pluck(1).inject(0, function(acc, n) { return acc + n; }), + fraction = 0.0, + angle = series.pie.startAngle, + value = 0.0; + + var slices = portions.collect(function(slice){ + angle += fraction; + value = parseFloat(slice.value[1]); // @warning : won't support null values !! + fraction = value/sum; + return { + name: slice.name, + fraction: fraction, + x: slice.value[0], + y: value, + value: value, + options: slice.options, + series: slice.series, + startAngle: 2 * angle * Math.PI, + endAngle: 2 * (angle + fraction) * Math.PI + }; + }); + + ctx.save(); + + if(sw > 0){ + slices.each(function (slice) { + if (slice.startAngle == slice.endAngle) return; + + var bisection = (slice.startAngle + slice.endAngle) / 2, + xOffset = center.x + Math.cos(bisection) * slice.options.explode + sw, + yOffset = center.y + Math.sin(bisection) * slice.options.explode + sw; + + this.pie.plotSlice(xOffset, yOffset, radius, slice.startAngle, slice.endAngle, false, vScale); + + if (series.pie.fill) { + ctx.fillStyle = 'rgba(0,0,0,0.1)'; + ctx.fill(); + } + }, this); + } + + if (options.HtmlText || !this.textEnabled) + html = ['
']; + + slices.each(function (slice, index) { + if (slice.startAngle == slice.endAngle) return; + + var bisection = (slice.startAngle + slice.endAngle) / 2, + color = slice.series.color, + fillColor = slice.options.fillColor || color, + xOffset = center.x + Math.cos(bisection) * slice.options.explode, + yOffset = center.y + Math.sin(bisection) * slice.options.explode; + + this.pie.plotSlice(xOffset, yOffset, radius, slice.startAngle, slice.endAngle, false, vScale); + + if(series.pie.fill){ + ctx.fillStyle = this.processColor(fillColor, {opacity: series.pie.fillOpacity}); + ctx.fill(); + } + ctx.lineWidth = lw; + ctx.strokeStyle = color; + ctx.stroke(); + + var label = options.pie.labelFormatter(slice), + textAlignRight = (Math.cos(bisection) < 0), + distX = xOffset + Math.cos(bisection) * (series.pie.explode + radius), + distY = yOffset + Math.sin(bisection) * (series.pie.explode + radius); + + if (slice.fraction && label) { + if (options.HtmlText || !this.textEnabled) { + var divStyle = 'position:absolute;top:' + (distY - 5) + 'px;'; //@todo: change + if (textAlignRight) + divStyle += 'right:'+(this.canvasWidth - distX)+'px;text-align:right;'; + else + divStyle += 'left:'+distX+'px;text-align:left;'; + html.push('
', label, '
'); + } + else { + style.halign = textAlignRight ? 'r' : 'l'; + ctx.drawText( + label, + distX, + distY + style.size / 2, + style + ); + } + } + }, this); + + if (options.HtmlText || !this.textEnabled) { + html.push('
'); + this.el.insert(html.join('')); + } + + ctx.restore(); + options.pie.drawn = true; + }, + plotSlice: function(x, y, radius, startAngle, endAngle, fill, vScale) { + var ctx = this.ctx; + vScale = vScale || 1; + + ctx.scale(1, vScale); + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.arc (x, y, radius, startAngle, endAngle, fill); + ctx.lineTo(x, y); + ctx.closePath(); + } +}); + + +/** Candles **/ +Flotr.addType('candles', { + options: { + show: false, // => setting to true will show candle sticks, false will hide + lineWidth: 1, // => in pixels + wickLineWidth: 1, // => in pixels + candleWidth: 0.6, // => in units of the x axis + fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill + upFillColor: '#00A8F0',// => up sticks fill color + downFillColor: '#CB4B4B',// => down sticks fill color + fillOpacity: 0.5, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill + barcharts: false // => draw as barcharts (not standard bars but financial barcharts) + }, + /** + * Draws candles series in the canvas element. + * @param {Object} series - Series with options.candles.show = true. + */ + draw: function(series) { + var ctx = this.ctx, + bw = series.candles.candleWidth; + + ctx.save(); + ctx.translate(this.plotOffset.left, this.plotOffset.top); + ctx.lineJoin = 'miter'; + + /** + * @todo linewidth not interpreted the right way. + */ + ctx.lineWidth = series.candles.lineWidth; + this.candles.plotShadows(series, bw/2); + this.candles.plot(series, bw/2); + + ctx.restore(); + }, + plot: function(series, offset){ + var data = series.data; + if(data.length < 1) return; + + var xa = series.xaxis, + ya = series.yaxis, + ctx = this.ctx; + + for(var i = 0; i < data.length; i++){ + var d = data[i], + x = d[0], + open = d[1], + high = d[2], + low = d[3], + close = d[4]; + + var left = x - series.candles.candleWidth/2, + right = x + series.candles.candleWidth/2, + bottom = Math.max(ya.min, low), + top = Math.min(ya.max, high), + bottom2 = Math.max(ya.min, Math.min(open, close)), + top2 = Math.min(ya.max, Math.max(open, close)); + + if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max) + continue; + + var color = series.candles[open>close?'downFillColor':'upFillColor']; + /** + * Fill the candle. + */ + if(series.candles.fill && !series.candles.barcharts){ + ctx.fillStyle = this.processColor(color, {opacity: series.candles.fillOpacity}); + ctx.fillRect(xa.d2p(left), ya.d2p(top2) + offset, xa.d2p(right) - xa.d2p(left), ya.d2p(bottom2) - ya.d2p(top2)); + } + + /** + * Draw candle outline/border, high, low. + */ + if(series.candles.lineWidth || series.candles.wickLineWidth){ + var x, y, pixelOffset = (series.candles.wickLineWidth % 2) / 2; + + x = Math.floor(xa.d2p((left + right) / 2)) + pixelOffset; + + ctx.save(); + ctx.strokeStyle = color; + ctx.lineWidth = series.candles.wickLineWidth; + ctx.lineCap = 'butt'; + + if (series.candles.barcharts) { + ctx.beginPath(); + + ctx.moveTo(x, Math.floor(ya.d2p(top) + offset)); + ctx.lineTo(x, Math.floor(ya.d2p(bottom) + offset)); + + y = Math.floor(ya.d2p(open) + offset)+0.5; + ctx.moveTo(Math.floor(xa.d2p(left))+pixelOffset, y); + ctx.lineTo(x, y); + + y = Math.floor(ya.d2p(close) + offset)+0.5; + ctx.moveTo(Math.floor(xa.d2p(right))+pixelOffset, y); + ctx.lineTo(x, y); + } + else { + ctx.strokeRect(xa.d2p(left), ya.d2p(top2) + offset, xa.d2p(right) - xa.d2p(left), ya.d2p(bottom2) - ya.d2p(top2)); + + ctx.beginPath(); + ctx.moveTo(x, Math.floor(ya.d2p(top2 ) + offset)); + ctx.lineTo(x, Math.floor(ya.d2p(top ) + offset)); + ctx.moveTo(x, Math.floor(ya.d2p(bottom2) + offset)); + ctx.lineTo(x, Math.floor(ya.d2p(bottom ) + offset)); + } + + ctx.stroke(); + ctx.restore(); + } + } + }, + plotShadows: function(series, offset){ + var data = series.data; + if(data.length < 1 || series.candles.barcharts) return; + + var xa = series.xaxis, + ya = series.yaxis, + sw = this.options.shadowSize; + + for(var i = 0; i < data.length; i++){ + var d = data[i], + x = d[0], + open = d[1], + high = d[2], + low = d[3], + close = d[4]; + + var left = x - series.candles.candleWidth/2, + right = x + series.candles.candleWidth/2, + bottom = Math.max(ya.min, Math.min(open, close)), + top = Math.min(ya.max, Math.max(open, close)); + + if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max) + continue; + + var width = xa.d2p(right)-xa.d2p(left)-((xa.d2p(right)+sw <= this.plotWidth) ? 0 : sw); + var height = Math.max(0, ya.d2p(bottom)-ya.d2p(top)-((ya.d2p(bottom)+sw <= this.plotHeight) ? 0 : sw)); + + this.ctx.fillStyle = 'rgba(0,0,0,0.05)'; + this.ctx.fillRect(Math.min(xa.d2p(left)+sw, this.plotWidth), Math.min(ya.d2p(top)+sw, this.plotWidth), width, height); + } + }, + extendXRange: function(axis){ + if(axis.options.max == null){ + var newmin = axis.min, + newmax = axis.max, + i, c; + + for(i = 0; i < this.series.length; ++i){ + c = this.series[i].candles; + if(c.show && this.series[i].xaxis == axis) { + // We don't use c.candleWidth in order not to stick the borders + newmax = Math.max(axis.datamax + 0.5, newmax); + newmin = Math.min(axis.datamin - 0.5, newmin); + } + } + axis.max = newmax; + axis.min = newmin; + } + } +}); + + +/** Markers **/ +/** + * Formats the marker labels. + * @param {Object} obj - Marker value Object {x:..,y:..} + * @return {String} Formatted marker string + */ +Flotr.defaultMarkerFormatter = function(obj){ + return (Math.round(obj.y*100)/100)+''; +}; + +Flotr.addType('markers', { + options: { + show: false, // => setting to true will show markers, false will hide + lineWidth: 1, // => line width of the rectangle around the marker + fill: false, // => fill or not the marekers' rectangles + fillColor: "#FFFFFF", // => fill color + fillOpacity: 0.4, // => fill opacity + stroke: false, // => draw the rectangle around the markers + position: 'ct', // => the markers position (vertical align: b, m, t, horizontal align: l, c, r) + labelFormatter: Flotr.defaultMarkerFormatter + }, + /** + * Draws lines series in the canvas element. + * @param {Object} series - Series with options.lines.show = true. + */ + draw: function(series){ + series = series || this.series; + var ctx = this.ctx, + xa = series.xaxis, + ya = series.yaxis, + options = series.markers, + data = series.data; + + ctx.save(); + ctx.translate(this.plotOffset.left, this.plotOffset.top); + ctx.lineJoin = 'round'; + ctx.lineWidth = options.lineWidth; + ctx.strokeStyle = 'rgba(0,0,0,0.5)'; + ctx.fillStyle = this.processColor(options.fillColor, {opacity: options.fillOpacity}); + + for(var i = 0; i < data.length; ++i){ + var x = data[i][0], xPos = xa.d2p(x), + y = data[i][1], yPos = ya.d2p(y), + label = options.labelFormatter({x: x, y: y, index: i, data : data}); + + this.markers.plot(xPos, yPos, label, options); + } + + ctx.restore(); + }, + plot: function(x, y, label, options) { + var ctx = this.ctx, + dim = this.getTextDimensions(label, null, null), + margin = 2, + left = x, + top = y; + + dim.width = Math.floor(dim.width+margin*2); + dim.height = Math.floor(dim.height+margin*2); + + if (options.position.indexOf('c') != -1) left -= dim.width/2 + margin; + else if (options.position.indexOf('l') != -1) left -= dim.width; + + if (options.position.indexOf('m') != -1) top -= dim.height/2 + margin; + else if (options.position.indexOf('t') != -1) top -= dim.height; + + left = Math.floor(left)+0.5; + top = Math.floor(top)+0.5; + + if(options.fill) + ctx.fillRect(left, top, dim.width, dim.height); + + if(options.stroke) + ctx.strokeRect(left, top, dim.width, dim.height); + + ctx.drawText(label, left+margin, top+margin, {valign: 't', halign: 'l'}); + } +}); + +Flotr.addType('radar', { + options: { + show: false, // => setting to true will show radar chart, false will hide + lineWidth: 2, // => line width in pixels + fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill + fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill + radiusRatio: 0.90 // => ratio of the radar, against the plot size + }, + draw: function(series){ + var ctx = this.ctx, + options = this.options; + + ctx.save(); + ctx.translate(this.plotOffset.left+this.plotWidth/2, this.plotOffset.top+this.plotHeight/2); + ctx.lineWidth = series.radar.lineWidth; + + ctx.fillStyle = 'rgba(0,0,0,0.05)'; + ctx.strokeStyle = 'rgba(0,0,0,0.05)'; + this.radar.plot(series, series.shadowSize / 2); + + ctx.strokeStyle = 'rgba(0,0,0,0.1)'; + this.radar.plot(series, series.shadowSize / 4); + + ctx.strokeStyle = series.color; + ctx.fillStyle = this.processColor(series.color, {opacity: series.radar.fillOpacity}); + this.radar.plot(series); + + ctx.restore(); + }, + plot: function(series, offset){ + var ctx = this.ctx, + options = this.options, + data = series.data, + radius = Math.min(this.plotHeight, this.plotWidth)*options.radar.radiusRatio/2, + coeff = 2*(Math.PI/data.length), + angle = -Math.PI/2; + + offset = offset || 0; + + ctx.beginPath(); + for(var i = 0; i < data.length; ++i){ + var x = data[i][0], + y = data[i][1], + ratio = y / this.axes.y.max; + + ctx[i == 0 ? 'moveTo' : 'lineTo'](Math.cos(i*coeff+angle)*radius*ratio + offset, Math.sin(i*coeff+angle)*radius*ratio + offset); + } + ctx.closePath(); + if (series.radar.fill) ctx.fill(); + ctx.stroke(); + } +}); + +Flotr.addType('bubbles', { + options: { + show: false, // => setting to true will show radar chart, false will hide + lineWidth: 2, // => line width in pixels + fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill + fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill + baseRadius: 2 // => ratio of the radar, against the plot size + }, + draw: function(series){ + var ctx = this.ctx, + options = this.options; + + ctx.save(); + ctx.translate(this.plotOffset.left, this.plotOffset.top); + ctx.lineWidth = series.bubbles.lineWidth; + + ctx.fillStyle = 'rgba(0,0,0,0.05)'; + ctx.strokeStyle = 'rgba(0,0,0,0.05)'; + this.bubbles.plot(series, series.shadowSize / 2); + + ctx.strokeStyle = 'rgba(0,0,0,0.1)'; + this.bubbles.plot(series, series.shadowSize / 4); + + ctx.strokeStyle = series.color; + ctx.fillStyle = this.processColor(series.color, {opacity: series.radar.fillOpacity}); + this.bubbles.plot(series); + + ctx.restore(); + }, + plot: function(series, offset){ + var ctx = this.ctx, + options = this.options, + data = series.data, + radius = options.bubbles.baseRadius; + + offset = offset || 0; + + for(var i = 0; i < data.length; ++i){ + var x = data[i][0], + y = data[i][1], + z = data[i][2]; + + ctx.beginPath(); + ctx.arc(series.xaxis.d2p(x) + offset, series.yaxis.d2p(y) + offset, radius * z, 0, Math.PI*2, true); + ctx.stroke(); + if (series.bubbles.fill) ctx.fill(); + ctx.closePath(); + } + }/*, + extendXRange: function(axis){ + if(axis.options.max == null){ + var newmin = axis.min, + newmax = axis.max, + i, j, c, r, data, d; + + for(i = 0; i < this.series.length; ++i){ + c = this.series[i].bubbles; + if(c.show && this.series[i].xaxis == axis) { + data = this.series[i].data; + if (data) + for(j = 0; j < data.length; j++) { + d = data[j]; + r = d[2] * c.baseRadius * (this.plotWidth / (axis.datamax - axis.datamin)); + newmax = Math.max(d[0] + r, newmax); + newmin = Math.min(d[0] - r, newmin); + } + } + } + axis.max = newmax; + axis.min = newmin; + } + }, + extendYRange: function(axis){ + if(axis.options.max == null){ + var newmin = axis.min, + newmax = axis.max, + i, j, c, r, data, d; + + for(i = 0; i < this.series.length; ++i){ + c = this.series[i].bubbles; + if(c.show && this.series[i].yaxis == axis) { + data = this.series[i].data; + if (data) + for(j = 0; j < data.length; j++) { + d = data[j]; + r = d[2] * c.baseRadius; + newmax = Math.max(d[1] + r, newmax); + newmin = Math.min(d[1] - r, newmin); + } + } + } + axis.max = newmax; + axis.min = newmin; + } + }*/ +}); + +Flotr.addPlugin('spreadsheet', { + options: { + show: false, // => show the data grid using two tabs + tabGraphLabel: 'Graph', + tabDataLabel: 'Data', + toolbarDownload: 'Download CSV', // @todo: add better language support + toolbarSelectAll: 'Select all', + csvFileSeparator: ',', + decimalSeparator: '.' + }, + /** + * Builds the tabs in the DOM + */ + callbacks: { + 'flotr:afterconstruct': function(){ + this.el.select('.flotr-tabs-group,.flotr-datagrid-container').invoke('remove'); + + if (!this.options.spreadsheet.show) return; + + var ss = this.spreadsheet; + ss.tabsContainer = new Element('div', {style:'position:absolute;left:0px;width:'+this.canvasWidth+'px'}).addClassName('flotr-tabs-group'); + ss.tabs = { + graph: new Element('div', {style:'float:left'}).addClassName('flotr-tab selected').update(this.options.spreadsheet.tabGraphLabel), + data: new Element('div', {style:'float:left'}).addClassName('flotr-tab').update(this.options.spreadsheet.tabDataLabel) + }; + ss.tabsContainer.insert(ss.tabs.graph).insert(ss.tabs.data); + + this.el.insert({bottom: ss.tabsContainer}); + + var offset = ss.tabs.data.getHeight() + 2; + this.plotOffset.bottom += offset; + ss.tabsContainer.setStyle({top: this.canvasHeight-offset+'px'}); + + ss.tabs.graph.observe('click', function(){ss.showTab('graph')}); + ss.tabs.data.observe('click', function(){ss.showTab('data')}); + } + }, + /** + * Constructs the data table for the spreadsheet + * @todo make a spreadsheet manager (Flotr.Spreadsheet) + * @return {Element} The resulting table element + */ + constructDataGrid: function(){ + // If the data grid has already been built, nothing to do here + if (this.spreadsheet.datagrid) return this.spreadsheet.datagrid; + + var i, j, + s = this.series, + datagrid = this.loadDataGrid(), + t = this.spreadsheet.datagrid = new Element('table', {style:'height:100px'}).addClassName('flotr-datagrid'), + colgroup = ['']; + + // First row : series' labels + var html = ['']; + html.push(' '); + for (i = 0; i < s.length; ++i) { + html.push(''+(s[i].label || String.fromCharCode(65+i))+''); + colgroup.push(''); + } + html.push(''); + + // Data rows + for (j = 0; j < datagrid.length; ++j) { + html.push(''); + for (i = 0; i < s.length+1; ++i) { + var tag = 'td', + content = (datagrid[j][i] != null ? Math.round(datagrid[j][i]*100000)/100000 : ''); + + if (i == 0) { + tag = 'th'; + var label; + if(this.options.xaxis.ticks) { + var tick = this.options.xaxis.ticks.find(function (x) { return x[0] == datagrid[j][i] }); + if (tick) label = tick[1]; + } + else { + label = this.options.xaxis.tickFormatter.bind(this)(content); + } + + if (label) content = label; + } + + html.push('<'+tag+(tag=='th'?' scope="row"':'')+'>'+content+''); + } + html.push(''); + } + colgroup.push(''); + t.update(colgroup.join('')+html.join('')); + + if (!Prototype.Browser.IE) { + t.select('td').each(function(td) { + td.observe('mouseover', function(e){ + td = e.element(); + var siblings = td.previousSiblings(); + + t.select('th[scope=col]')[siblings.length-1].addClassName('hover'); + t.select('colgroup col')[siblings.length].addClassName('hover'); + }).observe('mouseout', function(){ + t.select('colgroup col.hover, th.hover').invoke('removeClassName', 'hover'); + }); + }); + } + + var toolbar = new Element('div').addClassName('flotr-datagrid-toolbar'). + insert(new Element('button', {type:'button'}).addClassName('flotr-datagrid-toolbar-button').update(this.options.spreadsheet.toolbarDownload).observe('click', this.spreadsheet.downloadCSV.bindAsEventListener(this))). + insert(new Element('button', {type:'button'}).addClassName('flotr-datagrid-toolbar-button').update(this.options.spreadsheet.toolbarSelectAll).observe('click', this.spreadsheet.selectAllData.bindAsEventListener(this))); + + var container = new Element('div', {style:'left:0px;top:0px;width:'+this.canvasWidth+'px;height:'+(this.canvasHeight-this.spreadsheet.tabsContainer.getHeight()-2)+'px;overflow:auto;'}).addClassName('flotr-datagrid-container'); + container.insert(toolbar); + t.wrap(container.hide()); + + this.el.insert(container); + return t; + }, + /** + * Shows the specified tab, by its name + * @todo make a tab manager (Flotr.Tabs) + * @param {String} tabName - The tab name + */ + showTab: function(tabName){ + var selector = 'canvas, .flotr-labels, .flotr-legend, .flotr-legend-bg, .flotr-title, .flotr-subtitle'; + switch(tabName) { + case 'graph': + if (this.spreadsheet.datagrid) + this.spreadsheet.datagrid.up().hide(); + this.el.select(selector).invoke('show'); + this.spreadsheet.tabs.data.removeClassName('selected'); + this.spreadsheet.tabs.graph.addClassName('selected'); + break; + case 'data': + this.spreadsheet.constructDataGrid(); + this.spreadsheet.datagrid.up().show(); + this.el.select(selector).invoke('hide'); + this.spreadsheet.tabs.data.addClassName('selected'); + this.spreadsheet.tabs.graph.removeClassName('selected'); + break; + } + }, + /** + * Selects the data table in the DOM for copy/paste + */ + selectAllData: function(){ + if (this.spreadsheet.tabs) { + var selection, range, doc, win, node = this.spreadsheet.constructDataGrid(); + + this.spreadsheet.showTab('data'); + + // deferred to be able to select the table + setTimeout(function () { + if ((doc = node.ownerDocument) && (win = doc.defaultView) && + win.getSelection && doc.createRange && + (selection = window.getSelection()) && + selection.removeAllRanges) { + range = doc.createRange(); + range.selectNode(node); + selection.removeAllRanges(); + selection.addRange(range); + } + else if (document.body && document.body.createTextRange && + (range = document.body.createTextRange())) { + range.moveToElementText(node); + range.select(); + } + }, 0); + return true; + } + else return false; + }, + /** + * Converts the data into CSV in order to download a file + */ + downloadCSV: function(){ + var i, csv = '', + series = this.series, + options = this.options, + dg = this.loadDataGrid(), + separator = encodeURIComponent(options.spreadsheet.csvFileSeparator); + + if (options.spreadsheet.decimalSeparator === options.spreadsheet.csvFileSeparator) { + throw "The decimal separator is the same as the column separator ("+options.spreadsheet.decimalSeparator+")"; + } + + // The first row + for (i = 0; i < series.length; ++i) { + csv += separator+'"'+(series[i].label || String.fromCharCode(65+i)).replace(/\"/g, '\\"')+'"'; + } + csv += "%0D%0A"; // \r\n + + // For each row + for (i = 0; i < dg.length; ++i) { + var rowLabel = ''; + // The first column + if (this.options.xaxis.ticks) { + var tick = this.options.xaxis.ticks.find(function (x){return x[0] == dg[i][0]}); + if (tick) rowLabel = tick[1]; + } + else { + rowLabel = this.options.xaxis.tickFormatter.bind(this)(dg[i][0]); + } + rowLabel = '"'+(rowLabel+'').replace(/\"/g, '\\"')+'"'; + var numbers = dg[i].slice(1).join(separator); + if (options.spreadsheet.decimalSeparator !== '.') { + numbers = numbers.replace(/\./g, options.spreadsheet.decimalSeparator); + } + csv += rowLabel+separator+numbers+"%0D%0A"; // \t and \r\n + } + if (Prototype.Browser.IE) { + csv = csv.replace(new RegExp(separator, 'g'), decodeURIComponent(separator)).replace(/%0A/g, '\n').replace(/%0D/g, '\r'); + window.open().document.write(csv); + } + else window.open('data:text/csv,'+csv); + } +}); \ No newline at end of file diff --git a/sample_for_plotting/js/hsd.js b/sample_for_plotting/js/hsd.js new file mode 100644 index 0000000..5838b37 --- /dev/null +++ b/sample_for_plotting/js/hsd.js @@ -0,0 +1,2 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement){cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close()}d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border"){for(;g=0===c})}function S(a){return !a||!a.parentNode||a.parentNode.nodeType===11}function K(){return !0}function J(){return !1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b])){continue}if(b!=="toJSON"){return !1}}return !0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else{d=b}}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a){return this}if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2]){return f.find(a)}this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return !d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a)){return f.ready(a)}a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0){return}A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete"){return setTimeout(e.ready,1)}if(c.addEventListener){c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1)}else{if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval" in a},isNumeric:function(a){return !isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a)){return !1}try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf")){return !1}}catch(c){return !1}var d;for(d in a){}return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a){return !1}return !0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b){return null}b=e.trim(b);if(a.JSON&&a.JSON.parse){return a.JSON.parse(b)}if(n.test(b.replace(o,"@").replace(p,"]").replace(q,""))){return(new Function("return "+b))()}e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a){if(c.apply(a[f],d)===!1){break}}}else{for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k){for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e){return{}}g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent){for(o in {submit:1,change:1,focusin:1}){n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p}}k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return !!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b){return}n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function"){e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c)}g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c]){return g.events}k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k]){return}if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1){return !0}}return !1},val:function(a){var c,d,e,g=this[0];if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set" in c)||c.set(this,h,"value")===b){this.value=h}}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get" in c&&(d=c.get(g,"value"))!==b){return d}d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return !b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0){return null}c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn){return f(a)[c](d)}if(typeof a.getAttribute=="undefined"){return f.prop(a,c,d)}i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set" in h&&i&&(g=h.set(a,d,c))!==b){return g}a.setAttribute(c,""+d);return d}if(h&&"get" in h&&i&&(g=h.get(a,c))!==null){return g}g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h]){return}c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j){j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0)}return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1){return}r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode){r.push([m,s]),n=m}n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9){return[]}if(!b||typeof b!="string"){return e}var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b)){if(w.length===2&&o.relative[w[0]]){j=y(w[0]+w[1],d,f)}else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length){b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}}}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length){q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}}else{k=w=[]}}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]"){if(!u){e.push.apply(e,k)}else{if(d&&d.nodeType===1){for(t=0;k[t]!=null;t++){k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t])}}else{for(t=0;k[t]!=null;t++){k[t]&&k[t].nodeType===1&&e.push(j[t])}}}}else{s(k,e)}l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h){for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a){return[]}for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1))}return !1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else{a[2]&&m.error(a[0])}a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not"){if((a.exec(b[3])||"").length>1||/^\w/.test(b[3])){b[3]=m(b[3],null,null,c)}else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return !1}}else{if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0])){return !0}}return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return !!a.firstChild},empty:function(a){return !a.firstChild},has:function(a,b,c){return !!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f){return f(a,c,b,d)}if(e==="contains"){return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0}if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f){return f(a,c,b,d)}}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match){o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q))}var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]"){Array.prototype.push.apply(d,a)}else{if(typeof a.length=="number"){for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++){c[e].nodeType===1&&d.push(c[e])}c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1]){return s(e.getElementsByTagName(b),f)}if(h[2]&&o.find.CLASS&&e.getElementsByClassName){return s(e.getElementsByClassName(h[2]),f)}}if(e.nodeType===9){if(b==="body"&&e.body){return s([e.body],f)}if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode){return s([],f)}if(i.id===h[3]){return s([i],f)}}try{return s(e.querySelectorAll(b),f)}catch(j){}}else{if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p){return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}}catch(r){}finally{l||k.removeAttribute("id")}}}}return a(b,e,f,g)};for(var e in a){m[e]=a[e]}b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a)){try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11){return f}}}catch(g){}}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1){return}o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c){return b.getElementsByClassName(a[1])}},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return !!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return !1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a)){f+=d[0],a=a.replace(o.match.PSEUDO,"")}a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0){for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11){break}}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a){return this[0]&&this[0].parentNode?this.prevAll().length:-1}if(typeof a=="string"){return f.inArray(this[0],f(a))}return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d))){g.nodeType===1&&e.push(g),g=g[c]}return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c]){if(a.nodeType===1&&++e===b){break}}return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling){a.nodeType===1&&a!==b&&c.push(a)}return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a)){return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))})}if(typeof a!="object"&&a!==b){return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))}return f.text(this)},wrapAll:function(a){if(f.isFunction(a)){return this.each(function(b){f(this).wrapAll(a.call(this,b))})}if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1){a=a.firstChild}return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a)){return this.each(function(b){f(this).wrapInner(a.call(this,b))})}return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)})}if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)})}if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++){if(!a||f.filter(a,[d]).length){!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d)}}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild){b.removeChild(b.firstChild)}}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null}if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g){e[g]&&bk(d[g],e[g])}}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g){bj(d[g],e[g])}}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k){continue}if(typeof k=="string"){if(!_.test(k)){k=b.createTextNode(k)}else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--){o=o.lastChild}if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i){f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}}var r;if(!f.support.appendChecked){if(k[0]&&typeof(r=k.length)=="number"){for(i=0;i=0){return b+"px"}}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter){return}}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return !f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS){return bS.apply(this,arguments)}if(!this.length){return this}var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified")){f.lastModified[k]=y}if(z=v.getResponseHeader("Etag")){f.etag[k]=z}}if(a===304){w="notmodified",o=!0}else{try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}}else{u=w;if(!w||a){w="error",a<0&&(a=0)}}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n)){o[c[1].toLowerCase()]=c[2]}}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2){for(b in a){j[b]=[j[b],a[b]]}}else{b=a[v.status],v.then(b,b)}}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2){return !1}t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers){v.setRequestHeader(u,d.headers[u])}if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return !1}for(u in {success:1,error:1,complete:1}){v[u](d[u])}p=b$(bU,d,c,v);if(!p){w(-1,"No Transport")}else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2){w(-1,z)}else{throw z}}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a)){f.each(a,function(){e(this.name,this.value)})}else{for(var g in a){ca(g,a[g],c,e)}}return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState)){d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")}},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch){ch[a](0,1)}}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return !this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials" in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields){for(j in c.xhrFields){h[j]=c.xhrFields[j]}}c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e){h.setRequestHeader(j,e[j])}}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e){h.readyState!==4&&h.abort()}else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0){return this.animate(cu("show",3),a,b,c)}for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties){i.animatedProperties[b]!==!0&&(g=!1)}if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show){for(b in i.animatedProperties){f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0)}}d=i.complete,d&&(i.complete=!1,d.call(h))}return !1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return !0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using" in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0]){return null}var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static"){a=a.offsetParent}return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e){return null}g=cy(e);return g?"pageXOffset" in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e){return a==null?null:this}if(f.isFunction(a)){return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))})}if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9){return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c])}if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;(function(){function d(F){function w(J){var K=J.charCodeAt(0);if(K!==92){return K}var I=J.charAt(1);return(K=k[I])?K:"0"<=I&&I<="7"?parseInt(J.substring(1),8):I==="u"||I==="x"?parseInt(J.substring(2),16):J.charCodeAt(1)}function C(I){if(I<32){return(I<16?"\\x0":"\\x")+I.toString(16)}I=String.fromCharCode(I);if(I==="\\"||I==="-"||I==="["||I==="]"){I="\\"+I}return I}function A(J){for(var M=J.substring(1,J.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),J=[],I=[],O=M[0]==="^",P=O?1:0,L=M.length;P122||(N<65||K>90||I.push([Math.max(65,K)|32,Math.min(N,90)|32]),N<97||K>122||I.push([Math.max(97,K)&-33,Math.min(N,122)&-33]))}}I.sort(function(Q,R){return Q[0]-R[0]||R[1]-Q[1]});M=[];K=[NaN,NaN];for(P=0;PL[0]&&(L[1]+1>L[0]&&I.push("-"),I.push(C(L[1])))}I.push("]");return I.join("")}function E(J){for(var M=J.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),I=M.length,N=[],O=0,L=0;O=2&&J==="["?M[O]=A(K):J!=="\\"&&(M[O]=K.replace(/[A-Za-z]/g,function(P){P=P.charCodeAt(0);return"["+String.fromCharCode(P&-33,P|32)+"]"}))}}return M.join("")}for(var G=0,H=!1,x=!1,u=0,D=F.length;u=5&&"lang-"===O.substring(0,5))&&!(D&&typeof D[1]==="string")){M=!1,O="src"}M||(B[K]=O)}I=L;L+=K.length;if(M){M=D[1];var H=K.indexOf(M),G=H+M.length;D[2]&&(G=K.length-D[2].length,H=G-M.length);O=O.substring(5);t(F+I,K.substring(0,H),x,C);t(F+I+H,M,s(O,M),C);t(F+I+G,K.substring(G),x,C)}else{C.push(F+I,O)}}P.e=C}var w={},A;(function(){for(var G=u.concat(k),B=[],F={},H=0,E=G.length;H=0;){w[I.charAt(C)]=D}}D=D[1];I=""+D;F.hasOwnProperty(I)||(B.push(D),F[I]=q)}B.push(/[\S\s]/);A=d(B)})();var v=k.length;return x}function o(u){var k=[],w=[];u.tripleQuotedStrings?k.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):u.multiLineStrings?k.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,q,"'\"`"]):k.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);u.verbatimStrings&&w.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var v=u.hashComments;v&&(u.cStyleComments?(v>1?k.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):k.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),w.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):k.push(["com",/^#[^\n\r]*/,q,"#"]));u.cStyleComments&&(w.push(["com",/^\/\/[^\n\r]*/,q]),w.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));u.regexLiterals&&w.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(v=u.types)&&w.push(["typ",v]);u=(""+u.keywords).replace(/^ | $/g,"");u.length&&w.push(["kwd",RegExp("^(?:"+u.replace(/[\s,]+/g,"|")+")\\b"),q]);k.push(["pln",/^\s+/,q," \r\n\t\xa0"]);w.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return h(k,w)}function r(H,x){function E(K){switch(K.nodeType){case 1:if(B.test(K.className)){break}if("BR"===K.nodeName){C(K),K.parentNode&&K.parentNode.removeChild(K)}else{for(K=K.firstChild;K;K=K.nextSibling){E(K)}}break;case 3:case 4:if(v){var k=K.nodeValue,L=k.match(I);if(L){var M=k.substring(0,L.index);K.nodeValue=M;(k=k.substring(L.index+L[0].length))&&K.parentNode.insertBefore(J.createTextNode(k),K.nextSibling);C(K);M||K.parentNode.removeChild(K)}}}}function C(K){function k(M,R){var Q=R?M.cloneNode(!1):M,P=M.parentNode;if(P){var P=k(P,1),O=M.nextSibling;P.appendChild(Q);for(var N=O;N;N=O){O=N.nextSibling,P.appendChild(N)}}return Q}for(;!K.nextSibling;){if(K=K.parentNode,!K){return}}for(var K=k(K.nextSibling,0),L;(L=K.parentNode)&&L.nodeType===1;){K=L}F.push(K)}var B=/(?:^|\s)nocode(?:\s|$)/,I=/\r\n?|\n/,J=H.ownerDocument,A;H.currentStyle?A=H.currentStyle.whiteSpace:window.getComputedStyle&&(A=J.defaultView.getComputedStyle(H,q).getPropertyValue("white-space"));var v=A&&"pre"===A.substring(0,3);for(A=J.createElement("LI");H.firstChild;){A.appendChild(H.firstChild)}for(var F=[A],D=0;D=0;){var v=k[w];y.hasOwnProperty(v)?window.console&&console.warn("cannot override language handler %s",v):y[v]=u}}function s(u,k){if(!u||!y.hasOwnProperty(u)){u=/^\s*=J&&(Q+=2);T>=V&&(X+=2)}}catch(C){"console" in window&&console.log(C&&C.stack?C.stack:C)}}var m=["break,continue,do,else,for,if,return,while"],j=[[m,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],n=[j,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],l=[j,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],i=[l,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],j=[j,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],g=[m,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],f=[m,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],m=[m,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,b=/\S/,a=o({keywords:[n,i,j,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+g,f,m],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),y={};z(a,["default-code"]);z(h([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);z(h([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);z(h([],[["atv",/^[\S\s]+/]]),["uq.val"]);z(o({keywords:n,hashComments:!0,cStyleComments:!0,types:e}),["c","cc","cpp","cxx","cyc","m"]);z(o({keywords:"null,true,false"}),["json"]);z(o({keywords:i,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:e}),["cs"]);z(o({keywords:l,cStyleComments:!0}),["java"]);z(o({keywords:m,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);z(o({keywords:g,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py"]);z(o({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);z(o({keywords:f,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);z(o({keywords:j,cStyleComments:!0,regexLiterals:!0}),["js"]);z(o({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);z(h([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(u,k,w){var v=document.createElement("PRE");v.innerHTML=u;w&&r(v,w);p({g:k,i:w,h:v});return v.innerHTML};window.prettyPrint=function(E){function v(){for(var L=window.PR_SHOULD_USE_CONTINUATION?w.now()+250:Infinity;u=0){var I=I.match(B),K,H;if(H=!I){H=O;for(var M=void 0,N=H.firstChild;N;N=N.nextSibling){var J=N.nodeType,M=J===1?M?H:N:J===3?b.test(N.nodeValue)?H:M:M}H=(K=M===H?void 0:M)&&"CODE"===K.tagName}H&&(I=K.className.match(B));I&&(I=I[1]);H=!1;for(M=O.parentNode;M;M=M.parentNode){if((M.tagName==="pre"||M.tagName==="code"||M.tagName==="xmp")&&M.className&&M.className.indexOf("prettyprint")>=0){H=!0;break}}H||((H=(H=O.className.match(/\blinenums\b(?::(\d+))?/))?H[1]&&H[1].length?+H[1]:!0:!1)&&r(O,H),D={g:I,h:O,i:H},p(D))}}u=0&&cIcI&&cM.y>cK.offsetHeight){cN=cM.y-cK.offsetHeight}if(cJ+cK.offsetWidth>cP){cJ=cP-cK.offsetWidth}}}cK.style.top=(cN+ca())+"px";cK.style.left=cK.style.right="";if(cQ=="right"){cJ=bx.clientWidth-cK.offsetWidth;cK.style.right="0px"}else{if(cQ=="left"){cJ=0}else{if(cQ=="middle"){cJ=(bx.clientWidth-cK.offsetWidth)/2}}cK.style.left=(cJ+aV())+"px"}if(cO){ao(cJ,cN,cJ+cK.offsetWidth,cN+cK.offsetHeight)}},lineCount:function(){return cg.size},clipPos:aI,getCursor:function(cI){if(cI==null){cI=cF.inverted}return S(cI?cF.from:cF.to)},somethingSelected:function(){return !U(cF.from,cF.to)},setCursor:ag(function(cI,cK,cJ){if(cK==null&&typeof cI.line=="number"){aW(cI.line,cI.ch,cJ)}else{aW(cI,cK,cJ)}}),setSelection:ag(function(cK,cJ,cI){(cI?bl:bk)(aI(cK),aI(cJ||cK))}),getLine:function(cI){if(be(cI)){return cn(cI).text}},getLineHandle:function(cI){if(be(cI)){return cn(cI)}},setLine:ag(function(cI,cJ){if(be(cI)){bA(cJ,{line:cI,ch:0},{line:cI,ch:cn(cI).text.length})}}),removeLine:ag(function(cI){if(be(cI)){bA("",{line:cI,ch:0},aI({line:cI+1,ch:0}))}}),replaceRange:ag(bA),getRange:function(cJ,cI){return cx(aI(cJ),aI(cI))},execCommand:function(cI){return D[cI](bS)},moveH:ag(cm),deleteH:ag(b5),moveV:ag(cf),toggleOverwrite:function(){b6=!b6},posFromIndex:function(cJ){var cK=0,cI;cg.iter(0,cg.size,function(cL){var cM=cL.text.length+1;if(cM>cJ){cI=cJ;return true}cJ-=cM;++cK});return aI({line:cK,ch:cI})},indexFromPos:function(cJ){if(cJ.line<0||cJ.ch<0){return 0}var cI=cJ.ch;cg.iter(0,cJ.line,function(cK){cI+=cK.text.length+1});return cI},operation:function(cI){return ag(cI)()},refresh:function(){bW(true)},getInputField:function(){return ba},getWrapperElement:function(){return ar},getScrollerElement:function(){return a8},getGutterElement:function(){return aw}};function cn(cI){return v(cg,cI)}function aS(cJ,cI){aH=true;var cK=cI-cJ.height;for(var cL=cJ;cL;cL=cL.parent){cL.height+=cK}}function aM(cI){var cJ={line:0,ch:0};aD(cJ,{line:cg.size-1,ch:cn(cg.size-1).text.length},u(cI),cJ,cJ);b8=true}function bL(cI){var cJ=[];cg.iter(0,cg.size,function(cK){cJ.push(cK.text)});return cJ.join("\n")}function b3(cO){aU(cO.shiftKey);for(var cL=g(cO);cL!=ar;cL=cL.parentNode){if(cL.parentNode==bx&&cL!=bZ){return}}for(var cL=g(cO);cL!=ar;cL=cL.parentNode){if(cL.parentNode==aO){if(bK.onGutterClick){bK.onGutterClick(bS,l(aO.childNodes,cL)+cz,cO)}return L(cO)}}var cI=aT(cO);switch(s(cO)){case 3:if(G&&!E){aR(cO)}return;case 2:if(cI){aW(cI.line,cI.ch,true)}return}if(!cI){if(g(cO)==a8){L(cO)}return}if(!b2){cD()}var cJ=+new Date;if(aP&&aP.time>cJ-400&&U(aP.pos,cI)){L(cO);setTimeout(bn,20);return az(cI.line)}else{if(bd&&bd.time>cJ-400&&U(bd.pos,cI)){aP={time:cJ,pos:cI};L(cO);return bt(cI)}else{bd={time:cJ,pos:cI}}}var cQ=cI,cK;if(y&&!U(cF.from,cF.to)&&!R(cI,cF.from)&&!R(cF.to,cI)){if(d){bi.draggable=true}var cN=m(cu,"mouseup",ag(function(cR){if(d){bi.draggable=false}a0=false;cN();if(Math.abs(cO.clientX-cR.clientX)+Math.abs(cO.clientY-cR.clientY)<10){L(cR);aW(cI.line,cI.ch,true);bn()}}),true);a0=true;return}L(cO);aW(cI.line,cI.ch,true);function cP(cR){var cT=aT(cR,true);if(cT&&!U(cT,cQ)){if(!b2){cD()}cQ=cT;bl(cI,cT);b8=false;var cS=bo();if(cT.line>=cS.to||cT.line-1){setTimeout(ag(function(){bm(cF.to.line,"smart")}),75)}}aF()}function b4(cI){if(bK.onKeyEvent&&bK.onKeyEvent(bS,F(cI))){return}if(cI.keyCode==16){b1=null}}function cD(){if(bK.readOnly){return}if(!b2){if(bK.onFocus){bK.onFocus(bS)}b2=true;if(ar.className.search(/\bCodeMirror-focused\b/)==-1){ar.className+=" CodeMirror-focused"}if(!a4){ck(true)}}ac();cw()}function at(){if(b2){if(bK.onBlur){bK.onBlur(bS)}b2=false;ar.className=ar.className.replace(" CodeMirror-focused","")}clearInterval(cy);setTimeout(function(){if(!b2){b1=null}},150)}function aD(cN,cM,cL,cJ,cI){if(aY){var cK=[];cg.iter(cN.line,cM.line+1,function(cO){cK.push(cO.text)});aY.addChange(cN.line,cL.length,cK);while(aY.done.length>bK.undoDepth){aY.done.shift()}}ah(cN,cM,cL,cJ,cI)}function bT(cN,cM){var cL=cN.pop();if(cL){var cJ=[],cI=cL.start+cL.added;cg.iter(cL.start,cI,function(cO){cJ.push(cO.text)});cM.push({start:cL.start,added:cL.old.length,old:cJ});var cK=aI({line:cL.start+cL.old.length-1,ch:O(cJ[cJ.length-1],cL.old[cL.old.length-1])});ah({line:cL.start,ch:0},{line:cI-1,ch:cn(cI-1).text.length},cL.old,cK,cK);b8=true}}function cC(){bT(aY.done,aY.undone)}function cr(){bT(aY.undone,aY.done)}function ah(cX,cM,c3,cI,c4){var c2=false,cL=bp.length;if(!bK.lineWrapping){cg.iter(cX.line,cM.line,function(c5){if(c5.text.length==cL){c2=true;return true}})}if(cX.line!=cM.line||c3.length>1){aH=true}var cU=cM.line-cX.line,cT=cn(cX.line),cJ=cn(cM.line);if(cX.ch==0&&cM.ch==0&&c3[c3.length-1]==""){var cR=[],cS=null;if(cX.line){cS=cn(cX.line-1);cS.fixMarkEnds(cJ)}else{cJ.fixMarkStarts()}for(var cZ=0,c1=c3.length-1;cZ1){cg.remove(cX.line+1,cU-1,ci)}cg.insert(cX.line+1,cR)}}}if(bK.lineWrapping){var cO=a8.clientWidth/a6()-3;cg.iter(cX.line,cX.line+c3.length,function(c5){if(c5.hidden){return}var c6=Math.ceil(c5.text.length/cO)||1;if(c6!=c5.height){aS(c5,c6)}})}else{cg.iter(cX.line,cZ+c3.length,function(c6){var c5=c6.text;if(c5.length>cL){bp=c5;cL=c5.length;au=null;c2=false}});if(c2){cL=0;bp="";au=null;cg.iter(0,cg.size,function(c6){var c5=c6.text;if(c5.length>cL){cL=c5.length;bp=c5}})}}var cK=[],cQ=c3.length-cU-1;for(var cZ=0,cW=b0.length;cZcM.line){cK.push(c0+cQ)}}}var cY=cX.line+Math.min(c3.length,500);cp(cX.line,cY);cK.push(cY);b0=cK;br(100);ap.push({from:cX.line,to:cM.line+1,diff:cQ});var cP={from:cX,to:cM,text:c3};if(cv){for(var cN=cv;cN.next;cN=cN.next){}cN.next=cP}else{cv=cP}function cV(c5){return c5<=Math.min(cM.line,cM.line+cQ)?c5:c5+cQ}bk(cI,c4,cV(cF.from.line),cV(cF.to.line));bx.style.height=(cg.height*bz()+2*ca())+"px"}function bA(cJ,cM,cL){cM=aI(cM);if(!cL){cL=cM}else{cL=aI(cL)}cJ=u(cJ);function cK(cP){if(R(cP,cM)){return cP}if(!R(cL,cP)){return cI}var cN=cP.line+cJ.length-(cL.line-cM.line)-1;var cO=cP.ch;if(cP.line==cL.line){cO+=cJ[cJ.length-1].length-(cL.ch-(cL.line==cM.line?cM.ch:0))}return{line:cN,ch:cO}}var cI;aq(cJ,cM,cL,function(cN){cI=cN;return{from:cK(cF.from),to:cK(cF.to)}});return cI}function bf(cI,cJ){aq(u(cI),cF.from,cF.to,function(cK){if(cJ=="end"){return{from:cK,to:cK}}else{if(cJ=="start"){return{from:cF.from,to:cF.from}}else{return{from:cF.from,to:cK}}}})}function aq(cL,cN,cM,cI){var cK=cL.length==1?cL[0].length+cN.ch:cL[cL.length-1].length;var cJ=cI({line:cN.line+cL.length-1,ch:cK});aD(cN,cM,cL,cJ.from,cJ.to)}function cx(cM,cL){var cJ=cM.line,cI=cL.line;if(cJ==cI){return cn(cJ).text.slice(cM.ch,cL.ch)}var cK=[cn(cJ).text.slice(cM.ch)];cg.iter(cJ+1,cI,function(cN){cK.push(cN.text)});cK.push(cn(cI).text.slice(0,cL.ch));return cK.join("\n")}function bM(){return cx(cF.from,cF.to)}var bg=false;function ac(){if(bg){return}bQ.set(bK.pollInterval,function(){aC();bv();if(b2){ac()}am()})}function aF(){var cI=false;bg=true;function cJ(){aC();var cK=bv();if(!cK&&!cI){cI=true;bQ.set(60,cJ)}else{bg=false;ac()}am()}bQ.set(20,cJ)}var aZ="";function bv(){if(a4||!b2||V(ba)){return false}var cJ=ba.value;if(cJ==aZ){return false}b1=null;var cK=0,cI=Math.min(aZ.length,cJ.length);while(cKcJ){a1.scrollIntoView()}}function bY(){var cJ=cA(cF.inverted?cF.from:cF.to);var cI=bK.lineWrapping?Math.min(cJ.x,bi.offsetWidth):cJ.x;return ao(cI,cJ.y,cI,cJ.yBot)}function ao(cK,cP,cI,cO){var cM=aV(),cV=ca(),cR=bz();cP+=cV;cO+=cV;cK+=cM;cI+=cM;var cS=a8.clientHeight,cL=a8.scrollTop,cJ=false,cU=true;if(cPcL+cS){a8.scrollTop=cO+cR-cS;cJ=true}}var cQ=a8.clientWidth,cT=a8.scrollLeft;var cN=bK.fixedGutter?aw.clientWidth:0;if(cKcQ+cT-3){a8.scrollLeft=cI+10-cQ;cJ=true;if(cI>bx.clientWidth){cU=false}}}if(cJ&&bK.onScroll){bK.onScroll(bS)}return cU}function bo(){var cJ=bz(),cL=a8.scrollTop-ca();var cI=Math.max(0,Math.floor(cL/cJ));var cK=Math.ceil((cL+a8.clientHeight)/cJ);return{from:P(cg,cI),to:P(cg,cK)}}function bW(cR,cN){if(!a8.clientWidth){cz=bw=a2=0;return}var cL=bo();if(cR!==true&&cR.length==0&&cL.from>=cz&&cL.to<=bw){return}var cS=Math.max(cL.from-100,0),cT=Math.min(cg.size,cL.to+100);if(czcT&&bw-cT<20){cT=Math.min(cg.size,bw)}var cU=cR===true?[]:bJ([{from:cz,to:bw,domStart:0}],cR);var cQ=0;for(var cO=0;cOcT){cP.to=cT}if(cP.from>=cP.to){cU.splice(cO--,1)}else{cQ+=cP.to-cP.from}}if(cQ==cT-cS){return}cU.sort(function(cW,cV){return cW.domStart-cV.domStart});var cK=bz(),cI=aw.style.display;af.style.display=aw.style.display="none";aG(cS,cT,cU);af.style.display="";var cJ=cS!=cz||cT!=bw||by!=a8.clientHeight+cK;if(cJ){by=a8.clientHeight+cK}cz=cS;bw=cT;a2=e(cg,cS);bZ.style.top=(a2*cK)+"px";bx.style.height=(cg.height*cK+2*ca())+"px";if(af.childNodes.length!=bw-cz){throw new Error("BAD PATCH! "+JSON.stringify(cU)+" size="+(bw-cz)+" nodes="+af.childNodes.length)}if(bK.lineWrapping){au=a8.clientWidth;var cM=af.firstChild;cg.iter(cz,bw,function(cW){if(!cW.hidden){var cV=Math.round(cM.offsetHeight/cK)||1;if(cW.height!=cV){aS(cW,cV);aH=true}}cM=cM.nextSibling})}else{if(au==null){au=cb(bp)}if(au>a8.clientWidth){bi.style.width=au+"px";bx.style.width="";bx.style.width=a8.scrollWidth+"px"}else{bi.style.width=bx.style.width=""}}aw.style.display=cI;if(cJ||aH){aA()}a5();if(!cN&&bK.onUpdate){bK.onUpdate(bS)}return true}function bJ(cR,cP){for(var cM=0,cK=cP.length||0;cM=cN.to){cI.push(cN)}else{if(cO.from>cN.from){cI.push({from:cN.from,to:cO.from,domStart:cN.domStart})}if(cO.tocO){cL=cI(cL);cO++}for(var cN=0,cR=cX.to-cX.from;cN=cV;var cS=cu.createElement("div"),cK;cg.iter(cV,cW,function(cZ){var c1=null,c0=null;if(cM){c1=0;if(cT==cN){cM=false;c0=cF.to.ch}}else{if(cU==cN){if(cT==cN){c1=cF.from.ch;c0=cF.to.ch}else{cM=true;c1=cF.from.ch}}}if(cQ&&cQ.to==cN){cQ=cY.shift()}if(!cQ||cQ.from>cN){if(cZ.hidden){cS.innerHTML="
"}else{cS.innerHTML=cZ.getHTML(c1,c0,true,bh)}af.insertBefore(cS.firstChild,cL)}else{cL=cL.nextSibling}++cN})}function aA(){if(!bK.gutter&&!bK.lineNumbers){return}var cI=bZ.offsetHeight,cP=a8.clientHeight;aw.style.height=(cI-cP<2?cP:cI)+"px";var cK=[],cJ=cz;cg.iter(cz,Math.max(bw,cz+1),function(cR){if(cR.hidden){cK.push("
")}else{var cQ=cR.gutterMarker;var cT=bK.lineNumbers?cJ+bK.firstLineNumber:null;if(cQ&&cQ.text){cT=cQ.text.replace("%N%",cT!=null?cT:"")}else{if(cT==null){cT="\u00a0"}}cK.push((cQ&&cQ.style?'
':"
"),cT);for(var cS=1;cS ")}cK.push("
")}++cJ});aw.style.display="none";aO.innerHTML=cK.join("");var cO=String(cg.size).length,cM=aO.firstChild,cN=z(cM),cL="";while(cN.length+cL.lengthcK||cQ>cN.text.length){cQ=cN.text.length}return{line:cR,ch:cQ}}cR+=cP}}var cI=cn(cM.line);if(!cI.hidden){return cM}if(cM.line>=cJ){return cL(1)||cL(-1)}else{return cL(-1)||cL(1)}}function aW(cI,cK,cJ){var cL=aI({line:cI,ch:cK||0});(cJ?bl:bk)(cL,cL)}function bI(cI){return Math.max(0,Math.min(cI,cg.size-1))}function aI(cK){if(cK.line<0){return{line:0,ch:0}}if(cK.line>=cg.size){return{line:cg.size-1,ch:cn(cg.size-1).text.length}}var cI=cK.ch,cJ=cn(cK.line).text.length;if(cI==null||cI>cJ){return{line:cK.line,ch:cJ}}else{if(cI<0){return{line:cK.line,ch:0}}else{return cK}}}function b7(cL,cP){var cM=cF.inverted?cF.from:cF.to,cQ=cM.line,cI=cM.ch;var cO=cn(cQ);function cJ(){for(var cR=cQ+cL,cT=cL<0?-1:cg.size;cR!=cT;cR+=cL){var cS=cn(cR);if(!cS.hidden){cQ=cR;cO=cS;return true}}}function cN(cR){if(cI==(cL<0?0:cO.text.length)){if(!cR&&cJ()){cI=cL<0?cO.text.length:0}else{return false}}else{cI+=cL}return true}if(cP=="char"){cN()}else{if(cP=="column"){cN(true)}else{if(cP=="word"){var cK=false;for(;;){if(cL<0){if(!cN()){break}}if(W(cO.text.charAt(cI))){cK=true}else{if(cK){if(cL<0){cL=1;cN()}break}}if(cL>0){if(!cN()){break}}}}}}return{line:cQ,ch:cI}}function cm(cI,cJ){var cK=cI<0?cF.from:cF.to;if(b1||U(cF.from,cF.to)){cK=b7(cI,cJ)}aW(cK.line,cK.ch,true)}function b5(cI,cJ){if(!U(cF.from,cF.to)){bA("",cF.from,cF.to)}else{if(cI<0){bA("",b7(cI,cJ),cF.to)}else{bA("",cF.from,b7(cI,cJ))}}bP=true}var cd=null;function cf(cI,cJ){var cL=0,cM=cA(cF.inverted?cF.from:cF.to,true);if(cd!=null){cM.x=cd}if(cJ=="page"){cL=a8.clientHeight}else{if(cJ=="line"){cL=bz()}}var cK=bs(cM.x,cM.y+cL*cI+2);aW(cK.line,cK.ch,true);cd=cM.x}function bt(cL){var cJ=cn(cL.line).text;var cK=cL.ch,cI=cL.ch;while(cK>0&&W(cJ.charAt(cK-1))){--cK}while(cIbp.length){bp=cL.text}})}ap.push({from:0,to:cg.size})}function aL(){for(var cJ='',cI=0;cI"}function cE(){bh=aL();bW(true)}function cl(){a8.className=a8.className.replace(/\s*cm-s-\w+/g,"")+bK.theme.replace(/(^|\s)\s*/g," cm-s-")}function cG(){this.set=[]}cG.prototype.clear=ag(function(){var cN=Infinity,cJ=-Infinity;for(var cM=0,cP=this.set.length;cM
";return aj.firstChild.firstChild.offsetWidth}var cP=0,cN=0,cQ=cR.length,cM;var cJ=Math.min(cQ,Math.ceil(cO/a6()));for(;;){var cK=cS(cJ);if(cK<=cO&&cJcM){return cQ}cJ=Math.floor(cQ*0.8);cK=cS(cJ);if(cKcO-cN)?cP:cQ}var cT=Math.ceil((cP+cQ)/2),cI=cS(cT);if(cI>cO){cQ=cT;cM=cI}else{cP=cT;cN=cI}}}var ch=Math.floor(Math.random()*16777215).toString(16);function bO(cK,cN){var cI="";if(bK.lineWrapping){var cJ=cK.text.indexOf(" ",cN+2);cI=H(cK.text.slice(cN+1,cJ<0?cK.text.length:cJ+(A?5:0)))}aj.innerHTML="
"+cK.getHTML(null,null,false,bh,cN)+''+H(cK.text.charAt(cN)||" ")+""+cI+"
";var cM=document.getElementById("CodeMirror-temp-"+ch);var cP=cM.offsetTop,cO=cM.offsetLeft;if(A&&cN&&cP==0&&cO==0){var cL=document.createElement("span");cL.innerHTML="x";cM.parentNode.insertBefore(cL,cM.nextSibling);cP=cL.offsetTop}return{top:cP,left:cO}}function cA(cN,cL){var cI,cJ=bz(),cM=cJ*(e(cg,cN.line)-(cL?a2:0));if(cN.ch==0){cI=0}else{var cK=bO(cn(cN.line),cN.ch);cI=cK.left;if(bK.lineWrapping){cM+=Math.max(0,cK.top)}}return{x:cI,y:cM,yBot:cM+cJ}}function bs(cR,cQ){if(cQ<0){cQ=0}var cO=bz(),cM=a6(),cX=a2+Math.floor(cQ/cO);var cS=P(cg,cX);if(cS>=cg.size){return{line:cg.size-1,ch:cn(cg.size-1).text.length}}var cJ=cn(cS),cU=cJ.text;var cZ=bK.lineWrapping,cP=cZ?cX-e(cg,cS):0;if(cR<=0&&cP==0){return{line:cS,ch:0}}function cY(c1){var c2=bO(cJ,c1);if(cZ){var c3=Math.round(c2.top/cO);return Math.max(0,c2.left+(c3-cP)*a8.clientWidth)}return c2.left}var cW=0,cV=0,cK=cU.length,cI;var cT=Math.min(cK,Math.ceil((cR+cP*a8.clientWidth*0.9)/cM));for(;;){var cN=cY(cT);if(cN<=cR&&cTcI){return{line:cS,ch:cK}}cT=Math.floor(cK*0.8);cN=cY(cT);if(cNcR-cV)?cW:cK}}var c0=Math.ceil((cW+cK)/2),cL=cY(c0);if(cL>cR){cK=c0;cI=cL}else{cW=c0;cV=cL}}}function ae(cK){var cI=cA(cK,true),cJ=aa(bi);return{x:cJ.left+cI.x,y:cJ.top+cI.y,yBot:cJ.top+cI.yBot}}var aQ,al,bE;function bz(){if(bE==null){bE="
";for(var cJ=0;cJ<49;++cJ){bE+="x
"}bE+="x
"}var cI=af.clientHeight;if(cI==al){return aQ}al=cI;aj.innerHTML=bE;aQ=aj.firstChild.offsetHeight/50||1;aj.innerHTML="";return aQ}var cB,bj=0;function a6(){if(a8.clientWidth==bj){return cB}bj=a8.clientWidth;return(cB=cb("x"))}function ca(){return bi.offsetTop}function aV(){return bi.offsetLeft}function aT(cM,cL){var cK=aa(a8,true),cI,cN;try{cI=cM.clientX;cN=cM.clientY}catch(cM){return null}if(!cL&&(cI-cK.left>a8.clientWidth||cN-cK.top>a8.clientHeight)){return null}var cJ=aa(bi,true);return bs(cI-cJ.left,cN-cJ.top)}function aR(cJ){var cN=aT(cJ);if(!cN||window.opera){return}if(U(cF.from,cF.to)||R(cN,cF.from)||!R(cN,cF.to)){ag(aW)(cN.line,cN.ch)}var cM=ba.style.cssText;bH.style.position="absolute";ba.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(cJ.clientY-5)+"px; left: "+(cJ.clientX-5)+"px; z-index: 1000; background: white; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";a4=true;var cL=ba.value=bM();bn();ba.select();function cI(){var cO=u(ba.value).join("\n");if(cO!=cL){ag(bf)(cO,"end")}bH.style.position="relative";ba.style.cssText=cM;a4=false;ck(true);ac()}if(G){r(cJ);var cK=m(window,"mouseup",function(){cK();setTimeout(cI,20)},true)}else{setTimeout(cI,50)}}function cw(){clearInterval(cy);var cI=true;a1.style.visibility="";cy=setInterval(function(){a1.style.visibility=(cI=!cI)?"":"hidden"},650)}var bc={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"};function bX(cO){var cI=cF.inverted?cF.from:cF.to,cQ=cn(cI.line),cJ=cI.ch-1;var cN=(cJ>=0&&bc[cQ.text.charAt(cJ)])||bc[cQ.text.charAt(++cJ)];if(!cN){return}var cR=cN.charAt(0),cP=cN.charAt(1)==">",c1=cP?1:-1,cW=cQ.styles;for(var c2=cJ+1,cY=0,c0=cW.length;cY=c9&&c8"==cP){cL.push(db)}else{if(cL.pop()!=c6.charAt(0)){return{pos:c8,match:false}}else{if(!cL.length){return{pos:c8,match:true}}}}}}}}for(var cY=cI.line,c0=cP?Math.min(cY+100,cg.size):Math.max(-1,cY-100);cY!=c0;cY+=c1){var cQ=cn(cY),cM=cY==cI.line;var cS=cT(cQ,cM&&cP?cJ+1:0,cM&&!cP?cJ:cQ.text.length);if(cS){break}}if(!cS){cS={pos:null,match:false}}var cZ=cS.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket";var cX=bq({line:cI.line,ch:cJ},{line:cI.line,ch:cJ+1},cZ),cK=cS.pos!=null&&bq({line:cY,ch:cS.pos},{line:cY,ch:cS.pos+1},cZ);var cU=ag(function(){cX.clear();cK&&cK.clear()});if(cO){setTimeout(cU,800)}else{bN=cU}}function aX(cO){var cN,cK;for(var cJ=cO,cL=cO-40;cJ>cL;--cJ){if(cJ==0){return 0}var cI=cn(cJ-1);if(cI.stateAfter){return cJ}var cM=cI.indentation(bK.tabSize);if(cK==null||cN>cM){cK=cJ-1;cN=cM}}return cK}function cc(cK){var cJ=aX(cK),cI=cJ&&cn(cJ-1).stateAfter;if(!cI){cI=N(bU)}else{cI=k(bU,cI)}cg.iter(cJ,cK,function(cL){cL.highlight(bU,cI,bK.tabSize);cL.stateAfter=k(bU,cI)});if(cJ=cg.size){continue}var cJ=aX(cL),cI=cJ&&cn(cJ-1).stateAfter;if(cI){cI=k(bU,cI)}else{cI=N(bU)}var cN=0,cK=bU.compareStates,cQ=false,cP=cJ,cM=false;cg.iter(cP,cg.size,function(cS){var cT=cS.stateAfter;if(+new Date>cO){b0.push(cP);br(bK.workDelay);if(cQ){ap.push({from:cL,to:cP+1})}return(cM=true)}var cU=cS.highlight(bU,cI,bK.tabSize);if(cU){cQ=true}cS.stateAfter=k(bU,cI);if(cK){if(cT&&cK(cT,cI)){return true}}else{if(cU!==false||!cT){cN=0}else{if(++cN>3&&(!bU.indent||bU.indent(cT,"")==bU.indent(cI,""))){return true}}}++cP});if(cM){return}if(cQ){ap.push({from:cL,to:cP+1})}}if(cR&&bK.onHighlightComplete){bK.onHighlightComplete(bS)}}function br(cI){if(!b0.length){return}ak.set(cI,ag(bC))}function aC(){b8=bP=cv=null;ap=[];aE=false;ci=[]}function am(){var cM=false,cJ;if(aE){cM=!bY()}if(ap.length){cJ=bW(ap,true)}else{if(aE){a5()}if(aH){aA()}}if(cM){bY()}if(aE){cH();cw()}if(b2&&!a4&&(b8===true||(b8!==false&&aE))){ck(bP)}if(aE&&bK.matchBrackets){setTimeout(ag(function(){if(bN){bN();bN=null}if(U(cF.from,cF.to)){bX(false)}}),20)}var cI=cv,cK=ci;if(aE&&bK.onCursorActivity){bK.onCursorActivity(bS)}if(cI&&bK.onChange&&bS){bK.onChange(bS,cI)}for(var cL=0;cL0&&ae.ch=this.string.length},sol:function(){return this.pos==0},peek:function(){return this.string.charAt(this.pos)},next:function(){if(this.posad},eatSpace:function(){var ac=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos))){++this.pos}return this.pos>ac},skipToEnd:function(){this.pos=this.string.length},skipTo:function(ac){var ad=this.string.indexOf(ac,this.pos);if(ad>-1){this.pos=ad;return true}},backUp:function(ac){this.pos-=ac},column:function(){return j(this.string,this.start,this.tabSize)},indentation:function(){return j(this.string,null,this.tabSize)},match:function(af,ad,ac){if(typeof af=="string"){function ag(ah){return ac?ah.toLowerCase():ah}if(ag(this.string).indexOf(ag(af),this.pos)==this.pos){if(ad!==false){this.pos+=af.length}return true}}else{var ae=this.string.slice(this.pos).match(af);if(ae&&ad!==false){this.pos+=ae[0].length}return ae}},current:function(){return this.string.slice(this.start,this.pos)}};o.StringStream=a;function C(af,ae,ac,ad){this.from=af;this.to=ae;this.style=ac;this.set=ad}C.prototype={attach:function(ac){this.set.push(ac)},detach:function(ad){var ac=l(this.set,ad);if(ac>-1){this.set.splice(ac,1)}},split:function(af,ac){if(this.to<=af&&this.to!=null){return null}var ae=this.from=ag){this.from=Math.max(af,this.from)+ae}if(this.to!=null&&this.to>ag){this.to=afthis.from&&(afthis.from||this.from==null)){this.to=null}},isDead:function(){return this.from!=null&&this.to!=null&&this.from>=this.to},sameSet:function(ac){return this.set==ac.set}};function x(ac){this.from=ac;this.to=ac;this.line=null}x.prototype={attach:function(ac){this.line=ac},detach:function(ac){if(this.line==ac){this.line=null}},split:function(ad,ac){if(adthis.to},clipTo:function(ad,ag,ac,af,ae){if((ad||agthis.to)){this.from=0;this.to=-1}else{if(this.from>ag){this.from=this.to=Math.max(af,this.from)+ae}}},sameSet:function(ac){return false},find:function(){if(!this.line||!this.line.parent){return null}return{line:Q(this.line),ch:this.from}},clear:function(){if(this.line){var ac=l(this.line.marked,this);if(ac!=-1){this.line.marked.splice(ac,1)}this.line=null}}};function c(ad,ac){this.styles=ac||[ad,null];this.text=ad;this.height=1;this.marked=this.gutterMarker=this.className=this.handlers=null;this.stateAfter=this.parent=this.hidden=null}c.inheritMarks=function(ag,aj){var af=new c(ag),ac=aj&&aj.marked;if(ac){for(var ae=0;ae5000){am[aj++]=this.text.slice(al.pos);am[aj++]=null;break}}if(am.length!=aj){am.length=aj;ag=true}if(aj&&am[aj-2]!=ak){ag=true}return ag||(am.length<5&&this.text.length<10?null:false)},getTokenAt:function(ah,af,ae){var ac=this.text,ag=new a(ac);while(ag.pos':"
")}function aw(aF,aE){if(!aF){return}if(af&&A&&aF.charAt(0)==" "){aF="\u00a0"+aF.slice(1)}af=false;if(aE){aj.push('',H(aF).replace(/\t/g,an),"")}else{aj.push(H(aF).replace(/\t/g,an))}}var ap=this.styles,ah=this.text,ao=this.marked;if(aq==av){aq=null}var ay=ah.length;if(at!=null){ay=Math.min(at,ay)}if(!ah&&at==null){aw(" ",aq!=null&&av==null?"CodeMirror-selected":null)}else{if(!ao&&aq==null){for(var ax=0,ak=0;akay){ar=ar.slice(0,ay-ak)}ak+=au;aw(ar,az&&"cm-"+az)}}else{var ae=0,ax=0,am="",az,aC=0;var aA=-1,ai=null;function aB(){if(ao){aA+=1;ai=(aAae){al=aq}else{if(av==null||av>ae){aD=" CodeMirror-selected";if(av!=null){al=Math.min(al,av)}}}}while(ai&&ai.to!=null&&ai.to<=ae){aB()}if(ai){if(ai.from>ae){al=Math.min(al,ai.from)}else{aD+=" "+ai.style;if(ai.to!=null){al=Math.min(al,ai.to)}}}for(;;){var ad=ae+am.length;var ac=az;if(aD){ac=az?az+aD:aD}aw(ad>al?am.slice(0,al-ae):am,ac);if(ad>=al){am=am.slice(al-ae);ae=al;break}ae=ad;am=ap[ax++];az="cm-"+ap[ax++]}}if(aq!=null&&av==null){aw(" ","CodeMirror-selected")}}}if(ag){aj.push("
")}return aj.join("")},cleanUp:function(){this.parent=null;if(this.marked){for(var ac=0,ad=this.marked.length;acai){ak.push(ae.slice(ai-ah,Math.min(ae.length,aj-ah)),ac[ag+1])}if(af>=ai){ad=1}}else{if(ad==1){if(af>aj){ak.push(ae.slice(0,aj-ah),ac[ag+1])}else{ak.push(ae,ac[ag+1])}}}ah=af}}function X(ad){this.lines=ad;this.parent=null;for(var ae=0,af=ad.length,ac=0;ae50){while(ac.lines.length>50){var af=ac.lines.splice(ac.lines.length-25,25);var ai=new X(af);ac.height-=ai.height;this.children.splice(ae+1,0,ai);ai.parent=this}this.maybeSpill()}break}ad-=ah}},maybeSpill:function(){if(this.children.length<=10){return}var af=this;do{var ad=af.children.splice(af.children.length-5,5);var ae=new f(ad);if(!af.parent){var ag=new f(af.children);ag.parent=af;af.children=[ag,ae];af=ag}else{af.size-=ae.size;af.height-=ae.height;var ac=l(af.parent.children,af);af.parent.children.splice(ac+1,0,ae)}ae.parent=af.parent}while(af.children.length>10);af.parent.maybeSpill()},iter:function(ae,ad,ac){this.iterN(ae,ad-ae,ac)},iterN:function(ac,aj,ai){for(var ad=0,ag=this.children.length;ad400||!ag||ag.start>aj+ae||ag.start+ag.added=0;--ad){ag.old.unshift(ac[ad])}ag.added+=ag.start-aj;ag.start=aj}else{if(ag.start-1){b="\r\n"}}());function j(ad,ac,af){if(ac==null){ac=ad.search(/[^\s\u00a0]/);if(ac==-1){ac=ad.length}}for(var ae=0,ag=0;ae=0&&ac>=0;--ad,--ac){if(af.charAt(ad)!=ae.charAt(ac)){break}}return ac+1}function l(af,ac){if(af.indexOf){return af.indexOf(ac)}for(var ad=0,ae=af.length;ad-1){ac.push(ae.slice(af,ae.charAt(ad-1)=="\r"?ad-1:ad));af=ad+1}ac.push(ae.slice(af));return ac}:function(ac){return ac.split(/\r?\n/)};o.splitLines=u;var V=window.getSelection?function(ad){try{return ad.selectionStart!=ad.selectionEnd}catch(ac){return false}}:function(ae){try{var ac=ae.ownerDocument.selection.createRange()}catch(ad){}if(!ac||ac.parentElement()!=ae){return false}return ac.compareEndPoints("StartToEnd",ac)!=0};o.defineMode("null",function(){return{token:function(ac){ac.skipToEnd()}}});o.defineMIME("text/plain","null");var J={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",91:"Mod",92:"Mod",93:"Mod",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63276:"PageUp",63277:"PageDown",63275:"End",63273:"Home",63234:"Left",63232:"Up",63235:"Right",63233:"Down",63302:"Insert",63272:"Delete"};o.keyNames=J;(function(){for(var ac=0;ac<10;ac++){J[ac+48]=String(ac)}for(var ac=65;ac<=90;ac++){J[ac]=String.fromCharCode(ac)}for(var ac=1;ac<=12;ac++){J[ac+111]=J[ac+63235]="F"+ac}})();return o})();CodeMirror.defineMode("javascript",function(J,N){var w=J.indentUnit;var R=N.json;var b=function(){function X(aa){return{type:aa,style:"keyword"}}var U=X("keyword a"),Z=X("keyword b"),Y=X("keyword c");var V=X("operator"),W={type:"atom",style:"atom"};return{"if":U,"while":U,"with":U,"else":Z,"do":Z,"try":Z,"finally":Z,"return":Y,"break":Y,"continue":Y,"new":Y,"delete":Y,"throw":Y,"var":X("var"),"const":X("var"),let:X("var"),"function":X("function"),"catch":X("catch"),"for":X("for"),"switch":X("switch"),"case":X("case"),"default":X("default"),"in":V,"typeof":V,"instanceof":V,"true":W,"false":W,"null":W,"undefined":W,"NaN":W,"Infinity":W}}();var O=/[+\-*&%=<>!?|]/;function S(W,V,U){V.tokenize=U;return U(W,V)}function h(X,U){var W=false,V;while((V=X.next())!=null){if(V==U&&!W){return false}W=!W&&V=="\\"}return W}var T,p;function C(W,V,U){T=W;p=U;return V}function l(Y,W){var U=Y.next();if(U=='"'||U=="'"){return S(Y,W,A(U))}else{if(/[\[\]{}\(\),;\:\.]/.test(U)){return C(U)}else{if(U=="0"&&Y.eat(/x/i)){Y.eatWhile(/[\da-f]/i);return C("number","number")}else{if(/\d/.test(U)){Y.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);return C("number","number")}else{if(U=="/"){if(Y.eat("*")){return S(Y,W,f)}else{if(Y.eat("/")){Y.skipToEnd();return C("comment","comment")}else{if(W.reAllowed){h(Y,"/");Y.eatWhile(/[gimy]/);return C("regexp","string")}else{Y.eatWhile(O);return C("operator",null,Y.current())}}}}else{if(U=="#"){Y.skipToEnd();return C("error","error")}else{if(O.test(U)){Y.eatWhile(O);return C("operator",null,Y.current())}else{Y.eatWhile(/[\w\$_]/);var X=Y.current(),V=b.propertyIsEnumerable(X)&&b[X];return(V&&W.kwAllowed)?C(V.type,V.style,X):C("variable","variable",X)}}}}}}}}function A(U){return function(W,V){if(!h(W,U)){V.tokenize=l}return C("string","string")}}function f(X,W){var U=false,V;while(V=X.next()){if(V=="/"&&U){W.tokenize=l;break}U=(V=="*")}return C("comment","comment")}var k={atom:true,number:true,variable:true,string:true,regexp:true};function u(Z,V,U,Y,W,X){this.indented=Z;this.column=V;this.type=U;this.prev=W;this.info=X;if(Y!=null){this.align=Y}}function x(W,V){for(var U=W.localVars;U;U=U.next){if(U.name==V){return true}}}function F(Y,V,U,X,Z){var aa=Y.cc;v.state=Y;v.stream=Z;v.marked=null,v.cc=aa;if(!Y.lexical.hasOwnProperty("align")){Y.lexical.align=true}while(true){var W=aa.length?aa.pop():R?y:z;if(W(U,X)){while(aa.length&&aa[aa.length-1].lex){aa.pop()()}if(v.marked){return v.marked}if(U=="variable"&&x(Y,X)){return"variable-2"}return V}}}var v={state:null,column:null,marked:null,cc:null};function a(){for(var U=arguments.length-1;U>=0;U--){v.cc.push(arguments[U])}}function H(){a.apply(null,arguments);return true}function m(V){var W=v.state;if(W.context){v.marked="def";for(var U=W.localVars;U;U=U.next){if(U.name==V){return}}W.localVars={name:V,next:W.localVars}}}var E={name:"this",next:{name:"arguments"}};function t(){if(!v.state.context){v.state.localVars=E}v.state.context={prev:v.state.context,vars:v.state.localVars}}function s(){v.state.localVars=v.state.context.vars;v.state.context=v.state.context.prev}function j(V,W){var U=function(){var X=v.state;X.lexical=new u(X.indented,v.stream.column(),V,null,X.lexical,W)};U.lex=true;return U}function G(){var U=v.state;if(U.lexical.prev){if(U.lexical.type==")"){U.indented=U.lexical.indented}U.lexical=U.lexical.prev}}G.lex=true;function c(V){return function U(W){if(W==V){return H()}else{if(V==";"){return a()}else{return H(arguments.callee)}}}}function z(U){if(U=="var"){return H(j("vardef"),K,c(";"),G)}if(U=="keyword a"){return H(j("form"),y,z,G)}if(U=="keyword b"){return H(j("form"),z,G)}if(U=="{"){return H(j("}"),n,G)}if(U==";"){return H()}if(U=="function"){return H(i)}if(U=="for"){return H(j("form"),c("("),j(")"),g,c(")"),G,z,G)}if(U=="variable"){return H(j("stat"),D)}if(U=="switch"){return H(j("form"),y,j("}","switch"),c("{"),n,G,G)}if(U=="case"){return H(y,c(":"))}if(U=="default"){return H(c(":"))}if(U=="catch"){return H(j("form"),t,c("("),r,c(")"),z,G,s)}return a(j("stat"),y,c(";"),G)}function y(U){if(k.hasOwnProperty(U)){return H(M)}if(U=="function"){return H(i)}if(U=="keyword c"){return H(B)}if(U=="("){return H(j(")"),y,c(")"),G,M)}if(U=="operator"){return H(y)}if(U=="["){return H(j("]"),P(y,"]"),G,M)}if(U=="{"){return H(j("}"),P(o,"}"),G,M)}return H()}function B(U){if(U.match(/[;\}\)\],]/)){return a()}return a(y)}function M(U,V){if(U=="operator"&&/\+\+|--/.test(V)){return H(M)}if(U=="operator"){return H(y)}if(U==";"){return}if(U=="("){return H(j(")"),P(y,")"),G,M)}if(U=="."){return H(Q,M)}if(U=="["){return H(j("]"),y,c("]"),G,M)}}function D(U){if(U==":"){return H(G,z)}return a(M,c(";"),G)}function Q(U){if(U=="variable"){v.marked="property";return H()}}function o(U){if(U=="variable"){v.marked="property"}if(k.hasOwnProperty(U)){return H(c(":"),y)}}function P(W,U){function V(Y){if(Y==","){return H(W,V)}if(Y==U){return H()}return H(c(U))}return function X(Y){if(Y==U){return H()}else{return a(W,V)}}}function n(U){if(U=="}"){return H()}return a(z,n)}function K(U,V){if(U=="variable"){m(V);return H(I)}return H()}function I(U,V){if(V=="="){return H(y,I)}if(U==","){return H(K)}}function g(U){if(U=="var"){return H(K,e)}if(U==";"){return a(e)}if(U=="variable"){return H(L)}return a(e)}function L(U,V){if(V=="in"){return H(y)}return H(M,e)}function e(U,V){if(U==";"){return H(d)}if(V=="in"){return H(y)}return H(y,c(";"),d)}function d(U){if(U!=")"){H(y)}}function i(U,V){if(U=="variable"){m(V);return H(i)}if(U=="("){return H(j(")"),t,P(r,")"),G,z,s)}}function r(U,V){if(U=="variable"){m(V);return H()}}return{startState:function(U){return{tokenize:l,reAllowed:true,kwAllowed:true,cc:[],lexical:new u((U||0)-w,0,"block",false),localVars:null,context:null,indented:0}},token:function(W,V){if(W.sol()){if(!V.lexical.hasOwnProperty("align")){V.lexical.align=false}V.indented=W.indentation()}if(W.eatSpace()){return null}var U=V.tokenize(W,V);if(T=="comment"){return U}V.reAllowed=T=="operator"||T=="keyword c"||T.match(/^[\[{}\(,;:]$/);V.kwAllowed=T!=".";return F(V,U,T,p,W)},indent:function(Z,U){if(Z.tokenize!=l){return 0}var Y=U&&U.charAt(0),W=Z.lexical,X=W.type,V=Y==X;if(X=="vardef"){return W.indented+4}else{if(X=="form"&&Y=="{"){return W.indented}else{if(X=="stat"||X=="form"){return W.indented+w}else{if(W.info=="switch"&&!V){return W.indented+(/^(?:case|default)\b/.test(U)?w:2*w)}else{if(W.align){return W.column+(V?0:1)}else{return W.indented+(V?0:w)}}}}}},electricChars:":{}"}});CodeMirror.defineMIME("text/javascript","javascript");CodeMirror.defineMIME("application/json",{name:"javascript",json:true});CodeMirror.defineMode("htmlmixed",function(b,d){var a=CodeMirror.getMode(b,{name:"xml",htmlMode:true});var c=CodeMirror.getMode(b,"javascript");var i=CodeMirror.getMode(b,"css");function e(l,k){var j=a.token(l,k.htmlState);if(j=="tag"&&l.current()==">"&&k.htmlState.context){if(/^script$/i.test(k.htmlState.context.tagName)){k.token=h;k.localState=c.startState(a.indent(k.htmlState,""));k.mode="javascript"}else{if(/^style$/i.test(k.htmlState.context.tagName)){k.token=f;k.localState=i.startState(a.indent(k.htmlState,""));k.mode="css"}}}return j}function g(n,j,k){var m=n.current();var l=m.search(j);if(l>-1){n.backUp(m.length-l)}return k}function h(k,j){if(k.match(/^<\/\s*script\s*>/i,false)){j.token=e;j.curState=null;j.mode="html";return e(k,j)}return g(k,/<\/\s*script\s*>/,c.token(k,j.localState))}function f(k,j){if(k.match(/^<\/\s*style\s*>/i,false)){j.token=e;j.localState=null;j.mode="html";return e(k,j)}return g(k,/<\/\s*style\s*>/,i.token(k,j.localState))}return{startState:function(){var j=a.startState();return{token:e,localState:null,mode:"html",htmlState:j}},copyState:function(k){if(k.localState){var j=CodeMirror.copyState(k.token==f?i:c,k.localState)}return{token:k.token,localState:j,mode:k.mode,htmlState:CodeMirror.copyState(a,k.htmlState)}},token:function(k,j){return j.token(k,j)},indent:function(k,j){if(k.token==e||/^\s*<\//.test(j)){return a.indent(k.htmlState,j)}else{if(k.token==h){return c.indent(k.localState,j)}else{return i.indent(k.localState,j)}}},compareStates:function(k,j){return a.compareStates(k.htmlState,j.htmlState)},electricChars:"/{}:"}});CodeMirror.defineMIME("text/html","htmlmixed");CodeMirror.defineMode("css",function(e){var d=e.indentUnit,f;function c(i,j){f=j;return i}function h(k,j){var i=k.next();if(i=="@"){k.eatWhile(/[\w\\\-]/);return c("meta",k.current())}else{if(i=="/"&&k.eat("*")){j.tokenize=a;return a(k,j)}else{if(i=="<"&&k.eat("!")){j.tokenize=b;return b(k,j)}else{if(i=="="){c(null,"compare")}else{if((i=="~"||i=="|")&&k.eat("=")){return c(null,"compare")}else{if(i=='"'||i=="'"){j.tokenize=g(i);return j.tokenize(k,j)}else{if(i=="#"){k.eatWhile(/[\w\\\-]/);return c("atom","hash")}else{if(i=="!"){k.match(/^\s*\w*/);return c("keyword","important")}else{if(/\d/.test(i)){k.eatWhile(/[\w.%]/);return c("number","unit")}else{if(/[,.+>*\/]/.test(i)){return c(null,"select-op")}else{if(/[;{}:\[\]]/.test(i)){return c(null,i)}else{k.eatWhile(/[\w\\\-]/);return c("variable","variable")}}}}}}}}}}}}function a(l,k){var i=false,j;while((j=l.next())!=null){if(i&&j=="/"){k.tokenize=h;break}i=(j=="*")}return c("comment","comment")}function b(l,k){var j=0,i;while((i=l.next())!=null){if(j>=2&&i==">"){k.tokenize=h;break}j=(i=="-")?j+1:0}return c("comment","comment")}function g(i){return function(m,k){var l=false,j;while((j=m.next())!=null){if(j==i&&!l){break}l=!l&&j=="\\"}if(!l){k.tokenize=h}return c("string","string")}}return{startState:function(i){return{tokenize:h,baseIndent:i||0,stack:[]}},token:function(l,k){if(l.eatSpace()){return null}var j=k.tokenize(l,k);var i=k.stack[k.stack.length-1];if(f=="hash"&&i=="rule"){j="atom"}else{if(j=="variable"){if(i=="rule"){j="number"}else{if(!i||i=="@media{"){j="tag"}}}}if(i=="rule"&&/^[\{\};]$/.test(f)){k.stack.pop()}if(f=="{"){if(i=="@media"){k.stack[k.stack.length-1]="@media{"}else{k.stack.push("{")}}else{if(f=="}"){k.stack.pop()}else{if(f=="@media"){k.stack.push("@media")}else{if(i=="{"&&f!="comment"){k.stack.push("rule")}}}}return j},indent:function(j,i){var k=j.stack.length;if(/^\}/.test(i)){k-=j.stack[j.stack.length-1]=="rule"?2:1}return j.baseIndent+k*d},electricChars:"}"}});CodeMirror.defineMIME("text/css","css");CodeMirror.defineMode("xml",function(x,k){var p=x.indentUnit;var w=k.htmlMode?{autoSelfClosers:{br:true,img:true,hr:true,link:true,input:true,meta:true,col:true,frame:true,base:true,area:true},doNotIndent:{pre:true},allowUnquoted:true}:{autoSelfClosers:{},doNotIndent:{},allowUnquoted:false};var a=k.alignCDATA;var f,g;function o(C,B){function z(E){B.tokenize=E;return E(C,B)}var A=C.next();if(A=="<"){if(C.eat("!")){if(C.eat("[")){if(C.match("CDATA[")){return z(v("atom","]]>"))}else{return null}}else{if(C.match("--")){return z(v("comment","-->"))}else{if(C.match("DOCTYPE",true,true)){C.eatWhile(/[\w\._\-]/);return z(y(1))}else{return null}}}}else{if(C.eat("?")){C.eatWhile(/[\w\._\-]/);B.tokenize=v("meta","?>");return"meta"}else{g=C.eat("/")?"closeTag":"openTag";C.eatSpace();f="";var D;while((D=C.eat(/[^\s\u00a0=<>\"\'\/?]/))){f+=D}B.tokenize=n;return"tag"}}}else{if(A=="&"){C.eatWhile(/[^;]/);C.eat(";");return"atom"}else{C.eatWhile(/[^&<]/);return null}}}function n(B,A){var z=B.next();if(z==">"||(z=="/"&&B.eat(">"))){A.tokenize=o;g=z==">"?"endTag":"selfcloseTag";return"tag"}else{if(z=="="){g="equals";return null}else{if(/[\'\"]/.test(z)){A.tokenize=j(z);return A.tokenize(B,A)}else{B.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);return"word"}}}}function j(z){return function(B,A){while(!B.eol()){if(B.next()==z){A.tokenize=n;break}}return"string"}}function v(A,z){return function(C,B){while(!C.eol()){if(C.match(z)){B.tokenize=o;break}C.next()}return A}}function y(z){return function(C,B){var A;while((A=C.next())!=null){if(A=="<"){B.tokenize=y(z+1);return B.tokenize(C,B)}else{if(A==">"){if(z==1){B.tokenize=o;break}else{B.tokenize=y(z-1);return B.tokenize(C,B)}}}}return"meta"}}var l,h;function b(){for(var z=arguments.length-1;z>=0;z--){l.cc.push(arguments[z])}}function e(){b.apply(null,arguments);return true}function i(z,B){var A=w.doNotIndent.hasOwnProperty(z)||(l.context&&l.context.noIndent);l.context={prev:l.context,tagName:z,indent:l.indented,startOfLine:B,noIndent:A}}function t(){if(l.context){l.context=l.context.prev}}function d(z){if(z=="openTag"){l.tagName=f;return e(m,c(l.startOfLine))}else{if(z=="closeTag"){var A=false;if(l.context){A=l.context.tagName!=f}else{A=true}if(A){h="error"}return e(r(A))}}return e()}function c(z){return function(A){if(A=="selfcloseTag"||(A=="endTag"&&w.autoSelfClosers.hasOwnProperty(l.tagName.toLowerCase()))){return e()}if(A=="endTag"){i(l.tagName,z);return e()}return e()}}function r(z){return function(A){if(z){h="error"}if(A=="endTag"){t();return e()}h="error";return e(arguments.callee)}}function m(z){if(z=="word"){h="attribute";return e(m)}if(z=="equals"){return e(u,m)}if(z=="string"){h="error";return e(m)}return b()}function u(z){if(z=="word"&&w.allowUnquoted){h="string";return e()}if(z=="string"){return e(s)}return b()}function s(z){if(z=="string"){return e(s)}else{return b()}}return{startState:function(){return{tokenize:o,cc:[],indented:0,startOfLine:true,tagName:null,context:null}},token:function(C,B){if(C.sol()){B.startOfLine=true;B.indented=C.indentation()}if(C.eatSpace()){return null}h=g=f=null;var A=B.tokenize(C,B);B.type=g;if((A||g)&&A!="comment"){l=B;while(true){var z=B.cc.pop()||d;if(z(g||A)){break}}}B.startOfLine=false;return h||A},indent:function(C,z,B){var A=C.context;if((C.tokenize!=n&&C.tokenize!=o)||A&&A.noIndent){return B?B.match(/^(\s*)/)[0].length:0}if(a&&/0){v=e.pop()}}function ac(t,ag){for(var af=0;af=x){return["","TK_EOF"]}T=false;var an=c.charAt(o);o+=1;var ap=l&&N(v.mode);if(ap){var ah=0;while(L(an,H)){if(an==="\n"){u();E.push("\n");ae=true;ah=0}else{if(an==="\t"){ah+=4}else{if(an==="\r"){}else{ah+=1}}}if(o>=x){return["","TK_EOF"]}an=c.charAt(o);o+=1}if(v.indentation_baseline===-1){v.indentation_baseline=ah}if(ae){var aj;for(aj=0;aj=x){return["","TK_EOF"]}an=c.charAt(o);o+=1}if(V){if(k>1){for(aj=0;aj0}if(L(an,Y)){if(o=x){break}}}o+=2;if(ao){return["/*"+ak+"*/","TK_INLINE_COMMENT"]}else{return["/*"+ak+"*/","TK_BLOCK_COMMENT"]}}if(c.charAt(o)==="/"){ak=an;while(c.charAt(o)!=="\r"&&c.charAt(o)!=="\n"){ak+=c.charAt(o);o+=1;if(o>=x){break}}o+=1;if(T){D()}return[ak,"TK_COMMENT"]}}if(an==="'"||an==='"'||(an==="/"&&((S==="TK_WORD"&&L(m,["return","do"]))||(S==="TK_COMMENT"||S==="TK_START_EXPR"||S==="TK_START_BLOCK"||S==="TK_END_BLOCK"||S==="TK_OPERATOR"||S==="TK_EQUALS"||S==="TK_EOF"||S==="TK_SEMICOLON")))){var ar=an;var am=false;var af=an;if(o=x){return[af,"TK_STRING"]}}}else{while(am||c.charAt(o)!==ar){af+=c.charAt(o);if(!am){am=c.charAt(o)==="\\"}else{am=false}o+=1;if(o>=x){return[af,"TK_STRING"]}}}}o+=1;af+=ar;if(ar==="/"){while(o"){v.in_html_comment=false;o+=2;if(T){D()}return["-->","TK_COMMENT"]}if(L(an,g)){while(o=x){break}}if(an==="="){return[an,"TK_EQUALS"]}else{return[an,"TK_OPERATOR"]}}return[an,"TK_UNKNOWN"]}ab="";while(K>0){ab+=j;K-=1}while(d&&(d[0]===" "||d[0]==="\t")){ad+=d[0];d=d.substring(1)}c=d;C="";S="TK_START_EXPR";m="";y="";E=[];G=false;H="\n\r\t ".split("");Y="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$".split("");aa="0123456789".split("");g="+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::".split(" ");w="continue,try,throw,return,var,if,switch,case,default,for,while,break,function".split(",");e=[];n("BLOCK");o=0;while(true){var U=X(o);r=U[0];W=U[1];if(W==="TK_EOF"){break}switch(W){case"TK_START_EXPR":if(r==="["){if(S==="TK_WORD"||m===")"){if(L(m,w)){A()}n("(EXPRESSION)");J();break}if(v.mode==="[EXPRESSION]"||v.mode==="[INDENTED-EXPRESSION]"){if(y==="]"&&m===","){if(v.mode==="[EXPRESSION]"){v.mode="[INDENTED-EXPRESSION]";if(!l){p()}}n("[EXPRESSION]");if(!l){D()}}else{if(m==="["){if(v.mode==="[EXPRESSION]"){v.mode="[INDENTED-EXPRESSION]";if(!l){p()}}n("[EXPRESSION]");if(!l){D()}}else{n("[EXPRESSION]")}}}else{n("[EXPRESSION]")}}else{n("(EXPRESSION)")}if(m===";"||S==="TK_START_BLOCK"){D()}else{if(S==="TK_END_EXPR"||S==="TK_START_EXPR"||S==="TK_END_BLOCK"||m==="."){}else{if(S!=="TK_WORD"&&S!=="TK_OPERATOR"){A()}else{if(C==="function"||C==="typeof"){if(s){A()}}else{if(L(m,w)||m==="catch"){A()}}}}}J();break;case"TK_END_EXPR":if(r==="]"){if(l){if(m==="}"){P();J();f();break}}else{if(v.mode==="[INDENTED-EXPRESSION]"){if(m==="]"){f();D();J();break}}}}f();J();break;case"TK_START_BLOCK":if(C==="do"){n("DO_BLOCK")}else{n("BLOCK")}if(R=="expand"){if(S!=="TK_OPERATOR"){if(m==="return"||m==="="){A()}else{D(true)}}J();p()}else{if(S!=="TK_OPERATOR"&&S!=="TK_START_EXPR"){if(S==="TK_START_BLOCK"){D()}else{A()}}else{if(N(v.previous_mode)&&m===","){if(y==="}"){A()}else{D()}}}p();J()}break;case"TK_END_BLOCK":f();if(R=="expand"){if(m!=="{"){D()}J()}else{if(S==="TK_START_BLOCK"){if(ae){P()}else{u()}}else{if(N(v.mode)&&l){l=false;D();l=true}else{D()}}J()}break;case"TK_WORD":if(G){A();J();A();G=false;break}if(r==="function"){if(v.var_line){v.var_line_reindented=true}if((ae||m===";")&&m!=="{"){k=ae?k:0;if(!V){k=1}for(var Z=0;Z<2-k;Z++){D(false)}}}if(r==="case"||r==="default"){if(m===":"){P()}else{v.indentation_level--;D();v.indentation_level++}J();v.in_case=true;break}Q="NONE";if(S==="TK_END_BLOCK"){if(!L(r.toLowerCase(),["else","catch","finally"])){Q="NEWLINE"}else{if(R=="expand"||R=="end-expand"){Q="NEWLINE"}else{Q="SPACE";A()}}}else{if(S==="TK_SEMICOLON"&&(v.mode==="BLOCK"||v.mode==="DO_BLOCK")){Q="NEWLINE"}else{if(S==="TK_SEMICOLON"&&F(v.mode)){Q="SPACE"}else{if(S==="TK_STRING"){Q="NEWLINE"}else{if(S==="TK_WORD"){if(m==="else"){u(true)}Q="SPACE"}else{if(S==="TK_START_BLOCK"){Q="NEWLINE"}else{if(S==="TK_END_EXPR"){A();Q="NEWLINE"}}}}}}}if(L(r,w)&&m!==")"){if(m=="else"){Q="SPACE"}else{Q="NEWLINE"}}if(v.if_line&&S==="TK_END_EXPR"){v.if_line=false}if(L(r.toLowerCase(),["else","catch","finally"])){if(S!=="TK_END_BLOCK"||R=="expand"||R=="end-expand"){D()}else{u(true);A()}}else{if(Q==="NEWLINE"){if((S==="TK_START_EXPR"||m==="="||m===",")&&r==="function"){}else{if(r==="function"&&m=="new"){A()}else{if(m==="return"||m==="throw"){A()}else{if(S!=="TK_END_EXPR"){if((S!=="TK_START_EXPR"||r!=="var")&&m!==":"){if(r==="if"&&C==="else"&&m!=="{"){A()}else{v.var_line=false;v.var_line_reindented=false;D()}}}else{if(L(r,w)&&m!=")"){v.var_line=false;v.var_line_reindented=false;D()}}}}}}else{if(N(v.mode)&&m===","&&y==="}"){D()}else{if(Q==="SPACE"){A()}}}}J();C=r;if(r==="var"){v.var_line=true;v.var_line_reindented=false;v.var_line_tainted=false}if(r==="if"){v.if_line=true}if(r==="else"){v.if_line=false}break;case"TK_SEMICOLON":J();v.var_line=false;v.var_line_reindented=false;if(v.mode=="OBJECT"){v.mode="BLOCK"}break;case"TK_STRING":if(S==="TK_START_BLOCK"||S==="TK_END_BLOCK"||S==="TK_SEMICOLON"){D()}else{if(S==="TK_WORD"){A()}}J();break;case"TK_EQUALS":if(v.var_line){v.var_line_tainted=true}A();J();A();break;case"TK_OPERATOR":var b=true;var I=true;if(v.var_line&&r===","&&(F(v.mode))){v.var_line_tainted=false}if(v.var_line){if(r===","){if(v.var_line_tainted){J();v.var_line_reindented=true;v.var_line_tainted=false;D();break}else{v.var_line_tainted=false}}}if(m==="return"||m==="throw"){A();J();break}if(r===":"&&v.in_case){J();D();v.in_case=false;break}if(r==="::"){J();break}if(r===","){if(v.var_line){if(v.var_line_tainted){J();D();v.var_line_tainted=false}else{J();A()}}else{if(S==="TK_END_BLOCK"&&v.mode!=="(EXPRESSION)"){J();if(v.mode==="OBJECT"&&m==="}"){D()}else{A()}}else{if(v.mode==="OBJECT"){J();D()}else{J();A()}}}break}else{if(L(r,["--","++","!"])||(L(r,["-","+"])&&(L(S,["TK_START_BLOCK","TK_START_EXPR","TK_EQUALS","TK_OPERATOR"])||L(m,w)))){b=false;I=false;if(m===";"&&F(v.mode)){b=true}if(S==="TK_WORD"&&L(m,w)){b=true}if(v.mode==="BLOCK"&&(m==="{"||m===";")){D()}}else{if(r==="."){b=false}else{if(r===":"){if(v.ternary_depth==0){v.mode="OBJECT";b=false}else{v.ternary_depth-=1}}else{if(r==="?"){v.ternary_depth+=1}}}}}if(b){A()}J();if(I){A()}if(r==="!"){}break;case"TK_BLOCK_COMMENT":var M=r.split(/\x0a|\x0d\x0a/);if(ac(M.slice(1),"*")){D();E.push(M[0]);for(Z=1;Z1){D();u()}else{A()}for(Z=0;Z=f){u/=2;t/=2;s>>>=1}return(u+s)/t};return m};function e(s){var r,o,w=this,v=s.length;var p=0,n=w.i=w.j=w.m=0;w.S=[];w.c=[];if(!v){s=[v++]}while(p-1,Gecko:b.indexOf("Gecko")>-1&&b.indexOf("KHTML")===-1,MobileSafari:/Apple.*Mobile.*Safari/.test(b)}})(),BrowserFeatures:{XPath:!!document.evaluate,SelectorsAPI:!!document.querySelector,ElementExtensions:(function(){var a=window.Element||window.HTMLElement;return !!(a&&a.prototype)})(),SpecificElementExtensions:(function(){if(typeof window.HTMLDivElement!=="undefined"){return true}var c=document.createElement("div");var b=document.createElement("form");var a=false;if(c.__proto__&&(c.__proto__!==b.__proto__)){a=true}c=b=null;return a})()},ScriptFragment:"]*>([\\S\\s]*?)<\/script>",JSONFilter:/^\/\*-secure-([\s\S]*)\*\/\s*$/,emptyFunction:function(){},K:function(a){return a}};if(Prototype.Browser.MobileSafari){Prototype.BrowserFeatures.SpecificElementExtensions=false}var Abstract={};var Try={these:function(){var c;for(var b=0,d=arguments.length;b0){if(match=source.match(pattern)){result+=source.slice(0,match.index);result+=String.interpret(replacement(match));source=source.slice(match.index+match[0].length)}else{result+=source,source=""}}return result}function sub(pattern,replacement,count){replacement=prepareReplacement(replacement);count=Object.isUndefined(count)?1:count;return this.gsub(pattern,function(match){if(--count<0){return match[0]}return replacement(match)})}function scan(pattern,iterator){this.gsub(pattern,iterator);return String(this)}function truncate(length,truncation){length=length||30;truncation=Object.isUndefined(truncation)?"...":truncation;return this.length>length?this.slice(0,length-truncation.length)+truncation:String(this)}function strip(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}function stripTags(){return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi,"")}function stripScripts(){return this.replace(new RegExp(Prototype.ScriptFragment,"img"),"")}function extractScripts(){var matchAll=new RegExp(Prototype.ScriptFragment,"img");var matchOne=new RegExp(Prototype.ScriptFragment,"im");return(this.match(matchAll)||[]).map(function(scriptTag){return(scriptTag.match(matchOne)||["",""])[1]})}function evalScripts(){return this.extractScripts().map(function(script){return eval(script)})}function escapeHTML(){return this.replace(/&/g,"&").replace(//g,">")}function unescapeHTML(){return this.stripTags().replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&")}function toQueryParams(separator){var match=this.strip().match(/([^?#]*)(#.*)?$/);if(!match){return{}}return match[1].split(separator||"&").inject({},function(hash,pair){if((pair=pair.split("="))[0]){var key=decodeURIComponent(pair.shift());var value=pair.length>1?pair.join("="):pair[0];if(value!=undefined){value=decodeURIComponent(value)}if(key in hash){if(!Object.isArray(hash[key])){hash[key]=[hash[key]]}hash[key].push(value)}else{hash[key]=value}}return hash})}function toArray(){return this.split("")}function succ(){return this.slice(0,this.length-1)+String.fromCharCode(this.charCodeAt(this.length-1)+1)}function times(count){return count<1?"":new Array(count+1).join(this)}function camelize(){var parts=this.split("-"),len=parts.length;if(len==1){return parts[0]}var camelized=this.charAt(0)=="-"?parts[0].charAt(0).toUpperCase()+parts[0].substring(1):parts[0];for(var i=1;i-1}function startsWith(pattern){return this.indexOf(pattern)===0}function endsWith(pattern){var d=this.length-pattern.length;return d>=0&&this.lastIndexOf(pattern)===d}function empty(){return this==""}function blank(){return/^\s*$/.test(this)}function interpolate(object,pattern){return new Template(this,pattern).evaluate(object)}return{gsub:gsub,sub:sub,scan:scan,truncate:truncate,strip:String.prototype.trim?String.prototype.trim:strip,stripTags:stripTags,stripScripts:stripScripts,extractScripts:extractScripts,evalScripts:evalScripts,escapeHTML:escapeHTML,unescapeHTML:unescapeHTML,toQueryParams:toQueryParams,parseQuery:toQueryParams,toArray:toArray,succ:succ,times:times,camelize:camelize,capitalize:capitalize,underscore:underscore,dasherize:dasherize,inspect:inspect,toJSON:toJSON,unfilterJSON:unfilterJSON,isJSON:isJSON,evalJSON:evalJSON,include:include,startsWith:startsWith,endsWith:endsWith,empty:empty,blank:blank,interpolate:interpolate}})());var Template=Class.create({initialize:function(a,b){this.template=a.toString();this.pattern=b||Template.Pattern},evaluate:function(a){if(a&&Object.isFunction(a.toTemplateReplacements)){a=a.toTemplateReplacements()}return this.template.gsub(this.pattern,function(d){if(a==null){return(d[1]+"")}var f=d[1]||"";if(f=="\\"){return d[2]}var b=a,g=d[3];var e=/^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;d=e.exec(g);if(d==null){return f}while(d!=null){var c=d[1].startsWith("[")?d[2].replace(/\\\\]/g,"]"):d[1];b=b[c];if(null==b||""==d[3]){break}g=g.substring("["==d[3]?d[1].length:d[0].length);d=e.exec(g)}return f+String.interpret(b)})}});Template.Pattern=/(^|.|\r|\n)(#\{(.*?)\})/;var $break={};var Enumerable=(function(){function c(y,x){var w=0;try{this._each(function(A){y.call(x,A,w++)})}catch(z){if(z!=$break){throw z}}return this}function r(z,y,x){var w=-z,A=[],B=this.toArray();if(z<1){return B}while((w+=z)=w){w=A}});return w}function n(y,x){y=y||Prototype.K;var w;this.each(function(A,z){A=y.call(x,A,z);if(w==null||Ay?1:0}).pluck("value")}function o(){return this.map()}function s(){var x=Prototype.K,w=$A(arguments);if(Object.isFunction(w.last())){x=w.pop()}var y=[this].concat(w).map($A);return this.map(function(A,z){return x(y.pluck(z))})}function k(){return this.toArray().length}function u(){return"#"}return{each:c,eachSlice:r,all:b,every:b,any:i,some:i,collect:j,map:j,detect:t,findAll:h,select:h,filter:h,grep:g,include:a,member:a,inGroupsOf:q,inject:l,invoke:v,max:p,min:n,partition:e,pluck:f,reject:d,sortBy:m,toArray:o,entries:o,zip:s,size:k,inspect:u,find:t}})();function $A(c){if(!c){return[]}if("toArray" in Object(c)){return c.toArray()}var b=c.length||0,a=new Array(b);while(b--){a[b]=c[b]}return a}function $w(a){if(!Object.isString(a)){return[]}a=a.strip();return a?a.split(/\s+/):[]}Array.from=$A;(function(){var s=Array.prototype,m=s.slice,o=s.forEach;function b(w){for(var v=0,x=this.length;v"}function j(){return Object.toJSON(this.toObject())}function h(){return new Hash(this)}return{initialize:e,_each:f,set:k,get:c,unset:n,toObject:p,toTemplateReplacements:p,keys:o,values:m,index:g,merge:i,update:d,toQueryString:a,inspect:l,toJSON:j,clone:h}})());Hash.from=$H;Object.extend(Number.prototype,(function(){function d(){return this.toPaddedString(2,16)}function e(){return this+1}function a(k,j){$R(0,this,true).each(k,j);return this}function b(l,k){var j=this.toString(k||10);return"0".times(l-j.length)+j}function f(){return isFinite(this)?this.toString():"null"}function i(){return Math.abs(this)}function h(){return Math.round(this)}function g(){return Math.ceil(this)}function c(){return Math.floor(this)}return{toColorPart:d,succ:e,times:a,toPaddedString:b,toJSON:f,abs:i,round:h,ceil:g,floor:c}})());function $R(c,a,b){return new ObjectRange(c,a,b)}var ObjectRange=Class.create(Enumerable,(function(){function b(f,d,e){this.start=f;this.end=d;this.exclusive=e}function c(d){var e=this.start;while(this.include(e)){d(e);e=e.succ()}}function a(d){if(d1&&!((a==4)&&this._complete)){this.respondToReadyState(this.transport.readyState)}},setRequestHeaders:function(){var e={"X-Requested-With":"XMLHttpRequest","X-Prototype-Version":Prototype.Version,Accept:"text/javascript, text/html, application/xml, text/xml, */*"};if(this.method=="post"){e["Content-type"]=this.options.contentType+(this.options.encoding?"; charset="+this.options.encoding:"");if(this.transport.overrideMimeType&&(navigator.userAgent.match(/Gecko\/(\d{4})/)||[0,2005])[1]<2005){e.Connection="close"}}if(typeof this.options.requestHeaders=="object"){var c=this.options.requestHeaders;if(Object.isFunction(c.push)){for(var b=0,d=c.length;b=200&&a<300)},getStatus:function(){try{return this.transport.status||0}catch(a){return 0}},respondToReadyState:function(a){var c=Ajax.Request.Events[a],b=new Ajax.Response(this);if(c=="Complete"){try{this._complete=true;(this.options["on"+b.status]||this.options["on"+(this.success()?"Success":"Failure")]||Prototype.emptyFunction)(b,b.headerJSON)}catch(d){this.dispatchException(d)}var f=b.getHeader("Content-type");if(this.options.evalJS=="force"||(this.options.evalJS&&this.isSameOrigin()&&f&&f.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))){this.evalResponse()}}try{(this.options["on"+c]||Prototype.emptyFunction)(b,b.headerJSON);Ajax.Responders.dispatch("on"+c,this,b,b.headerJSON)}catch(d){this.dispatchException(d)}if(c=="Complete"){this.transport.onreadystatechange=Prototype.emptyFunction}},isSameOrigin:function(){var a=this.url.match(/^\s*https?:\/\/[^\/]*/);return !a||(a[0]=="#{protocol}//#{domain}#{port}".interpolate({protocol:location.protocol,domain:document.domain,port:location.port?":"+location.port:""}))},getHeader:function(a){try{return this.transport.getResponseHeader(a)||null}catch(b){return null}},evalResponse:function(){try{return eval((this.transport.responseText||"").unfilterJSON())}catch(e){this.dispatchException(e)}},dispatchException:function(a){(this.options.onException||Prototype.emptyFunction)(this,a);Ajax.Responders.dispatch("onException",this,a)}});Ajax.Request.Events=["Uninitialized","Loading","Loaded","Interactive","Complete"];Ajax.Response=Class.create({initialize:function(c){this.request=c;var d=this.transport=c.transport,a=this.readyState=d.readyState;if((a>2&&!Prototype.Browser.IE)||a==4){this.status=this.getStatus();this.statusText=this.getStatusText();this.responseText=String.interpret(d.responseText);this.headerJSON=this._getHeaderJSON()}if(a==4){var b=d.responseXML;this.responseXML=Object.isUndefined(b)?null:b;this.responseJSON=this._getResponseJSON()}},status:0,statusText:"",getStatus:Ajax.Request.prototype.getStatus,getStatusText:function(){try{return this.transport.statusText||""}catch(a){return""}},getHeader:Ajax.Request.prototype.getHeader,getAllHeaders:function(){try{return this.getAllResponseHeaders()}catch(a){return null}},getResponseHeader:function(a){return this.transport.getResponseHeader(a)},getAllResponseHeaders:function(){return this.transport.getAllResponseHeaders()},_getHeaderJSON:function(){var a=this.getHeader("X-JSON");if(!a){return null}a=decodeURIComponent(escape(a));try{return a.evalJSON(this.request.options.sanitizeJSON||!this.request.isSameOrigin())}catch(b){this.request.dispatchException(b)}},_getResponseJSON:function(){var a=this.request.options;if(!a.evalJSON||(a.evalJSON!="force"&&!(this.getHeader("Content-type")||"").include("application/json"))||this.responseText.blank()){return null}try{return this.responseText.evalJSON(a.sanitizeJSON||!this.request.isSameOrigin())}catch(b){this.request.dispatchException(b)}}});Ajax.Updater=Class.create(Ajax.Request,{initialize:function($super,a,c,b){this.container={success:(a.success||a),failure:(a.failure||(a.success?null:a))};b=Object.clone(b);var d=b.onComplete;b.onComplete=(function(e,f){this.updateContent(e.responseText);if(Object.isFunction(d)){d(e,f)}}).bind(this);$super(c,b)},updateContent:function(d){var c=this.container[this.success()?"success":"failure"],a=this.options;if(!a.evalScripts){d=d.stripScripts()}if(c=$(c)){if(a.insertion){if(Object.isString(a.insertion)){var b={};b[a.insertion]=d;c.insert(b)}else{a.insertion(c,d)}}else{c.update(d)}}}});Ajax.PeriodicalUpdater=Class.create(Ajax.Base,{initialize:function($super,a,c,b){$super(b);this.onComplete=this.options.onComplete;this.frequency=(this.options.frequency||2);this.decay=(this.options.decay||1);this.updater={};this.container=a;this.url=c;this.start()},start:function(){this.options.onComplete=this.updateComplete.bind(this);this.onTimerEvent()},stop:function(){this.updater.options.onComplete=undefined;clearTimeout(this.timer);(this.onComplete||Prototype.emptyFunction).apply(this,arguments)},updateComplete:function(a){if(this.options.decay){this.decay=(a.responseText==this.lastText?this.decay*this.options.decay:1);this.lastText=a.responseText}this.timer=this.onTimerEvent.bind(this).delay(this.decay*this.frequency)},onTimerEvent:function(){this.updater=new Ajax.Updater(this.container,this.url,this.options)}});function $(b){if(arguments.length>1){for(var a=0,d=[],c=arguments.length;a';delete e.name;return Element.writeAttribute(document.createElement(f),e)}if(!d[f]){d[f]=Element.extend(document.createElement(f))}return Element.writeAttribute(d[f].cloneNode(false),e)};Object.extend(c.Element,a||{});if(a){c.Element.prototype=a.prototype}})(this);Element.cache={};Element.idCounter=1;Element.Methods={visible:function(a){return $(a).style.display!="none"},toggle:function(a){a=$(a);Element[Element.visible(a)?"hide":"show"](a);return a},hide:function(a){a=$(a);a.style.display="none";return a},show:function(a){a=$(a);a.style.display="";return a},remove:function(a){a=$(a);a.parentNode.removeChild(a);return a},update:(function(){var b=(function(){var e=document.createElement("select"),f=true;e.innerHTML='';if(e.options&&e.options[0]){f=e.options[0].nodeName.toUpperCase()!=="OPTION"}e=null;return f})();var a=(function(){try{var f=document.createElement("table");if(f&&f.tBodies){f.innerHTML="
";var h=typeof f.tBodies[0]=="undefined";f=null;return h}}catch(g){return true}})();var d=(function(){var f=document.createElement("script"),h=false;try{f.appendChild(document.createTextNode(""));h=!f.firstChild||f.firstChild&&f.firstChild.nodeType!==3}catch(g){h=true}f=null;return h})();function c(f,g){f=$(f);if(g&&g.toElement){g=g.toElement()}if(Object.isElement(g)){return f.update().insert(g)}g=Object.toHTML(g);var e=f.tagName.toUpperCase();if(e==="SCRIPT"&&d){f.text=g;return f}if(b||a){if(e in Element._insertionTranslations.tags){while(f.firstChild){f.removeChild(f.firstChild)}Element._getContentFromAnonymousElement(e,g.stripScripts()).each(function(h){f.appendChild(h)})}else{f.innerHTML=g.stripScripts()}}else{f.innerHTML=g.stripScripts()}g.evalScripts.bind(g).defer();return f}return c})(),replace:function(b,c){b=$(b);if(c&&c.toElement){c=c.toElement()}else{if(!Object.isElement(c)){c=Object.toHTML(c);var a=b.ownerDocument.createRange();a.selectNode(b);c.evalScripts.bind(c).defer();c=a.createContextualFragment(c.stripScripts())}}b.parentNode.replaceChild(c,b);return b},insert:function(c,e){c=$(c);if(Object.isString(e)||Object.isNumber(e)||Object.isElement(e)||(e&&(e.toElement||e.toHTML))){e={bottom:e}}var d,f,b,g;for(var a in e){d=e[a];a=a.toLowerCase();f=Element._insertionTranslations[a];if(d&&d.toElement){d=d.toElement()}if(Object.isElement(d)){f(c,d);continue}d=Object.toHTML(d);b=((a=="before"||a=="after")?c.parentNode:c).tagName.toUpperCase();g=Element._getContentFromAnonymousElement(b,d.stripScripts());if(a=="top"||a=="after"){g.reverse()}g.each(f.curry(c));d.evalScripts.bind(d).defer()}return c},wrap:function(b,c,a){b=$(b);if(Object.isElement(c)){$(c).writeAttribute(a||{})}else{if(Object.isString(c)){c=new Element(c,a)}else{c=new Element("div",c)}}if(b.parentNode){b.parentNode.replaceChild(c,b)}c.appendChild(b);return c},inspect:function(b){b=$(b);var a="<"+b.tagName.toLowerCase();$H({id:"id",className:"class"}).each(function(f){var e=f.first(),c=f.last();var d=(b[e]||"").toString();if(d){a+=" "+c+"="+d.inspect(true)}});return a+">"},recursivelyCollect:function(a,c){a=$(a);var b=[];while(a=a[c]){if(a.nodeType==1){b.push(Element.extend(a))}}return b},ancestors:function(a){return Element.recursivelyCollect(a,"parentNode")},descendants:function(a){return Element.select(a,"*")},firstDescendant:function(a){a=$(a).firstChild;while(a&&a.nodeType!=1){a=a.nextSibling}return $(a)},immediateDescendants:function(a){if(!(a=$(a).firstChild)){return[]}while(a&&a.nodeType!=1){a=a.nextSibling}if(a){return[a].concat($(a).nextSiblings())}return[]},previousSiblings:function(a){return Element.recursivelyCollect(a,"previousSibling")},nextSiblings:function(a){return Element.recursivelyCollect(a,"nextSibling")},siblings:function(a){a=$(a);return Element.previousSiblings(a).reverse().concat(Element.nextSiblings(a))},match:function(b,a){if(Object.isString(a)){a=new Selector(a)}return a.match($(b))},up:function(b,d,a){b=$(b);if(arguments.length==1){return $(b.parentNode)}var c=Element.ancestors(b);return Object.isNumber(d)?c[d]:Selector.findElement(c,d,a)},down:function(b,c,a){b=$(b);if(arguments.length==1){return Element.firstDescendant(b)}return Object.isNumber(c)?Element.descendants(b)[c]:Element.select(b,c)[a||0]},previous:function(b,d,a){b=$(b);if(arguments.length==1){return $(Selector.handlers.previousElementSibling(b))}var c=Element.previousSiblings(b);return Object.isNumber(d)?c[d]:Selector.findElement(c,d,a)},next:function(c,d,b){c=$(c);if(arguments.length==1){return $(Selector.handlers.nextElementSibling(c))}var a=Element.nextSiblings(c);return Object.isNumber(d)?a[d]:Selector.findElement(a,d,b)},select:function(b){var a=Array.prototype.slice.call(arguments,1);return Selector.findChildElements(b,a)},adjacent:function(b){var a=Array.prototype.slice.call(arguments,1);return Selector.findChildElements(b.parentNode,a).without(b)},identify:function(a){a=$(a);var b=Element.readAttribute(a,"id");if(b){return b}do{b="anonymous_element_"+Element.idCounter++}while($(b));Element.writeAttribute(a,"id",b);return b},readAttribute:function(c,a){c=$(c);if(Prototype.Browser.IE){var b=Element._attributeTranslations.read;if(b.values[a]){return b.values[a](c,a)}if(b.names[a]){a=b.names[a]}if(a.include(":")){return(!c.attributes||!c.attributes[a])?null:c.attributes[a].value}}return c.getAttribute(a)},writeAttribute:function(e,c,f){e=$(e);var b={},d=Element._attributeTranslations.write;if(typeof c=="object"){b=c}else{b[c]=Object.isUndefined(f)?true:f}for(var a in b){c=d.names[a]||a;f=b[a];if(d.values[a]){c=d.values[a](e,f)}if(f===false||f===null){e.removeAttribute(c)}else{if(f===true){e.setAttribute(c,c)}else{e.setAttribute(c,f)}}}return e},getHeight:function(a){return Element.getDimensions(a).height},getWidth:function(a){return Element.getDimensions(a).width},classNames:function(a){return new Element.ClassNames(a)},hasClassName:function(a,b){if(!(a=$(a))){return}var c=a.className;return(c.length>0&&(c==b||new RegExp("(^|\\s)"+b+"(\\s|$)").test(c)))},addClassName:function(a,b){if(!(a=$(a))){return}if(!Element.hasClassName(a,b)){a.className+=(a.className?" ":"")+b}return a},removeClassName:function(a,b){if(!(a=$(a))){return}a.className=a.className.replace(new RegExp("(^|\\s+)"+b+"(\\s+|$)")," ").strip();return a},toggleClassName:function(a,b){if(!(a=$(a))){return}return Element[Element.hasClassName(a,b)?"removeClassName":"addClassName"](a,b)},cleanWhitespace:function(b){b=$(b);var c=b.firstChild;while(c){var a=c.nextSibling;if(c.nodeType==3&&!/\S/.test(c.nodeValue)){b.removeChild(c)}c=a}return b},empty:function(a){return $(a).innerHTML.blank()},descendantOf:function(b,a){b=$(b),a=$(a);if(b.compareDocumentPosition){return(b.compareDocumentPosition(a)&8)===8}if(a.contains){return a.contains(b)&&a!==b}while(b=b.parentNode){if(b==a){return true}}return false},scrollTo:function(a){a=$(a);var b=Element.cumulativeOffset(a);window.scrollTo(b[0],b[1]);return a},getStyle:function(b,c){b=$(b);c=c=="float"?"cssFloat":c.camelize();var d=b.style[c];if(!d||d=="auto"){var a=document.defaultView.getComputedStyle(b,null);d=a?a[c]:null}if(c=="opacity"){return d?parseFloat(d):1}return d=="auto"?null:d},getOpacity:function(a){return $(a).getStyle("opacity")},setStyle:function(b,c){b=$(b);var e=b.style,a;if(Object.isString(c)){b.style.cssText+=";"+c;return c.include("opacity")?b.setOpacity(c.match(/opacity:\s*(\d?\.?\d*)/)[1]):b}for(var d in c){if(d=="opacity"){b.setOpacity(c[d])}else{e[(d=="float"||d=="cssFloat")?(Object.isUndefined(e.styleFloat)?"cssFloat":"styleFloat"):d]=c[d]}}return b},setOpacity:function(a,b){a=$(a);a.style.opacity=(b==1||b==="")?"":(b<0.00001)?0:b;return a},getDimensions:function(c){c=$(c);var g=Element.getStyle(c,"display");if(g!="none"&&g!=null){return{width:c.offsetWidth,height:c.offsetHeight}}var b=c.style;var f=b.visibility;var d=b.position;var a=b.display;b.visibility="hidden";if(d!="fixed"){b.position="absolute"}b.display="block";var h=c.clientWidth;var e=c.clientHeight;b.display=a;b.position=d;b.visibility=f;return{width:h,height:e}},makePositioned:function(a){a=$(a);var b=Element.getStyle(a,"position");if(b=="static"||!b){a._madePositioned=true;a.style.position="relative";if(Prototype.Browser.Opera){a.style.top=0;a.style.left=0}}return a},undoPositioned:function(a){a=$(a);if(a._madePositioned){a._madePositioned=undefined;a.style.position=a.style.top=a.style.left=a.style.bottom=a.style.right=""}return a},makeClipping:function(a){a=$(a);if(a._overflow){return a}a._overflow=Element.getStyle(a,"overflow")||"auto";if(a._overflow!=="hidden"){a.style.overflow="hidden"}return a},undoClipping:function(a){a=$(a);if(!a._overflow){return a}a.style.overflow=a._overflow=="auto"?"":a._overflow;a._overflow=null;return a},cumulativeOffset:function(b){var a=0,c=0;do{a+=b.offsetTop||0;c+=b.offsetLeft||0;b=b.offsetParent}while(b);return Element._returnOffset(c,a)},positionedOffset:function(b){var a=0,d=0;do{a+=b.offsetTop||0;d+=b.offsetLeft||0;b=b.offsetParent;if(b){if(b.tagName.toUpperCase()=="BODY"){break}var c=Element.getStyle(b,"position");if(c!=="static"){break}}}while(b);return Element._returnOffset(d,a)},absolutize:function(b){b=$(b);if(Element.getStyle(b,"position")=="absolute"){return b}var d=Element.positionedOffset(b);var f=d[1];var e=d[0];var c=b.clientWidth;var a=b.clientHeight;b._originalLeft=e-parseFloat(b.style.left||0);b._originalTop=f-parseFloat(b.style.top||0);b._originalWidth=b.style.width;b._originalHeight=b.style.height;b.style.position="absolute";b.style.top=f+"px";b.style.left=e+"px";b.style.width=c+"px";b.style.height=a+"px";return b},relativize:function(a){a=$(a);if(Element.getStyle(a,"position")=="relative"){return a}a.style.position="relative";var c=parseFloat(a.style.top||0)-(a._originalTop||0);var b=parseFloat(a.style.left||0)-(a._originalLeft||0);a.style.top=c+"px";a.style.left=b+"px";a.style.height=a._originalHeight;a.style.width=a._originalWidth;return a},cumulativeScrollOffset:function(b){var a=0,c=0;do{a+=b.scrollTop||0;c+=b.scrollLeft||0;b=b.parentNode}while(b);return Element._returnOffset(c,a)},getOffsetParent:function(a){if(a.offsetParent){return $(a.offsetParent)}if(a==document.body){return $(a)}while((a=a.parentNode)&&a!=document.body){if(Element.getStyle(a,"position")!="static"){return $(a)}}return $(document.body)},viewportOffset:function(d){var a=0,c=0;var b=d;do{a+=b.offsetTop||0;c+=b.offsetLeft||0;if(b.offsetParent==document.body&&Element.getStyle(b,"position")=="absolute"){break}}while(b=b.offsetParent);b=d;do{if(!Prototype.Browser.Opera||(b.tagName&&(b.tagName.toUpperCase()=="BODY"))){a-=b.scrollTop||0;c-=b.scrollLeft||0}}while(b=b.parentNode);return Element._returnOffset(c,a)},clonePosition:function(b,d){var a=Object.extend({setLeft:true,setTop:true,setWidth:true,setHeight:true,offsetTop:0,offsetLeft:0},arguments[2]||{});d=$(d);var e=Element.viewportOffset(d);b=$(b);var f=[0,0];var c=null;if(Element.getStyle(b,"position")=="absolute"){c=Element.getOffsetParent(b);f=Element.viewportOffset(c)}if(c==document.body){f[0]-=document.body.offsetLeft;f[1]-=document.body.offsetTop}if(a.setLeft){b.style.left=(e[0]-f[0]+a.offsetLeft)+"px"}if(a.setTop){b.style.top=(e[1]-f[1]+a.offsetTop)+"px"}if(a.setWidth){b.style.width=d.offsetWidth+"px"}if(a.setHeight){b.style.height=d.offsetHeight+"px"}return b}};Object.extend(Element.Methods,{getElementsBySelector:Element.Methods.select,childElements:Element.Methods.immediateDescendants});Element._attributeTranslations={write:{names:{className:"class",htmlFor:"for"},values:{}}};if(Prototype.Browser.Opera){Element.Methods.getStyle=Element.Methods.getStyle.wrap(function(d,b,c){switch(c){case"left":case"top":case"right":case"bottom":if(d(b,"position")==="static"){return null}case"height":case"width":if(!Element.visible(b)){return null}var e=parseInt(d(b,c),10);if(e!==b["offset"+c.capitalize()]){return e+"px"}var a;if(c==="height"){a=["border-top-width","padding-top","padding-bottom","border-bottom-width"]}else{a=["border-left-width","padding-left","padding-right","border-right-width"]}return a.inject(e,function(f,g){var h=d(b,g);return h===null?f:f-parseInt(h,10)})+"px";default:return d(b,c)}});Element.Methods.readAttribute=Element.Methods.readAttribute.wrap(function(c,a,b){if(b==="title"){return a.title}return c(a,b)})}else{if(Prototype.Browser.IE){Element.Methods.getOffsetParent=Element.Methods.getOffsetParent.wrap(function(c,b){b=$(b);try{b.offsetParent}catch(f){return $(document.body)}var a=b.getStyle("position");if(a!=="static"){return c(b)}b.setStyle({position:"relative"});var d=c(b);b.setStyle({position:a});return d});$w("positionedOffset viewportOffset").each(function(a){Element.Methods[a]=Element.Methods[a].wrap(function(f,c){c=$(c);try{c.offsetParent}catch(h){return Element._returnOffset(0,0)}var b=c.getStyle("position");if(b!=="static"){return f(c)}var d=c.getOffsetParent();if(d&&d.getStyle("position")==="fixed"){d.setStyle({zoom:1})}c.setStyle({position:"relative"});var g=f(c);c.setStyle({position:b});return g})});Element.Methods.cumulativeOffset=Element.Methods.cumulativeOffset.wrap(function(b,a){try{a.offsetParent}catch(c){return Element._returnOffset(0,0)}return b(a)});Element.Methods.getStyle=function(a,b){a=$(a);b=(b=="float"||b=="cssFloat")?"styleFloat":b.camelize();var c=a.style[b];if(!c&&a.currentStyle){c=a.currentStyle[b]}if(b=="opacity"){if(c=(a.getStyle("filter")||"").match(/alpha\(opacity=(.*)\)/)){if(c[1]){return parseFloat(c[1])/100}}return 1}if(c=="auto"){if((b=="width"||b=="height")&&(a.getStyle("display")!="none")){return a["offset"+b.capitalize()]+"px"}return null}return c};Element.Methods.setOpacity=function(b,e){function f(g){return g.replace(/alpha\([^\)]*\)/gi,"")}b=$(b);var a=b.currentStyle;if((a&&!a.hasLayout)||(!a&&b.style.zoom=="normal")){b.style.zoom=1}var d=b.getStyle("filter"),c=b.style;if(e==1||e===""){(d=f(d))?c.filter=d:c.removeAttribute("filter");return b}else{if(e<0.00001){e=0}}c.filter=f(d)+"alpha(opacity="+(e*100)+")";return b};Element._attributeTranslations=(function(){var b="className";var a="for";var c=document.createElement("div");c.setAttribute(b,"x");if(c.className!=="x"){c.setAttribute("class","x");if(c.className==="x"){b="class"}}c=null;c=document.createElement("label");c.setAttribute(a,"x");if(c.htmlFor!=="x"){c.setAttribute("htmlFor","x");if(c.htmlFor==="x"){a="htmlFor"}}c=null;return{read:{names:{"class":b,className:b,"for":a,htmlFor:a},values:{_getAttr:function(d,e){return d.getAttribute(e)},_getAttr2:function(d,e){return d.getAttribute(e,2)},_getAttrNode:function(d,f){var e=d.getAttributeNode(f);return e?e.value:""},_getEv:(function(){var d=document.createElement("div");d.onclick=Prototype.emptyFunction;var g=d.getAttribute("onclick");var e;if(String(g).indexOf("{")>-1){e=function(f,h){h=f.getAttribute(h);if(!h){return null}h=h.toString();h=h.split("{")[1];h=h.split("}")[0];return h.strip()}}else{if(g===""){e=function(f,h){h=f.getAttribute(h);if(!h){return null}return h.strip()}}}d=null;return e})(),_flag:function(d,e){return $(d).hasAttribute(e)?e:null},style:function(d){return d.style.cssText.toLowerCase()},title:function(d){return d.title}}}}})();Element._attributeTranslations.write={names:Object.extend({cellpadding:"cellPadding",cellspacing:"cellSpacing"},Element._attributeTranslations.read.names),values:{checked:function(a,b){a.checked=!!b},style:function(a,b){a.style.cssText=b?b:""}}};Element._attributeTranslations.has={};$w("colSpan rowSpan vAlign dateTime accessKey tabIndex encType maxLength readOnly longDesc frameBorder").each(function(a){Element._attributeTranslations.write.names[a.toLowerCase()]=a;Element._attributeTranslations.has[a.toLowerCase()]=a});(function(a){Object.extend(a,{href:a._getAttr2,src:a._getAttr2,type:a._getAttr,action:a._getAttrNode,disabled:a._flag,checked:a._flag,readonly:a._flag,multiple:a._flag,onload:a._getEv,onunload:a._getEv,onclick:a._getEv,ondblclick:a._getEv,onmousedown:a._getEv,onmouseup:a._getEv,onmouseover:a._getEv,onmousemove:a._getEv,onmouseout:a._getEv,onfocus:a._getEv,onblur:a._getEv,onkeypress:a._getEv,onkeydown:a._getEv,onkeyup:a._getEv,onsubmit:a._getEv,onreset:a._getEv,onselect:a._getEv,onchange:a._getEv})})(Element._attributeTranslations.read.values);if(Prototype.BrowserFeatures.ElementExtensions){(function(){function a(e){var b=e.getElementsByTagName("*"),d=[];for(var c=0,f;f=b[c];c++){if(f.tagName!=="!"){d.push(f)}}return d}Element.Methods.down=function(c,d,b){c=$(c);if(arguments.length==1){return c.firstDescendant()}return Object.isNumber(d)?a(c)[d]:Element.select(c,d)[b||0]}})()}}else{if(Prototype.Browser.Gecko&&/rv:1\.8\.0/.test(navigator.userAgent)){Element.Methods.setOpacity=function(a,b){a=$(a);a.style.opacity=(b==1)?0.999999:(b==="")?"":(b<0.00001)?0:b;return a}}else{if(Prototype.Browser.WebKit){Element.Methods.setOpacity=function(a,b){a=$(a);a.style.opacity=(b==1||b==="")?"":(b<0.00001)?0:b;if(b==1){if(a.tagName.toUpperCase()=="IMG"&&a.width){a.width++;a.width--}else{try{var d=document.createTextNode(" ");a.appendChild(d);a.removeChild(d)}catch(c){}}}return a};Element.Methods.cumulativeOffset=function(b){var a=0,c=0;do{a+=b.offsetTop||0;c+=b.offsetLeft||0;if(b.offsetParent==document.body){if(Element.getStyle(b,"position")=="absolute"){break}}b=b.offsetParent}while(b);return Element._returnOffset(c,a)}}}}}if("outerHTML" in document.documentElement){Element.Methods.replace=function(c,e){c=$(c);if(e&&e.toElement){e=e.toElement()}if(Object.isElement(e)){c.parentNode.replaceChild(e,c);return c}e=Object.toHTML(e);var d=c.parentNode,b=d.tagName.toUpperCase();if(Element._insertionTranslations.tags[b]){var f=c.next();var a=Element._getContentFromAnonymousElement(b,e.stripScripts());d.removeChild(c);if(f){a.each(function(g){d.insertBefore(g,f)})}else{a.each(function(g){d.appendChild(g)})}}else{c.outerHTML=e.stripScripts()}e.evalScripts.bind(e).defer();return c}}Element._returnOffset=function(b,c){var a=[b,c];a.left=b;a.top=c;return a};Element._getContentFromAnonymousElement=function(c,b){var d=new Element("div"),a=Element._insertionTranslations.tags[c];if(a){d.innerHTML=a[0]+b+a[1];a[2].times(function(){d=d.firstChild})}else{d.innerHTML=b}return $A(d.childNodes)};Element._insertionTranslations={before:function(a,b){a.parentNode.insertBefore(b,a)},top:function(a,b){a.insertBefore(b,a.firstChild)},bottom:function(a,b){a.appendChild(b)},after:function(a,b){a.parentNode.insertBefore(b,a.nextSibling)},tags:{TABLE:["
test
","
",1],TBODY:["","
",2],TR:["","
",3],TD:["
","
",4],SELECT:["",1]}};(function(){var a=Element._insertionTranslations.tags;Object.extend(a,{THEAD:a.TBODY,TFOOT:a.TBODY,TH:a.TD})})();Element.Methods.Simulated={hasAttribute:function(a,c){c=Element._attributeTranslations.has[c]||c;var b=$(a).getAttributeNode(c);return !!(b&&b.specified)}};Element.Methods.ByTag={};Object.extend(Element,Element.Methods);(function(a){if(!Prototype.BrowserFeatures.ElementExtensions&&a.__proto__){window.HTMLElement={};window.HTMLElement.prototype=a.__proto__;Prototype.BrowserFeatures.ElementExtensions=true}a=null})(document.createElement("div"));Element.extend=(function(){function c(g){if(typeof window.Element!="undefined"){var i=window.Element.prototype;if(i){var k="_"+(Math.random()+"").slice(2);var h=document.createElement(g);i[k]="x";var j=(h[k]!=="x");delete i[k];h=null;return j}}return false}function b(h,g){for(var j in g){var i=g[j];if(Object.isFunction(i)&&!(j in h)){h[j]=i.methodize()}}}var d=c("object");if(Prototype.BrowserFeatures.SpecificElementExtensions){if(d){return function(h){if(h&&typeof h._extendedByPrototype=="undefined"){var g=h.tagName;if(g&&(/^(?:object|applet|embed)$/i.test(g))){b(h,Element.Methods);b(h,Element.Methods.Simulated);b(h,Element.Methods.ByTag[g.toUpperCase()])}}return h}}return Prototype.K}var a={},e=Element.Methods.ByTag;var f=Object.extend(function(i){if(!i||typeof i._extendedByPrototype!="undefined"||i.nodeType!=1||i==window){return i}var g=Object.clone(a),h=i.tagName.toUpperCase();if(e[h]){Object.extend(g,e[h])}b(i,g);i._extendedByPrototype=Prototype.emptyFunction;return i},{refresh:function(){if(!Prototype.BrowserFeatures.ElementExtensions){Object.extend(a,Element.Methods);Object.extend(a,Element.Methods.Simulated)}}});f.refresh();return f})();Element.hasAttribute=function(a,b){if(a.hasAttribute){return a.hasAttribute(b)}return Element.Methods.Simulated.hasAttribute(a,b)};Element.addMethods=function(c){var i=Prototype.BrowserFeatures,d=Element.Methods.ByTag;if(!c){Object.extend(Form,Form.Methods);Object.extend(Form.Element,Form.Element.Methods);Object.extend(Element.Methods.ByTag,{FORM:Object.clone(Form.Methods),INPUT:Object.clone(Form.Element.Methods),SELECT:Object.clone(Form.Element.Methods),TEXTAREA:Object.clone(Form.Element.Methods)})}if(arguments.length==2){var b=c;c=arguments[1]}if(!b){Object.extend(Element.Methods,c||{})}else{if(Object.isArray(b)){b.each(g)}else{g(b)}}function g(k){k=k.toUpperCase();if(!Element.Methods.ByTag[k]){Element.Methods.ByTag[k]={}}Object.extend(Element.Methods.ByTag[k],c)}function a(m,l,k){k=k||false;for(var o in m){var n=m[o];if(!Object.isFunction(n)){continue}if(!k||!(o in l)){l[o]=n.methodize()}}}function e(n){var k;var m={OPTGROUP:"OptGroup",TEXTAREA:"TextArea",P:"Paragraph",FIELDSET:"FieldSet",UL:"UList",OL:"OList",DL:"DList",DIR:"Directory",H1:"Heading",H2:"Heading",H3:"Heading",H4:"Heading",H5:"Heading",H6:"Heading",Q:"Quote",INS:"Mod",DEL:"Mod",A:"Anchor",IMG:"Image",CAPTION:"TableCaption",COL:"TableCol",COLGROUP:"TableCol",THEAD:"TableSection",TFOOT:"TableSection",TBODY:"TableSection",TR:"TableRow",TH:"TableCell",TD:"TableCell",FRAMESET:"FrameSet",IFRAME:"IFrame"};if(m[n]){k="HTML"+m[n]+"Element"}if(window[k]){return window[k]}k="HTML"+n+"Element";if(window[k]){return window[k]}k="HTML"+n.capitalize()+"Element";if(window[k]){return window[k]}var l=document.createElement(n);var o=l.__proto__||l.constructor.prototype;l=null;return o}var h=window.HTMLElement?HTMLElement.prototype:Element.prototype;if(i.ElementExtensions){a(Element.Methods,h);a(Element.Methods.Simulated,h,true)}if(i.SpecificElementExtensions){for(var j in Element.Methods.ByTag){var f=e(j);if(Object.isUndefined(f)){continue}a(d[j],f.prototype)}}Object.extend(Element,Element.Methods);delete Element.ByTag;if(Element.extend.refresh){Element.extend.refresh()}Element.cache={}};document.viewport={getDimensions:function(){return{width:this.getWidth(),height:this.getHeight()}},getScrollOffsets:function(){return Element._returnOffset(window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft,window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop)}};(function(b){var g=Prototype.Browser,e=document,c,d={};function a(){if(g.WebKit&&!e.evaluate){return document}if(g.Opera&&window.parseFloat(window.opera.version())<9.5){return document.body}return document.documentElement}function f(h){if(!c){c=a()}d[h]="client"+h;b["get"+h]=function(){return c[d[h]]};return b["get"+h]()}b.getWidth=f.curry("Width");b.getHeight=f.curry("Height")})(document.viewport);Element.Storage={UID:1};Element.addMethods({getStorage:function(b){if(!(b=$(b))){return}var a;if(b===window){a=0}else{if(typeof b._prototypeUID==="undefined"){b._prototypeUID=[Element.Storage.UID++]}a=b._prototypeUID[0]}if(!Element.Storage[a]){Element.Storage[a]=$H()}return Element.Storage[a]},store:function(b,a,c){if(!(b=$(b))){return}if(arguments.length===2){Element.getStorage(b).update(a)}else{Element.getStorage(b).set(a,c)}return b},retrieve:function(c,b,a){if(!(c=$(c))){return}var e=Element.getStorage(c),d=e.get(b);if(Object.isUndefined(d)){e.set(b,a);d=a}return d},clone:function(c,a){if(!(c=$(c))){return}var e=c.cloneNode(a);e._prototypeUID=void 0;if(a){var d=Element.select(e,"*"),b=d.length;while(b--){d[b]._prototypeUID=void 0}}return Element.extend(e)}});var Selector=Class.create({initialize:function(a){this.expression=a.strip();if(this.shouldUseSelectorsAPI()){this.mode="selectorsAPI"}else{if(this.shouldUseXPath()){this.mode="xpath";this.compileXPathMatcher()}else{this.mode="normal";this.compileMatcher()}}},shouldUseXPath:(function(){var a=(function(){var e=false;if(document.evaluate&&window.XPathResult){var d=document.createElement("div");d.innerHTML="
";var c=".//*[local-name()='ul' or local-name()='UL']//*[local-name()='li' or local-name()='LI']";var b=document.evaluate(c,d,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);e=(b.snapshotLength!==2);d=null}return e})();return function(){if(!Prototype.BrowserFeatures.XPath){return false}var b=this.expression;if(Prototype.Browser.WebKit&&(b.include("-of-type")||b.include(":empty"))){return false}if((/(\[[\w-]*?:|:checked)/).test(b)){return false}if(a){return false}return true}})(),shouldUseSelectorsAPI:function(){if(!Prototype.BrowserFeatures.SelectorsAPI){return false}if(Selector.CASE_INSENSITIVE_CLASS_NAMES){return false}if(!Selector._div){Selector._div=new Element("div")}try{Selector._div.querySelector(this.expression)}catch(a){return false}return true},compileMatcher:function(){var e=this.expression,ps=Selector.patterns,h=Selector.handlers,c=Selector.criteria,le,p,m,len=ps.length,name;if(Selector._cache[e]){this.matcher=Selector._cache[e];return}this.matcher=["this.matcher = function(root) {","var r = root, h = Selector.handlers, c = false, n;"];while(e&&le!=e&&(/\S/).test(e)){le=e;for(var i=0;i"}});if(Prototype.BrowserFeatures.SelectorsAPI&&document.compatMode==="BackCompat"){Selector.CASE_INSENSITIVE_CLASS_NAMES=(function(){var c=document.createElement("div"),a=document.createElement("span");c.id="prototype_test_id";a.className="Test";c.appendChild(a);var b=(c.querySelector("#prototype_test_id .test")!==null);c=a=null;return b})()}Object.extend(Selector,{_cache:{},xpath:{descendant:"//*",child:"/*",adjacent:"/following-sibling::*[1]",laterSibling:"/following-sibling::*",tagName:function(a){if(a[1]=="*"){return""}return"[local-name()='"+a[1].toLowerCase()+"' or local-name()='"+a[1].toUpperCase()+"']"},className:"[contains(concat(' ', @class, ' '), ' #{1} ')]",id:"[@id='#{1}']",attrPresence:function(a){a[1]=a[1].toLowerCase();return new Template("[@#{1}]").evaluate(a)},attr:function(a){a[1]=a[1].toLowerCase();a[3]=a[5]||a[6];return new Template(Selector.xpath.operators[a[2]]).evaluate(a)},pseudo:function(a){var b=Selector.xpath.pseudos[a[1]];if(!b){return""}if(Object.isFunction(b)){return b(a)}return new Template(Selector.xpath.pseudos[a[1]]).evaluate(a)},operators:{"=":"[@#{1}='#{3}']","!=":"[@#{1}!='#{3}']","^=":"[starts-with(@#{1}, '#{3}')]","$=":"[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']","*=":"[contains(@#{1}, '#{3}')]","~=":"[contains(concat(' ', @#{1}, ' '), ' #{3} ')]","|=":"[contains(concat('-', @#{1}, '-'), '-#{3}-')]"},pseudos:{"first-child":"[not(preceding-sibling::*)]","last-child":"[not(following-sibling::*)]","only-child":"[not(preceding-sibling::* or following-sibling::*)]",empty:"[count(*) = 0 and (count(text()) = 0)]",checked:"[@checked]",disabled:"[(@disabled) and (@type!='hidden')]",enabled:"[not(@disabled) and (@type!='hidden')]",not:function(f){var j=f[6],c=Selector.patterns,k=Selector.xpath,a,l,h=c.length,b;var d=[];while(j&&a!=j&&(/\S/).test(j)){a=j;for(var g=0;g= 0)]";return new Template(d).evaluate({fragment:g,a:f,b:c})}}}},criteria:{tagName:'n = h.tagName(n, r, "#{1}", c); c = false;',className:'n = h.className(n, r, "#{1}", c); c = false;',id:'n = h.id(n, r, "#{1}", c); c = false;',attrPresence:'n = h.attrPresence(n, r, "#{1}", c); c = false;',attr:function(a){a[3]=(a[5]||a[6]);return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(a)},pseudo:function(a){if(a[6]){a[6]=a[6].replace(/"/g,'\\"')}return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(a)},descendant:'c = "descendant";',child:'c = "child";',adjacent:'c = "adjacent";',laterSibling:'c = "laterSibling";'},patterns:[{name:"laterSibling",re:/^\s*~\s*/},{name:"child",re:/^\s*>\s*/},{name:"adjacent",re:/^\s*\+\s*/},{name:"descendant",re:/^\s/},{name:"tagName",re:/^\s*(\*|[\w\-]+)(\b|$)?/},{name:"id",re:/^#([\w\-\*]+)(\b|$)/},{name:"className",re:/^\.([\w\-\*]+)(\b|$)/},{name:"pseudo",re:/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/},{name:"attrPresence",re:/^\[((?:[\w-]+:)?[\w-]+)\]/},{name:"attr",re:/\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/}],assertions:{tagName:function(a,b){return b[1].toUpperCase()==a.tagName.toUpperCase()},className:function(a,b){return Element.hasClassName(a,b[1])},id:function(a,b){return a.id===b[1]},attrPresence:function(a,b){return Element.hasAttribute(a,b[1])},attr:function(b,c){var a=Element.readAttribute(b,c[1]);return a&&Selector.operators[c[2]](a,c[5]||c[6])}},handlers:{concat:function(d,c){for(var e=0,f;f=c[e];e++){d.push(f)}return d},mark:function(a){var d=Prototype.emptyFunction;for(var b=0,c;c=a[b];b++){c._countedByPrototype=d}return a},unmark:(function(){var a=(function(){var b=document.createElement("div"),e=false,d="_countedByPrototype",c="x";b[d]=c;e=(b.getAttribute(d)===c);b=null;return e})();return a?function(b){for(var c=0,d;d=b[c];c++){d.removeAttribute("_countedByPrototype")}return b}:function(b){for(var c=0,d;d=b[c];c++){d._countedByPrototype=void 0}return b}})(),index:function(a,d,g){a._countedByPrototype=Prototype.emptyFunction;if(d){for(var b=a.childNodes,e=b.length-1,c=1;e>=0;e--){var f=b[e];if(f.nodeType==1&&(!g||f._countedByPrototype)){f.nodeIndex=c++}}}else{for(var e=0,c=1,b=a.childNodes;f=b[e];e++){if(f.nodeType==1&&(!g||f._countedByPrototype)){f.nodeIndex=c++}}}},unique:function(b){if(b.length==0){return b}var d=[],e;for(var c=0,a=b.length;c0?[c]:[]}return $R(1,e).inject([],function(a,b){if(0==(b-c)%d&&(b-c)/d>=0){a.push(b)}return a})},nth:function(c,s,u,r,e){if(c.length==0){return[]}if(s=="even"){s="2n+0"}if(s=="odd"){s="2n+1"}var q=Selector.handlers,p=[],d=[],g;q.mark(c);for(var o=0,f;f=c[o];o++){if(!f.parentNode._countedByPrototype){q.index(f.parentNode,r,e);d.push(f.parentNode)}}if(s.match(/^\d+$/)){s=Number(s);for(var o=0,f;f=c[o];o++){if(f.nodeIndex==s){p.push(f)}}}else{if(g=s.match(/^(-?\d*)?n(([+-])(\d+))?/)){if(g[1]=="-"){g[1]=-1}var v=g[1]?Number(g[1]):1;var t=g[2]?Number(g[2]):0;var w=Selector.pseudos.getIndices(v,t,c.length);for(var o=0,f,k=w.length;f=c[o];o++){for(var n=0;n+()\s-]+|\*|\[.*?\])+)\s*(,|$)/,function(c){a.push(c[1].strip())});return a},matchElements:function(f,g){var e=$$(g),d=Selector.handlers;d.mark(e);for(var c=0,b=[],a;a=f[c];c++){if(a._countedByPrototype){b.push(a)}}d.unmark(e);return b},findElement:function(b,c,a){if(Object.isNumber(c)){a=c;c=false}return Selector.matchElements(b,c||"*")[a||0]},findChildElements:function(e,g){g=Selector.split(g.join(","));var d=[],f=Selector.handlers;for(var c=0,b=g.length,a;c1)?f.unique(d):d}});if(Prototype.Browser.IE){Object.extend(Selector.handlers,{concat:function(d,c){for(var e=0,f;f=c[e];e++){if(f.tagName!=="!"){d.push(f)}}return d}})}function $$(){return Selector.findChildElements(document,$A(arguments))}var Form={reset:function(a){a=$(a);a.reset();return a},serializeElements:function(g,b){if(typeof b!="object"){b={hash:!!b}}else{if(Object.isUndefined(b.hash)){b.hash=true}}var c,f,a=false,e=b.submit;var d=g.inject({},function(h,i){if(!i.disabled&&i.name){c=i.name;f=$(i).getValue();if(f!=null&&i.type!="file"&&(i.type!="submit"||(!a&&e!==false&&(!e||c==e)&&(a=true)))){if(c in h){if(!Object.isArray(h[c])){h[c]=[h[c]]}h[c].push(f)}else{h[c]=f}}}return h});return b.hash?d:Object.toQueryString(d)}};Form.Methods={serialize:function(b,a){return Form.serializeElements(Form.getElements(b),a)},getElements:function(e){var f=$(e).getElementsByTagName("*"),d,a=[],c=Form.Element.Serializers;for(var b=0;d=f[b];b++){a.push(d)}return a.inject([],function(g,h){if(c[h.tagName.toLowerCase()]){g.push(Element.extend(h))}return g})},getInputs:function(g,c,d){g=$(g);var a=g.getElementsByTagName("input");if(!c&&!d){return $A(a).map(Element.extend)}for(var e=0,h=[],f=a.length;e=0}).sortBy(function(d){return d.tabIndex}).first();return a?a:c.find(function(d){return/^(?:input|select|textarea)$/i.test(d.tagName)})},focusFirstElement:function(a){a=$(a);a.findFirstElement().activate();return a},request:function(b,a){b=$(b),a=Object.clone(a||{});var d=a.parameters,c=b.readAttribute("action")||"";if(c.blank()){c=window.location.href}a.parameters=b.serialize(true);if(d){if(Object.isString(d)){d=d.toQueryParams()}Object.extend(a.parameters,d)}if(b.hasAttribute("method")&&!a.method){a.method=b.method}return new Ajax.Request(c,a)}};Form.Element={focus:function(a){$(a).focus();return a},select:function(a){$(a).select();return a}};Form.Element.Methods={serialize:function(a){a=$(a);if(!a.disabled&&a.name){var b=a.getValue();if(b!=undefined){var c={};c[a.name]=b;return Object.toQueryString(c)}}return""},getValue:function(a){a=$(a);var b=a.tagName.toLowerCase();return Form.Element.Serializers[b](a)},setValue:function(a,b){a=$(a);var c=a.tagName.toLowerCase();Form.Element.Serializers[c](a,b);return a},clear:function(a){$(a).value="";return a},present:function(a){return $(a).value!=""},activate:function(a){a=$(a);try{a.focus();if(a.select&&(a.tagName.toLowerCase()!="input"||!(/^(?:button|reset|submit)$/i.test(a.type)))){a.select()}}catch(b){}return a},disable:function(a){a=$(a);a.disabled=true;return a},enable:function(a){a=$(a);a.disabled=false;return a}};var Field=Form.Element;var $F=Form.Element.Methods.getValue;Form.Element.Serializers={input:function(a,b){switch(a.type.toLowerCase()){case"checkbox":case"radio":return Form.Element.Serializers.inputSelector(a,b);default:return Form.Element.Serializers.textarea(a,b)}},inputSelector:function(a,b){if(Object.isUndefined(b)){return a.checked?a.value:null}else{a.checked=!!b}},textarea:function(a,b){if(Object.isUndefined(b)){return a.value}else{a.value=b}},select:function(c,f){if(Object.isUndefined(f)){return this[c.type=="select-one"?"selectOne":"selectMany"](c)}else{var b,d,g=!Object.isArray(f);for(var a=0,e=c.length;a=0?this.optionValue(b.options[a]):null},selectMany:function(d){var a,e=d.length;if(!e){return null}for(var c=0,a=[];c=this.offset[1]&&c=this.offset[0]&&a=this.offset[1]&&this.ycomp=this.offset[0]&&this.xcomp0})._each(a)},set:function(a){this.element.className=a},add:function(a){if(this.include(a)){return}this.set($A(this).concat(a).join(" "))},remove:function(a){if(!this.include(a)){return}this.set($A(this).without(a).join(" "))},toString:function(){return $A(this).join(" ")}};Object.extend(Element.ClassNames.prototype,Enumerable); \ No newline at end of file diff --git "a/sample_for_plotting/\350\257\264\346\230\216.htm" "b/sample_for_plotting/\350\257\264\346\230\216.htm" new file mode 100644 index 0000000..7c9488d --- /dev/null +++ "b/sample_for_plotting/\350\257\264\346\230\216.htm" @@ -0,0 +1,62 @@ + + + + + + +йվվļ˵ + + + + + +
+
+

+

+ + + + + + + + + + +
 йվվļ˵

+   صĸļйվվ(www.chinaz.com) Ǵwww.chinaz.comصģϵǾٱվE-mail: sc@chinaz.com
+
+   ʹǰĶʹñվṩļ
+   1) վ֤ṩԺͰȫԡ
+   2) ʹǰ鶾 (ҲʹԴע)
+   3) ɱվṩijվغıվŲ
+   4) תرվṩԴɾ˵ļ
+   5) վṩijΪѼó漰ֺİȨд֪ͨǡE-mail: sc@chinaz.com + +

   κɵվ̳(chinaz.com)Եõļ֧֣

+

   ϵԱ: sc@chinaz.com
+   Ͷ: ads@chinaz.com   йվվΪйվṩ

+
+   + C H I N A Z . C O M                                            Powered by CHINAZ.STUDIO
+
+
+

+ +

+ + + + \ No newline at end of file diff --git "a/sample_for_plotting/\350\257\264\346\230\216.txt" "b/sample_for_plotting/\350\257\264\346\230\216.txt" new file mode 100644 index 0000000..d6732ad --- /dev/null +++ "b/sample_for_plotting/\350\257\264\346\230\216.txt" @@ -0,0 +1,4 @@ +IE8360FireFoxChromeSafariOperaΡѹ֮. + + +*Ʒɡվزġռתע \ No newline at end of file