summaryrefslogtreecommitdiff
path: root/addons/web_graph/static/lib/flotr2
diff options
context:
space:
mode:
authorBharat R. Devnani (OpenERP) <bde@tinyerp.com>2014-03-04 11:08:49 +0530
committerBharat R. Devnani (OpenERP) <bde@tinyerp.com>2014-03-04 11:08:49 +0530
commit67b68d8e4e7015e368324dd0c02aa29fed71d359 (patch)
treed72e75ef050bd65dcb53d2a27305a0285ca2963b /addons/web_graph/static/lib/flotr2
parent7c1af9ef1441b2097c815758670b70a690598d62 (diff)
parente76c36d704c142fca08bf1297897d4091bf7a4cb (diff)
[MERGE] merged with main web
bzr revid: bde@tinyerp.com-20140304053849-wpvxs1ojl5jyjokt
Diffstat (limited to 'addons/web_graph/static/lib/flotr2')
-rw-r--r--addons/web_graph/static/lib/flotr2/LICENSE19
-rw-r--r--addons/web_graph/static/lib/flotr2/Makefile40
-rw-r--r--addons/web_graph/static/lib/flotr2/README.md89
-rw-r--r--addons/web_graph/static/lib/flotr2/dev/notes.txt86
-rw-r--r--addons/web_graph/static/lib/flotr2/flotr2.examples.min.js2
-rw-r--r--addons/web_graph/static/lib/flotr2/flotr2.examples.types.js1425
-rw-r--r--addons/web_graph/static/lib/flotr2/flotr2.ie.min.js33
-rw-r--r--addons/web_graph/static/lib/flotr2/flotr2.js6865
-rw-r--r--addons/web_graph/static/lib/flotr2/flotr2.min.js27
-rw-r--r--addons/web_graph/static/lib/flotr2/js/Axis.js303
-rw-r--r--addons/web_graph/static/lib/flotr2/js/Color.js163
-rw-r--r--addons/web_graph/static/lib/flotr2/js/DOM.js88
-rw-r--r--addons/web_graph/static/lib/flotr2/js/Date.js207
-rw-r--r--addons/web_graph/static/lib/flotr2/js/DefaultOptions.js98
-rw-r--r--addons/web_graph/static/lib/flotr2/js/EventAdapter.js52
-rw-r--r--addons/web_graph/static/lib/flotr2/js/Flotr.js250
-rw-r--r--addons/web_graph/static/lib/flotr2/js/Graph.js745
-rw-r--r--addons/web_graph/static/lib/flotr2/js/Series.js74
-rw-r--r--addons/web_graph/static/lib/flotr2/js/Text.js88
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/crosshair.js84
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/download.js51
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/grid.js208
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/handles.js199
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/hit.js337
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/labels.js227
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/legend.js179
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/selection.js278
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/spreadsheet.js296
-rw-r--r--addons/web_graph/static/lib/flotr2/js/plugins/titles.js177
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/bars.js274
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/bubbles.js119
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/candles.js127
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/gantt.js229
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/lines.js275
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/markers.js140
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/pie.js210
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/points.js66
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/radar.js60
-rw-r--r--addons/web_graph/static/lib/flotr2/js/types/timeline.js90
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/base64.js113
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/bean-min.js10
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/bean.js501
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/canvas2image.js198
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/canvastext.js429
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/excanvas.js1425
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/imagediff.js343
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/jasmine/MIT.LICENSE20
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine-html.js190
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.css166
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.js2476
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine_favicon.pngbin700 -> 0 bytes
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/prototype.js4320
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/underscore-min.js27
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/underscore.js839
-rw-r--r--addons/web_graph/static/lib/flotr2/lib/yepnope.js1
55 files changed, 0 insertions, 25338 deletions
diff --git a/addons/web_graph/static/lib/flotr2/LICENSE b/addons/web_graph/static/lib/flotr2/LICENSE
deleted file mode 100644
index eeb8ce52b3b..00000000000
--- a/addons/web_graph/static/lib/flotr2/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2012 Carl Sutherland
-
-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.
diff --git a/addons/web_graph/static/lib/flotr2/Makefile b/addons/web_graph/static/lib/flotr2/Makefile
deleted file mode 100644
index 70157b0f3fa..00000000000
--- a/addons/web_graph/static/lib/flotr2/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-all: test flotr2
-
-test:
- cd spec; jasmine-headless-webkit -j jasmine.yml -c
-
-libraries:
- smoosh make/lib.json
- cat ./build/bean.js > build/lib.js
- cat ./build/underscore.js >> build/lib.js
- cat ./build/bean.min.js > build/lib.min.js
- echo ";" >> build/lib.min.js
- cat ./build/underscore.min.js >> build/lib.min.js
- echo ";" >> build/lib.min.js
-
-ie:
- smoosh make/ie.json
-
-flotr2: libraries ie
- smoosh make/flotr2.json
- cat build/lib.js build/flotr2.js > flotr2.js
- cat build/lib.min.js > flotr2.min.js
- cat build/flotr2.min.js >> flotr2.min.js
- echo ';' >> flotr2.min.js
- cp build/ie.min.js flotr2.ie.min.js
-
-flotr2-basic: libraries ie
- smoosh make/basic.json
- cat build/lib.min.js > flotr2-basic.min.js
- cat build/flotr2-basic.min.js >> flotr2-basic.min.js
-
-flotr2-standalone: ie
- smoosh make/flotr2.json
- cat build/flotr2.js > flotr2.js
- cp build/ie.min.js flotr2.ie.min.js
-
-flotr-examples:
- smoosh make/examples.json
- cp build/examples.min.js flotr2.examples.min.js
- cp build/examples-types.js flotr2.examples.types.js
-
diff --git a/addons/web_graph/static/lib/flotr2/README.md b/addons/web_graph/static/lib/flotr2/README.md
deleted file mode 100644
index 46f180c0fc6..00000000000
--- a/addons/web_graph/static/lib/flotr2/README.md
+++ /dev/null
@@ -1,89 +0,0 @@
-Flotr2
-======
-
-The Canvas graphing library.
-
-![Google Groups](http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif)
-
-http://groups.google.com/group/flotr2/
-
-Please fork http://jsfiddle.net/cesutherland/ZFBj5/ with your question or bug reproduction case.
-
-
-API
----
-
-The API consists of a primary draw method which accepts a configuration object, helper methods, and several microlibs.
-
-### Example
-
-```javascript
- var
- // Container div:
- container = document.getElementById("flotr-example-graph"),
- // First data series:
- d1 = [[0, 3], [4, 8], [8, 5], [9, 13]],
- // Second data series:
- d2 = [],
- // A couple flotr configuration options:
- options = {
- xaxis: {
- minorTickFreq: 4
- },
- grid: {
- minorVerticalLines: true
- }
- },
- i, graph;
-
- // Generated second data set:
- for (i = 0; i < 14; i += 0.5) {
- d2.push([i, Math.sin(i)]);
- }
-
- // Draw the graph:
- graph = Flotr.draw(
- container, // Container element
- [ d1, d2 ], // Array of data series
- options // Configuration options
- );
-```
-
-### Microlibs
-
-* [underscore.js](http://documentcloud.github.com/underscore/)
-* [bean.js](https://github.com/fat/bean)
-
-Extending
----------
-
-Flotr may be extended by adding new plugins and graph types.
-
-### Graph Types
-
-Graph types define how a particular chart is rendered. Examples include line, bar, pie.
-
-Existing graph types are found in `js/types/`.
-
-### Plugins
-
-Plugins extend the core of flotr with new functionality. They can add interactions, new decorations, etc. Examples
-include titles, labels and selection.
-
-The plugins included are found in `js/plugins/`.
-
-Development
------------
-
-This project uses [smoosh](https://github.com/fat/smoosh) to build and [jasmine](http://pivotal.github.com/jasmine/)
-with [js-imagediff](https://github.com/HumbleSoftware/js-imagediff) to test. Tests may be executed by
-[jasmine-headless-webkit](http://johnbintz.github.com/jasmine-headless-webkit/) with
-`cd spec; jasmine-headless-webkit -j jasmine.yml -c` or by a browser by navigating to
-`flotr2/spec/SpecRunner.html`.
-
-Shoutouts
----------
-
-Thanks to Bas Wenneker, Fabien Ménager and others for all the work on the original Flotr.
-Thanks to Jochen Berger and Jordan Santell for their contributions to Flotr2.
-
diff --git a/addons/web_graph/static/lib/flotr2/dev/notes.txt b/addons/web_graph/static/lib/flotr2/dev/notes.txt
deleted file mode 100644
index 982474e579f..00000000000
--- a/addons/web_graph/static/lib/flotr2/dev/notes.txt
+++ /dev/null
@@ -1,86 +0,0 @@
-Flotr 2 Architecture Notes
-
-
-Global:
-======
-
-Flotr.js -
- versioning information
- browser detection
- extension (plugins, graph types)
- draw
- clone / merge
- tick size
- tick formatter
- engineering notation
- magnitude
- rad, pixel, floor
- drawText
- measureText
- getBestTextAlign
- align map
- compatibility
-
-
-Graph Architecture:
-===================
-
-Axis -
- all series
- orientation
- ticks (major, minor)
- scale (d2p, p2d, logarithmic)
- notion of stacks
-
-Series -
- per 'data'
- notion of range (x, y, min, max)
-
-Graph -
- DOM constructon
- event attachment
- options initialization
- data range calculations
- canvas spacing calculations
- event normalization
- draw methods
- DOM cleanup
- event cleanup
-
-
-Utilities:
-==========
-
-Color
- build colors
- parse textual color data
- convert colors
- clone colors
-
-Text
- calculate text size
- canvas size
- html size
-
-Date
- formatting
- constants
-
-
-Spacing Calculation
-===================
-
-Flotr
- calculate data
- calculate margins
-
-Chart
- calculate Data Ranges - Explicit or auto data minimum, maximums
- calculate Data Range Extensions - By chart type, extend data range with needs of chart type (ie. stacked bars, stacked lines)
- add Chart Padding - By chart type
-
-Text
- use explicit margins
- calculate label margins
- calculate title margins
-
diff --git a/addons/web_graph/static/lib/flotr2/flotr2.examples.min.js b/addons/web_graph/static/lib/flotr2/flotr2.examples.min.js
deleted file mode 100644
index 7bbf25592a3..00000000000
--- a/addons/web_graph/static/lib/flotr2/flotr2.examples.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-
-(function(){var a=Flotr.EventAdapter,b=Flotr._,c="click",d="example",e="mouseenter",f="mouseleave",g=".",h="flotr-examples",i="flotr-examples-container",j="flotr-examples-reset",k="flotr-examples-thumbs",l="flotr-examples-thumb",m="flotr-examples-collapsed",n="flotr-examples-highlight",o="flotr-examples-large",p="flotr-examples-medium",q="flotr-examples-small",r="flotr-examples-mobile",s='<div class="'+l+'"></div>',t='<div class="'+h+'">'+'<div class="'+j+'">View All</div>'+'<div class="'+k+'"></div>'+'<div class="'+i+'"></div>'+"</div>";Examples=function(a){if(b.isUndefined(Flotr.ExampleList))throw"Flotr.ExampleList not defined.";this.options=a,this.list=Flotr.ExampleList,this.current=null,this.single=!1,this._initNodes(),this._example=new Flotr.Examples.Example({node:this._exampleNode}),this._initExamples()},Examples.prototype={examples:function(){function f(b){var c=$(b.currentTarget),e=c.data("example"),f=b.data.orientation;f^c.hasClass(n)&&(c.toggleClass(n).css(a),d._example.executeCallback(e,c))}var a={cursor:"pointer"},b=this._thumbsNode,c=this.list.get(),d=this,e=["basic","basic-axis","basic-bars","basic-bars-horizontal","basic-bar-stacked","basic-stacked-horizontal","basic-pie","basic-radar","basic-bubble","basic-candle","basic-legend","mouse-tracking","mouse-zoom","mouse-drag","basic-time","negative-values","click-example","download-image","download-data","advanced-titles","color-gradients","basic-timeline","advanced-markers"];(function h(){var a=e.shift(),f=c[a];if(f.type==="profile"||f.type==="test")return;var g=$(s);g.data("example",f),b.append(g),d._example.executeCallback(f,g),g.click(function(){d._loadExample(f)}),e.length&&setTimeout(h,20)})(),b.delegate(g+l,"mouseenter",{orientation:!0},f),b.delegate(g+l,"mouseleave",{orientation:!1},f)},_loadExample:function(a){a&&(window.location.hash="!"+(this.single?"single/":"")+a.key,u||(this._thumbsNode.css({position:"absolute",height:"0px",overflow:"hidden",width:"0px"}),this._resetNode.css({top:"16px"})),this._examplesNode.addClass(m),this._exampleNode.show(),this._example.setExample(a),this._resize(),$(document).scrollTop(0))},_reset:function(){window.location.hash="",u||this._thumbsNode.css({position:"",height:"",overflow:"",width:""}),this._examplesNode.removeClass(m),this._thumbsNode.height(""),this._exampleNode.hide()},_initNodes:function(){var a=$(this.options.node),b=this,c=$(t);b._resetNode=c.find(g+j),b._exampleNode=c.find(g+i),b._thumbsNode=c.find(g+k),b._examplesNode=c,b._resetNode.click(function(){b._reset()}),a.append(c),this._initResizer()},_initResizer:function(){function e(){var b=c.height()-(a.options.thumbPadding||0),e=c.width(),f;e>1760?(f=o,a._thumbsNode.height(b)):e>1140?(f=p,a._thumbsNode.height(b)):(f=q,a._thumbsNode.height("")),d!==f&&(d&&a._examplesNode.removeClass(d),a._examplesNode.addClass(f),d=f)}var a=this,b=a._examplesNode,c=$(window),d;$(window).resize(e),e(),this._resize=e},_initExamples:function(){var a=window.location.hash,b,c;a?(a=a.substring(2),c=a.split("/"),c.length==1?(b=this.list.get(a),this.examples()):c[0]=="single"&&(this.single=!0,b=this.list.get(c[1])),this._loadExample(b)):this.examples()}};var u=function(){var a=!!(navigator.userAgent.match(/Android/i)||navigator.userAgent.match(/webOS/i)||navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i)),b=!!$.browser.mozilla;return!a||b}();Flotr.Examples=Examples})(),function(){var a=Flotr._,b=".",c="flotr-example",d="flotr-example-label",e="flotr-example-title",f="flotr-example-description",g="flotr-example-editor",h="flotr-example-graph",i='<div class="'+c+'">'+'<div class="'+d+" "+e+'"></div>'+'<div class="'+f+'"></div>'+'<div class="'+g+'"></div>'+"</div>",j=function(a){this.options=a,this.example=null,this._initNodes()};j.prototype={setExample:function(a){var b=this.getSource(a),c=this._editorNode;this.example=a,Math.seedrandom(a.key),this._exampleNode.css({display:"block"}),this._titleNode.html(a.name||""),this._markupNode.html(a.description||""),this._editor?this._editor.setExample(b):this._editor=new Flotr.Examples.Editor(c,{example:b,teardown:function(){Flotr.EventAdapter.stopObserving($(c).find(".render")[0]),$(c).find("canvas").each(function(a,b){Flotr.EventAdapter.stopObserving(b)})}})},getSource:function(a){var b=a.callback.toString();return navigator.userAgent.search(/firefox/i)!==-1&&(b=js_beautify(b)),b},executeCallback:function(b,c){a.isElement(c)||(c=c[0]);var d=b.args?[c].concat(b.args):[c];return Math.seedrandom(b.key),b.callback.apply(this,d)},_initNodes:function(){var a=this.options.node,c=$(i);this._titleNode=c.find(b+e),this._markupNode=c.find(b+f),this._editorNode=c.find(b+g),this._exampleNode=c,a.append(c)}},Flotr.Examples.Example=j}(),function(){function Editor(a,b){function o(){i.hide(),f&&f.call(),m.render({example:d,render:h})}function p(a,b,c){var d=!1,e='<span class="error">Error: </span>',f,g;e+='<span class="message">'+a+"</span>",typeof c!="undefined"&&(e+='<span class="position">',e+='Line <span class="line">'+c+"</span>",console.log(b),b&&(e+=" of ",b==window.location?(e+='<span class="url">script</span>',!d):e+='<span class="url">'+b+"</span>"),e+=".</span>"),i.show(),i.html(e)}var c=b.type||"javascript",d=b.example||"",e=b.noRun||!1,f=b.teardown||!1,g=$(T_CONTROLS),h=$(T_RENDER),i=$(T_ERRORS),j=$(T_SOURCE),k=$(T_EDITOR),l="editor-render-"+COUNT,m,h,n;m=new TYPES[c]({onerror:p});if(!m)throw"Invalid type: API not found for type `"+c+"`.";h.attr("id",l),i.hide(),k.append(h).append(g).append(j).addClass(c).addClass(e?"no-run":""),a=$(a),a.append(k),j.append(i),d=m.example({example:d,render:h}),n=CodeMirror(j[0],{value:d,readOnly:e,lineNumbers:!0,mode:m.codeMirrorType}),e||(g.delegate(".run","click",function(){d=n.getValue(),o()}),o()),window.onerror=function(a,b,c){return p(a,b,c),console.log(a),ONERROR&&$.isFunction(ONERROR)?ONERROR(a,b,c):!1},COUNT++,this.setExample=function(a){d=m.example({example:a,render:h}),n.setValue(d),n.refresh(),o()}}var ONERROR=window.onerror,COUNT=0,TYPES={},T_CONTROLS='<div class="controls"><button class="run btn large primary">Run</button></div>',T_EDITOR='<div class="editor"></div>',T_SOURCE='<div class="source"></div>',T_ERRORS='<div class="errors"></div>',T_RENDER='<div class="render"></div>',T_IFRAME="<iframe></iframe>";TYPES.javascript=function(b){this.onerror=b.onerror},TYPES.javascript.prototype={codeMirrorType:"javascript",example:function(a){var b=a.example,c=a.render,d=$(c).attr("id");return"("+b+')(document.getElementById("'+d+'"));'},render:function(o){eval(o.example)}},TYPES.html=function(b){this.onerror=b.onerror},TYPES.html.prototype={codeMirrorType:"htmlmixed",example:function(a){return $.trim(a.example)},render:function(a){var b=a.example,c=a.render,d=$(T_IFRAME),e=this,f,g;c.html(d),f=d[0].contentWindow,g=f.document,g.open(),f.onerror=d.onerror=function(){e.onerror.apply(null,arguments)},g.write(b),g.close()}},typeof Flotr.Examples=="undefined"&&(Flotr.Examples={}),Flotr.Examples.Editor=Editor}(),function(){var a=Flotr.DOM,b=Flotr.EventAdapter,c=Flotr._,d="click",e="example-profile",f="examples",g=function(a){if(c.isUndefined(Flotr.ExampleList))throw"Flotr.ExampleList not defined.";this.editMode="off",this.list=Flotr.ExampleList,this.current=null,this.single=!1,this.init()};g.prototype=c.extend({},Flotr.Examples.prototype,{examples:function(){var e=document.getElementById(f),g=a.node("<ul></ul>"),h;c.each(this.list.getType("profile"),function(e){h=a.node("<li>"+e.name+"</li>"),a.insert(g,h),b.observe(h,d,c.bind(function(){this.example(e)},this))},this),a.insert(e,g)},example:function(a){this._renderSource(a),this.profileStart(a),setTimeout(c.bind(function(){this._renderGraph(a),this.profileEnd()},this),50)},profileStart:function(a){var b=document.getElementById(e);this._startTime=new Date,b.innerHTML='<div>Profile started for "'+a.name+'"...</div>'},profileEnd:function(a){var b=document.getElementById(e);profileTime=new Date-this._startTime,this._startTime=null,b.innerHTML+="<div>Profile complete: "+profileTime+"ms<div>"}}),Flotr.Profile=g}() \ No newline at end of file
diff --git a/addons/web_graph/static/lib/flotr2/flotr2.examples.types.js b/addons/web_graph/static/lib/flotr2/flotr2.examples.types.js
deleted file mode 100644
index f22bc9596f9..00000000000
--- a/addons/web_graph/static/lib/flotr2/flotr2.examples.types.js
+++ /dev/null
@@ -1,1425 +0,0 @@
-(function () {
-
-var ExampleList = function () {
-
- // Map of examples.
- this.examples = {};
-
-};
-
-ExampleList.prototype = {
-
- add : function (example) {
- this.examples[example.key] = example;
- },
-
- get : function (key) {
- return key ? (this.examples[key] || null) : this.examples;
- },
-
- getType : function (type) {
- return Flotr._.select(this.examples, function (example) {
- return (example.type === type);
- });
- }
-}
-
-Flotr.ExampleList = new ExampleList();
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic',
- name : 'Basic',
- callback : basic
-});
-
-function basic (container) {
-
- var
- d1 = [[0, 3], [4, 8], [8, 5], [9, 13]], // First data series
- d2 = [], // Second data series
- i, graph;
-
- // Generate first data set
- for (i = 0; i < 14; i += 0.5) {
- d2.push([i, Math.sin(i)]);
- }
-
- // Draw Graph
- graph = Flotr.draw(container, [ d1, d2 ], {
- xaxis: {
- minorTickFreq: 4
- },
- grid: {
- minorVerticalLines: true
- }
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-stacked',
- name : 'Basic Stacked',
- callback : basic_stacked,
- type : 'test'
-});
-
-function basic_stacked (container) {
-
- var
- d1 = [[0, 3], [4, 8], [8, 2], [9, 3]], // First data series
- d2 = [[0, 2], [4, 3], [8, 8], [9, 4]], // Second data series
- i, graph;
-
- // Draw Graph
- graph = Flotr.draw(container, [ d1, d2 ], {
- lines: {
- show : true,
- stacked: true
- },
- xaxis: {
- minorTickFreq: 4
- },
- grid: {
- minorVerticalLines: true
- }
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-stepped',
- name : 'Basic Stepped',
- callback : basic_stepped,
- type : 'test'
-});
-
-function basic_stepped (container) {
-
- var
- d1 = [[0, 3], [4, 8], [8, 5], [9, 13]], // First data series
- d2 = [], // Second data series
- i, graph;
-
- // Generate first data set
- for (i = 0; i < 14; i += 0.5) {
- d2.push([i, Math.sin(i)]);
- }
-
- // Draw Graph
- graph = Flotr.draw(container, [ d1, d2 ], {
- lines: {
- steps : true,
- show : true
- },
- xaxis: {
- minorTickFreq: 4
- },
- yaxis: {
- autoscale: true
- },
- grid: {
- minorVerticalLines: true
- },
- mouse : {
- track : true,
- relative : true
- }
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-axis',
- name : 'Basic Axis',
- callback : basic_axis
-});
-
-function basic_axis (container) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- d4 = [],
- d5 = [], // Data
- ticks = [[ 0, "Lower"], 10, 20, 30, [40, "Upper"]], // Ticks for the Y-Axis
- graph;
-
- for(var i = 0; i <= 10; i += 0.1){
- d1.push([i, 4 + Math.pow(i,1.5)]);
- d2.push([i, Math.pow(i,3)]);
- d3.push([i, i*5+3*Math.sin(i*4)]);
- d4.push([i, i]);
- if( i.toFixed(1)%1 == 0 ){
- d5.push([i, 2*i]);
- }
- }
-
- d3[30][1] = null;
- d3[31][1] = null;
-
- function ticksFn (n) { return '('+n+')'; }
-
- graph = Flotr.draw(container, [
- { data : d1, label : 'y = 4 + x^(1.5)', lines : { fill : true } },
- { data : d2, label : 'y = x^3'},
- { data : d3, label : 'y = 5x + 3sin(4x)'},
- { data : d4, label : 'y = x'},
- { data : d5, label : 'y = 2x', lines : { show : true }, points : { show : true } }
- ], {
- xaxis : {
- noTicks : 7, // Display 7 ticks.
- tickFormatter : ticksFn, // Displays tick values between brackets.
- min : 1, // Part of the series is not displayed.
- max : 7.5 // Part of the series is not displayed.
- },
- yaxis : {
- ticks : ticks, // Set Y-Axis ticks
- max : 40 // Maximum value along Y-Axis
- },
- grid : {
- verticalLines : false,
- backgroundColor : {
- colors : [[0,'#fff'], [1,'#ccc']],
- start : 'top',
- end : 'bottom'
- }
- },
- legend : {
- position : 'nw'
- },
- title : 'Basic Axis example',
- subtitle : 'This is a subtitle'
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-bars',
- name : 'Basic Bars',
- callback : basic_bars
-});
-
-Flotr.ExampleList.add({
- key : 'basic-bars-horizontal',
- name : 'Horizontal Bars',
- args : [true],
- callback : basic_bars,
- tolerance : 5
-});
-
-function basic_bars (container, horizontal) {
-
- var
- horizontal = (horizontal ? true : false), // Show horizontal bars
- d1 = [], // First data series
- d2 = [], // Second data series
- point, // Data point variable declaration
- i;
-
- for (i = 0; i < 4; i++) {
-
- if (horizontal) {
- point = [Math.ceil(Math.random()*10), i];
- } else {
- point = [i, Math.ceil(Math.random()*10)];
- }
-
- d1.push(point);
-
- if (horizontal) {
- point = [Math.ceil(Math.random()*10), i+0.5];
- } else {
- point = [i+0.5, Math.ceil(Math.random()*10)];
- }
-
- d2.push(point);
- };
-
- // Draw the graph
- Flotr.draw(
- container,
- [d1, d2],
- {
- bars : {
- show : true,
- horizontal : horizontal,
- shadowSize : 0,
- barWidth : 0.5
- },
- mouse : {
- track : true,
- relative : true
- },
- yaxis : {
- min : 0,
- autoscaleMargin : 1
- }
- }
- );
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-bar-stacked',
- name : 'Stacked Bars',
- callback : bars_stacked
-});
-
-Flotr.ExampleList.add({
- key : 'basic-stacked-horizontal',
- name : 'Stacked Horizontal Bars',
- args : [true],
- callback : bars_stacked,
- tolerance : 5
-});
-
-function bars_stacked (container, horizontal) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- graph, i;
-
- for (i = -10; i < 10; i++) {
- if (horizontal) {
- d1.push([Math.random(), i]);
- d2.push([Math.random(), i]);
- d3.push([Math.random(), i]);
- } else {
- d1.push([i, Math.random()]);
- d2.push([i, Math.random()]);
- d3.push([i, Math.random()]);
- }
- }
-
- graph = Flotr.draw(container,[
- { data : d1, label : 'Serie 1' },
- { data : d2, label : 'Serie 2' },
- { data : d3, label : 'Serie 3' }
- ], {
- legend : {
- backgroundColor : '#D2E8FF' // Light blue
- },
- bars : {
- show : true,
- stacked : true,
- horizontal : horizontal,
- barWidth : 0.6,
- lineWidth : 1,
- shadowSize : 0
- },
- grid : {
- verticalLines : horizontal,
- horizontalLines : !horizontal
- }
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-pie',
- name : 'Basic Pie',
- callback : basic_pie
-});
-
-function basic_pie (container) {
-
- var
- d1 = [[0, 4]],
- d2 = [[0, 3]],
- d3 = [[0, 1.03]],
- d4 = [[0, 3.5]],
- graph;
-
- graph = Flotr.draw(container, [
- { data : d1, label : 'Comedy' },
- { data : d2, label : 'Action' },
- { data : d3, label : 'Romance',
- pie : {
- explode : 50
- }
- },
- { data : d4, label : 'Drama' }
- ], {
- HtmlText : false,
- grid : {
- verticalLines : false,
- horizontalLines : false
- },
- xaxis : { showLabels : false },
- yaxis : { showLabels : false },
- pie : {
- show : true,
- explode : 6
- },
- mouse : { track : true },
- legend : {
- position : 'se',
- backgroundColor : '#D2E8FF'
- }
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-radar',
- name : 'Basic Radar',
- callback : basic_radar
-});
-
-function basic_radar (container) {
-
- // Fill series s1 and s2.
- var
- s1 = { label : 'Actual', data : [[0, 3], [1, 8], [2, 5], [3, 5], [4, 3], [5, 9]] },
- s2 = { label : 'Target', data : [[0, 8], [1, 7], [2, 8], [3, 2], [4, 4], [5, 7]] },
- graph, ticks;
-
- // Radar Labels
- ticks = [
- [0, "Statutory"],
- [1, "External"],
- [2, "Videos"],
- [3, "Yippy"],
- [4, "Management"],
- [5, "oops"]
- ];
-
- // Draw the graph.
- graph = Flotr.draw(container, [ s1, s2 ], {
- radar : { show : true},
- grid : { circular : true, minorHorizontalLines : true},
- yaxis : { min : 0, max : 10, minorTickFreq : 2},
- xaxis : { ticks : ticks}
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-bubble',
- name : 'Basic Bubble',
- callback : basic_bubble
-});
-
-function basic_bubble (container) {
-
- var
- d1 = [],
- d2 = [],
- point, graph, i;
-
- for (i = 0; i < 10; i++ ){
- point = [i, Math.ceil(Math.random()*10), Math.ceil(Math.random()*10)];
- d1.push(point);
-
- point = [i, Math.ceil(Math.random()*10), Math.ceil(Math.random()*10)];
- d2.push(point);
- }
-
- // Draw the graph
- graph = Flotr.draw(container, [d1, d2], {
- bubbles : { show : true, baseRadius : 5 },
- xaxis : { min : -4, max : 14 },
- yaxis : { min : -4, max : 14 }
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-candle',
- name : 'Basic Candle',
- callback : basic_candle
-});
-
-function basic_candle (container) {
-
- var
- d1 = [],
- price = 3.206,
- graph,
- i, a, b, c;
-
- for (i = 0; i < 50; i++) {
- a = Math.random();
- b = Math.random();
- c = (Math.random() * (a + b)) - b;
- d1.push([i, price, price + a, price - b, price + c]);
- price = price + c;
- }
-
- // Graph
- graph = Flotr.draw(container, [ d1 ], {
- candles : { show : true, candleWidth : 0.6 },
- xaxis : { noTicks : 10 }
- });
-}
-
-})();
-
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-legend',
- name : 'Basic Legend',
- callback : basic_legend
-});
-
-function basic_legend (container) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- data,
- graph, i;
-
- // Data Generation
- for (i = 0; i < 15; i += 0.5) {
- d1.push([i, i + Math.sin(i+Math.PI)]);
- d2.push([i, i]);
- d3.push([i, 15-Math.cos(i)]);
- }
-
- data = [
- { data : d1, label :'x + sin(x+&pi;)' },
- { data : d2, label :'x' },
- { data : d3, label :'15 - cos(x)' }
- ];
-
-
- // This function prepend each label with 'y = '
- function labelFn (label) {
- return 'y = ' + label;
- }
-
- // Draw graph
- graph = Flotr.draw(container, data, {
- legend : {
- position : 'se', // Position the legend 'south-east'.
- labelFormatter : labelFn, // Format the labels.
- backgroundColor : '#D2E8FF' // A light blue background color.
- },
- HtmlText : false
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'mouse-tracking',
- name : 'Mouse Tracking',
- callback : mouse_tracking
-});
-
-function mouse_tracking (container) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- graph, i;
-
- for (i = 0; i < 20; i += 0.5) {
- d1.push([i, 2*i]);
- d2.push([i, i*1.5+1.5*Math.sin(i)]);
- d3.push([i, 3*Math.cos(i)+10]);
- }
-
- graph = Flotr.draw(
- container,
- [
- {
- data : d1,
- mouse : { track : false } // Disable mouse tracking for d1
- },
- d2,
- d3
- ],
- {
- mouse : {
- track : true, // Enable mouse tracking
- lineColor : 'purple',
- relative : true,
- position : 'ne',
- sensibility : 1,
- trackDecimals : 2,
- trackFormatter : function (o) { return 'x = ' + o.x +', y = ' + o.y; }
- },
- crosshair : {
- mode : 'xy'
- }
- }
- );
-
-};
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'mouse-zoom',
- name : 'Mouse Zoom',
- callback : mouse_zoom,
- description : "<p>Select an area of the graph to zoom. Click to reset the chart.</p>"
-});
-
-function mouse_zoom (container) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- options,
- graph,
- i;
-
- for (i = 0; i < 40; i += 0.5) {
- d1.push([i, Math.sin(i)+3*Math.cos(i)]);
- d2.push([i, Math.pow(1.1, i)]);
- d3.push([i, 40 - i+Math.random()*10]);
- }
-
- options = {
- selection : { mode : 'x', fps : 30 },
- title : 'Mouse Zoom'
- };
-
- // Draw graph with default options, overwriting with passed options
- function drawGraph (opts) {
-
- // Clone the options, so the 'options' variable always keeps intact.
- var o = Flotr._.extend(Flotr._.clone(options), opts || {});
-
- // Return a new graph.
- return Flotr.draw(
- container,
- [ d1, d2, d3 ],
- o
- );
- }
-
- // Actually draw the graph.
- graph = drawGraph();
-
- // Hook into the 'flotr:select' event.
- Flotr.EventAdapter.observe(container, 'flotr:select', function (area) {
-
- // Draw graph with new area
- f = drawGraph({
- xaxis: {min:area.x1, max:area.x2},
- yaxis: {min:area.y1, max:area.y2}
- });
-
- });
-
- // When graph is clicked, draw the graph with default area.
- Flotr.EventAdapter.observe(container, 'flotr:click', function () { drawGraph(); });
-};
-
-})();
-
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'mouse-drag',
- name : 'Mouse Drag',
- callback : mouse_drag
-});
-
-function mouse_drag (container) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- options,
- graph,
- start,
- i;
-
- for (i = -40; i < 40; i += 0.5) {
- d1.push([i, Math.sin(i)+3*Math.cos(i)]);
- d2.push([i, Math.pow(1.1, i)]);
- d3.push([i, 40 - i+Math.random()*10]);
- }
-
- options = {
- xaxis: {min: 0, max: 20},
- title : 'Mouse Drag'
- };
-
- // Draw graph with default options, overwriting with passed options
- function drawGraph (opts) {
-
- // Clone the options, so the 'options' variable always keeps intact.
- var o = Flotr._.extend(Flotr._.clone(options), opts || {});
-
- // Return a new graph.
- return Flotr.draw(
- container,
- [ d1, d2, d3 ],
- o
- );
- }
-
- graph = drawGraph();
-
- function initializeDrag (e) {
- start = graph.getEventPosition(e);
- Flotr.EventAdapter.observe(document, 'mousemove', move);
- Flotr.EventAdapter.observe(document, 'mouseup', stopDrag);
- }
-
- function move (e) {
- var
- end = graph.getEventPosition(e),
- xaxis = graph.axes.x,
- offset = start.x - end.x;
-
- graph = drawGraph({
- xaxis : {
- min : xaxis.min + offset,
- max : xaxis.max + offset
- }
- });
- // @todo: refector initEvents in order not to remove other observed events
- Flotr.EventAdapter.observe(graph.overlay, 'mousedown', initializeDrag);
- }
-
- function stopDrag () {
- Flotr.EventAdapter.stopObserving(document, 'mousemove', move);
- }
-
- Flotr.EventAdapter.observe(graph.overlay, 'mousedown', initializeDrag);
-
-};
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-time',
- name : 'Basic Time',
- callback : basic_time,
- description : "<p>Select an area of the graph to zoom. Click to reset the chart.</p>"
-});
-
-function basic_time (container) {
-
- var
- d1 = [],
- start = new Date("2009/01/01 01:00").getTime(),
- options,
- graph,
- i, x, o;
-
- for (i = 0; i < 100; i++) {
- x = start+(i*1000*3600*24*36.5);
- d1.push([x, i+Math.random()*30+Math.sin(i/20+Math.random()*2)*20+Math.sin(i/10+Math.random())*10]);
- }
-
- options = {
- xaxis : {
- mode : 'time',
- labelsAngle : 45
- },
- selection : {
- mode : 'x'
- },
- HtmlText : false,
- title : 'Time'
- };
-
- // Draw graph with default options, overwriting with passed options
- function drawGraph (opts) {
-
- // Clone the options, so the 'options' variable always keeps intact.
- o = Flotr._.extend(Flotr._.clone(options), opts || {});
-
- // Return a new graph.
- return Flotr.draw(
- container,
- [ d1 ],
- o
- );
- }
-
- graph = drawGraph();
-
- Flotr.EventAdapter.observe(container, 'flotr:select', function(area){
- // Draw selected area
- graph = drawGraph({
- xaxis : { min : area.x1, max : area.x2, mode : 'time', labelsAngle : 45 },
- yaxis : { min : area.y1, max : area.y2 }
- });
- });
-
- // When graph is clicked, draw the graph with default area.
- Flotr.EventAdapter.observe(container, 'flotr:click', function () { graph = drawGraph(); });
-};
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'negative-values',
- name : 'Negative Values',
- callback : negative_values
-});
-
-function negative_values (container) {
-
- var
- d0 = [], // Line through y = 0
- d1 = [], // Random data presented as a scatter plot.
- d2 = [], // A regression line for the scatter.
- sx = 0,
- sy = 0,
- sxy = 0,
- sxsq = 0,
- xmean,
- ymean,
- alpha,
- beta,
- n, x, y;
-
- for (n = 0; n < 20; n++){
-
- x = n;
- y = x + Math.random()*8 - 15;
-
- d0.push([x, 0]);
- d1.push([x, y]);
-
- // Computations used for regression line
- sx += x;
- sy += y;
- sxy += x*y;
- sxsq += Math.pow(x,2);
- }
-
- xmean = sx/n;
- ymean = sy/n;
- beta = ((n*sxy) - (sx*sy))/((n*sxsq)-(Math.pow(sx,2)));
- alpha = ymean - (beta * xmean);
-
- // Compute the regression line.
- for (n = 0; n < 20; n++){
- d2.push([n, alpha + beta*n])
- }
-
- // Draw the graph
- graph = Flotr.draw(
- container, [
- { data : d0, shadowSize : 0, color : '#545454' }, // Horizontal
- { data : d1, label : 'y = x + (Math.random() * 8) - 15', points : { show : true } }, // Scatter
- { data : d2, label : 'y = ' + alpha.toFixed(2) + ' + ' + beta.toFixed(2) + '*x' } // Regression
- ],
- {
- legend : { position : 'se', backgroundColor : '#D2E8FF' },
- title : 'Negative Values'
- }
- );
-};
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'click-example',
- name : 'Click Example',
- callback : click_example
-});
-
-function click_example (container) {
-
- var
- d1 = [[0,0]], // Point at origin
- options,
- graph;
-
- options = {
- xaxis: {min: 0, max: 15},
- yaxis: {min: 0, max: 15},
- lines: {show: true},
- points: {show: true},
- mouse: {track:true},
- title: 'Click Example'
- };
-
- graph = Flotr.draw(container, [d1], options);
-
- // Add a point to the series and redraw the graph
- Flotr.EventAdapter.observe(container, 'flotr:click', function(position){
-
- // Add a point to the series at the location of the click
- d1.push([position.x, position.y]);
-
- // Sort the series.
- d1 = d1.sort(function (a, b) { return a[0] - b[0]; });
-
- // Redraw the graph, with the new series.
- graph = Flotr.draw(container, [d1], options);
- });
-};
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'download-image',
- name : 'Download Image',
- callback : download_image,
- description : '' +
- '<form name="image-download" id="image-download" action="" onsubmit="return false">' +
- '<label><input type="radio" name="format" value="png" checked="checked" /> PNG</label>' +
- '<label><input type="radio" name="format" value="jpeg" /> JPEG</label>' +
-
- '<button name="to-image" onclick="CurrentExample(\'to-image\')">To Image</button>' +
- '<button name="download" onclick="CurrentExample(\'download\')">Download</button>' +
- '<button name="reset" onclick="CurrentExample(\'reset\')">Reset</button>' +
- '</form>'
-});
-
-function download_image (container) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- d4 = [],
- d5 = [],
- graph,
- i;
-
- for (i = 0; i <= 10; i += 0.1) {
- d1.push([i, 4 + Math.pow(i,1.5)]);
- d2.push([i, Math.pow(i,3)]);
- d3.push([i, i*5+3*Math.sin(i*4)]);
- d4.push([i, i]);
- if( i.toFixed(1)%1 == 0 ){
- d5.push([i, 2*i]);
- }
- }
-
- // Draw the graph
- graph = Flotr.draw(
- container,[
- {data:d1, label:'y = 4 + x^(1.5)', lines:{fill:true}},
- {data:d2, label:'y = x^3', yaxis:2},
- {data:d3, label:'y = 5x + 3sin(4x)'},
- {data:d4, label:'y = x'},
- {data:d5, label:'y = 2x', lines: {show: true}, points: {show: true}}
- ],{
- title: 'Download Image Example',
- subtitle: 'You can save me as an image',
- xaxis:{
- noTicks: 7, // Display 7 ticks.
- tickFormatter: function(n){ return '('+n+')'; }, // => displays tick values between brackets.
- min: 1, // => part of the series is not displayed.
- max: 7.5, // => part of the series is not displayed.
- labelsAngle: 45,
- title: 'x Axis'
- },
- yaxis:{
- ticks: [[0, "Lower"], 10, 20, 30, [40, "Upper"]],
- max: 40,
- title: 'y = f(x)'
- },
- y2axis:{color:'#FF0000', max: 500, title: 'y = x^3'},
- grid:{
- verticalLines: false,
- backgroundColor: 'white'
- },
- HtmlText: false,
- legend: {
- position: 'nw'
- }
- });
-
- this.CurrentExample = function (operation) {
-
- var
- format = $('#image-download input:radio[name=format]:checked').val();
- if (Flotr.isIE && Flotr.isIE < 9) {
- alert(
- "Your browser doesn't allow you to get a bitmap image from the plot, " +
- "you can only get a VML image that you can use in Microsoft Office.<br />"
- );
- }
-
- if (operation == 'to-image') {
- graph.download.saveImage(format, null, null, true)
- } else if (operation == 'download') {
- graph.download.saveImage(format);
- } else if (operation == 'reset') {
- graph.download.restoreCanvas();
- }
- };
-
- return graph;
-};
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'download-data',
- name : 'Download Data',
- callback : download_data
-});
-
-function download_data (container) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- d4 = [],
- d5 = [],
- graph,
- i,x;
-
- for (i = 0; i <= 100; i += 1) {
- x = i / 10;
- d1.push([x, 4 + Math.pow(x,1.5)]);
- d2.push([x, Math.pow(x,3)]);
- d3.push([x, i*5+3*Math.sin(x*4)]);
- d4.push([x, x]);
- if(x%1 === 0 ){
- d5.push([x, 2*x]);
- }
- }
-
- // Draw the graph.
- graph = Flotr.draw(
- container, [
- { data : d1, label : 'y = 4 + x^(1.5)', lines : { fill : true } },
- { data : d2, label : 'y = x^3' },
- { data : d3, label : 'y = 5x + 3sin(4x)' },
- { data : d4, label : 'y = x' },
- { data : d5, label : 'y = 2x', lines : { show : true }, points : { show : true } }
- ],{
- xaxis : {
- noTicks : 7,
- tickFormatter : function (n) { return '('+n+')'; },
- min: 1, // Part of the series is not displayed.
- max: 7.5
- },
- yaxis : {
- ticks : [[ 0, "Lower"], 10, 20, 30, [40, "Upper"]],
- max : 40
- },
- grid : {
- verticalLines : false,
- backgroundColor : 'white'
- },
- legend : {
- position : 'nw'
- },
- spreadsheet : {
- show : true,
- tickFormatter : function (e) { return e+''; }
- }
- });
-};
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'advanced-titles',
- name : 'Advanced Titles',
- callback : advanced_titles
-});
-
-function advanced_titles (container) {
-
- var
- d1 = [],
- d2 = [],
- d3 = [],
- d4 = [],
- d5 = [],
- graph,
- i;
-
- for (i = 0; i <= 10; i += 0.1) {
- d1.push([i, 4 + Math.pow(i,1.5)]);
- d2.push([i, Math.pow(i,3)]);
- d3.push([i, i*5+3*Math.sin(i*4)]);
- d4.push([i, i]);
- if (i.toFixed(1)%1 == 0) {
- d5.push([i, 2*i]);
- }
- }
-
- // Draw the graph.
- graph = Flotr.draw(
- container,[
- { data : d1, label : 'y = 4 + x^(1.5)', lines : { fill : true } },
- { data : d2, label : 'y = x^3', yaxis : 2 },
- { data : d3, label : 'y = 5x + 3sin(4x)' },
- { data : d4, label : 'y = x' },
- { data : d5, label : 'y = 2x', lines : { show : true }, points : { show : true } }
- ], {
- title : 'Advanced Titles Example',
- subtitle : 'You can save me as an image',
- xaxis : {
- noTicks : 7,
- tickFormatter : function (n) { return '('+n+')'; },
- min : 1,
- max : 7.5,
- labelsAngle : 45,
- title : 'x Axis'
- },
- yaxis : {
- ticks : [[0, "Lower"], 10, 20, 30, [40, "Upper"]],
- max : 40,
- title : 'y = f(x)'
- },
- y2axis : { color : '#FF0000', max : 500, title : 'y = x^3' },
- grid : {
- verticalLines : false,
- backgroundColor : 'white'
- },
- HtmlText : false,
- legend : {
- position : 'nw'
- }
- });
-};
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'color-gradients',
- name : 'Color Gradients',
- callback : color_gradients
-});
-
-function color_gradients (container) {
-
- var
- bars = {
- data: [],
- bars: {
- show: true,
- barWidth: 0.8,
- lineWidth: 0,
- fillColor: {
- colors: ['#CB4B4B', '#fff'],
- start: 'top',
- end: 'bottom'
- },
- fillOpacity: 0.8
- }
- }, markers = {
- data: [],
- markers: {
- show: true,
- position: 'ct'
- }
- }, lines = {
- data: [],
- lines: {
- show: true,
- fillColor: ['#00A8F0', '#fff'],
- fill: true,
- fillOpacity: 1
- }
- },
- point,
- graph,
- i;
-
- for (i = 0; i < 8; i++) {
- point = [i, Math.ceil(Math.random() * 10)];
- bars.data.push(point);
- markers.data.push(point);
- }
-
- for (i = -1; i < 9; i += 0.01){
- lines.data.push([i, i*i/8+2]);
- }
-
- graph = Flotr.draw(
- container,
- [lines, bars, markers], {
- yaxis: {
- min: 0,
- max: 11
- },
- xaxis: {
- min: -0.5,
- max: 7.5
- },
- grid: {
- verticalLines: false,
- backgroundColor: ['#fff', '#ccc']
- }
- }
- );
-};
-
-})();
-
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'profile-bars',
- name : 'Profile Bars',
- type : 'profile',
- callback : profile_bars
-});
-
-/*
-Flotr.ExampleList.add({
- key : 'basic-bars-horizontal',
- name : 'Horizontal Bars',
- args : [true],
- callback : basic_bars
-});
-*/
-
-function profile_bars (container, horizontal) {
-
- var
- horizontal = (horizontal ? true : false), // Show horizontal bars
- d1 = [], // First data series
- d2 = [], // Second data series
- point, // Data point variable declaration
- i;
-
- for (i = 0; i < 5000; i++) {
-
- if (horizontal) {
- point = [Math.ceil(Math.random()*10), i];
- } else {
- point = [i, Math.ceil(Math.random()*10)];
- }
-
- d1.push(point);
-
- if (horizontal) {
- point = [Math.ceil(Math.random()*10), i+0.5];
- } else {
- point = [i+0.5, Math.ceil(Math.random()*10)];
- }
-
- d2.push(point);
- };
-
- // Draw the graph
- Flotr.draw(
- container,
- [d1, d2],
- {
- bars : {
- show : true,
- horizontal : horizontal,
- barWidth : 0.5
- },
- mouse : {
- track : true,
- relative : true
- },
- yaxis : {
- min : 0,
- autoscaleMargin : 1
- }
- }
- );
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'basic-timeline',
- name : 'Basic Timeline',
- callback : basic_timeline
-});
-
-function basic_timeline (container) {
-
- var
- d1 = [[1, 4, 5]],
- d2 = [[3.2, 3, 4]],
- d3 = [[1.9, 2, 2], [5, 2, 3.3]],
- d4 = [[1.55, 1, 9]],
- d5 = [[5, 0, 2.3]],
- data = [],
- timeline = { show : true, barWidth : .5 },
- markers = [],
- labels = ['Obama', 'Bush', 'Clinton', 'Palin', 'McCain'],
- i, graph, point;
-
- // Timeline
- Flotr._.each([d1, d2, d3, d4, d5], function (d) {
- data.push({
- data : d,
- timeline : Flotr._.clone(timeline)
- });
- });
-
- // Markers
- Flotr._.each([d1, d2, d3, d4, d5], function (d) {
- point = d[0];
- markers.push([point[0], point[1]]);
- });
- data.push({
- data: markers,
- markers: {
- show: true,
- position: 'rm',
- fontSize: 11,
- labelFormatter : function (o) { return labels[o.index]; }
- }
- });
-
- // Draw Graph
- graph = Flotr.draw(container, data, {
- xaxis: {
- noTicks: 3,
- tickFormatter: function (x) {
- var
- x = parseInt(x),
- months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
- return months[(x-1)%12];
- }
- },
- yaxis: {
- showLabels : false
- },
- grid: {
- horizontalLines : false
- }
- });
-}
-
-})();
-
-(function () {
-
-Flotr.ExampleList.add({
- key : 'advanced-markers',
- name : 'Advanced Markers',
- callback : advanced_markers,
- timeout : 150
-});
-
-function advanced_markers (container) {
-
- var
- xmark = new Image(),
- checkmark = new Image(),
- bars = {
- data: [],
- bars: {
- show: true,
- barWidth: 0.6,
- lineWidth: 0,
- fillOpacity: 0.8
- }
- }, markers = {
- data: [],
- markers: {
- show: true,
- position: 'ct',
- labelFormatter: function (o) {
- return (o.y >= 5) ? checkmark : xmark;
- }
- }
- },
- flotr = Flotr,
- point,
- graph,
- i;
-
-
- for (i = 0; i < 8; i++) {
- point = [i, Math.ceil(Math.random() * 10)];
- bars.data.push(point);
- markers.data.push(point);
- }
-
- var runner = function () {
- if (!xmark.complete || !checkmark.complete) {
- setTimeout(runner, 50);
- return;
- }
-
- graph = flotr.draw(
- container,
- [bars, markers], {
- yaxis: {
- min: 0,
- max: 11
- },
- xaxis: {
- min: -0.5,
- max: 7.5
- },
- grid: {
- verticalLines: false
- }
- }
- );
- }
-
- xmark.onload = runner;
- xmark.src = 'images/xmark.png';
- checkmark.src = 'images/checkmark.png';
-};
-
-})();
-
diff --git a/addons/web_graph/static/lib/flotr2/flotr2.ie.min.js b/addons/web_graph/static/lib/flotr2/flotr2.ie.min.js
deleted file mode 100644
index 0c64520fcb5..00000000000
--- a/addons/web_graph/static/lib/flotr2/flotr2.ie.min.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2006 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// Known Issues:
-//
-// * Patterns only support repeat.
-// * Radial gradient are not implemented. The VML version of these look very
-// different from the canvas one.
-// * Clipping paths are not implemented.
-// * Coordsize. The width and height attribute have higher priority than the
-// width and height style values which isn't correct.
-// * Painting mode isn't implemented.
-// * Canvas width/height should is using content-box by default. IE in
-// Quirks mode will draw the canvas using border-box. Either change your
-// doctype to HTML5
-// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
-// or use Box Sizing Behavior from WebFX
-// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
-// * Non uniform scaling does not correctly scale strokes.
-// * Optimize. There is always room for speed improvements.
-// Only add this code if we do not already have a canvas implementation
-
-document.createElement("canvas").getContext||function(){function j(){return this.context_||(this.context_=new N(this))}function l(a,b,c){var d=k.call(arguments,2);return function(){return a.apply(b,d.concat(k.call(arguments)))}}function m(a){return String(a).replace(/&/g,"&amp;").replace(/"/g,"&quot;")}function n(a,b,c){a.namespaces[b]||a.namespaces.add(b,c,"#default#VML")}function o(a){n(a,"g_vml_","urn:schemas-microsoft-com:vml"),n(a,"g_o_","urn:schemas-microsoft-com:office:office");if(!a.styleSheets.ex_canvas_){var b=a.createStyleSheet();b.owningElement.id="ex_canvas_",b.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}function q(a){var b=a.srcElement;switch(a.propertyName){case"width":b.getContext().clearRect(),b.style.width=b.attributes.width.nodeValue+"px",b.firstChild&&(b.firstChild.style.width=b.clientWidth+"px");break;case"height":b.getContext().clearRect(),b.style.height=b.attributes.height.nodeValue+"px",b.firstChild&&(b.firstChild.style.height=b.clientHeight+"px")}}function r(a){var b=a.srcElement;b.firstChild&&(b.firstChild.style.width=b.clientWidth+"px",b.firstChild.style.height=b.clientHeight+"px")}function v(){return[[1,0,0],[0,1,0],[0,0,1]]}function w(a,b){var c=v();for(var d=0;d<3;d++)for(var e=0;e<3;e++){var f=0;for(var g=0;g<3;g++)f+=a[d][g]*b[g][e];c[d][e]=f}return c}function x(a,b){b.fillStyle=a.fillStyle,b.lineCap=a.lineCap,b.lineJoin=a.lineJoin,b.lineWidth=a.lineWidth,b.miterLimit=a.miterLimit,b.shadowBlur=a.shadowBlur,b.shadowColor=a.shadowColor,b.shadowOffsetX=a.shadowOffsetX,b.shadowOffsetY=a.shadowOffsetY,b.strokeStyle=a.strokeStyle,b.globalAlpha=a.globalAlpha,b.font=a.font,b.textAlign=a.textAlign,b.textBaseline=a.textBaseline,b.arcScaleX_=a.arcScaleX_,b.arcScaleY_=a.arcScaleY_,b.lineScale_=a.lineScale_}function z(a){var b=a.indexOf("(",3),c=a.indexOf(")",b+1),d=a.substring(b+1,c).split(",");if(d.length!=4||a.charAt(3)!="a")d[3]=1;return d}function A(a){return parseFloat(a)/100}function B(a,b,c){return Math.min(c,Math.max(b,a))}function C(a){var b,c,d,e,f,g;e=parseFloat(a[0])/360%360,e<0&&e++,f=B(A(a[1]),0,1),g=B(A(a[2]),0,1);if(f==0)b=c=d=g;else{var h=g<.5?g*(1+f):g+f-g*f,i=2*g-h;b=D(i,h,e+1/3),c=D(i,h,e),d=D(i,h,e-1/3)}return"#"+s[Math.floor(b*255)]+s[Math.floor(c*255)]+s[Math.floor(d*255)]}function D(a,b,c){return c<0&&c++,c>1&&c--,6*c<1?a+(b-a)*6*c:2*c<1?b:3*c<2?a+(b-a)*(2/3-c)*6:a}function F(a){if(a in E)return E[a];var b,c=1;a=String(a);if(a.charAt(0)=="#")b=a;else if(/^rgb/.test(a)){var d=z(a),b="#",e;for(var f=0;f<3;f++)d[f].indexOf("%")!=-1?e=Math.floor(A(d[f])*255):e=+d[f],b+=s[B(e,0,255)];c=+d[3]}else if(/^hsl/.test(a)){var d=z(a);b=C(d),c=d[3]}else b=y[a]||a;return E[a]={color:b,alpha:c}}function I(a){if(H[a])return H[a];var b=document.createElement("div"),c=b.style;try{c.font=a}catch(d){}return H[a]={style:c.fontStyle||G.style,variant:c.fontVariant||G.variant,weight:c.fontWeight||G.weight,size:c.fontSize||G.size,family:c.fontFamily||G.family}}function J(a,b){var c={};for(var d in a)c[d]=a[d];var e=parseFloat(b.currentStyle.fontSize),f=parseFloat(a.size);return typeof a.size=="number"?c.size=a.size:a.size.indexOf("px")!=-1?c.size=f:a.size.indexOf("em")!=-1?c.size=e*f:a.size.indexOf("%")!=-1?c.size=e/100*f:a.size.indexOf("pt")!=-1?c.size=f/.75:c.size=e,c}function K(a){return a.style+" "+a.variant+" "+a.weight+" "+a.size+"px "+a.family}function M(a){return L[a]||"square"}function N(a){this.m_=v(),this.mStack_=[],this.aStack_=[],this.currentPath_=[],this.strokeStyle="#000",this.fillStyle="#000",this.lineWidth=1,this.lineJoin="miter",this.lineCap="butt",this.miterLimit=g*1,this.globalAlpha=1,this.font="10px sans-serif",this.textAlign="left",this.textBaseline="alphabetic",this.canvas=a;var b="width:"+a.clientWidth+"px;height:"+a.clientHeight+"px;overflow:hidden;position:absolute",c=a.ownerDocument.createElement("div");c.style.cssText=b,a.appendChild(c);var d=c.cloneNode(!1);d.style.backgroundColor="red",d.style.filter="alpha(opacity=0)",a.appendChild(d),this.element_=c,this.arcScaleX_=1,this.arcScaleY_=1,this.lineScale_=1}function P(a,b,c,d){a.currentPath_.push({type:"bezierCurveTo",cp1x:b.x,cp1y:b.y,cp2x:c.x,cp2y:c.y,x:d.x,y:d.y}),a.currentX_=d.x,a.currentY_=d.y}function Q(a,b){var c=F(a.strokeStyle),d=c.color,e=c.alpha*a.globalAlpha,f=a.lineScale_*a.lineWidth;f<1&&(e*=f),b.push("<g_vml_:stroke",' opacity="',e,'"',' joinstyle="',a.lineJoin,'"',' miterlimit="',a.miterLimit,'"',' endcap="',M(a.lineCap),'"',' weight="',f,'px"',' color="',d,'" />')}function R(b,c,d,e){var f=b.fillStyle,h=b.arcScaleX_,i=b.arcScaleY_,j=e.x-d.x,k=e.y-d.y;if(f instanceof V){var l=0,m={x:0,y:0},n=0,o=1;if(f.type_=="gradient"){var p=f.x0_/h,q=f.y0_/i,r=f.x1_/h,s=f.y1_/i,t=S(b,p,q),u=S(b,r,s),v=u.x-t.x,w=u.y-t.y;l=Math.atan2(v,w)*180/Math.PI,l<0&&(l+=360),l<1e-6&&(l=0)}else{var t=S(b,f.x0_,f.y0_);m={x:(t.x-d.x)/j,y:(t.y-d.y)/k},j/=h*g,k/=i*g;var x=a.max(j,k);n=2*f.r0_/x,o=2*f.r1_/x-n}var y=f.colors_;y.sort(function(a,b){return a.offset-b.offset});var z=y.length,A=y[0].color,B=y[z-1].color,C=y[0].alpha*b.globalAlpha,D=y[z-1].alpha*b.globalAlpha,E=[];for(var G=0;G<z;G++){var H=y[G];E.push(H.offset*o+n+" "+H.color)}c.push('<g_vml_:fill type="',f.type_,'"',' method="none" focus="100%"',' color="',A,'"',' color2="',B,'"',' colors="',E.join(","),'"',' opacity="',D,'"',' g_o_:opacity2="',C,'"',' angle="',l,'"',' focusposition="',m.x,",",m.y,'" />')}else if(f instanceof W){if(j&&k){var I=-d.x,J=-d.y;c.push("<g_vml_:fill",' position="',I/j*h*h,",",J/k*i*i,'"',' type="tile"',' src="',f.src_,'" />')}}else{var K=F(b.fillStyle),L=K.color,M=K.alpha*b.globalAlpha;c.push('<g_vml_:fill color="',L,'" opacity="',M,'" />')}}function S(a,b,c){var d=a.m_;return{x:g*(b*d[0][0]+c*d[1][0]+d[2][0])-h,y:g*(b*d[0][1]+c*d[1][1]+d[2][1])-h}}function T(a){return isFinite(a[0][0])&&isFinite(a[0][1])&&isFinite(a[1][0])&&isFinite(a[1][1])&&isFinite(a[2][0])&&isFinite(a[2][1])}function U(a,b,c){if(!T(b))return;a.m_=b;if(c){var d=b[0][0]*b[1][1]-b[0][1]*b[1][0];a.lineScale_=f(e(d))}}function V(a){this.type_=a,this.x0_=0,this.y0_=0,this.r0_=0,this.x1_=0,this.y1_=0,this.r1_=0,this.colors_=[]}function W(a,b){Y(a);switch(b){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=b;break;default:X("SYNTAX_ERR")}this.src_=a.src,this.width_=a.width,this.height_=a.height}function X(a){throw new Z(a)}function Y(a){(!a||a.nodeType!=1||a.tagName!="IMG")&&X("TYPE_MISMATCH_ERR"),a.readyState!="complete"&&X("INVALID_STATE_ERR")}function Z(a){this.code=this[a],this.message=a+": DOM Exception "+this.code}var a=Math,b=a.round,c=a.sin,d=a.cos,e=a.abs,f=a.sqrt,g=10,h=g/2,i=+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1],k=Array.prototype.slice;o(document);var p={init:function(a){var b=a||document;b.createElement("canvas"),b.attachEvent("onreadystatechange",l(this.init_,this,b))},init_:function(a){var b=a.getElementsByTagName("canvas");for(var c=0;c<b.length;c++)this.initElement(b[c])},initElement:function(a){if(!a.getContext){a.getContext=j,o(a.ownerDocument),a.innerHTML="",a.attachEvent("onpropertychange",q),a.attachEvent("onresize",r);var b=a.attributes;b.width&&b.width.specified?a.style.width=b.width.nodeValue+"px":a.width=a.clientWidth,b.height&&b.height.specified?a.style.height=b.height.nodeValue+"px":a.height=a.clientHeight}return a}};p.init();var s=[];for(var t=0;t<16;t++)for(var u=0;u<16;u++)s[t*16+u]=t.toString(16)+u.toString(16);var y={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"},E={},G={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"},H={},L={butt:"flat",round:"round"},O=N.prototype;O.clearRect=function(){this.textMeasureEl_&&(this.textMeasureEl_.removeNode(!0),this.textMeasureEl_=null),this.element_.innerHTML=""},O.beginPath=function(){this.currentPath_=[]},O.moveTo=function(a,b){var c=S(this,a,b);this.currentPath_.push({type:"moveTo",x:c.x,y:c.y}),this.currentX_=c.x,this.currentY_=c.y},O.lineTo=function(a,b){var c=S(this,a,b);this.currentPath_.push({type:"lineTo",x:c.x,y:c.y}),this.currentX_=c.x,this.currentY_=c.y},O.bezierCurveTo=function(a,b,c,d,e,f){var g=S(this,e,f),h=S(this,a,b),i=S(this,c,d);P(this,h,i,g)},O.quadraticCurveTo=function(a,b,c,d){var e=S(this,a,b),f=S(this,c,d),g={x:this.currentX_+2/3*(e.x-this.currentX_),y:this.currentY_+2/3*(e.y-this.currentY_)},h={x:g.x+(f.x-this.currentX_)/3,y:g.y+(f.y-this.currentY_)/3};P(this,g,h,f)},O.arc=function(a,b,f,i,j,k){f*=g;var l=k?"at":"wa",m=a+d(i)*f-h,n=b+c(i)*f-h,o=a+d(j)*f-h,p=b+c(j)*f-h;e(m-o)<1e-7&&!k&&(m+=.125),e(n-p)<1e-7&&k&&(n-=.125);var q=S(this,a,b),r=S(this,m,n),s=S(this,o,p);this.currentPath_.push({type:l,x:q.x,y:q.y,radius:f,xStart:r.x,yStart:r.y,xEnd:s.x,yEnd:s.y})},O.rect=function(a,b,c,d){this.moveTo(a,b),this.lineTo(a+c,b),this.lineTo(a+c,b+d),this.lineTo(a,b+d),this.closePath()},O.strokeRect=function(a,b,c,d){var e=this.currentPath_;this.beginPath(),this.moveTo(a,b),this.lineTo(a+c,b),this.lineTo(a+c,b+d),this.lineTo(a,b+d),this.closePath(),this.stroke(),this.currentPath_=e},O.fillRect=function(a,b,c,d){var e=this.currentPath_;this.beginPath(),this.moveTo(a,b),this.lineTo(a+c,b),this.lineTo(a+c,b+d),this.lineTo(a,b+d),this.closePath(),this.fill(),this.currentPath_=e},O.createLinearGradient=function(a,b,c,d){var e=new V("gradient");return e.x0_=a,e.y0_=b,e.x1_=c,e.y1_=d,e},O.createRadialGradient=function(a,b,c,d,e,f){var g=new V("gradientradial");return g.x0_=a,g.y0_=b,g.r0_=c,g.x1_=d,g.y1_=e,g.r1_=f,g},O.drawImage=function(c,d){var e,f,h,i,j,k,l,m,n=c.runtimeStyle.width,o=c.runtimeStyle.height;c.runtimeStyle.width="auto",c.runtimeStyle.height="auto";var p=c.width,q=c.height;c.runtimeStyle.width=n,c.runtimeStyle.height=o;if(arguments.length==3)e=arguments[1],f=arguments[2],j=k=0,l=h=p,m=i=q;else if(arguments.length==5)e=arguments[1],f=arguments[2],h=arguments[3],i=arguments[4],j=k=0,l=p,m=q;else if(arguments.length==9)j=arguments[1],k=arguments[2],l=arguments[3],m=arguments[4],e=arguments[5],f=arguments[6],h=arguments[7],i=arguments[8];else throw Error("Invalid number of arguments");var r=S(this,e,f),s=l/2,t=m/2,u=[],v=10,w=10;u.push(" <g_vml_:group",' coordsize="',g*v,",",g*w,'"',' coordorigin="0,0"',' style="width:',v,"px;height:",w,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var x=[];x.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",b(r.x/g),",","Dy=",b(r.y/g),"");var y=r,z=S(this,e+h,f),A=S(this,e,f+i),B=S(this,e+h,f+i);y.x=a.max(y.x,z.x,A.x,B.x),y.y=a.max(y.y,z.y,A.y,B.y),u.push("padding:0 ",b(y.x/g),"px ",b(y.y/g),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",x.join(""),", sizingmethod='clip');")}else u.push("top:",b(r.y/g),"px;left:",b(r.x/g),"px;");u.push(' ">','<g_vml_:image src="',c.src,'"',' style="width:',g*h,"px;"," height:",g*i,'px"',' cropleft="',j/p,'"',' croptop="',k/q,'"',' cropright="',(p-j-l)/p,'"',' cropbottom="',(q-k-m)/q,'"'," />","</g_vml_:group>"),this.element_.insertAdjacentHTML("BeforeEnd",u.join(""))},O.stroke=function(a){var c=[],d=!1,e=10,f=10;c.push("<g_vml_:shape",' filled="',!!a,'"',' style="position:absolute;width:',e,"px;height:",f,'px;"',' coordorigin="0,0"',' coordsize="',g*e,",",g*f,'"',' stroked="',!a,'"',' path="');var h=!1,i={x:null,y:null},j={x:null,y:null};for(var k=0;k<this.currentPath_.length;k++){var l=this.currentPath_[k],m;switch(l.type){case"moveTo":m=l,c.push(" m ",b(l.x),",",b(l.y));break;case"lineTo":c.push(" l ",b(l.x),",",b(l.y));break;case"close":c.push(" x "),l=null;break;case"bezierCurveTo":c.push(" c ",b(l.cp1x),",",b(l.cp1y),",",b(l.cp2x),",",b(l.cp2y),",",b(l.x),",",b(l.y));break;case"at":case"wa":c.push(" ",l.type," ",b(l.x-this.arcScaleX_*l.radius),",",b(l.y-this.arcScaleY_*l.radius)," ",b(l.x+this.arcScaleX_*l.radius),",",b(l.y+this.arcScaleY_*l.radius)," ",b(l.xStart),",",b(l.yStart)," ",b(l.xEnd),",",b(l.yEnd))}if(l){if(i.x==null||l.x<i.x)i.x=l.x;if(j.x==null||l.x>j.x)j.x=l.x;if(i.y==null||l.y<i.y)i.y=l.y;if(j.y==null||l.y>j.y)j.y=l.y}}c.push(' ">'),a?R(this,c,i,j):Q(this,c),c.push("</g_vml_:shape>"),this.element_.insertAdjacentHTML("beforeEnd",c.join(""))},O.fill=function(){this.stroke(!0)},O.closePath=function(){this.currentPath_.push({type:"close"})},O.save=function(){var a={};x(this,a),this.aStack_.push(a),this.mStack_.push(this.m_),this.m_=w(v(),this.m_)},O.restore=function(){this.aStack_.length&&(x(this.aStack_.pop(),this),this.m_=this.mStack_.pop())},O.translate=function(a,b){var c=[[1,0,0],[0,1,0],[a,b,1]];U(this,w(c,this.m_),!1)},O.rotate=function(a){var b=d(a),e=c(a),f=[[b,e,0],[-e,b,0],[0,0,1]];U(this,w(f,this.m_),!1)},O.scale=function(a,b){this.arcScaleX_*=a,this.arcScaleY_*=b;var c=[[a,0,0],[0,b,0],[0,0,1]];U(this,w(c,this.m_),!0)},O.transform=function(a,b,c,d,e,f){var g=[[a,b,0],[c,d,0],[e,f,1]];U(this,w(g,this.m_),!0)},O.setTransform=function(a,b,c,d,e,f){var g=[[a,b,0],[c,d,0],[e,f,1]];U(this,g,!0)},O.drawText_=function(a,c,d,e,f){var h=this.m_,i=1e3,j=0,k=i,l={x:0,y:0},n=[],o=J(I(this.font),this.element_),p=K(o),q=this.element_.currentStyle,r=this.textAlign.toLowerCase();switch(r){case"left":case"center":case"right":break;case"end":r=q.direction=="ltr"?"right":"left";break;case"start":r=q.direction=="rtl"?"right":"left";break;default:r="left"}switch(this.textBaseline){case"hanging":case"top":l.y=o.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":l.y=-o.size/2.25}switch(r){case"right":j=i,k=.05;break;case"center":j=k=i/2}var s=S(this,c+l.x,d+l.y);n.push('<g_vml_:line from="',-j,' 0" to="',k,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!f,'" stroked="',!!f,'" style="position:absolute;width:1px;height:1px;">'),f?Q(this,n):R(this,n,{x:-j,y:0},{x:k,y:o.size});var t=h[0][0].toFixed(3)+","+h[1][0].toFixed(3)+","+h[0][1].toFixed(3)+","+h[1][1].toFixed(3)+",0,0",u=b(s.x/g)+","+b(s.y/g);n.push('<g_vml_:skew on="t" matrix="',t,'" ',' offset="',u,'" origin="',j,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',m(a),'" style="v-text-align:',r,";font:",m(p),'" /></g_vml_:line>'),this.element_.insertAdjacentHTML("beforeEnd",n.join(""))},O.fillText=function(a,b,c,d){this.drawText_(a,b,c,d,!1)},O.strokeText=function(a,b,c,d){this.drawText_(a,b,c,d,!0)},O.measureText=function(a){if(!this.textMeasureEl_){var b='<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",b),this.textMeasureEl_=this.element_.lastChild}var c=this.element_.ownerDocument;return this.textMeasureEl_.innerHTML="",this.textMeasureEl_.style.font=this.font,this.textMeasureEl_.appendChild(c.createTextNode(a)),{width:this.textMeasureEl_.offsetWidth}},O.clip=function(){},O.arcTo=function(){},O.createPattern=function(a,b){return new W(a,b)},V.prototype.addColorStop=function(a,b){b=F(b),this.colors_.push({offset:a,color:b.color,alpha:b.alpha})};var $=Z.prototype=new Error;$.INDEX_SIZE_ERR=1,$.DOMSTRING_SIZE_ERR=2,$.HIERARCHY_REQUEST_ERR=3,$.WRONG_DOCUMENT_ERR=4,$.INVALID_CHARACTER_ERR=5,$.NO_DATA_ALLOWED_ERR=6,$.NO_MODIFICATION_ALLOWED_ERR=7,$.NOT_FOUND_ERR=8,$.NOT_SUPPORTED_ERR=9,$.INUSE_ATTRIBUTE_ERR=10,$.INVALID_STATE_ERR=11,$.SYNTAX_ERR=12,$.INVALID_MODIFICATION_ERR=13,$.NAMESPACE_ERR=14,$.INVALID_ACCESS_ERR=15,$.VALIDATION_ERR=16,$.TYPE_MISMATCH_ERR=17,G_vmlCanvasManager=p,CanvasRenderingContext2D=N,CanvasGradient=V,CanvasPattern=W,DOMException=Z}(),function(){function c(b){var c,d,e,f,g,h;e=b.length,d=0,c="";while(d<e){f=b.charCodeAt(d++)&255;if(d==e){c+=a.charAt(f>>2),c+=a.charAt((f&3)<<4),c+="==";break}g=b.charCodeAt(d++);if(d==e){c+=a.charAt(f>>2),c+=a.charAt((f&3)<<4|(g&240)>>4),c+=a.charAt((g&15)<<2),c+="=";break}h=b.charCodeAt(d++),c+=a.charAt(f>>2),c+=a.charAt((f&3)<<4|(g&240)>>4),c+=a.charAt((g&15)<<2|(h&192)>>6),c+=a.charAt(h&63)}return c}function d(a){var c,d,e,f,g,h,i;h=a.length,g=0,i="";while(g<h){do c=b[a.charCodeAt(g++)&255];while(g<h&&c==-1);if(c==-1)break;do d=b[a.charCodeAt(g++)&255];while(g<h&&d==-1);if(d==-1)break;i+=String.fromCharCode(c<<2|(d&48)>>4);do{e=a.charCodeAt(g++)&255;if(e==61)return i;e=b[e]}while(g<h&&e==-1);if(e==-1)break;i+=String.fromCharCode((d&15)<<4|(e&60)>>2);do{f=a.charCodeAt(g++)&255;if(f==61)return i;f=b[f]}while(g<h&&f==-1);if(f==-1)break;i+=String.fromCharCode((e&3)<<6|f)}return i}var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b=[-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];window.btoa||(window.btoa=c),window.atob||(window.atob=d)}();var CanvasText={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]]},"�":{diacritic:"`",letter:"a"},"�":{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"},"�":{diacritic:"`",letter:"A"},"�":{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:{"�":{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]]}},style:{size:8,font:null,color:"#000000",weight:1,textAlign:"left",textBaseline:"bottom",adjustAlign:!1,angle:0,tracking:1,boundingBoxColor:"#ff0000",originPointColor:"#000000"},debug:!1,_bufferLexemes:{},extend:function(a,b){for(var c in b){if(c in a)continue;a[c]=b[c]}return a},letter:function(a){return CanvasText.letters[a]},parseLexemes:function(a){if(CanvasText._bufferLexemes[a])return CanvasText._bufferLexemes[a];var b,c,d=a.match(/&[A-Za-z]{2,5};|\s|./g),e=[],f=[];for(b=0;b<d.length;b++){c=d[b];if(c.length==1)f.push(c);else{var g=c.substring(1,c.length-1);CanvasText.specialchars[g]?f.push(g):f=f.concat(c.toArray())}}for(b=0;b<f.length;b++)c=f[b],(c=CanvasText.letters[c]||CanvasText.specialchars[c])&&e.push(c);for(b=0;b<e.length;b++)(e===null||typeof e=="undefined")&&delete e[b];return CanvasText._bufferLexemes[a]=e},ascent:function(a){return a=a||CanvasText.style,a.size||CanvasText.style.size},descent:function(a){return a=a||CanvasText.style,7*(a.size||CanvasText.style.size)/25},measure:function(a,b){if(!a)return;b=b||CanvasText.style;var d,e,f=CanvasText.parseLexemes(a),g=0;for(d=f.length-1;d>-1;--d)c=f[d],e=c.diacritic?CanvasText.letter(c.letter).width:c.width,g+=e*(b.tracking||CanvasText.style.tracking)*(b.size||CanvasText.style.size)/25;return g},getDimensions:function(a,b){b=b||CanvasText.style;var c=CanvasText.measure(a,b),d=b.size||CanvasText.style.size,e=b.angle||CanvasText.style.angle;return b.angle==0?{width:c,height:d}:{width:Math.abs(Math.cos(e)*c)+Math.abs(Math.sin(e)*d),height:Math.abs(Math.sin(e)*c)+Math.abs(Math.cos(e)*d)}},drawPoints:function(a,b,c,d,e,f){var g,h,i=!0,j=0;f=f||{x:0,y:0},a.beginPath();for(g=0;g<b.length;g++){h=b[g];if(!h){i=!0;continue}i?(a.moveTo(c+h[0]*e+f.x,d-h[1]*e+f.y),i=!1):a.lineTo(c+h[0]*e+f.x,d-h[1]*e+f.y)}a.stroke(),a.closePath()},draw:function(a,b,c,d){if(!a)return;CanvasText.extend(d,CanvasText.style);var e,f,g=0,h=d.size/25,i=0,j=0,k=CanvasText.parseLexemes(a),l={x:0,y:0},m=CanvasText.measure(a,d),n;d.adjustAlign&&(n=CanvasText.getBestAlign(d.angle,d),CanvasText.extend(d,n));switch(d.textAlign){case"left":break;case"center":l.x=-m/2;break;case"right":l.x=-m}switch(d.textBaseline){case"bottom":break;case"middle":l.y=d.size/2;break;case"top":l.y=d.size}this.save(),this.translate(b,c),this.rotate(d.angle),this.lineCap="round",this.lineWidth=2*h*(d.weight||CanvasText.style.weight),this.strokeStyle=d.color||CanvasText.style.color;for(e=0;e<k.length;e++){f=k[e];if(f.width==-1){i=0,j=d.size*1.4;continue}var o=f.points,p=f.width;if(f.diacritic){var q=CanvasText.diacritics[f.diacritic],r=CanvasText.letter(f.letter);CanvasText.drawPoints(this,q.points,i,j-(f.letter.toUpperCase()==f.letter?3:0),h,l),o=r.points,p=r.width}CanvasText.drawPoints(this,o,i,j,h,l),CanvasText.debug&&(this.save(),this.lineJoin="miter",this.lineWidth=.5,this.strokeStyle=d.boundingBoxColor||CanvasText.style.boundingBoxColor,this.strokeRect(i+l.x,j+l.y,p*h,-d.size),this.fillStyle=d.originPointColor||CanvasText.style.originPointColor,this.beginPath(),this.arc(0,0,1.5,0,Math.PI*2,!0),this.fill(),this.closePath(),this.restore()),i+=p*h*(d.tracking||CanvasText.style.tracking)}return this.restore(),g}};CanvasText.proto=window.CanvasRenderingContext2D?window.CanvasRenderingContext2D.prototype:document.createElement("canvas").getContext("2d").__proto__,CanvasText.proto&&(CanvasText.proto.drawText=CanvasText.draw,CanvasText.proto.measure=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/addons/web_graph/static/lib/flotr2/flotr2.js b/addons/web_graph/static/lib/flotr2/flotr2.js
deleted file mode 100644
index 8431b4d9ee9..00000000000
--- a/addons/web_graph/static/lib/flotr2/flotr2.js
+++ /dev/null
@@ -1,6865 +0,0 @@
-/*!
- * bean.js - copyright Jacob Thornton 2011
- * https://github.com/fat/bean
- * MIT License
- * special thanks to:
- * dean edwards: http://dean.edwards.name/
- * dperini: https://github.com/dperini/nwevents
- * the entire mootools team: github.com/mootools/mootools-core
- */
-/*global module:true, define:true*/
-!function (name, context, definition) {
- if (typeof module !== 'undefined') module.exports = definition(name, context);
- else if (typeof define === 'function' && typeof define.amd === 'object') define(definition);
- else context[name] = definition(name, context);
-}('bean', this, function (name, context) {
- var win = window
- , old = context[name]
- , overOut = /over|out/
- , namespaceRegex = /[^\.]*(?=\..*)\.|.*/
- , nameRegex = /\..*/
- , addEvent = 'addEventListener'
- , attachEvent = 'attachEvent'
- , removeEvent = 'removeEventListener'
- , detachEvent = 'detachEvent'
- , doc = document || {}
- , root = doc.documentElement || {}
- , W3C_MODEL = root[addEvent]
- , eventSupport = W3C_MODEL ? addEvent : attachEvent
- , slice = Array.prototype.slice
- , mouseTypeRegex = /click|mouse|menu|drag|drop/i
- , touchTypeRegex = /^touch|^gesture/i
- , ONE = { one: 1 } // singleton for quick matching making add() do one()
-
- , nativeEvents = (function (hash, events, i) {
- for (i = 0; i < events.length; i++)
- hash[events[i]] = 1
- return hash
- })({}, (
- 'click dblclick mouseup mousedown contextmenu ' + // mouse buttons
- 'mousewheel DOMMouseScroll ' + // mouse wheel
- 'mouseover mouseout mousemove selectstart selectend ' + // mouse movement
- 'keydown keypress keyup ' + // keyboard
- 'orientationchange ' + // mobile
- 'focus blur change reset select submit ' + // form elements
- 'load unload beforeunload resize move DOMContentLoaded readystatechange ' + // window
- 'error abort scroll ' + // misc
- (W3C_MODEL ? // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event
- // that doesn't actually exist, so make sure we only do these on newer browsers
- 'show ' + // mouse buttons
- 'input invalid ' + // form elements
- 'touchstart touchmove touchend touchcancel ' + // touch
- 'gesturestart gesturechange gestureend ' + // gesture
- 'message readystatechange pageshow pagehide popstate ' + // window
- 'hashchange offline online ' + // window
- 'afterprint beforeprint ' + // printing
- 'dragstart dragenter dragover dragleave drag drop dragend ' + // dnd
- 'loadstart progress suspend emptied stalled loadmetadata ' + // media
- 'loadeddata canplay canplaythrough playing waiting seeking ' + // media
- 'seeked ended durationchange timeupdate play pause ratechange ' + // media
- 'volumechange cuechange ' + // media
- 'checking noupdate downloading cached updateready obsolete ' + // appcache
- '' : '')
- ).split(' ')
- )
-
- , customEvents = (function () {
- function isDescendant(parent, node) {
- while ((node = node.parentNode) !== null) {
- if (node === parent) return true
- }
- return false
- }
-
- function check(event) {
- var related = event.relatedTarget
- if (!related) return related === null
- return (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isDescendant(this, related))
- }
-
- return {
- mouseenter: { base: 'mouseover', condition: check }
- , mouseleave: { base: 'mouseout', condition: check }
- , mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' }
- }
- })()
-
- , fixEvent = (function () {
- var commonProps = 'altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which'.split(' ')
- , mouseProps = commonProps.concat('button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement'.split(' '))
- , keyProps = commonProps.concat('char charCode key keyCode'.split(' '))
- , touchProps = commonProps.concat('touches targetTouches changedTouches scale rotation'.split(' '))
- , preventDefault = 'preventDefault'
- , createPreventDefault = function (event) {
- return function () {
- if (event[preventDefault])
- event[preventDefault]()
- else
- event.returnValue = false
- }
- }
- , stopPropagation = 'stopPropagation'
- , createStopPropagation = function (event) {
- return function () {
- if (event[stopPropagation])
- event[stopPropagation]()
- else
- event.cancelBubble = true
- }
- }
- , createStop = function (synEvent) {
- return function () {
- synEvent[preventDefault]()
- synEvent[stopPropagation]()
- synEvent.stopped = true
- }
- }
- , copyProps = function (event, result, props) {
- var i, p
- for (i = props.length; i--;) {
- p = props[i]
- if (!(p in result) && p in event) result[p] = event[p]
- }
- }
-
- return function (event, isNative) {
- var result = { originalEvent: event, isNative: isNative }
- if (!event)
- return result
-
- var props
- , type = event.type
- , target = event.target || event.srcElement
-
- result[preventDefault] = createPreventDefault(event)
- result[stopPropagation] = createStopPropagation(event)
- result.stop = createStop(result)
- result.target = target && target.nodeType === 3 ? target.parentNode : target
-
- if (isNative) { // we only need basic augmentation on custom events, the rest is too expensive
- if (type.indexOf('key') !== -1) {
- props = keyProps
- result.keyCode = event.which || event.keyCode
- } else if (mouseTypeRegex.test(type)) {
- props = mouseProps
- result.rightClick = event.which === 3 || event.button === 2
- result.pos = { x: 0, y: 0 }
- if (event.pageX || event.pageY) {
- result.clientX = event.pageX
- result.clientY = event.pageY
- } else if (event.clientX || event.clientY) {
- result.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft
- result.clientY = event.clientY + doc.body.scrollTop + root.scrollTop
- }
- if (overOut.test(type))
- result.relatedTarget = event.relatedTarget || event[(type === 'mouseover' ? 'from' : 'to') + 'Element']
- } else if (touchTypeRegex.test(type)) {
- props = touchProps
- }
- copyProps(event, result, props || commonProps)
- }
- return result
- }
- })()
-
- // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both
- , targetElement = function (element, isNative) {
- return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element
- }
-
- // we use one of these per listener, of any type
- , RegEntry = (function () {
- function entry(element, type, handler, original, namespaces) {
- this.element = element
- this.type = type
- this.handler = handler
- this.original = original
- this.namespaces = namespaces
- this.custom = customEvents[type]
- this.isNative = nativeEvents[type] && element[eventSupport]
- this.eventType = W3C_MODEL || this.isNative ? type : 'propertychange'
- this.customType = !W3C_MODEL && !this.isNative && type
- this.target = targetElement(element, this.isNative)
- this.eventSupport = this.target[eventSupport]
- }
-
- entry.prototype = {
- // given a list of namespaces, is our entry in any of them?
- inNamespaces: function (checkNamespaces) {
- var i, j
- if (!checkNamespaces)
- return true
- if (!this.namespaces)
- return false
- for (i = checkNamespaces.length; i--;) {
- for (j = this.namespaces.length; j--;) {
- if (checkNamespaces[i] === this.namespaces[j])
- return true
- }
- }
- return false
- }
-
- // match by element, original fn (opt), handler fn (opt)
- , matches: function (checkElement, checkOriginal, checkHandler) {
- return this.element === checkElement &&
- (!checkOriginal || this.original === checkOriginal) &&
- (!checkHandler || this.handler === checkHandler)
- }
- }
-
- return entry
- })()
-
- , registry = (function () {
- // our map stores arrays by event type, just because it's better than storing
- // everything in a single array. uses '$' as a prefix for the keys for safety
- var map = {}
-
- // generic functional search of our registry for matching listeners,
- // `fn` returns false to break out of the loop
- , forAll = function (element, type, original, handler, fn) {
- if (!type || type === '*') {
- // search the whole registry
- for (var t in map) {
- if (t.charAt(0) === '$')
- forAll(element, t.substr(1), original, handler, fn)
- }
- } else {
- var i = 0, l, list = map['$' + type], all = element === '*'
- if (!list)
- return
- for (l = list.length; i < l; i++) {
- if (all || list[i].matches(element, original, handler))
- if (!fn(list[i], list, i, type))
- return
- }
- }
- }
-
- , has = function (element, type, original) {
- // we're not using forAll here simply because it's a bit slower and this
- // needs to be fast
- var i, list = map['$' + type]
- if (list) {
- for (i = list.length; i--;) {
- if (list[i].matches(element, original, null))
- return true
- }
- }
- return false
- }
-
- , get = function (element, type, original) {
- var entries = []
- forAll(element, type, original, null, function (entry) { return entries.push(entry) })
- return entries
- }
-
- , put = function (entry) {
- (map['$' + entry.type] || (map['$' + entry.type] = [])).push(entry)
- return entry
- }
-
- , del = function (entry) {
- forAll(entry.element, entry.type, null, entry.handler, function (entry, list, i) {
- list.splice(i, 1)
- if (list.length === 0)
- delete map['$' + entry.type]
- return false
- })
- }
-
- // dump all entries, used for onunload
- , entries = function () {
- var t, entries = []
- for (t in map) {
- if (t.charAt(0) === '$')
- entries = entries.concat(map[t])
- }
- return entries
- }
-
- return { has: has, get: get, put: put, del: del, entries: entries }
- })()
-
- // add and remove listeners to DOM elements
- , listener = W3C_MODEL ? function (element, type, fn, add) {
- element[add ? addEvent : removeEvent](type, fn, false)
- } : function (element, type, fn, add, custom) {
- if (custom && add && element['_on' + custom] === null)
- element['_on' + custom] = 0
- element[add ? attachEvent : detachEvent]('on' + type, fn)
- }
-
- , nativeHandler = function (element, fn, args) {
- return function (event) {
- event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, true)
- return fn.apply(element, [event].concat(args))
- }
- }
-
- , customHandler = function (element, fn, type, condition, args, isNative) {
- return function (event) {
- if (condition ? condition.apply(this, arguments) : W3C_MODEL ? true : event && event.propertyName === '_on' + type || !event) {
- if (event)
- event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, isNative)
- fn.apply(element, event && (!args || args.length === 0) ? arguments : slice.call(arguments, event ? 0 : 1).concat(args))
- }
- }
- }
-
- , once = function (rm, element, type, fn, originalFn) {
- // wrap the handler in a handler that does a remove as well
- return function () {
- rm(element, type, originalFn)
- fn.apply(this, arguments)
- }
- }
-
- , removeListener = function (element, orgType, handler, namespaces) {
- var i, l, entry
- , type = (orgType && orgType.replace(nameRegex, ''))
- , handlers = registry.get(element, type, handler)
-
- for (i = 0, l = handlers.length; i < l; i++) {
- if (handlers[i].inNamespaces(namespaces)) {
- if ((entry = handlers[i]).eventSupport)
- listener(entry.target, entry.eventType, entry.handler, false, entry.type)
- // TODO: this is problematic, we have a registry.get() and registry.del() that
- // both do registry searches so we waste cycles doing this. Needs to be rolled into
- // a single registry.forAll(fn) that removes while finding, but the catch is that
- // we'll be splicing the arrays that we're iterating over. Needs extra tests to
- // make sure we don't screw it up. @rvagg
- registry.del(entry)
- }
- }
- }
-
- , addListener = function (element, orgType, fn, originalFn, args) {
- var entry
- , type = orgType.replace(nameRegex, '')
- , namespaces = orgType.replace(namespaceRegex, '').split('.')
-
- if (registry.has(element, type, fn))
- return element // no dupe
- if (type === 'unload')
- fn = once(removeListener, element, type, fn, originalFn) // self clean-up
- if (customEvents[type]) {
- if (customEvents[type].condition)
- fn = customHandler(element, fn, type, customEvents[type].condition, true)
- type = customEvents[type].base || type
- }
- entry = registry.put(new RegEntry(element, type, fn, originalFn, namespaces[0] && namespaces))
- entry.handler = entry.isNative ?
- nativeHandler(element, entry.handler, args) :
- customHandler(element, entry.handler, type, false, args, false)
- if (entry.eventSupport)
- listener(entry.target, entry.eventType, entry.handler, true, entry.customType)
- }
-
- , del = function (selector, fn, $) {
- return function (e) {
- var target, i, array = typeof selector === 'string' ? $(selector, this) : selector
- for (target = e.target; target && target !== this; target = target.parentNode) {
- for (i = array.length; i--;) {
- if (array[i] === target) {
- return fn.apply(target, arguments)
- }
- }
- }
- }
- }
-
- , remove = function (element, typeSpec, fn) {
- var k, m, type, namespaces, i
- , rm = removeListener
- , isString = typeSpec && typeof typeSpec === 'string'
-
- if (isString && typeSpec.indexOf(' ') > 0) {
- // remove(el, 't1 t2 t3', fn) or remove(el, 't1 t2 t3')
- typeSpec = typeSpec.split(' ')
- for (i = typeSpec.length; i--;)
- remove(element, typeSpec[i], fn)
- return element
- }
- type = isString && typeSpec.replace(nameRegex, '')
- if (type && customEvents[type])
- type = customEvents[type].type
- if (!typeSpec || isString) {
- // remove(el) or remove(el, t1.ns) or remove(el, .ns) or remove(el, .ns1.ns2.ns3)
- if (namespaces = isString && typeSpec.replace(namespaceRegex, ''))
- namespaces = namespaces.split('.')
- rm(element, type, fn, namespaces)
- } else if (typeof typeSpec === 'function') {
- // remove(el, fn)
- rm(element, null, typeSpec)
- } else {
- // remove(el, { t1: fn1, t2, fn2 })
- for (k in typeSpec) {
- if (typeSpec.hasOwnProperty(k))
- remove(element, k, typeSpec[k])
- }
- }
- return element
- }
-
- , add = function (element, events, fn, delfn, $) {
- var type, types, i, args
- , originalFn = fn
- , isDel = fn && typeof fn === 'string'
-
- if (events && !fn && typeof events === 'object') {
- for (type in events) {
- if (events.hasOwnProperty(type))
- add.apply(this, [ element, type, events[type] ])
- }
- } else {
- args = arguments.length > 3 ? slice.call(arguments, 3) : []
- types = (isDel ? fn : events).split(' ')
- isDel && (fn = del(events, (originalFn = delfn), $)) && (args = slice.call(args, 1))
- // special case for one()
- this === ONE && (fn = once(remove, element, events, fn, originalFn))
- for (i = types.length; i--;) addListener(element, types[i], fn, originalFn, args)
- }
- return element
- }
-
- , one = function () {
- return add.apply(ONE, arguments)
- }
-
- , fireListener = W3C_MODEL ? function (isNative, type, element) {
- var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents')
- evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1)
- element.dispatchEvent(evt)
- } : function (isNative, type, element) {
- element = targetElement(element, isNative)
- // if not-native then we're using onpropertychange so we just increment a custom property
- isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++
- }
-
- , fire = function (element, type, args) {
- var i, j, l, names, handlers
- , types = type.split(' ')
-
- for (i = types.length; i--;) {
- type = types[i].replace(nameRegex, '')
- if (names = types[i].replace(namespaceRegex, ''))
- names = names.split('.')
- if (!names && !args && element[eventSupport]) {
- fireListener(nativeEvents[type], type, element)
- } else {
- // non-native event, either because of a namespace, arguments or a non DOM element
- // iterate over all listeners and manually 'fire'
- handlers = registry.get(element, type)
- args = [false].concat(args)
- for (j = 0, l = handlers.length; j < l; j++) {
- if (handlers[j].inNamespaces(names))
- handlers[j].handler.apply(element, args)
- }
- }
- }
- return element
- }
-
- , clone = function (element, from, type) {
- var i = 0
- , handlers = registry.get(from, type)
- , l = handlers.length
-
- for (;i < l; i++)
- handlers[i].original && add(element, handlers[i].type, handlers[i].original)
- return element
- }
-
- , bean = {
- add: add
- , one: one
- , remove: remove
- , clone: clone
- , fire: fire
- , noConflict: function () {
- context[name] = old
- return this
- }
- }
-
- if (win[attachEvent]) {
- // for IE, clean up on unload to avoid leaks
- var cleanup = function () {
- var i, entries = registry.entries()
- for (i in entries) {
- if (entries[i].type && entries[i].type !== 'unload')
- remove(entries[i].element, entries[i].type)
- }
- win[detachEvent]('onunload', cleanup)
- win.CollectGarbage && win.CollectGarbage()
- }
- win[attachEvent]('onunload', cleanup)
- }
-
- return bean
-});
-// Underscore.js 1.1.7
-// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore is freely distributable under the MIT license.
-// Portions of Underscore are inspired or borrowed from Prototype,
-// Oliver Steele's Functional, and John Resig's Micro-Templating.
-// For all details and documentation:
-// http://documentcloud.github.com/underscore
-
-(function() {
-
- // Baseline setup
- // --------------
-
- // Establish the root object, `window` in the browser, or `global` on the server.
- var root = this;
-
- // Save the previous value of the `_` variable.
- var previousUnderscore = root._;
-
- // Establish the object that gets returned to break out of a loop iteration.
- var breaker = {};
-
- // Save bytes in the minified (but not gzipped) version:
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
-
- // Create quick reference variables for speed access to core prototypes.
- var slice = ArrayProto.slice,
- unshift = ArrayProto.unshift,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty;
-
- // All **ECMAScript 5** native function implementations that we hope to use
- // are declared here.
- var
- nativeForEach = ArrayProto.forEach,
- nativeMap = ArrayProto.map,
- nativeReduce = ArrayProto.reduce,
- nativeReduceRight = ArrayProto.reduceRight,
- nativeFilter = ArrayProto.filter,
- nativeEvery = ArrayProto.every,
- nativeSome = ArrayProto.some,
- nativeIndexOf = ArrayProto.indexOf,
- nativeLastIndexOf = ArrayProto.lastIndexOf,
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind;
-
- // Create a safe reference to the Underscore object for use below.
- var _ = function(obj) { return new wrapper(obj); };
-
- // Export the Underscore object for **CommonJS**, with backwards-compatibility
- // for the old `require()` API. If we're not in CommonJS, add `_` to the
- // global object.
- if (typeof module !== 'undefined' && module.exports) {
- module.exports = _;
- _._ = _;
- } else {
- // Exported as a string, for Closure Compiler "advanced" mode.
- root['_'] = _;
- }
-
- // Current version.
- _.VERSION = '1.1.7';
-
- // Collection Functions
- // --------------------
-
- // The cornerstone, an `each` implementation, aka `forEach`.
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
- var each = _.each = _.forEach = function(obj, iterator, context) {
- if (obj == null) return;
- if (nativeForEach && obj.forEach === nativeForEach) {
- obj.forEach(iterator, context);
- } else if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
- }
- } else {
- for (var key in obj) {
- if (hasOwnProperty.call(obj, key)) {
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
- }
- }
- }
- };
-
- // Return the results of applying the iterator to each element.
- // Delegates to **ECMAScript 5**'s native `map` if available.
- _.map = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
- each(obj, function(value, index, list) {
- results[results.length] = iterator.call(context, value, index, list);
- });
- return results;
- };
-
- // **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
- var initial = memo !== void 0;
- if (obj == null) obj = [];
- if (nativeReduce && obj.reduce === nativeReduce) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
- }
- each(obj, function(value, index, list) {
- if (!initial) {
- memo = value;
- initial = true;
- } else {
- memo = iterator.call(context, memo, value, index, list);
- }
- });
- if (!initial) throw new TypeError("Reduce of empty array with no initial value");
- return memo;
- };
-
- // The right-associative version of reduce, also known as `foldr`.
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
- if (obj == null) obj = [];
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
- if (context) iterator = _.bind(iterator, context);
- return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
- }
- var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
- return _.reduce(reversed, iterator, memo, context);
- };
-
- // Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, iterator, context) {
- var result;
- any(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) {
- result = value;
- return true;
- }
- });
- return result;
- };
-
- // Return all the elements that pass a truth test.
- // Delegates to **ECMAScript 5**'s native `filter` if available.
- // Aliased as `select`.
- _.filter = _.select = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
- each(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
-
- // Return all the elements for which a truth test fails.
- _.reject = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- each(obj, function(value, index, list) {
- if (!iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
-
- // Determine whether all of the elements match a truth test.
- // Delegates to **ECMAScript 5**'s native `every` if available.
- // Aliased as `all`.
- _.every = _.all = function(obj, iterator, context) {
- var result = true;
- if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
- each(obj, function(value, index, list) {
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
- });
- return result;
- };
-
- // Determine if at least one element in the object matches a truth test.
- // Delegates to **ECMAScript 5**'s native `some` if available.
- // Aliased as `any`.
- var any = _.some = _.any = function(obj, iterator, context) {
- iterator = iterator || _.identity;
- var result = false;
- if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
- each(obj, function(value, index, list) {
- if (result |= iterator.call(context, value, index, list)) return breaker;
- });
- return !!result;
- };
-
- // Determine if a given value is included in the array or object using `===`.
- // Aliased as `contains`.
- _.include = _.contains = function(obj, target) {
- var found = false;
- if (obj == null) return found;
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
- any(obj, function(value) {
- if (found = value === target) return true;
- });
- return found;
- };
-
- // Invoke a method (with arguments) on every item in a collection.
- _.invoke = function(obj, method) {
- var args = slice.call(arguments, 2);
- return _.map(obj, function(value) {
- return (method.call ? method || value : value[method]).apply(value, args);
- });
- };
-
- // Convenience version of a common use case of `map`: fetching a property.
- _.pluck = function(obj, key) {
- return _.map(obj, function(value){ return value[key]; });
- };
-
- // Return the maximum element or (element-based computation).
- _.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
- var result = {computed : -Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed >= result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Return the minimum element (or element-based computation).
- _.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
- var result = {computed : Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed < result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, iterator, context) {
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value : value,
- criteria : iterator.call(context, value, index, list)
- };
- }).sort(function(left, right) {
- var a = left.criteria, b = right.criteria;
- return a < b ? -1 : a > b ? 1 : 0;
- }), 'value');
- };
-
- // Groups the object's values by a criterion produced by an iterator
- _.groupBy = function(obj, iterator) {
- var result = {};
- each(obj, function(value, index) {
- var key = iterator(value, index);
- (result[key] || (result[key] = [])).push(value);
- });
- return result;
- };
-
- // Use a comparator function to figure out at what index an object should
- // be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iterator) {
- iterator || (iterator = _.identity);
- var low = 0, high = array.length;
- while (low < high) {
- var mid = (low + high) >> 1;
- iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
- }
- return low;
- };
-
- // Safely convert anything iterable into a real, live array.
- _.toArray = function(iterable) {
- if (!iterable) return [];
- if (iterable.toArray) return iterable.toArray();
- if (_.isArray(iterable)) return slice.call(iterable);
- if (_.isArguments(iterable)) return slice.call(iterable);
- return _.values(iterable);
- };
-
- // Return the number of elements in an object.
- _.size = function(obj) {
- return _.toArray(obj).length;
- };
-
- // Array Functions
- // ---------------
-
- // Get the first element of an array. Passing **n** will return the first N
- // values in the array. Aliased as `head`. The **guard** check allows it to work
- // with `_.map`.
- _.first = _.head = function(array, n, guard) {
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
- };
-
- // Returns everything but the first entry of the array. Aliased as `tail`.
- // Especially useful on the arguments object. Passing an **index** will return
- // the rest of the values in the array from that index onward. The **guard**
- // check allows it to work with `_.map`.
- _.rest = _.tail = function(array, index, guard) {
- return slice.call(array, (index == null) || guard ? 1 : index);
- };
-
- // Get the last element of an array.
- _.last = function(array) {
- return array[array.length - 1];
- };
-
- // Trim out all falsy values from an array.
- _.compact = function(array) {
- return _.filter(array, function(value){ return !!value; });
- };
-
- // Return a completely flattened version of an array.
- _.flatten = function(array) {
- return _.reduce(array, function(memo, value) {
- if (_.isArray(value)) return memo.concat(_.flatten(value));
- memo[memo.length] = value;
- return memo;
- }, []);
- };
-
- // Return a version of the array that does not contain the specified value(s).
- _.without = function(array) {
- return _.difference(array, slice.call(arguments, 1));
- };
-
- // Produce a duplicate-free version of the array. If the array has already
- // been sorted, you have the option of using a faster algorithm.
- // Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted) {
- return _.reduce(array, function(memo, el, i) {
- if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
- return memo;
- }, []);
- };
-
- // Produce an array that contains the union: each distinct element from all of
- // the passed-in arrays.
- _.union = function() {
- return _.uniq(_.flatten(arguments));
- };
-
- // Produce an array that contains every item shared between all the
- // passed-in arrays. (Aliased as "intersect" for back-compat.)
- _.intersection = _.intersect = function(array) {
- var rest = slice.call(arguments, 1);
- return _.filter(_.uniq(array), function(item) {
- return _.every(rest, function(other) {
- return _.indexOf(other, item) >= 0;
- });
- });
- };
-
- // Take the difference between one array and another.
- // Only the elements present in just the first array will remain.
- _.difference = function(array, other) {
- return _.filter(array, function(value){ return !_.include(other, value); });
- };
-
- // Zip together multiple lists into a single array -- elements that share
- // an index go together.
- _.zip = function() {
- var args = slice.call(arguments);
- var length = _.max(_.pluck(args, 'length'));
- var results = new Array(length);
- for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
- return results;
- };
-
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
- // we need this function. Return the position of the first occurrence of an
- // item in an array, or -1 if the item is not included in the array.
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
- // If the array is large and already in sort order, pass `true`
- // for **isSorted** to use binary search.
- _.indexOf = function(array, item, isSorted) {
- if (array == null) return -1;
- var i, l;
- if (isSorted) {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
- for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
- return -1;
- };
-
-
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
- _.lastIndexOf = function(array, item) {
- if (array == null) return -1;
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
- var i = array.length;
- while (i--) if (array[i] === item) return i;
- return -1;
- };
-
- // Generate an integer Array containing an arithmetic progression. A port of
- // the native Python `range()` function. See
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
- _.range = function(start, stop, step) {
- if (arguments.length <= 1) {
- stop = start || 0;
- start = 0;
- }
- step = arguments[2] || 1;
-
- var len = Math.max(Math.ceil((stop - start) / step), 0);
- var idx = 0;
- var range = new Array(len);
-
- while(idx < len) {
- range[idx++] = start;
- start += step;
- }
-
- return range;
- };
-
- // Function (ahem) Functions
- // ------------------
-
- // Create a function bound to a given object (assigning `this`, and arguments,
- // optionally). Binding with arguments is also known as `curry`.
- // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
- // We check for `func.bind` first, to fail fast when `func` is undefined.
- _.bind = function(func, obj) {
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- var args = slice.call(arguments, 2);
- return function() {
- return func.apply(obj, args.concat(slice.call(arguments)));
- };
- };
-
- // Bind all of an object's methods to that object. Useful for ensuring that
- // all callbacks defined on an object belong to it.
- _.bindAll = function(obj) {
- var funcs = slice.call(arguments, 1);
- if (funcs.length == 0) funcs = _.functions(obj);
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
- return obj;
- };
-
- // Memoize an expensive function by storing its results.
- _.memoize = function(func, hasher) {
- var memo = {};
- hasher || (hasher = _.identity);
- return function() {
- var key = hasher.apply(this, arguments);
- return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
- };
- };
-
- // Delays a function for the given number of milliseconds, and then calls
- // it with the arguments supplied.
- _.delay = function(func, wait) {
- var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(func, args); }, wait);
- };
-
- // Defers a function, scheduling it to run after the current call stack has
- // cleared.
- _.defer = function(func) {
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
- };
-
- // Internal function used to implement `_.throttle` and `_.debounce`.
- var limit = function(func, wait, debounce) {
- var timeout;
- return function() {
- var context = this, args = arguments;
- var throttler = function() {
- timeout = null;
- func.apply(context, args);
- };
- if (debounce) clearTimeout(timeout);
- if (debounce || !timeout) timeout = setTimeout(throttler, wait);
- };
- };
-
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time.
- _.throttle = function(func, wait) {
- return limit(func, wait, false);
- };
-
- // Returns a function, that, as long as it continues to be invoked, will not
- // be triggered. The function will be called after it stops being called for
- // N milliseconds.
- _.debounce = function(func, wait) {
- return limit(func, wait, true);
- };
-
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- return memo = func.apply(this, arguments);
- };
- };
-
- // Returns the first function passed as an argument to the second,
- // allowing you to adjust arguments, run code before and after, and
- // conditionally execute the original function.
- _.wrap = function(func, wrapper) {
- return function() {
- var args = [func].concat(slice.call(arguments));
- return wrapper.apply(this, args);
- };
- };
-
- // Returns a function that is the composition of a list of functions, each
- // consuming the return value of the function that follows.
- _.compose = function() {
- var funcs = slice.call(arguments);
- return function() {
- var args = slice.call(arguments);
- for (var i = funcs.length - 1; i >= 0; i--) {
- args = [funcs[i].apply(this, args)];
- }
- return args[0];
- };
- };
-
- // Returns a function that will only be executed after being called N times.
- _.after = function(times, func) {
- return function() {
- if (--times < 1) { return func.apply(this, arguments); }
- };
- };
-
-
- // Object Functions
- // ----------------
-
- // Retrieve the names of an object's properties.
- // Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = nativeKeys || function(obj) {
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
- var keys = [];
- for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
- return keys;
- };
-
- // Retrieve the values of an object's properties.
- _.values = function(obj) {
- return _.map(obj, _.identity);
- };
-
- // Return a sorted list of the function names available on the object.
- // Aliased as `methods`
- _.functions = _.methods = function(obj) {
- var names = [];
- for (var key in obj) {
- if (_.isFunction(obj[key])) names.push(key);
- }
- return names.sort();
- };
-
- // Extend a given object with all the properties in passed-in object(s).
- _.extend = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- if (source[prop] !== void 0) obj[prop] = source[prop];
- }
- });
- return obj;
- };
-
- // Fill in a given object with default properties.
- _.defaults = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- if (obj[prop] == null) obj[prop] = source[prop];
- }
- });
- return obj;
- };
-
- // Create a (shallow-cloned) duplicate of an object.
- _.clone = function(obj) {
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
- };
-
- // Invokes interceptor with the obj, and then returns obj.
- // The primary purpose of this method is to "tap into" a method chain, in
- // order to perform operations on intermediate results within the chain.
- _.tap = function(obj, interceptor) {
- interceptor(obj);
- return obj;
- };
-
- // Perform a deep comparison to check if two objects are equal.
- _.isEqual = function(a, b) {
- // Check object identity.
- if (a === b) return true;
- // Different types?
- var atype = typeof(a), btype = typeof(b);
- if (atype != btype) return false;
- // Basic equality test (watch out for coercions).
- if (a == b) return true;
- // One is falsy and the other truthy.
- if ((!a && b) || (a && !b)) return false;
- // Unwrap any wrapped objects.
- if (a._chain) a = a._wrapped;
- if (b._chain) b = b._wrapped;
- // One of them implements an isEqual()?
- if (a.isEqual) return a.isEqual(b);
- if (b.isEqual) return b.isEqual(a);
- // Check dates' integer values.
- if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
- // Both are NaN?
- if (_.isNaN(a) && _.isNaN(b)) return false;
- // Compare regular expressions.
- if (_.isRegExp(a) && _.isRegExp(b))
- return a.source === b.source &&
- a.global === b.global &&
- a.ignoreCase === b.ignoreCase &&
- a.multiline === b.multiline;
- // If a is not an object by this point, we can't handle it.
- if (atype !== 'object') return false;
- // Check for different array lengths before comparing contents.
- if (a.length && (a.length !== b.length)) return false;
- // Nothing else worked, deep compare the contents.
- var aKeys = _.keys(a), bKeys = _.keys(b);
- // Different object sizes?
- if (aKeys.length != bKeys.length) return false;
- // Recursive comparison of contents.
- for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
- return true;
- };
-
- // Is a given array or object empty?
- _.isEmpty = function(obj) {
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
- for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
- return true;
- };
-
- // Is a given value a DOM element?
- _.isElement = function(obj) {
- return !!(obj && obj.nodeType == 1);
- };
-
- // Is a given value an array?
- // Delegates to ECMA5's native Array.isArray
- _.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) === '[object Array]';
- };
-
- // Is a given variable an object?
- _.isObject = function(obj) {
- return obj === Object(obj);
- };
-
- // Is a given variable an arguments object?
- _.isArguments = function(obj) {
- return !!(obj && hasOwnProperty.call(obj, 'callee'));
- };
-
- // Is a given value a function?
- _.isFunction = function(obj) {
- return !!(obj && obj.constructor && obj.call && obj.apply);
- };
-
- // Is a given value a string?
- _.isString = function(obj) {
- return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
- };
-
- // Is a given value a number?
- _.isNumber = function(obj) {
- return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
- };
-
- // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
- // that does not equal itself.
- _.isNaN = function(obj) {
- return obj !== obj;
- };
-
- // Is a given value a boolean?
- _.isBoolean = function(obj) {
- return obj === true || obj === false;
- };
-
- // Is a given value a date?
- _.isDate = function(obj) {
- return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
- };
-
- // Is the given value a regular expression?
- _.isRegExp = function(obj) {
- return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
- };
-
- // Is a given value equal to null?
- _.isNull = function(obj) {
- return obj === null;
- };
-
- // Is a given variable undefined?
- _.isUndefined = function(obj) {
- return obj === void 0;
- };
-
- // Utility Functions
- // -----------------
-
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
- // previous owner. Returns a reference to the Underscore object.
- _.noConflict = function() {
- root._ = previousUnderscore;
- return this;
- };
-
- // Keep the identity function around for default iterators.
- _.identity = function(value) {
- return value;
- };
-
- // Run a function **n** times.
- _.times = function (n, iterator, context) {
- for (var i = 0; i < n; i++) iterator.call(context, i);
- };
-
- // Add your own custom functions to the Underscore object, ensuring that
- // they're correctly added to the OOP wrapper as well.
- _.mixin = function(obj) {
- each(_.functions(obj), function(name){
- addToWrapper(name, _[name] = obj[name]);
- });
- };
-
- // Generate a unique integer id (unique within the entire client session).
- // Useful for temporary DOM ids.
- var idCounter = 0;
- _.uniqueId = function(prefix) {
- var id = idCounter++;
- return prefix ? prefix + id : id;
- };
-
- // By default, Underscore uses ERB-style template delimiters, change the
- // following template settings to use alternative delimiters.
- _.templateSettings = {
- evaluate : /<%([\s\S]+?)%>/g,
- interpolate : /<%=([\s\S]+?)%>/g
- };
-
- // JavaScript micro-templating, similar to John Resig's implementation.
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
- // and correctly escapes quotes within interpolated code.
- _.template = function(str, data) {
- var c = _.templateSettings;
- var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
- 'with(obj||{}){__p.push(\'' +
- str.replace(/\\/g, '\\\\')
- .replace(/'/g, "\\'")
- .replace(c.interpolate, function(match, code) {
- return "'," + code.replace(/\\'/g, "'") + ",'";
- })
- .replace(c.evaluate || null, function(match, code) {
- return "');" + code.replace(/\\'/g, "'")
- .replace(/[\r\n\t]/g, ' ') + "__p.push('";
- })
- .replace(/\r/g, '\\r')
- .replace(/\n/g, '\\n')
- .replace(/\t/g, '\\t')
- + "');}return __p.join('');";
- var func = new Function('obj', tmpl);
- return data ? func(data) : func;
- };
-
- // The OOP Wrapper
- // ---------------
-
- // If Underscore is called as a function, it returns a wrapped object that
- // can be used OO-style. This wrapper holds altered versions of all the
- // underscore functions. Wrapped objects may be chained.
- var wrapper = function(obj) { this._wrapped = obj; };
-
- // Expose `wrapper.prototype` as `_.prototype`
- _.prototype = wrapper.prototype;
-
- // Helper function to continue chaining intermediate results.
- var result = function(obj, chain) {
- return chain ? _(obj).chain() : obj;
- };
-
- // A method to easily add functions to the OOP wrapper.
- var addToWrapper = function(name, func) {
- wrapper.prototype[name] = function() {
- var args = slice.call(arguments);
- unshift.call(args, this._wrapped);
- return result(func.apply(_, args), this._chain);
- };
- };
-
- // Add all of the Underscore functions to the wrapper object.
- _.mixin(_);
-
- // Add all mutator Array functions to the wrapper.
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
- var method = ArrayProto[name];
- wrapper.prototype[name] = function() {
- method.apply(this._wrapped, arguments);
- return result(this._wrapped, this._chain);
- };
- });
-
- // Add all accessor Array functions to the wrapper.
- each(['concat', 'join', 'slice'], function(name) {
- var method = ArrayProto[name];
- wrapper.prototype[name] = function() {
- return result(method.apply(this._wrapped, arguments), this._chain);
- };
- });
-
- // Start chaining a wrapped Underscore object.
- wrapper.prototype.chain = function() {
- this._chain = true;
- return this;
- };
-
- // Extracts the result from a wrapped and chained object.
- wrapper.prototype.value = function() {
- return this._wrapped;
- };
-
-})();
-/**
- * Flotr2 (c) 2012 Carl Sutherland
- * MIT License
- * Special thanks to:
- * Flotr: http://code.google.com/p/flotr/ (fork)
- * Flot: https://github.com/flot/flot (original fork)
- */
-(function () {
-
-var
- global = this,
- previousFlotr = this.Flotr,
- Flotr;
-
-Flotr = {
- _: _,
- bean: bean,
- isIphone: /iphone/i.test(navigator.userAgent),
- isIE: (navigator.appVersion.indexOf("MSIE") != -1 ? parseFloat(navigator.appVersion.split("MSIE")[1]) : false),
-
- /**
- * 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);
- },
-
- /**
- * 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
- * @TODO See if we can't remove this.
- */
- merge: function(src, dest){
- var i, v, result = dest || {};
-
- for (i in src) {
- v = src[i];
- if (v && typeof(v) === 'object') {
- if (v.constructor === Array) {
- result[i] = this._.clone(v);
- } else if (v.constructor !== RegExp && !this._.isElement(v)) {
- result[i] = Flotr.merge(v, (dest ? dest[i] : undefined));
- } else {
- result[i] = v;
- }
- } else {
- result[i] = v;
- }
- }
-
- return result;
- },
-
- /**
- * Recursively clones an object.
- * @param {Object} object - The object to clone
- * @return {Object} the clone
- * @TODO See if we can't remove this.
- */
- clone: function(object){
- return Flotr.merge(object, {});
- },
-
- /**
- * 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
- * @param {Object} axisOpts - the axis' options
- * @return {String} formatted tick string
- */
- defaultTickFormatter: function(val, axisOpts){
- 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);
- },
- drawText: function(ctx, text, x, y, style) {
- if (!ctx.fillText) {
- ctx.drawText(text, x, y, style);
- return;
- }
-
- style = this._.extend({
- size: Flotr.defaultOptions.fontSize,
- color: '#000000',
- textAlign: 'left',
- textBaseline: 'bottom',
- weight: 1,
- angle: 0
- }, style);
-
- ctx.save();
- ctx.translate(x, y);
- ctx.rotate(style.angle);
- ctx.fillStyle = style.color;
- ctx.font = (style.weight > 1 ? "bold " : "") + (style.size*1.3) + "px sans-serif";
- ctx.textAlign = style.textAlign;
- ctx.textBaseline = style.textBaseline;
- ctx.fillText(text, 0, 0);
- ctx.restore();
- },
- getBestTextAlign: function(angle, style) {
- style = style || {textAlign: 'center', textBaseline: 'middle'};
- angle += Flotr.getTextAngleFromAlign(style);
-
- if (Math.abs(Math.cos(angle)) > 10e-3)
- style.textAlign = (Math.cos(angle) > 0 ? 'right' : 'left');
-
- if (Math.abs(Math.sin(angle)) > 10e-3)
- style.textBaseline = (Math.sin(angle) > 0 ? 'top' : 'bottom');
-
- return style;
- },
- alignTable: {
- 'right middle' : 0,
- 'right top' : Math.PI/4,
- 'center top' : Math.PI/2,
- 'left top' : 3*(Math.PI/4),
- 'left middle' : Math.PI,
- 'left bottom' : -3*(Math.PI/4),
- 'center bottom': -Math.PI/2,
- 'right bottom' : -Math.PI/4,
- 'center middle': 0
- },
- getTextAngleFromAlign: function(style) {
- return Flotr.alignTable[style.textAlign+' '+style.textBaseline] || 0;
- },
- noConflict : function () {
- global.Flotr = previousFlotr;
- return this;
- }
-};
-
-global.Flotr = Flotr;
-
-})();
-
-/**
- * Flotr Defaults
- */
-Flotr.defaultOptions = {
- colors: ['#00A8F0', '#C0D800', '#CB4B4B', '#4DA74D', '#9440ED'], //=> The default colorscheme. When there are > 5 series, additional colors are generated.
- ieBackgroundColor: '#FFFFFF', // Background color for excanvas clipping
- 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
- fontColor: '#545454', // => default font color
- fontSize: 7.5, // => canvas' text font size
- resolution: 1, // => resolution of the graph, to have printer-friendly graphs !
- parseFloat: true, // => whether to preprocess data for floats (ie. if input is string)
- xaxis: {
- ticks: null, // => format: either [1, 3] or [[1, 'a'], 3]
- minorTicks: null, // => format: either [1, 3] or [[1, 'a'], 3]
- showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise
- showMinorLabels: false,// => true to show the axis minor ticks labels, false to hide
- 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
- minorTickFreq: null, // => number of minor ticks between major ticks for autogenerated ticks
- tickFormatter: Flotr.defaultTickFormatter, // => fn: number, Object -> 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
- autoscale: false, // => Turns autoscaling on with true
- 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,
- timeMode:'UTC', // => For UTC time ('local' for local time).
- timeUnit:'millisecond',// => Unit for time (millisecond, second, minute, hour, day, month, year)
- scaling: 'linear', // => Scaling, can be 'linear' or 'logarithmic'
- base: Math.E,
- titleAlign: 'center',
- margin: true // => Turn off margins with false
- },
- x2axis: {},
- yaxis: {
- ticks: null, // => format: either [1, 3] or [[1, 'a'], 3]
- minorTicks: null, // => format: either [1, 3] or [[1, 'a'], 3]
- showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise
- showMinorLabels: false,// => true to show the axis minor ticks labels, false to hide
- 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
- minorTickFreq: null, // => number of minor ticks between major ticks for autogenerated ticks
- tickFormatter: Flotr.defaultTickFormatter, // => fn: number, Object -> 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
- autoscale: false, // => Turns autoscaling on with true
- 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,
- titleAlign: 'center',
- margin: true // => Turn off margins with false
- },
- y2axis: {
- titleAngle: 270
- },
- grid: {
- color: '#545454', // => primary color used for outline and labels
- backgroundColor: null, // => null for transparent, else color
- backgroundImage: null, // => background image. String or object with src, left and top
- watermarkAlpha: 0.4, // =>
- tickColor: '#DDDDDD', // => color used for the ticks
- labelMargin: 3, // => margin in pixels
- verticalLines: true, // => whether to show gridlines in vertical direction
- minorVerticalLines: null, // => whether to show gridlines for minor ticks in vertical dir.
- horizontalLines: true, // => whether to show gridlines in horizontal direction
- minorHorizontalLines: null, // => whether to show gridlines for minor ticks in horizontal dir.
- outlineWidth: 1, // => width of the grid outline/border in pixels
- outline : 'nsew', // => walls of the outline to display
- circular: false // => if set to true, the grid will be circular, must be used when radars are drawn
- },
- mouse: {
- track: false, // => true to track the mouse, no tracking otherwise
- trackAll: false,
- 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
- trackY: true, // => whether or not to track the mouse in the y axis
- 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 Color
- */
-
-(function () {
-
-var
- _ = Flotr._;
-
-// Constructor
-function Color (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();
-}
-
-// Constants
-var 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]
-};
-
-Color.prototype = {
- scale: function(rf, gf, bf, af){
- var x = 4;
- while (-1 < --x) {
- if (!_.isUndefined(arguments[x])) this[this.rgba[x]] *= arguments[x];
- }
- return this.normalize();
- },
- alpha: function(alpha) {
- if (!_.isUndefined(alpha) && !_.isNull(alpha)) {
- this.a = alpha;
- }
- return this.normalize();
- },
- clone: function(){
- return new 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, 10), 0, 255);
- this.g = limit(parseInt(this.g, 10), 0, 255);
- this.b = limit(parseInt(this.b, 10), 0, 255);
- this.a = limit(this.a, 0, 1);
- return this;
- },
- distance: function(color){
- if (!color) return;
- color = new 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(',')+')';
- },
- contrast: function () {
- var
- test = 1 - ( 0.299 * this.r + 0.587 * this.g + 0.114 * this.b) / 255;
- return (test < 0.5 ? '#000000' : '#ffffff');
- }
-};
-
-_.extend(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 Color) return color;
-
- var result;
-
- // #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], 10), parseInt(result[2], 10), parseInt(result[3], 10));
-
- // #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], 10), parseInt(result[2], 10), parseInt(result[3], 10), 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+'').replace(/^\s*([\S\s]*?)\s*$/, '$1').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);
- },
-
- /**
- * Process color and options into color style.
- */
- processColor: function(color, options) {
-
- var opacity = options.opacity;
- if (!color) return 'rgba(0, 0, 0, 0)';
- if (color instanceof Color) return color.alpha(opacity).toString();
- if (_.isString(color)) return Color.parse(color).alpha(opacity).toString();
-
- var grad = color.colors ? color : {colors: color};
-
- if (!options.ctx) {
- if (!_.isArray(grad.colors)) return 'rgba(0, 0, 0, 0)';
- return Color.parse(_.isArray(grad.colors[0]) ? grad.colors[0][1] : grad.colors[0]).alpha(opacity).toString();
- }
- grad = _.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 (_.isArray(c)) {
- stop = c[0];
- c = c[1];
- }
- else stop = i / (grad.colors.length-1);
- gradient.addColorStop(stop, Color.parse(c).alpha(opacity));
- }
- return gradient;
- }
-});
-
-Flotr.Color = Color;
-
-})();
-
-/**
- * Flotr Date
- */
-Flotr.Date = {
-
- set : function (date, name, mode, value) {
- mode = mode || 'UTC';
- name = 'set' + (mode === 'UTC' ? 'UTC' : '') + name;
- date[name](value);
- },
-
- get : function (date, name, mode) {
- mode = mode || 'UTC';
- name = 'get' + (mode === 'UTC' ? 'UTC' : '') + name;
- return date[name]();
- },
-
- format: function(d, format, mode) {
- 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
- get = this.get,
- tokens = {
- h: get(d, 'Hours', mode).toString(),
- H: leftPad(get(d, 'Hours', mode)),
- M: leftPad(get(d, 'Minutes', mode)),
- S: leftPad(get(d, 'Seconds', mode)),
- s: get(d, 'Milliseconds', mode),
- d: get(d, 'Date', mode).toString(),
- m: (get(d, 'Month') + 1).toString(),
- y: get(d, 'FullYear').toString(),
- b: Flotr.Date.monthNames[get(d, 'Month', mode)]
- };
-
- 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
- options = axis.options,
- scale = Flotr.Date.timeUnits[options.timeUnit],
- d = new Date(v * scale);
-
- // first check global format
- if (axis.options.timeFormat)
- return Flotr.Date.format(d, options.timeFormat, options.timeMode);
-
- var span = (axis.max - axis.min) * scale,
- t = axis.tickSize * Flotr.Date.timeUnits[axis.tickUnit];
-
- return Flotr.Date.format(d, Flotr.Date.getFormat(t, span), options.timeMode);
- },
- generator: function(axis) {
-
- var
- set = this.set,
- get = this.get,
- timeUnits = this.timeUnits,
- spec = this.spec,
- options = axis.options,
- mode = options.timeMode,
- scale = timeUnits[options.timeUnit],
- min = axis.min * scale,
- max = axis.max * scale,
- delta = (max - min) / options.noTicks,
- ticks = [],
- tickSize = axis.tickSize,
- tickUnit,
- formatter, i;
-
- // Use custom formatter or time tick formatter
- formatter = (options.tickFormatter === Flotr.defaultTickFormatter ?
- this.formatter : options.tickFormatter
- );
-
- for (i = 0; i < spec.length - 1; ++i) {
- var d = spec[i][0] * timeUnits[spec[i][1]];
- if (delta < (d + spec[i+1][0] * timeUnits[spec[i+1][1]]) / 2 && d >= tickSize)
- break;
- }
- tickSize = spec[i][0];
- tickUnit = spec[i][1];
-
- // special-case the possibility of several years
- if (tickUnit == "year") {
- tickSize = Flotr.getTickSize(options.noTicks*timeUnits.year, min, max, 0);
-
- // Fix for 0.5 year case
- if (tickSize == 0.5) {
- tickUnit = "month";
- tickSize = 6;
- }
- }
-
- axis.tickUnit = tickUnit;
- axis.tickSize = tickSize;
-
- var
- d = new Date(min);
-
- var step = tickSize * timeUnits[tickUnit];
-
- function setTick (name) {
- set(d, name, mode, Flotr.floorInBase(
- get(d, name, mode), tickSize
- ));
- }
-
- switch (tickUnit) {
- case "millisecond": setTick('Milliseconds'); break;
- case "second": setTick('Seconds'); break;
- case "minute": setTick('Minutes'); break;
- case "hour": setTick('Hours'); break;
- case "month": setTick('Month'); break;
- case "year": setTick('FullYear'); break;
- }
-
- // reset smaller components
- if (step >= timeUnits.second) set(d, 'Milliseconds', mode, 0);
- if (step >= timeUnits.minute) set(d, 'Seconds', mode, 0);
- if (step >= timeUnits.hour) set(d, 'Minutes', mode, 0);
- if (step >= timeUnits.day) set(d, 'Hours', mode, 0);
- if (step >= timeUnits.day * 4) set(d, 'Date', mode, 1);
- if (step >= timeUnits.year) set(d, 'Month', mode, 0);
-
- var carry = 0, v = NaN, prev;
- do {
- prev = v;
- v = d.getTime();
- ticks.push({ v: v / scale, label: formatter(v / scale, axis) });
- if (tickUnit == "month") {
- if (tickSize < 1) {
- /* a bit complicated - we'll divide the month up but we need to take care of fractions
- so we don't end up in the middle of a day */
- set(d, 'Date', mode, 1);
- var start = d.getTime();
- set(d, 'Month', mode, get(d, 'Month', mode) + 1)
- var end = d.getTime();
- d.setTime(v + carry * timeUnits.hour + (end - start) * tickSize);
- carry = get(d, 'Hours', mode)
- set(d, 'Hours', mode, 0);
- }
- else
- set(d, 'Month', mode, get(d, 'Month', mode) + tickSize);
- }
- else if (tickUnit == "year") {
- set(d, 'FullYear', mode, get(d, 'FullYear', mode) + tickSize);
- }
- else
- d.setTime(v + step);
-
- } while (v < 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"]
-};
-
-(function () {
-
-var _ = Flotr._;
-
-Flotr.DOM = {
- addClass: function(element, name){
- var classList = (element.className ? element.className : '');
- if (_.include(classList.split(/\s+/g), name)) return;
- element.className = (classList ? classList + ' ' : '') + name;
- },
- /**
- * Create an element.
- */
- create: function(tag){
- return document.createElement(tag);
- },
- node: function(html) {
- var div = Flotr.DOM.create('div'), n;
- div.innerHTML = html;
- n = div.children[0];
- div.innerHTML = '';
- return n;
- },
- /**
- * Remove all children.
- */
- empty: function(element){
- element.innerHTML = '';
- /*
- if (!element) return;
- _.each(element.childNodes, function (e) {
- Flotr.DOM.empty(e);
- element.removeChild(e);
- });
- */
- },
- hide: function(element){
- Flotr.DOM.setStyles(element, {display:'none'});
- },
- /**
- * Insert a child.
- * @param {Element} element
- * @param {Element|String} Element or string to be appended.
- */
- insert: function(element, child){
- if(_.isString(child))
- element.innerHTML += child;
- else if (_.isElement(child))
- element.appendChild(child);
- },
- // @TODO find xbrowser implementation
- opacity: function(element, opacity) {
- element.style.opacity = opacity;
- },
- position: function(element, p){
- if (!element.offsetParent)
- return {left: (element.offsetLeft || 0), top: (element.offsetTop || 0)};
-
- p = this.position(element.offsetParent);
- p.left += element.offsetLeft;
- p.top += element.offsetTop;
- return p;
- },
- removeClass: function(element, name) {
- var classList = (element.className ? element.className : '');
- element.className = _.filter(classList.split(/\s+/g), function (c) {
- if (c != name) return true; }
- ).join(' ');
- },
- setStyles: function(element, o) {
- _.each(o, function (value, key) {
- element.style[key] = value;
- });
- },
- show: function(element){
- Flotr.DOM.setStyles(element, {display:''});
- },
- /**
- * Return element size.
- */
- size: function(element){
- return {
- height : element.offsetHeight,
- width : element.offsetWidth };
- }
-};
-
-})();
-
-/**
- * Flotr Event Adapter
- */
-(function () {
-var
- F = Flotr,
- bean = F.bean;
-F.EventAdapter = {
- observe: function(object, name, callback) {
- bean.add(object, name, callback);
- return this;
- },
- fire: function(object, name, args) {
- bean.fire(object, name, args);
- if (typeof(Prototype) != 'undefined')
- Event.fire(object, name, args);
- // @TODO Someone who uses mootools, add mootools adapter for existing applciations.
- return this;
- },
- stopObserving: function(object, name, callback) {
- bean.remove(object, name, callback);
- return this;
- },
- eventPointer: function(e) {
- if (!F._.isUndefined(e.touches) && e.touches.length > 0) {
- return {
- x : e.touches[0].pageX,
- y : e.touches[0].pageY
- };
- } else if (!F._.isUndefined(e.changedTouches) && e.changedTouches.length > 0) {
- return {
- x : e.changedTouches[0].pageX,
- y : e.changedTouches[0].pageY
- };
- } else if (e.pageX || e.pageY) {
- return {
- x : e.pageX,
- y : e.pageY
- };
- } else if (e.clientX || e.clientY) {
- var
- d = document,
- b = d.body,
- de = d.documentElement;
- return {
- x: e.clientX + b.scrollLeft + de.scrollLeft,
- y: e.clientY + b.scrollTop + de.scrollTop
- };
- }
- }
-};
-})();
-
-/**
- * Text Utilities
- */
-(function () {
-
-var
- F = Flotr,
- D = F.DOM,
- _ = F._,
-
-Text = function (o) {
- this.o = o;
-};
-
-Text.prototype = {
-
- dimensions : function (text, canvasStyle, htmlStyle, className) {
-
- if (!text) return { width : 0, height : 0 };
-
- return (this.o.html) ?
- this.html(text, this.o.element, htmlStyle, className) :
- this.canvas(text, canvasStyle);
- },
-
- canvas : function (text, style) {
-
- if (!this.o.textEnabled) return;
- style = style || {};
-
- var
- metrics = this.measureText(text, style),
- width = metrics.width,
- height = style.size || F.defaultOptions.fontSize,
- angle = style.angle || 0,
- cosAngle = Math.cos(angle),
- sinAngle = Math.sin(angle),
- widthPadding = 2,
- heightPadding = 6,
- bounds;
-
- bounds = {
- width: Math.abs(cosAngle * width) + Math.abs(sinAngle * height) + widthPadding,
- height: Math.abs(sinAngle * width) + Math.abs(cosAngle * height) + heightPadding
- };
-
- return bounds;
- },
-
- html : function (text, element, style, className) {
-
- var div = D.create('div');
-
- D.setStyles(div, { 'position' : 'absolute', 'top' : '-10000px' });
- D.insert(div, '<div style="'+style+'" class="'+className+' flotr-dummy-div">' + text + '</div>');
- D.insert(this.o.element, div);
-
- return D.size(div);
- },
-
- measureText : function (text, style) {
-
- var
- context = this.o.ctx,
- metrics;
-
- if (!context.fillText || (F.isIphone && context.measure)) {
- return { width : context.measure(text, style)};
- }
-
- style = _.extend({
- size: F.defaultOptions.fontSize,
- weight: 1,
- angle: 0
- }, style);
-
- context.save();
- context.font = (style.weight > 1 ? "bold " : "") + (style.size*1.3) + "px sans-serif";
- metrics = context.measureText(text);
- context.restore();
-
- return metrics;
- }
-};
-
-Flotr.Text = Text;
-
-})();
-
-/**
- * Flotr Graph class that plots a graph on creation.
- */
-(function () {
-
-var
- D = Flotr.DOM,
- E = Flotr.EventAdapter,
- _ = Flotr._,
- flotr = Flotr;
-/**
- * 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
- */
-Graph = function(el, data, options){
-// Let's see if we can get away with out this [JS]
-// try {
- this._setEl(el);
- this._initMembers();
- this._initPlugins();
-
- E.fire(this.el, 'flotr:beforeinit', [this]);
-
- this.data = data;
- this.series = flotr.Series.getSeries(data);
- this._initOptions(options);
- this._initGraphTypes();
- this._initCanvas();
- this._text = new flotr.Text({
- element : this.el,
- ctx : this.ctx,
- html : this.options.HtmlText,
- textEnabled : this.textEnabled
- });
- E.fire(this.el, 'flotr:afterconstruct', [this]);
- this._initEvents();
-
- this.findDataRanges();
- this.calculateSpacing();
-
- this.draw(_.bind(function() {
- E.fire(this.el, 'flotr:afterinit', [this]);
- }, this));
-/*
- try {
- } catch (e) {
- try {
- console.error(e);
- } catch (e2) {}
- }*/
-};
-
-function observe (object, name, callback) {
- E.observe.apply(this, arguments);
- this._handles.push(arguments);
- return this;
-}
-
-Graph.prototype = {
-
- destroy: function () {
- E.fire(this.el, 'flotr:destroy');
- _.each(this._handles, function (handle) {
- E.stopObserving.apply(this, handle);
- });
- this._handles = [];
- this.el.graph = null;
- },
-
- observe : observe,
-
- /**
- * @deprecated
- */
- _observe : observe,
-
- processColor: function(color, options){
- var o = { x1: 0, y1: 0, x2: this.plotWidth, y2: this.plotHeight, opacity: 1, ctx: this.ctx };
- _.extend(o, options);
- return flotr.Color.processColor(color, o);
- },
- /**
- * Function determines the min and max values for the xaxis and yaxis.
- *
- * TODO logarithmic range validation (consideration of 0)
- */
- findDataRanges: function(){
- var a = this.axes,
- xaxis, yaxis, range;
-
- _.each(this.series, function (series) {
- range = series.getRange();
- if (range) {
- xaxis = series.xaxis;
- yaxis = series.yaxis;
- xaxis.datamin = Math.min(range.xmin, xaxis.datamin);
- xaxis.datamax = Math.max(range.xmax, xaxis.datamax);
- yaxis.datamin = Math.min(range.ymin, yaxis.datamin);
- yaxis.datamax = Math.max(range.ymax, yaxis.datamax);
- xaxis.used = (xaxis.used || range.xused);
- yaxis.used = (yaxis.used || range.yused);
- }
- }, this);
-
- // Check for empty data, no data case (none used)
- if (!a.x.used && !a.x2.used) a.x.used = true;
- if (!a.y.used && !a.y2.used) a.y.used = true;
-
- _.each(a, function (axis) {
- axis.calculateRange();
- });
-
- var
- types = _.keys(flotr.graphTypes),
- drawn = false;
-
- _.each(this.series, function (series) {
- if (series.hide) return;
- _.each(types, function (type) {
- if (series[type] && series[type].show) {
- this.extendRange(type, series);
- drawn = true;
- }
- }, this);
- if (!drawn) {
- this.extendRange(this.options.defaultType, series);
- }
- }, this);
- },
-
- extendRange : function (type, series) {
- if (this[type].extendRange) this[type].extendRange(series, series.data, series[type], this[type]);
- if (this[type].extendYRange) this[type].extendYRange(series.yaxis, series.data, series[type], this[type]);
- if (this[type].extendXRange) this[type].extendXRange(series.xaxis, series.data, series[type], this[type]);
- },
-
- /**
- * Calculates axis label sizes.
- */
- calculateSpacing: function(){
-
- var a = this.axes,
- options = this.options,
- series = this.series,
- margin = options.grid.labelMargin,
- T = this._text,
- x = a.x,
- x2 = a.x2,
- y = a.y,
- y2 = a.y2,
- maxOutset = options.grid.outlineWidth,
- i, j, l, dim;
-
- // TODO post refactor, fix this
- _.each(a, function (axis) {
- axis.calculateTicks();
- axis.calculateTextDimensions(T, options);
- });
-
- // Title height
- dim = T.dimensions(
- options.title,
- {size: options.fontSize*1.5},
- 'font-size:1em;font-weight:bold;',
- 'flotr-title'
- );
- this.titleHeight = dim.height;
-
- // Subtitle height
- dim = T.dimensions(
- options.subtitle,
- {size: options.fontSize},
- 'font-size:smaller;',
- 'flotr-subtitle'
- );
- this.subtitleHeight = dim.height;
-
- 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;
- if (x.options.margin === false) {
- p.bottom = 0;
- p.top = 0;
- } else {
- p.bottom += (options.grid.circular ? 0 : (x.used && x.options.showLabels ? (x.maxLabel.height + margin) : 0)) +
- (x.used && x.options.title ? (x.titleSize.height + margin) : 0) + maxOutset;
-
- p.top += (options.grid.circular ? 0 : (x2.used && x2.options.showLabels ? (x2.maxLabel.height + margin) : 0)) +
- (x2.used && x2.options.title ? (x2.titleSize.height + margin) : 0) + this.subtitleHeight + this.titleHeight + maxOutset;
- }
- if (y.options.margin === false) {
- p.left = 0;
- p.right = 0;
- } else {
- p.left += (options.grid.circular ? 0 : (y.used && y.options.showLabels ? (y.maxLabel.width + margin) : 0)) +
- (y.used && y.options.title ? (y.titleSize.width + margin) : 0) + maxOutset;
-
- p.right += (options.grid.circular ? 0 : (y2.used && y2.options.showLabels ? (y2.maxLabel.width + margin) : 0)) +
- (y2.used && y2.options.title ? (y2.titleSize.width + margin) : 0) + maxOutset;
- }
-
- p.top = Math.floor(p.top); // In order the outline not to be blured
-
- this.plotWidth = this.canvasWidth - p.left - p.right;
- this.plotHeight = this.canvasHeight - p.bottom - p.top;
-
- // TODO post refactor, fix this
- x.length = x2.length = this.plotWidth;
- y.length = y2.length = this.plotHeight;
- y.offset = y2.offset = this.plotHeight;
- x.setScale();
- x2.setScale();
- y.setScale();
- y2.setScale();
- },
- /**
- * Draws grid, labels, series and outline.
- */
- draw: function(after) {
-
- var
- context = this.ctx,
- i;
-
- E.fire(this.el, 'flotr:beforedraw', [this.series, this]);
-
- if (this.series.length) {
-
- context.save();
- context.translate(this.plotOffset.left, this.plotOffset.top);
-
- for (i = 0; i < this.series.length; i++) {
- if (!this.series[i].hide) this.drawSeries(this.series[i]);
- }
-
- context.restore();
- this.clip();
- }
-
- E.fire(this.el, 'flotr:afterdraw', [this.series, this]);
- if (after) after();
- },
- /**
- * Actually draws the graph.
- * @param {Object} series - series to draw
- */
- drawSeries: function(series){
-
- function drawChart (series, typeKey) {
- var options = this.getOptions(series, typeKey);
- this[typeKey].draw(options);
- }
-
- var drawn = false;
- series = series || this.series;
-
- _.each(flotr.graphTypes, function (type, typeKey) {
- if (series[typeKey] && series[typeKey].show && this[typeKey]) {
- drawn = true;
- drawChart.call(this, series, typeKey);
- }
- }, this);
-
- if (!drawn) drawChart.call(this, series, this.options.defaultType);
- },
-
- getOptions : function (series, typeKey) {
- var
- type = series[typeKey],
- graphType = this[typeKey],
- options = {
- context : this.ctx,
- width : this.plotWidth,
- height : this.plotHeight,
- fontSize : this.options.fontSize,
- fontColor : this.options.fontColor,
- textEnabled : this.textEnabled,
- htmlText : this.options.HtmlText,
- text : this._text, // TODO Is this necessary?
- element : this.el,
- data : series.data,
- color : series.color,
- shadowSize : series.shadowSize,
- xScale : _.bind(series.xaxis.d2p, series.xaxis),
- yScale : _.bind(series.yaxis.d2p, series.yaxis)
- };
-
- options = flotr.merge(type, options);
-
- // Fill
- options.fillStyle = this.processColor(
- type.fillColor || series.color,
- {opacity: type.fillOpacity}
- );
-
- return options;
- },
- /**
- * Calculates the coordinates from a mouse event object.
- * @param {Event} event - Mouse Event object.
- * @return {Object} Object with coordinates of the mouse.
- */
- getEventPosition: function (e){
-
- var
- d = document,
- b = d.body,
- de = d.documentElement,
- axes = this.axes,
- plotOffset = this.plotOffset,
- lastMousePos = this.lastMousePos,
- pointer = E.eventPointer(e),
- dx = pointer.x - lastMousePos.pageX,
- dy = pointer.y - lastMousePos.pageY,
- r, rx, ry;
-
- if ('ontouchstart' in this.el) {
- r = D.position(this.overlay);
- rx = pointer.x - r.left - plotOffset.left;
- ry = pointer.y - r.top - plotOffset.top;
- } else {
- r = this.overlay.getBoundingClientRect();
- rx = e.clientX - r.left - plotOffset.left - b.scrollLeft - de.scrollLeft;
- ry = e.clientY - r.top - plotOffset.top - b.scrollTop - de.scrollTop;
- }
-
- return {
- x: axes.x.p2d(rx),
- x2: axes.x2.p2d(rx),
- y: axes.y.p2d(ry),
- y2: axes.y2.p2d(ry),
- relX: rx,
- relY: ry,
- dX: dx,
- dY: dy,
- absX: pointer.x,
- absY: pointer.y,
- pageX: pointer.x,
- pageY: pointer.y
- };
- },
- /**
- * Observes the 'click' event and fires the 'flotr:click' event.
- * @param {Event} event - 'click' Event object.
- */
- clickHandler: function(event){
- if(this.ignoreClick){
- this.ignoreClick = false;
- return this.ignoreClick;
- }
- E.fire(this.el, '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){
- if (this.mouseDownMoveHandler) return;
- var pos = this.getEventPosition(event);
- E.fire(this.el, 'flotr:mousemove', [event, pos, this]);
- this.lastMousePos = pos;
- },
- /**
- * Observes the 'mousedown' event.
- * @param {Event} event - 'mousedown' Event object.
- */
- mouseDownHandler: function (event){
-
- /*
- // @TODO Context menu?
- if(event.isRightClick()) {
- event.stop();
-
- var overlay = this.overlay;
- overlay.hide();
-
- function cancelContextMenu () {
- overlay.show();
- E.stopObserving(document, 'mousemove', cancelContextMenu);
- }
- E.observe(document, 'mousemove', cancelContextMenu);
- return;
- }
- */
-
- if (this.mouseUpHandler) return;
- this.mouseUpHandler = _.bind(function (e) {
- E.stopObserving(document, 'mouseup', this.mouseUpHandler);
- E.stopObserving(document, 'mousemove', this.mouseDownMoveHandler);
- this.mouseDownMoveHandler = null;
- this.mouseUpHandler = null;
- // @TODO why?
- //e.stop();
- E.fire(this.el, 'flotr:mouseup', [e, this]);
- }, this);
- this.mouseDownMoveHandler = _.bind(function (e) {
- var pos = this.getEventPosition(e);
- E.fire(this.el, 'flotr:mousemove', [event, pos, this]);
- this.lastMousePos = pos;
- }, this);
- E.observe(document, 'mouseup', this.mouseUpHandler);
- E.observe(document, 'mousemove', this.mouseDownMoveHandler);
- E.fire(this.el, 'flotr:mousedown', [event, this]);
- this.ignoreClick = false;
- },
- drawTooltip: function(content, x, y, options) {
- var mt = this.getMouseTrack(),
- style = '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;',
- p = options.position,
- m = options.margin,
- plotOffset = this.plotOffset;
-
- if(x !== null && y !== null){
- if (!options.relative) { // absolute to the canvas
- if(p.charAt(0) == 'n') style += 'top:' + (m + plotOffset.top) + 'px;bottom:auto;';
- else if(p.charAt(0) == 's') style += 'bottom:' + (m + plotOffset.bottom) + 'px;top:auto;';
- if(p.charAt(1) == 'e') style += 'right:' + (m + plotOffset.right) + 'px;left:auto;';
- else if(p.charAt(1) == 'w') style += 'left:' + (m + plotOffset.left) + 'px;right:auto;';
- }
- else { // relative to the mouse
- if(p.charAt(0) == 'n') style += 'bottom:' + (m - plotOffset.top - y + this.canvasHeight) + 'px;top:auto;';
- else if(p.charAt(0) == 's') style += 'top:' + (m + plotOffset.top + y) + 'px;bottom:auto;';
- if(p.charAt(1) == 'e') style += 'left:' + (m + plotOffset.left + x) + 'px;right:auto;';
- else if(p.charAt(1) == 'w') style += 'right:' + (m - plotOffset.left - x + this.canvasWidth) + 'px;left:auto;';
- }
-
- mt.style.cssText = style;
- D.empty(mt);
- D.insert(mt, content);
- D.show(mt);
- }
- else {
- D.hide(mt);
- }
- },
-
- clip: function () {
-
- var
- ctx = this.ctx,
- o = this.plotOffset,
- w = this.canvasWidth,
- h = this.canvasHeight;
-
- if (flotr.isIE && flotr.isIE < 9) {
- // Clipping for excanvas :-(
- ctx.save();
- ctx.fillStyle = this.processColor(this.options.ieBackgroundColor);
- ctx.fillRect(0, 0, w, o.top);
- ctx.fillRect(0, 0, o.left, h);
- ctx.fillRect(0, h - o.bottom, w, o.bottom);
- ctx.fillRect(w - o.right, 0, o.right,h);
- ctx.restore();
- } else {
- ctx.clearRect(0, 0, w, o.top);
- ctx.clearRect(0, 0, o.left, h);
- ctx.clearRect(0, h - o.bottom, w, o.bottom);
- ctx.clearRect(w - o.right, 0, o.right,h);
- }
- },
-
- _initMembers: function() {
- this._handles = [];
- this.lastMousePos = {pageX: null, pageY: null };
- this.plotOffset = {left: 0, right: 0, top: 0, bottom: 0};
- this.ignoreClick = true;
- this.prevHit = null;
- },
-
- _initGraphTypes: function() {
- _.each(flotr.graphTypes, function(handler, graphType){
- this[graphType] = flotr.clone(handler);
- }, this);
- },
-
- _initEvents: function () {
-
- var
- el = this.el,
- touchendHandler, movement, touchend;
-
- if ('ontouchstart' in el) {
-
- touchendHandler = _.bind(function (e) {
- touchend = true;
- E.stopObserving(document, 'touchend', touchendHandler);
- E.fire(el, 'flotr:mouseup', [event, this]);
- this.multitouches = null;
-
- if (!movement) {
- this.clickHandler(e);
- }
- }, this);
-
- this.observe(this.overlay, 'touchstart', _.bind(function (e) {
- movement = false;
- touchend = false;
- this.ignoreClick = false;
-
- if (e.touches && e.touches.length > 1) {
- this.multitouches = e.touches;
- }
-
- E.fire(el, 'flotr:mousedown', [event, this]);
- this.observe(document, 'touchend', touchendHandler);
- }, this));
-
- this.observe(this.overlay, 'touchmove', _.bind(function (e) {
-
- var pos = this.getEventPosition(e);
-
- e.preventDefault();
-
- movement = true;
-
- if (this.multitouches || (e.touches && e.touches.length > 1)) {
- this.multitouches = e.touches;
- } else {
- if (!touchend) {
- E.fire(el, 'flotr:mousemove', [event, pos, this]);
- }
- }
- this.lastMousePos = pos;
- }, this));
-
- } else {
- this.
- observe(this.overlay, 'mousedown', _.bind(this.mouseDownHandler, this)).
- observe(el, 'mousemove', _.bind(this.mouseMoveHandler, this)).
- observe(this.overlay, 'click', _.bind(this.clickHandler, this)).
- observe(el, 'mouseout', function () {
- E.fire(el, 'flotr:mouseout');
- });
- }
- },
-
- /**
- * 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.
- */
- _initCanvas: function(){
- var el = this.el,
- o = this.options,
- children = el.children,
- removedChildren = [],
- child, i,
- size, style;
-
- // Empty the el
- for (i = children.length; i--;) {
- child = children[i];
- if (!this.canvas && child.className === 'flotr-canvas') {
- this.canvas = child;
- } else if (!this.overlay && child.className === 'flotr-overlay') {
- this.overlay = child;
- } else {
- removedChildren.push(child);
- }
- }
- for (i = removedChildren.length; i--;) {
- el.removeChild(removedChildren[i]);
- }
-
- D.setStyles(el, {position: 'relative'}); // For positioning labels and overlay.
- size = {};
- size.width = el.clientWidth;
- size.height = el.clientHeight;
-
- if(size.width <= 0 || size.height <= 0 || o.resolution <= 0){
- throw 'Invalid dimensions for plot, width = ' + size.width + ', height = ' + size.height + ', resolution = ' + o.resolution;
- }
-
- // Main canvas for drawing graph types
- this.canvas = getCanvas(this.canvas, 'canvas');
- // Overlay canvas for interactive features
- this.overlay = getCanvas(this.overlay, 'overlay');
- this.ctx = getContext(this.canvas);
- this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
- this.octx = getContext(this.overlay);
- this.octx.clearRect(0, 0, this.overlay.width, this.overlay.height);
- this.canvasHeight = size.height;
- this.canvasWidth = size.width;
- this.textEnabled = !!this.ctx.drawText || !!this.ctx.fillText; // Enable text functions
-
- function getCanvas(canvas, name){
- if(!canvas){
- canvas = D.create('canvas');
- if (typeof FlashCanvas != "undefined" && typeof canvas.getContext === 'function') {
- FlashCanvas.initElement(canvas);
- }
- canvas.className = 'flotr-'+name;
- canvas.style.cssText = 'position:absolute;left:0px;top:0px;';
- D.insert(el, canvas);
- }
- _.each(size, function(size, attribute){
- D.show(canvas);
- if (name == 'canvas' && canvas.getAttribute(attribute) === size) {
- return;
- }
- canvas.setAttribute(attribute, size * o.resolution);
- canvas.style[attribute] = size + 'px';
- });
- canvas.context_ = null; // Reset the ExCanvas context
- return canvas;
- }
-
- function getContext(canvas){
- if(window.G_vmlCanvasManager) window.G_vmlCanvasManager.initElement(canvas); // For ExCanvas
- var context = canvas.getContext('2d');
- if(!window.G_vmlCanvasManager) context.scale(o.resolution, o.resolution);
- return context;
- }
- },
-
- _initPlugins: function(){
- // TODO Should be moved to flotr and mixed in.
- _.each(flotr.plugins, function(plugin, name){
- _.each(plugin.callbacks, function(fn, c){
- this.observe(this.el, c, _.bind(fn, this));
- }, this);
- this[name] = flotr.clone(plugin);
- _.each(this[name], function(fn, p){
- if (_.isFunction(fn))
- this[name][p] = _.bind(fn, this);
- }, this);
- }, this);
- },
-
- /**
- * Sets options and initializes some variables and color specific values, used by the constructor.
- * @param {Object} opts - options object
- */
- _initOptions: function(opts){
- var options = flotr.clone(flotr.defaultOptions);
- options.x2axis = _.extend(_.clone(options.xaxis), options.x2axis);
- options.y2axis = _.extend(_.clone(options.yaxis), options.y2axis);
- this.options = flotr.merge(opts || {}, options);
-
- if (this.options.grid.minorVerticalLines === null &&
- this.options.xaxis.scaling === 'logarithmic') {
- this.options.grid.minorVerticalLines = true;
- }
- if (this.options.grid.minorHorizontalLines === null &&
- this.options.yaxis.scaling === 'logarithmic') {
- this.options.grid.minorHorizontalLines = true;
- }
-
- E.fire(this.el, 'flotr:afterinitoptions', [this]);
-
- this.axes = flotr.Axis.getAxes(this.options);
-
- // 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(_.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){
- s.color = colors[j++].toString();
- }else if(_.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] = _.extend(_.clone(this.options[t]), s[t]);
- }
- s.mouse = _.extend(_.clone(this.options.mouse), s.mouse);
-
- if (_.isUndefined(s.shadowSize)) s.shadowSize = this.options.shadowSize;
- }
- },
-
- _setEl: function(el) {
- if (!el) throw 'The target container doesn\'t exist';
- else if (el.graph instanceof Graph) el.graph.destroy();
- else if (!el.clientWidth) throw 'The target container must be visible';
-
- el.graph = this;
- this.el = el;
- }
-};
-
-Flotr.Graph = Graph;
-
-})();
-
-/**
- * Flotr Axis Library
- */
-
-(function () {
-
-var
- _ = Flotr._,
- LOGARITHMIC = 'logarithmic';
-
-function Axis (o) {
-
- this.orientation = 1;
- this.offset = 0;
- this.datamin = Number.MAX_VALUE;
- this.datamax = -Number.MAX_VALUE;
-
- _.extend(this, o);
-
- this._setTranslations();
-}
-
-
-// Prototype
-Axis.prototype = {
-
- setScale : function () {
- var length = this.length;
- if (this.options.scaling == LOGARITHMIC) {
- this.scale = length / (log(this.max, this.options.base) - log(this.min, this.options.base));
- } else {
- this.scale = length / (this.max - this.min);
- }
- },
-
- calculateTicks : function () {
- var options = this.options;
-
- this.ticks = [];
- this.minorTicks = [];
-
- // User Ticks
- if(options.ticks){
- this._cleanUserTicks(options.ticks, this.ticks);
- this._cleanUserTicks(options.minorTicks || [], this.minorTicks);
- }
- else {
- if (options.mode == 'time') {
- this._calculateTimeTicks();
- } else if (options.scaling === 'logarithmic') {
- this._calculateLogTicks();
- } else {
- this._calculateTicks();
- }
- }
- },
-
- /**
- * Calculates the range of an axis to apply autoscaling.
- */
- calculateRange: function () {
-
- if (!this.used) return;
-
- var axis = this,
- o = axis.options,
- min = o.min !== null ? o.min : axis.datamin,
- max = o.max !== null ? o.max : axis.datamax,
- margin = o.autoscaleMargin;
-
- if (o.scaling == 'logarithmic') {
- if (min <= 0) min = axis.datamin;
-
- // Let it widen later on
- if (max <= 0) max = min;
- }
-
- if (max == min) {
- var widen = max ? 0.01 : 1.00;
- if (o.min === null) min -= widen;
- if (o.max === null) max += widen;
- }
-
- if (o.scaling === 'logarithmic') {
- if (min < 0) min = max / o.base; // Could be the result of widening
-
- var maxexp = Math.log(max);
- if (o.base != Math.E) maxexp /= Math.log(o.base);
- maxexp = Math.ceil(maxexp);
-
- var minexp = Math.log(min);
- if (o.base != Math.E) minexp /= Math.log(o.base);
- minexp = Math.ceil(minexp);
-
- axis.tickSize = Flotr.getTickSize(o.noTicks, minexp, maxexp, o.tickDecimals === null ? 0 : o.tickDecimals);
-
- // Try to determine a suitable amount of miniticks based on the length of a decade
- if (o.minorTickFreq === null) {
- if (maxexp - minexp > 10)
- o.minorTickFreq = 0;
- else if (maxexp - minexp > 5)
- o.minorTickFreq = 2;
- else
- o.minorTickFreq = 5;
- }
- } else {
- axis.tickSize = Flotr.getTickSize(o.noTicks, min, max, o.tickDecimals);
- }
-
- axis.min = min;
- axis.max = max; //extendRange may use axis.min or axis.max, so it should be set before it is caled
-
- // Autoscaling. @todo This probably fails with log scale. Find a testcase and fix it
- if(o.min === null && o.autoscale){
- axis.min -= axis.tickSize * margin;
- // Make sure we don't go below zero if all values are positive.
- if(axis.min < 0 && axis.datamin >= 0) axis.min = 0;
- axis.min = axis.tickSize * Math.floor(axis.min / axis.tickSize);
- }
-
- if(o.max === null && o.autoscale){
- axis.max += axis.tickSize * margin;
- if(axis.max > 0 && axis.datamax <= 0 && axis.datamax != axis.datamin) axis.max = 0;
- axis.max = axis.tickSize * Math.ceil(axis.max / axis.tickSize);
- }
-
- if (axis.min == axis.max) axis.max = axis.min + 1;
- },
-
- calculateTextDimensions : function (T, options) {
-
- var maxLabel = '',
- length,
- i;
-
- if (this.options.showLabels) {
- for (i = 0; i < this.ticks.length; ++i) {
- length = this.ticks[i].label.length;
- if (length > maxLabel.length){
- maxLabel = this.ticks[i].label;
- }
- }
- }
-
- this.maxLabel = T.dimensions(
- maxLabel,
- {size:options.fontSize, angle: Flotr.toRad(this.options.labelsAngle)},
- 'font-size:smaller;',
- 'flotr-grid-label'
- );
-
- this.titleSize = T.dimensions(
- this.options.title,
- {size:options.fontSize*1.2, angle: Flotr.toRad(this.options.titleAngle)},
- 'font-weight:bold;',
- 'flotr-axis-title'
- );
- },
-
- _cleanUserTicks : function (ticks, axisTicks) {
-
- var axis = this, options = this.options,
- v, i, label, tick;
-
- if(_.isFunction(ticks)) ticks = ticks({min : axis.min, max : axis.max});
-
- for(i = 0; i < ticks.length; ++i){
- tick = ticks[i];
- if(typeof(tick) === 'object'){
- v = tick[0];
- label = (tick.length > 1) ? tick[1] : options.tickFormatter(v, {min : axis.min, max : axis.max});
- } else {
- v = tick;
- label = options.tickFormatter(v, {min : this.min, max : this.max});
- }
- axisTicks[i] = { v: v, label: label };
- }
- },
-
- _calculateTimeTicks : function () {
- this.ticks = Flotr.Date.generator(this);
- },
-
- _calculateLogTicks : function () {
-
- var axis = this,
- o = axis.options,
- v,
- decadeStart;
-
- var max = Math.log(axis.max);
- if (o.base != Math.E) max /= Math.log(o.base);
- max = Math.ceil(max);
-
- var min = Math.log(axis.min);
- if (o.base != Math.E) min /= Math.log(o.base);
- min = Math.ceil(min);
-
- for (i = min; i < max; i += axis.tickSize) {
- decadeStart = (o.base == Math.E) ? Math.exp(i) : Math.pow(o.base, i);
- // Next decade begins here:
- var decadeEnd = decadeStart * ((o.base == Math.E) ? Math.exp(axis.tickSize) : Math.pow(o.base, axis.tickSize));
- var stepSize = (decadeEnd - decadeStart) / o.minorTickFreq;
-
- axis.ticks.push({v: decadeStart, label: o.tickFormatter(decadeStart, {min : axis.min, max : axis.max})});
- for (v = decadeStart + stepSize; v < decadeEnd; v += stepSize)
- axis.minorTicks.push({v: v, label: o.tickFormatter(v, {min : axis.min, max : axis.max})});
- }
-
- // Always show the value at the would-be start of next decade (end of this decade)
- decadeStart = (o.base == Math.E) ? Math.exp(i) : Math.pow(o.base, i);
- axis.ticks.push({v: decadeStart, label: o.tickFormatter(decadeStart, {min : axis.min, max : axis.max})});
- },
-
- _calculateTicks : function () {
-
- var axis = this,
- o = axis.options,
- tickSize = axis.tickSize,
- min = axis.min,
- max = axis.max,
- start = tickSize * Math.ceil(min / tickSize), // Round to nearest multiple of tick size.
- decimals,
- minorTickSize,
- v, v2,
- i, j;
-
- if (o.minorTickFreq)
- minorTickSize = tickSize / o.minorTickFreq;
-
- // Then store all possible ticks.
- for (i = 0; (v = v2 = start + i * tickSize) <= max; ++i){
-
- // Round (this is always needed to fix numerical instability).
- decimals = o.tickDecimals;
- if (decimals === null) decimals = 1 - Math.floor(Math.log(tickSize) / Math.LN10);
- if (decimals < 0) decimals = 0;
-
- v = v.toFixed(decimals);
- axis.ticks.push({ v: v, label: o.tickFormatter(v, {min : axis.min, max : axis.max}) });
-
- if (o.minorTickFreq) {
- for (j = 0; j < o.minorTickFreq && (i * tickSize + j * minorTickSize) < max; ++j) {
- v = v2 + j * minorTickSize;
- axis.minorTicks.push({ v: v, label: o.tickFormatter(v, {min : axis.min, max : axis.max}) });
- }
- }
- }
-
- },
-
- _setTranslations : function (logarithmic) {
- this.d2p = (logarithmic ? d2pLog : d2p);
- this.p2d = (logarithmic ? p2dLog : p2d);
- }
-};
-
-
-// Static Methods
-_.extend(Axis, {
- getAxes : function (options) {
- return {
- x: new Axis({options: options.xaxis, n: 1, length: this.plotWidth}),
- x2: new Axis({options: options.x2axis, n: 2, length: this.plotWidth}),
- y: new Axis({options: options.yaxis, n: 1, length: this.plotHeight, offset: this.plotHeight, orientation: -1}),
- y2: new Axis({options: options.y2axis, n: 2, length: this.plotHeight, offset: this.plotHeight, orientation: -1})
- };
- }
-});
-
-
-// Helper Methods
-
-function d2p (dataValue) {
- return this.offset + this.orientation * (dataValue - this.min) * this.scale;
-}
-
-function p2d (pointValue) {
- return (this.offset + this.orientation * pointValue) / this.scale + this.min;
-}
-
-function d2pLog (dataValue) {
- return this.offset + this.orientation * (log(dataValue, this.options.base) - log(this.min, this.options.base)) * this.scale;
-}
-
-function p2dLog (pointValue) {
- return exp((this.offset + this.orientation * pointValue) / this.scale + log(this.min, this.options.base), this.options.base);
-}
-
-function log (value, base) {
- value = Math.log(Math.max(value, Number.MIN_VALUE));
- if (base !== Math.E)
- value /= Math.log(base);
- return value;
-}
-
-function exp (value, base) {
- return (base === Math.E) ? Math.exp(value) : Math.pow(base, value);
-}
-
-Flotr.Axis = Axis;
-
-})();
-
-/**
- * Flotr Series Library
- */
-
-(function () {
-
-var
- _ = Flotr._;
-
-function Series (o) {
- _.extend(this, o);
-}
-
-Series.prototype = {
-
- getRange: function () {
-
- var
- data = this.data,
- length = data.length,
- xmin = Number.MAX_VALUE,
- ymin = Number.MAX_VALUE,
- xmax = -Number.MAX_VALUE,
- ymax = -Number.MAX_VALUE,
- xused = false,
- yused = false,
- x, y, i;
-
- if (length < 0 || this.hide) return false;
-
- for (i = 0; i < length; i++) {
- x = data[i][0];
- y = data[i][1];
- if (x < xmin) { xmin = x; xused = true; }
- if (x > xmax) { xmax = x; xused = true; }
- if (y < ymin) { ymin = y; yused = true; }
- if (y > ymax) { ymax = y; yused = true; }
- }
-
- return {
- xmin : xmin,
- xmax : xmax,
- ymin : ymin,
- ymax : ymax,
- xused : xused,
- yused : yused
- };
- }
-};
-
-_.extend(Series, {
- /**
- * 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 _.map(data, function(s){
- var series;
- if (s.data) {
- series = new Series();
- _.extend(series, s);
- } else {
- series = new Series({data:s});
- }
- return series;
- });
- }
-});
-
-Flotr.Series = Series;
-
-})();
-
-/** 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
- fillBorder: false, // => draw a border around the fill
- fillColor: null, // => fill color
- fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill
- steps: false, // => draw steps
- stacked: false // => setting to true will show stacked lines, false will show normal lines
- },
-
- stack : {
- values : []
- },
-
- /**
- * Draws lines series in the canvas element.
- * @param {Object} options
- */
- draw : function (options) {
-
- var
- context = options.context,
- lineWidth = options.lineWidth,
- shadowSize = options.shadowSize,
- offset;
-
- context.save();
- context.lineJoin = 'round';
-
- if (shadowSize) {
-
- context.lineWidth = shadowSize / 2;
- offset = lineWidth / 2 + context.lineWidth / 2;
-
- // @TODO do this instead with a linear gradient
- context.strokeStyle = "rgba(0,0,0,0.1)";
- this.plot(options, offset + shadowSize / 2, false);
-
- context.strokeStyle = "rgba(0,0,0,0.2)";
- this.plot(options, offset, false);
- }
-
- context.lineWidth = lineWidth;
- context.strokeStyle = options.color;
-
- this.plot(options, 0, true);
-
- context.restore();
- },
-
- plot : function (options, shadowOffset, incStack) {
-
- var
- context = options.context,
- width = options.width,
- height = options.height,
- xScale = options.xScale,
- yScale = options.yScale,
- data = options.data,
- stack = options.stacked ? this.stack : false,
- length = data.length - 1,
- prevx = null,
- prevy = null,
- zero = yScale(0),
- x1, x2, y1, y2, stack1, stack2, i;
-
- if (length < 1) return;
-
- context.beginPath();
-
- for (i = 0; i < length; ++i) {
-
- // To allow empty values
- if (data[i][1] === null || data[i+1][1] === null) continue;
-
- // Zero is infinity for log scales
- // TODO handle zero for logarithmic
- // if (xa.options.scaling === 'logarithmic' && (data[i][0] <= 0 || data[i+1][0] <= 0)) continue;
- // if (ya.options.scaling === 'logarithmic' && (data[i][1] <= 0 || data[i+1][1] <= 0)) continue;
-
- x1 = xScale(data[i][0]);
- x2 = xScale(data[i+1][0]);
-
- if (stack) {
-
- stack1 = stack.values[data[i][0]] || 0;
- stack2 = stack.values[data[i+1][0]] || stack.values[data[i][0]] || 0;
-
- y1 = yScale(data[i][1] + stack1);
- y2 = yScale(data[i+1][1] + stack2);
-
- if(incStack){
- stack.values[data[i][0]] = data[i][1]+stack1;
-
- if(i == length-1)
- stack.values[data[i+1][0]] = data[i+1][1]+stack2;
- }
- }
- else{
- y1 = yScale(data[i][1]);
- y2 = yScale(data[i+1][1]);
- }
-
- if (
- (y1 > height && y2 > height) ||
- (y1 < 0 && y2 < 0) ||
- (x1 < 0 && x2 < 0) ||
- (x1 > width && x2 > width)
- ) continue;
-
- if((prevx != x1) || (prevy != y1 + shadowOffset))
- context.moveTo(x1, y1 + shadowOffset);
-
- prevx = x2;
- prevy = y2 + shadowOffset;
- if (options.steps) {
- context.lineTo(prevx + shadowOffset / 2, y1 + shadowOffset);
- context.lineTo(prevx + shadowOffset / 2, prevy);
- } else {
- context.lineTo(prevx, prevy);
- }
- }
-
- if (!options.fill || options.fill && !options.fillBorder) context.stroke();
-
- // TODO stacked lines
- if(!shadowOffset && options.fill){
- x1 = xScale(data[0][0]);
- context.fillStyle = options.fillStyle;
- context.lineTo(x2, zero);
- context.lineTo(x1, zero);
- context.lineTo(x1, yScale(data[0][1]));
- context.fill();
- if (options.fillBorder) {
- context.stroke();
- }
- }
-
- context.closePath();
- },
-
- // Perform any pre-render precalculations (this should be run on data first)
- // - Pie chart total for calculating measures
- // - Stacks for lines and bars
- // precalculate : function () {
- // }
- //
- //
- // Get any bounds after pre calculation (axis can fetch this if does not have explicit min/max)
- // getBounds : function () {
- // }
- // getMin : function () {
- // }
- // getMax : function () {
- // }
- //
- //
- // Padding around rendered elements
- // getPadding : function () {
- // }
-
- extendYRange : function (axis, data, options, lines) {
-
- var o = axis.options;
-
- // If stacked and auto-min
- if (options.stacked && ((!o.max && o.max !== 0) || (!o.min && o.min !== 0))) {
-
- var
- newmax = axis.max,
- newmin = axis.min,
- positiveSums = lines.positiveSums || {},
- negativeSums = lines.negativeSums || {},
- x, j;
-
- for (j = 0; j < data.length; j++) {
-
- x = data[j][0] + '';
-
- // Positive
- if (data[j][1] > 0) {
- positiveSums[x] = (positiveSums[x] || 0) + data[j][1];
- newmax = Math.max(newmax, positiveSums[x]);
- }
-
- // Negative
- else {
- negativeSums[x] = (negativeSums[x] || 0) + data[j][1];
- newmin = Math.min(newmin, negativeSums[x]);
- }
- }
-
- lines.negativeSums = negativeSums;
- lines.positiveSums = positiveSums;
-
- axis.max = newmax;
- axis.min = newmin;
- }
-
- if (options.steps) {
-
- this.hit = function (options) {
- var
- data = options.data,
- args = options.args,
- yScale = options.yScale,
- mouse = args[0],
- length = data.length,
- n = args[1],
- x = mouse.x,
- relY = mouse.relY,
- i;
-
- for (i = 0; i < length - 1; i++) {
- if (x >= data[i][0] && x <= data[i+1][0]) {
- if (Math.abs(yScale(data[i][1]) - relY) < 8) {
- n.x = data[i][0];
- n.y = data[i][1];
- n.index = i;
- n.seriesIndex = options.index;
- }
- break;
- }
- }
- };
-
- this.drawHit = function (options) {
- var
- context = options.context,
- args = options.args,
- data = options.data,
- xScale = options.xScale,
- index = args.index,
- x = xScale(args.x),
- y = options.yScale(args.y),
- x2;
-
- if (data.length - 1 > index) {
- x2 = options.xScale(data[index + 1][0]);
- context.save();
- context.strokeStyle = options.color;
- context.lineWidth = options.lineWidth;
- context.beginPath();
- context.moveTo(x, y);
- context.lineTo(x2, y);
- context.stroke();
- context.closePath();
- context.restore();
- }
- };
-
- this.clearHit = function (options) {
- var
- context = options.context,
- args = options.args,
- data = options.data,
- xScale = options.xScale,
- width = options.lineWidth,
- index = args.index,
- x = xScale(args.x),
- y = options.yScale(args.y),
- x2;
-
- if (data.length - 1 > index) {
- x2 = options.xScale(data[index + 1][0]);
- context.clearRect(x - width, y - width, x2 - x + 2 * width, 2 * width);
- }
- };
- }
- }
-
-});
-
-/** 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)
- stacked: false, // => stacked bar charts
- centered: true, // => center the bars to their x axis value
- topPadding: 0.1 // => top padding in percent
- },
-
- stack : {
- positive : [],
- negative : [],
- _positive : [], // Shadow
- _negative : [] // Shadow
- },
-
- draw : function (options) {
- var
- context = options.context;
-
- context.save();
- context.lineJoin = 'miter';
- // @TODO linewidth not interpreted the right way.
- context.lineWidth = options.lineWidth;
- context.strokeStyle = options.color;
- if (options.fill) context.fillStyle = options.fillStyle;
-
- this.plot(options);
-
- context.restore();
- },
-
- plot : function (options) {
-
- var
- data = options.data,
- context = options.context,
- shadowSize = options.shadowSize,
- i, geometry, left, top, width, height;
-
- if (data.length < 1) return;
-
- this.translate(context, options.horizontal);
-
- for (i = 0; i < data.length; i++) {
-
- geometry = this.getBarGeometry(data[i][0], data[i][1], options);
- if (geometry === null) continue;
-
- left = geometry.left;
- top = geometry.top;
- width = geometry.width;
- height = geometry.height;
-
- if (options.fill) context.fillRect(left, top, width, height);
- if (shadowSize) {
- context.save();
- context.fillStyle = 'rgba(0,0,0,0.05)';
- context.fillRect(left + shadowSize, top + shadowSize, width, height);
- context.restore();
- }
- if (options.lineWidth) {
- context.strokeRect(left, top, width, height);
- }
- }
- },
-
- translate : function (context, horizontal) {
- if (horizontal) {
- context.rotate(-Math.PI / 2);
- context.scale(-1, 1);
- }
- },
-
- getBarGeometry : function (x, y, options) {
-
- var
- horizontal = options.horizontal,
- barWidth = options.barWidth,
- centered = options.centered,
- stack = options.stacked ? this.stack : false,
- lineWidth = options.lineWidth,
- bisection = centered ? barWidth / 2 : 0,
- xScale = horizontal ? options.yScale : options.xScale,
- yScale = horizontal ? options.xScale : options.yScale,
- xValue = horizontal ? y : x,
- yValue = horizontal ? x : y,
- stackOffset = 0,
- stackValue, left, right, top, bottom;
-
- // Stacked bars
- if (stack) {
- stackValue = yValue > 0 ? stack.positive : stack.negative;
- stackOffset = stackValue[xValue] || stackOffset;
- stackValue[xValue] = stackOffset + yValue;
- }
-
- left = xScale(xValue - bisection);
- right = xScale(xValue + barWidth - bisection);
- top = yScale(yValue + stackOffset);
- bottom = yScale(stackOffset);
-
- // TODO for test passing... probably looks better without this
- if (bottom < 0) bottom = 0;
-
- // TODO Skipping...
- // if (right < xa.min || left > xa.max || top < ya.min || bottom > ya.max) continue;
-
- return (x === null || y === null) ? null : {
- x : xValue,
- y : yValue,
- xScale : xScale,
- yScale : yScale,
- top : top,
- left : Math.min(left, right) - lineWidth / 2,
- width : Math.abs(right - left) - lineWidth,
- height : bottom - top
- };
- },
-
- hit : function (options) {
- var
- data = options.data,
- args = options.args,
- mouse = args[0],
- n = args[1],
- x = mouse.x,
- y = mouse.y,
- hitGeometry = this.getBarGeometry(x, y, options),
- width = hitGeometry.width / 2,
- left = hitGeometry.left,
- geometry, i;
-
- for (i = data.length; i--;) {
- geometry = this.getBarGeometry(data[i][0], data[i][1], options);
- if (geometry.y > hitGeometry.y && Math.abs(left - geometry.left) < width) {
- n.x = data[i][0];
- n.y = data[i][1];
- n.index = i;
- n.seriesIndex = options.index;
- }
- }
- },
-
- drawHit : function (options) {
- // TODO hits for stacked bars; implement using calculateStack option?
- var
- context = options.context,
- args = options.args,
- geometry = this.getBarGeometry(args.x, args.y, options),
- left = geometry.left,
- top = geometry.top,
- width = geometry.width,
- height = geometry.height;
-
- context.save();
- context.strokeStyle = options.color;
- context.lineWidth = options.lineWidth;
- this.translate(context, options.horizontal);
-
- // Draw highlight
- context.beginPath();
- context.moveTo(left, top + height);
- context.lineTo(left, top);
- context.lineTo(left + width, top);
- context.lineTo(left + width, top + height);
- if (options.fill) {
- context.fillStyle = options.fillStyle;
- context.fill();
- }
- context.stroke();
- context.closePath();
-
- context.restore();
- },
-
- clearHit: function (options) {
- var
- context = options.context,
- args = options.args,
- geometry = this.getBarGeometry(args.x, args.y, options),
- left = geometry.left,
- width = geometry.width,
- top = geometry.top,
- height = geometry.height,
- lineWidth = 2 * options.lineWidth;
-
- context.save();
- this.translate(context, options.horizontal);
- context.clearRect(
- left - lineWidth,
- Math.min(top, top + height) - lineWidth,
- width + 2 * lineWidth,
- Math.abs(height) + 2 * lineWidth
- );
- context.restore();
- },
-
- extendXRange : function (axis, data, options, bars) {
- this._extendRange(axis, data, options, bars);
- },
-
- extendYRange : function (axis, data, options, bars) {
- this._extendRange(axis, data, options, bars);
- },
- _extendRange: function (axis, data, options, bars) {
-
- var
- max = axis.options.max;
-
- if (_.isNumber(max) || _.isString(max)) return;
-
- var
- newmin = axis.min,
- newmax = axis.max,
- horizontal = options.horizontal,
- orientation = axis.orientation,
- positiveSums = this.positiveSums || {},
- negativeSums = this.negativeSums || {},
- value, datum, index, j;
-
- // Sides of bars
- if ((orientation == 1 && !horizontal) || (orientation == -1 && horizontal)) {
- if (options.centered) {
- newmax = Math.max(axis.datamax + options.barWidth, newmax);
- newmin = Math.min(axis.datamin - options.barWidth, newmin);
- }
- }
-
- if (options.stacked &&
- ((orientation == 1 && horizontal) || (orientation == -1 && !horizontal))){
-
- for (j = data.length; j--;) {
- value = data[j][(orientation == 1 ? 1 : 0)]+'';
- datum = data[j][(orientation == 1 ? 0 : 1)];
-
- // Positive
- if (datum > 0) {
- positiveSums[value] = (positiveSums[value] || 0) + datum;
- newmax = Math.max(newmax, positiveSums[value]);
- }
-
- // Negative
- else {
- negativeSums[value] = (negativeSums[value] || 0) + datum;
- newmin = Math.min(newmin, negativeSums[value]);
- }
- }
- }
-
- // End of bars
- if ((orientation == 1 && horizontal) || (orientation == -1 && !horizontal)) {
- if (options.topPadding && (axis.max === axis.datamax || (options.stacked && this.stackMax !== newmax))) {
- newmax += options.topPadding * (newmax - newmin);
- }
- }
-
- this.stackMin = newmin;
- this.stackMax = newmax;
- this.negativeSums = negativeSums;
- this.positiveSums = positiveSums;
-
- axis.max = newmax;
- axis.min = newmin;
- }
-
-});
-
-/** Bubbles **/
-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 (options) {
- var
- context = options.context,
- shadowSize = options.shadowSize;
-
- context.save();
- context.lineWidth = options.lineWidth;
-
- // Shadows
- context.fillStyle = 'rgba(0,0,0,0.05)';
- context.strokeStyle = 'rgba(0,0,0,0.05)';
- this.plot(options, shadowSize / 2);
- context.strokeStyle = 'rgba(0,0,0,0.1)';
- this.plot(options, shadowSize / 4);
-
- // Chart
- context.strokeStyle = options.color;
- context.fillStyle = options.fillStyle;
- this.plot(options);
-
- context.restore();
- },
- plot : function (options, offset) {
-
- var
- data = options.data,
- context = options.context,
- geometry,
- i, x, y, z;
-
- offset = offset || 0;
-
- for (i = 0; i < data.length; ++i){
-
- geometry = this.getGeometry(data[i], options);
-
- context.beginPath();
- context.arc(geometry.x + offset, geometry.y + offset, geometry.z, 0, 2 * Math.PI, true);
- context.stroke();
- if (options.fill) context.fill();
- context.closePath();
- }
- },
- getGeometry : function (point, options) {
- return {
- x : options.xScale(point[0]),
- y : options.yScale(point[1]),
- z : point[2] * options.baseRadius
- };
- },
- hit : function (options) {
- var
- data = options.data,
- args = options.args,
- mouse = args[0],
- n = args[1],
- x = mouse.x,
- y = mouse.y,
- geometry,
- dx, dy;
-
- for (i = data.length; i--;) {
- geometry = this.getGeometry(data[i], options);
-
- dx = geometry.x - options.xScale(x);
- dy = geometry.y - options.yScale(y);
-
- if (Math.sqrt(dx * dx + dy * dy) < geometry.z) {
- n.x = data[i][0];
- n.y = data[i][1];
- n.index = i;
- n.seriesIndex = options.index;
- }
- }
- },
- drawHit : function (options) {
-
- var
- context = options.context,
- geometry = this.getGeometry(options.data[options.args.index], options);
-
- context.save();
- context.lineWidth = options.lineWidth;
- context.fillStyle = options.fillStyle;
- context.strokeStyle = options.color;
- context.beginPath();
- context.arc(geometry.x, geometry.y, geometry.z, 0, 2 * Math.PI, true);
- context.fill();
- context.stroke();
- context.closePath();
- context.restore();
- },
- clearHit : function (options) {
-
- var
- context = options.context,
- geometry = this.getGeometry(options.data[options.args.index], options),
- offset = geometry.z + options.lineWidth;
-
- context.save();
- context.clearRect(
- geometry.x - offset,
- geometry.y - offset,
- 2 * offset,
- 2 * offset
- );
- context.restore();
- }
- // TODO Add a hit calculation method (like pie)
-});
-
-/** 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
- // TODO Test this barcharts option.
- barcharts: false // => draw as barcharts (not standard bars but financial barcharts)
- },
-
- draw : function (options) {
-
- var
- context = options.context;
-
- context.save();
- context.lineJoin = 'miter';
- context.lineCap = 'butt';
- // @TODO linewidth not interpreted the right way.
- context.lineWidth = options.wickLineWidth || options.lineWidth;
-
- this.plot(options);
-
- context.restore();
- },
-
- plot : function (options) {
-
- var
- data = options.data,
- context = options.context,
- xScale = options.xScale,
- yScale = options.yScale,
- width = options.candleWidth / 2,
- shadowSize = options.shadowSize,
- lineWidth = options.lineWidth,
- wickLineWidth = options.wickLineWidth,
- pixelOffset = (wickLineWidth % 2) / 2,
- color,
- datum, x, y,
- open, high, low, close,
- left, right, bottom, top, bottom2, top2,
- i;
-
- if (data.length < 1) return;
-
- for (i = 0; i < data.length; i++) {
- datum = data[i];
- x = datum[0];
- open = datum[1];
- high = datum[2];
- low = datum[3];
- close = datum[4];
- left = xScale(x - width);
- right = xScale(x + width);
- bottom = yScale(low);
- top = yScale(high);
- bottom2 = yScale(Math.min(open, close));
- top2 = yScale(Math.max(open, close));
-
- /*
- // TODO skipping
- if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)
- continue;
- */
-
- color = options[open > close ? 'downFillColor' : 'upFillColor'];
-
- // Fill the candle.
- // TODO Test the barcharts option
- if (options.fill && !options.barcharts) {
- context.fillStyle = 'rgba(0,0,0,0.05)';
- context.fillRect(left + shadowSize, top2 + shadowSize, right - left, bottom2 - top2);
- context.save();
- context.globalAlpha = options.fillOpacity;
- context.fillStyle = color;
- context.fillRect(left, top2 + lineWidth, right - left, bottom2 - top2);
- context.restore();
- }
-
- // Draw candle outline/border, high, low.
- if (lineWidth || wickLineWidth) {
-
- x = Math.floor((left + right) / 2) + pixelOffset;
-
- context.strokeStyle = color;
- context.beginPath();
-
- // TODO Again with the bartcharts
- if (options.barcharts) {
-
- context.moveTo(x, Math.floor(top + width));
- context.lineTo(x, Math.floor(bottom + width));
-
- y = Math.floor(open + width) + 0.5;
- context.moveTo(Math.floor(left) + pixelOffset, y);
- context.lineTo(x, y);
-
- y = Math.floor(close + width) + 0.5;
- context.moveTo(Math.floor(right) + pixelOffset, y);
- context.lineTo(x, y);
- } else {
- context.strokeRect(left, top2 + lineWidth, right - left, bottom2 - top2);
-
- context.moveTo(x, Math.floor(top2 + lineWidth));
- context.lineTo(x, Math.floor(top + lineWidth));
- context.moveTo(x, Math.floor(bottom2 + lineWidth));
- context.lineTo(x, Math.floor(bottom + lineWidth));
- }
-
- context.closePath();
- context.stroke();
- }
- }
- },
- extendXRange: function (axis, data, options) {
- if (axis.options.max === null) {
- axis.max = Math.max(axis.datamax + 0.5, axis.max);
- axis.min = Math.min(axis.datamin - 0.5, axis.min);
- }
- }
-});
-
-/** Gantt
- * Base on data in form [s,y,d] where:
- * y - executor or simply y value
- * s - task start value
- * d - task duration
- * **/
-Flotr.addType('gantt', {
- options: {
- show: false, // => setting to true will show gantt, 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
- centered: true // => center the bars to their x axis value
- },
- /**
- * Draws gantt series in the canvas element.
- * @param {Object} series - Series with options.gantt.show = true.
- */
- draw: function(series) {
- var ctx = this.ctx,
- bw = series.gantt.barWidth,
- lw = Math.min(series.gantt.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;
-
- ctx.save();
- this.gantt.plotShadows(series, bw, 0, series.gantt.fill);
- ctx.restore();
-
- if(series.gantt.fill){
- var color = series.gantt.fillColor || series.color;
- ctx.fillStyle = this.processColor(color, {opacity: series.gantt.fillOpacity});
- }
-
- this.gantt.plot(series, bw, 0, series.gantt.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, i;
-
- for(i = 0; i < data.length; i++){
- var y = data[i][0],
- s = data[i][1],
- d = data[i][2],
- drawLeft = true, drawTop = true, drawRight = true;
-
- if (s === null || d === null) continue;
-
- var left = s,
- right = s + d,
- bottom = y - (series.gantt.centered ? barWidth/2 : 0),
- top = y + barWidth - (series.gantt.centered ? barWidth/2 : 0);
-
- 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)
- drawTop = false;
- }
-
- if(bottom < ya.min)
- bottom = ya.min;
-
- if(top > ya.max){
- top = ya.max;
- if (ya.lastSerie != series)
- 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();
- ctx.closePath();
- }
-
- /**
- * Draw bar outline/border.
- */
- if(series.gantt.lineWidth && (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();
- ctx.closePath();
- }
- }
- },
- plotShadows: function(series, barWidth, offset){
- var data = series.data;
- if(data.length < 1) return;
-
- var i, y, s, d,
- xa = series.xaxis,
- ya = series.yaxis,
- ctx = this.ctx,
- sw = this.options.shadowSize;
-
- for(i = 0; i < data.length; i++){
- y = data[i][0];
- s = data[i][1];
- d = data[i][2];
-
- if (s === null || d === null) continue;
-
- var left = s,
- right = s + d,
- bottom = y - (series.gantt.centered ? barWidth/2 : 0),
- top = y + barWidth - (series.gantt.centered ? barWidth/2 : 0);
-
- 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 = 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.plotHeight), width, height);
- }
- },
- extendXRange: function(axis) {
- if(axis.options.max === null){
- var newmin = axis.min,
- newmax = axis.max,
- i, j, x, s, g,
- stackedSumsPos = {},
- stackedSumsNeg = {},
- lastSerie = null;
-
- for(i = 0; i < this.series.length; ++i){
- s = this.series[i];
- g = s.gantt;
-
- if(g.show && s.xaxis == axis) {
- for (j = 0; j < s.data.length; j++) {
- if (g.show) {
- y = s.data[j][0]+'';
- stackedSumsPos[y] = Math.max((stackedSumsPos[y] || 0), s.data[j][1]+s.data[j][2]);
- lastSerie = s;
- }
- }
- for (j in stackedSumsPos) {
- newmax = Math.max(stackedSumsPos[j], newmax);
- }
- }
- }
- axis.lastSerie = lastSerie;
- axis.max = newmax;
- axis.min = newmin;
- }
- },
- extendYRange: function(axis){
- if(axis.options.max === null){
- var newmax = Number.MIN_VALUE,
- newmin = Number.MAX_VALUE,
- i, j, s, g,
- stackedSumsPos = {},
- stackedSumsNeg = {},
- lastSerie = null;
-
- for(i = 0; i < this.series.length; ++i){
- s = this.series[i];
- g = s.gantt;
-
- if (g.show && !s.hide && s.yaxis == axis) {
- var datamax = Number.MIN_VALUE, datamin = Number.MAX_VALUE;
- for(j=0; j < s.data.length; j++){
- datamax = Math.max(datamax,s.data[j][0]);
- datamin = Math.min(datamin,s.data[j][0]);
- }
-
- if (g.centered) {
- newmax = Math.max(datamax + 0.5, newmax);
- newmin = Math.min(datamin - 0.5, newmin);
- }
- else {
- newmax = Math.max(datamax + 1, newmax);
- newmin = Math.min(datamin, newmin);
- }
- // For normal horizontal bars
- if (g.barWidth + datamax > newmax){
- newmax = axis.max + g.barWidth;
- }
- }
- }
- axis.lastSerie = lastSerie;
- axis.max = newmax;
- axis.min = newmin;
- axis.tickSize = Flotr.getTickSize(axis.options.noTicks, newmin, newmax, axis.options.tickDecimals);
- }
- }
-});
-
-/** Markers **/
-/**
- * Formats the marker labels.
- * @param {Object} obj - Marker value Object {x:..,y:..}
- * @return {String} Formatted marker string
- */
-(function () {
-
-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
- color: '#000000', // => text color
- 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)
- verticalMargin: 0, // => the margin between the point and the text.
- labelFormatter: Flotr.defaultMarkerFormatter,
- fontSize: Flotr.defaultOptions.fontSize,
- stacked: false, // => true if markers should be stacked
- stackingType: 'b', // => define staching behavior, (b- bars like, a - area like) (see Issue 125 for details)
- horizontal: false // => true if markers should be horizontal (For now only in a case on horizontal stacked bars, stacks should be calculated horizontaly)
- },
-
- // TODO test stacked markers.
- stack : {
- positive : [],
- negative : [],
- values : []
- },
-
- draw : function (options) {
-
- var
- data = options.data,
- context = options.context,
- stack = options.stacked ? options.stack : false,
- stackType = options.stackingType,
- stackOffsetNeg,
- stackOffsetPos,
- stackOffset,
- i, x, y, label;
-
- context.save();
- context.lineJoin = 'round';
- context.lineWidth = options.lineWidth;
- context.strokeStyle = 'rgba(0,0,0,0.5)';
- context.fillStyle = options.fillStyle;
-
- function stackPos (a, b) {
- stackOffsetPos = stack.negative[a] || 0;
- stackOffsetNeg = stack.positive[a] || 0;
- if (b > 0) {
- stack.positive[a] = stackOffsetPos + b;
- return stackOffsetPos + b;
- } else {
- stack.negative[a] = stackOffsetNeg + b;
- return stackOffsetNeg + b;
- }
- }
-
- for (i = 0; i < data.length; ++i) {
-
- x = data[i][0];
- y = data[i][1];
-
- if (stack) {
- if (stackType == 'b') {
- if (options.horizontal) y = stackPos(y, x);
- else x = stackPos(x, y);
- } else if (stackType == 'a') {
- stackOffset = stack.values[x] || 0;
- stack.values[x] = stackOffset + y;
- y = stackOffset + y;
- }
- }
-
- label = options.labelFormatter({x: x, y: y, index: i, data : data});
- this.plot(options.xScale(x), options.yScale(y), label, options);
- }
- context.restore();
- },
- plot: function(x, y, label, options) {
- var context = options.context;
- if (isImage(label) && !label.complete) {
- throw 'Marker image not loaded.';
- } else {
- this._plot(x, y, label, options);
- }
- },
-
- _plot: function(x, y, label, options) {
- var context = options.context,
- margin = 2,
- left = x,
- top = y,
- dim;
-
- if (isImage(label))
- dim = {height : label.height, width: label.width};
- else
- dim = options.text.canvas(label);
-
- 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 + options.verticalMargin;
- else top += options.verticalMargin;
-
- left = Math.floor(left)+0.5;
- top = Math.floor(top)+0.5;
-
- if(options.fill)
- context.fillRect(left, top, dim.width, dim.height);
-
- if(options.stroke)
- context.strokeRect(left, top, dim.width, dim.height);
-
- if (isImage(label))
- context.drawImage(label, left+margin, top+margin);
- else
- Flotr.drawText(context, label, left+margin, top+margin, {textBaseline: 'top', textAlign: 'left', size: options.fontSize, color: options.color});
- }
-});
-
-function isImage (i) {
- return typeof i === 'object' && i.constructor && (Image ? true : i.constructor === Image);
-}
-
-})();
-
-/** Pie **/
-/**
- * Formats the pies labels.
- * @param {Object} slice - Slice object
- * @return {String} Formatted pie label string
- */
-(function () {
-
-var
- _ = Flotr._;
-
-Flotr.defaultPieLabelFormatter = function (total, value) {
- return (100 * value / total).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
- },
-
- draw : function (options) {
-
- // TODO 3D charts what?
-
- var
- data = options.data,
- context = options.context,
- canvas = context.canvas,
- lineWidth = options.lineWidth,
- shadowSize = options.shadowSize,
- sizeRatio = options.sizeRatio,
- height = options.height,
- width = options.width,
- explode = options.explode,
- color = options.color,
- fill = options.fill,
- fillStyle = options.fillStyle,
- radius = Math.min(canvas.width, canvas.height) * sizeRatio / 2,
- value = data[0][1],
- html = [],
- vScale = 1,//Math.cos(series.pie.viewAngle);
- measure = Math.PI * 2 * value / this.total,
- startAngle = this.startAngle || (2 * Math.PI * options.startAngle), // TODO: this initial startAngle is already in radians (fixing will be test-unstable)
- endAngle = startAngle + measure,
- bisection = startAngle + measure / 2,
- label = options.labelFormatter(this.total, value),
- //plotTickness = Math.sin(series.pie.viewAngle)*series.pie.spliceThickness / vScale;
- explodeCoeff = explode + radius + 4,
- distX = Math.cos(bisection) * explodeCoeff,
- distY = Math.sin(bisection) * explodeCoeff,
- textAlign = distX < 0 ? 'right' : 'left',
- textBaseline = distY > 0 ? 'top' : 'bottom',
- style,
- x, y,
- distX, distY;
-
- context.save();
- context.translate(width / 2, height / 2);
- context.scale(1, vScale);
-
- x = Math.cos(bisection) * explode;
- y = Math.sin(bisection) * explode;
-
- // Shadows
- if (shadowSize > 0) {
- this.plotSlice(x + shadowSize, y + shadowSize, radius, startAngle, endAngle, context);
- if (fill) {
- context.fillStyle = 'rgba(0,0,0,0.1)';
- context.fill();
- }
- }
-
- this.plotSlice(x, y, radius, startAngle, endAngle, context);
- if (fill) {
- context.fillStyle = fillStyle;
- context.fill();
- }
- context.lineWidth = lineWidth;
- context.strokeStyle = color;
- context.stroke();
-
- style = {
- size : options.fontSize * 1.2,
- color : options.fontColor,
- weight : 1.5
- };
-
- if (label) {
- if (options.htmlText || !options.textEnabled) {
- divStyle = 'position:absolute;' + textBaseline + ':' + (height / 2 + (textBaseline === 'top' ? distY : -distY)) + 'px;';
- divStyle += textAlign + ':' + (width / 2 + (textAlign === 'right' ? -distX : distX)) + 'px;';
- html.push('<div style="', divStyle, '" class="flotr-grid-label">', label, '</div>');
- }
- else {
- style.textAlign = textAlign;
- style.textBaseline = textBaseline;
- Flotr.drawText(context, label, distX, distY, style);
- }
- }
-
- if (options.htmlText || !options.textEnabled) {
- var div = Flotr.DOM.node('<div style="color:' + options.fontColor + '" class="flotr-labels"></div>');
- Flotr.DOM.insert(div, html.join(''));
- Flotr.DOM.insert(options.element, div);
- }
-
- context.restore();
-
- // New start angle
- this.startAngle = endAngle;
- this.slices = this.slices || [];
- this.slices.push({
- radius : Math.min(canvas.width, canvas.height) * sizeRatio / 2,
- x : x,
- y : y,
- explode : explode,
- start : startAngle,
- end : endAngle
- });
- },
- plotSlice : function (x, y, radius, startAngle, endAngle, context) {
- context.beginPath();
- context.moveTo(x, y);
- context.arc(x, y, radius, startAngle, endAngle, false);
- context.lineTo(x, y);
- context.closePath();
- },
- hit : function (options) {
-
- var
- data = options.data[0],
- args = options.args,
- index = options.index,
- mouse = args[0],
- n = args[1],
- slice = this.slices[index],
- x = mouse.relX - options.width / 2,
- y = mouse.relY - options.height / 2,
- r = Math.sqrt(x * x + y * y),
- theta = Math.atan(y / x),
- circle = Math.PI * 2,
- explode = slice.explode || options.explode,
- start = slice.start % circle,
- end = slice.end % circle;
-
- if (x < 0) {
- theta += Math.PI;
- } else if (x > 0 && y < 0) {
- theta += circle;
- }
-
- if (r < slice.radius + explode && r > explode) {
- if ((start > end && (theta < end || theta > start)) ||
- (theta > start && theta < end)) {
-
- // TODO Decouple this from hit plugin (chart shouldn't know what n means)
- n.x = data[0];
- n.y = data[1];
- n.sAngle = start;
- n.eAngle = end;
- n.index = 0;
- n.seriesIndex = index;
- n.fraction = data[1] / this.total;
- }
- }
- },
- drawHit: function (options) {
- var
- context = options.context,
- slice = this.slices[options.args.seriesIndex];
-
- context.save();
- context.translate(options.width / 2, options.height / 2);
- this.plotSlice(slice.x, slice.y, slice.radius, slice.start, slice.end, context);
- context.stroke();
- context.restore();
- },
- clearHit : function (options) {
- var
- context = options.context,
- slice = this.slices[options.args.seriesIndex],
- padding = 2 * options.lineWidth,
- radius = slice.radius + padding;
-
- context.save();
- context.translate(options.width / 2, options.height / 2);
- context.clearRect(
- slice.x - radius,
- slice.y - radius,
- 2 * radius + padding,
- 2 * radius + padding
- );
- context.restore();
- },
- extendYRange : function (axis, data) {
- this.total = (this.total || 0) + data[0][1];
- }
-});
-})();
-
-/** 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
- },
-
- draw : function (options) {
- var
- context = options.context,
- lineWidth = options.lineWidth,
- shadowSize = options.shadowSize;
-
- context.save();
-
- if (shadowSize > 0) {
- context.lineWidth = shadowSize / 2;
-
- context.strokeStyle = 'rgba(0,0,0,0.1)';
- this.plot(options, shadowSize / 2 + context.lineWidth / 2);
-
- context.strokeStyle = 'rgba(0,0,0,0.2)';
- this.plot(options, context.lineWidth / 2);
- }
-
- context.lineWidth = options.lineWidth;
- context.strokeStyle = options.color;
- context.fillStyle = options.fillColor || options.color;
-
- this.plot(options);
- context.restore();
- },
-
- plot : function (options, offset) {
- var
- data = options.data,
- context = options.context,
- xScale = options.xScale,
- yScale = options.yScale,
- i, x, y;
-
- for (i = data.length - 1; i > -1; --i) {
- y = data[i][1];
- if (y === null) continue;
-
- x = xScale(data[i][0]);
- y = yScale(y);
-
- if (x < 0 || x > options.width || y < 0 || y > options.height) continue;
-
- context.beginPath();
- if (offset) {
- context.arc(x, y + offset, options.radius, 0, Math.PI, false);
- } else {
- context.arc(x, y, options.radius, 0, 2 * Math.PI, true);
- if (options.fill) context.fill();
- }
- context.stroke();
- context.closePath();
- }
- }
-});
-
-/** Radar **/
-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 (options) {
- var
- context = options.context,
- shadowSize = options.shadowSize;
-
- context.save();
- context.translate(options.width / 2, options.height / 2);
- context.lineWidth = options.lineWidth;
-
- // Shadow
- context.fillStyle = 'rgba(0,0,0,0.05)';
- context.strokeStyle = 'rgba(0,0,0,0.05)';
- this.plot(options, shadowSize / 2);
- context.strokeStyle = 'rgba(0,0,0,0.1)';
- this.plot(options, shadowSize / 4);
-
- // Chart
- context.strokeStyle = options.color;
- context.fillStyle = options.fillStyle;
- this.plot(options);
-
- context.restore();
- },
- plot : function (options, offset) {
- var
- data = options.data,
- context = options.context,
- radius = Math.min(options.height, options.width) * options.radiusRatio / 2,
- step = 2 * Math.PI / data.length,
- angle = -Math.PI / 2,
- i, ratio;
-
- offset = offset || 0;
-
- context.beginPath();
- for (i = 0; i < data.length; ++i) {
- ratio = data[i][1] / this.max;
-
- context[i === 0 ? 'moveTo' : 'lineTo'](
- Math.cos(i * step + angle) * radius * ratio + offset,
- Math.sin(i * step + angle) * radius * ratio + offset
- );
- }
- context.closePath();
- if (options.fill) context.fill();
- context.stroke();
- },
- extendYRange : function (axis, data) {
- this.max = Math.max(axis.max, this.max || -Number.MAX_VALUE);
- }
-});
-
-Flotr.addType('timeline', {
- options: {
- show: false,
- lineWidth: 1,
- barWidth: 0.2,
- fill: true,
- fillColor: null,
- fillOpacity: 0.4,
- centered: true
- },
-
- draw : function (options) {
-
- var
- context = options.context;
-
- context.save();
- context.lineJoin = 'miter';
- context.lineWidth = options.lineWidth;
- context.strokeStyle = options.color;
- context.fillStyle = options.fillStyle;
-
- this.plot(options);
-
- context.restore();
- },
-
- plot : function (options) {
-
- var
- data = options.data,
- context = options.context,
- xScale = options.xScale,
- yScale = options.yScale,
- barWidth = options.barWidth,
- lineWidth = options.lineWidth,
- i;
-
- Flotr._.each(data, function (timeline) {
-
- var
- x = timeline[0],
- y = timeline[1],
- w = timeline[2],
- h = barWidth,
-
- xt = Math.ceil(xScale(x)),
- wt = Math.ceil(xScale(x + w)) - xt,
- yt = Math.round(yScale(y)),
- ht = Math.round(yScale(y - h)) - yt,
-
- x0 = xt - lineWidth / 2,
- y0 = Math.round(yt - ht / 2) - lineWidth / 2;
-
- context.strokeRect(x0, y0, wt, ht);
- context.fillRect(x0, y0, wt, ht);
-
- });
- },
-
- extendRange : function (series) {
-
- var
- data = series.data,
- xa = series.xaxis,
- ya = series.yaxis,
- w = series.timeline.barWidth;
-
- if (xa.options.min === null)
- xa.min = xa.datamin - w / 2;
-
- if (xa.options.max === null) {
-
- var
- max = xa.max;
-
- Flotr._.each(data, function (timeline) {
- max = Math.max(max, timeline[0] + timeline[2]);
- }, this);
-
- xa.max = max + w / 2;
- }
-
- if (ya.options.min === null)
- ya.min = ya.datamin - w;
- if (ya.options.min === null)
- ya.max = ya.datamax + w;
- }
-
-});
-
-(function () {
-
-var D = Flotr.DOM;
-
-Flotr.addPlugin('crosshair', {
- options: {
- mode: null, // => one of null, 'x', 'y' or 'xy'
- color: '#FF0000', // => crosshair color
- hideCursor: true // => hide the cursor when the crosshair is shown
- },
- callbacks: {
- 'flotr:mousemove': function(e, pos) {
- if (this.options.crosshair.mode) {
- this.crosshair.clearCrosshair();
- this.crosshair.drawCrosshair(pos);
- }
- }
- },
- /**
- * Draws the selection box.
- */
- drawCrosshair: function(pos) {
- var octx = this.octx,
- options = this.options.crosshair,
- 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;
- D.removeClass(this.el, 'flotr-crosshair');
- return;
- }
-
- if (options.hideCursor) {
- this.el.style.cursor = 'none';
- D.addClass(this.el, 'flotr-crosshair');
- }
-
- octx.save();
- octx.strokeStyle = options.color;
- octx.lineWidth = 1;
- octx.beginPath();
-
- if (options.mode.indexOf('x') != -1) {
- octx.moveTo(x, plotOffset.top);
- octx.lineTo(x, plotOffset.top + this.plotHeight);
- }
-
- if (options.mode.indexOf('y') != -1) {
- octx.moveTo(plotOffset.left, y);
- octx.lineTo(plotOffset.left + this.plotWidth, y);
- }
-
- octx.stroke();
- octx.restore();
- },
- /**
- * Removes the selection box from the overlay canvas.
- */
- clearCrosshair: function() {
-
- var
- plotOffset = this.plotOffset,
- position = this.lastMousePos,
- context = this.octx;
-
- if (position) {
- context.clearRect(
- position.relX + plotOffset.left,
- plotOffset.top,
- 1,
- this.plotHeight + 1
- );
- context.clearRect(
- plotOffset.left,
- position.relY + plotOffset.top,
- this.plotWidth + 1,
- 1
- );
- }
- }
-});
-})();
-
-(function() {
-
-var
- D = Flotr.DOM,
- _ = Flotr._;
-
-function getImage (type, canvas, width, height) {
-
- // TODO add scaling for w / h
- var
- mime = 'image/'+type,
- data = canvas.toDataURL(mime),
- image = new Image();
- image.src = data;
- return image;
-}
-
-Flotr.addPlugin('download', {
-
- saveImage: function (type, width, height, replaceCanvas) {
- var image = null;
- if (Flotr.isIE && Flotr.isIE < 9) {
- image = '<html><body>'+this.canvas.firstChild.innerHTML+'</body></html>';
- return window.open().document.write(image);
- }
-
- if (type !== 'jpeg' && type !== 'png') return;
-
- image = getImage(type, this.canvas, width, height);
-
- if (_.isElement(image) && replaceCanvas) {
- this.download.restoreCanvas();
- D.hide(this.canvas);
- D.hide(this.overlay);
- D.setStyles({position: 'absolute'});
- D.insert(this.el, image);
- this.saveImageElement = image;
- } else {
- return window.open(image.src);
- }
- },
-
- restoreCanvas: function() {
- D.show(this.canvas);
- D.show(this.overlay);
- if (this.saveImageElement) this.el.removeChild(this.saveImageElement);
- this.saveImageElement = null;
- }
-});
-
-})();
-
-(function () {
-
-var E = Flotr.EventAdapter,
- _ = Flotr._;
-
-Flotr.addPlugin('graphGrid', {
-
- callbacks: {
- 'flotr:beforedraw' : function () {
- this.graphGrid.drawGrid();
- },
- 'flotr:afterdraw' : function () {
- this.graphGrid.drawOutline();
- }
- },
-
- drawGrid: function(){
-
- var
- ctx = this.ctx,
- options = this.options,
- grid = options.grid,
- verticalLines = grid.verticalLines,
- horizontalLines = grid.horizontalLines,
- minorVerticalLines = grid.minorVerticalLines,
- minorHorizontalLines = grid.minorHorizontalLines,
- plotHeight = this.plotHeight,
- plotWidth = this.plotWidth,
- a, v, i, j;
-
- if(verticalLines || minorVerticalLines ||
- horizontalLines || minorHorizontalLines){
- E.fire(this.el, 'flotr:beforegrid', [this.axes.x, this.axes.y, options, this]);
- }
- ctx.save();
- ctx.lineWidth = 1;
- ctx.strokeStyle = grid.tickColor;
-
- function circularHorizontalTicks (ticks) {
- for(i = 0; i < ticks.length; ++i){
- var ratio = ticks[i].v / a.max;
- for(j = 0; j <= sides; ++j){
- ctx[j === 0 ? 'moveTo' : 'lineTo'](
- Math.cos(j*coeff+angle)*radius*ratio,
- Math.sin(j*coeff+angle)*radius*ratio
- );
- }
- }
- }
- function drawGridLines (ticks, callback) {
- _.each(_.pluck(ticks, 'v'), function(v){
- // Don't show lines on upper and lower bounds.
- if ((v <= a.min || v >= a.max) ||
- (v == a.min || v == a.max) && grid.outlineWidth)
- return;
- callback(Math.floor(a.d2p(v)) + ctx.lineWidth/2);
- });
- }
- function drawVerticalLines (x) {
- ctx.moveTo(x, 0);
- ctx.lineTo(x, plotHeight);
- }
- function drawHorizontalLines (y) {
- ctx.moveTo(0, y);
- ctx.lineTo(plotWidth, y);
- }
-
- if (grid.circular) {
- ctx.translate(this.plotOffset.left+plotWidth/2, this.plotOffset.top+plotHeight/2);
- var radius = Math.min(plotHeight, plotWidth)*options.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();
-
- a = this.axes.y;
-
- if(horizontalLines){
- circularHorizontalTicks(a.ticks);
- }
- if(minorHorizontalLines){
- circularHorizontalTicks(a.minorTicks);
- }
-
- if(verticalLines){
- _.times(sides, function(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(grid.backgroundColor){
- ctx.fillStyle = this.processColor(grid.backgroundColor, {x1: 0, y1: 0, x2: plotWidth, y2: plotHeight});
- ctx.fillRect(0, 0, plotWidth, plotHeight);
- }
-
- ctx.beginPath();
-
- a = this.axes.x;
- if (verticalLines) drawGridLines(a.ticks, drawVerticalLines);
- if (minorVerticalLines) drawGridLines(a.minorTicks, drawVerticalLines);
-
- a = this.axes.y;
- if (horizontalLines) drawGridLines(a.ticks, drawHorizontalLines);
- if (minorHorizontalLines) drawGridLines(a.minorTicks, drawHorizontalLines);
-
- ctx.stroke();
- }
-
- ctx.restore();
- if(verticalLines || minorVerticalLines ||
- horizontalLines || minorHorizontalLines){
- E.fire(this.el, 'flotr:aftergrid', [this.axes.x, this.axes.y, options, this]);
- }
- },
-
- drawOutline: function(){
- var
- that = this,
- options = that.options,
- grid = options.grid,
- outline = grid.outline,
- ctx = that.ctx,
- backgroundImage = grid.backgroundImage,
- plotOffset = that.plotOffset,
- leftOffset = plotOffset.left,
- topOffset = plotOffset.top,
- plotWidth = that.plotWidth,
- plotHeight = that.plotHeight,
- v, img, src, left, top, globalAlpha;
-
- if (!grid.outlineWidth) return;
-
- ctx.save();
-
- if (grid.circular) {
- ctx.translate(leftOffset + plotWidth / 2, topOffset + plotHeight / 2);
- var radius = Math.min(plotHeight, plotWidth) * options.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 = grid.outlineWidth;
- ctx.strokeStyle = grid.color;
- ctx.lineJoin = 'round';
-
- for(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(leftOffset, topOffset);
-
- // Draw axis/grid border.
- var lw = grid.outlineWidth,
- orig = 0.5-lw+((lw+1)%2/2),
- lineTo = 'lineTo',
- moveTo = 'moveTo';
- ctx.lineWidth = lw;
- ctx.strokeStyle = grid.color;
- ctx.lineJoin = 'miter';
- ctx.beginPath();
- ctx.moveTo(orig, orig);
- plotWidth = plotWidth - (lw / 2) % 1;
- plotHeight = plotHeight + lw / 2;
- ctx[outline.indexOf('n') !== -1 ? lineTo : moveTo](plotWidth, orig);
- ctx[outline.indexOf('e') !== -1 ? lineTo : moveTo](plotWidth, plotHeight);
- ctx[outline.indexOf('s') !== -1 ? lineTo : moveTo](orig, plotHeight);
- ctx[outline.indexOf('w') !== -1 ? lineTo : moveTo](orig, orig);
- ctx.stroke();
- ctx.closePath();
- }
-
- ctx.restore();
-
- if (backgroundImage) {
-
- src = backgroundImage.src || backgroundImage;
- left = (parseInt(backgroundImage.left, 10) || 0) + plotOffset.left;
- top = (parseInt(backgroundImage.top, 10) || 0) + plotOffset.top;
- img = new Image();
-
- img.onload = function() {
- ctx.save();
- if (backgroundImage.alpha) ctx.globalAlpha = backgroundImage.alpha;
- ctx.globalCompositeOperation = 'destination-over';
- ctx.drawImage(img, 0, 0, img.width, img.height, left, top, plotWidth, plotHeight);
- ctx.restore();
- };
-
- img.src = src;
- }
- }
-});
-
-})();
-
-(function () {
-
-var
- D = Flotr.DOM,
- _ = Flotr._,
- flotr = Flotr,
- S_MOUSETRACK = '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;';
-
-Flotr.addPlugin('hit', {
- callbacks: {
- 'flotr:mousemove': function(e, pos) {
- this.hit.track(pos);
- },
- 'flotr:click': function(pos) {
- this.hit.track(pos);
- },
- 'flotr:mouseout': function() {
- this.hit.clearHit();
- }
- },
- track : function (pos) {
- if (this.options.mouse.track || _.any(this.series, function(s){return s.mouse && s.mouse.track;})) {
- this.hit.hit(pos);
- }
- },
- /**
- * Try a method on a graph type. If the method exists, execute it.
- * @param {Object} series
- * @param {String} method Method name.
- * @param {Array} args Arguments applied to method.
- * @return executed successfully or failed.
- */
- executeOnType: function(s, method, args){
- var
- success = false,
- options;
-
- if (!_.isArray(s)) s = [s];
-
- function e(s, index) {
- _.each(_.keys(flotr.graphTypes), function (type) {
- if (s[type] && s[type].show && this[type][method]) {
- options = this.getOptions(s, type);
-
- options.fill = !!s.mouse.fillColor;
- options.fillStyle = this.processColor(s.mouse.fillColor || '#ffffff', {opacity: s.mouse.fillOpacity});
- options.color = s.mouse.lineColor;
- options.context = this.octx;
- options.index = index;
-
- if (args) options.args = args;
- this[type][method].call(this[type], options);
- success = true;
- }
- }, this);
- }
- _.each(s, e, this);
-
- return success;
- },
- /**
- * Updates the mouse tracking point on the overlay.
- */
- drawHit: function(n){
- var octx = this.octx,
- s = n.series;
-
- if (s.mouse.lineColor) {
- octx.save();
- octx.lineWidth = (s.points ? s.points.lineWidth : 1);
- octx.strokeStyle = s.mouse.lineColor;
- octx.fillStyle = this.processColor(s.mouse.fillColor || '#ffffff', {opacity: s.mouse.fillOpacity});
- octx.translate(this.plotOffset.left, this.plotOffset.top);
-
- if (!this.hit.executeOnType(s, 'drawHit', n)) {
- var xa = n.xaxis,
- ya = n.yaxis;
-
- octx.beginPath();
- // TODO fix this (points) should move to general testable graph mixin
- octx.arc(xa.d2p(n.x), ya.d2p(n.y), s.points.radius || s.mouse.radius, 0, 2 * Math.PI, true);
- octx.fill();
- octx.stroke();
- octx.closePath();
- }
- octx.restore();
- }
- this.prevHit = n;
- },
- /**
- * Removes the mouse tracking point from the overlay.
- */
- clearHit: function(){
- var prev = this.prevHit,
- octx = this.octx,
- plotOffset = this.plotOffset;
- octx.save();
- octx.translate(plotOffset.left, plotOffset.top);
- if (prev) {
- if (!this.hit.executeOnType(prev.series, 'clearHit', this.prevHit)) {
- // TODO fix this (points) should move to general testable graph mixin
- var
- s = prev.series,
- lw = (s.points ? s.points.lineWidth : 1);
- offset = (s.points.radius || s.mouse.radius) + lw;
- octx.clearRect(
- prev.xaxis.d2p(prev.x) - offset,
- prev.yaxis.d2p(prev.y) - offset,
- offset*2,
- offset*2
- );
- }
- D.hide(this.mouseTrack);
- this.prevHit = null;
- }
- octx.restore();
- },
- /**
- * 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
- options = this.options,
- prevHit = this.prevHit,
- closest, sensibility, dataIndex, seriesIndex, series, value, xaxis, yaxis;
-
- if (this.series.length === 0) return;
-
- // Nearest data element.
- // dist, x, y, relX, relY, absX, absY, sAngle, eAngle, fraction, mouse,
- // xaxis, yaxis, series, index, seriesIndex
- n = {
- relX : mouse.relX,
- relY : mouse.relY,
- absX : mouse.absX,
- absY : mouse.absY
- };
-
- if (options.mouse.trackY &&
- !options.mouse.trackAll &&
- this.hit.executeOnType(this.series, 'hit', [mouse, n]))
- {
-
- if (!_.isUndefined(n.seriesIndex)) {
- series = this.series[n.seriesIndex];
- n.series = series;
- n.mouse = series.mouse;
- n.xaxis = series.xaxis;
- n.yaxis = series.yaxis;
- }
- } else {
-
- closest = this.hit.closest(mouse);
-
- if (closest) {
-
- closest = options.mouse.trackY ? closest.point : closest.x;
- seriesIndex = closest.seriesIndex;
- series = this.series[seriesIndex];
- xaxis = series.xaxis;
- yaxis = series.yaxis;
- sensibility = 2 * series.mouse.sensibility;
-
- if
- (options.mouse.trackAll ||
- (closest.distanceX < sensibility / xaxis.scale &&
- (!options.mouse.trackY || closest.distanceY < sensibility / yaxis.scale)))
- {
- n.series = series;
- n.xaxis = series.xaxis;
- n.yaxis = series.yaxis;
- n.mouse = series.mouse;
- n.x = closest.x;
- n.y = closest.y;
- n.dist = closest.distance;
- n.index = closest.dataIndex;
- n.seriesIndex = seriesIndex;
- }
- }
- }
-
- if (!prevHit || (prevHit.index !== n.index || prevHit.seriesIndex !== n.seriesIndex)) {
- this.hit.clearHit();
- if (n.series && n.mouse && n.mouse.track) {
- this.hit.drawMouseTrack(n);
- this.hit.drawHit(n);
- Flotr.EventAdapter.fire(this.el, 'flotr:hit', [n, this]);
- }
- }
- },
-
- closest : function (mouse) {
-
- var
- series = this.series,
- options = this.options,
- mouseX = mouse.x,
- mouseY = mouse.y,
- compare = Number.MAX_VALUE,
- compareX = Number.MAX_VALUE,
- closest = {},
- closestX = {},
- check = false,
- serie, data,
- distance, distanceX, distanceY,
- x, y, i, j;
-
- function setClosest (o) {
- o.distance = distance;
- o.distanceX = distanceX;
- o.distanceY = distanceY;
- o.seriesIndex = i;
- o.dataIndex = j;
- o.x = x;
- o.y = y;
- }
-
- for (i = 0; i < series.length; i++) {
-
- serie = series[i];
- data = serie.data;
-
- if (data.length) check = true;
-
- for (j = data.length; j--;) {
-
- x = data[j][0];
- y = data[j][1];
-
- if (x === null || y === null) continue;
-
- // don't check if the point isn't visible in the current range
- if (x < serie.xaxis.min || x > serie.xaxis.max) continue;
-
- distanceX = Math.abs(x - mouseX);
- distanceY = Math.abs(y - mouseY);
-
- // Skip square root for speed
- distance = distanceX * distanceX + distanceY * distanceY;
-
- if (distance < compare) {
- compare = distance;
- setClosest(closest);
- }
-
- if (distanceX < compareX) {
- compareX = distanceX;
- setClosest(closestX);
- }
- }
- }
-
- return check ? {
- point : closest,
- x : closestX
- } : false;
- },
-
- drawMouseTrack : function (n) {
-
- var
- pos = '',
- s = n.series,
- p = n.mouse.position,
- m = n.mouse.margin,
- elStyle = S_MOUSETRACK,
- mouseTrack = this.mouseTrack,
- plotOffset = this.plotOffset,
- left = plotOffset.left,
- right = plotOffset.right,
- bottom = plotOffset.bottom,
- top = plotOffset.top,
- decimals = n.mouse.trackDecimals,
- options = this.options;
-
- // Create
- if (!mouseTrack) {
- mouseTrack = D.node('<div class="flotr-mouse-value"></div>');
- this.mouseTrack = mouseTrack;
- D.insert(this.el, mouseTrack);
- }
-
- if (!n.mouse.relative) { // absolute to the canvas
-
- if (p.charAt(0) == 'n') pos += 'top:' + (m + top) + 'px;bottom:auto;';
- else if (p.charAt(0) == 's') pos += 'bottom:' + (m + bottom) + 'px;top:auto;';
- if (p.charAt(1) == 'e') pos += 'right:' + (m + right) + 'px;left:auto;';
- else if (p.charAt(1) == 'w') pos += 'left:' + (m + left) + 'px;right:auto;';
-
- // Bars
- } else if (s.bars.show) {
- pos += 'bottom:' + (m - top - n.yaxis.d2p(n.y/2) + this.canvasHeight) + 'px;top:auto;';
- pos += 'left:' + (m + left + n.xaxis.d2p(n.x - options.bars.barWidth/2)) + 'px;right:auto;';
-
- // Pie
- } else if (s.pie.show) {
- var center = {
- x: (this.plotWidth)/2,
- y: (this.plotHeight)/2
- },
- radius = (Math.min(this.canvasWidth, this.canvasHeight) * s.pie.sizeRatio) / 2,
- bisection = n.sAngle<n.eAngle ? (n.sAngle + n.eAngle) / 2: (n.sAngle + n.eAngle + 2* Math.PI) / 2;
-
- pos += 'bottom:' + (m - top - center.y - Math.sin(bisection) * radius/2 + this.canvasHeight) + 'px;top:auto;';
- pos += 'left:' + (m + left + center.x + Math.cos(bisection) * radius/2) + 'px;right:auto;';
-
- // Default
- } else {
- if (p.charAt(0) == 'n') pos += 'bottom:' + (m - top - n.yaxis.d2p(n.y) + this.canvasHeight) + 'px;top:auto;';
- else if (p.charAt(0) == 's') pos += 'top:' + (m + top + n.yaxis.d2p(n.y)) + 'px;bottom:auto;';
- if (p.charAt(1) == 'e') pos += 'left:' + (m + left + n.xaxis.d2p(n.x)) + 'px;right:auto;';
- else if (p.charAt(1) == 'w') pos += 'right:' + (m - left - n.xaxis.d2p(n.x) + this.canvasWidth) + 'px;left:auto;';
- }
-
- elStyle += pos;
- mouseTrack.style.cssText = elStyle;
-
- if (!decimals || decimals < 0) decimals = 0;
-
- mouseTrack.innerHTML = n.mouse.trackFormatter({
- x: n.x.toFixed(decimals),
- y: n.y.toFixed(decimals),
- series: n.series,
- index: n.index,
- nearest: n,
- fraction: n.fraction
- });
-
- D.show(mouseTrack);
- }
-
-});
-})();
-
-/**
- * Selection Handles Plugin
- *
- *
- * Options
- * show - True enables the handles plugin.
- * drag - Left and Right drag handles
- * scroll - Scrolling handle
- */
-(function () {
-
-function isLeftClick (e, type) {
- return (e.which ? (e.which === 1) : (e.button === 0 || e.button === 1));
-}
-
-function boundX(x, graph) {
- return Math.min(Math.max(0, x), graph.plotWidth - 1);
-}
-
-function boundY(y, graph) {
- return Math.min(Math.max(0, y), graph.plotHeight);
-}
-
-var
- D = Flotr.DOM,
- E = Flotr.EventAdapter,
- _ = Flotr._;
-
-
-Flotr.addPlugin('selection', {
-
- options: {
- pinchOnly: null, // Only select on pinch
- mode: null, // => one of null, 'x', 'y' or 'xy'
- color: '#B6D9FF', // => selection box color
- fps: 20 // => frames-per-second
- },
-
- callbacks: {
- 'flotr:mouseup' : function (event) {
-
- var
- options = this.options.selection,
- selection = this.selection,
- pointer = this.getEventPosition(event);
-
- if (!options || !options.mode) return;
- if (selection.interval) clearInterval(selection.interval);
-
- if (this.multitouches) {
- selection.updateSelection();
- } else
- if (!options.pinchOnly) {
- selection.setSelectionPos(selection.selection.second, pointer);
- }
- selection.clearSelection();
-
- if(selection.selecting && selection.selectionIsSane()){
- selection.drawSelection();
- selection.fireSelectEvent();
- this.ignoreClick = true;
- }
- },
- 'flotr:mousedown' : function (event) {
-
- var
- options = this.options.selection,
- selection = this.selection,
- pointer = this.getEventPosition(event);
-
- if (!options || !options.mode) return;
- if (!options.mode || (!isLeftClick(event) && _.isUndefined(event.touches))) return;
- if (!options.pinchOnly) selection.setSelectionPos(selection.selection.first, pointer);
- if (selection.interval) clearInterval(selection.interval);
-
- this.lastMousePos.pageX = null;
- selection.selecting = false;
- selection.interval = setInterval(
- _.bind(selection.updateSelection, this),
- 1000 / options.fps
- );
- },
- 'flotr:destroy' : function (event) {
- clearInterval(this.selection.interval);
- }
- },
-
- // TODO This isn't used. Maybe it belongs in the draw area and fire select event methods?
- getArea: function() {
-
- var s = this.selection.selection,
- first = s.first,
- second = s.second;
-
- return {
- x1: Math.min(first.x, second.x),
- x2: Math.max(first.x, second.x),
- y1: Math.min(first.y, second.y),
- y2: Math.max(first.y, second.y)
- };
- },
-
- selection: {first: {x: -1, y: -1}, second: {x: -1, y: -1}},
- prevSelection: null,
- interval: null,
-
- /**
- * Fires the 'flotr:select' event when the user made a selection.
- */
- fireSelectEvent: function(name){
- var a = this.axes,
- s = this.selection.selection,
- x1, x2, y1, y2;
-
- name = name || 'select';
-
- 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);
-
- E.fire(this.el, 'flotr:'+name, [{
- 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]);
- },
-
- /**
- * 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,
- s = this.selection.selection;
-
- this.selection.clearSelection();
-
- s.first.y = boundY((selX && !selY) ? 0 : (ya.max - area.y1) * vertScale, this);
- s.second.y = boundY((selX && !selY) ? this.plotHeight - 1: (ya.max - area.y2) * vertScale, this);
- s.first.x = boundX((selY && !selX) ? 0 : area.x1, this);
- s.second.x = boundX((selY && !selX) ? this.plotWidth : area.x2, this);
-
- this.selection.drawSelection();
- if (!preventEvent)
- this.selection.fireSelectEvent();
- },
-
- /**
- * Calculates the position of the selection.
- * @param {Object} pos - Position object.
- * @param {Event} event - Event object.
- */
- setSelectionPos: function(pos, pointer) {
- var mode = this.options.selection.mode,
- selection = this.selection.selection;
-
- if(mode.indexOf('x') == -1) {
- pos.x = (pos == selection.first) ? 0 : this.plotWidth;
- }else{
- pos.x = boundX(pointer.relX, this);
- }
-
- if (mode.indexOf('y') == -1) {
- pos.y = (pos == selection.first) ? 0 : this.plotHeight - 1;
- }else{
- pos.y = boundY(pointer.relY, this);
- }
- },
- /**
- * Draws the selection box.
- */
- drawSelection: function() {
-
- this.selection.fireSelectEvent('selecting');
-
- var s = this.selection.selection,
- octx = this.octx,
- options = this.options,
- plotOffset = this.plotOffset,
- prevSelection = this.selection.prevSelection;
-
- if (prevSelection &&
- 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.selection.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();
- },
-
- /**
- * Updates (draws) the selection box.
- */
- updateSelection: function(){
- if (!this.lastMousePos.pageX) return;
-
- this.selection.selecting = true;
-
- if (this.multitouches) {
- this.selection.setSelectionPos(this.selection.selection.first, this.getEventPosition(this.multitouches[0]));
- this.selection.setSelectionPos(this.selection.selection.second, this.getEventPosition(this.multitouches[1]));
- } else
- if (this.options.selection.pinchOnly) {
- return;
- } else {
- this.selection.setSelectionPos(this.selection.selection.second, this.lastMousePos);
- }
-
- this.selection.clearSelection();
-
- if(this.selection.selectionIsSane()) {
- this.selection.drawSelection();
- }
- },
-
- /**
- * Removes the selection box from the overlay canvas.
- */
- clearSelection: function() {
- if (!this.selection.prevSelection) return;
-
- var prevSelection = this.selection.prevSelection,
- lw = 1,
- 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 + 0.5,
- y + plotOffset.top - lw,
- w + 2 * lw + 0.5,
- h + 2 * lw + 0.5);
-
- this.selection.prevSelection = null;
- },
- /**
- * Determines whether or not the selection is sane and should be drawn.
- * @return {Boolean} - True when sane, false otherwise.
- */
- selectionIsSane: function(){
- var s = this.selection.selection;
- return Math.abs(s.second.x - s.first.x) >= 5 ||
- Math.abs(s.second.y - s.first.y) >= 5;
- }
-
-});
-
-})();
-
-(function () {
-
-var D = Flotr.DOM;
-
-Flotr.addPlugin('labels', {
-
- callbacks : {
- 'flotr:afterdraw' : function () {
- this.labels.draw();
- }
- },
-
- draw: function(){
- // Construct fixed width label boxes, which can be styled easily.
- var
- axis, tick, left, top, xBoxWidth,
- radius, sides, coeff, angle,
- div, i, html = '',
- noLabels = 0,
- options = this.options,
- ctx = this.ctx,
- a = this.axes,
- style = { size: options.fontSize };
-
- 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);
-
- radius = this.plotHeight * options.radar.radiusRatio / 2 + options.fontSize;
- sides = this.axes.x.ticks.length;
- coeff = 2 * (Math.PI / sides);
- angle = -Math.PI / 2;
-
- drawLabelCircular(this, a.x, false);
- drawLabelCircular(this, a.x, true);
- drawLabelCircular(this, a.y, false);
- drawLabelCircular(this, a.y, true);
- ctx.restore();
- }
-
- if (!options.HtmlText && this.textEnabled) {
- drawLabelNoHtmlText(this, a.x, 'center', 'top');
- drawLabelNoHtmlText(this, a.x2, 'center', 'bottom');
- drawLabelNoHtmlText(this, a.y, 'right', 'middle');
- drawLabelNoHtmlText(this, a.y2, 'left', 'middle');
-
- } else if ((
- a.x.options.showLabels ||
- a.x2.options.showLabels ||
- a.y.options.showLabels ||
- a.y2.options.showLabels) &&
- !options.grid.circular
- ) {
-
- html = '';
-
- drawLabelHtml(this, a.x);
- drawLabelHtml(this, a.x2);
- drawLabelHtml(this, a.y);
- drawLabelHtml(this, a.y2);
-
- ctx.stroke();
- ctx.restore();
- div = D.create('div');
- D.setStyles(div, {
- fontSize: 'smaller',
- color: options.grid.color
- });
- div.className = 'flotr-labels';
- D.insert(this.el, div);
- D.insert(div, html);
- }
-
- function drawLabelCircular (graph, axis, minorTicks) {
- var
- ticks = minorTicks ? axis.minorTicks : axis.ticks,
- isX = axis.orientation === 1,
- isFirst = axis.n === 1,
- style, offset;
-
- style = {
- color : axis.options.color || options.grid.color,
- angle : Flotr.toRad(axis.options.labelsAngle),
- textBaseline : 'middle'
- };
-
- for (i = 0; i < ticks.length &&
- (minorTicks ? axis.options.showMinorLabels : axis.options.showLabels); ++i){
- tick = ticks[i];
- tick.label += '';
- if (!tick.label || !tick.label.length) { continue; }
-
- x = Math.cos(i * coeff + angle) * radius;
- y = Math.sin(i * coeff + angle) * radius;
-
- style.textAlign = isX ? (Math.abs(x) < 0.1 ? 'center' : (x < 0 ? 'right' : 'left')) : 'left';
-
- Flotr.drawText(
- ctx, tick.label,
- isX ? x : 3,
- isX ? y : -(axis.ticks[i].v / axis.max) * (radius - options.fontSize),
- style
- );
- }
- }
-
- function drawLabelNoHtmlText (graph, axis, textAlign, textBaseline) {
- var
- isX = axis.orientation === 1,
- isFirst = axis.n === 1,
- style, offset;
-
- style = {
- color : axis.options.color || options.grid.color,
- textAlign : textAlign,
- textBaseline : textBaseline,
- angle : Flotr.toRad(axis.options.labelsAngle)
- };
- style = Flotr.getBestTextAlign(style.angle, style);
-
- for (i = 0; i < axis.ticks.length && continueShowingLabels(axis); ++i) {
-
- tick = axis.ticks[i];
- if (!tick.label || !tick.label.length) { continue; }
-
- offset = axis.d2p(tick.v);
- if (offset < 0 ||
- offset > (isX ? graph.plotWidth : graph.plotHeight)) { continue; }
-
- Flotr.drawText(
- ctx, tick.label,
- leftOffset(graph, isX, isFirst, offset),
- topOffset(graph, isX, isFirst, offset),
- style
- );
-
- // Only draw on axis y2
- if (!isX && !isFirst) {
- ctx.save();
- ctx.strokeStyle = style.color;
- ctx.beginPath();
- ctx.moveTo(graph.plotOffset.left + graph.plotWidth - 8, graph.plotOffset.top + axis.d2p(tick.v));
- ctx.lineTo(graph.plotOffset.left + graph.plotWidth, graph.plotOffset.top + axis.d2p(tick.v));
- ctx.stroke();
- ctx.restore();
- }
- }
-
- function continueShowingLabels (axis) {
- return axis.options.showLabels && axis.used;
- }
- function leftOffset (graph, isX, isFirst, offset) {
- return graph.plotOffset.left +
- (isX ? offset :
- (isFirst ?
- -options.grid.labelMargin :
- options.grid.labelMargin + graph.plotWidth));
- }
- function topOffset (graph, isX, isFirst, offset) {
- return graph.plotOffset.top +
- (isX ? options.grid.labelMargin : offset) +
- ((isX && isFirst) ? graph.plotHeight : 0);
- }
- }
-
- function drawLabelHtml (graph, axis) {
- var
- isX = axis.orientation === 1,
- isFirst = axis.n === 1,
- name = '',
- left, style, top,
- offset = graph.plotOffset;
-
- if (!isX && !isFirst) {
- ctx.save();
- ctx.strokeStyle = axis.options.color || options.grid.color;
- ctx.beginPath();
- }
-
- if (axis.options.showLabels && (isFirst ? true : axis.used)) {
- for (i = 0; i < axis.ticks.length; ++i) {
- tick = axis.ticks[i];
- if (!tick.label || !tick.label.length ||
- ((isX ? offset.left : offset.top) + axis.d2p(tick.v) < 0) ||
- ((isX ? offset.left : offset.top) + axis.d2p(tick.v) > (isX ? graph.canvasWidth : graph.canvasHeight))) {
- continue;
- }
- top = offset.top +
- (isX ?
- ((isFirst ? 1 : -1 ) * (graph.plotHeight + options.grid.labelMargin)) :
- axis.d2p(tick.v) - axis.maxLabel.height / 2);
- left = isX ? (offset.left + axis.d2p(tick.v) - xBoxWidth / 2) : 0;
-
- name = '';
- if (i === 0) {
- name = ' first';
- } else if (i === axis.ticks.length - 1) {
- name = ' last';
- }
- name += isX ? ' flotr-grid-label-x' : ' flotr-grid-label-y';
-
- html += [
- '<div style="position:absolute; text-align:' + (isX ? 'center' : 'right') + '; ',
- 'top:' + top + 'px; ',
- ((!isX && !isFirst) ? 'right:' : 'left:') + left + 'px; ',
- 'width:' + (isX ? xBoxWidth : ((isFirst ? offset.left : offset.right) - options.grid.labelMargin)) + 'px; ',
- axis.options.color ? ('color:' + axis.options.color + '; ') : ' ',
- '" class="flotr-grid-label' + name + '">' + tick.label + '</div>'
- ].join(' ');
-
- if (!isX && !isFirst) {
- ctx.moveTo(offset.left + graph.plotWidth - 8, offset.top + axis.d2p(tick.v));
- ctx.lineTo(offset.left + graph.plotWidth, offset.top + axis.d2p(tick.v));
- }
- }
- }
- }
- }
-
-});
-})();
-
-(function () {
-
-var
- D = Flotr.DOM,
- _ = Flotr._;
-
-Flotr.addPlugin('legend', {
- options: {
- 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,
- labelBoxOpacity: 0.4,
- 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
- },
- callbacks: {
- 'flotr:afterinit': function() {
- this.legend.insertLegend();
- }
- },
- /**
- * 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,
- itemCount = _.filter(series, function(s) {return (s.label && !s.hide);}).length,
- p = legend.position,
- m = legend.margin,
- i, label, color;
-
- if (itemCount) {
- if (!options.HtmlText && this.textEnabled && !legend.container) {
- var style = {
- size: options.fontSize*1.1,
- color: options.grid.color
- };
-
- var 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;
- label = legend.labelFormatter(series[i].label);
- labelMaxWidth = Math.max(labelMaxWidth, this._text.measureText(label, style).width);
- }
-
- var legendWidth = Math.round(lbw + lbm*3 + labelMaxWidth),
- legendHeight = Math.round(itemCount*(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
- color = this.processColor(legend.backgroundColor || 'rgb(240,240,240)', {opacity: legend.backgroundOpacity || 0.1});
-
- ctx.fillStyle = color;
- ctx.fillRect(offsetX, offsetY, legendWidth, legendHeight);
- ctx.strokeStyle = 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;
- 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
- Flotr.drawText(ctx, label, x + lbw + lbm, y + lbh, style);
-
- y += lbh + lbm;
- }
- }
- else {
- for(i = 0; i < series.length; ++i){
- if(!series[i].label || series[i].hide) continue;
-
- if(i % legend.noColumns === 0){
- fragments.push(rowStarted ? '</tr><tr>' : '<tr>');
- rowStarted = true;
- }
-
- // @TODO remove requirement on bars
- var s = series[i],
- boxWidth = legend.labelBoxWidth,
- boxHeight = legend.labelBoxHeight,
- opacityValue = (s.bars ? s.bars.fillOpacity : legend.labelBoxOpacity),
- opacity = 'opacity:' + opacityValue + ';filter:alpha(opacity=' + opacityValue*100 + ');';
-
- label = legend.labelFormatter(s.label);
- color = 'background-color:' + ((s.bars && s.bars.show && s.bars.fillColor && s.bars.fill) ? s.bars.fillColor : s.color) + ';';
-
- fragments.push(
- '<td class="flotr-legend-color-box">',
- '<div style="border:1px solid ', legend.labelBoxBorderColor, ';padding:1px">',
- '<div style="width:', (boxWidth-1), 'px;height:', (boxHeight-1), 'px;border:1px solid ', series[i].color, '">', // Border
- '<div style="width:', boxWidth, 'px;height:', boxHeight, 'px;', 'opacity:.4;', color, '"></div>', // Background
- '</div>',
- '</div>',
- '</td>',
- '<td class="flotr-legend-label">', label, '</td>'
- );
- }
- if(rowStarted) fragments.push('</tr>');
-
- if(fragments.length > 0){
- var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join('') + '</table>';
- if(legend.container){
- D.insert(legend.container, table);
- }
- else {
- var styles = {position: 'absolute', 'z-index': 2};
-
- if(p.charAt(0) == 'n') { styles.top = (m + plotOffset.top) + 'px'; styles.bottom = 'auto'; }
- else if(p.charAt(0) == 's') { styles.bottom = (m + plotOffset.bottom) + 'px'; styles.top = 'auto'; }
- if(p.charAt(1) == 'e') { styles.right = (m + plotOffset.right) + 'px'; styles.left = 'auto'; }
- else if(p.charAt(1) == 'w') { styles.left = (m + plotOffset.left) + 'px'; styles.right = 'auto'; }
-
- var div = D.create('div'), size;
- div.className = 'flotr-legend';
- D.setStyles(div, styles);
- D.insert(div, table);
- D.insert(this.el, div);
-
- if(!legend.backgroundOpacity)
- return;
-
- var c = legend.backgroundColor || options.grid.backgroundColor || '#ffffff';
-
- _.extend(styles, D.size(div), {
- 'backgroundColor': c,
- 'z-index': 1
- });
- styles.width += 'px';
- styles.height += 'px';
-
- // Put in the transparent background separately to avoid blended labels and
- div = D.create('div');
- div.className = 'flotr-legend-bg';
- D.setStyles(div, styles);
- D.opacity(div, legend.backgroundOpacity);
- D.insert(div, ' ');
- D.insert(this.el, div);
- }
- }
- }
- }
- }
-});
-})();
-
-/** Spreadsheet **/
-(function() {
-
-function getRowLabel(value){
- if (this.options.spreadsheet.tickFormatter){
- //TODO maybe pass the xaxis formatter to the custom tick formatter as an opt-out?
- return this.options.spreadsheet.tickFormatter(value);
- }
- else {
- var t = _.find(this.axes.x.ticks, function(t){return t.v == value;});
- if (t) {
- return t.label;
- }
- return value;
- }
-}
-
-var
- D = Flotr.DOM,
- _ = Flotr._;
-
-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: '.',
- tickFormatter: null,
- initialTab: 'graph'
- },
- /**
- * Builds the tabs in the DOM
- */
- callbacks: {
- 'flotr:afterconstruct': function(){
- // @TODO necessary?
- //this.el.select('.flotr-tabs-group,.flotr-datagrid-container').invoke('remove');
-
- if (!this.options.spreadsheet.show) return;
-
- var ss = this.spreadsheet,
- container = D.node('<div class="flotr-tabs-group" style="position:absolute;left:0px;width:'+this.canvasWidth+'px"></div>'),
- graph = D.node('<div style="float:left" class="flotr-tab selected">'+this.options.spreadsheet.tabGraphLabel+'</div>'),
- data = D.node('<div style="float:left" class="flotr-tab">'+this.options.spreadsheet.tabDataLabel+'</div>'),
- offset;
-
- ss.tabsContainer = container;
- ss.tabs = { graph : graph, data : data };
-
- D.insert(container, graph);
- D.insert(container, data);
- D.insert(this.el, container);
-
- offset = D.size(data).height + 2;
- this.plotOffset.bottom += offset;
-
- D.setStyles(container, {top: this.canvasHeight-offset+'px'});
-
- this.
- observe(graph, 'click', function(){ss.showTab('graph');}).
- observe(data, 'click', function(){ss.showTab('data');});
- if (this.options.spreadsheet.initialTab !== 'graph'){
- ss.showTab(this.options.spreadsheet.initialTab);
- }
- }
- },
- /**
- * 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,
- rows = {};
-
- /* 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)
- **/
- _.each(s, function(serie, i){
- _.each(serie.data, function (v) {
- var x = v[0],
- y = v[1],
- r = rows[x];
- if (r) {
- r[i+1] = y;
- } else {
- var newRow = [];
- newRow[0] = x;
- newRow[i+1] = y;
- rows[x] = newRow;
- }
- });
- });
-
- // The data grid is sorted by x value
- this.seriesData = _.sortBy(rows, function(row, x){
- return parseInt(x, 10);
- });
- return this.seriesData;
- },
- /**
- * 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 s = this.series,
- datagrid = this.spreadsheet.loadDataGrid(),
- colgroup = ['<colgroup><col />'],
- buttonDownload, buttonSelect, t;
-
- // First row : series' labels
- var html = ['<table class="flotr-datagrid"><tr class="first-row">'];
- html.push('<th>&nbsp;</th>');
- _.each(s, function(serie,i){
- html.push('<th scope="col">'+(serie.label || String.fromCharCode(65+i))+'</th>');
- colgroup.push('<col />');
- });
- html.push('</tr>');
- // Data rows
- _.each(datagrid, function(row){
- html.push('<tr>');
- _.times(s.length+1, function(i){
- var tag = 'td',
- value = row[i],
- // TODO: do we really want to handle problems with floating point
- // precision here?
- content = (!_.isUndefined(value) ? Math.round(value*100000)/100000 : '');
- if (i === 0) {
- tag = 'th';
- var label = getRowLabel.call(this, content);
- if (label) content = label;
- }
-
- html.push('<'+tag+(tag=='th'?' scope="row"':'')+'>'+content+'</'+tag+'>');
- }, this);
- html.push('</tr>');
- }, this);
- colgroup.push('</colgroup>');
- t = D.node(html.join(''));
-
- /**
- * @TODO disabled this
- if (!Flotr.isIE || Flotr.isIE == 9) {
- function handleMouseout(){
- t.select('colgroup col.hover, th.hover').invoke('removeClassName', 'hover');
- }
- function handleMouseover(e){
- var td = e.element(),
- siblings = td.previousSiblings();
- t.select('th[scope=col]')[siblings.length-1].addClassName('hover');
- t.select('colgroup col')[siblings.length].addClassName('hover');
- }
- _.each(t.select('td'), function(td) {
- Flotr.EventAdapter.
- observe(td, 'mouseover', handleMouseover).
- observe(td, 'mouseout', handleMouseout);
- });
- }
- */
-
- buttonDownload = D.node(
- '<button type="button" class="flotr-datagrid-toolbar-button">' +
- this.options.spreadsheet.toolbarDownload +
- '</button>');
-
- buttonSelect = D.node(
- '<button type="button" class="flotr-datagrid-toolbar-button">' +
- this.options.spreadsheet.toolbarSelectAll+
- '</button>');
-
- this.
- observe(buttonDownload, 'click', _.bind(this.spreadsheet.downloadCSV, this)).
- observe(buttonSelect, 'click', _.bind(this.spreadsheet.selectAllData, this));
-
- var toolbar = D.node('<div class="flotr-datagrid-toolbar"></div>');
- D.insert(toolbar, buttonDownload);
- D.insert(toolbar, buttonSelect);
-
- var containerHeight =this.canvasHeight - D.size(this.spreadsheet.tabsContainer).height-2,
- container = D.node('<div class="flotr-datagrid-container" style="position:absolute;left:0px;top:0px;width:'+
- this.canvasWidth+'px;height:'+containerHeight+'px;overflow:auto;z-index:10"></div>');
-
- D.insert(container, toolbar);
- D.insert(container, t);
- D.insert(this.el, container);
- this.spreadsheet.datagrid = t;
- this.spreadsheet.container = 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){
- if (this.spreadsheet.activeTab === tabName){
- return;
- }
- switch(tabName) {
- case 'graph':
- D.hide(this.spreadsheet.container);
- D.removeClass(this.spreadsheet.tabs.data, 'selected');
- D.addClass(this.spreadsheet.tabs.graph, 'selected');
- break;
- case 'data':
- if (!this.spreadsheet.datagrid)
- this.spreadsheet.constructDataGrid();
- D.show(this.spreadsheet.container);
- D.addClass(this.spreadsheet.tabs.data, 'selected');
- D.removeClass(this.spreadsheet.tabs.graph, 'selected');
- break;
- default:
- throw 'Illegal tab name: ' + tabName;
- }
- this.spreadsheet.activeTab = tabName;
- },
- /**
- * 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 csv = '',
- series = this.series,
- options = this.options,
- dg = this.spreadsheet.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
- _.each(series, function(serie, i){
- csv += separator+'"'+(serie.label || String.fromCharCode(65+i)).replace(/\"/g, '\\"')+'"';
- });
-
- csv += "%0D%0A"; // \r\n
-
- // For each row
- csv += _.reduce(dg, function(memo, row){
- var rowLabel = getRowLabel.call(this, row[0]) || '';
- rowLabel = '"'+(rowLabel+'').replace(/\"/g, '\\"')+'"';
- var numbers = row.slice(1).join(separator);
- if (options.spreadsheet.decimalSeparator !== '.') {
- numbers = numbers.replace(/\./g, options.spreadsheet.decimalSeparator);
- }
- return memo + rowLabel+separator+numbers+"%0D%0A"; // \t and \r\n
- }, '', this);
-
- if (Flotr.isIE && Flotr.isIE < 9) {
- 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);
- }
-});
-})();
-
-(function () {
-
-var D = Flotr.DOM;
-
-Flotr.addPlugin('titles', {
- callbacks: {
- 'flotr:afterdraw': function() {
- this.titles.drawTitles();
- }
- },
- /**
- * 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,
- textAlign: 'center'
- };
-
- // Add subtitle
- if (options.subtitle){
- Flotr.drawText(
- ctx, 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){
- Flotr.drawText(
- ctx, options.title,
- this.plotOffset.left + this.plotWidth/2,
- this.titleHeight - 2,
- style
- );
- }
-
- style.weight = 1.8;
- style.size *= 0.8;
-
- // Add x axis title
- if (a.x.options.title && a.x.used){
- style.textAlign = a.x.options.titleAlign || 'center';
- style.textBaseline = 'top';
- style.angle = Flotr.toRad(a.x.options.titleAngle);
- style = Flotr.getBestTextAlign(style.angle, style);
- Flotr.drawText(
- ctx, 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.textAlign = a.x2.options.titleAlign || 'center';
- style.textBaseline = 'bottom';
- style.angle = Flotr.toRad(a.x2.options.titleAngle);
- style = Flotr.getBestTextAlign(style.angle, style);
- Flotr.drawText(
- ctx, 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.textAlign = a.y.options.titleAlign || 'right';
- style.textBaseline = 'middle';
- style.angle = Flotr.toRad(a.y.options.titleAngle);
- style = Flotr.getBestTextAlign(style.angle, style);
- Flotr.drawText(
- ctx, 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.textAlign = a.y2.options.titleAlign || 'left';
- style.textBaseline = 'middle';
- style.angle = Flotr.toRad(a.y2.options.titleAngle);
- style = Flotr.getBestTextAlign(style.angle, style);
- Flotr.drawText(
- ctx, 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(
- '<div style="position:absolute;top:0;left:',
- this.plotOffset.left, 'px;font-size:1em;font-weight:bold;text-align:center;width:',
- this.plotWidth,'px;" class="flotr-title">', options.title, '</div>'
- );
-
- // Add subtitle
- if (options.subtitle)
- html.push(
- '<div style="position:absolute;top:', this.titleHeight, 'px;left:',
- this.plotOffset.left, 'px;font-size:smaller;text-align:center;width:',
- this.plotWidth, 'px;" class="flotr-subtitle">', options.subtitle, '</div>'
- );
-
- html.push('</div>');
-
- html.push('<div class="flotr-axis-title" style="font-weight:bold;">');
-
- // Add x axis title
- if (a.x.options.title && a.x.used)
- html.push(
- '<div style="position:absolute;top:',
- (this.plotOffset.top + this.plotHeight + options.grid.labelMargin + a.x.titleSize.height),
- 'px;left:', this.plotOffset.left, 'px;width:', this.plotWidth,
- 'px;text-align:center;" class="flotr-axis-title">', a.x.options.title, '</div>'
- );
-
- // Add x2 axis title
- if (a.x2.options.title && a.x2.used)
- html.push(
- '<div style="position:absolute;top:0;left:', this.plotOffset.left, 'px;width:',
- this.plotWidth, 'px;text-align:center;" class="flotr-axis-title">', a.x2.options.title, '</div>'
- );
-
- // Add y axis title
- if (a.y.options.title && a.y.used)
- html.push(
- '<div style="position:absolute;top:',
- (this.plotOffset.top + this.plotHeight/2 - a.y.titleSize.height/2),
- 'px;left:0;text-align:right;" class="flotr-axis-title">', a.y.options.title, '</div>'
- );
-
- // Add y2 axis title
- if (a.y2.options.title && a.y2.used)
- html.push(
- '<div style="position:absolute;top:',
- (this.plotOffset.top + this.plotHeight/2 - a.y.titleSize.height/2),
- 'px;right:0;text-align:right;" class="flotr-axis-title">', a.y2.options.title, '</div>'
- );
-
- html = html.join('');
-
- var div = D.create('div');
- D.setStyles({
- color: options.grid.color
- });
- div.className = 'flotr-titles';
- D.insert(this.el, div);
- D.insert(div, html);
- }
- }
-});
-})();
diff --git a/addons/web_graph/static/lib/flotr2/flotr2.min.js b/addons/web_graph/static/lib/flotr2/flotr2.min.js
deleted file mode 100644
index 0dce3034464..00000000000
--- a/addons/web_graph/static/lib/flotr2/flotr2.min.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*!
- * bean.js - copyright Jacob Thornton 2011
- * https://github.com/fat/bean
- * MIT License
- * special thanks to:
- * dean edwards: http://dean.edwards.name/
- * dperini: https://github.com/dperini/nwevents
- * the entire mootools team: github.com/mootools/mootools-core
- *//*global module:true, define:true*/
-!function(a,b,c){typeof module!="undefined"?module.exports=c(a,b):typeof define=="function"&&typeof define.amd=="object"?define(c):b[a]=c(a,b)}("bean",this,function(a,b){var c=window,d=b[a],e=/over|out/,f=/[^\.]*(?=\..*)\.|.*/,g=/\..*/,h="addEventListener",i="attachEvent",j="removeEventListener",k="detachEvent",l=document||{},m=l.documentElement||{},n=m[h],o=n?h:i,p=Array.prototype.slice,q=/click|mouse|menu|drag|drop/i,r=/^touch|^gesture/i,s={one:1},t=function(a,b,c){for(c=0;c<b.length;c++)a[b[c]]=1;return a}({},("click dblclick mouseup mousedown contextmenu mousewheel DOMMouseScroll mouseover mouseout mousemove selectstart selectend keydown keypress keyup orientationchange focus blur change reset select submit load unload beforeunload resize move DOMContentLoaded readystatechange error abort scroll "+(n?"show input invalid touchstart touchmove touchend touchcancel gesturestart gesturechange gestureend message readystatechange pageshow pagehide popstate hashchange offline online afterprint beforeprint dragstart dragenter dragover dragleave drag drop dragend loadstart progress suspend emptied stalled loadmetadata loadeddata canplay canplaythrough playing waiting seeking seeked ended durationchange timeupdate play pause ratechange volumechange cuechange checking noupdate downloading cached updateready obsolete ":"")).split(" ")),u=function(){function a(a,b){while((b=b.parentNode)!==null)if(b===a)return!0;return!1}function b(b){var c=b.relatedTarget;return c?c!==this&&c.prefix!=="xul"&&!/document/.test(this.toString())&&!a(this,c):c===null}return{mouseenter:{base:"mouseover",condition:b},mouseleave:{base:"mouseout",condition:b},mousewheel:{base:/Firefox/.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel"}}}(),v=function(){var a="altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which".split(" "),b=a.concat("button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" ")),c=a.concat("char charCode key keyCode".split(" ")),d=a.concat("touches targetTouches changedTouches scale rotation".split(" ")),f="preventDefault",g=function(a){return function(){a[f]?a[f]():a.returnValue=!1}},h="stopPropagation",i=function(a){return function(){a[h]?a[h]():a.cancelBubble=!0}},j=function(a){return function(){a[f](),a[h](),a.stopped=!0}},k=function(a,b,c){var d,e;for(d=c.length;d--;)e=c[d],!(e in b)&&e in a&&(b[e]=a[e])};return function(n,o){var p={originalEvent:n,isNative:o};if(!n)return p;var s,t=n.type,u=n.target||n.srcElement;p[f]=g(n),p[h]=i(n),p.stop=j(p),p.target=u&&u.nodeType===3?u.parentNode:u;if(o){if(t.indexOf("key")!==-1)s=c,p.keyCode=n.which||n.keyCode;else if(q.test(t)){s=b,p.rightClick=n.which===3||n.button===2,p.pos={x:0,y:0};if(n.pageX||n.pageY)p.clientX=n.pageX,p.clientY=n.pageY;else if(n.clientX||n.clientY)p.clientX=n.clientX+l.body.scrollLeft+m.scrollLeft,p.clientY=n.clientY+l.body.scrollTop+m.scrollTop;e.test(t)&&(p.relatedTarget=n.relatedTarget||n[(t==="mouseover"?"from":"to")+"Element"])}else r.test(t)&&(s=d);k(n,p,s||a)}return p}}(),w=function(a,b){return!n&&!b&&(a===l||a===c)?m:a},x=function(){function a(a,b,c,d,e){this.element=a,this.type=b,this.handler=c,this.original=d,this.namespaces=e,this.custom=u[b],this.isNative=t[b]&&a[o],this.eventType=n||this.isNative?b:"propertychange",this.customType=!n&&!this.isNative&&b,this.target=w(a,this.isNative),this.eventSupport=this.target[o]}return a.prototype={inNamespaces:function(a){var b,c;if(!a)return!0;if(!this.namespaces)return!1;for(b=a.length;b--;)for(c=this.namespaces.length;c--;)if(a[b]===this.namespaces[c])return!0;return!1},matches:function(a,b,c){return this.element===a&&(!b||this.original===b)&&(!c||this.handler===c)}},a}(),y=function(){var a={},b=function(c,d,e,f,g){if(!d||d==="*")for(var h in a)h.charAt(0)==="$"&&b(c,h.substr(1),e,f,g);else{var i=0,j,k=a["$"+d],l=c==="*";if(!k)return;for(j=k.length;i<j;i++)if(l||k[i].matches(c,e,f))if(!g(k[i],k,i,d))return}},c=function(b,c,d){var e,f=a["$"+c];if(f)for(e=f.length;e--;)if(f[e].matches(b,d,null))return!0;return!1},d=function(a,c,d){var e=[];return b(a,c,d,null,function(a){return e.push(a)}),e},e=function(b){return(a["$"+b.type]||(a["$"+b.type]=[])).push(b),b},f=function(c){b(c.element,c.type,null,c.handler,function(b,c,d){return c.splice(d,1),c.length===0&&delete a["$"+b.type],!1})},g=function(){var b,c=[];for(b in a)b.charAt(0)==="$"&&(c=c.concat(a[b]));return c};return{has:c,get:d,put:e,del:f,entries:g}}(),z=n?function(a,b,c,d){a[d?h:j](b,c,!1)}:function(a,b,c,d,e){e&&d&&a["_on"+e]===null&&(a["_on"+e]=0),a[d?i:k]("on"+b,c)},A=function(a,b,d){return function(e){return e=v(e||((this.ownerDocument||this.document||this).parentWindow||c).event,!0),b.apply(a,[e].concat(d))}},B=function(a,b,d,e,f,g){return function(h){if(e?e.apply(this,arguments):n?!0:h&&h.propertyName==="_on"+d||!h)h&&(h=v(h||((this.ownerDocument||this.document||this).parentWindow||c).event,g)),b.apply(a,h&&(!f||f.length===0)?arguments:p.call(arguments,h?0:1).concat(f))}},C=function(a,b,c,d,e){return function(){a(b,c,e),d.apply(this,arguments)}},D=function(a,b,c,d){var e,f,h,i=b&&b.replace(g,""),j=y.get(a,i,c);for(e=0,f=j.length;e<f;e++)j[e].inNamespaces(d)&&((h=j[e]).eventSupport&&z(h.target,h.eventType,h.handler,!1,h.type),y.del(h))},E=function(a,b,c,d,e){var h,i=b.replace(g,""),j=b.replace(f,"").split(".");if(y.has(a,i,c))return a;i==="unload"&&(c=C(D,a,i,c,d)),u[i]&&(u[i].condition&&(c=B(a,c,i,u[i].condition,!0)),i=u[i].base||i),h=y.put(new x(a,i,c,d,j[0]&&j)),h.handler=h.isNative?A(a,h.handler,e):B(a,h.handler,i,!1,e,!1),h.eventSupport&&z(h.target,h.eventType,h.handler,!0,h.customType)},F=function(a,b,c){return function(d){var e,f,g=typeof a=="string"?c(a,this):a;for(e=d.target;e&&e!==this;e=e.parentNode)for(f=g.length;f--;)if(g[f]===e)return b.apply(e,arguments)}},G=function(a,b,c){var d,e,h,i,j,k=D,l=b&&typeof b=="string";if(l&&b.indexOf(" ")>0){b=b.split(" ");for(j=b.length;j--;)G(a,b[j],c);return a}h=l&&b.replace(g,""),h&&u[h]&&(h=u[h].type);if(!b||l){if(i=l&&b.replace(f,""))i=i.split(".");k(a,h,c,i)}else if(typeof b=="function")k(a,null,b);else for(d in b)b.hasOwnProperty(d)&&G(a,d,b[d]);return a},H=function(a,b,c,d,e){var f,g,h,i,j=c,k=c&&typeof c=="string";if(b&&!c&&typeof b=="object")for(f in b)b.hasOwnProperty(f)&&H.apply(this,[a,f,b[f]]);else{i=arguments.length>3?p.call(arguments,3):[],g=(k?c:b).split(" "),k&&(c=F(b,j=d,e))&&(i=p.call(i,1)),this===s&&(c=C(G,a,b,c,j));for(h=g.length;h--;)E(a,g[h],c,j,i)}return a},I=function(){return H.apply(s,arguments)},J=n?function(a,b,d){var e=l.createEvent(a?"HTMLEvents":"UIEvents");e[a?"initEvent":"initUIEvent"](b,!0,!0,c,1),d.dispatchEvent(e)}:function(a,b,c){c=w(c,a),a?c.fireEvent("on"+b,l.createEventObject()):c["_on"+b]++},K=function(a,b,c){var d,e,h,i,j,k=b.split(" ");for(d=k.length;d--;){b=k[d].replace(g,"");if(i=k[d].replace(f,""))i=i.split(".");if(!i&&!c&&a[o])J(t[b],b,a);else{j=y.get(a,b),c=[!1].concat(c);for(e=0,h=j.length;e<h;e++)j[e].inNamespaces(i)&&j[e].handler.apply(a,c)}}return a},L=function(a,b,c){var d=0,e=y.get(b,c),f=e.length;for(;d<f;d++)e[d].original&&H(a,e[d].type,e[d].original);return a},M={add:H,one:I,remove:G,clone:L,fire:K,noConflict:function(){return b[a]=d,this}};if(c[i]){var N=function(){var a,b=y.entries();for(a in b)b[a].type&&b[a].type!=="unload"&&G(b[a].element,b[a].type);c[k]("onunload",N),c.CollectGarbage&&c.CollectGarbage()};c[i]("onunload",N)}return M});
-// Underscore.js 1.1.7
-// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore is freely distributable under the MIT license.
-// Portions of Underscore are inspired or borrowed from Prototype,
-// Oliver Steele's Functional, and John Resig's Micro-Templating.
-// For all details and documentation:
-// http://documentcloud.github.com/underscore
-
-(function(){var a=this,b=a._,c={},d=Array.prototype,e=Object.prototype,f=Function.prototype,g=d.slice,h=d.unshift,i=e.toString,j=e.hasOwnProperty,k=d.forEach,l=d.map,m=d.reduce,n=d.reduceRight,o=d.filter,p=d.every,q=d.some,r=d.indexOf,s=d.lastIndexOf,t=Array.isArray,u=Object.keys,v=f.bind,w=function(a){return new B(a)};typeof module!="undefined"&&module.exports?(module.exports=w,w._=w):a._=w,w.VERSION="1.1.7";var x=w.each=w.forEach=function(a,b,d){if(a==null)return;if(k&&a.forEach===k)a.forEach(b,d);else if(a.length===+a.length){for(var e=0,f=a.length;e<f;e++)if(e in a&&b.call(d,a[e],e,a)===c)return}else for(var g in a)if(j.call(a,g)&&b.call(d,a[g],g,a)===c)return};w.map=function(a,b,c){var d=[];return a==null?d:l&&a.map===l?a.map(b,c):(x(a,function(a,e,f){d[d.length]=b.call(c,a,e,f)}),d)},w.reduce=w.foldl=w.inject=function(a,b,c,d){var e=c!==void 0;a==null&&(a=[]);if(m&&a.reduce===m)return d&&(b=w.bind(b,d)),e?a.reduce(b,c):a.reduce(b);x(a,function(a,f,g){e?c=b.call(d,c,a,f,g):(c=a,e=!0)});if(!e)throw new TypeError("Reduce of empty array with no initial value");return c},w.reduceRight=w.foldr=function(a,b,c,d){a==null&&(a=[]);if(n&&a.reduceRight===n)return d&&(b=w.bind(b,d)),c!==void 0?a.reduceRight(b,c):a.reduceRight(b);var e=(w.isArray(a)?a.slice():w.toArray(a)).reverse();return w.reduce(e,b,c,d)},w.find=w.detect=function(a,b,c){var d;return y(a,function(a,e,f){if(b.call(c,a,e,f))return d=a,!0}),d},w.filter=w.select=function(a,b,c){var d=[];return a==null?d:o&&a.filter===o?a.filter(b,c):(x(a,function(a,e,f){b.call(c,a,e,f)&&(d[d.length]=a)}),d)},w.reject=function(a,b,c){var d=[];return a==null?d:(x(a,function(a,e,f){b.call(c,a,e,f)||(d[d.length]=a)}),d)},w.every=w.all=function(a,b,d){var e=!0;return a==null?e:p&&a.every===p?a.every(b,d):(x(a,function(a,f,g){if(!(e=e&&b.call(d,a,f,g)))return c}),e)};var y=w.some=w.any=function(a,b,d){b=b||w.identity;var e=!1;return a==null?e:q&&a.some===q?a.some(b,d):(x(a,function(a,f,g){if(e|=b.call(d,a,f,g))return c}),!!e)};w.include=w.contains=function(a,b){var c=!1;return a==null?c:r&&a.indexOf===r?a.indexOf(b)!=-1:(y(a,function(a){if(c=a===b)return!0}),c)},w.invoke=function(a,b){var c=g.call(arguments,2);return w.map(a,function(a){return(b.call?b||a:a[b]).apply(a,c)})},w.pluck=function(a,b){return w.map(a,function(a){return a[b]})},w.max=function(a,b,c){if(!b&&w.isArray(a))return Math.max.apply(Math,a);var d={computed:-Infinity};return x(a,function(a,e,f){var g=b?b.call(c,a,e,f):a;g>=d.computed&&(d={value:a,computed:g})}),d.value},w.min=function(a,b,c){if(!b&&w.isArray(a))return Math.min.apply(Math,a);var d={computed:Infinity};return x(a,function(a,e,f){var g=b?b.call(c,a,e,f):a;g<d.computed&&(d={value:a,computed:g})}),d.value},w.sortBy=function(a,b,c){return w.pluck(w.map(a,function(a,d,e){return{value:a,criteria:b.call(c,a,d,e)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c<d?-1:c>d?1:0}),"value")},w.groupBy=function(a,b){var c={};return x(a,function(a,d){var e=b(a,d);(c[e]||(c[e]=[])).push(a)}),c},w.sortedIndex=function(a,b,c){c||(c=w.identity);var d=0,e=a.length;while(d<e){var f=d+e>>1;c(a[f])<c(b)?d=f+1:e=f}return d},w.toArray=function(a){return a?a.toArray?a.toArray():w.isArray(a)?g.call(a):w.isArguments(a)?g.call(a):w.values(a):[]},w.size=function(a){return w.toArray(a).length},w.first=w.head=function(a,b,c){return b!=null&&!c?g.call(a,0,b):a[0]},w.rest=w.tail=function(a,b,c){return g.call(a,b==null||c?1:b)},w.last=function(a){return a[a.length-1]},w.compact=function(a){return w.filter(a,function(a){return!!a})},w.flatten=function(a){return w.reduce(a,function(a,b){return w.isArray(b)?a.concat(w.flatten(b)):(a[a.length]=b,a)},[])},w.without=function(a){return w.difference(a,g.call(arguments,1))},w.uniq=w.unique=function(a,b){return w.reduce(a,function(a,c,d){if(0==d||(b===!0?w.last(a)!=c:!w.include(a,c)))a[a.length]=c;return a},[])},w.union=function(){return w.uniq(w.flatten(arguments))},w.intersection=w.intersect=function(a){var b=g.call(arguments,1);return w.filter(w.uniq(a),function(a){return w.every(b,function(b){return w.indexOf(b,a)>=0})})},w.difference=function(a,b){return w.filter(a,function(a){return!w.include(b,a)})},w.zip=function(){var a=g.call(arguments),b=w.max(w.pluck(a,"length")),c=new Array(b);for(var d=0;d<b;d++)c[d]=w.pluck(a,""+d);return c},w.indexOf=function(a,b,c){if(a==null)return-1;var d,e;if(c)return d=w.sortedIndex(a,b),a[d]===b?d:-1;if(r&&a.indexOf===r)return a.indexOf(b);for(d=0,e=a.length;d<e;d++)if(a[d]===b)return d;return-1},w.lastIndexOf=function(a,b){if(a==null)return-1;if(s&&a.lastIndexOf===s)return a.lastIndexOf(b);var c=a.length;while(c--)if(a[c]===b)return c;return-1},w.range=function(a,b,c){arguments.length<=1&&(b=a||0,a=0),c=arguments[2]||1;var d=Math.max(Math.ceil((b-a)/c),0),e=0,f=new Array(d);while(e<d)f[e++]=a,a+=c;return f},w.bind=function(a,b){if(a.bind===v&&v)return v.apply(a,g.call(arguments,1));var c=g.call(arguments,2);return function(){return a.apply(b,c.concat(g.call(arguments)))}},w.bindAll=function(a){var b=g.call(arguments,1);return b.length==0&&(b=w.functions(a)),x(b,function(b){a[b]=w.bind(a[b],a)}),a},w.memoize=function(a,b){var c={};return b||(b=w.identity),function(){var d=b.apply(this,arguments);return j.call(c,d)?c[d]:c[d]=a.apply(this,arguments)}},w.delay=function(a,b){var c=g.call(arguments,2);return setTimeout(function(){return a.apply(a,c)},b)},w.defer=function(a){return w.delay.apply(w,[a,1].concat(g.call(arguments,1)))};var z=function(a,b,c){var d;return function(){var e=this,f=arguments,g=function(){d=null,a.apply(e,f)};c&&clearTimeout(d);if(c||!d)d=setTimeout(g,b)}};w.throttle=function(a,b){return z(a,b,!1)},w.debounce=function(a,b){return z(a,b,!0)},w.once=function(a){var b=!1,c;return function(){return b?c:(b=!0,c=a.apply(this,arguments))}},w.wrap=function(a,b){return function(){var c=[a].concat(g.call(arguments));return b.apply(this,c)}},w.compose=function(){var a=g.call(arguments);return function(){var b=g.call(arguments);for(var c=a.length-1;c>=0;c--)b=[a[c].apply(this,b)];return b[0]}},w.after=function(a,b){return function(){if(--a<1)return b.apply(this,arguments)}},w.keys=u||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[];for(var c in a)j.call(a,c)&&(b[b.length]=c);return b},w.values=function(a){return w.map(a,w.identity)},w.functions=w.methods=function(a){var b=[];for(var c in a)w.isFunction(a[c])&&b.push(c);return b.sort()},w.extend=function(a){return x(g.call(arguments,1),function(b){for(var c in b)b[c]!==void 0&&(a[c]=b[c])}),a},w.defaults=function(a){return x(g.call(arguments,1),function(b){for(var c in b)a[c]==null&&(a[c]=b[c])}),a},w.clone=function(a){return w.isArray(a)?a.slice():w.extend({},a)},w.tap=function(a,b){return b(a),a},w.isEqual=function(a,b){if(a===b)return!0;var c=typeof a,d=typeof b;if(c!=d)return!1;if(a==b)return!0;if(!a&&b||a&&!b)return!1;a._chain&&(a=a._wrapped),b._chain&&(b=b._wrapped);if(a.isEqual)return a.isEqual(b);if(b.isEqual)return b.isEqual(a);if(w.isDate(a)&&w.isDate(b))return a.getTime()===b.getTime();if(w.isNaN(a)&&w.isNaN(b))return!1;if(w.isRegExp(a)&&w.isRegExp(b))return a.source===b.source&&a.global===b.global&&a.ignoreCase===b.ignoreCase&&a.multiline===b.multiline;if(c!=="object")return!1;if(a.length&&a.length!==b.length)return!1;var e=w.keys(a),f=w.keys(b);if(e.length!=f.length)return!1;for(var g in a)if(!(g in b)||!w.isEqual(a[g],b[g]))return!1;return!0},w.isEmpty=function(a){if(w.isArray(a)||w.isString(a))return a.length===0;for(var b in a)if(j.call(a,b))return!1;return!0},w.isElement=function(a){return!!a&&a.nodeType==1},w.isArray=t||function(a){return i.call(a)==="[object Array]"},w.isObject=function(a){return a===Object(a)},w.isArguments=function(a){return!!a&&!!j.call(a,"callee")},w.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)},w.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)},w.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)},w.isNaN=function(a){return a!==a},w.isBoolean=function(a){return a===!0||a===!1},w.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)},w.isRegExp=function(a){return!(!(a&&a.test&&a.exec)||!a.ignoreCase&&a.ignoreCase!==!1)},w.isNull=function(a){return a===null},w.isUndefined=function(a){return a===void 0},w.noConflict=function(){return a._=b,this},w.identity=function(a){return a},w.times=function(a,b,c){for(var d=0;d<a;d++)b.call(c,d)},w.mixin=function(a){x(w.functions(a),function(b){D(b,w[b]=a[b])})};var A=0;w.uniqueId=function(a){var b=A++;return a?a+b:b},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g},w.template=function(a,b){var c=w.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(c.interpolate,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(c.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj",d);return b?e(b):e};var B=function(a){this._wrapped=a};w.prototype=B.prototype;var C=function(a,b){return b?w(a).chain():a},D=function(a,b){B.prototype[a]=function(){var a=g.call(arguments);return h.call(a,this._wrapped),C(b.apply(w,a),this._chain)}};w.mixin(w),x(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var b=d[a];B.prototype[a]=function(){return b.apply(this._wrapped,arguments),C(this._wrapped,this._chain)}}),x(["concat","join","slice"],function(a){var b=d[a];B.prototype[a]=function(){return C(b.apply(this._wrapped,arguments),this._chain)}}),B.prototype.chain=function(){return this._chain=!0,this},B.prototype.value=function(){return this._wrapped}})();
-/**
- * Flotr2 (c) 2012 Carl Sutherland
- * MIT License
- * Special thanks to:
- * Flotr: http://code.google.com/p/flotr/ (fork)
- * Flot: https://github.com/flot/flot (original fork)
- */
-(function(){var a=this,b=this.Flotr,c;c={_:_,bean:bean,isIphone:/iphone/i.test(navigator.userAgent),isIE:navigator.appVersion.indexOf("MSIE")!=-1?parseFloat(navigator.appVersion.split("MSIE")[1]):!1,graphTypes:{},plugins:{},addType:function(a,b){c.graphTypes[a]=b,c.defaultOptions[a]=b.options||{},c.defaultOptions.defaultType=c.defaultOptions.defaultType||a},addPlugin:function(a,b){c.plugins[a]=b,c.defaultOptions[a]=b.options||{}},draw:function(a,b,d,e){return e=e||c.Graph,new e(a,b,d)},merge:function(a,b){var d,e,f=b||{};for(d in a)e=a[d],e&&typeof e=="object"?e.constructor===Array?f[d]=this._.clone(e):e.constructor!==RegExp&&!this._.isElement(e)?f[d]=c.merge(e,b?b[d]:undefined):f[d]=e:f[d]=e;return f},clone:function(a){return c.merge(a,{})},getTickSize:function(a,b,d,e){var f=(d-b)/a,g=c.getMagnitude(f),h=10,i=f/g;return i<1.5?h=1:i<2.25?h=2:i<3?h=e===0?2:2.5:i<7.5&&(h=5),h*g},defaultTickFormatter:function(a,b){return a+""},defaultTrackFormatter:function(a){return"("+a.x+", "+a.y+")"},engineeringNotation:function(a,b,c){var d=["Y","Z","E","P","T","G","M","k",""],e=["y","z","a","f","p","n","µ","m",""],f=d.length;c=c||1e3,b=Math.pow(10,b||2);if(a===0)return 0;if(a>1)while(f--&&a>=c)a/=c;else{d=e,f=d.length;while(f--&&a<1)a*=c}return Math.round(a*b)/b+d[f]},getMagnitude:function(a){return Math.pow(10,Math.floor(Math.log(a)/Math.LN10))},toPixel:function(a){return Math.floor(a)+.5},toRad:function(a){return-a*(Math.PI/180)},floorInBase:function(a,b){return b*Math.floor(a/b)},drawText:function(a,b,d,e,f){if(!a.fillText){a.drawText(b,d,e,f);return}f=this._.extend({size:c.defaultOptions.fontSize,color:"#000000",textAlign:"left",textBaseline:"bottom",weight:1,angle:0},f),a.save(),a.translate(d,e),a.rotate(f.angle),a.fillStyle=f.color,a.font=(f.weight>1?"bold ":"")+f.size*1.3+"px sans-serif",a.textAlign=f.textAlign,a.textBaseline=f.textBaseline,a.fillText(b,0,0),a.restore()},getBestTextAlign:function(a,b){return b=b||{textAlign:"center",textBaseline:"middle"},a+=c.getTextAngleFromAlign(b),Math.abs(Math.cos(a))>.01&&(b.textAlign=Math.cos(a)>0?"right":"left"),Math.abs(Math.sin(a))>.01&&(b.textBaseline=Math.sin(a)>0?"top":"bottom"),b},alignTable:{"right middle":0,"right top":Math.PI/4,"center top":Math.PI/2,"left top":3*(Math.PI/4),"left middle":Math.PI,"left bottom":-3*(Math.PI/4),"center bottom":-Math.PI/2,"right bottom":-Math.PI/4,"center middle":0},getTextAngleFromAlign:function(a){return c.alignTable[a.textAlign+" "+a.textBaseline]||0},noConflict:function(){return a.Flotr=b,this}},a.Flotr=c})(),Flotr.defaultOptions={colors:["#00A8F0","#C0D800","#CB4B4B","#4DA74D","#9440ED"],ieBackgroundColor:"#FFFFFF",title:null,subtitle:null,shadowSize:4,defaultType:null,HtmlText:!0,fontColor:"#545454",fontSize:7.5,resolution:1,parseFloat:!0,xaxis:{ticks:null,minorTicks:null,showLabels:!0,showMinorLabels:!1,labelsAngle:0,title:null,titleAngle:0,noTicks:5,minorTickFreq:null,tickFormatter:Flotr.defaultTickFormatter,tickDecimals:null,min:null,max:null,autoscale:!1,autoscaleMargin:0,color:null,mode:"normal",timeFormat:null,timeMode:"UTC",timeUnit:"millisecond",scaling:"linear",base:Math.E,titleAlign:"center",margin:!0},x2axis:{},yaxis:{ticks:null,minorTicks:null,showLabels:!0,showMinorLabels:!1,labelsAngle:0,title:null,titleAngle:90,noTicks:5,minorTickFreq:null,tickFormatter:Flotr.defaultTickFormatter,tickDecimals:null,min:null,max:null,autoscale:!1,autoscaleMargin:0,color:null,scaling:"linear",base:Math.E,titleAlign:"center",margin:!0},y2axis:{titleAngle:270},grid:{color:"#545454",backgroundColor:null,backgroundImage:null,watermarkAlpha:.4,tickColor:"#DDDDDD",labelMargin:3,verticalLines:!0,minorVerticalLines:null,horizontalLines:!0,minorHorizontalLines:null,outlineWidth:1,outline:"nsew",circular:!1},mouse:{track:!1,trackAll:!1,position:"se",relative:!1,trackFormatter:Flotr.defaultTrackFormatter,margin:5,lineColor:"#FF3F19",trackDecimals:1,sensibility:2,trackY:!0,radius:3,fillColor:null,fillOpacity:.4}},function(){function b(a,b,c,d){this.rgba=["r","g","b","a"];var e=4;while(-1<--e)this[this.rgba[e]]=arguments[e]||(e==3?1:0);this.normalize()}var a=Flotr._,c={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]};b.prototype={scale:function(b,c,d,e){var f=4;while(-1<--f)a.isUndefined(arguments[f])||(this[this.rgba[f]]*=arguments[f]);return this.normalize()},alpha:function(b){return!a.isUndefined(b)&&!a.isNull(b)&&(this.a=b),this.normalize()},clone:function(){return new b(this.r,this.b,this.g,this.a)},limit:function(a,b,c){return Math.max(Math.min(a,c),b)},normalize:function(){var a=this.limit;return this.r=a(parseInt(this.r,10),0,255),this.g=a(parseInt(this.g,10),0,255),this.b=a(parseInt(this.b,10),0,255),this.a=a(this.a,0,1),this},distance:function(a){if(!a)return;a=new b.parse(a);var c=0,d=3;while(-1<--d)c+=Math.abs(this[this.rgba[d]]-a[this.rgba[d]]);return c},toString:function(){return this.a>=1?"rgb("+[this.r,this.g,this.b].join(",")+")":"rgba("+[this.r,this.g,this.b,this.a].join(",")+")"},contrast:function(){var a=1-(.299*this.r+.587*this.g+.114*this.b)/255;return a<.5?"#000000":"#ffffff"}},a.extend(b,{parse:function(a){if(a instanceof b)return a;var d;if(d=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(a))return new b(parseInt(d[1],16),parseInt(d[2],16),parseInt(d[3],16));if(d=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(a))return new b(parseInt(d[1],10),parseInt(d[2],10),parseInt(d[3],10));if(d=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(a))return new b(parseInt(d[1]+d[1],16),parseInt(d[2]+d[2],16),parseInt(d[3]+d[3],16));if(d=/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(a))return new b(parseInt(d[1],10),parseInt(d[2],10),parseInt(d[3],10),parseFloat(d[4]));if(d=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(a))return new b(parseFloat(d[1])*2.55,parseFloat(d[2])*2.55,parseFloat(d[3])*2.55);if(d=/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(a))return new b(parseFloat(d[1])*2.55,parseFloat(d[2])*2.55,parseFloat(d[3])*2.55,parseFloat(d[4]));var e=(a+"").replace(/^\s*([\S\s]*?)\s*$/,"$1").toLowerCase();return e=="transparent"?new b(255,255,255,0):(d=c[e])?new b(d[0],d[1],d[2]):new b(0,0,0,0)},processColor:function(c,d){var e=d.opacity;if(!c)return"rgba(0, 0, 0, 0)";if(c instanceof b)return c.alpha(e).toString();if(a.isString(c))return b.parse(c).alpha(e).toString();var f=c.colors?c:{colors:c};if(!d.ctx)return a.isArray(f.colors)?b.parse(a.isArray(f.colors[0])?f.colors[0][1]:f.colors[0]).alpha(e).toString():"rgba(0, 0, 0, 0)";f=a.extend({start:"top",end:"bottom"},f),/top/i.test(f.start)&&(d.x1=0),/left/i.test(f.start)&&(d.y1=0),/bottom/i.test(f.end)&&(d.x2=0),/right/i.test(f.end)&&(d.y2=0);var g,h,i,j=d.ctx.createLinearGradient(d.x1,d.y1,d.x2,d.y2);for(g=0;g<f.colors.length;g++)h=f.colors[g],a.isArray(h)?(i=h[0],h=h[1]):i=g/(f.colors.length-1),j.addColorStop(i,b.parse(h).alpha(e));return j}}),Flotr.Color=b}(),Flotr.Date={set:function(a,b,c,d){c=c||"UTC",b="set"+(c==="UTC"?"UTC":"")+b,a[b](d)},get:function(a,b,c){return c=c||"UTC",b="get"+(c==="UTC"?"UTC":"")+b,a[b]()},format:function(a,b,c){function f(a){return a+="",a.length==1?"0"+a:a}if(!a)return;var d=this.get,e={h:d(a,"Hours",c).toString(),H:f(d(a,"Hours",c)),M:f(d(a,"Minutes",c)),S:f(d(a,"Seconds",c)),s:d(a,"Milliseconds",c),d:d(a,"Date",c).toString(),m:(d(a,"Month")+1).toString(),y:d(a,"FullYear").toString(),b:Flotr.Date.monthNames[d(a,"Month",c)]},g=[],h,i=!1;for(var j=0;j<b.length;++j)h=b.charAt(j),i?(g.push(e[h]||h),i=!1):h=="%"?i=!0:g.push(h);return g.join("")},getFormat:function(a,b){var c=Flotr.Date.timeUnits;return a<c.second?"%h:%M:%S.%s":a<c.minute?"%h:%M:%S":a<c.day?b<2*c.day?"%h:%M":"%b %d %h:%M":a<c.month?"%b %d":a<c.year?b<c.year?"%b":"%b %y":"%y"},formatter:function(a,b){var c=b.options,d=Flotr.Date.timeUnits[c.timeUnit],e=new Date(a*d);if(b.options.timeFormat)return Flotr.Date.format(e,c.timeFormat,c.timeMode);var f=(b.max-b.min)*d,g=b.tickSize*Flotr.Date.timeUnits[b.tickUnit];return Flotr.Date.format(e,Flotr.Date.getFormat(g,f),c.timeMode)},generator:function(a){function s(a){b(q,a,g,Flotr.floorInBase(c(q,a,g),m))}var b=this.set,c=this.get,d=this.timeUnits,e=this.spec,f=a.options,g=f.timeMode,h=d[f.timeUnit],i=a.min*h,j=a.max*h,k=(j-i)/f.noTicks,l=[],m=a.tickSize,n,o,p;o=f.tickFormatter===Flotr.defaultTickFormatter?this.formatter:f.tickFormatter;for(p=0;p<e.length-1;++p){var q=e[p][0]*d[e[p][1]];if(k<(q+e[p+1][0]*d[e[p+1][1]])/2&&q>=m)break}m=e[p][0],n=e[p][1],n=="year"&&(m=Flotr.getTickSize(f.noTicks*d.year,i,j,0),m==.5&&(n="month",m=6)),a.tickUnit=n,a.tickSize=m;var q=new Date(i),r=m*d[n];switch(n){case"millisecond":s("Milliseconds");break;case"second":s("Seconds");break;case"minute":s("Minutes");break;case"hour":s("Hours");break;case"month":s("Month");break;case"year":s("FullYear")}r>=d.second&&b(q,"Milliseconds",g,0),r>=d.minute&&b(q,"Seconds",g,0),r>=d.hour&&b(q,"Minutes",g,0),r>=d.day&&b(q,"Hours",g,0),r>=d.day*4&&b(q,"Date",g,1),r>=d.year&&b(q,"Month",g,0);var t=0,u=NaN,v;do{v=u,u=q.getTime(),l.push({v:u/h,label:o(u/h,a)});if(n=="month")if(m<1){b(q,"Date",g,1);var w=q.getTime();b(q,"Month",g,c(q,"Month",g)+1);var x=q.getTime();q.setTime(u+t*d.hour+(x-w)*m),t=c(q,"Hours",g),b(q,"Hours",g,0)}else b(q,"Month",g,c(q,"Month",g)+m);else n=="year"?b(q,"FullYear",g,c(q,"FullYear",g)+m):q.setTime(u+r)}while(u<j&&u!=v);return l},timeUnits:{millisecond:1,second:1e3,minute:6e4,hour:36e5,day:864e5,month:2592e6,year:31556952e3},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"],[.25,"month"],[.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"]},function(){var a=Flotr._;Flotr.DOM={addClass:function(b,c){var d=b.className?b.className:"";if(a.include(d.split(/\s+/g),c))return;b.className=(d?d+" ":"")+c},create:function(a){return document.createElement(a)},node:function(a){var b=Flotr.DOM.create("div"),c;return b.innerHTML=a,c=b.children[0],b.innerHTML="",c},empty:function(a){a.innerHTML=""},hide:function(a){Flotr.DOM.setStyles(a,{display:"none"})},insert:function(b,c){a.isString(c)?b.innerHTML+=c:a.isElement(c)&&b.appendChild(c)},opacity:function(a,b){a.style.opacity=b},position:function(a,b){return a.offsetParent?(b=this.position(a.offsetParent),b.left+=a.offsetLeft,b.top+=a.offsetTop,b):{left:a.offsetLeft||0,top:a.offsetTop||0}},removeClass:function(b,c){var d=b.className?b.className:"";b.className=a.filter(d.split(/\s+/g),function(a){if(a!=c)return!0}).join(" ")},setStyles:function(b,c){a.each(c,function(a,c){b.style[c]=a})},show:function(a){Flotr.DOM.setStyles(a,{display:""})},size:function(a){return{height:a.offsetHeight,width:a.offsetWidth}}}}(),function(){var a=Flotr,b=a.bean;a.EventAdapter={observe:function(a,c,d){return b.add(a,c,d),this},fire:function(a,c,d){return b.fire(a,c,d),typeof Prototype!="undefined"&&Event.fire(a,c,d),this},stopObserving:function(a,c,d){return b.remove(a,c,d),this},eventPointer:function(b){if(!a._.isUndefined(b.touches)&&b.touches.length>0)return{x:b.touches[0].pageX,y:b.touches[0].pageY};if(!a._.isUndefined(b.changedTouches)&&b.changedTouches.length>0)return{x:b.changedTouches[0].pageX,y:b.changedTouches[0].pageY};if(b.pageX||b.pageY)return{x:b.pageX,y:b.pageY};if(b.clientX||b.clientY){var c=document,d=c.body,e=c.documentElement;return{x:b.clientX+d.scrollLeft+e.scrollLeft,y:b.clientY+d.scrollTop+e.scrollTop}}}}}(),function(){var a=Flotr,b=a.DOM,c=a._,d=function(a){this.o=a};d.prototype={dimensions:function(a,b,c,d){return a?this.o.html?this.html(a,this.o.element,c,d):this.canvas(a,b):{width:0,height:0}},canvas:function(b,c){if(!this.o.textEnabled)return;c=c||{};var d=this.measureText(b,c),e=d.width,f=c.size||a.defaultOptions.fontSize,g=c.angle||0,h=Math.cos(g),i=Math.sin(g),j=2,k=6,l;return l={width:Math.abs(h*e)+Math.abs(i*f)+j,height:Math.abs(i*e)+Math.abs(h*f)+k},l},html:function(a,c,d,e){var f=b.create("div");return b.setStyles(f,{position:"absolute",top:"-10000px"}),b.insert(f,'<div style="'+d+'" class="'+e+' flotr-dummy-div">'+a+"</div>"),b.insert(this.o.element,f),b.size(f)},measureText:function(b,d){var e=this.o.ctx,f;return!e.fillText||a.isIphone&&e.measure?{width:e.measure(b,d)}:(d=c.extend({size:a.defaultOptions.fontSize,weight:1,angle:0},d),e.save(),e.font=(d.weight>1?"bold ":"")+d.size*1.3+"px sans-serif",f=e.measureText(b),e.restore(),f)}},Flotr.Text=d}(),function(){function e(a,c,d){return b.observe.apply(this,arguments),this._handles.push(arguments),this}var a=Flotr.DOM,b=Flotr.EventAdapter,c=Flotr._,d=Flotr;Graph=function(a,e,f){this._setEl(a),this._initMembers(),this._initPlugins(),b.fire(this.el,"flotr:beforeinit",[this]),this.data=e,this.series=d.Series.getSeries(e),this._initOptions(f),this._initGraphTypes(),this._initCanvas(),this._text=new d.Text({element:this.el,ctx:this.ctx,html:this.options.HtmlText,textEnabled:this.textEnabled}),b.fire(this.el,"flotr:afterconstruct",[this]),this._initEvents(),this.findDataRanges(),this.calculateSpacing(),this.draw(c.bind(function(){b.fire(this.el,"flotr:afterinit",[this])},this))},Graph.prototype={destroy:function(){b.fire(this.el,"flotr:destroy"),c.each(this._handles,function(a){b.stopObserving.apply(this,a)}),this._handles=[],this.el.graph=null},observe:e,_observe:e,processColor:function(a,b){var e={x1:0,y1:0,x2:this.plotWidth,y2:this.plotHeight,opacity:1,ctx:this.ctx};return c.extend(e,b),d.Color.processColor(a,e)},findDataRanges:function(){var a=this.axes,b,e,f;c.each(this.series,function(a){f=a.getRange(),f&&(b=a.xaxis,e=a.yaxis,b.datamin=Math.min(f.xmin,b.datamin),b.datamax=Math.max(f.xmax,b.datamax),e.datamin=Math.min(f.ymin,e.datamin),e.datamax=Math.max(f.ymax,e.datamax),b.used=b.used||f.xused,e.used=e.used||f.yused)},this),!a.x.used&&!a.x2.used&&(a.x.used=!0),!a.y.used&&!a.y2.used&&(a.y.used=!0),c.each(a,function(a){a.calculateRange()});var g=c.keys(d.graphTypes),h=!1;c.each(this.series,function(a){if(a.hide)return;c.each(g,function(b){a[b]&&a[b].show&&(this.extendRange(b,a),h=!0)},this),h||this.extendRange(this.options.defaultType,a)},this)},extendRange:function(a,b){this[a].extendRange&&this[a].extendRange(b,b.data,b[a],this[a]),this[a].extendYRange&&this[a].extendYRange(b.yaxis,b.data,b[a],this[a]),this[a].extendXRange&&this[a].extendXRange(b.xaxis,b.data,b[a],this[a])},calculateSpacing:function(){var a=this.axes,b=this.options,d=this.series,e=b.grid.labelMargin,f=this._text,g=a.x,h=a.x2,i=a.y,j=a.y2,k=b.grid.outlineWidth,l,m,n,o;c.each(a,function(a){a.calculateTicks(),a.calculateTextDimensions(f,b)}),o=f.dimensions(b.title,{size:b.fontSize*1.5},"font-size:1em;font-weight:bold;","flotr-title"),this.titleHeight=o.height,o=f.dimensions(b.subtitle,{size:b.fontSize},"font-size:smaller;","flotr-subtitle"),this.subtitleHeight=o.height;for(m=0;m<b.length;++m)d[m].points.show&&(k=Math.max(k,d[m].points.radius+d[m].points.lineWidth/2));var p=this.plotOffset;g.options.margin===!1?(p.bottom=0,p.top=0):(p.bottom+=(b.grid.circular?0:g.used&&g.options.showLabels?g.maxLabel.height+e:0)+(g.used&&g.options.title?g.titleSize.height+e:0)+k,p.top+=(b.grid.circular?0:h.used&&h.options.showLabels?h.maxLabel.height+e:0)+(h.used&&h.options.title?h.titleSize.height+e:0)+this.subtitleHeight+this.titleHeight+k),i.options.margin===!1?(p.left=0,p.right=0):(p.left+=(b.grid.circular?0:i.used&&i.options.showLabels?i.maxLabel.width+e:0)+(i.used&&i.options.title?i.titleSize.width+e:0)+k,p.right+=(b.grid.circular?0:j.used&&j.options.showLabels?j.maxLabel.width+e:0)+(j.used&&j.options.title?j.titleSize.width+e:0)+k),p.top=Math.floor(p.top),this.plotWidth=this.canvasWidth-p.left-p.right,this.plotHeight=this.canvasHeight-p.bottom-p.top,g.length=h.length=this.plotWidth,i.length=j.length=this.plotHeight,i.offset=j.offset=this.plotHeight,g.setScale(),h.setScale(),i.setScale(),j.setScale()},draw:function(a){var c=this.ctx,d;b.fire(this.el,"flotr:beforedraw",[this.series,this]);if(this.series.length){c.save(),c.translate(this.plotOffset.left,this.plotOffset.top);for(d=0;d<this.series.length;d++)this.series[d].hide||this.drawSeries(this.series[d]);c.restore(),this.clip()}b.fire(this.el,"flotr:afterdraw",[this.series,this]),a&&a()},drawSeries:function(a){function b(a,b){var c=this.getOptions(a,b);this[b].draw(c)}var e=!1;a=a||this.series,c.each(d.graphTypes,function(c,d){a[d]&&a[d].show&&this[d]&&(e=!0,b.call(this,a,d))},this),e||b.call(this,a,this.options.defaultType)},getOptions:function(a,b){var e=a[b],f=this[b],g={context:this.ctx,width:this.plotWidth,height:this.plotHeight,fontSize:this.options.fontSize,fontColor:this.options.fontColor,textEnabled:this.textEnabled,htmlText:this.options.HtmlText,text:this._text,element:this.el,data:a.data,color:a.color,shadowSize:a.shadowSize,xScale:c.bind(a.xaxis.d2p,a.xaxis),yScale:c.bind(a.yaxis.d2p,a.yaxis)};return g=d.merge(e,g),g.fillStyle=this.processColor(e.fillColor||a.color,{opacity:e.fillOpacity}),g},getEventPosition:function(c){var d=document,e=d.body,f=d.documentElement,g=this.axes,h=this.plotOffset,i=this.lastMousePos,j=b.eventPointer(c),k=j.x-i.pageX,l=j.y-i.pageY,m,n,o;return"ontouchstart"in this.el?(m=a.position(this.overlay),n=j.x-m.left-h.left,o=j.y-m.top-h.top):(m=this.overlay.getBoundingClientRect(),n=c.clientX-m.left-h.left-e.scrollLeft-f.scrollLeft,o=c.clientY-m.top-h.top-e.scrollTop-f.scrollTop),{x:g.x.p2d(n),x2:g.x2.p2d(n),y:g.y.p2d(o),y2:g.y2.p2d(o),relX:n,relY:o,dX:k,dY:l,absX:j.x,absY:j.y,pageX:j.x,pageY:j.y}},clickHandler:function(a){if(this.ignoreClick)return this.ignoreClick=!1,this.ignoreClick;b.fire(this.el,"flotr:click",[this.getEventPosition(a),this])},mouseMoveHandler:function(a){if(this.mouseDownMoveHandler)return;var c=this.getEventPosition(a);b.fire(this.el,"flotr:mousemove",[a,c,this]),this.lastMousePos=c},mouseDownHandler:function(a){if(this.mouseUpHandler)return;this.mouseUpHandler=c.bind(function(a){b.stopObserving(document,"mouseup",this.mouseUpHandler),b.stopObserving(document,"mousemove",this.mouseDownMoveHandler),this.mouseDownMoveHandler=null,this.mouseUpHandler=null,b.fire(this.el,"flotr:mouseup",[a,this])},this),this.mouseDownMoveHandler=c.bind(function(c){var d=this.getEventPosition(c);b.fire(this.el,"flotr:mousemove",[a,d,this]),this.lastMousePos=d},this),b.observe(document,"mouseup",this.mouseUpHandler),b.observe(document,"mousemove",this.mouseDownMoveHandler),b.fire(this.el,"flotr:mousedown",[a,this]),this.ignoreClick=!1},drawTooltip:function(b,c,d,e){var f=this.getMouseTrack(),g="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;",h=e.position,i=e.margin,j=this.plotOffset;c!==null&&d!==null?(e.relative?(h.charAt(0)=="n"?g+="bottom:"+(i-j.top-d+this.canvasHeight)+"px;top:auto;":h.charAt(0)=="s"&&(g+="top:"+(i+j.top+d)+"px;bottom:auto;"),h.charAt(1)=="e"?g+="left:"+(i+j.left+c)+"px;right:auto;":h.charAt(1)=="w"&&(g+="right:"+(i-j.left-c+this.canvasWidth)+"px;left:auto;")):(h.charAt(0)=="n"?g+="top:"+(i+j.top)+"px;bottom:auto;":h.charAt(0)=="s"&&(g+="bottom:"+(i+j.bottom)+"px;top:auto;"),h.charAt(1)=="e"?g+="right:"+(i+j.right)+"px;left:auto;":h.charAt(1)=="w"&&(g+="left:"+(i+j.left)+"px;right:auto;")),f.style.cssText=g,a.empty(f),a.insert(f,b),a.show(f)):a.hide(f)},clip:function(){var a=this.ctx,b=this.plotOffset,c=this.canvasWidth,e=this.canvasHeight;d.isIE&&d.isIE<9?(a.save(),a.fillStyle=this.processColor(this.options.ieBackgroundColor),a.fillRect(0,0,c,b.top),a.fillRect(0,0,b.left,e),a.fillRect(0,e-b.bottom,c,b.bottom),a.fillRect(c-b.right,0,b.right,e),a.restore()):(a.clearRect(0,0,c,b.top),a.clearRect(0,0,b.left,e),a.clearRect(0,e-b.bottom,c,b.bottom),a.clearRect(c-b.right,0,b.right,e))},_initMembers:function(){this._handles=[],this.lastMousePos={pageX:null,pageY:null},this.plotOffset={left:0,right:0,top:0,bottom:0},this.ignoreClick=!0,this.prevHit=null},_initGraphTypes:function(){c.each(d.graphTypes,function(a,b){this[b]=d.clone(a)},this)},_initEvents:function(){var a=this.el,d,e,f;"ontouchstart"in a?(d=c.bind(function(c){f=!0,b.stopObserving(document,"touchend",d),b.fire(a,"flotr:mouseup",[event,this]),this.multitouches=null,e||this.clickHandler(c)},this),this.observe(this.overlay,"touchstart",c.bind(function(c){e=!1,f=!1,this.ignoreClick=!1,c.touches&&c.touches.length>1&&(this.multitouches=c.touches),b.fire(a,"flotr:mousedown",[event,this]),this.observe(document,"touchend",d)},this)),this.observe(this.overlay,"touchmove",c.bind(function(c){var d=this.getEventPosition(c);c.preventDefault(),e=!0,this.multitouches||c.touches&&c.touches.length>1?this.multitouches=c.touches:f||b.fire(a,"flotr:mousemove",[event,d,this]),this.lastMousePos=d},this))):this.observe(this.overlay,"mousedown",c.bind(this.mouseDownHandler,this)).observe(a,"mousemove",c.bind(this.mouseMoveHandler,this)).observe(this.overlay,"click",c.bind(this.clickHandler,this)).observe(a,"mouseout",function(){b.fire(a,"flotr:mouseout")})},_initCanvas:function(){function k(e,f){return e||(e=a.create("canvas"),typeof FlashCanvas!="undefined"&&typeof e.getContext=="function"&&FlashCanvas.initElement(e),e.className="flotr-"+f,e.style.cssText="position:absolute;left:0px;top:0px;",a.insert(b,e)),c.each(i,function(b,c){a.show(e);if(f=="canvas"&&e.getAttribute(c)===b)return;e.setAttribute(c,b*d.resolution),e.style[c]=b+"px"}),e.context_=null,e}function l(a){window.G_vmlCanvasManager&&window.G_vmlCanvasManager.initElement(a);var b=a.getContext("2d");return window.G_vmlCanvasManager||b.scale(d.resolution,d.resolution),b}var b=this.el,d=this.options,e=b.children,f=[],g,h,i,j;for(h=e.length;h--;)g=e[h],!this.canvas&&g.className==="flotr-canvas"?this.canvas=g:!this.overlay&&g.className==="flotr-overlay"?this.overlay=g:f.push(g);for(h=f.length;h--;)b.removeChild(f[h]);a.setStyles(b,{position:"relative"}),i={},i.width=b.clientWidth,i.height=b.clientHeight;if(i.width<=0||i.height<=0||d.resolution<=0)throw"Invalid dimensions for plot, width = "+i.width+", height = "+i.height+", resolution = "+d.resolution;this.canvas=k(this.canvas,"canvas"),this.overlay=k(this.overlay,"overlay"),this.ctx=l(this.canvas),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.octx=l(this.overlay),this.octx.clearRect(0,0,this.overlay.width,this.overlay.height),this.canvasHeight=i.height,this.canvasWidth=i.width,this.textEnabled=!!this.ctx.drawText||!!this.ctx.fillText},_initPlugins:function(){c.each(d.plugins,function(a,b){c.each(a.callbacks,function(a,b){this.observe(this.el,b,c.bind(a,this))},this),this[b]=d.clone(a),c.each(this[b],function(a,d){c.isFunction(a)&&(this[b][d]=c.bind(a,this))},this)},this)},_initOptions:function(a){var e=d.clone(d.defaultOptions);e.x2axis=c.extend(c.clone(e.xaxis),e.x2axis),e.y2axis=c.extend(c.clone(e.yaxis),e.y2axis),this.options=d.merge(a||{},e),this.options.grid.minorVerticalLines===null&&this.options.xaxis.scaling==="logarithmic"&&(this.options.grid.minorVerticalLines=!0),this.options.grid.minorHorizontalLines===null&&this.options.yaxis.scaling==="logarithmic"&&(this.options.grid.minorHorizontalLines=!0),b.fire(this.el,"flotr:afterinitoptions",[this]),this.axes=d.Axis.getAxes(this.options);var f=[],g=[],h=this.series.length,i=this.series.length,j=this.options.colors,k=[],l=0,m,n,o,p;for(n=i-1;n>-1;--n)m=this.series[n].color,m&&(--i,c.isNumber(m)?f.push(m):k.push(d.Color.parse(m)));for(n=f.length-1;n>-1;--n)i=Math.max(i,f[n]+1);for(n=0;g.length<i;){m=j.length==n?new d.Color(100,100,100):d.Color.parse(j[n]);var q=l%2==1?-1:1,r=1+q*Math.ceil(l/2)*.2;m.scale(r,r,r),g.push(m),++n>=j.length&&(n=0,++l)}for(n=0,o=0;n<h;++n){p=this.series[n],p.color?c.isNumber(p.color)&&(p.color=g[p.color].toString()):p.color=g[o++].toString(),p.xaxis||(p.xaxis=this.axes.x),p.xaxis==1?p.xaxis=this.axes.x:p.xaxis==2&&(p.xaxis=this.axes.x2),p.yaxis||(p.yaxis=this.axes.y),p.yaxis==1?p.yaxis=this.axes.y:p.yaxis==2&&(p.yaxis=this.axes.y2);for(var s in d.graphTypes)p[s]=c.extend(c.clone(this.options[s]),p[s]);p.mouse=c.extend(c.clone(this.options.mouse),p.mouse),c.isUndefined(p.shadowSize)&&(p.shadowSize=this.options.shadowSize)}},_setEl:function(a){if(!a)throw"The target container doesn't exist";if(a.graph instanceof Graph)a.graph.destroy();else if(!a.clientWidth)throw"The target container must be visible";a.graph=this,this.el=a}},Flotr.Graph=Graph}(),function(){function c(b){this.orientation=1,this.offset=0,this.datamin=Number.MAX_VALUE,this.datamax=-Number.MAX_VALUE,a.extend(this,b),this._setTranslations()}function d(a){return this.offset+this.orientation*(a-this.min)*this.scale}function e(a){return(this.offset+this.orientation*a)/this.scale+this.min}function f(a){return this.offset+this.orientation*(h(a,this.options.base)-h(this.min,this.options.base))*this.scale}function g(a){return j((this.offset+this.orientation*a)/this.scale+h(this.min,this.options.base),this.options.base)}function h(a,b){return a=Math.log(Math.max(a,Number.MIN_VALUE)),b!==Math.E&&(a/=Math.log(b)),a}function j(a,b){return b===Math.E?Math.exp(a):Math.pow(b,a)}var a=Flotr._,b="logarithmic";c.prototype={setScale:function(){var a=this.length;this.options.scaling==b?this.scale=a/(h(this.max,this.options.base)-h(this.min,this.options.base)):this.scale=a/(this.max-this.min)},calculateTicks:function(){var a=this.options;this.ticks=[],this.minorTicks=[],a.ticks?(this._cleanUserTicks(a.ticks,this.ticks),this._cleanUserTicks(a.minorTicks||[],this.minorTicks)):a.mode=="time"?this._calculateTimeTicks():a.scaling==="logarithmic"?this._calculateLogTicks():this._calculateTicks()},calculateRange:function(){if(!this.used)return;var a=this,b=a.options,c=b.min!==null?b.min:a.datamin,d=b.max!==null?b.max:a.datamax,e=b.autoscaleMargin;b.scaling=="logarithmic"&&(c<=0&&(c=a.datamin),d<=0&&(d=c));if(d==c){var f=d?.01:1;b.min===null&&(c-=f),b.max===null&&(d+=f)}if(b.scaling==="logarithmic"){c<0&&(c=d/b.base);var g=Math.log(d);b.base!=Math.E&&(g/=Math.log(b.base)),g=Math.ceil(g);var h=Math.log(c);b.base!=Math.E&&(h/=Math.log(b.base)),h=Math.ceil(h),a.tickSize=Flotr.getTickSize(b.noTicks,h,g,b.tickDecimals===null?0:b.tickDecimals),b.minorTickFreq===null&&(g-h>10?b.minorTickFreq=0:g-h>5?b.minorTickFreq=2:b.minorTickFreq=5)}else a.tickSize=Flotr.getTickSize(b.noTicks,c,d,b.tickDecimals);a.min=c,a.max=d,b.min===null&&b.autoscale&&(a.min-=a.tickSize*e,a.min<0&&a.datamin>=0&&(a.min=0),a.min=a.tickSize*Math.floor(a.min/a.tickSize)),b.max===null&&b.autoscale&&(a.max+=a.tickSize*e,a.max>0&&a.datamax<=0&&a.datamax!=a.datamin&&(a.max=0),a.max=a.tickSize*Math.ceil(a.max/a.tickSize)),a.min==a.max&&(a.max=a.min+1)},calculateTextDimensions:function(a,b){var c="",d,e;if(this.options.showLabels)for(e=0;e<this.ticks.length;++e)d=this.ticks[e].label.length,d>c.length&&(c=this.ticks[e].label);this.maxLabel=a.dimensions(c,{size:b.fontSize,angle:Flotr.toRad(this.options.labelsAngle)},"font-size:smaller;","flotr-grid-label"),this.titleSize=a.dimensions(this.options.title,{size:b.fontSize*1.2,angle:Flotr.toRad(this.options.titleAngle)},"font-weight:bold;","flotr-axis-title")},_cleanUserTicks:function(b,c){var d=this,e=this.options,f,g,h,i;a.isFunction(b)&&(b=b({min:d.min,max:d.max}));for(g=0;g<b.length;++g)i=b[g],typeof i=="object"?(f=i[0],h=i.length>1?i[1]:e.tickFormatter(f,{min:d.min,max:d.max})):(f=i,h=e.tickFormatter(f,{min:this.min,max:this.max})),c[g]={v:f,label:h}},_calculateTimeTicks:function(){this.ticks=Flotr.Date.generator(this)},_calculateLogTicks:function(){var a=this,b=a.options,c,d,e=Math.log(a.max);b.base!=Math.E&&(e/=Math.log(b.base)),e=Math.ceil(e);var f=Math.log(a.min);b.base!=Math.E&&(f/=Math.log(b.base)),f=Math.ceil(f);for(i=f;i<e;i+=a.tickSize){d=b.base==Math.E?Math.exp(i):Math.pow(b.base,i);var g=d*(b.base==Math.E?Math.exp(a.tickSize):Math.pow(b.base,a.tickSize)),h=(g-d)/b.minorTickFreq;a.ticks.push({v:d,label:b.tickFormatter(d,{min:a.min,max:a.max})});for(c=d+h;c<g;c+=h)a.minorTicks.push({v:c,label:b.tickFormatter(c,{min:a.min,max:a.max})})}d=b.base==Math.E?Math.exp(i):Math.pow(b.base,i),a.ticks.push({v:d,label:b.tickFormatter(d,{min:a.min,max:a.max})})},_calculateTicks:function(){var a=this,b=a.options,c=a.tickSize,d=a.min,e=a.max,f=c*Math.ceil(d/c),g,h,i,j,k,l;b.minorTickFreq&&(h=c/b.minorTickFreq);for(k=0;(i=j=f+k*c)<=e;++k){g=b.tickDecimals,g===null&&(g=1-Math.floor(Math.log(c)/Math.LN10)),g<0&&(g=0),i=i.toFixed(g),a.ticks.push({v:i,label:b.tickFormatter(i,{min:a.min,max:a.max})});if(b.minorTickFreq)for(l=0;l<b.minorTickFreq&&k*c+l*h<e;++l)i=j+l*h,a.minorTicks.push({v:i,label:b.tickFormatter(i,{min:a.min,max:a.max})})}},_setTranslations:function(a){this.d2p=a?f:d,this.p2d=a?g:e}},a.extend(c,{getAxes:function(a){return{x:new c({options:a.xaxis,n:1,length:this.plotWidth}),x2:new c({options:a.x2axis,n:2,length:this.plotWidth}),y:new c({options:a.yaxis,n:1,length:this.plotHeight,offset:this.plotHeight,orientation:-1}),y2:new c({options:a.y2axis,n:2,length:this.plotHeight,offset:this.plotHeight,orientation:-1})}}}),Flotr.Axis=c}(),function(){function b(b){a.extend(this,b)}var a=Flotr._;b.prototype={getRange:function(){var a=this.data,b=a.length,c=Number.MAX_VALUE,d=Number.MAX_VALUE,e=-Number.MAX_VALUE,f=-Number.MAX_VALUE,g=!1,h=!1,i,j,k;if(b<0||this.hide)return!1;for(k=0;k<b;k++)i=a[k][0],j=a[k][1],i<c&&(c=i,g=!0),i>e&&(e=i,g=!0),j<d&&(d=j,h=!0),j>f&&(f=j,h=!0);return{xmin:c,xmax:e,ymin:d,ymax:f,xused:g,yused:h}}},a.extend(b,{getSeries:function(c){return a.map(c,function(c){var d;return c.data?(d=new b,a.extend(d,c)):d=new b({data:c}),d})}}),Flotr.Series=b}(),Flotr.addType("lines",{options:{show:!1,lineWidth:2,fill:!1,fillBorder:!1,fillColor:null,fillOpacity:.4,steps:!1,stacked:!1},stack:{values:[]},draw:function(a){var b=a.context,c=a.lineWidth,d=a.shadowSize,e;b.save(),b.lineJoin="round",d&&(b.lineWidth=d/2,e=c/2+b.lineWidth/2,b.strokeStyle="rgba(0,0,0,0.1)",this.plot(a,e+d/2,!1),b.strokeStyle="rgba(0,0,0,0.2)",this.plot(a,e,!1)),b.lineWidth=c,b.strokeStyle=a.color,this.plot(a,0,!0),b.restore()},plot:function(a,b,c){var d=a.context,e=a.width,f=a.height,g=a.xScale,h=a.yScale,i=a.data,j=a.stacked?this.stack:!1,k=i.length-1,l=null,m=null,n=h(0),o,p,q,r,s,t,u;if(k<1)return;d.beginPath();for(u=0;u<k;++u){if(i[u][1]===null||i[u+1][1]===null)continue;o=g(i[u][0]),p=g(i[u+1][0]),j?(s=j.values[i[u][0]]||0,t=j.values[i[u+1][0]]||j.values[i[u][0]]||0,q=h(i[u][1]+s),r=h(i[u+1][1]+t),c&&(j.values[i[u][0]]=i[u][1]+s,u==k-1&&(j.values[i[u+1][0]]=i[u+1][1]+t))):(q=h(i[u][1]),r=h(i[u+1][1]));if(q>f&&r>f||q<0&&r<0||o<0&&p<0||o>e&&p>e)continue;(l!=o||m!=q+b)&&d.moveTo(o,q+b),l=p,m=r+b,a.steps?(d.lineTo(l+b/2,q+b),d.lineTo(l+b/2,m)):d.lineTo(l,m)}(!a.fill||a.fill&&!a.fillBorder)&&d.stroke(),!b&&a.fill&&(o=g(i[0][0]),d.fillStyle=a.fillStyle,d.lineTo(p,n),d.lineTo(o,n),d.lineTo(o,h(i[0][1])),d.fill(),a.fillBorder&&d.stroke()),d.closePath()},extendYRange:function(a,b,c,d){var e=a.options;if(c.stacked&&(!e.max&&e.max!==0||!e.min&&e.min!==0)){var f=a.max,g=a.min,h=d.positiveSums||{},i=d.negativeSums||{},j,k;for(k=0;k<b.length;k++)j=b[k][0]+"",b[k][1]>0?(h[j]=(h[j]||0)+b[k][1],f=Math.max(f,h[j])):(i[j]=(i[j]||0)+b[k][1],g=Math.min(g,i[j]));d.negativeSums=i,d.positiveSums=h,a.max=f,a.min=g}c.steps&&(this.hit=function(a){var b=a.data,c=a.args,d=a.yScale,e=c[0],f=b.length,g=c[1],h=e.x,i=e.relY,j;for(j=0;j<f-1;j++)if(h>=b[j][0]&&h<=b[j+1][0]){Math.abs(d(b[j][1])-i)<8&&(g.x=b[j][0],g.y=b[j][1],g.index=j,g.seriesIndex=a.index);break}},this.drawHit=function(a){var b=a.context,c=a.args,d=a.data,e=a.xScale,f=c.index,g=e(c.x),h=a.yScale(c.y),i;d.length-1>f&&(i=a.xScale(d[f+1][0]),b.save(),b.strokeStyle=a.color,b.lineWidth=a.lineWidth,b.beginPath(),b.moveTo(g,h),b.lineTo(i,h),b.stroke(),b.closePath(),b.restore())},this.clearHit=function(a){var b=a.context,c=a.args,d=a.data,e=a.xScale,f=a.lineWidth,g=c.index,h=e(c.x),i=a.yScale(c.y),j;d.length-1>g&&(j=a.xScale(d[g+1][0]),b.clearRect(h-f,i-f,j-h+2*f,2*f))})}}),Flotr.addType("bars",{options:{show:!1,lineWidth:2,barWidth:1,fill:!0,fillColor:null,fillOpacity:.4,horizontal:!1,stacked:!1,centered:!0,topPadding:.1},stack:{positive:[],negative:[],_positive:[],_negative:[]},draw:function(a){var b=a.context;b.save(),b.lineJoin="miter",b.lineWidth=a.lineWidth,b.strokeStyle=a.color,a.fill&&(b.fillStyle=a.fillStyle),this.plot(a),b.restore()},plot:function(a){var b=a.data,c=a.context,d=a.shadowSize,e,f,g,h,i,j;if(b.length<1)return;this.translate(c,a.horizontal);for(e=0;e<b.length;e++){f=this.getBarGeometry(b[e][0],b[e][1],a);if(f===null)continue;g=f.left,h=f.top,i=f.width,j=f.height,a.fill&&c.fillRect(g,h,i,j),d&&(c.save(),c.fillStyle="rgba(0,0,0,0.05)",c.fillRect(g+d,h+d,i,j),c.restore()),a.lineWidth&&c.strokeRect(g,h,i,j)}},translate:function(a,b){b&&(a.rotate(-Math.PI/2),a.scale(-1,1))},getBarGeometry:function(a,b,c){var d=c.horizontal,e=c.barWidth,f=c.centered,g=c.stacked?this.stack:!1,h=c.lineWidth,i=f?e/2:0,j=d?c.yScale:c.xScale,k=d?c.xScale:c.yScale,l=d?b:a,m=d?a:b,n=0,o,p,q,r,s;return g&&(o=m>0?g.positive:g.negative,n=o[l]||n,o[l]=n+m),p=j(l-i),q=j(l+e-i),r=k(m+n),s=k(n),s<0&&(s=0),a===null||b===null?null:{x:l,y:m,xScale:j,yScale:k,top:r,left:Math.min(p,q)-h/2,width:Math.abs(q-p)-h,height:s-r}},hit:function(a){var b=a.data,c=a.args,d=c[0],e=c[1],f=d.x,g=d.y,h=this.getBarGeometry(f,g,a),i=h.width/2,j=h.left,k,l;for(l=b.length;l--;)k=this.getBarGeometry(b[l][0],b[l][1],a),k.y>h.y&&Math.abs(j-k.left)<i&&(e.x=b[l][0],e.y=b[l][1],e.index=l,e.seriesIndex=a.index)},drawHit:function(a){var b=a.context,c=a.args,d=this.getBarGeometry(c.x,c.y,a),e=d.left,f=d.top,g=d.width,h=d.height;b.save(),b.strokeStyle=a.color,b.lineWidth=a.lineWidth,this.translate(b,a.horizontal),b.beginPath(),b.moveTo(e,f+h),b.lineTo(e,f),b.lineTo(e+g,f),b.lineTo(e+g,f+h),a.fill&&(b.fillStyle=a.fillStyle,b.fill()),b.stroke(),b.closePath(),b.restore()},clearHit:function(a){var b=a.context,c=a.args,d=this.getBarGeometry(c.x,c.y,a),e=d.left,f=d.width,g=d.top,h=d.height,i=2*a.lineWidth;b.save(),this.translate(b,a.horizontal),b.clearRect(e-i,Math.min(g,g+h)-i,f+2*i,Math.abs(h)+2*i),b.restore()},extendXRange:function(a,b,c,d){this._extendRange(a,b,c,d)},extendYRange:function(a,b,c,d){this._extendRange(a,b,c,d)},_extendRange:function(a,b,c,d){var e=a.options.max;if(_.isNumber(e)||_.isString(e))return;var f=a.min,g=a.max,h=c.horizontal,i=a.orientation,j=this.positiveSums||{},k=this.negativeSums||{},l,m,n,o;(i==1&&!h||i==-1&&h)&&c.centered&&(g=Math.max(a.datamax+c.barWidth,g),f=Math.min(a.datamin-c.barWidth,f));if(c.stacked&&(i==1&&h||i==-1&&!h))for(o=b.length;o--;)l=b[o][i==1?1:0]+"",m=b[o][i==1?0:1],m>0?(j[l]=(j[l]||0)+m,g=Math.max(g,j[l])):(k[l]=(k[l]||0)+m,f=Math.min(f,k[l]));(i==1&&h||i==-1&&!h)&&c.topPadding&&(a.max===a.datamax||c.stacked&&this.stackMax!==g)&&(g+=c.topPadding*(g-f)),this.stackMin=f,this.stackMax=g,this.negativeSums=k,this.positiveSums=j,a.max=g,a.min=f}}),Flotr.addType("bubbles",{options:{show:!1,lineWidth:2,fill:!0,fillOpacity:.4,baseRadius:2},draw:function(a){var b=a.context,c=a.shadowSize;b.save(),b.lineWidth=a.lineWidth,b.fillStyle="rgba(0,0,0,0.05)",b.strokeStyle="rgba(0,0,0,0.05)",this.plot(a,c/2),b.strokeStyle="rgba(0,0,0,0.1)",this.plot(a,c/4),b.strokeStyle=a.color,b.fillStyle=a.fillStyle,this.plot(a),b.restore()},plot:function(a,b){var c=a.data,d=a.context,e,f,g,h,i;b=b||0;for(f=0;f<c.length;++f)e=this.getGeometry(c[f],a),d.beginPath(),d.arc(e.x+b,e.y+b,e.z,0,2*Math.PI,!0),d.stroke(),a.fill&&d.fill(),d.closePath()},getGeometry:function(a,b){return{x:b.xScale(a[0]),y:b.yScale(a[1]),z:a[2]*b.baseRadius}},hit:function(a){var b=a.data,c=a.args,d=c[0],e=c[1],f=d.x,g=d.y,h,j,k;for(i=b.length;i--;)h=this.getGeometry(b[i],a),j=h.x-a.xScale(f),k=h.y-a.yScale(g),Math.sqrt(j*j+k*k)<h.z&&(e.x=b[i][0],e.y=b[i][1],e.index=i,e.seriesIndex=a.index)},drawHit:function(a){var b=a.context,c=this.getGeometry(a.data[a.args.index],a);b.save(),b.lineWidth=a.lineWidth,b.fillStyle=a.fillStyle,b.strokeStyle=a.color,b.beginPath(),b.arc(c.x,c.y,c.z,0,2*Math.PI,!0),b.fill(),b.stroke(),b.closePath(),b.restore()},clearHit:function(a){var b=a.context,c=this.getGeometry(a.data[a.args.index],a),d=c.z+a.lineWidth;b.save(),b.clearRect(c.x-d,c.y-d,2*d,2*d),b.restore()}}),Flotr.addType("candles",{options:{show:!1,lineWidth:1,wickLineWidth:1,candleWidth:.6,fill:!0,upFillColor:"#00A8F0",downFillColor:"#CB4B4B",fillOpacity:.5,barcharts:!1},draw:function(a){var b=a.context;b.save(),b.lineJoin="miter",b.lineCap="butt",b.lineWidth=a.wickLineWidth||a.lineWidth,this.plot(a),b.restore()},plot:function(a){var b=a.data,c=a.context,d=a.xScale,e=a.yScale,f=a.candleWidth/2,g=a.shadowSize,h=a.lineWidth,i=a.wickLineWidth,j=i%2/2,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y;if(b.length<1)return;for(y=0;y<b.length;y++){l=b[y],m=l[0],o=l[1],p=l[2],q=l[3],r=l[4],s=d(m-f),t=d(m+f),u=e(q),v=e(p),w=e(Math.min(o,r)),x=e(Math.max(o,r)),k=a[o>r?"downFillColor":"upFillColor"],a.fill&&!a.barcharts&&(c.fillStyle="rgba(0,0,0,0.05)",c.fillRect(s+g,x+g,t-s,w-x),c.save(),c.globalAlpha=a.fillOpacity,c.fillStyle=k,c.fillRect(s,x+h,t-s,w-x),c.restore());if(h||i)m=Math.floor((s+t)/2)+j,c.strokeStyle=k,c.beginPath(),a.barcharts?(c.moveTo(m,Math.floor(v+f)),c.lineTo(m,Math.floor(u+f)),n=Math.floor(o+f)+.5,c.moveTo(Math.floor(s)+j,n),c.lineTo(m,n),n=Math.floor(r+f)+.5,c.moveTo(Math.floor(t)+j,n),c.lineTo(m,n)):(c.strokeRect(s,x+h,t-s,w-x),c.moveTo(m,Math.floor(x+h)),c.lineTo(m,Math.floor(v+h)),c.moveTo(m,Math.floor(w+h)),c.lineTo(m,Math.floor(u+h))),c.closePath(),c.stroke()}},extendXRange:function(a,b,c){a.options.max===null&&(a.max=Math.max(a.datamax+.5,a.max),a.min=Math.min(a.datamin-.5,a.min))}}),Flotr.addType("gantt",{options:{show:!1,lineWidth:2,barWidth:1,fill:!0,fillColor:null,fillOpacity:.4,centered:!0},draw:function(a){var b=this.ctx,c=a.gantt.barWidth,d=Math.min(a.gantt.lineWidth,c);b.save(),b.translate(this.plotOffset.left,this.plotOffset.top),b.lineJoin="miter",b.lineWidth=d,b.strokeStyle=a.color,b.save(),this.gantt.plotShadows(a,c,0,a.gantt.fill),b.restore();if(a.gantt.fill){var e=a.gantt.fillColor||a.color;b.fillStyle=this.processColor(e,{opacity:a.gantt.fillOpacity})}this.gantt.plot(a,c,0,a.gantt.fill),b.restore()},plot:function(a,b,c,d){var e=a.data;if(e.length<1)return;var f=a.xaxis,g=a.yaxis,h=this.ctx,i;for(i=0;i<e.length;i++){var j=e[i][0],k=e[i][1],l=e[i][2],m=!0,n=!0,o=!0;if(k===null||l===null)continue;var p=k,q=k+l,r=j-(a.gantt.centered?b/2:0),s=j+b-(a.gantt.centered?b/2:0);if(q<f.min||p>f.max||s<g.min||r>g.max)continue;p<f.min&&(p=f.min,m=!1),q>f.max&&(q=f.max,f.lastSerie!=a&&(n=!1)),r<g.min&&(r=g.min),s>g.max&&(s=g.max,g.lastSerie!=a&&(n=!1)),d&&(h.beginPath(),h.moveTo(f.d2p(p),g.d2p(r)+c),h.lineTo(f.d2p(p),g.d2p(s)+c),h.lineTo(f.d2p(q),g.d2p(s)+c),h.lineTo(f.d2p(q),g.d2p(r)+c),h.fill(),h.closePath()),a.gantt.lineWidth&&(m||o||n)&&(h.beginPath(),h.moveTo(f.d2p(p),g.d2p(r)+c),h[m?"lineTo":"moveTo"](f.d2p(p),g.d2p(s)+c),h[n?"lineTo":"moveTo"](f.d2p(q),g.d2p(s)+c),h[o?"lineTo":"moveTo"](f.d2p(q),g.d2p(r)+c),h.stroke(),h.closePath())}},plotShadows:function(a,b,c){var d=a.data;if(d.length<1)return;var e,f,g,h,i=a.xaxis,j=a.yaxis,k=this.ctx,l=this.options.shadowSize;for(e=0;e<d.length;e++){f=d[e][0],g=d[e][1],h=d[e][2];if(g===null||h===null)continue;var m=g,n=g+h,o=f-(a.gantt.centered?b/2:0),p=f+b-(a.gantt.centered?b/2:0);if(n<i.min||m>i.max||p<j.min||o>j.max)continue;m<i.min&&(m=i.min),n>i.max&&(n=i.max),o<j.min&&(o=j.min),p>j.max&&(p=j.max);var q=i.d2p(n)-i.d2p(m)-(i.d2p(n)+l<=this.plotWidth?0:l),r=j.d2p(o)-j.d2p(p)-(j.d2p(o)+l<=this.plotHeight?0:l);k.fillStyle="rgba(0,0,0,0.05)",k.fillRect(Math.min(i.d2p(m)+l,this.plotWidth),Math.min(j.d2p(p)+l,this.plotHeight),q,r)}},extendXRange:function(a){if(a.options.max===null){var b=a.min,c=a.max,d,e,f,g,h,i={},j={},k=null;for(d=0;d<this.series.length;++d){g=this.series[d],h=g.gantt;if(h.show&&g.xaxis==a){for(e=0;e<g.data.length;e++)h.show&&(y=g.data[e][0]+"",i[y]=Math.max(i[y]||0,g.data[e][1]+g.data[e][2]),k=g);for(e in i)c=Math.max(i[e],c)}}a.lastSerie=k,a.max=c,a.min=b}},extendYRange:function(a){if(a.options.max===null){var b=Number.MIN_VALUE,c=Number.MAX_VALUE,d,e,f,g,h={},i={},j=null;for(d=0;d<this.series.length;++d){f=this.series[d],g=f.gantt;if(g.show&&!f.hide&&f.yaxis==a){var k=Number.MIN_VALUE,l=Number.MAX_VALUE;for(e=0;e<f.data.length;e++)k=Math.max(k,f.data[e][0]),l=Math.min(l,f.data[e][0]);g.centered?(b=Math.max(k+.5,b),c=Math.min(l-.5,c)):(b=Math.max(k+1,b),c=Math.min(l,c)),g.barWidth+k>b&&(b=a.max+g.barWidth)}}a.lastSerie=j,a.max=b,a.min=c,a.tickSize=Flotr.getTickSize(a.options.noTicks,c,b,a.options.tickDecimals)}}}),function(){function a(a){return typeof a=="object"&&a.constructor&&(Image?!0:a.constructor===Image)}Flotr.defaultMarkerFormatter=function(a){return Math.round(a.y*100)/100+""},Flotr.addType("markers",{options:{show:!1,lineWidth:1,color:"#000000",fill:!1,fillColor:"#FFFFFF",fillOpacity:.4,stroke:!1,position:"ct",verticalMargin:0,labelFormatter:Flotr.defaultMarkerFormatter,fontSize:Flotr.defaultOptions.fontSize,stacked:!1,stackingType:"b",horizontal:!1},stack:{positive:[],negative:[],values:[]},draw:function(a){function m(a,b){return g=d.negative[a]||0,f=d.positive[a]||0,b>0?(d.positive[a]=g+b,g+b):(d.negative[a]=f+b,f+b)}var b=a.data,c=a.context,d=a.stacked?a.stack:!1,e=a.stackingType,f,g,h,i,j,k,l;c.save(),c.lineJoin="round",c.lineWidth=a.lineWidth,c.strokeStyle="rgba(0,0,0,0.5)",c.fillStyle=a.fillStyle;for(i=0;i<b.length;++i)j=b[i][0],k=b[i][1],d&&(e=="b"?a.horizontal?k=m(k,j):j=m(j,k):e=="a"&&(h=d.values[j]||0,d.values[j]=h+k,k=h+k)),l=a.labelFormatter({x:j,y:k,index:i,data:b}),this.plot(a.xScale(j),a.yScale(k),l,a);c.restore()},plot:function(b,c,d,e){var f=e.context;if(a(d)&&!d.complete)throw"Marker image not loaded.";this._plot(b,c,d,e)},_plot:function(b,c,d,e){var f=e.context,g=2,h=b,i=c,j;a(d)?j={height:d.height,width:d.width}:j=e.text.canvas(d),j.width=Math.floor(j.width+g*2),j.height=Math.floor(j.height+g*2),e.position.indexOf("c")!=-1?h-=j.width/2+g:e.position.indexOf("l")!=-1&&(h-=j.width),e.position.indexOf("m")!=-1?i-=j.height/2+g:e.position.indexOf("t")!=-1?i-=j.height+e.verticalMargin:i+=e.verticalMargin,h=Math.floor(h)+.5,i=Math.floor(i)+.5,e.fill&&f.fillRect(h,i,j.width,j.height),e.stroke&&f.strokeRect(h,i,j.width,j.height),a(d)?f.drawImage(d,h+g,i+g):Flotr.drawText(f,d,h+g,i+g,{textBaseline:"top",textAlign:"left",size:e.fontSize,color:e.color})}})}(),function(){var a=Flotr._;Flotr.defaultPieLabelFormatter=function(a,b){return(100*b/a).toFixed(2)+"%"},Flotr.addType("pie",{options:{show:!1,lineWidth:1,fill:!0,fillColor:null,fillOpacity:.6,explode:6,sizeRatio:.6,startAngle:Math.PI/4,labelFormatter:Flotr.defaultPieLabelFormatter,pie3D:!1,pie3DviewAngle:Math.PI/2*.8,pie3DspliceThickness:20},draw:function(a){var b=a.data,c=a.context,d=c.canvas,e=a.lineWidth,f=a.shadowSize,g=a.sizeRatio,h=a.height,i=a.width,j=a.explode,k=a.color,l=a.fill,m=a.fillStyle,n=Math.min(d.width,d.height)*g/2,o=b[0][1],p=[],q=1,r=Math.PI*2*o/this.total,s=this.startAngle||2*Math.PI*a.startAngle,t=s+r,u=s+r/2,v=a.labelFormatter(this.total,o),w=j+n+4,x=Math.cos(u)*w,y=Math.sin(u)*w,z=x<0?"right":"left",A=y>0?"top":"bottom",B,C,D,x,y;c.save(),c.translate(i/2,h/2),c.scale(1,q),C=Math.cos(u)*j,D=Math.sin(u)*j,f>0&&(this.plotSlice(C+f,D+f,n,s,t,c),l&&(c.fillStyle="rgba(0,0,0,0.1)",c.fill())),this.plotSlice(C,D,n,s,t,c),l&&(c.fillStyle=m,c.fill()),c.lineWidth=e,c.strokeStyle=k,c.stroke(),B={size:a.fontSize*1.2,color:a.fontColor,weight:1.5},v&&(a.htmlText||!a.textEnabled?(divStyle="position:absolute;"+A+":"+(h/2+(A==="top"?y:-y))+"px;",divStyle+=z+":"+(i/2+(z==="right"?-x:x))+"px;",p.push('<div style="',divStyle,'" class="flotr-grid-label">',v,"</div>")):(B.textAlign=z,B.textBaseline=A,Flotr.drawText(c,v,x,y,B)));if(a.htmlText||!a.textEnabled){var E=Flotr.DOM.node('<div style="color:'+a.fontColor+'" class="flotr-labels"></div>');Flotr.DOM.insert(E,p.join("")),Flotr.DOM.insert(a.element,E)}c.restore(),this.startAngle=t,this.slices=this.slices||[],this.slices.push({radius:Math.min(d.width,d.height)*g/2,x:C,y:D,explode:j,start:s,end:t})},plotSlice:function(a,b,c,d,e,f){f.beginPath(),f.moveTo(a,b),f.arc(a,b,c,d,e,!1),f.lineTo(a,b),f.closePath()},hit:function(a){var b=a.data[0],c=a.args,d=a.index,e=c[0],f=c[1],g=this.slices[d],h=e.relX-a.width/2,i=e.relY-a.height/2,j=Math.sqrt(h*h+i*i),k=Math.atan(i/h),l=Math.PI*2,m=g.explode||a.explode,n=g.start%l,o=g.end%l;h<0?k+=Math.PI:h>0&&i<0&&(k+=l),j<g.radius+m&&j>m&&(n>o&&(k<o||k>n)||k>n&&k<o)&&(f.x=b[0],f.y=b[1],f.sAngle=n,f.eAngle=o,f.index=0,f.seriesIndex=d,f.fraction=b[1]/this.total)},drawHit:function(a){var b=a.context,c=this.slices[a.args.seriesIndex];b.save(),b.translate(a.width/2,a.height/2),this.plotSlice(c.x,c.y,c.radius,c.start,c.end,b),b.stroke(),b.restore()},clearHit:function(a){var b=a.context,c=this.slices[a.args.seriesIndex],d=2*a.lineWidth,e=c.radius+d;b.save(),b.translate(a.width/2,a.height/2),b.clearRect(c.x-e,c.y-e,2*e+d,2*e+d),b.restore()},extendYRange:function(a,b){this.total=(this.total||0)+b[0][1]}})}(),Flotr.addType("points",{options:{show:!1,radius:3,lineWidth:2,fill:!0,fillColor:"#FFFFFF",fillOpacity:.4},draw:function(a){var b=a.context,c=a.lineWidth,d=a.shadowSize;b.save(),d>0&&(b.lineWidth=d/2,b.strokeStyle="rgba(0,0,0,0.1)",this.plot(a,d/2+b.lineWidth/2),b.strokeStyle="rgba(0,0,0,0.2)",this.plot(a,b.lineWidth/2)),b.lineWidth=a.lineWidth,b.strokeStyle=a.color,b.fillStyle=a.fillColor||a.color,this.plot(a),b.restore()},plot:function(a,b){var c=a.data,d=a.context,e=a.xScale,f=a.yScale,g,h,i;for(g=c.length-1;g>-1;--g){i=c[g][1];if(i===null)continue;h=e(c[g][0]),i=f(i);if(h<0||h>a.width||i<0||i>a.height)continue;d.beginPath(),b?d.arc(h,i+b,a.radius,0,Math.PI,!1):(d.arc(h,i,a.radius,0,2*Math.PI,!0),a.fill&&d.fill()),d.stroke(),d.closePath()}}}),Flotr.addType("radar",{options:{show:!1,lineWidth:2,fill:!0,fillOpacity:.4,radiusRatio:.9},draw:function(a){var b=a.context,c=a.shadowSize;b.save(),b.translate(a.width/2,a.height/2),b.lineWidth=a.lineWidth,b.fillStyle="rgba(0,0,0,0.05)",b.strokeStyle="rgba(0,0,0,0.05)",this.plot(a,c/2),b.strokeStyle="rgba(0,0,0,0.1)",this.plot(a,c/4),b.strokeStyle=a.color,b.fillStyle=a.fillStyle,this.plot(a),b.restore()},plot:function(a,b){var c=a.data,d=a.context,e=Math.min(a.height,a.width)*a.radiusRatio/2,f=2*Math.PI/c.length,g=-Math.PI/2,h,i;b=b||0,d.beginPath();for(h=0;h<c.length;++h)i=c[h][1]/this.max,d[h===0?"moveTo":"lineTo"](Math.cos(h*f+g)*e*i+b,Math.sin(h*f+g)*e*i+b);d.closePath(),a.fill&&d.fill(),d.stroke()},extendYRange:function(a,b){this.max=Math.max(a.max,this.max||-Number.MAX_VALUE)}}),Flotr.addType("timeline",{options:{show:!1,lineWidth:1,barWidth:.2,fill:!0,fillColor:null,fillOpacity:.4,centered:!0},draw:function(a){var b=a.context;b.save(),b.lineJoin="miter",b.lineWidth=a.lineWidth,b.strokeStyle=a.color,b.fillStyle=a.fillStyle,this.plot(a),b.restore()},plot:function(a){var b=a.data,c=a.context,d=a.xScale,e=a.yScale,f=a.barWidth,g=a.lineWidth,h;Flotr._.each(b,function(a){var b=a[0],h=a[1],i=a[2],j=f,k=Math.ceil(d(b)),l=Math.ceil(d(b+i))-k,m=Math.round(e(h)),n=Math.round(e(h-j))-m,o=k-g/2,p=Math.round(m-n/2)-g/2;c.strokeRect(o,p,l,n),c.fillRect(o,p,l,n)})},extendRange:function(a){var b=a.data,c=a.xaxis,d=a.yaxis,e=a.timeline.barWidth;c.options.min===null&&(c.min=c.datamin-e/2);if(c.options.max===null){var f=c.max;Flotr._.each(b,function(a){f=Math.max(f,a[0]+a[2])},this),c.max=f+e/2}d.options.min===null&&(d.min=d.datamin-e),d.options.min===null&&(d.max=d.datamax+e)}}),function(){var a=Flotr.DOM;Flotr.addPlugin("crosshair",{options:{mode:null,color:"#FF0000",hideCursor:!0},callbacks:{"flotr:mousemove":function(a,b){this.options.crosshair.mode&&(this.crosshair.clearCrosshair(),this.crosshair.drawCrosshair(b))}},drawCrosshair:function(b){var c=this.octx,d=this.options.crosshair,e=this.plotOffset,f=e.left+b.relX+.5,g=e.top+b.relY+.5;if(b.relX<0||b.relY<0||b.relX>this.plotWidth||b.relY>this.plotHeight){this.el.style.cursor=null,a.removeClass(this.el,"flotr-crosshair");return}d.hideCursor&&(this.el.style.cursor="none",a.addClass(this.el,"flotr-crosshair")),c.save(),c.strokeStyle=d.color,c.lineWidth=1,c.beginPath(),d.mode.indexOf("x")!=-1&&(c.moveTo(f,e.top),c.lineTo(f,e.top+this.plotHeight)),d.mode.indexOf("y")!=-1&&(c.moveTo(e.left,g),c.lineTo(e.left+this.plotWidth,g)),c.stroke(),c.restore()},clearCrosshair:function(){var a=this.plotOffset,b=this.lastMousePos,c=this.octx;b&&(c.clearRect(b.relX+a.left,a.top,1,this.plotHeight+1),c.clearRect(a.left,b.relY+a.top,this.plotWidth+1,1))}})}(),function(){function c(a,b,c,d){var e="image/"+a,f=b.toDataURL(e),g=new Image;return g.src=f,g}var a=Flotr.DOM,b=Flotr._;Flotr.addPlugin("download",{saveImage:function(d,e,f,g){var h=null;if(Flotr.isIE&&Flotr.isIE<9)return h="<html><body>"+this.canvas.firstChild.innerHTML+"</body></html>",window.open().document.write(h);if(d!=="jpeg"&&d!=="png")return;h=c(d,this.canvas,e,f);if(b.isElement(h)&&g)this.download.restoreCanvas(),a.hide(this.canvas),a.hide(this.overlay),a.setStyles({position:"absolute"}),a.insert(this.el,h),this.saveImageElement=h;else return window.open(h.src)},restoreCanvas:function(){a.show(this.canvas),a.show(this.overlay),this.saveImageElement&&this.el.removeChild(this.saveImageElement),this.saveImageElement=null}})}(),function(){var a=Flotr.EventAdapter,b=Flotr._;Flotr.addPlugin("graphGrid",{callbacks:{"flotr:beforedraw":function(){this.graphGrid.drawGrid()},"flotr:afterdraw":function(){this.graphGrid.drawOutline()}},drawGrid:function(){function p(a){for(n=0;n<a.length;++n){var b=a[n].v/l.max;for(o=0;o<=u;++o)c[o===0?"moveTo":"lineTo"](Math.cos(o*v+w)*t*b,Math.sin(o*v+w)*t*b)}}function q(a,d){b.each(b.pluck(a,"v"),function(a){if(a<=l.min||a>=l.max||(a==l.min||a==l.max)&&e.outlineWidth)return;d(Math.floor(l.d2p(a))+c.lineWidth/2)})}function r(a){c.moveTo(a,0),c.lineTo(a,j)}function s(a){c.moveTo(0,a),c.lineTo(k,a)}var c=this.ctx,d=this.options,e=d.grid,f=e.verticalLines,g=e.horizontalLines,h=e.minorVerticalLines,i=e.minorHorizontalLines,j=this.plotHeight,k=this.plotWidth,l,m,n,o;(f||h||g||i)&&a.fire(this.el,"flotr:beforegrid",[this.axes.x,this.axes.y,d,this]),c.save(),c.lineWidth=1,c.strokeStyle=e.tickColor;if(e.circular){c.translate(this.plotOffset.left+k/2,this.plotOffset.top+j/2);var t=Math.min(j,k)*d.radar.radiusRatio/2,u=this.axes.x.ticks.length,v=2*(Math.PI/u),w=-Math.PI/2;c.beginPath(),l=this.axes.y,g&&p(l.ticks),i&&p(l.minorTicks),f&&b.times(u,function(a){c.moveTo(0,0),c.lineTo(Math.cos(a*v+w)*t,Math.sin(a*v+w)*t)}),c.stroke()}else c.translate(this.plotOffset.left,this.plotOffset.top),e.backgroundColor&&(c.fillStyle=this.processColor(e.backgroundColor,{x1:0,y1:0,x2:k,y2:j}),c.fillRect(0,0,k,j)),c.beginPath(),l=this.axes.x,f&&q(l.ticks,r),h&&q(l.minorTicks,r),l=this.axes.y,g&&q(l.ticks,s),i&&q(l.minorTicks,s),c.stroke();c.restore(),(f||h||g||i)&&a.fire(this.el,"flotr:aftergrid",[this.axes.x,this.axes.y,d,this])},drawOutline:function(){var a=this,b=a.options,c=b.grid,d=c.outline,e=a.ctx,f=c.backgroundImage,g=a.plotOffset,h=g.left,j=g.top,k=a.plotWidth,l=a.plotHeight,m,n,o,p,q,r;if(!c.outlineWidth)return;e.save();if(c.circular){e.translate(h+k/2,j+l/2);var s=Math.min(l,k)*b.radar.radiusRatio/2,t=this.axes.x.ticks.length,u=2*(Math.PI/t),v=-Math.PI/2;e.beginPath(),e.lineWidth=c.outlineWidth,e.strokeStyle=c.color,e.lineJoin="round";for(i=0;i<=t;++i)e[i===0?"moveTo":"lineTo"](Math.cos(i*u+v)*s,Math.sin(i*u+v)*s);e.stroke()}else{e.translate(h,j);var w=c.outlineWidth,x=.5-w+(w+1)%2/2,y="lineTo",z="moveTo";e.lineWidth=w,e.strokeStyle=c.color,e.lineJoin="miter",e.beginPath(),e.moveTo(x,x),k-=w/2%1,l+=w/2,e[d.indexOf("n")!==-1?y:z](k,x),e[d.indexOf("e")!==-1?y:z](k,l),e[d.indexOf("s")!==-1?y:z](x,l),e[d.indexOf("w")!==-1?y:z](x,x),e.stroke(),e.closePath()}e.restore(),f&&(o=f.src||f,p=(parseInt(f.left,10)||0)+g.left,q=(parseInt(f.top,10)||0)+g.top,n=new Image,n.onload=function(){e.save(),f.alpha&&(e.globalAlpha=f.alpha),e.globalCompositeOperation="destination-over",e.drawImage(n,0,0,n.width,n.height,p,q,k,l),e.restore()},n.src=o)}})}(),function(){var a=Flotr.DOM,b=Flotr._,c=Flotr,d="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;";Flotr.addPlugin("hit",{callbacks:{"flotr:mousemove":function(a,b){this.hit.track(b)},"flotr:click":function(a){this.hit.track(a)},"flotr:mouseout":function(){this.hit.clearHit()}},track:function(a){(this.options.mouse.track||b.any(this.series,function(a){return a.mouse&&a.mouse.track}))&&this.hit.hit(a)},executeOnType:function(a,d,e){function h(a,h){b.each(b.keys(c.graphTypes),function(b){a[b]&&a[b].show&&this[b][d]&&(g=this.getOptions(a,b),g.fill=!!a.mouse.fillColor,g.fillStyle=this.processColor(a.mouse.fillColor||"#ffffff",{opacity:a.mouse.fillOpacity}),g.color=a.mouse.lineColor,g.context=this.octx,g.index=h,e&&(g.args=e),this[b][d].call(this[b],g),f=!0)},this)}var f=!1,g;return b.isArray(a)||(a=[a]),b.each(a,h,this),f},drawHit:function(a){var b=this.octx,c=a.series;if(c.mouse.lineColor){b.save(),b.lineWidth=c.points?c.points.lineWidth:1,b.strokeStyle=c.mouse.lineColor,b.fillStyle=this.processColor(c.mouse.fillColor||"#ffffff",{opacity:c.mouse.fillOpacity}),b.translate(this.plotOffset.left,this.plotOffset.top);if(!this.hit.executeOnType(c,"drawHit",a)){var d=a.xaxis,e=a.yaxis;b.beginPath(),b.arc(d.d2p(a.x),e.d2p(a.y),c.points.radius||c.mouse.radius,0,2*Math.PI,!0),b.fill(),b.stroke(),b.closePath()}b.restore()}this.prevHit=a},clearHit:function(){var b=this.prevHit,c=this.octx,d=this.plotOffset;c.save(),c.translate(d.left,d.top);if(b){if(!this.hit.executeOnType(b.series,"clearHit",this.prevHit)){var e=b.series,f=e.points?e.points.lineWidth:1;offset=(e.points.radius||e.mouse.radius)+f,c.clearRect(b.xaxis.d2p(b.x)-offset,b.yaxis.d2p(b.y)-offset,offset*2,offset*2)}a.hide(this.mouseTrack),this.prevHit=null}c.restore()},hit:function(a){var c=this.options,d=this.prevHit,e,f,g,h,i,j,k,l;if(this.series.length===0)return;n={relX:a.relX,relY:a.relY,absX:a.absX,absY:a.absY};if(c.mouse.trackY&&!c.mouse.trackAll&&this.hit.executeOnType(this.series,"hit",[a,n]))b.isUndefined(n.seriesIndex)||(i=this.series[n.seriesIndex],n.series=i,n.mouse=i.mouse,n.xaxis=i.xaxis,n.yaxis=i.yaxis);else{e=this.hit.closest(a);if(e){e=c.mouse.trackY?e.point:e.x,h=e.seriesIndex,i=this.series[h],k=i.xaxis,l=i.yaxis,f=2*i.mouse.sensibility;if(c.mouse.trackAll||e.distanceX<f/k.scale&&(!c.mouse.trackY||e.distanceY<f/l.scale))n.series=i,n.xaxis=i.xaxis,n.yaxis=i.yaxis,n.mouse=i.mouse,n.x=e.x,n.y=e.y,n.dist=e.distance,n.index=e.dataIndex,n.seriesIndex=h}}if(!d||d.index!==n.index||d.seriesIndex!==n.seriesIndex)this.hit.clearHit(),n.series&&n.mouse&&n.mouse.track&&(this.hit.drawMouseTrack(n),this.hit.drawHit(n),Flotr.EventAdapter.fire(this.el,"flotr:hit",[n,this]))},closest:function(a){function t(a){a.distance=m,a.distanceX=n,a.distanceY=o,a.seriesIndex=r,a.dataIndex=s,a.x=p,a.y=q}var b=this.series,c=this.options,d=a.x,e=a.y,f=Number.MAX_VALUE,g=Number.MAX_VALUE,h={},i={},j=!1,k,l,m,n,o,p,q,r,s;for(r=0;r<b.length;r++){k=b[r],l=k.data,l.length&&(j=!0);for(s=l.length;s--;){p=l[s][0],q=l[s][1];if(p===null||q===null)continue;if(p<k.xaxis.min||p>k.xaxis.max)continue;n=Math.abs(p-d),o=Math.abs(q-e),m=n*n+o*o,m<f&&(f=m,t(h)),n<g&&(g=n,t(i))}}return j?{point:h,x:i}:!1},drawMouseTrack:function(b){var c="",e=b.series,f=b.mouse.position,g=b.mouse.margin,h=d,i=this.mouseTrack,j=this.plotOffset,k=j.left,l=j.right,m=j.bottom,n=j.top,o=b.mouse.trackDecimals,p=this.options;i||(i=a.node('<div class="flotr-mouse-value"></div>'),this.mouseTrack=i,a.insert(this.el,i));if(!b.mouse.relative)f.charAt(0)=="n"?c+="top:"+(g+n)+"px;bottom:auto;":f.charAt(0)=="s"&&(c+="bottom:"+(g+m)+"px;top:auto;"),f.charAt(1)=="e"?c+="right:"+(g+l)+"px;left:auto;":f.charAt(1)=="w"&&(c+="left:"+(g+k)+"px;right:auto;");else if(e.bars.show)c+="bottom:"+(g-n-b.yaxis.d2p(b.y/2)+this.canvasHeight)+"px;top:auto;",c+="left:"+(g+k+b.xaxis.d2p(b.x-p.bars.barWidth/2))+"px;right:auto;";else if(e.pie.show){var q={x:this.plotWidth/2,y:this.plotHeight/2},r=Math.min(this.canvasWidth,this.canvasHeight)*e.pie.sizeRatio/2,s=b.sAngle<b.eAngle?(b.sAngle+b.eAngle)/2:(b.sAngle+b.eAngle+2*Math.PI)/2;c+="bottom:"+(g-n-q.y-Math.sin(s)*r/2+this.canvasHeight)+"px;top:auto;",c+="left:"+(g+k+q.x+Math.cos(s)*r/2)+"px;right:auto;"}else f.charAt(0)=="n"?c+="bottom:"+(g-n-b.yaxis.d2p(b.y)+this.canvasHeight)+"px;top:auto;":f.charAt(0)=="s"&&(c+="top:"+(g+n+b.yaxis.d2p(b.y))+"px;bottom:auto;"),f.charAt(1)=="e"?c+="left:"+(g+k+b.xaxis.d2p(b.x))+"px;right:auto;":f.charAt(1)=="w"&&(c+="right:"+(g-k-b.xaxis.d2p(b.x)+this.canvasWidth)+"px;left:auto;");h+=c,i.style.cssText=h;if(!o||o<0)o=0;i.innerHTML=b.mouse.trackFormatter({x:b.x.toFixed(o),y:b.y.toFixed(o),series:b.series,index:b.index,nearest:b,fraction:b.fraction}),a.show(i)}})}(),function(){function a(a,b){return a.which?a.which===1:a.button===0||a.button===1}function b(a,b){return Math.min(Math.max(0,a),b.plotWidth-1)}function c(a,b){return Math.min(Math.max(0,a),b.plotHeight)}var d=Flotr.DOM,e=Flotr.EventAdapter,f=Flotr._;Flotr.addPlugin("selection",{options:{pinchOnly:null,mode:null,color:"#B6D9FF",fps:20},callbacks:{"flotr:mouseup":function(a){var b=this.options.selection,c=this.selection,d=this.getEventPosition(a);if(!b||!b.mode)return;c.interval&&clearInterval(c.interval),this.multitouches?c.updateSelection():b.pinchOnly||c.setSelectionPos(c.selection.second,d),c.clearSelection(),c.selecting&&c.selectionIsSane()&&(c.drawSelection(),c.fireSelectEvent(),this.ignoreClick=!0)},"flotr:mousedown":function(b){var c=this.options.selection,d=this.selection,e=this.getEventPosition(b);if(!c||!c.mode)return;if(!c.mode||!a(b)&&f.isUndefined(b.touches))return;c.pinchOnly||d.setSelectionPos(d.selection.first,e),d.interval&&clearInterval(d.interval),this.lastMousePos.pageX=null,d.selecting=!1,d.interval=setInterval(f.bind(d.updateSelection,this),1e3/c.fps)},"flotr:destroy":function(a){clearInterval(this.selection.interval)}},getArea:function(){var a=this.selection.selection,b=a.first,c=a.second;return{x1:Math.min(b.x,c.x),x2:Math.max(b.x,c.x),y1:Math.min(b.y,c.y),y2:Math.max(b.y,c.y)}},selection:{first:{x:-1,y:-1},second:{x:-1,y:-1}},prevSelection:null,interval:null,fireSelectEvent:function(a){var b=this.axes,c=this.selection.selection,d,f,g,h;a=a||"select",d=b.x.p2d(c.first.x),f=b.x.p2d(c.second.x),g=b.y.p2d(c.first.y),h=b.y.p2d(c.second.y),e.fire(this.el,"flotr:"+a,[{x1:Math.min(d,f),y1:Math.min(g,h),x2:Math.max(d,f),y2:Math.max(g,h),xfirst:d,xsecond:f,yfirst:g,ysecond:h},this])},setSelection:function(a,d){var e=this.options,f=this.axes.x,g=this.axes.y,h=g.scale,i=f.scale,j=e.selection.mode.indexOf("x")!=-1,k=e.selection.mode.indexOf("y")!=-1,l=this.selection.selection;this.selection.clearSelection(),l.first.y=c(j&&!k?0:(g.max-a.y1)*h,this),l.second.y=c(j&&!k?this.plotHeight-1:(g.max-a.y2)*h,this),l.first.x=b(k&&!j?0:a.x1,this),l.second.x=b(k&&!j?this.plotWidth:a.x2,this),this.selection.drawSelection(),d||this.selection.fireSelectEvent()},setSelectionPos:function(a,d){var e=this.options.selection.mode,f=this.selection.selection;e.indexOf("x")==-1?a.x=a==f.first?0:this.plotWidth:a.x=b(d.relX,this),e.indexOf("y")==-1?a.y=a==f.first?0:this.plotHeight-1:a.y=c(d.relY,this)},drawSelection:function(){this.selection.fireSelectEvent("selecting");var a=this.selection.selection,b=this.octx,c=this.options,d=this.plotOffset,e=this.selection.prevSelection;if(e&&a.first.x==e.first.x&&a.first.y==e.first.y&&a.second.x==e.second.x&&a.second.y==e.second.y)return;b.save(),b.strokeStyle=this.processColor(c.selection.color,{opacity:.8}),b.lineWidth=1,b.lineJoin="miter",b.fillStyle=this.processColor(c.selection.color,{opacity:.4}),this.selection.prevSelection={first:{x:a.first.x,y:a.first.y},second:{x:a.second.x,y:a.second.y}};var f=Math.min(a.first.x,a.second.x),g=Math.min(a.first.y,a.second.y),h=Math.abs(a.second.x-a.first.x),i=Math.abs(a.second.y-a.first.y);b.fillRect(f+d.left+.5,g+d.top+.5,h,i),b.strokeRect(f+d.left+.5,g+d.top+.5,h,i),b.restore()},updateSelection:function(){if(!this.lastMousePos.pageX)return;this.selection.selecting=!0;if(this.multitouches)this.selection.setSelectionPos(this.selection.selection.first,this.getEventPosition(this.multitouches[0])),this.selection.setSelectionPos(this.selection.selection.second,this.getEventPosition(this.multitouches[1]));else{if(this.options.selection.pinchOnly)return;this.selection.setSelectionPos(this.selection.selection.second,this.lastMousePos)}this.selection.clearSelection(),this.selection.selectionIsSane()&&this.selection.drawSelection()},clearSelection:function(){if(!this.selection.prevSelection)return;var a=this.selection.prevSelection,b=1,c=this.plotOffset,d=Math.min(a.first.x,a.second.x),e=Math.min(a.first.y,a.second.y),f=Math.abs(a.second.x-a.first.x),g=Math.abs(a.second.y-a.first.y);this.octx.clearRect(d+c.left-b+.5,e+c.top-b,f+2*b+.5,g+2*b+.5),this.selection.prevSelection=null},selectionIsSane:function(){var a=this.selection.selection;return Math.abs(a.second.x-a.first.x)>=5||Math.abs(a.second.y-a.first.y)>=5}})}(),function(){var a=Flotr.DOM;Flotr.addPlugin("labels",{callbacks:{"flotr:afterdraw":function(){this.labels.draw()}},draw:function(){function s(a,b,d){var e=d?b.minorTicks:b.ticks,f=b.orientation===1,h=b.n===1,k,m;k={color:b.options.color||o.grid.color,angle:Flotr.toRad(b.options.labelsAngle),textBaseline:"middle"};for(l=0;l<e.length&&(d?b.options.showMinorLabels:b.options.showLabels);++l){c=e[l],c.label+="";if(!c.label||!c.label.length)continue;x=Math.cos(l*i+j)*g,y=Math.sin(l*i+j)*g,k.textAlign=f?Math.abs(x)<.1?"center":x<0?"right":"left":"left",Flotr.drawText(p,c.label,f?x:3,f?y:-(b.ticks[l].v/b.max)*(g-o.fontSize),k)}}function t(a,b,d,e){function j(a){return a.options.showLabels&&a.used}function k(a,b,c,d){return a.plotOffset.left+(b?d:c?-o.grid.labelMargin:o.grid.labelMargin+a.plotWidth)}function m(a,b,c,d){return a.plotOffset.top+(b?o.grid.labelMargin:d)+(b&&c?a.plotHeight:0)}var f=b.orientation===1,g=b.n===1,h,i;h={color:b.options.color||o.grid.color,textAlign:d,textBaseline:e,angle:Flotr.toRad(b.options.labelsAngle)},h=Flotr.getBestTextAlign(h.angle,h);for(l=0;l<b.ticks.length&&j(b);++l){c=b.ticks[l];if(!c.label||!c.label.length)continue;i=b.d2p(c.v);if(i<0||i>(f?a.plotWidth:a.plotHeight))continue;Flotr.drawText(p,c.label,k(a,f,g,i),m(a,f,g,i),h),!f&&!g&&(p.save(),p.strokeStyle=h.color,p.beginPath(),p.moveTo(a.plotOffset.left+a.plotWidth-8,a.plotOffset.top+b.d2p(c.v)),p.lineTo(a.plotOffset.left+a.plotWidth,a.plotOffset.top+b.d2p(c.v)),p.stroke(),p.restore())}}function u(a,b){var d=b.orientation===1,e=b.n===1,g="",h,i,j,k=a.plotOffset;!d&&!e&&(p.save(),p.strokeStyle=b.options.color||o.grid.color,p.beginPath());if(b.options.showLabels&&(e?!0:b.used))for(l=0;l<b.ticks.length;++l){c=b.ticks[l];if(!c.label||!c.label.length||(d?k.left:k.top)+b.d2p(c.v)<0||(d?k.left:k.top)+b.d2p(c.v)>(d?a.canvasWidth:a.canvasHeight))continue;j=k.top+(d?(e?1:-1)*(a.plotHeight+o.grid.labelMargin):b.d2p(c.v)-b.maxLabel.height/2),h=d?k.left+b.d2p(c.v)-f/2:0,g="",l===0?g=" first":l===b.ticks.length-1&&(g=" last"),g+=d?" flotr-grid-label-x":" flotr-grid-label-y",m+=['<div style="position:absolute; text-align:'+(d?"center":"right")+"; ","top:"+j+"px; ",(!d&&!e?"right:":"left:")+h+"px; ","width:"+(d?f:(e?k.left:k.right)-o.grid.labelMargin)+"px; ",b.options.color?"color:"+b.options.color+"; ":" ",'" class="flotr-grid-label'+g+'">'+c.label+"</div>"].join(" "),!d&&!e&&(p.moveTo(k.left+a.plotWidth-8,k.top+b.d2p(c.v)),p.lineTo(k.left+a.plotWidth,k.top+b.d2p(c.v)))}}var b,c,d,e,f,g,h,i,j,k,l,m="",n=0,o=this.options,p=this.ctx,q=this.axes,r={size:o.fontSize};for(l=0;l<q.x.ticks.length;++l)q.x.ticks[l].label&&++n;f=this.plotWidth/n,o.grid.circular&&(p.save(),p.translate(this.plotOffset.left+this.plotWidth/2,this.plotOffset.top+this.plotHeight/2),g=this.plotHeight*o.radar.radiusRatio/2+o.fontSize,h=this.axes.x.ticks.length,i=2*(Math.PI/h),j=-Math.PI/2,s(this,q.x,!1),s(this,q.x,!0),s(this,q.y,!1),s(this,q.y,!0),p.restore()),!o.HtmlText&&this.textEnabled?(t(this,q.x,"center","top"),t(this,q.x2,"center","bottom"),t(this,q.y,"right","middle"),t(this,q.y2,"left","middle")):(q.x.options.showLabels||q.x2.options.showLabels||q.y.options.showLabels||q.y2.options.showLabels)&&!o.grid.circular&&(m="",u(this,q.x),u(this,q.x2),u(this,q.y),u(this,q.y2),p.stroke(),p.restore(),k=a.create("div"),a.setStyles(k,{fontSize:"smaller",color:o.grid.color}),k.className="flotr-labels",a.insert(this.el,k),a.insert(k,m))}})}(),function(){var a=Flotr.DOM,b=Flotr._;Flotr.addPlugin("legend",{options:{show:!0,noColumns:1,labelFormatter:function(a){return a},labelBoxBorderColor:"#CCCCCC",labelBoxWidth:14,labelBoxHeight:10,labelBoxMargin:5,labelBoxOpacity:.4,container:null,position:"nw",margin:5,backgroundColor:null,backgroundOpacity:.85},callbacks:{"flotr:afterinit":function(){this.legend.insertLegend()}},insertLegend:function(){if(!this.options.legend.show)return;var c=this.series,d=this.plotOffset,e=this.options,f=e.legend,g=[],h=!1,i=this.ctx,j=b.filter(c,function(a){return a.label&&!a.hide}).length,k=f.position,l=f.margin,m,n,o;if(j)if(!e.HtmlText&&this.textEnabled&&!f.container){var p={size:e.fontSize*1.1,color:e.grid.color},q=f.labelBoxWidth,r=f.labelBoxHeight,s=f.labelBoxMargin,t=d.left+l,u=d.top+l,v=0;for(m=c.length-1;m>-1;--m){if(!c[m].label||c[m].hide)continue;n=f.labelFormatter(c[m].label),v=Math.max(v,this._text.measureText(n,p).width)}var w=Math.round(q+s*3+v),x=Math.round(j*(s+r)+s);k.charAt(0)=="s"&&(u=d.top+this.plotHeight-(l+x)),k.charAt(1)=="e"&&(t=d.left+this.plotWidth-(l+w)),o=this.processColor(f.backgroundColor||"rgb(240,240,240)",{opacity:f.backgroundOpacity||.1}),i.fillStyle=o,i.fillRect(t,u,w,x),i.strokeStyle=f.labelBoxBorderColor,i.strokeRect(Flotr.toPixel(t),Flotr.toPixel(u),w,x);var y=t+s,z=u+s;for(m=0;m<c.length;m++){if(!c[m].label||c[m].hide)continue;n=f.labelFormatter(c[m].label),i.fillStyle=c[m].color,i.fillRect(y,z,q-1,r-1),i.strokeStyle=f.labelBoxBorderColor,i.lineWidth=1,i.strokeRect(Math.ceil(y)-1.5,Math.ceil(z)-1.5,q+2,r+2),Flotr.drawText(i,n,y+q+s,z+r,p),z+=r+s}}else{for(m=0;m<c.length;++m){if(!c[m].label||c[m].hide)continue;m%f.noColumns===0&&(g.push(h?"</tr><tr>":"<tr>"),h=!0);var A=c[m],B=f.labelBoxWidth,C=f.labelBoxHeight,E=A.bars?A.bars.fillOpacity:f.labelBoxOpacity,F="opacity:"+E+";filter:alpha(opacity="+E*100+");";n=f.labelFormatter(A.label),o="background-color:"+(A.bars&&A.bars.show&&A.bars.fillColor&&A.bars.fill?A.bars.fillColor:A.color)+";",g.push('<td class="flotr-legend-color-box">','<div style="border:1px solid ',f.labelBoxBorderColor,';padding:1px">','<div style="width:',B-1,"px;height:",C-1,"px;border:1px solid ",c[m].color,'">','<div style="width:',B,"px;height:",C,"px;","opacity:.4;",o,'"></div>',"</div>","</div>","</td>",'<td class="flotr-legend-label">',n,"</td>")}h&&g.push("</tr>");if(g.length>0){var G='<table style="font-size:smaller;color:'+e.grid.color+'">'+g.join("")+"</table>";if(f.container)a.insert(f.container,G);else{var H={position:"absolute","z-index":2};k.charAt(0)=="n"?(H.top=l+d.top+"px",H.bottom="auto"):k.charAt(0)=="s"&&(H.bottom=l+d.bottom+"px",H.top="auto"),k.charAt(1)=="e"?(H.right=l+d.right+"px",H.left="auto"):k.charAt(1)=="w"&&(H.left=l+d.left+"px",H.right="auto");var I=a.create("div"),J;I.className="flotr-legend",a.setStyles(I,H),a.insert(I,G),a.insert(this.el,I);if(!f.backgroundOpacity)return;var K=f.backgroundColor||e.grid.backgroundColor||"#ffffff";b.extend(H,a.size(I),{backgroundColor:K,"z-index":1}),H.width+="px",H.height+="px",I=a.create("div"),I.className="flotr-legend-bg",a.setStyles(I,H),a.opacity(I,f.backgroundOpacity),a.insert(I," "),a.insert(this.el,I)}}}}})}(),function(){function a(a){if(this.options.spreadsheet.tickFormatter)return this.options.spreadsheet.tickFormatter(a);var b=c.find(this.axes.x.ticks,function(b){return b.v==a});return b?b.label:a}var b=Flotr.DOM,c=Flotr._;Flotr.addPlugin("spreadsheet",{options:{show:!1,tabGraphLabel:"Graph",tabDataLabel:"Data",toolbarDownload:"Download CSV",toolbarSelectAll:"Select all",csvFileSeparator:",",decimalSeparator:".",tickFormatter:null,initialTab:"graph"},callbacks:{"flotr:afterconstruct":function(){if(!this.options.spreadsheet.show)return;var a=this.spreadsheet,c=b.node('<div class="flotr-tabs-group" style="position:absolute;left:0px;width:'+this.canvasWidth+'px"></div>'),d=b.node('<div style="float:left" class="flotr-tab selected">'+this.options.spreadsheet.tabGraphLabel+"</div>"),e=b.node('<div style="float:left" class="flotr-tab">'+this.options.spreadsheet.tabDataLabel+"</div>"),f;a.tabsContainer=c,a.tabs={graph:d,data:e},b.insert(c,d),b.insert(c,e),b.insert(this.el,c),f=b.size(e).height+2,this.plotOffset.bottom+=f,b.setStyles(c,{top:this.canvasHeight-f+"px"}),this.observe(d,"click",function(){a.showTab("graph")}).observe(e,"click",function(){a.showTab("data")}),this.options.spreadsheet.initialTab!=="graph"&&a.showTab(this.options.spreadsheet.initialTab)}},loadDataGrid:function(){if(this.seriesData)return this.seriesData;var a=this.series,b={};return c.each(a,function(a,d){c.each(a.data,function(a){var c=a[0],e=a[1],f=b[c];if(f)f[d+1]=e;else{var g=[];g[0]=c,g[d+1]=e,b[c]=g}})}),this.seriesData=c.sortBy(b,function(a,b){return parseInt(b,10)}),this.seriesData},constructDataGrid:function(){if(this.spreadsheet.datagrid)return this.spreadsheet.datagrid;var d=this.series,e=this.spreadsheet.loadDataGrid(),f=["<colgroup><col />"],g,h,i,j=['<table class="flotr-datagrid"><tr class="first-row">'];j.push("<th>&nbsp;</th>"),c.each(d,function(a,b){j.push('<th scope="col">'+(a.label||String.fromCharCode(65+b))+"</th>"),f.push("<col />")}),j.push("</tr>"),c.each(e,function(b){j.push("<tr>"),c.times(d.length+1,function(d){var e="td",f=b[d],g=c.isUndefined(f)?"":Math.round(f*1e5)/1e5;if(d===0){e="th";var h=a.call(this,g);h&&(g=h)}j.push("<"+e+(e=="th"?' scope="row"':"")+">"+g+"</"+e+">")},this),j.push("</tr>")},this),f.push("</colgroup>"),i=b.node(j.join("")),g=b.node('<button type="button" class="flotr-datagrid-toolbar-button">'+this.options.spreadsheet.toolbarDownload+"</button>"),h=b.node('<button type="button" class="flotr-datagrid-toolbar-button">'+this.options.spreadsheet.toolbarSelectAll+"</button>"),this.observe(g,"click",c.bind(this.spreadsheet.downloadCSV,this)).observe(h,"click",c.bind(this.spreadsheet.selectAllData,this));var k=b.node('<div class="flotr-datagrid-toolbar"></div>');b.insert(k,g),b.insert(k,h);var l=this.canvasHeight-b.size(this.spreadsheet.tabsContainer).height-2,m=b.node('<div class="flotr-datagrid-container" style="position:absolute;left:0px;top:0px;width:'+this.canvasWidth+"px;height:"+l+'px;overflow:auto;z-index:10"></div>');return b.insert(m,k),b.insert(m,i),b.insert(this.el,m),this.spreadsheet.datagrid=i,this.spreadsheet.container=m,i},showTab:function(a){if(this.spreadsheet.activeTab===a)return;switch(a){case"graph":b.hide(this.spreadsheet.container),b.removeClass(this.spreadsheet.tabs.data,"selected"),b.addClass(this.spreadsheet.tabs.graph,"selected");break;case"data":this.spreadsheet.datagrid||this.spreadsheet.constructDataGrid(),b.show(this.spreadsheet.container),b.addClass(this.spreadsheet.tabs.data,"selected"),b.removeClass(this.spreadsheet.tabs.graph,"selected");break;default:throw"Illegal tab name: "+a}this.spreadsheet.activeTab=a},selectAllData:function(){if(this.spreadsheet.tabs){var a,b,c,d,e=this.spreadsheet.constructDataGrid();return this.spreadsheet.showTab("data"),setTimeout(function(){(c=e.ownerDocument)&&(d=c.defaultView)&&d.getSelection&&c.createRange&&(a=window.getSelection())&&a.removeAllRanges?(b=c.createRange(),b.selectNode(e),a.removeAllRanges(),a.addRange(b)):document.body&&document.body.createTextRange&&(b=document.body.createTextRange())&&(b.moveToElementText(e),b.select())},0),!0}return!1},downloadCSV:function(){var b="",d=this.series,e=this.options,f=this.spreadsheet.loadDataGrid(),g=encodeURIComponent(e.spreadsheet.csvFileSeparator);if(e.spreadsheet.decimalSeparator===e.spreadsheet.csvFileSeparator)throw"The decimal separator is the same as the column separator ("+e.spreadsheet.decimalSeparator+")";c.each(d,function(a,c){b+=g+'"'+(a.label||String.fromCharCode(65+c)).replace(/\"/g,'\\"')+'"'}),b+="%0D%0A",b+=c.reduce(f,function(b,c){var d=a.call(this,c[0])||"";d='"'+(d+"").replace(/\"/g,'\\"')+'"';var f=c.slice(1).join(g);return e.spreadsheet.decimalSeparator!=="."&&(f=f.replace(/\./g,e.spreadsheet.decimalSeparator)),b+d+g+f+"%0D%0A"},"",this),Flotr.isIE&&Flotr.isIE<9?(b=b.replace(new RegExp(g,"g"),decodeURIComponent(g)).replace(/%0A/g,"\n").replace(/%0D/g,"\r"),window.open().document.write(b)):window.open("data:text/csv,"+b)}})}(),function(){var a=Flotr.DOM;Flotr.addPlugin("titles",{callbacks:{"flotr:afterdraw":function(){this.titles.drawTitles()}},drawTitles:function(){var b,c=this.options,d=c.grid.labelMargin,e=this.ctx,f=this.axes;if(!c.HtmlText&&this.textEnabled){var g={size:c.fontSize,color:c.grid.color,textAlign:"center"};c.subtitle&&Flotr.drawText(e,c.subtitle,this.plotOffset.left+this.plotWidth/2,this.titleHeight+this.subtitleHeight-2,g),g.weight=1.5,g.size*=1.5,c.title&&Flotr.drawText(e,c.title,this.plotOffset.left+this.plotWidth/2,this.titleHeight-2,g),g.weight=1.8,g.size*=.8,f.x.options.title&&f.x.used&&(g.textAlign=f.x.options.titleAlign||"center",g.textBaseline="top",g.angle=Flotr.toRad(f.x.options.titleAngle),g=Flotr.getBestTextAlign(g.angle,g),Flotr.drawText(e,f.x.options.title,this.plotOffset.left+this.plotWidth/2,this.plotOffset.top+f.x.maxLabel.height+this.plotHeight+2*d,g)),f.x2.options.title&&f.x2.used&&(g.textAlign=f.x2.options.titleAlign||"center",g.textBaseline="bottom",g.angle=Flotr.toRad(f.x2.options.titleAngle),g=Flotr.getBestTextAlign(g.angle,g),Flotr.drawText(e,f.x2.options.title,this.plotOffset.left+this.plotWidth/2,this.plotOffset.top-f.x2.maxLabel.height-2*d,g)),f.y.options.title&&f.y.used&&(g.textAlign=f.y.options.titleAlign||"right",g.textBaseline="middle",g.angle=Flotr.toRad(f.y.options.titleAngle),g=Flotr.getBestTextAlign(g.angle,g),Flotr.drawText(e,f.y.options.title,this.plotOffset.left-f.y.maxLabel.width-2*d,this.plotOffset.top+this.plotHeight/2,g)),f.y2.options.title&&f.y2.used&&(g.textAlign=f.y2.options.titleAlign||"left",g.textBaseline="middle",g.angle=Flotr.toRad(f.y2.options.titleAngle),g=Flotr.getBestTextAlign(g.angle,g),Flotr.drawText(e,f.y2.options.title,this.plotOffset.left+this.plotWidth+f.y2.maxLabel.width+2*d,this.plotOffset.top+this.plotHeight/2,g))}else{b=[],c.title&&b.push('<div style="position:absolute;top:0;left:',this.plotOffset.left,"px;font-size:1em;font-weight:bold;text-align:center;width:",this.plotWidth,'px;" class="flotr-title">',c.title,"</div>"),c.subtitle&&b.push('<div style="position:absolute;top:',this.titleHeight,"px;left:",this.plotOffset.left,"px;font-size:smaller;text-align:center;width:",this.plotWidth,'px;" class="flotr-subtitle">',c.subtitle,"</div>"),b.push("</div>"),b.push('<div class="flotr-axis-title" style="font-weight:bold;">'),f.x.options.title&&f.x.used&&b.push('<div style="position:absolute;top:',this.plotOffset.top+this.plotHeight+c.grid.labelMargin+f.x.titleSize.height,"px;left:",this.plotOffset.left,"px;width:",this.plotWidth,'px;text-align:center;" class="flotr-axis-title">',f.x.options.title,"</div>"),f.x2.options.title&&f.x2.used&&b.push('<div style="position:absolute;top:0;left:',this.plotOffset.left,"px;width:",this.plotWidth,'px;text-align:center;" class="flotr-axis-title">',f.x2.options.title,"</div>"),f.y.options.title&&f.y.used&&b.push('<div style="position:absolute;top:',this.plotOffset.top+this.plotHeight/2-f.y.titleSize.height/2,'px;left:0;text-align:right;" class="flotr-axis-title">',f.y.options.title,"</div>"),f.y2.options.title&&f.y2.used&&b.push('<div style="position:absolute;top:',this.plotOffset.top+this.plotHeight/2-f.y.titleSize.height/2,'px;right:0;text-align:right;" class="flotr-axis-title">',f.y2.options.title,"</div>"),b=b.join("");var h=a.create("div");a.setStyles({color:c.grid.color}),h.className="flotr-titles",a.insert(this.el,h),a.insert(h,b)}}})}();
diff --git a/addons/web_graph/static/lib/flotr2/js/Axis.js b/addons/web_graph/static/lib/flotr2/js/Axis.js
deleted file mode 100644
index 1c697309ef8..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/Axis.js
+++ /dev/null
@@ -1,303 +0,0 @@
-/**
- * Flotr Axis Library
- */
-
-(function () {
-
-var
- _ = Flotr._,
- LOGARITHMIC = 'logarithmic';
-
-function Axis (o) {
-
- this.orientation = 1;
- this.offset = 0;
- this.datamin = Number.MAX_VALUE;
- this.datamax = -Number.MAX_VALUE;
-
- _.extend(this, o);
-
- this._setTranslations();
-}
-
-
-// Prototype
-Axis.prototype = {
-
- setScale : function () {
- var length = this.length;
- if (this.options.scaling == LOGARITHMIC) {
- this.scale = length / (log(this.max, this.options.base) - log(this.min, this.options.base));
- } else {
- this.scale = length / (this.max - this.min);
- }
- },
-
- calculateTicks : function () {
- var options = this.options;
-
- this.ticks = [];
- this.minorTicks = [];
-
- // User Ticks
- if(options.ticks){
- this._cleanUserTicks(options.ticks, this.ticks);
- this._cleanUserTicks(options.minorTicks || [], this.minorTicks);
- }
- else {
- if (options.mode == 'time') {
- this._calculateTimeTicks();
- } else if (options.scaling === 'logarithmic') {
- this._calculateLogTicks();
- } else {
- this._calculateTicks();
- }
- }
- },
-
- /**
- * Calculates the range of an axis to apply autoscaling.
- */
- calculateRange: function () {
-
- if (!this.used) return;
-
- var axis = this,
- o = axis.options,
- min = o.min !== null ? o.min : axis.datamin,
- max = o.max !== null ? o.max : axis.datamax,
- margin = o.autoscaleMargin;
-
- if (o.scaling == 'logarithmic') {
- if (min <= 0) min = axis.datamin;
-
- // Let it widen later on
- if (max <= 0) max = min;
- }
-
- if (max == min) {
- var widen = max ? 0.01 : 1.00;
- if (o.min === null) min -= widen;
- if (o.max === null) max += widen;
- }
-
- if (o.scaling === 'logarithmic') {
- if (min < 0) min = max / o.base; // Could be the result of widening
-
- var maxexp = Math.log(max);
- if (o.base != Math.E) maxexp /= Math.log(o.base);
- maxexp = Math.ceil(maxexp);
-
- var minexp = Math.log(min);
- if (o.base != Math.E) minexp /= Math.log(o.base);
- minexp = Math.ceil(minexp);
-
- axis.tickSize = Flotr.getTickSize(o.noTicks, minexp, maxexp, o.tickDecimals === null ? 0 : o.tickDecimals);
-
- // Try to determine a suitable amount of miniticks based on the length of a decade
- if (o.minorTickFreq === null) {
- if (maxexp - minexp > 10)
- o.minorTickFreq = 0;
- else if (maxexp - minexp > 5)
- o.minorTickFreq = 2;
- else
- o.minorTickFreq = 5;
- }
- } else {
- axis.tickSize = Flotr.getTickSize(o.noTicks, min, max, o.tickDecimals);
- }
-
- axis.min = min;
- axis.max = max; //extendRange may use axis.min or axis.max, so it should be set before it is caled
-
- // Autoscaling. @todo This probably fails with log scale. Find a testcase and fix it
- if(o.min === null && o.autoscale){
- axis.min -= axis.tickSize * margin;
- // Make sure we don't go below zero if all values are positive.
- if(axis.min < 0 && axis.datamin >= 0) axis.min = 0;
- axis.min = axis.tickSize * Math.floor(axis.min / axis.tickSize);
- }
-
- if(o.max === null && o.autoscale){
- axis.max += axis.tickSize * margin;
- if(axis.max > 0 && axis.datamax <= 0 && axis.datamax != axis.datamin) axis.max = 0;
- axis.max = axis.tickSize * Math.ceil(axis.max / axis.tickSize);
- }
-
- if (axis.min == axis.max) axis.max = axis.min + 1;
- },
-
- calculateTextDimensions : function (T, options) {
-
- var maxLabel = '',
- length,
- i;
-
- if (this.options.showLabels) {
- for (i = 0; i < this.ticks.length; ++i) {
- length = this.ticks[i].label.length;
- if (length > maxLabel.length){
- maxLabel = this.ticks[i].label;
- }
- }
- }
-
- this.maxLabel = T.dimensions(
- maxLabel,
- {size:options.fontSize, angle: Flotr.toRad(this.options.labelsAngle)},
- 'font-size:smaller;',
- 'flotr-grid-label'
- );
-
- this.titleSize = T.dimensions(
- this.options.title,
- {size:options.fontSize*1.2, angle: Flotr.toRad(this.options.titleAngle)},
- 'font-weight:bold;',
- 'flotr-axis-title'
- );
- },
-
- _cleanUserTicks : function (ticks, axisTicks) {
-
- var axis = this, options = this.options,
- v, i, label, tick;
-
- if(_.isFunction(ticks)) ticks = ticks({min : axis.min, max : axis.max});
-
- for(i = 0; i < ticks.length; ++i){
- tick = ticks[i];
- if(typeof(tick) === 'object'){
- v = tick[0];
- label = (tick.length > 1) ? tick[1] : options.tickFormatter(v, {min : axis.min, max : axis.max});
- } else {
- v = tick;
- label = options.tickFormatter(v, {min : this.min, max : this.max});
- }
- axisTicks[i] = { v: v, label: label };
- }
- },
-
- _calculateTimeTicks : function () {
- this.ticks = Flotr.Date.generator(this);
- },
-
- _calculateLogTicks : function () {
-
- var axis = this,
- o = axis.options,
- v,
- decadeStart;
-
- var max = Math.log(axis.max);
- if (o.base != Math.E) max /= Math.log(o.base);
- max = Math.ceil(max);
-
- var min = Math.log(axis.min);
- if (o.base != Math.E) min /= Math.log(o.base);
- min = Math.ceil(min);
-
- for (i = min; i < max; i += axis.tickSize) {
- decadeStart = (o.base == Math.E) ? Math.exp(i) : Math.pow(o.base, i);
- // Next decade begins here:
- var decadeEnd = decadeStart * ((o.base == Math.E) ? Math.exp(axis.tickSize) : Math.pow(o.base, axis.tickSize));
- var stepSize = (decadeEnd - decadeStart) / o.minorTickFreq;
-
- axis.ticks.push({v: decadeStart, label: o.tickFormatter(decadeStart, {min : axis.min, max : axis.max})});
- for (v = decadeStart + stepSize; v < decadeEnd; v += stepSize)
- axis.minorTicks.push({v: v, label: o.tickFormatter(v, {min : axis.min, max : axis.max})});
- }
-
- // Always show the value at the would-be start of next decade (end of this decade)
- decadeStart = (o.base == Math.E) ? Math.exp(i) : Math.pow(o.base, i);
- axis.ticks.push({v: decadeStart, label: o.tickFormatter(decadeStart, {min : axis.min, max : axis.max})});
- },
-
- _calculateTicks : function () {
-
- var axis = this,
- o = axis.options,
- tickSize = axis.tickSize,
- min = axis.min,
- max = axis.max,
- start = tickSize * Math.ceil(min / tickSize), // Round to nearest multiple of tick size.
- decimals,
- minorTickSize,
- v, v2,
- i, j;
-
- if (o.minorTickFreq)
- minorTickSize = tickSize / o.minorTickFreq;
-
- // Then store all possible ticks.
- for (i = 0; (v = v2 = start + i * tickSize) <= max; ++i){
-
- // Round (this is always needed to fix numerical instability).
- decimals = o.tickDecimals;
- if (decimals === null) decimals = 1 - Math.floor(Math.log(tickSize) / Math.LN10);
- if (decimals < 0) decimals = 0;
-
- v = v.toFixed(decimals);
- axis.ticks.push({ v: v, label: o.tickFormatter(v, {min : axis.min, max : axis.max}) });
-
- if (o.minorTickFreq) {
- for (j = 0; j < o.minorTickFreq && (i * tickSize + j * minorTickSize) < max; ++j) {
- v = v2 + j * minorTickSize;
- axis.minorTicks.push({ v: v, label: o.tickFormatter(v, {min : axis.min, max : axis.max}) });
- }
- }
- }
-
- },
-
- _setTranslations : function (logarithmic) {
- this.d2p = (logarithmic ? d2pLog : d2p);
- this.p2d = (logarithmic ? p2dLog : p2d);
- }
-};
-
-
-// Static Methods
-_.extend(Axis, {
- getAxes : function (options) {
- return {
- x: new Axis({options: options.xaxis, n: 1, length: this.plotWidth}),
- x2: new Axis({options: options.x2axis, n: 2, length: this.plotWidth}),
- y: new Axis({options: options.yaxis, n: 1, length: this.plotHeight, offset: this.plotHeight, orientation: -1}),
- y2: new Axis({options: options.y2axis, n: 2, length: this.plotHeight, offset: this.plotHeight, orientation: -1})
- };
- }
-});
-
-
-// Helper Methods
-
-function d2p (dataValue) {
- return this.offset + this.orientation * (dataValue - this.min) * this.scale;
-}
-
-function p2d (pointValue) {
- return (this.offset + this.orientation * pointValue) / this.scale + this.min;
-}
-
-function d2pLog (dataValue) {
- return this.offset + this.orientation * (log(dataValue, this.options.base) - log(this.min, this.options.base)) * this.scale;
-}
-
-function p2dLog (pointValue) {
- return exp((this.offset + this.orientation * pointValue) / this.scale + log(this.min, this.options.base), this.options.base);
-}
-
-function log (value, base) {
- value = Math.log(Math.max(value, Number.MIN_VALUE));
- if (base !== Math.E)
- value /= Math.log(base);
- return value;
-}
-
-function exp (value, base) {
- return (base === Math.E) ? Math.exp(value) : Math.pow(base, value);
-}
-
-Flotr.Axis = Axis;
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/Color.js b/addons/web_graph/static/lib/flotr2/js/Color.js
deleted file mode 100644
index ab4ba0b432d..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/Color.js
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- * Flotr Color
- */
-
-(function () {
-
-var
- _ = Flotr._;
-
-// Constructor
-function Color (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();
-}
-
-// Constants
-var 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]
-};
-
-Color.prototype = {
- scale: function(rf, gf, bf, af){
- var x = 4;
- while (-1 < --x) {
- if (!_.isUndefined(arguments[x])) this[this.rgba[x]] *= arguments[x];
- }
- return this.normalize();
- },
- alpha: function(alpha) {
- if (!_.isUndefined(alpha) && !_.isNull(alpha)) {
- this.a = alpha;
- }
- return this.normalize();
- },
- clone: function(){
- return new 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, 10), 0, 255);
- this.g = limit(parseInt(this.g, 10), 0, 255);
- this.b = limit(parseInt(this.b, 10), 0, 255);
- this.a = limit(this.a, 0, 1);
- return this;
- },
- distance: function(color){
- if (!color) return;
- color = new 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(',')+')';
- },
- contrast: function () {
- var
- test = 1 - ( 0.299 * this.r + 0.587 * this.g + 0.114 * this.b) / 255;
- return (test < 0.5 ? '#000000' : '#ffffff');
- }
-};
-
-_.extend(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 Color) return color;
-
- var result;
-
- // #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], 10), parseInt(result[2], 10), parseInt(result[3], 10));
-
- // #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], 10), parseInt(result[2], 10), parseInt(result[3], 10), 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+'').replace(/^\s*([\S\s]*?)\s*$/, '$1').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);
- },
-
- /**
- * Process color and options into color style.
- */
- processColor: function(color, options) {
-
- var opacity = options.opacity;
- if (!color) return 'rgba(0, 0, 0, 0)';
- if (color instanceof Color) return color.alpha(opacity).toString();
- if (_.isString(color)) return Color.parse(color).alpha(opacity).toString();
-
- var grad = color.colors ? color : {colors: color};
-
- if (!options.ctx) {
- if (!_.isArray(grad.colors)) return 'rgba(0, 0, 0, 0)';
- return Color.parse(_.isArray(grad.colors[0]) ? grad.colors[0][1] : grad.colors[0]).alpha(opacity).toString();
- }
- grad = _.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 (_.isArray(c)) {
- stop = c[0];
- c = c[1];
- }
- else stop = i / (grad.colors.length-1);
- gradient.addColorStop(stop, Color.parse(c).alpha(opacity));
- }
- return gradient;
- }
-});
-
-Flotr.Color = Color;
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/DOM.js b/addons/web_graph/static/lib/flotr2/js/DOM.js
deleted file mode 100644
index 43df857395b..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/DOM.js
+++ /dev/null
@@ -1,88 +0,0 @@
-(function () {
-
-var _ = Flotr._;
-
-Flotr.DOM = {
- addClass: function(element, name){
- var classList = (element.className ? element.className : '');
- if (_.include(classList.split(/\s+/g), name)) return;
- element.className = (classList ? classList + ' ' : '') + name;
- },
- /**
- * Create an element.
- */
- create: function(tag){
- return document.createElement(tag);
- },
- node: function(html) {
- var div = Flotr.DOM.create('div'), n;
- div.innerHTML = html;
- n = div.children[0];
- div.innerHTML = '';
- return n;
- },
- /**
- * Remove all children.
- */
- empty: function(element){
- element.innerHTML = '';
- /*
- if (!element) return;
- _.each(element.childNodes, function (e) {
- Flotr.DOM.empty(e);
- element.removeChild(e);
- });
- */
- },
- hide: function(element){
- Flotr.DOM.setStyles(element, {display:'none'});
- },
- /**
- * Insert a child.
- * @param {Element} element
- * @param {Element|String} Element or string to be appended.
- */
- insert: function(element, child){
- if(_.isString(child))
- element.innerHTML += child;
- else if (_.isElement(child))
- element.appendChild(child);
- },
- // @TODO find xbrowser implementation
- opacity: function(element, opacity) {
- element.style.opacity = opacity;
- },
- position: function(element, p){
- if (!element.offsetParent)
- return {left: (element.offsetLeft || 0), top: (element.offsetTop || 0)};
-
- p = this.position(element.offsetParent);
- p.left += element.offsetLeft;
- p.top += element.offsetTop;
- return p;
- },
- removeClass: function(element, name) {
- var classList = (element.className ? element.className : '');
- element.className = _.filter(classList.split(/\s+/g), function (c) {
- if (c != name) return true; }
- ).join(' ');
- },
- setStyles: function(element, o) {
- _.each(o, function (value, key) {
- element.style[key] = value;
- });
- },
- show: function(element){
- Flotr.DOM.setStyles(element, {display:''});
- },
- /**
- * Return element size.
- */
- size: function(element){
- return {
- height : element.offsetHeight,
- width : element.offsetWidth };
- }
-};
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/Date.js b/addons/web_graph/static/lib/flotr2/js/Date.js
deleted file mode 100644
index fe72dba709f..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/Date.js
+++ /dev/null
@@ -1,207 +0,0 @@
-/**
- * Flotr Date
- */
-Flotr.Date = {
-
- set : function (date, name, mode, value) {
- mode = mode || 'UTC';
- name = 'set' + (mode === 'UTC' ? 'UTC' : '') + name;
- date[name](value);
- },
-
- get : function (date, name, mode) {
- mode = mode || 'UTC';
- name = 'get' + (mode === 'UTC' ? 'UTC' : '') + name;
- return date[name]();
- },
-
- format: function(d, format, mode) {
- 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
- get = this.get,
- tokens = {
- h: get(d, 'Hours', mode).toString(),
- H: leftPad(get(d, 'Hours', mode)),
- M: leftPad(get(d, 'Minutes', mode)),
- S: leftPad(get(d, 'Seconds', mode)),
- s: get(d, 'Milliseconds', mode),
- d: get(d, 'Date', mode).toString(),
- m: (get(d, 'Month') + 1).toString(),
- y: get(d, 'FullYear').toString(),
- b: Flotr.Date.monthNames[get(d, 'Month', mode)]
- };
-
- 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
- options = axis.options,
- scale = Flotr.Date.timeUnits[options.timeUnit],
- d = new Date(v * scale);
-
- // first check global format
- if (axis.options.timeFormat)
- return Flotr.Date.format(d, options.timeFormat, options.timeMode);
-
- var span = (axis.max - axis.min) * scale,
- t = axis.tickSize * Flotr.Date.timeUnits[axis.tickUnit];
-
- return Flotr.Date.format(d, Flotr.Date.getFormat(t, span), options.timeMode);
- },
- generator: function(axis) {
-
- var
- set = this.set,
- get = this.get,
- timeUnits = this.timeUnits,
- spec = this.spec,
- options = axis.options,
- mode = options.timeMode,
- scale = timeUnits[options.timeUnit],
- min = axis.min * scale,
- max = axis.max * scale,
- delta = (max - min) / options.noTicks,
- ticks = [],
- tickSize = axis.tickSize,
- tickUnit,
- formatter, i;
-
- // Use custom formatter or time tick formatter
- formatter = (options.tickFormatter === Flotr.defaultTickFormatter ?
- this.formatter : options.tickFormatter
- );
-
- for (i = 0; i < spec.length - 1; ++i) {
- var d = spec[i][0] * timeUnits[spec[i][1]];
- if (delta < (d + spec[i+1][0] * timeUnits[spec[i+1][1]]) / 2 && d >= tickSize)
- break;
- }
- tickSize = spec[i][0];
- tickUnit = spec[i][1];
-
- // special-case the possibility of several years
- if (tickUnit == "year") {
- tickSize = Flotr.getTickSize(options.noTicks*timeUnits.year, min, max, 0);
-
- // Fix for 0.5 year case
- if (tickSize == 0.5) {
- tickUnit = "month";
- tickSize = 6;
- }
- }
-
- axis.tickUnit = tickUnit;
- axis.tickSize = tickSize;
-
- var
- d = new Date(min);
-
- var step = tickSize * timeUnits[tickUnit];
-
- function setTick (name) {
- set(d, name, mode, Flotr.floorInBase(
- get(d, name, mode), tickSize
- ));
- }
-
- switch (tickUnit) {
- case "millisecond": setTick('Milliseconds'); break;
- case "second": setTick('Seconds'); break;
- case "minute": setTick('Minutes'); break;
- case "hour": setTick('Hours'); break;
- case "month": setTick('Month'); break;
- case "year": setTick('FullYear'); break;
- }
-
- // reset smaller components
- if (step >= timeUnits.second) set(d, 'Milliseconds', mode, 0);
- if (step >= timeUnits.minute) set(d, 'Seconds', mode, 0);
- if (step >= timeUnits.hour) set(d, 'Minutes', mode, 0);
- if (step >= timeUnits.day) set(d, 'Hours', mode, 0);
- if (step >= timeUnits.day * 4) set(d, 'Date', mode, 1);
- if (step >= timeUnits.year) set(d, 'Month', mode, 0);
-
- var carry = 0, v = NaN, prev;
- do {
- prev = v;
- v = d.getTime();
- ticks.push({ v: v / scale, label: formatter(v / scale, axis) });
- if (tickUnit == "month") {
- if (tickSize < 1) {
- /* a bit complicated - we'll divide the month up but we need to take care of fractions
- so we don't end up in the middle of a day */
- set(d, 'Date', mode, 1);
- var start = d.getTime();
- set(d, 'Month', mode, get(d, 'Month', mode) + 1)
- var end = d.getTime();
- d.setTime(v + carry * timeUnits.hour + (end - start) * tickSize);
- carry = get(d, 'Hours', mode)
- set(d, 'Hours', mode, 0);
- }
- else
- set(d, 'Month', mode, get(d, 'Month', mode) + tickSize);
- }
- else if (tickUnit == "year") {
- set(d, 'FullYear', mode, get(d, 'FullYear', mode) + tickSize);
- }
- else
- d.setTime(v + step);
-
- } while (v < 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"]
-};
diff --git a/addons/web_graph/static/lib/flotr2/js/DefaultOptions.js b/addons/web_graph/static/lib/flotr2/js/DefaultOptions.js
deleted file mode 100644
index 7399553df6a..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/DefaultOptions.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * Flotr Defaults
- */
-Flotr.defaultOptions = {
- colors: ['#00A8F0', '#C0D800', '#CB4B4B', '#4DA74D', '#9440ED'], //=> The default colorscheme. When there are > 5 series, additional colors are generated.
- ieBackgroundColor: '#FFFFFF', // Background color for excanvas clipping
- 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
- fontColor: '#545454', // => default font color
- fontSize: 7.5, // => canvas' text font size
- resolution: 1, // => resolution of the graph, to have printer-friendly graphs !
- parseFloat: true, // => whether to preprocess data for floats (ie. if input is string)
- xaxis: {
- ticks: null, // => format: either [1, 3] or [[1, 'a'], 3]
- minorTicks: null, // => format: either [1, 3] or [[1, 'a'], 3]
- showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise
- showMinorLabels: false,// => true to show the axis minor ticks labels, false to hide
- 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
- minorTickFreq: null, // => number of minor ticks between major ticks for autogenerated ticks
- tickFormatter: Flotr.defaultTickFormatter, // => fn: number, Object -> 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
- autoscale: false, // => Turns autoscaling on with true
- 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,
- timeMode:'UTC', // => For UTC time ('local' for local time).
- timeUnit:'millisecond',// => Unit for time (millisecond, second, minute, hour, day, month, year)
- scaling: 'linear', // => Scaling, can be 'linear' or 'logarithmic'
- base: Math.E,
- titleAlign: 'center',
- margin: true // => Turn off margins with false
- },
- x2axis: {},
- yaxis: {
- ticks: null, // => format: either [1, 3] or [[1, 'a'], 3]
- minorTicks: null, // => format: either [1, 3] or [[1, 'a'], 3]
- showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise
- showMinorLabels: false,// => true to show the axis minor ticks labels, false to hide
- 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
- minorTickFreq: null, // => number of minor ticks between major ticks for autogenerated ticks
- tickFormatter: Flotr.defaultTickFormatter, // => fn: number, Object -> 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
- autoscale: false, // => Turns autoscaling on with true
- 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,
- titleAlign: 'center',
- margin: true // => Turn off margins with false
- },
- y2axis: {
- titleAngle: 270
- },
- grid: {
- color: '#545454', // => primary color used for outline and labels
- backgroundColor: null, // => null for transparent, else color
- backgroundImage: null, // => background image. String or object with src, left and top
- watermarkAlpha: 0.4, // =>
- tickColor: '#DDDDDD', // => color used for the ticks
- labelMargin: 3, // => margin in pixels
- verticalLines: true, // => whether to show gridlines in vertical direction
- minorVerticalLines: null, // => whether to show gridlines for minor ticks in vertical dir.
- horizontalLines: true, // => whether to show gridlines in horizontal direction
- minorHorizontalLines: null, // => whether to show gridlines for minor ticks in horizontal dir.
- outlineWidth: 1, // => width of the grid outline/border in pixels
- outline : 'nsew', // => walls of the outline to display
- circular: false // => if set to true, the grid will be circular, must be used when radars are drawn
- },
- mouse: {
- track: false, // => true to track the mouse, no tracking otherwise
- trackAll: false,
- 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
- trackY: true, // => whether or not to track the mouse in the y axis
- 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
- }
-};
diff --git a/addons/web_graph/static/lib/flotr2/js/EventAdapter.js b/addons/web_graph/static/lib/flotr2/js/EventAdapter.js
deleted file mode 100644
index 062ceeab294..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/EventAdapter.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Flotr Event Adapter
- */
-(function () {
-var
- F = Flotr,
- bean = F.bean;
-F.EventAdapter = {
- observe: function(object, name, callback) {
- bean.add(object, name, callback);
- return this;
- },
- fire: function(object, name, args) {
- bean.fire(object, name, args);
- if (typeof(Prototype) != 'undefined')
- Event.fire(object, name, args);
- // @TODO Someone who uses mootools, add mootools adapter for existing applciations.
- return this;
- },
- stopObserving: function(object, name, callback) {
- bean.remove(object, name, callback);
- return this;
- },
- eventPointer: function(e) {
- if (!F._.isUndefined(e.touches) && e.touches.length > 0) {
- return {
- x : e.touches[0].pageX,
- y : e.touches[0].pageY
- };
- } else if (!F._.isUndefined(e.changedTouches) && e.changedTouches.length > 0) {
- return {
- x : e.changedTouches[0].pageX,
- y : e.changedTouches[0].pageY
- };
- } else if (e.pageX || e.pageY) {
- return {
- x : e.pageX,
- y : e.pageY
- };
- } else if (e.clientX || e.clientY) {
- var
- d = document,
- b = d.body,
- de = d.documentElement;
- return {
- x: e.clientX + b.scrollLeft + de.scrollLeft,
- y: e.clientY + b.scrollTop + de.scrollTop
- };
- }
- }
-};
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/Flotr.js b/addons/web_graph/static/lib/flotr2/js/Flotr.js
deleted file mode 100644
index e8256096adb..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/Flotr.js
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * Flotr2 (c) 2012 Carl Sutherland
- * MIT License
- * Special thanks to:
- * Flotr: http://code.google.com/p/flotr/ (fork)
- * Flot: https://github.com/flot/flot (original fork)
- */
-(function () {
-
-var
- global = this,
- previousFlotr = this.Flotr,
- Flotr;
-
-Flotr = {
- _: _,
- bean: bean,
- isIphone: /iphone/i.test(navigator.userAgent),
- isIE: (navigator.appVersion.indexOf("MSIE") != -1 ? parseFloat(navigator.appVersion.split("MSIE")[1]) : false),
-
- /**
- * 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);
- },
-
- /**
- * 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
- * @TODO See if we can't remove this.
- */
- merge: function(src, dest){
- var i, v, result = dest || {};
-
- for (i in src) {
- v = src[i];
- if (v && typeof(v) === 'object') {
- if (v.constructor === Array) {
- result[i] = this._.clone(v);
- } else if (v.constructor !== RegExp && !this._.isElement(v)) {
- result[i] = Flotr.merge(v, (dest ? dest[i] : undefined));
- } else {
- result[i] = v;
- }
- } else {
- result[i] = v;
- }
- }
-
- return result;
- },
-
- /**
- * Recursively clones an object.
- * @param {Object} object - The object to clone
- * @return {Object} the clone
- * @TODO See if we can't remove this.
- */
- clone: function(object){
- return Flotr.merge(object, {});
- },
-
- /**
- * 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
- * @param {Object} axisOpts - the axis' options
- * @return {String} formatted tick string
- */
- defaultTickFormatter: function(val, axisOpts){
- 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);
- },
- drawText: function(ctx, text, x, y, style) {
- if (!ctx.fillText) {
- ctx.drawText(text, x, y, style);
- return;
- }
-
- style = this._.extend({
- size: Flotr.defaultOptions.fontSize,
- color: '#000000',
- textAlign: 'left',
- textBaseline: 'bottom',
- weight: 1,
- angle: 0
- }, style);
-
- ctx.save();
- ctx.translate(x, y);
- ctx.rotate(style.angle);
- ctx.fillStyle = style.color;
- ctx.font = (style.weight > 1 ? "bold " : "") + (style.size*1.3) + "px sans-serif";
- ctx.textAlign = style.textAlign;
- ctx.textBaseline = style.textBaseline;
- ctx.fillText(text, 0, 0);
- ctx.restore();
- },
- getBestTextAlign: function(angle, style) {
- style = style || {textAlign: 'center', textBaseline: 'middle'};
- angle += Flotr.getTextAngleFromAlign(style);
-
- if (Math.abs(Math.cos(angle)) > 10e-3)
- style.textAlign = (Math.cos(angle) > 0 ? 'right' : 'left');
-
- if (Math.abs(Math.sin(angle)) > 10e-3)
- style.textBaseline = (Math.sin(angle) > 0 ? 'top' : 'bottom');
-
- return style;
- },
- alignTable: {
- 'right middle' : 0,
- 'right top' : Math.PI/4,
- 'center top' : Math.PI/2,
- 'left top' : 3*(Math.PI/4),
- 'left middle' : Math.PI,
- 'left bottom' : -3*(Math.PI/4),
- 'center bottom': -Math.PI/2,
- 'right bottom' : -Math.PI/4,
- 'center middle': 0
- },
- getTextAngleFromAlign: function(style) {
- return Flotr.alignTable[style.textAlign+' '+style.textBaseline] || 0;
- },
- noConflict : function () {
- global.Flotr = previousFlotr;
- return this;
- }
-};
-
-global.Flotr = Flotr;
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/Graph.js b/addons/web_graph/static/lib/flotr2/js/Graph.js
deleted file mode 100644
index 0e0310a5f4e..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/Graph.js
+++ /dev/null
@@ -1,745 +0,0 @@
-/**
- * Flotr Graph class that plots a graph on creation.
- */
-(function () {
-
-var
- D = Flotr.DOM,
- E = Flotr.EventAdapter,
- _ = Flotr._,
- flotr = Flotr;
-/**
- * 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
- */
-Graph = function(el, data, options){
-// Let's see if we can get away with out this [JS]
-// try {
- this._setEl(el);
- this._initMembers();
- this._initPlugins();
-
- E.fire(this.el, 'flotr:beforeinit', [this]);
-
- this.data = data;
- this.series = flotr.Series.getSeries(data);
- this._initOptions(options);
- this._initGraphTypes();
- this._initCanvas();
- this._text = new flotr.Text({
- element : this.el,
- ctx : this.ctx,
- html : this.options.HtmlText,
- textEnabled : this.textEnabled
- });
- E.fire(this.el, 'flotr:afterconstruct', [this]);
- this._initEvents();
-
- this.findDataRanges();
- this.calculateSpacing();
-
- this.draw(_.bind(function() {
- E.fire(this.el, 'flotr:afterinit', [this]);
- }, this));
-/*
- try {
- } catch (e) {
- try {
- console.error(e);
- } catch (e2) {}
- }*/
-};
-
-function observe (object, name, callback) {
- E.observe.apply(this, arguments);
- this._handles.push(arguments);
- return this;
-}
-
-Graph.prototype = {
-
- destroy: function () {
- E.fire(this.el, 'flotr:destroy');
- _.each(this._handles, function (handle) {
- E.stopObserving.apply(this, handle);
- });
- this._handles = [];
- this.el.graph = null;
- },
-
- observe : observe,
-
- /**
- * @deprecated
- */
- _observe : observe,
-
- processColor: function(color, options){
- var o = { x1: 0, y1: 0, x2: this.plotWidth, y2: this.plotHeight, opacity: 1, ctx: this.ctx };
- _.extend(o, options);
- return flotr.Color.processColor(color, o);
- },
- /**
- * Function determines the min and max values for the xaxis and yaxis.
- *
- * TODO logarithmic range validation (consideration of 0)
- */
- findDataRanges: function(){
- var a = this.axes,
- xaxis, yaxis, range;
-
- _.each(this.series, function (series) {
- range = series.getRange();
- if (range) {
- xaxis = series.xaxis;
- yaxis = series.yaxis;
- xaxis.datamin = Math.min(range.xmin, xaxis.datamin);
- xaxis.datamax = Math.max(range.xmax, xaxis.datamax);
- yaxis.datamin = Math.min(range.ymin, yaxis.datamin);
- yaxis.datamax = Math.max(range.ymax, yaxis.datamax);
- xaxis.used = (xaxis.used || range.xused);
- yaxis.used = (yaxis.used || range.yused);
- }
- }, this);
-
- // Check for empty data, no data case (none used)
- if (!a.x.used && !a.x2.used) a.x.used = true;
- if (!a.y.used && !a.y2.used) a.y.used = true;
-
- _.each(a, function (axis) {
- axis.calculateRange();
- });
-
- var
- types = _.keys(flotr.graphTypes),
- drawn = false;
-
- _.each(this.series, function (series) {
- if (series.hide) return;
- _.each(types, function (type) {
- if (series[type] && series[type].show) {
- this.extendRange(type, series);
- drawn = true;
- }
- }, this);
- if (!drawn) {
- this.extendRange(this.options.defaultType, series);
- }
- }, this);
- },
-
- extendRange : function (type, series) {
- if (this[type].extendRange) this[type].extendRange(series, series.data, series[type], this[type]);
- if (this[type].extendYRange) this[type].extendYRange(series.yaxis, series.data, series[type], this[type]);
- if (this[type].extendXRange) this[type].extendXRange(series.xaxis, series.data, series[type], this[type]);
- },
-
- /**
- * Calculates axis label sizes.
- */
- calculateSpacing: function(){
-
- var a = this.axes,
- options = this.options,
- series = this.series,
- margin = options.grid.labelMargin,
- T = this._text,
- x = a.x,
- x2 = a.x2,
- y = a.y,
- y2 = a.y2,
- maxOutset = options.grid.outlineWidth,
- i, j, l, dim;
-
- // TODO post refactor, fix this
- _.each(a, function (axis) {
- axis.calculateTicks();
- axis.calculateTextDimensions(T, options);
- });
-
- // Title height
- dim = T.dimensions(
- options.title,
- {size: options.fontSize*1.5},
- 'font-size:1em;font-weight:bold;',
- 'flotr-title'
- );
- this.titleHeight = dim.height;
-
- // Subtitle height
- dim = T.dimensions(
- options.subtitle,
- {size: options.fontSize},
- 'font-size:smaller;',
- 'flotr-subtitle'
- );
- this.subtitleHeight = dim.height;
-
- 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;
- if (x.options.margin === false) {
- p.bottom = 0;
- p.top = 0;
- } else {
- p.bottom += (options.grid.circular ? 0 : (x.used && x.options.showLabels ? (x.maxLabel.height + margin) : 0)) +
- (x.used && x.options.title ? (x.titleSize.height + margin) : 0) + maxOutset;
-
- p.top += (options.grid.circular ? 0 : (x2.used && x2.options.showLabels ? (x2.maxLabel.height + margin) : 0)) +
- (x2.used && x2.options.title ? (x2.titleSize.height + margin) : 0) + this.subtitleHeight + this.titleHeight + maxOutset;
- }
- if (y.options.margin === false) {
- p.left = 0;
- p.right = 0;
- } else {
- p.left += (options.grid.circular ? 0 : (y.used && y.options.showLabels ? (y.maxLabel.width + margin) : 0)) +
- (y.used && y.options.title ? (y.titleSize.width + margin) : 0) + maxOutset;
-
- p.right += (options.grid.circular ? 0 : (y2.used && y2.options.showLabels ? (y2.maxLabel.width + margin) : 0)) +
- (y2.used && y2.options.title ? (y2.titleSize.width + margin) : 0) + maxOutset;
- }
-
- p.top = Math.floor(p.top); // In order the outline not to be blured
-
- this.plotWidth = this.canvasWidth - p.left - p.right;
- this.plotHeight = this.canvasHeight - p.bottom - p.top;
-
- // TODO post refactor, fix this
- x.length = x2.length = this.plotWidth;
- y.length = y2.length = this.plotHeight;
- y.offset = y2.offset = this.plotHeight;
- x.setScale();
- x2.setScale();
- y.setScale();
- y2.setScale();
- },
- /**
- * Draws grid, labels, series and outline.
- */
- draw: function(after) {
-
- var
- context = this.ctx,
- i;
-
- E.fire(this.el, 'flotr:beforedraw', [this.series, this]);
-
- if (this.series.length) {
-
- context.save();
- context.translate(this.plotOffset.left, this.plotOffset.top);
-
- for (i = 0; i < this.series.length; i++) {
- if (!this.series[i].hide) this.drawSeries(this.series[i]);
- }
-
- context.restore();
- this.clip();
- }
-
- E.fire(this.el, 'flotr:afterdraw', [this.series, this]);
- if (after) after();
- },
- /**
- * Actually draws the graph.
- * @param {Object} series - series to draw
- */
- drawSeries: function(series){
-
- function drawChart (series, typeKey) {
- var options = this.getOptions(series, typeKey);
- this[typeKey].draw(options);
- }
-
- var drawn = false;
- series = series || this.series;
-
- _.each(flotr.graphTypes, function (type, typeKey) {
- if (series[typeKey] && series[typeKey].show && this[typeKey]) {
- drawn = true;
- drawChart.call(this, series, typeKey);
- }
- }, this);
-
- if (!drawn) drawChart.call(this, series, this.options.defaultType);
- },
-
- getOptions : function (series, typeKey) {
- var
- type = series[typeKey],
- graphType = this[typeKey],
- options = {
- context : this.ctx,
- width : this.plotWidth,
- height : this.plotHeight,
- fontSize : this.options.fontSize,
- fontColor : this.options.fontColor,
- textEnabled : this.textEnabled,
- htmlText : this.options.HtmlText,
- text : this._text, // TODO Is this necessary?
- element : this.el,
- data : series.data,
- color : series.color,
- shadowSize : series.shadowSize,
- xScale : _.bind(series.xaxis.d2p, series.xaxis),
- yScale : _.bind(series.yaxis.d2p, series.yaxis)
- };
-
- options = flotr.merge(type, options);
-
- // Fill
- options.fillStyle = this.processColor(
- type.fillColor || series.color,
- {opacity: type.fillOpacity}
- );
-
- return options;
- },
- /**
- * Calculates the coordinates from a mouse event object.
- * @param {Event} event - Mouse Event object.
- * @return {Object} Object with coordinates of the mouse.
- */
- getEventPosition: function (e){
-
- var
- d = document,
- b = d.body,
- de = d.documentElement,
- axes = this.axes,
- plotOffset = this.plotOffset,
- lastMousePos = this.lastMousePos,
- pointer = E.eventPointer(e),
- dx = pointer.x - lastMousePos.pageX,
- dy = pointer.y - lastMousePos.pageY,
- r, rx, ry;
-
- if ('ontouchstart' in this.el) {
- r = D.position(this.overlay);
- rx = pointer.x - r.left - plotOffset.left;
- ry = pointer.y - r.top - plotOffset.top;
- } else {
- r = this.overlay.getBoundingClientRect();
- rx = e.clientX - r.left - plotOffset.left - b.scrollLeft - de.scrollLeft;
- ry = e.clientY - r.top - plotOffset.top - b.scrollTop - de.scrollTop;
- }
-
- return {
- x: axes.x.p2d(rx),
- x2: axes.x2.p2d(rx),
- y: axes.y.p2d(ry),
- y2: axes.y2.p2d(ry),
- relX: rx,
- relY: ry,
- dX: dx,
- dY: dy,
- absX: pointer.x,
- absY: pointer.y,
- pageX: pointer.x,
- pageY: pointer.y
- };
- },
- /**
- * Observes the 'click' event and fires the 'flotr:click' event.
- * @param {Event} event - 'click' Event object.
- */
- clickHandler: function(event){
- if(this.ignoreClick){
- this.ignoreClick = false;
- return this.ignoreClick;
- }
- E.fire(this.el, '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){
- if (this.mouseDownMoveHandler) return;
- var pos = this.getEventPosition(event);
- E.fire(this.el, 'flotr:mousemove', [event, pos, this]);
- this.lastMousePos = pos;
- },
- /**
- * Observes the 'mousedown' event.
- * @param {Event} event - 'mousedown' Event object.
- */
- mouseDownHandler: function (event){
-
- /*
- // @TODO Context menu?
- if(event.isRightClick()) {
- event.stop();
-
- var overlay = this.overlay;
- overlay.hide();
-
- function cancelContextMenu () {
- overlay.show();
- E.stopObserving(document, 'mousemove', cancelContextMenu);
- }
- E.observe(document, 'mousemove', cancelContextMenu);
- return;
- }
- */
-
- if (this.mouseUpHandler) return;
- this.mouseUpHandler = _.bind(function (e) {
- E.stopObserving(document, 'mouseup', this.mouseUpHandler);
- E.stopObserving(document, 'mousemove', this.mouseDownMoveHandler);
- this.mouseDownMoveHandler = null;
- this.mouseUpHandler = null;
- // @TODO why?
- //e.stop();
- E.fire(this.el, 'flotr:mouseup', [e, this]);
- }, this);
- this.mouseDownMoveHandler = _.bind(function (e) {
- var pos = this.getEventPosition(e);
- E.fire(this.el, 'flotr:mousemove', [event, pos, this]);
- this.lastMousePos = pos;
- }, this);
- E.observe(document, 'mouseup', this.mouseUpHandler);
- E.observe(document, 'mousemove', this.mouseDownMoveHandler);
- E.fire(this.el, 'flotr:mousedown', [event, this]);
- this.ignoreClick = false;
- },
- drawTooltip: function(content, x, y, options) {
- var mt = this.getMouseTrack(),
- style = '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;',
- p = options.position,
- m = options.margin,
- plotOffset = this.plotOffset;
-
- if(x !== null && y !== null){
- if (!options.relative) { // absolute to the canvas
- if(p.charAt(0) == 'n') style += 'top:' + (m + plotOffset.top) + 'px;bottom:auto;';
- else if(p.charAt(0) == 's') style += 'bottom:' + (m + plotOffset.bottom) + 'px;top:auto;';
- if(p.charAt(1) == 'e') style += 'right:' + (m + plotOffset.right) + 'px;left:auto;';
- else if(p.charAt(1) == 'w') style += 'left:' + (m + plotOffset.left) + 'px;right:auto;';
- }
- else { // relative to the mouse
- if(p.charAt(0) == 'n') style += 'bottom:' + (m - plotOffset.top - y + this.canvasHeight) + 'px;top:auto;';
- else if(p.charAt(0) == 's') style += 'top:' + (m + plotOffset.top + y) + 'px;bottom:auto;';
- if(p.charAt(1) == 'e') style += 'left:' + (m + plotOffset.left + x) + 'px;right:auto;';
- else if(p.charAt(1) == 'w') style += 'right:' + (m - plotOffset.left - x + this.canvasWidth) + 'px;left:auto;';
- }
-
- mt.style.cssText = style;
- D.empty(mt);
- D.insert(mt, content);
- D.show(mt);
- }
- else {
- D.hide(mt);
- }
- },
-
- clip: function () {
-
- var
- ctx = this.ctx,
- o = this.plotOffset,
- w = this.canvasWidth,
- h = this.canvasHeight;
-
- if (flotr.isIE && flotr.isIE < 9) {
- // Clipping for excanvas :-(
- ctx.save();
- ctx.fillStyle = this.processColor(this.options.ieBackgroundColor);
- ctx.fillRect(0, 0, w, o.top);
- ctx.fillRect(0, 0, o.left, h);
- ctx.fillRect(0, h - o.bottom, w, o.bottom);
- ctx.fillRect(w - o.right, 0, o.right,h);
- ctx.restore();
- } else {
- ctx.clearRect(0, 0, w, o.top);
- ctx.clearRect(0, 0, o.left, h);
- ctx.clearRect(0, h - o.bottom, w, o.bottom);
- ctx.clearRect(w - o.right, 0, o.right,h);
- }
- },
-
- _initMembers: function() {
- this._handles = [];
- this.lastMousePos = {pageX: null, pageY: null };
- this.plotOffset = {left: 0, right: 0, top: 0, bottom: 0};
- this.ignoreClick = true;
- this.prevHit = null;
- },
-
- _initGraphTypes: function() {
- _.each(flotr.graphTypes, function(handler, graphType){
- this[graphType] = flotr.clone(handler);
- }, this);
- },
-
- _initEvents: function () {
-
- var
- el = this.el,
- touchendHandler, movement, touchend;
-
- if ('ontouchstart' in el) {
-
- touchendHandler = _.bind(function (e) {
- touchend = true;
- E.stopObserving(document, 'touchend', touchendHandler);
- E.fire(el, 'flotr:mouseup', [event, this]);
- this.multitouches = null;
-
- if (!movement) {
- this.clickHandler(e);
- }
- }, this);
-
- this.observe(this.overlay, 'touchstart', _.bind(function (e) {
- movement = false;
- touchend = false;
- this.ignoreClick = false;
-
- if (e.touches && e.touches.length > 1) {
- this.multitouches = e.touches;
- }
-
- E.fire(el, 'flotr:mousedown', [event, this]);
- this.observe(document, 'touchend', touchendHandler);
- }, this));
-
- this.observe(this.overlay, 'touchmove', _.bind(function (e) {
-
- var pos = this.getEventPosition(e);
-
- e.preventDefault();
-
- movement = true;
-
- if (this.multitouches || (e.touches && e.touches.length > 1)) {
- this.multitouches = e.touches;
- } else {
- if (!touchend) {
- E.fire(el, 'flotr:mousemove', [event, pos, this]);
- }
- }
- this.lastMousePos = pos;
- }, this));
-
- } else {
- this.
- observe(this.overlay, 'mousedown', _.bind(this.mouseDownHandler, this)).
- observe(el, 'mousemove', _.bind(this.mouseMoveHandler, this)).
- observe(this.overlay, 'click', _.bind(this.clickHandler, this)).
- observe(el, 'mouseout', function () {
- E.fire(el, 'flotr:mouseout');
- });
- }
- },
-
- /**
- * 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.
- */
- _initCanvas: function(){
- var el = this.el,
- o = this.options,
- children = el.children,
- removedChildren = [],
- child, i,
- size, style;
-
- // Empty the el
- for (i = children.length; i--;) {
- child = children[i];
- if (!this.canvas && child.className === 'flotr-canvas') {
- this.canvas = child;
- } else if (!this.overlay && child.className === 'flotr-overlay') {
- this.overlay = child;
- } else {
- removedChildren.push(child);
- }
- }
- for (i = removedChildren.length; i--;) {
- el.removeChild(removedChildren[i]);
- }
-
- D.setStyles(el, {position: 'relative'}); // For positioning labels and overlay.
- size = {};
- size.width = el.clientWidth;
- size.height = el.clientHeight;
-
- if(size.width <= 0 || size.height <= 0 || o.resolution <= 0){
- throw 'Invalid dimensions for plot, width = ' + size.width + ', height = ' + size.height + ', resolution = ' + o.resolution;
- }
-
- // Main canvas for drawing graph types
- this.canvas = getCanvas(this.canvas, 'canvas');
- // Overlay canvas for interactive features
- this.overlay = getCanvas(this.overlay, 'overlay');
- this.ctx = getContext(this.canvas);
- this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
- this.octx = getContext(this.overlay);
- this.octx.clearRect(0, 0, this.overlay.width, this.overlay.height);
- this.canvasHeight = size.height;
- this.canvasWidth = size.width;
- this.textEnabled = !!this.ctx.drawText || !!this.ctx.fillText; // Enable text functions
-
- function getCanvas(canvas, name){
- if(!canvas){
- canvas = D.create('canvas');
- if (typeof FlashCanvas != "undefined" && typeof canvas.getContext === 'function') {
- FlashCanvas.initElement(canvas);
- }
- canvas.className = 'flotr-'+name;
- canvas.style.cssText = 'position:absolute;left:0px;top:0px;';
- D.insert(el, canvas);
- }
- _.each(size, function(size, attribute){
- D.show(canvas);
- if (name == 'canvas' && canvas.getAttribute(attribute) === size) {
- return;
- }
- canvas.setAttribute(attribute, size * o.resolution);
- canvas.style[attribute] = size + 'px';
- });
- canvas.context_ = null; // Reset the ExCanvas context
- return canvas;
- }
-
- function getContext(canvas){
- if(window.G_vmlCanvasManager) window.G_vmlCanvasManager.initElement(canvas); // For ExCanvas
- var context = canvas.getContext('2d');
- if(!window.G_vmlCanvasManager) context.scale(o.resolution, o.resolution);
- return context;
- }
- },
-
- _initPlugins: function(){
- // TODO Should be moved to flotr and mixed in.
- _.each(flotr.plugins, function(plugin, name){
- _.each(plugin.callbacks, function(fn, c){
- this.observe(this.el, c, _.bind(fn, this));
- }, this);
- this[name] = flotr.clone(plugin);
- _.each(this[name], function(fn, p){
- if (_.isFunction(fn))
- this[name][p] = _.bind(fn, this);
- }, this);
- }, this);
- },
-
- /**
- * Sets options and initializes some variables and color specific values, used by the constructor.
- * @param {Object} opts - options object
- */
- _initOptions: function(opts){
- var options = flotr.clone(flotr.defaultOptions);
- options.x2axis = _.extend(_.clone(options.xaxis), options.x2axis);
- options.y2axis = _.extend(_.clone(options.yaxis), options.y2axis);
- this.options = flotr.merge(opts || {}, options);
-
- if (this.options.grid.minorVerticalLines === null &&
- this.options.xaxis.scaling === 'logarithmic') {
- this.options.grid.minorVerticalLines = true;
- }
- if (this.options.grid.minorHorizontalLines === null &&
- this.options.yaxis.scaling === 'logarithmic') {
- this.options.grid.minorHorizontalLines = true;
- }
-
- E.fire(this.el, 'flotr:afterinitoptions', [this]);
-
- this.axes = flotr.Axis.getAxes(this.options);
-
- // 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(_.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){
- s.color = colors[j++].toString();
- }else if(_.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] = _.extend(_.clone(this.options[t]), s[t]);
- }
- s.mouse = _.extend(_.clone(this.options.mouse), s.mouse);
-
- if (_.isUndefined(s.shadowSize)) s.shadowSize = this.options.shadowSize;
- }
- },
-
- _setEl: function(el) {
- if (!el) throw 'The target container doesn\'t exist';
- else if (el.graph instanceof Graph) el.graph.destroy();
- else if (!el.clientWidth) throw 'The target container must be visible';
-
- el.graph = this;
- this.el = el;
- }
-};
-
-Flotr.Graph = Graph;
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/Series.js b/addons/web_graph/static/lib/flotr2/js/Series.js
deleted file mode 100644
index e9a0c0fbeaa..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/Series.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Flotr Series Library
- */
-
-(function () {
-
-var
- _ = Flotr._;
-
-function Series (o) {
- _.extend(this, o);
-}
-
-Series.prototype = {
-
- getRange: function () {
-
- var
- data = this.data,
- length = data.length,
- xmin = Number.MAX_VALUE,
- ymin = Number.MAX_VALUE,
- xmax = -Number.MAX_VALUE,
- ymax = -Number.MAX_VALUE,
- xused = false,
- yused = false,
- x, y, i;
-
- if (length < 0 || this.hide) return false;
-
- for (i = 0; i < length; i++) {
- x = data[i][0];
- y = data[i][1];
- if (x < xmin) { xmin = x; xused = true; }
- if (x > xmax) { xmax = x; xused = true; }
- if (y < ymin) { ymin = y; yused = true; }
- if (y > ymax) { ymax = y; yused = true; }
- }
-
- return {
- xmin : xmin,
- xmax : xmax,
- ymin : ymin,
- ymax : ymax,
- xused : xused,
- yused : yused
- };
- }
-};
-
-_.extend(Series, {
- /**
- * 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 _.map(data, function(s){
- var series;
- if (s.data) {
- series = new Series();
- _.extend(series, s);
- } else {
- series = new Series({data:s});
- }
- return series;
- });
- }
-});
-
-Flotr.Series = Series;
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/Text.js b/addons/web_graph/static/lib/flotr2/js/Text.js
deleted file mode 100644
index f24cf7ac4bf..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/Text.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * Text Utilities
- */
-(function () {
-
-var
- F = Flotr,
- D = F.DOM,
- _ = F._,
-
-Text = function (o) {
- this.o = o;
-};
-
-Text.prototype = {
-
- dimensions : function (text, canvasStyle, htmlStyle, className) {
-
- if (!text) return { width : 0, height : 0 };
-
- return (this.o.html) ?
- this.html(text, this.o.element, htmlStyle, className) :
- this.canvas(text, canvasStyle);
- },
-
- canvas : function (text, style) {
-
- if (!this.o.textEnabled) return;
- style = style || {};
-
- var
- metrics = this.measureText(text, style),
- width = metrics.width,
- height = style.size || F.defaultOptions.fontSize,
- angle = style.angle || 0,
- cosAngle = Math.cos(angle),
- sinAngle = Math.sin(angle),
- widthPadding = 2,
- heightPadding = 6,
- bounds;
-
- bounds = {
- width: Math.abs(cosAngle * width) + Math.abs(sinAngle * height) + widthPadding,
- height: Math.abs(sinAngle * width) + Math.abs(cosAngle * height) + heightPadding
- };
-
- return bounds;
- },
-
- html : function (text, element, style, className) {
-
- var div = D.create('div');
-
- D.setStyles(div, { 'position' : 'absolute', 'top' : '-10000px' });
- D.insert(div, '<div style="'+style+'" class="'+className+' flotr-dummy-div">' + text + '</div>');
- D.insert(this.o.element, div);
-
- return D.size(div);
- },
-
- measureText : function (text, style) {
-
- var
- context = this.o.ctx,
- metrics;
-
- if (!context.fillText || (F.isIphone && context.measure)) {
- return { width : context.measure(text, style)};
- }
-
- style = _.extend({
- size: F.defaultOptions.fontSize,
- weight: 1,
- angle: 0
- }, style);
-
- context.save();
- context.font = (style.weight > 1 ? "bold " : "") + (style.size*1.3) + "px sans-serif";
- metrics = context.measureText(text);
- context.restore();
-
- return metrics;
- }
-};
-
-Flotr.Text = Text;
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/crosshair.js b/addons/web_graph/static/lib/flotr2/js/plugins/crosshair.js
deleted file mode 100644
index 611ebf85800..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/crosshair.js
+++ /dev/null
@@ -1,84 +0,0 @@
-(function () {
-
-var D = Flotr.DOM;
-
-Flotr.addPlugin('crosshair', {
- options: {
- mode: null, // => one of null, 'x', 'y' or 'xy'
- color: '#FF0000', // => crosshair color
- hideCursor: true // => hide the cursor when the crosshair is shown
- },
- callbacks: {
- 'flotr:mousemove': function(e, pos) {
- if (this.options.crosshair.mode) {
- this.crosshair.clearCrosshair();
- this.crosshair.drawCrosshair(pos);
- }
- }
- },
- /**
- * Draws the selection box.
- */
- drawCrosshair: function(pos) {
- var octx = this.octx,
- options = this.options.crosshair,
- 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;
- D.removeClass(this.el, 'flotr-crosshair');
- return;
- }
-
- if (options.hideCursor) {
- this.el.style.cursor = 'none';
- D.addClass(this.el, 'flotr-crosshair');
- }
-
- octx.save();
- octx.strokeStyle = options.color;
- octx.lineWidth = 1;
- octx.beginPath();
-
- if (options.mode.indexOf('x') != -1) {
- octx.moveTo(x, plotOffset.top);
- octx.lineTo(x, plotOffset.top + this.plotHeight);
- }
-
- if (options.mode.indexOf('y') != -1) {
- octx.moveTo(plotOffset.left, y);
- octx.lineTo(plotOffset.left + this.plotWidth, y);
- }
-
- octx.stroke();
- octx.restore();
- },
- /**
- * Removes the selection box from the overlay canvas.
- */
- clearCrosshair: function() {
-
- var
- plotOffset = this.plotOffset,
- position = this.lastMousePos,
- context = this.octx;
-
- if (position) {
- context.clearRect(
- position.relX + plotOffset.left,
- plotOffset.top,
- 1,
- this.plotHeight + 1
- );
- context.clearRect(
- plotOffset.left,
- position.relY + plotOffset.top,
- this.plotWidth + 1,
- 1
- );
- }
- }
-});
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/download.js b/addons/web_graph/static/lib/flotr2/js/plugins/download.js
deleted file mode 100644
index 5d585325be9..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/download.js
+++ /dev/null
@@ -1,51 +0,0 @@
-(function() {
-
-var
- D = Flotr.DOM,
- _ = Flotr._;
-
-function getImage (type, canvas, width, height) {
-
- // TODO add scaling for w / h
- var
- mime = 'image/'+type,
- data = canvas.toDataURL(mime),
- image = new Image();
- image.src = data;
- return image;
-}
-
-Flotr.addPlugin('download', {
-
- saveImage: function (type, width, height, replaceCanvas) {
- var image = null;
- if (Flotr.isIE && Flotr.isIE < 9) {
- image = '<html><body>'+this.canvas.firstChild.innerHTML+'</body></html>';
- return window.open().document.write(image);
- }
-
- if (type !== 'jpeg' && type !== 'png') return;
-
- image = getImage(type, this.canvas, width, height);
-
- if (_.isElement(image) && replaceCanvas) {
- this.download.restoreCanvas();
- D.hide(this.canvas);
- D.hide(this.overlay);
- D.setStyles({position: 'absolute'});
- D.insert(this.el, image);
- this.saveImageElement = image;
- } else {
- return window.open(image.src);
- }
- },
-
- restoreCanvas: function() {
- D.show(this.canvas);
- D.show(this.overlay);
- if (this.saveImageElement) this.el.removeChild(this.saveImageElement);
- this.saveImageElement = null;
- }
-});
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/grid.js b/addons/web_graph/static/lib/flotr2/js/plugins/grid.js
deleted file mode 100644
index ab90d8d591a..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/grid.js
+++ /dev/null
@@ -1,208 +0,0 @@
-(function () {
-
-var E = Flotr.EventAdapter,
- _ = Flotr._;
-
-Flotr.addPlugin('graphGrid', {
-
- callbacks: {
- 'flotr:beforedraw' : function () {
- this.graphGrid.drawGrid();
- },
- 'flotr:afterdraw' : function () {
- this.graphGrid.drawOutline();
- }
- },
-
- drawGrid: function(){
-
- var
- ctx = this.ctx,
- options = this.options,
- grid = options.grid,
- verticalLines = grid.verticalLines,
- horizontalLines = grid.horizontalLines,
- minorVerticalLines = grid.minorVerticalLines,
- minorHorizontalLines = grid.minorHorizontalLines,
- plotHeight = this.plotHeight,
- plotWidth = this.plotWidth,
- a, v, i, j;
-
- if(verticalLines || minorVerticalLines ||
- horizontalLines || minorHorizontalLines){
- E.fire(this.el, 'flotr:beforegrid', [this.axes.x, this.axes.y, options, this]);
- }
- ctx.save();
- ctx.lineWidth = 1;
- ctx.strokeStyle = grid.tickColor;
-
- function circularHorizontalTicks (ticks) {
- for(i = 0; i < ticks.length; ++i){
- var ratio = ticks[i].v / a.max;
- for(j = 0; j <= sides; ++j){
- ctx[j === 0 ? 'moveTo' : 'lineTo'](
- Math.cos(j*coeff+angle)*radius*ratio,
- Math.sin(j*coeff+angle)*radius*ratio
- );
- }
- }
- }
- function drawGridLines (ticks, callback) {
- _.each(_.pluck(ticks, 'v'), function(v){
- // Don't show lines on upper and lower bounds.
- if ((v <= a.min || v >= a.max) ||
- (v == a.min || v == a.max) && grid.outlineWidth)
- return;
- callback(Math.floor(a.d2p(v)) + ctx.lineWidth/2);
- });
- }
- function drawVerticalLines (x) {
- ctx.moveTo(x, 0);
- ctx.lineTo(x, plotHeight);
- }
- function drawHorizontalLines (y) {
- ctx.moveTo(0, y);
- ctx.lineTo(plotWidth, y);
- }
-
- if (grid.circular) {
- ctx.translate(this.plotOffset.left+plotWidth/2, this.plotOffset.top+plotHeight/2);
- var radius = Math.min(plotHeight, plotWidth)*options.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();
-
- a = this.axes.y;
-
- if(horizontalLines){
- circularHorizontalTicks(a.ticks);
- }
- if(minorHorizontalLines){
- circularHorizontalTicks(a.minorTicks);
- }
-
- if(verticalLines){
- _.times(sides, function(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(grid.backgroundColor){
- ctx.fillStyle = this.processColor(grid.backgroundColor, {x1: 0, y1: 0, x2: plotWidth, y2: plotHeight});
- ctx.fillRect(0, 0, plotWidth, plotHeight);
- }
-
- ctx.beginPath();
-
- a = this.axes.x;
- if (verticalLines) drawGridLines(a.ticks, drawVerticalLines);
- if (minorVerticalLines) drawGridLines(a.minorTicks, drawVerticalLines);
-
- a = this.axes.y;
- if (horizontalLines) drawGridLines(a.ticks, drawHorizontalLines);
- if (minorHorizontalLines) drawGridLines(a.minorTicks, drawHorizontalLines);
-
- ctx.stroke();
- }
-
- ctx.restore();
- if(verticalLines || minorVerticalLines ||
- horizontalLines || minorHorizontalLines){
- E.fire(this.el, 'flotr:aftergrid', [this.axes.x, this.axes.y, options, this]);
- }
- },
-
- drawOutline: function(){
- var
- that = this,
- options = that.options,
- grid = options.grid,
- outline = grid.outline,
- ctx = that.ctx,
- backgroundImage = grid.backgroundImage,
- plotOffset = that.plotOffset,
- leftOffset = plotOffset.left,
- topOffset = plotOffset.top,
- plotWidth = that.plotWidth,
- plotHeight = that.plotHeight,
- v, img, src, left, top, globalAlpha;
-
- if (!grid.outlineWidth) return;
-
- ctx.save();
-
- if (grid.circular) {
- ctx.translate(leftOffset + plotWidth / 2, topOffset + plotHeight / 2);
- var radius = Math.min(plotHeight, plotWidth) * options.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 = grid.outlineWidth;
- ctx.strokeStyle = grid.color;
- ctx.lineJoin = 'round';
-
- for(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(leftOffset, topOffset);
-
- // Draw axis/grid border.
- var lw = grid.outlineWidth,
- orig = 0.5-lw+((lw+1)%2/2),
- lineTo = 'lineTo',
- moveTo = 'moveTo';
- ctx.lineWidth = lw;
- ctx.strokeStyle = grid.color;
- ctx.lineJoin = 'miter';
- ctx.beginPath();
- ctx.moveTo(orig, orig);
- plotWidth = plotWidth - (lw / 2) % 1;
- plotHeight = plotHeight + lw / 2;
- ctx[outline.indexOf('n') !== -1 ? lineTo : moveTo](plotWidth, orig);
- ctx[outline.indexOf('e') !== -1 ? lineTo : moveTo](plotWidth, plotHeight);
- ctx[outline.indexOf('s') !== -1 ? lineTo : moveTo](orig, plotHeight);
- ctx[outline.indexOf('w') !== -1 ? lineTo : moveTo](orig, orig);
- ctx.stroke();
- ctx.closePath();
- }
-
- ctx.restore();
-
- if (backgroundImage) {
-
- src = backgroundImage.src || backgroundImage;
- left = (parseInt(backgroundImage.left, 10) || 0) + plotOffset.left;
- top = (parseInt(backgroundImage.top, 10) || 0) + plotOffset.top;
- img = new Image();
-
- img.onload = function() {
- ctx.save();
- if (backgroundImage.alpha) ctx.globalAlpha = backgroundImage.alpha;
- ctx.globalCompositeOperation = 'destination-over';
- ctx.drawImage(img, 0, 0, img.width, img.height, left, top, plotWidth, plotHeight);
- ctx.restore();
- };
-
- img.src = src;
- }
- }
-});
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/handles.js b/addons/web_graph/static/lib/flotr2/js/plugins/handles.js
deleted file mode 100644
index 92fd3247fdf..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/handles.js
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * Selection Handles Plugin
- *
- * Depends upon options.selection.mode
- *
- * Options
- * show - True enables the handles plugin.
- * drag - Left and Right drag handles
- * scroll - Scrolling handle
- */
-(function () {
-
-var D = Flotr.DOM;
-
-Flotr.addPlugin('handles', {
-
- options: {
- show: false,
- drag: true,
- scroll: true
- },
-
- callbacks: {
- 'flotr:afterinit': init,
- 'flotr:select': handleSelect,
- 'flotr:mousedown': reset,
- 'flotr:mousemove': mouseMoveHandler
- }
-
-});
-
-
-function init() {
-
- var
- options = this.options,
- handles = this.handles,
- el = this.el,
- scroll, left, right, container;
-
- if (!options.selection.mode || !options.handles.show || 'ontouchstart' in el) return;
-
- handles.initialized = true;
-
- container = D.node('<div class="flotr-handles"></div>');
- options = options.handles;
-
- // Drag handles
- if (options.drag) {
- right = D.node('<div class="flotr-handles-handle flotr-handles-drag flotr-handles-right"></div>');
- left = D.node('<div class="flotr-handles-handle flotr-handles-drag flotr-handles-left"></div>');
- D.insert(container, right);
- D.insert(container, left);
- D.hide(left);
- D.hide(right);
- handles.left = left;
- handles.right = right;
-
- this.observe(left, 'mousedown', function () {
- handles.moveHandler = leftMoveHandler;
- });
- this.observe(right, 'mousedown', function () {
- handles.moveHandler = rightMoveHandler;
- });
- }
-
- // Scroll handle
- if (options.scroll) {
- scroll = D.node('<div class="flotr-handles-handle flotr-handles-scroll"></div>');
- D.insert(container, scroll);
- D.hide(scroll);
- handles.scroll = scroll;
- this.observe(scroll, 'mousedown', function () {
- handles.moveHandler = scrollMoveHandler;
- });
- }
-
- this.observe(document, 'mouseup', function() {
- handles.moveHandler = null;
- });
-
- D.insert(el, container);
-}
-
-
-function handleSelect(selection) {
-
- if (!this.handles.initialized) return;
-
- var
- handles = this.handles,
- options = this.options.handles,
- left = handles.left,
- right = handles.right,
- scroll = handles.scroll;
-
- if (options) {
- if (options.drag) {
- positionDrag(this, left, selection.x1);
- positionDrag(this, right, selection.x2);
- }
-
- if (options.scroll) {
- positionScroll(
- this,
- scroll,
- selection.x1,
- selection.x2
- );
- }
- }
-}
-
-function positionDrag(graph, handle, x) {
-
- D.show(handle);
-
- var size = D.size(handle),
- l = Math.round(graph.axes.x.d2p(x) - size.width / 2),
- t = (graph.plotHeight - size.height) / 2;
-
- D.setStyles(handle, {
- 'left' : l+'px',
- 'top' : t+'px'
- });
-}
-
-function positionScroll(graph, handle, x1, x2) {
-
- D.show(handle);
-
- var size = D.size(handle),
- l = Math.round(graph.axes.x.d2p(x1)),
- t = (graph.plotHeight) - size.height / 2,
- w = (graph.axes.x.d2p(x2) - graph.axes.x.d2p(x1));
-
- D.setStyles(handle, {
- 'left' : l+'px',
- 'top' : t+'px',
- 'width': w+'px'
- });
-}
-
-function reset() {
-
- if (!this.handles.initialized) return;
-
- var
- handles = this.handles;
- if (handles) {
- D.hide(handles.left);
- D.hide(handles.right);
- D.hide(handles.scroll);
- }
-}
-
-function mouseMoveHandler(e, position) {
-
- if (!this.handles.initialized) return;
- if (!this.handles.moveHandler) return;
-
- var
- delta = position.dX,
- selection = this.selection.selection,
- area = this.selection.getArea(),
- handles = this.handles;
-
- handles.moveHandler(area, delta);
- checkSwap(area, handles);
-
- this.selection.setSelection(area);
-}
-
-function checkSwap (area, handles) {
- var moveHandler = handles.moveHandler;
- if (area.x1 > area.x2) {
- if (moveHandler == leftMoveHandler) {
- moveHandler = rightMoveHandler;
- } else if (moveHandler == rightMoveHandler) {
- moveHandler = leftMoveHandler;
- }
- handles.moveHandler = moveHandler;
- }
-}
-
-function leftMoveHandler(area, delta) {
- area.x1 += delta;
-}
-
-function rightMoveHandler(area, delta) {
- area.x2 += delta;
-}
-
-function scrollMoveHandler(area, delta) {
- area.x1 += delta;
- area.x2 += delta;
-}
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/hit.js b/addons/web_graph/static/lib/flotr2/js/plugins/hit.js
deleted file mode 100644
index eeff570df35..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/hit.js
+++ /dev/null
@@ -1,337 +0,0 @@
-(function () {
-
-var
- D = Flotr.DOM,
- _ = Flotr._,
- flotr = Flotr,
- S_MOUSETRACK = '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;';
-
-Flotr.addPlugin('hit', {
- callbacks: {
- 'flotr:mousemove': function(e, pos) {
- this.hit.track(pos);
- },
- 'flotr:click': function(pos) {
- this.hit.track(pos);
- },
- 'flotr:mouseout': function() {
- this.hit.clearHit();
- }
- },
- track : function (pos) {
- if (this.options.mouse.track || _.any(this.series, function(s){return s.mouse && s.mouse.track;})) {
- this.hit.hit(pos);
- }
- },
- /**
- * Try a method on a graph type. If the method exists, execute it.
- * @param {Object} series
- * @param {String} method Method name.
- * @param {Array} args Arguments applied to method.
- * @return executed successfully or failed.
- */
- executeOnType: function(s, method, args){
- var
- success = false,
- options;
-
- if (!_.isArray(s)) s = [s];
-
- function e(s, index) {
- _.each(_.keys(flotr.graphTypes), function (type) {
- if (s[type] && s[type].show && this[type][method]) {
- options = this.getOptions(s, type);
-
- options.fill = !!s.mouse.fillColor;
- options.fillStyle = this.processColor(s.mouse.fillColor || '#ffffff', {opacity: s.mouse.fillOpacity});
- options.color = s.mouse.lineColor;
- options.context = this.octx;
- options.index = index;
-
- if (args) options.args = args;
- this[type][method].call(this[type], options);
- success = true;
- }
- }, this);
- }
- _.each(s, e, this);
-
- return success;
- },
- /**
- * Updates the mouse tracking point on the overlay.
- */
- drawHit: function(n){
- var octx = this.octx,
- s = n.series;
-
- if (s.mouse.lineColor) {
- octx.save();
- octx.lineWidth = (s.points ? s.points.lineWidth : 1);
- octx.strokeStyle = s.mouse.lineColor;
- octx.fillStyle = this.processColor(s.mouse.fillColor || '#ffffff', {opacity: s.mouse.fillOpacity});
- octx.translate(this.plotOffset.left, this.plotOffset.top);
-
- if (!this.hit.executeOnType(s, 'drawHit', n)) {
- var xa = n.xaxis,
- ya = n.yaxis;
-
- octx.beginPath();
- // TODO fix this (points) should move to general testable graph mixin
- octx.arc(xa.d2p(n.x), ya.d2p(n.y), s.points.radius || s.mouse.radius, 0, 2 * Math.PI, true);
- octx.fill();
- octx.stroke();
- octx.closePath();
- }
- octx.restore();
- }
- this.prevHit = n;
- },
- /**
- * Removes the mouse tracking point from the overlay.
- */
- clearHit: function(){
- var prev = this.prevHit,
- octx = this.octx,
- plotOffset = this.plotOffset;
- octx.save();
- octx.translate(plotOffset.left, plotOffset.top);
- if (prev) {
- if (!this.hit.executeOnType(prev.series, 'clearHit', this.prevHit)) {
- // TODO fix this (points) should move to general testable graph mixin
- var
- s = prev.series,
- lw = (s.points ? s.points.lineWidth : 1);
- offset = (s.points.radius || s.mouse.radius) + lw;
- octx.clearRect(
- prev.xaxis.d2p(prev.x) - offset,
- prev.yaxis.d2p(prev.y) - offset,
- offset*2,
- offset*2
- );
- }
- D.hide(this.mouseTrack);
- this.prevHit = null;
- }
- octx.restore();
- },
- /**
- * 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
- options = this.options,
- prevHit = this.prevHit,
- closest, sensibility, dataIndex, seriesIndex, series, value, xaxis, yaxis;
-
- if (this.series.length === 0) return;
-
- // Nearest data element.
- // dist, x, y, relX, relY, absX, absY, sAngle, eAngle, fraction, mouse,
- // xaxis, yaxis, series, index, seriesIndex
- n = {
- relX : mouse.relX,
- relY : mouse.relY,
- absX : mouse.absX,
- absY : mouse.absY
- };
-
- if (options.mouse.trackY &&
- !options.mouse.trackAll &&
- this.hit.executeOnType(this.series, 'hit', [mouse, n]))
- {
-
- if (!_.isUndefined(n.seriesIndex)) {
- series = this.series[n.seriesIndex];
- n.series = series;
- n.mouse = series.mouse;
- n.xaxis = series.xaxis;
- n.yaxis = series.yaxis;
- }
- } else {
-
- closest = this.hit.closest(mouse);
-
- if (closest) {
-
- closest = options.mouse.trackY ? closest.point : closest.x;
- seriesIndex = closest.seriesIndex;
- series = this.series[seriesIndex];
- xaxis = series.xaxis;
- yaxis = series.yaxis;
- sensibility = 2 * series.mouse.sensibility;
-
- if
- (options.mouse.trackAll ||
- (closest.distanceX < sensibility / xaxis.scale &&
- (!options.mouse.trackY || closest.distanceY < sensibility / yaxis.scale)))
- {
- n.series = series;
- n.xaxis = series.xaxis;
- n.yaxis = series.yaxis;
- n.mouse = series.mouse;
- n.x = closest.x;
- n.y = closest.y;
- n.dist = closest.distance;
- n.index = closest.dataIndex;
- n.seriesIndex = seriesIndex;
- }
- }
- }
-
- if (!prevHit || (prevHit.index !== n.index || prevHit.seriesIndex !== n.seriesIndex)) {
- this.hit.clearHit();
- if (n.series && n.mouse && n.mouse.track) {
- this.hit.drawMouseTrack(n);
- this.hit.drawHit(n);
- Flotr.EventAdapter.fire(this.el, 'flotr:hit', [n, this]);
- }
- }
- },
-
- closest : function (mouse) {
-
- var
- series = this.series,
- options = this.options,
- mouseX = mouse.x,
- mouseY = mouse.y,
- compare = Number.MAX_VALUE,
- compareX = Number.MAX_VALUE,
- closest = {},
- closestX = {},
- check = false,
- serie, data,
- distance, distanceX, distanceY,
- x, y, i, j;
-
- function setClosest (o) {
- o.distance = distance;
- o.distanceX = distanceX;
- o.distanceY = distanceY;
- o.seriesIndex = i;
- o.dataIndex = j;
- o.x = x;
- o.y = y;
- }
-
- for (i = 0; i < series.length; i++) {
-
- serie = series[i];
- data = serie.data;
-
- if (data.length) check = true;
-
- for (j = data.length; j--;) {
-
- x = data[j][0];
- y = data[j][1];
-
- if (x === null || y === null) continue;
-
- // don't check if the point isn't visible in the current range
- if (x < serie.xaxis.min || x > serie.xaxis.max) continue;
-
- distanceX = Math.abs(x - mouseX);
- distanceY = Math.abs(y - mouseY);
-
- // Skip square root for speed
- distance = distanceX * distanceX + distanceY * distanceY;
-
- if (distance < compare) {
- compare = distance;
- setClosest(closest);
- }
-
- if (distanceX < compareX) {
- compareX = distanceX;
- setClosest(closestX);
- }
- }
- }
-
- return check ? {
- point : closest,
- x : closestX
- } : false;
- },
-
- drawMouseTrack : function (n) {
-
- var
- pos = '',
- s = n.series,
- p = n.mouse.position,
- m = n.mouse.margin,
- elStyle = S_MOUSETRACK,
- mouseTrack = this.mouseTrack,
- plotOffset = this.plotOffset,
- left = plotOffset.left,
- right = plotOffset.right,
- bottom = plotOffset.bottom,
- top = plotOffset.top,
- decimals = n.mouse.trackDecimals,
- options = this.options;
-
- // Create
- if (!mouseTrack) {
- mouseTrack = D.node('<div class="flotr-mouse-value"></div>');
- this.mouseTrack = mouseTrack;
- D.insert(this.el, mouseTrack);
- }
-
- if (!n.mouse.relative) { // absolute to the canvas
-
- if (p.charAt(0) == 'n') pos += 'top:' + (m + top) + 'px;bottom:auto;';
- else if (p.charAt(0) == 's') pos += 'bottom:' + (m + bottom) + 'px;top:auto;';
- if (p.charAt(1) == 'e') pos += 'right:' + (m + right) + 'px;left:auto;';
- else if (p.charAt(1) == 'w') pos += 'left:' + (m + left) + 'px;right:auto;';
-
- // Bars
- } else if (s.bars.show) {
- pos += 'bottom:' + (m - top - n.yaxis.d2p(n.y/2) + this.canvasHeight) + 'px;top:auto;';
- pos += 'left:' + (m + left + n.xaxis.d2p(n.x - options.bars.barWidth/2)) + 'px;right:auto;';
-
- // Pie
- } else if (s.pie.show) {
- var center = {
- x: (this.plotWidth)/2,
- y: (this.plotHeight)/2
- },
- radius = (Math.min(this.canvasWidth, this.canvasHeight) * s.pie.sizeRatio) / 2,
- bisection = n.sAngle<n.eAngle ? (n.sAngle + n.eAngle) / 2: (n.sAngle + n.eAngle + 2* Math.PI) / 2;
-
- pos += 'bottom:' + (m - top - center.y - Math.sin(bisection) * radius/2 + this.canvasHeight) + 'px;top:auto;';
- pos += 'left:' + (m + left + center.x + Math.cos(bisection) * radius/2) + 'px;right:auto;';
-
- // Default
- } else {
- if (p.charAt(0) == 'n') pos += 'bottom:' + (m - top - n.yaxis.d2p(n.y) + this.canvasHeight) + 'px;top:auto;';
- else if (p.charAt(0) == 's') pos += 'top:' + (m + top + n.yaxis.d2p(n.y)) + 'px;bottom:auto;';
- if (p.charAt(1) == 'e') pos += 'left:' + (m + left + n.xaxis.d2p(n.x)) + 'px;right:auto;';
- else if (p.charAt(1) == 'w') pos += 'right:' + (m - left - n.xaxis.d2p(n.x) + this.canvasWidth) + 'px;left:auto;';
- }
-
- elStyle += pos;
- mouseTrack.style.cssText = elStyle;
-
- if (!decimals || decimals < 0) decimals = 0;
-
- mouseTrack.innerHTML = n.mouse.trackFormatter({
- x: n.x.toFixed(decimals),
- y: n.y.toFixed(decimals),
- series: n.series,
- index: n.index,
- nearest: n,
- fraction: n.fraction
- });
-
- D.show(mouseTrack);
- }
-
-});
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/labels.js b/addons/web_graph/static/lib/flotr2/js/plugins/labels.js
deleted file mode 100644
index 8e016c8fa03..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/labels.js
+++ /dev/null
@@ -1,227 +0,0 @@
-(function () {
-
-var D = Flotr.DOM;
-
-Flotr.addPlugin('labels', {
-
- callbacks : {
- 'flotr:afterdraw' : function () {
- this.labels.draw();
- }
- },
-
- draw: function(){
- // Construct fixed width label boxes, which can be styled easily.
- var
- axis, tick, left, top, xBoxWidth,
- radius, sides, coeff, angle,
- div, i, html = '',
- noLabels = 0,
- options = this.options,
- ctx = this.ctx,
- a = this.axes,
- style = { size: options.fontSize };
-
- 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);
-
- radius = this.plotHeight * options.radar.radiusRatio / 2 + options.fontSize;
- sides = this.axes.x.ticks.length;
- coeff = 2 * (Math.PI / sides);
- angle = -Math.PI / 2;
-
- drawLabelCircular(this, a.x, false);
- drawLabelCircular(this, a.x, true);
- drawLabelCircular(this, a.y, false);
- drawLabelCircular(this, a.y, true);
- ctx.restore();
- }
-
- if (!options.HtmlText && this.textEnabled) {
- drawLabelNoHtmlText(this, a.x, 'center', 'top');
- drawLabelNoHtmlText(this, a.x2, 'center', 'bottom');
- drawLabelNoHtmlText(this, a.y, 'right', 'middle');
- drawLabelNoHtmlText(this, a.y2, 'left', 'middle');
-
- } else if ((
- a.x.options.showLabels ||
- a.x2.options.showLabels ||
- a.y.options.showLabels ||
- a.y2.options.showLabels) &&
- !options.grid.circular
- ) {
-
- html = '';
-
- drawLabelHtml(this, a.x);
- drawLabelHtml(this, a.x2);
- drawLabelHtml(this, a.y);
- drawLabelHtml(this, a.y2);
-
- ctx.stroke();
- ctx.restore();
- div = D.create('div');
- D.setStyles(div, {
- fontSize: 'smaller',
- color: options.grid.color
- });
- div.className = 'flotr-labels';
- D.insert(this.el, div);
- D.insert(div, html);
- }
-
- function drawLabelCircular (graph, axis, minorTicks) {
- var
- ticks = minorTicks ? axis.minorTicks : axis.ticks,
- isX = axis.orientation === 1,
- isFirst = axis.n === 1,
- style, offset;
-
- style = {
- color : axis.options.color || options.grid.color,
- angle : Flotr.toRad(axis.options.labelsAngle),
- textBaseline : 'middle'
- };
-
- for (i = 0; i < ticks.length &&
- (minorTicks ? axis.options.showMinorLabels : axis.options.showLabels); ++i){
- tick = ticks[i];
- tick.label += '';
- if (!tick.label || !tick.label.length) { continue; }
-
- x = Math.cos(i * coeff + angle) * radius;
- y = Math.sin(i * coeff + angle) * radius;
-
- style.textAlign = isX ? (Math.abs(x) < 0.1 ? 'center' : (x < 0 ? 'right' : 'left')) : 'left';
-
- Flotr.drawText(
- ctx, tick.label,
- isX ? x : 3,
- isX ? y : -(axis.ticks[i].v / axis.max) * (radius - options.fontSize),
- style
- );
- }
- }
-
- function drawLabelNoHtmlText (graph, axis, textAlign, textBaseline) {
- var
- isX = axis.orientation === 1,
- isFirst = axis.n === 1,
- style, offset;
-
- style = {
- color : axis.options.color || options.grid.color,
- textAlign : textAlign,
- textBaseline : textBaseline,
- angle : Flotr.toRad(axis.options.labelsAngle)
- };
- style = Flotr.getBestTextAlign(style.angle, style);
-
- for (i = 0; i < axis.ticks.length && continueShowingLabels(axis); ++i) {
-
- tick = axis.ticks[i];
- if (!tick.label || !tick.label.length) { continue; }
-
- offset = axis.d2p(tick.v);
- if (offset < 0 ||
- offset > (isX ? graph.plotWidth : graph.plotHeight)) { continue; }
-
- Flotr.drawText(
- ctx, tick.label,
- leftOffset(graph, isX, isFirst, offset),
- topOffset(graph, isX, isFirst, offset),
- style
- );
-
- // Only draw on axis y2
- if (!isX && !isFirst) {
- ctx.save();
- ctx.strokeStyle = style.color;
- ctx.beginPath();
- ctx.moveTo(graph.plotOffset.left + graph.plotWidth - 8, graph.plotOffset.top + axis.d2p(tick.v));
- ctx.lineTo(graph.plotOffset.left + graph.plotWidth, graph.plotOffset.top + axis.d2p(tick.v));
- ctx.stroke();
- ctx.restore();
- }
- }
-
- function continueShowingLabels (axis) {
- return axis.options.showLabels && axis.used;
- }
- function leftOffset (graph, isX, isFirst, offset) {
- return graph.plotOffset.left +
- (isX ? offset :
- (isFirst ?
- -options.grid.labelMargin :
- options.grid.labelMargin + graph.plotWidth));
- }
- function topOffset (graph, isX, isFirst, offset) {
- return graph.plotOffset.top +
- (isX ? options.grid.labelMargin : offset) +
- ((isX && isFirst) ? graph.plotHeight : 0);
- }
- }
-
- function drawLabelHtml (graph, axis) {
- var
- isX = axis.orientation === 1,
- isFirst = axis.n === 1,
- name = '',
- left, style, top,
- offset = graph.plotOffset;
-
- if (!isX && !isFirst) {
- ctx.save();
- ctx.strokeStyle = axis.options.color || options.grid.color;
- ctx.beginPath();
- }
-
- if (axis.options.showLabels && (isFirst ? true : axis.used)) {
- for (i = 0; i < axis.ticks.length; ++i) {
- tick = axis.ticks[i];
- if (!tick.label || !tick.label.length ||
- ((isX ? offset.left : offset.top) + axis.d2p(tick.v) < 0) ||
- ((isX ? offset.left : offset.top) + axis.d2p(tick.v) > (isX ? graph.canvasWidth : graph.canvasHeight))) {
- continue;
- }
- top = offset.top +
- (isX ?
- ((isFirst ? 1 : -1 ) * (graph.plotHeight + options.grid.labelMargin)) :
- axis.d2p(tick.v) - axis.maxLabel.height / 2);
- left = isX ? (offset.left + axis.d2p(tick.v) - xBoxWidth / 2) : 0;
-
- name = '';
- if (i === 0) {
- name = ' first';
- } else if (i === axis.ticks.length - 1) {
- name = ' last';
- }
- name += isX ? ' flotr-grid-label-x' : ' flotr-grid-label-y';
-
- html += [
- '<div style="position:absolute; text-align:' + (isX ? 'center' : 'right') + '; ',
- 'top:' + top + 'px; ',
- ((!isX && !isFirst) ? 'right:' : 'left:') + left + 'px; ',
- 'width:' + (isX ? xBoxWidth : ((isFirst ? offset.left : offset.right) - options.grid.labelMargin)) + 'px; ',
- axis.options.color ? ('color:' + axis.options.color + '; ') : ' ',
- '" class="flotr-grid-label' + name + '">' + tick.label + '</div>'
- ].join(' ');
-
- if (!isX && !isFirst) {
- ctx.moveTo(offset.left + graph.plotWidth - 8, offset.top + axis.d2p(tick.v));
- ctx.lineTo(offset.left + graph.plotWidth, offset.top + axis.d2p(tick.v));
- }
- }
- }
- }
- }
-
-});
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/legend.js b/addons/web_graph/static/lib/flotr2/js/plugins/legend.js
deleted file mode 100644
index d130cb5e90b..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/legend.js
+++ /dev/null
@@ -1,179 +0,0 @@
-(function () {
-
-var
- D = Flotr.DOM,
- _ = Flotr._;
-
-Flotr.addPlugin('legend', {
- options: {
- 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,
- labelBoxOpacity: 0.4,
- 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
- },
- callbacks: {
- 'flotr:afterinit': function() {
- this.legend.insertLegend();
- }
- },
- /**
- * 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,
- itemCount = _.filter(series, function(s) {return (s.label && !s.hide);}).length,
- p = legend.position,
- m = legend.margin,
- i, label, color;
-
- if (itemCount) {
- if (!options.HtmlText && this.textEnabled && !legend.container) {
- var style = {
- size: options.fontSize*1.1,
- color: options.grid.color
- };
-
- var 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;
- label = legend.labelFormatter(series[i].label);
- labelMaxWidth = Math.max(labelMaxWidth, this._text.measureText(label, style).width);
- }
-
- var legendWidth = Math.round(lbw + lbm*3 + labelMaxWidth),
- legendHeight = Math.round(itemCount*(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
- color = this.processColor(legend.backgroundColor || 'rgb(240,240,240)', {opacity: legend.backgroundOpacity || 0.1});
-
- ctx.fillStyle = color;
- ctx.fillRect(offsetX, offsetY, legendWidth, legendHeight);
- ctx.strokeStyle = 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;
- 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
- Flotr.drawText(ctx, label, x + lbw + lbm, y + lbh, style);
-
- y += lbh + lbm;
- }
- }
- else {
- for(i = 0; i < series.length; ++i){
- if(!series[i].label || series[i].hide) continue;
-
- if(i % legend.noColumns === 0){
- fragments.push(rowStarted ? '</tr><tr>' : '<tr>');
- rowStarted = true;
- }
-
- // @TODO remove requirement on bars
- var s = series[i],
- boxWidth = legend.labelBoxWidth,
- boxHeight = legend.labelBoxHeight,
- opacityValue = (s.bars ? s.bars.fillOpacity : legend.labelBoxOpacity),
- opacity = 'opacity:' + opacityValue + ';filter:alpha(opacity=' + opacityValue*100 + ');';
-
- label = legend.labelFormatter(s.label);
- color = 'background-color:' + ((s.bars && s.bars.show && s.bars.fillColor && s.bars.fill) ? s.bars.fillColor : s.color) + ';';
-
- fragments.push(
- '<td class="flotr-legend-color-box">',
- '<div style="border:1px solid ', legend.labelBoxBorderColor, ';padding:1px">',
- '<div style="width:', (boxWidth-1), 'px;height:', (boxHeight-1), 'px;border:1px solid ', series[i].color, '">', // Border
- '<div style="width:', boxWidth, 'px;height:', boxHeight, 'px;', 'opacity:.4;', color, '"></div>', // Background
- '</div>',
- '</div>',
- '</td>',
- '<td class="flotr-legend-label">', label, '</td>'
- );
- }
- if(rowStarted) fragments.push('</tr>');
-
- if(fragments.length > 0){
- var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join('') + '</table>';
- if(legend.container){
- D.insert(legend.container, table);
- }
- else {
- var styles = {position: 'absolute', 'z-index': 2};
-
- if(p.charAt(0) == 'n') { styles.top = (m + plotOffset.top) + 'px'; styles.bottom = 'auto'; }
- else if(p.charAt(0) == 's') { styles.bottom = (m + plotOffset.bottom) + 'px'; styles.top = 'auto'; }
- if(p.charAt(1) == 'e') { styles.right = (m + plotOffset.right) + 'px'; styles.left = 'auto'; }
- else if(p.charAt(1) == 'w') { styles.left = (m + plotOffset.left) + 'px'; styles.right = 'auto'; }
-
- var div = D.create('div'), size;
- div.className = 'flotr-legend';
- D.setStyles(div, styles);
- D.insert(div, table);
- D.insert(this.el, div);
-
- if(!legend.backgroundOpacity)
- return;
-
- var c = legend.backgroundColor || options.grid.backgroundColor || '#ffffff';
-
- _.extend(styles, D.size(div), {
- 'backgroundColor': c,
- 'z-index': 1
- });
- styles.width += 'px';
- styles.height += 'px';
-
- // Put in the transparent background separately to avoid blended labels and
- div = D.create('div');
- div.className = 'flotr-legend-bg';
- D.setStyles(div, styles);
- D.opacity(div, legend.backgroundOpacity);
- D.insert(div, ' ');
- D.insert(this.el, div);
- }
- }
- }
- }
- }
-});
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/selection.js b/addons/web_graph/static/lib/flotr2/js/plugins/selection.js
deleted file mode 100644
index bb508840d6d..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/selection.js
+++ /dev/null
@@ -1,278 +0,0 @@
-/**
- * Selection Handles Plugin
- *
- *
- * Options
- * show - True enables the handles plugin.
- * drag - Left and Right drag handles
- * scroll - Scrolling handle
- */
-(function () {
-
-function isLeftClick (e, type) {
- return (e.which ? (e.which === 1) : (e.button === 0 || e.button === 1));
-}
-
-function boundX(x, graph) {
- return Math.min(Math.max(0, x), graph.plotWidth - 1);
-}
-
-function boundY(y, graph) {
- return Math.min(Math.max(0, y), graph.plotHeight);
-}
-
-var
- D = Flotr.DOM,
- E = Flotr.EventAdapter,
- _ = Flotr._;
-
-
-Flotr.addPlugin('selection', {
-
- options: {
- pinchOnly: null, // Only select on pinch
- mode: null, // => one of null, 'x', 'y' or 'xy'
- color: '#B6D9FF', // => selection box color
- fps: 20 // => frames-per-second
- },
-
- callbacks: {
- 'flotr:mouseup' : function (event) {
-
- var
- options = this.options.selection,
- selection = this.selection,
- pointer = this.getEventPosition(event);
-
- if (!options || !options.mode) return;
- if (selection.interval) clearInterval(selection.interval);
-
- if (this.multitouches) {
- selection.updateSelection();
- } else
- if (!options.pinchOnly) {
- selection.setSelectionPos(selection.selection.second, pointer);
- }
- selection.clearSelection();
-
- if(selection.selecting && selection.selectionIsSane()){
- selection.drawSelection();
- selection.fireSelectEvent();
- this.ignoreClick = true;
- }
- },
- 'flotr:mousedown' : function (event) {
-
- var
- options = this.options.selection,
- selection = this.selection,
- pointer = this.getEventPosition(event);
-
- if (!options || !options.mode) return;
- if (!options.mode || (!isLeftClick(event) && _.isUndefined(event.touches))) return;
- if (!options.pinchOnly) selection.setSelectionPos(selection.selection.first, pointer);
- if (selection.interval) clearInterval(selection.interval);
-
- this.lastMousePos.pageX = null;
- selection.selecting = false;
- selection.interval = setInterval(
- _.bind(selection.updateSelection, this),
- 1000 / options.fps
- );
- },
- 'flotr:destroy' : function (event) {
- clearInterval(this.selection.interval);
- }
- },
-
- // TODO This isn't used. Maybe it belongs in the draw area and fire select event methods?
- getArea: function() {
-
- var s = this.selection.selection,
- first = s.first,
- second = s.second;
-
- return {
- x1: Math.min(first.x, second.x),
- x2: Math.max(first.x, second.x),
- y1: Math.min(first.y, second.y),
- y2: Math.max(first.y, second.y)
- };
- },
-
- selection: {first: {x: -1, y: -1}, second: {x: -1, y: -1}},
- prevSelection: null,
- interval: null,
-
- /**
- * Fires the 'flotr:select' event when the user made a selection.
- */
- fireSelectEvent: function(name){
- var a = this.axes,
- s = this.selection.selection,
- x1, x2, y1, y2;
-
- name = name || 'select';
-
- 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);
-
- E.fire(this.el, 'flotr:'+name, [{
- 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]);
- },
-
- /**
- * 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,
- s = this.selection.selection;
-
- this.selection.clearSelection();
-
- s.first.y = boundY((selX && !selY) ? 0 : (ya.max - area.y1) * vertScale, this);
- s.second.y = boundY((selX && !selY) ? this.plotHeight - 1: (ya.max - area.y2) * vertScale, this);
- s.first.x = boundX((selY && !selX) ? 0 : area.x1, this);
- s.second.x = boundX((selY && !selX) ? this.plotWidth : area.x2, this);
-
- this.selection.drawSelection();
- if (!preventEvent)
- this.selection.fireSelectEvent();
- },
-
- /**
- * Calculates the position of the selection.
- * @param {Object} pos - Position object.
- * @param {Event} event - Event object.
- */
- setSelectionPos: function(pos, pointer) {
- var mode = this.options.selection.mode,
- selection = this.selection.selection;
-
- if(mode.indexOf('x') == -1) {
- pos.x = (pos == selection.first) ? 0 : this.plotWidth;
- }else{
- pos.x = boundX(pointer.relX, this);
- }
-
- if (mode.indexOf('y') == -1) {
- pos.y = (pos == selection.first) ? 0 : this.plotHeight - 1;
- }else{
- pos.y = boundY(pointer.relY, this);
- }
- },
- /**
- * Draws the selection box.
- */
- drawSelection: function() {
-
- this.selection.fireSelectEvent('selecting');
-
- var s = this.selection.selection,
- octx = this.octx,
- options = this.options,
- plotOffset = this.plotOffset,
- prevSelection = this.selection.prevSelection;
-
- if (prevSelection &&
- 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.selection.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();
- },
-
- /**
- * Updates (draws) the selection box.
- */
- updateSelection: function(){
- if (!this.lastMousePos.pageX) return;
-
- this.selection.selecting = true;
-
- if (this.multitouches) {
- this.selection.setSelectionPos(this.selection.selection.first, this.getEventPosition(this.multitouches[0]));
- this.selection.setSelectionPos(this.selection.selection.second, this.getEventPosition(this.multitouches[1]));
- } else
- if (this.options.selection.pinchOnly) {
- return;
- } else {
- this.selection.setSelectionPos(this.selection.selection.second, this.lastMousePos);
- }
-
- this.selection.clearSelection();
-
- if(this.selection.selectionIsSane()) {
- this.selection.drawSelection();
- }
- },
-
- /**
- * Removes the selection box from the overlay canvas.
- */
- clearSelection: function() {
- if (!this.selection.prevSelection) return;
-
- var prevSelection = this.selection.prevSelection,
- lw = 1,
- 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 + 0.5,
- y + plotOffset.top - lw,
- w + 2 * lw + 0.5,
- h + 2 * lw + 0.5);
-
- this.selection.prevSelection = null;
- },
- /**
- * Determines whether or not the selection is sane and should be drawn.
- * @return {Boolean} - True when sane, false otherwise.
- */
- selectionIsSane: function(){
- var s = this.selection.selection;
- return Math.abs(s.second.x - s.first.x) >= 5 ||
- Math.abs(s.second.y - s.first.y) >= 5;
- }
-
-});
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/spreadsheet.js b/addons/web_graph/static/lib/flotr2/js/plugins/spreadsheet.js
deleted file mode 100644
index d75cb1991b1..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/spreadsheet.js
+++ /dev/null
@@ -1,296 +0,0 @@
-/** Spreadsheet **/
-(function() {
-
-function getRowLabel(value){
- if (this.options.spreadsheet.tickFormatter){
- //TODO maybe pass the xaxis formatter to the custom tick formatter as an opt-out?
- return this.options.spreadsheet.tickFormatter(value);
- }
- else {
- var t = _.find(this.axes.x.ticks, function(t){return t.v == value;});
- if (t) {
- return t.label;
- }
- return value;
- }
-}
-
-var
- D = Flotr.DOM,
- _ = Flotr._;
-
-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: '.',
- tickFormatter: null,
- initialTab: 'graph'
- },
- /**
- * Builds the tabs in the DOM
- */
- callbacks: {
- 'flotr:afterconstruct': function(){
- // @TODO necessary?
- //this.el.select('.flotr-tabs-group,.flotr-datagrid-container').invoke('remove');
-
- if (!this.options.spreadsheet.show) return;
-
- var ss = this.spreadsheet,
- container = D.node('<div class="flotr-tabs-group" style="position:absolute;left:0px;width:'+this.canvasWidth+'px"></div>'),
- graph = D.node('<div style="float:left" class="flotr-tab selected">'+this.options.spreadsheet.tabGraphLabel+'</div>'),
- data = D.node('<div style="float:left" class="flotr-tab">'+this.options.spreadsheet.tabDataLabel+'</div>'),
- offset;
-
- ss.tabsContainer = container;
- ss.tabs = { graph : graph, data : data };
-
- D.insert(container, graph);
- D.insert(container, data);
- D.insert(this.el, container);
-
- offset = D.size(data).height + 2;
- this.plotOffset.bottom += offset;
-
- D.setStyles(container, {top: this.canvasHeight-offset+'px'});
-
- this.
- observe(graph, 'click', function(){ss.showTab('graph');}).
- observe(data, 'click', function(){ss.showTab('data');});
- if (this.options.spreadsheet.initialTab !== 'graph'){
- ss.showTab(this.options.spreadsheet.initialTab);
- }
- }
- },
- /**
- * 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,
- rows = {};
-
- /* 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)
- **/
- _.each(s, function(serie, i){
- _.each(serie.data, function (v) {
- var x = v[0],
- y = v[1],
- r = rows[x];
- if (r) {
- r[i+1] = y;
- } else {
- var newRow = [];
- newRow[0] = x;
- newRow[i+1] = y;
- rows[x] = newRow;
- }
- });
- });
-
- // The data grid is sorted by x value
- this.seriesData = _.sortBy(rows, function(row, x){
- return parseInt(x, 10);
- });
- return this.seriesData;
- },
- /**
- * 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 s = this.series,
- datagrid = this.spreadsheet.loadDataGrid(),
- colgroup = ['<colgroup><col />'],
- buttonDownload, buttonSelect, t;
-
- // First row : series' labels
- var html = ['<table class="flotr-datagrid"><tr class="first-row">'];
- html.push('<th>&nbsp;</th>');
- _.each(s, function(serie,i){
- html.push('<th scope="col">'+(serie.label || String.fromCharCode(65+i))+'</th>');
- colgroup.push('<col />');
- });
- html.push('</tr>');
- // Data rows
- _.each(datagrid, function(row){
- html.push('<tr>');
- _.times(s.length+1, function(i){
- var tag = 'td',
- value = row[i],
- // TODO: do we really want to handle problems with floating point
- // precision here?
- content = (!_.isUndefined(value) ? Math.round(value*100000)/100000 : '');
- if (i === 0) {
- tag = 'th';
- var label = getRowLabel.call(this, content);
- if (label) content = label;
- }
-
- html.push('<'+tag+(tag=='th'?' scope="row"':'')+'>'+content+'</'+tag+'>');
- }, this);
- html.push('</tr>');
- }, this);
- colgroup.push('</colgroup>');
- t = D.node(html.join(''));
-
- /**
- * @TODO disabled this
- if (!Flotr.isIE || Flotr.isIE == 9) {
- function handleMouseout(){
- t.select('colgroup col.hover, th.hover').invoke('removeClassName', 'hover');
- }
- function handleMouseover(e){
- var td = e.element(),
- siblings = td.previousSiblings();
- t.select('th[scope=col]')[siblings.length-1].addClassName('hover');
- t.select('colgroup col')[siblings.length].addClassName('hover');
- }
- _.each(t.select('td'), function(td) {
- Flotr.EventAdapter.
- observe(td, 'mouseover', handleMouseover).
- observe(td, 'mouseout', handleMouseout);
- });
- }
- */
-
- buttonDownload = D.node(
- '<button type="button" class="flotr-datagrid-toolbar-button">' +
- this.options.spreadsheet.toolbarDownload +
- '</button>');
-
- buttonSelect = D.node(
- '<button type="button" class="flotr-datagrid-toolbar-button">' +
- this.options.spreadsheet.toolbarSelectAll+
- '</button>');
-
- this.
- observe(buttonDownload, 'click', _.bind(this.spreadsheet.downloadCSV, this)).
- observe(buttonSelect, 'click', _.bind(this.spreadsheet.selectAllData, this));
-
- var toolbar = D.node('<div class="flotr-datagrid-toolbar"></div>');
- D.insert(toolbar, buttonDownload);
- D.insert(toolbar, buttonSelect);
-
- var containerHeight =this.canvasHeight - D.size(this.spreadsheet.tabsContainer).height-2,
- container = D.node('<div class="flotr-datagrid-container" style="position:absolute;left:0px;top:0px;width:'+
- this.canvasWidth+'px;height:'+containerHeight+'px;overflow:auto;z-index:10"></div>');
-
- D.insert(container, toolbar);
- D.insert(container, t);
- D.insert(this.el, container);
- this.spreadsheet.datagrid = t;
- this.spreadsheet.container = 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){
- if (this.spreadsheet.activeTab === tabName){
- return;
- }
- switch(tabName) {
- case 'graph':
- D.hide(this.spreadsheet.container);
- D.removeClass(this.spreadsheet.tabs.data, 'selected');
- D.addClass(this.spreadsheet.tabs.graph, 'selected');
- break;
- case 'data':
- if (!this.spreadsheet.datagrid)
- this.spreadsheet.constructDataGrid();
- D.show(this.spreadsheet.container);
- D.addClass(this.spreadsheet.tabs.data, 'selected');
- D.removeClass(this.spreadsheet.tabs.graph, 'selected');
- break;
- default:
- throw 'Illegal tab name: ' + tabName;
- }
- this.spreadsheet.activeTab = tabName;
- },
- /**
- * 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 csv = '',
- series = this.series,
- options = this.options,
- dg = this.spreadsheet.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
- _.each(series, function(serie, i){
- csv += separator+'"'+(serie.label || String.fromCharCode(65+i)).replace(/\"/g, '\\"')+'"';
- });
-
- csv += "%0D%0A"; // \r\n
-
- // For each row
- csv += _.reduce(dg, function(memo, row){
- var rowLabel = getRowLabel.call(this, row[0]) || '';
- rowLabel = '"'+(rowLabel+'').replace(/\"/g, '\\"')+'"';
- var numbers = row.slice(1).join(separator);
- if (options.spreadsheet.decimalSeparator !== '.') {
- numbers = numbers.replace(/\./g, options.spreadsheet.decimalSeparator);
- }
- return memo + rowLabel+separator+numbers+"%0D%0A"; // \t and \r\n
- }, '', this);
-
- if (Flotr.isIE && Flotr.isIE < 9) {
- 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);
- }
-});
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/plugins/titles.js b/addons/web_graph/static/lib/flotr2/js/plugins/titles.js
deleted file mode 100644
index cf95d9e7c80..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/plugins/titles.js
+++ /dev/null
@@ -1,177 +0,0 @@
-(function () {
-
-var D = Flotr.DOM;
-
-Flotr.addPlugin('titles', {
- callbacks: {
- 'flotr:afterdraw': function() {
- this.titles.drawTitles();
- }
- },
- /**
- * 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,
- textAlign: 'center'
- };
-
- // Add subtitle
- if (options.subtitle){
- Flotr.drawText(
- ctx, 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){
- Flotr.drawText(
- ctx, options.title,
- this.plotOffset.left + this.plotWidth/2,
- this.titleHeight - 2,
- style
- );
- }
-
- style.weight = 1.8;
- style.size *= 0.8;
-
- // Add x axis title
- if (a.x.options.title && a.x.used){
- style.textAlign = a.x.options.titleAlign || 'center';
- style.textBaseline = 'top';
- style.angle = Flotr.toRad(a.x.options.titleAngle);
- style = Flotr.getBestTextAlign(style.angle, style);
- Flotr.drawText(
- ctx, 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.textAlign = a.x2.options.titleAlign || 'center';
- style.textBaseline = 'bottom';
- style.angle = Flotr.toRad(a.x2.options.titleAngle);
- style = Flotr.getBestTextAlign(style.angle, style);
- Flotr.drawText(
- ctx, 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.textAlign = a.y.options.titleAlign || 'right';
- style.textBaseline = 'middle';
- style.angle = Flotr.toRad(a.y.options.titleAngle);
- style = Flotr.getBestTextAlign(style.angle, style);
- Flotr.drawText(
- ctx, 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.textAlign = a.y2.options.titleAlign || 'left';
- style.textBaseline = 'middle';
- style.angle = Flotr.toRad(a.y2.options.titleAngle);
- style = Flotr.getBestTextAlign(style.angle, style);
- Flotr.drawText(
- ctx, 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(
- '<div style="position:absolute;top:0;left:',
- this.plotOffset.left, 'px;font-size:1em;font-weight:bold;text-align:center;width:',
- this.plotWidth,'px;" class="flotr-title">', options.title, '</div>'
- );
-
- // Add subtitle
- if (options.subtitle)
- html.push(
- '<div style="position:absolute;top:', this.titleHeight, 'px;left:',
- this.plotOffset.left, 'px;font-size:smaller;text-align:center;width:',
- this.plotWidth, 'px;" class="flotr-subtitle">', options.subtitle, '</div>'
- );
-
- html.push('</div>');
-
- html.push('<div class="flotr-axis-title" style="font-weight:bold;">');
-
- // Add x axis title
- if (a.x.options.title && a.x.used)
- html.push(
- '<div style="position:absolute;top:',
- (this.plotOffset.top + this.plotHeight + options.grid.labelMargin + a.x.titleSize.height),
- 'px;left:', this.plotOffset.left, 'px;width:', this.plotWidth,
- 'px;text-align:center;" class="flotr-axis-title">', a.x.options.title, '</div>'
- );
-
- // Add x2 axis title
- if (a.x2.options.title && a.x2.used)
- html.push(
- '<div style="position:absolute;top:0;left:', this.plotOffset.left, 'px;width:',
- this.plotWidth, 'px;text-align:center;" class="flotr-axis-title">', a.x2.options.title, '</div>'
- );
-
- // Add y axis title
- if (a.y.options.title && a.y.used)
- html.push(
- '<div style="position:absolute;top:',
- (this.plotOffset.top + this.plotHeight/2 - a.y.titleSize.height/2),
- 'px;left:0;text-align:right;" class="flotr-axis-title">', a.y.options.title, '</div>'
- );
-
- // Add y2 axis title
- if (a.y2.options.title && a.y2.used)
- html.push(
- '<div style="position:absolute;top:',
- (this.plotOffset.top + this.plotHeight/2 - a.y.titleSize.height/2),
- 'px;right:0;text-align:right;" class="flotr-axis-title">', a.y2.options.title, '</div>'
- );
-
- html = html.join('');
-
- var div = D.create('div');
- D.setStyles({
- color: options.grid.color
- });
- div.className = 'flotr-titles';
- D.insert(this.el, div);
- D.insert(div, html);
- }
- }
-});
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/types/bars.js b/addons/web_graph/static/lib/flotr2/js/types/bars.js
deleted file mode 100644
index 03e7988b785..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/bars.js
+++ /dev/null
@@ -1,274 +0,0 @@
-/** 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)
- stacked: false, // => stacked bar charts
- centered: true, // => center the bars to their x axis value
- topPadding: 0.1 // => top padding in percent
- },
-
- stack : {
- positive : [],
- negative : [],
- _positive : [], // Shadow
- _negative : [] // Shadow
- },
-
- draw : function (options) {
- var
- context = options.context;
-
- context.save();
- context.lineJoin = 'miter';
- // @TODO linewidth not interpreted the right way.
- context.lineWidth = options.lineWidth;
- context.strokeStyle = options.color;
- if (options.fill) context.fillStyle = options.fillStyle;
-
- this.plot(options);
-
- context.restore();
- },
-
- plot : function (options) {
-
- var
- data = options.data,
- context = options.context,
- shadowSize = options.shadowSize,
- i, geometry, left, top, width, height;
-
- if (data.length < 1) return;
-
- this.translate(context, options.horizontal);
-
- for (i = 0; i < data.length; i++) {
-
- geometry = this.getBarGeometry(data[i][0], data[i][1], options);
- if (geometry === null) continue;
-
- left = geometry.left;
- top = geometry.top;
- width = geometry.width;
- height = geometry.height;
-
- if (options.fill) context.fillRect(left, top, width, height);
- if (shadowSize) {
- context.save();
- context.fillStyle = 'rgba(0,0,0,0.05)';
- context.fillRect(left + shadowSize, top + shadowSize, width, height);
- context.restore();
- }
- if (options.lineWidth) {
- context.strokeRect(left, top, width, height);
- }
- }
- },
-
- translate : function (context, horizontal) {
- if (horizontal) {
- context.rotate(-Math.PI / 2);
- context.scale(-1, 1);
- }
- },
-
- getBarGeometry : function (x, y, options) {
-
- var
- horizontal = options.horizontal,
- barWidth = options.barWidth,
- centered = options.centered,
- stack = options.stacked ? this.stack : false,
- lineWidth = options.lineWidth,
- bisection = centered ? barWidth / 2 : 0,
- xScale = horizontal ? options.yScale : options.xScale,
- yScale = horizontal ? options.xScale : options.yScale,
- xValue = horizontal ? y : x,
- yValue = horizontal ? x : y,
- stackOffset = 0,
- stackValue, left, right, top, bottom;
-
- // Stacked bars
- if (stack) {
- stackValue = yValue > 0 ? stack.positive : stack.negative;
- stackOffset = stackValue[xValue] || stackOffset;
- stackValue[xValue] = stackOffset + yValue;
- }
-
- left = xScale(xValue - bisection);
- right = xScale(xValue + barWidth - bisection);
- top = yScale(yValue + stackOffset);
- bottom = yScale(stackOffset);
-
- // TODO for test passing... probably looks better without this
- if (bottom < 0) bottom = 0;
-
- // TODO Skipping...
- // if (right < xa.min || left > xa.max || top < ya.min || bottom > ya.max) continue;
-
- return (x === null || y === null) ? null : {
- x : xValue,
- y : yValue,
- xScale : xScale,
- yScale : yScale,
- top : top,
- left : Math.min(left, right) - lineWidth / 2,
- width : Math.abs(right - left) - lineWidth,
- height : bottom - top
- };
- },
-
- hit : function (options) {
- var
- data = options.data,
- args = options.args,
- mouse = args[0],
- n = args[1],
- x = mouse.x,
- y = mouse.y,
- hitGeometry = this.getBarGeometry(x, y, options),
- width = hitGeometry.width / 2,
- left = hitGeometry.left,
- geometry, i;
-
- for (i = data.length; i--;) {
- geometry = this.getBarGeometry(data[i][0], data[i][1], options);
- if (geometry.y > hitGeometry.y && Math.abs(left - geometry.left) < width) {
- n.x = data[i][0];
- n.y = data[i][1];
- n.index = i;
- n.seriesIndex = options.index;
- }
- }
- },
-
- drawHit : function (options) {
- // TODO hits for stacked bars; implement using calculateStack option?
- var
- context = options.context,
- args = options.args,
- geometry = this.getBarGeometry(args.x, args.y, options),
- left = geometry.left,
- top = geometry.top,
- width = geometry.width,
- height = geometry.height;
-
- context.save();
- context.strokeStyle = options.color;
- context.lineWidth = options.lineWidth;
- this.translate(context, options.horizontal);
-
- // Draw highlight
- context.beginPath();
- context.moveTo(left, top + height);
- context.lineTo(left, top);
- context.lineTo(left + width, top);
- context.lineTo(left + width, top + height);
- if (options.fill) {
- context.fillStyle = options.fillStyle;
- context.fill();
- }
- context.stroke();
- context.closePath();
-
- context.restore();
- },
-
- clearHit: function (options) {
- var
- context = options.context,
- args = options.args,
- geometry = this.getBarGeometry(args.x, args.y, options),
- left = geometry.left,
- width = geometry.width,
- top = geometry.top,
- height = geometry.height,
- lineWidth = 2 * options.lineWidth;
-
- context.save();
- this.translate(context, options.horizontal);
- context.clearRect(
- left - lineWidth,
- Math.min(top, top + height) - lineWidth,
- width + 2 * lineWidth,
- Math.abs(height) + 2 * lineWidth
- );
- context.restore();
- },
-
- extendXRange : function (axis, data, options, bars) {
- this._extendRange(axis, data, options, bars);
- },
-
- extendYRange : function (axis, data, options, bars) {
- this._extendRange(axis, data, options, bars);
- },
- _extendRange: function (axis, data, options, bars) {
-
- var
- max = axis.options.max;
-
- if (_.isNumber(max) || _.isString(max)) return;
-
- var
- newmin = axis.min,
- newmax = axis.max,
- horizontal = options.horizontal,
- orientation = axis.orientation,
- positiveSums = this.positiveSums || {},
- negativeSums = this.negativeSums || {},
- value, datum, index, j;
-
- // Sides of bars
- if ((orientation == 1 && !horizontal) || (orientation == -1 && horizontal)) {
- if (options.centered) {
- newmax = Math.max(axis.datamax + options.barWidth, newmax);
- newmin = Math.min(axis.datamin - options.barWidth, newmin);
- }
- }
-
- if (options.stacked &&
- ((orientation == 1 && horizontal) || (orientation == -1 && !horizontal))){
-
- for (j = data.length; j--;) {
- value = data[j][(orientation == 1 ? 1 : 0)]+'';
- datum = data[j][(orientation == 1 ? 0 : 1)];
-
- // Positive
- if (datum > 0) {
- positiveSums[value] = (positiveSums[value] || 0) + datum;
- newmax = Math.max(newmax, positiveSums[value]);
- }
-
- // Negative
- else {
- negativeSums[value] = (negativeSums[value] || 0) + datum;
- newmin = Math.min(newmin, negativeSums[value]);
- }
- }
- }
-
- // End of bars
- if ((orientation == 1 && horizontal) || (orientation == -1 && !horizontal)) {
- if (options.topPadding && (axis.max === axis.datamax || (options.stacked && this.stackMax !== newmax))) {
- newmax += options.topPadding * (newmax - newmin);
- }
- }
-
- this.stackMin = newmin;
- this.stackMax = newmax;
- this.negativeSums = negativeSums;
- this.positiveSums = positiveSums;
-
- axis.max = newmax;
- axis.min = newmin;
- }
-
-});
diff --git a/addons/web_graph/static/lib/flotr2/js/types/bubbles.js b/addons/web_graph/static/lib/flotr2/js/types/bubbles.js
deleted file mode 100644
index a97c5a28a93..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/bubbles.js
+++ /dev/null
@@ -1,119 +0,0 @@
-/** Bubbles **/
-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 (options) {
- var
- context = options.context,
- shadowSize = options.shadowSize;
-
- context.save();
- context.lineWidth = options.lineWidth;
-
- // Shadows
- context.fillStyle = 'rgba(0,0,0,0.05)';
- context.strokeStyle = 'rgba(0,0,0,0.05)';
- this.plot(options, shadowSize / 2);
- context.strokeStyle = 'rgba(0,0,0,0.1)';
- this.plot(options, shadowSize / 4);
-
- // Chart
- context.strokeStyle = options.color;
- context.fillStyle = options.fillStyle;
- this.plot(options);
-
- context.restore();
- },
- plot : function (options, offset) {
-
- var
- data = options.data,
- context = options.context,
- geometry,
- i, x, y, z;
-
- offset = offset || 0;
-
- for (i = 0; i < data.length; ++i){
-
- geometry = this.getGeometry(data[i], options);
-
- context.beginPath();
- context.arc(geometry.x + offset, geometry.y + offset, geometry.z, 0, 2 * Math.PI, true);
- context.stroke();
- if (options.fill) context.fill();
- context.closePath();
- }
- },
- getGeometry : function (point, options) {
- return {
- x : options.xScale(point[0]),
- y : options.yScale(point[1]),
- z : point[2] * options.baseRadius
- };
- },
- hit : function (options) {
- var
- data = options.data,
- args = options.args,
- mouse = args[0],
- n = args[1],
- x = mouse.x,
- y = mouse.y,
- geometry,
- dx, dy;
-
- for (i = data.length; i--;) {
- geometry = this.getGeometry(data[i], options);
-
- dx = geometry.x - options.xScale(x);
- dy = geometry.y - options.yScale(y);
-
- if (Math.sqrt(dx * dx + dy * dy) < geometry.z) {
- n.x = data[i][0];
- n.y = data[i][1];
- n.index = i;
- n.seriesIndex = options.index;
- }
- }
- },
- drawHit : function (options) {
-
- var
- context = options.context,
- geometry = this.getGeometry(options.data[options.args.index], options);
-
- context.save();
- context.lineWidth = options.lineWidth;
- context.fillStyle = options.fillStyle;
- context.strokeStyle = options.color;
- context.beginPath();
- context.arc(geometry.x, geometry.y, geometry.z, 0, 2 * Math.PI, true);
- context.fill();
- context.stroke();
- context.closePath();
- context.restore();
- },
- clearHit : function (options) {
-
- var
- context = options.context,
- geometry = this.getGeometry(options.data[options.args.index], options),
- offset = geometry.z + options.lineWidth;
-
- context.save();
- context.clearRect(
- geometry.x - offset,
- geometry.y - offset,
- 2 * offset,
- 2 * offset
- );
- context.restore();
- }
- // TODO Add a hit calculation method (like pie)
-});
diff --git a/addons/web_graph/static/lib/flotr2/js/types/candles.js b/addons/web_graph/static/lib/flotr2/js/types/candles.js
deleted file mode 100644
index 0e484b366cc..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/candles.js
+++ /dev/null
@@ -1,127 +0,0 @@
-/** 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
- // TODO Test this barcharts option.
- barcharts: false // => draw as barcharts (not standard bars but financial barcharts)
- },
-
- draw : function (options) {
-
- var
- context = options.context;
-
- context.save();
- context.lineJoin = 'miter';
- context.lineCap = 'butt';
- // @TODO linewidth not interpreted the right way.
- context.lineWidth = options.wickLineWidth || options.lineWidth;
-
- this.plot(options);
-
- context.restore();
- },
-
- plot : function (options) {
-
- var
- data = options.data,
- context = options.context,
- xScale = options.xScale,
- yScale = options.yScale,
- width = options.candleWidth / 2,
- shadowSize = options.shadowSize,
- lineWidth = options.lineWidth,
- wickLineWidth = options.wickLineWidth,
- pixelOffset = (wickLineWidth % 2) / 2,
- color,
- datum, x, y,
- open, high, low, close,
- left, right, bottom, top, bottom2, top2,
- i;
-
- if (data.length < 1) return;
-
- for (i = 0; i < data.length; i++) {
- datum = data[i];
- x = datum[0];
- open = datum[1];
- high = datum[2];
- low = datum[3];
- close = datum[4];
- left = xScale(x - width);
- right = xScale(x + width);
- bottom = yScale(low);
- top = yScale(high);
- bottom2 = yScale(Math.min(open, close));
- top2 = yScale(Math.max(open, close));
-
- /*
- // TODO skipping
- if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)
- continue;
- */
-
- color = options[open > close ? 'downFillColor' : 'upFillColor'];
-
- // Fill the candle.
- // TODO Test the barcharts option
- if (options.fill && !options.barcharts) {
- context.fillStyle = 'rgba(0,0,0,0.05)';
- context.fillRect(left + shadowSize, top2 + shadowSize, right - left, bottom2 - top2);
- context.save();
- context.globalAlpha = options.fillOpacity;
- context.fillStyle = color;
- context.fillRect(left, top2 + lineWidth, right - left, bottom2 - top2);
- context.restore();
- }
-
- // Draw candle outline/border, high, low.
- if (lineWidth || wickLineWidth) {
-
- x = Math.floor((left + right) / 2) + pixelOffset;
-
- context.strokeStyle = color;
- context.beginPath();
-
- // TODO Again with the bartcharts
- if (options.barcharts) {
-
- context.moveTo(x, Math.floor(top + width));
- context.lineTo(x, Math.floor(bottom + width));
-
- y = Math.floor(open + width) + 0.5;
- context.moveTo(Math.floor(left) + pixelOffset, y);
- context.lineTo(x, y);
-
- y = Math.floor(close + width) + 0.5;
- context.moveTo(Math.floor(right) + pixelOffset, y);
- context.lineTo(x, y);
- } else {
- context.strokeRect(left, top2 + lineWidth, right - left, bottom2 - top2);
-
- context.moveTo(x, Math.floor(top2 + lineWidth));
- context.lineTo(x, Math.floor(top + lineWidth));
- context.moveTo(x, Math.floor(bottom2 + lineWidth));
- context.lineTo(x, Math.floor(bottom + lineWidth));
- }
-
- context.closePath();
- context.stroke();
- }
- }
- },
- extendXRange: function (axis, data, options) {
- if (axis.options.max === null) {
- axis.max = Math.max(axis.datamax + 0.5, axis.max);
- axis.min = Math.min(axis.datamin - 0.5, axis.min);
- }
- }
-});
diff --git a/addons/web_graph/static/lib/flotr2/js/types/gantt.js b/addons/web_graph/static/lib/flotr2/js/types/gantt.js
deleted file mode 100644
index 1498bcb51cf..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/gantt.js
+++ /dev/null
@@ -1,229 +0,0 @@
-/** Gantt
- * Base on data in form [s,y,d] where:
- * y - executor or simply y value
- * s - task start value
- * d - task duration
- * **/
-Flotr.addType('gantt', {
- options: {
- show: false, // => setting to true will show gantt, 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
- centered: true // => center the bars to their x axis value
- },
- /**
- * Draws gantt series in the canvas element.
- * @param {Object} series - Series with options.gantt.show = true.
- */
- draw: function(series) {
- var ctx = this.ctx,
- bw = series.gantt.barWidth,
- lw = Math.min(series.gantt.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;
-
- ctx.save();
- this.gantt.plotShadows(series, bw, 0, series.gantt.fill);
- ctx.restore();
-
- if(series.gantt.fill){
- var color = series.gantt.fillColor || series.color;
- ctx.fillStyle = this.processColor(color, {opacity: series.gantt.fillOpacity});
- }
-
- this.gantt.plot(series, bw, 0, series.gantt.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, i;
-
- for(i = 0; i < data.length; i++){
- var y = data[i][0],
- s = data[i][1],
- d = data[i][2],
- drawLeft = true, drawTop = true, drawRight = true;
-
- if (s === null || d === null) continue;
-
- var left = s,
- right = s + d,
- bottom = y - (series.gantt.centered ? barWidth/2 : 0),
- top = y + barWidth - (series.gantt.centered ? barWidth/2 : 0);
-
- 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)
- drawTop = false;
- }
-
- if(bottom < ya.min)
- bottom = ya.min;
-
- if(top > ya.max){
- top = ya.max;
- if (ya.lastSerie != series)
- 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();
- ctx.closePath();
- }
-
- /**
- * Draw bar outline/border.
- */
- if(series.gantt.lineWidth && (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();
- ctx.closePath();
- }
- }
- },
- plotShadows: function(series, barWidth, offset){
- var data = series.data;
- if(data.length < 1) return;
-
- var i, y, s, d,
- xa = series.xaxis,
- ya = series.yaxis,
- ctx = this.ctx,
- sw = this.options.shadowSize;
-
- for(i = 0; i < data.length; i++){
- y = data[i][0];
- s = data[i][1];
- d = data[i][2];
-
- if (s === null || d === null) continue;
-
- var left = s,
- right = s + d,
- bottom = y - (series.gantt.centered ? barWidth/2 : 0),
- top = y + barWidth - (series.gantt.centered ? barWidth/2 : 0);
-
- 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 = 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.plotHeight), width, height);
- }
- },
- extendXRange: function(axis) {
- if(axis.options.max === null){
- var newmin = axis.min,
- newmax = axis.max,
- i, j, x, s, g,
- stackedSumsPos = {},
- stackedSumsNeg = {},
- lastSerie = null;
-
- for(i = 0; i < this.series.length; ++i){
- s = this.series[i];
- g = s.gantt;
-
- if(g.show && s.xaxis == axis) {
- for (j = 0; j < s.data.length; j++) {
- if (g.show) {
- y = s.data[j][0]+'';
- stackedSumsPos[y] = Math.max((stackedSumsPos[y] || 0), s.data[j][1]+s.data[j][2]);
- lastSerie = s;
- }
- }
- for (j in stackedSumsPos) {
- newmax = Math.max(stackedSumsPos[j], newmax);
- }
- }
- }
- axis.lastSerie = lastSerie;
- axis.max = newmax;
- axis.min = newmin;
- }
- },
- extendYRange: function(axis){
- if(axis.options.max === null){
- var newmax = Number.MIN_VALUE,
- newmin = Number.MAX_VALUE,
- i, j, s, g,
- stackedSumsPos = {},
- stackedSumsNeg = {},
- lastSerie = null;
-
- for(i = 0; i < this.series.length; ++i){
- s = this.series[i];
- g = s.gantt;
-
- if (g.show && !s.hide && s.yaxis == axis) {
- var datamax = Number.MIN_VALUE, datamin = Number.MAX_VALUE;
- for(j=0; j < s.data.length; j++){
- datamax = Math.max(datamax,s.data[j][0]);
- datamin = Math.min(datamin,s.data[j][0]);
- }
-
- if (g.centered) {
- newmax = Math.max(datamax + 0.5, newmax);
- newmin = Math.min(datamin - 0.5, newmin);
- }
- else {
- newmax = Math.max(datamax + 1, newmax);
- newmin = Math.min(datamin, newmin);
- }
- // For normal horizontal bars
- if (g.barWidth + datamax > newmax){
- newmax = axis.max + g.barWidth;
- }
- }
- }
- axis.lastSerie = lastSerie;
- axis.max = newmax;
- axis.min = newmin;
- axis.tickSize = Flotr.getTickSize(axis.options.noTicks, newmin, newmax, axis.options.tickDecimals);
- }
- }
-});
diff --git a/addons/web_graph/static/lib/flotr2/js/types/lines.js b/addons/web_graph/static/lib/flotr2/js/types/lines.js
deleted file mode 100644
index d65971b2dfe..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/lines.js
+++ /dev/null
@@ -1,275 +0,0 @@
-/** 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
- fillBorder: false, // => draw a border around the fill
- fillColor: null, // => fill color
- fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill
- steps: false, // => draw steps
- stacked: false // => setting to true will show stacked lines, false will show normal lines
- },
-
- stack : {
- values : []
- },
-
- /**
- * Draws lines series in the canvas element.
- * @param {Object} options
- */
- draw : function (options) {
-
- var
- context = options.context,
- lineWidth = options.lineWidth,
- shadowSize = options.shadowSize,
- offset;
-
- context.save();
- context.lineJoin = 'round';
-
- if (shadowSize) {
-
- context.lineWidth = shadowSize / 2;
- offset = lineWidth / 2 + context.lineWidth / 2;
-
- // @TODO do this instead with a linear gradient
- context.strokeStyle = "rgba(0,0,0,0.1)";
- this.plot(options, offset + shadowSize / 2, false);
-
- context.strokeStyle = "rgba(0,0,0,0.2)";
- this.plot(options, offset, false);
- }
-
- context.lineWidth = lineWidth;
- context.strokeStyle = options.color;
-
- this.plot(options, 0, true);
-
- context.restore();
- },
-
- plot : function (options, shadowOffset, incStack) {
-
- var
- context = options.context,
- width = options.width,
- height = options.height,
- xScale = options.xScale,
- yScale = options.yScale,
- data = options.data,
- stack = options.stacked ? this.stack : false,
- length = data.length - 1,
- prevx = null,
- prevy = null,
- zero = yScale(0),
- x1, x2, y1, y2, stack1, stack2, i;
-
- if (length < 1) return;
-
- context.beginPath();
-
- for (i = 0; i < length; ++i) {
-
- // To allow empty values
- if (data[i][1] === null || data[i+1][1] === null) continue;
-
- // Zero is infinity for log scales
- // TODO handle zero for logarithmic
- // if (xa.options.scaling === 'logarithmic' && (data[i][0] <= 0 || data[i+1][0] <= 0)) continue;
- // if (ya.options.scaling === 'logarithmic' && (data[i][1] <= 0 || data[i+1][1] <= 0)) continue;
-
- x1 = xScale(data[i][0]);
- x2 = xScale(data[i+1][0]);
-
- if (stack) {
-
- stack1 = stack.values[data[i][0]] || 0;
- stack2 = stack.values[data[i+1][0]] || stack.values[data[i][0]] || 0;
-
- y1 = yScale(data[i][1] + stack1);
- y2 = yScale(data[i+1][1] + stack2);
-
- if(incStack){
- stack.values[data[i][0]] = data[i][1]+stack1;
-
- if(i == length-1)
- stack.values[data[i+1][0]] = data[i+1][1]+stack2;
- }
- }
- else{
- y1 = yScale(data[i][1]);
- y2 = yScale(data[i+1][1]);
- }
-
- if (
- (y1 > height && y2 > height) ||
- (y1 < 0 && y2 < 0) ||
- (x1 < 0 && x2 < 0) ||
- (x1 > width && x2 > width)
- ) continue;
-
- if((prevx != x1) || (prevy != y1 + shadowOffset))
- context.moveTo(x1, y1 + shadowOffset);
-
- prevx = x2;
- prevy = y2 + shadowOffset;
- if (options.steps) {
- context.lineTo(prevx + shadowOffset / 2, y1 + shadowOffset);
- context.lineTo(prevx + shadowOffset / 2, prevy);
- } else {
- context.lineTo(prevx, prevy);
- }
- }
-
- if (!options.fill || options.fill && !options.fillBorder) context.stroke();
-
- // TODO stacked lines
- if(!shadowOffset && options.fill){
- x1 = xScale(data[0][0]);
- context.fillStyle = options.fillStyle;
- context.lineTo(x2, zero);
- context.lineTo(x1, zero);
- context.lineTo(x1, yScale(data[0][1]));
- context.fill();
- if (options.fillBorder) {
- context.stroke();
- }
- }
-
- context.closePath();
- },
-
- // Perform any pre-render precalculations (this should be run on data first)
- // - Pie chart total for calculating measures
- // - Stacks for lines and bars
- // precalculate : function () {
- // }
- //
- //
- // Get any bounds after pre calculation (axis can fetch this if does not have explicit min/max)
- // getBounds : function () {
- // }
- // getMin : function () {
- // }
- // getMax : function () {
- // }
- //
- //
- // Padding around rendered elements
- // getPadding : function () {
- // }
-
- extendYRange : function (axis, data, options, lines) {
-
- var o = axis.options;
-
- // If stacked and auto-min
- if (options.stacked && ((!o.max && o.max !== 0) || (!o.min && o.min !== 0))) {
-
- var
- newmax = axis.max,
- newmin = axis.min,
- positiveSums = lines.positiveSums || {},
- negativeSums = lines.negativeSums || {},
- x, j;
-
- for (j = 0; j < data.length; j++) {
-
- x = data[j][0] + '';
-
- // Positive
- if (data[j][1] > 0) {
- positiveSums[x] = (positiveSums[x] || 0) + data[j][1];
- newmax = Math.max(newmax, positiveSums[x]);
- }
-
- // Negative
- else {
- negativeSums[x] = (negativeSums[x] || 0) + data[j][1];
- newmin = Math.min(newmin, negativeSums[x]);
- }
- }
-
- lines.negativeSums = negativeSums;
- lines.positiveSums = positiveSums;
-
- axis.max = newmax;
- axis.min = newmin;
- }
-
- if (options.steps) {
-
- this.hit = function (options) {
- var
- data = options.data,
- args = options.args,
- yScale = options.yScale,
- mouse = args[0],
- length = data.length,
- n = args[1],
- x = mouse.x,
- relY = mouse.relY,
- i;
-
- for (i = 0; i < length - 1; i++) {
- if (x >= data[i][0] && x <= data[i+1][0]) {
- if (Math.abs(yScale(data[i][1]) - relY) < 8) {
- n.x = data[i][0];
- n.y = data[i][1];
- n.index = i;
- n.seriesIndex = options.index;
- }
- break;
- }
- }
- };
-
- this.drawHit = function (options) {
- var
- context = options.context,
- args = options.args,
- data = options.data,
- xScale = options.xScale,
- index = args.index,
- x = xScale(args.x),
- y = options.yScale(args.y),
- x2;
-
- if (data.length - 1 > index) {
- x2 = options.xScale(data[index + 1][0]);
- context.save();
- context.strokeStyle = options.color;
- context.lineWidth = options.lineWidth;
- context.beginPath();
- context.moveTo(x, y);
- context.lineTo(x2, y);
- context.stroke();
- context.closePath();
- context.restore();
- }
- };
-
- this.clearHit = function (options) {
- var
- context = options.context,
- args = options.args,
- data = options.data,
- xScale = options.xScale,
- width = options.lineWidth,
- index = args.index,
- x = xScale(args.x),
- y = options.yScale(args.y),
- x2;
-
- if (data.length - 1 > index) {
- x2 = options.xScale(data[index + 1][0]);
- context.clearRect(x - width, y - width, x2 - x + 2 * width, 2 * width);
- }
- };
- }
- }
-
-});
diff --git a/addons/web_graph/static/lib/flotr2/js/types/markers.js b/addons/web_graph/static/lib/flotr2/js/types/markers.js
deleted file mode 100644
index ee1104e3568..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/markers.js
+++ /dev/null
@@ -1,140 +0,0 @@
-/** Markers **/
-/**
- * Formats the marker labels.
- * @param {Object} obj - Marker value Object {x:..,y:..}
- * @return {String} Formatted marker string
- */
-(function () {
-
-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
- color: '#000000', // => text color
- 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)
- verticalMargin: 0, // => the margin between the point and the text.
- labelFormatter: Flotr.defaultMarkerFormatter,
- fontSize: Flotr.defaultOptions.fontSize,
- stacked: false, // => true if markers should be stacked
- stackingType: 'b', // => define staching behavior, (b- bars like, a - area like) (see Issue 125 for details)
- horizontal: false // => true if markers should be horizontal (For now only in a case on horizontal stacked bars, stacks should be calculated horizontaly)
- },
-
- // TODO test stacked markers.
- stack : {
- positive : [],
- negative : [],
- values : []
- },
-
- draw : function (options) {
-
- var
- data = options.data,
- context = options.context,
- stack = options.stacked ? options.stack : false,
- stackType = options.stackingType,
- stackOffsetNeg,
- stackOffsetPos,
- stackOffset,
- i, x, y, label;
-
- context.save();
- context.lineJoin = 'round';
- context.lineWidth = options.lineWidth;
- context.strokeStyle = 'rgba(0,0,0,0.5)';
- context.fillStyle = options.fillStyle;
-
- function stackPos (a, b) {
- stackOffsetPos = stack.negative[a] || 0;
- stackOffsetNeg = stack.positive[a] || 0;
- if (b > 0) {
- stack.positive[a] = stackOffsetPos + b;
- return stackOffsetPos + b;
- } else {
- stack.negative[a] = stackOffsetNeg + b;
- return stackOffsetNeg + b;
- }
- }
-
- for (i = 0; i < data.length; ++i) {
-
- x = data[i][0];
- y = data[i][1];
-
- if (stack) {
- if (stackType == 'b') {
- if (options.horizontal) y = stackPos(y, x);
- else x = stackPos(x, y);
- } else if (stackType == 'a') {
- stackOffset = stack.values[x] || 0;
- stack.values[x] = stackOffset + y;
- y = stackOffset + y;
- }
- }
-
- label = options.labelFormatter({x: x, y: y, index: i, data : data});
- this.plot(options.xScale(x), options.yScale(y), label, options);
- }
- context.restore();
- },
- plot: function(x, y, label, options) {
- var context = options.context;
- if (isImage(label) && !label.complete) {
- throw 'Marker image not loaded.';
- } else {
- this._plot(x, y, label, options);
- }
- },
-
- _plot: function(x, y, label, options) {
- var context = options.context,
- margin = 2,
- left = x,
- top = y,
- dim;
-
- if (isImage(label))
- dim = {height : label.height, width: label.width};
- else
- dim = options.text.canvas(label);
-
- 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 + options.verticalMargin;
- else top += options.verticalMargin;
-
- left = Math.floor(left)+0.5;
- top = Math.floor(top)+0.5;
-
- if(options.fill)
- context.fillRect(left, top, dim.width, dim.height);
-
- if(options.stroke)
- context.strokeRect(left, top, dim.width, dim.height);
-
- if (isImage(label))
- context.drawImage(label, left+margin, top+margin);
- else
- Flotr.drawText(context, label, left+margin, top+margin, {textBaseline: 'top', textAlign: 'left', size: options.fontSize, color: options.color});
- }
-});
-
-function isImage (i) {
- return typeof i === 'object' && i.constructor && (Image ? true : i.constructor === Image);
-}
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/types/pie.js b/addons/web_graph/static/lib/flotr2/js/types/pie.js
deleted file mode 100644
index ec932be5e6d..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/pie.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/** Pie **/
-/**
- * Formats the pies labels.
- * @param {Object} slice - Slice object
- * @return {String} Formatted pie label string
- */
-(function () {
-
-var
- _ = Flotr._;
-
-Flotr.defaultPieLabelFormatter = function (total, value) {
- return (100 * value / total).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
- },
-
- draw : function (options) {
-
- // TODO 3D charts what?
-
- var
- data = options.data,
- context = options.context,
- canvas = context.canvas,
- lineWidth = options.lineWidth,
- shadowSize = options.shadowSize,
- sizeRatio = options.sizeRatio,
- height = options.height,
- width = options.width,
- explode = options.explode,
- color = options.color,
- fill = options.fill,
- fillStyle = options.fillStyle,
- radius = Math.min(canvas.width, canvas.height) * sizeRatio / 2,
- value = data[0][1],
- html = [],
- vScale = 1,//Math.cos(series.pie.viewAngle);
- measure = Math.PI * 2 * value / this.total,
- startAngle = this.startAngle || (2 * Math.PI * options.startAngle), // TODO: this initial startAngle is already in radians (fixing will be test-unstable)
- endAngle = startAngle + measure,
- bisection = startAngle + measure / 2,
- label = options.labelFormatter(this.total, value),
- //plotTickness = Math.sin(series.pie.viewAngle)*series.pie.spliceThickness / vScale;
- explodeCoeff = explode + radius + 4,
- distX = Math.cos(bisection) * explodeCoeff,
- distY = Math.sin(bisection) * explodeCoeff,
- textAlign = distX < 0 ? 'right' : 'left',
- textBaseline = distY > 0 ? 'top' : 'bottom',
- style,
- x, y,
- distX, distY;
-
- context.save();
- context.translate(width / 2, height / 2);
- context.scale(1, vScale);
-
- x = Math.cos(bisection) * explode;
- y = Math.sin(bisection) * explode;
-
- // Shadows
- if (shadowSize > 0) {
- this.plotSlice(x + shadowSize, y + shadowSize, radius, startAngle, endAngle, context);
- if (fill) {
- context.fillStyle = 'rgba(0,0,0,0.1)';
- context.fill();
- }
- }
-
- this.plotSlice(x, y, radius, startAngle, endAngle, context);
- if (fill) {
- context.fillStyle = fillStyle;
- context.fill();
- }
- context.lineWidth = lineWidth;
- context.strokeStyle = color;
- context.stroke();
-
- style = {
- size : options.fontSize * 1.2,
- color : options.fontColor,
- weight : 1.5
- };
-
- if (label) {
- if (options.htmlText || !options.textEnabled) {
- divStyle = 'position:absolute;' + textBaseline + ':' + (height / 2 + (textBaseline === 'top' ? distY : -distY)) + 'px;';
- divStyle += textAlign + ':' + (width / 2 + (textAlign === 'right' ? -distX : distX)) + 'px;';
- html.push('<div style="', divStyle, '" class="flotr-grid-label">', label, '</div>');
- }
- else {
- style.textAlign = textAlign;
- style.textBaseline = textBaseline;
- Flotr.drawText(context, label, distX, distY, style);
- }
- }
-
- if (options.htmlText || !options.textEnabled) {
- var div = Flotr.DOM.node('<div style="color:' + options.fontColor + '" class="flotr-labels"></div>');
- Flotr.DOM.insert(div, html.join(''));
- Flotr.DOM.insert(options.element, div);
- }
-
- context.restore();
-
- // New start angle
- this.startAngle = endAngle;
- this.slices = this.slices || [];
- this.slices.push({
- radius : Math.min(canvas.width, canvas.height) * sizeRatio / 2,
- x : x,
- y : y,
- explode : explode,
- start : startAngle,
- end : endAngle
- });
- },
- plotSlice : function (x, y, radius, startAngle, endAngle, context) {
- context.beginPath();
- context.moveTo(x, y);
- context.arc(x, y, radius, startAngle, endAngle, false);
- context.lineTo(x, y);
- context.closePath();
- },
- hit : function (options) {
-
- var
- data = options.data[0],
- args = options.args,
- index = options.index,
- mouse = args[0],
- n = args[1],
- slice = this.slices[index],
- x = mouse.relX - options.width / 2,
- y = mouse.relY - options.height / 2,
- r = Math.sqrt(x * x + y * y),
- theta = Math.atan(y / x),
- circle = Math.PI * 2,
- explode = slice.explode || options.explode,
- start = slice.start % circle,
- end = slice.end % circle;
-
- if (x < 0) {
- theta += Math.PI;
- } else if (x > 0 && y < 0) {
- theta += circle;
- }
-
- if (r < slice.radius + explode && r > explode) {
- if ((start > end && (theta < end || theta > start)) ||
- (theta > start && theta < end)) {
-
- // TODO Decouple this from hit plugin (chart shouldn't know what n means)
- n.x = data[0];
- n.y = data[1];
- n.sAngle = start;
- n.eAngle = end;
- n.index = 0;
- n.seriesIndex = index;
- n.fraction = data[1] / this.total;
- }
- }
- },
- drawHit: function (options) {
- var
- context = options.context,
- slice = this.slices[options.args.seriesIndex];
-
- context.save();
- context.translate(options.width / 2, options.height / 2);
- this.plotSlice(slice.x, slice.y, slice.radius, slice.start, slice.end, context);
- context.stroke();
- context.restore();
- },
- clearHit : function (options) {
- var
- context = options.context,
- slice = this.slices[options.args.seriesIndex],
- padding = 2 * options.lineWidth,
- radius = slice.radius + padding;
-
- context.save();
- context.translate(options.width / 2, options.height / 2);
- context.clearRect(
- slice.x - radius,
- slice.y - radius,
- 2 * radius + padding,
- 2 * radius + padding
- );
- context.restore();
- },
- extendYRange : function (axis, data) {
- this.total = (this.total || 0) + data[0][1];
- }
-});
-})();
diff --git a/addons/web_graph/static/lib/flotr2/js/types/points.js b/addons/web_graph/static/lib/flotr2/js/types/points.js
deleted file mode 100644
index ebb360e6fae..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/points.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/** 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
- },
-
- draw : function (options) {
- var
- context = options.context,
- lineWidth = options.lineWidth,
- shadowSize = options.shadowSize;
-
- context.save();
-
- if (shadowSize > 0) {
- context.lineWidth = shadowSize / 2;
-
- context.strokeStyle = 'rgba(0,0,0,0.1)';
- this.plot(options, shadowSize / 2 + context.lineWidth / 2);
-
- context.strokeStyle = 'rgba(0,0,0,0.2)';
- this.plot(options, context.lineWidth / 2);
- }
-
- context.lineWidth = options.lineWidth;
- context.strokeStyle = options.color;
- context.fillStyle = options.fillColor || options.color;
-
- this.plot(options);
- context.restore();
- },
-
- plot : function (options, offset) {
- var
- data = options.data,
- context = options.context,
- xScale = options.xScale,
- yScale = options.yScale,
- i, x, y;
-
- for (i = data.length - 1; i > -1; --i) {
- y = data[i][1];
- if (y === null) continue;
-
- x = xScale(data[i][0]);
- y = yScale(y);
-
- if (x < 0 || x > options.width || y < 0 || y > options.height) continue;
-
- context.beginPath();
- if (offset) {
- context.arc(x, y + offset, options.radius, 0, Math.PI, false);
- } else {
- context.arc(x, y, options.radius, 0, 2 * Math.PI, true);
- if (options.fill) context.fill();
- }
- context.stroke();
- context.closePath();
- }
- }
-});
diff --git a/addons/web_graph/static/lib/flotr2/js/types/radar.js b/addons/web_graph/static/lib/flotr2/js/types/radar.js
deleted file mode 100644
index d693ddc78ec..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/radar.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/** Radar **/
-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 (options) {
- var
- context = options.context,
- shadowSize = options.shadowSize;
-
- context.save();
- context.translate(options.width / 2, options.height / 2);
- context.lineWidth = options.lineWidth;
-
- // Shadow
- context.fillStyle = 'rgba(0,0,0,0.05)';
- context.strokeStyle = 'rgba(0,0,0,0.05)';
- this.plot(options, shadowSize / 2);
- context.strokeStyle = 'rgba(0,0,0,0.1)';
- this.plot(options, shadowSize / 4);
-
- // Chart
- context.strokeStyle = options.color;
- context.fillStyle = options.fillStyle;
- this.plot(options);
-
- context.restore();
- },
- plot : function (options, offset) {
- var
- data = options.data,
- context = options.context,
- radius = Math.min(options.height, options.width) * options.radiusRatio / 2,
- step = 2 * Math.PI / data.length,
- angle = -Math.PI / 2,
- i, ratio;
-
- offset = offset || 0;
-
- context.beginPath();
- for (i = 0; i < data.length; ++i) {
- ratio = data[i][1] / this.max;
-
- context[i === 0 ? 'moveTo' : 'lineTo'](
- Math.cos(i * step + angle) * radius * ratio + offset,
- Math.sin(i * step + angle) * radius * ratio + offset
- );
- }
- context.closePath();
- if (options.fill) context.fill();
- context.stroke();
- },
- extendYRange : function (axis, data) {
- this.max = Math.max(axis.max, this.max || -Number.MAX_VALUE);
- }
-});
diff --git a/addons/web_graph/static/lib/flotr2/js/types/timeline.js b/addons/web_graph/static/lib/flotr2/js/types/timeline.js
deleted file mode 100644
index 59ea6094c01..00000000000
--- a/addons/web_graph/static/lib/flotr2/js/types/timeline.js
+++ /dev/null
@@ -1,90 +0,0 @@
-Flotr.addType('timeline', {
- options: {
- show: false,
- lineWidth: 1,
- barWidth: 0.2,
- fill: true,
- fillColor: null,
- fillOpacity: 0.4,
- centered: true
- },
-
- draw : function (options) {
-
- var
- context = options.context;
-
- context.save();
- context.lineJoin = 'miter';
- context.lineWidth = options.lineWidth;
- context.strokeStyle = options.color;
- context.fillStyle = options.fillStyle;
-
- this.plot(options);
-
- context.restore();
- },
-
- plot : function (options) {
-
- var
- data = options.data,
- context = options.context,
- xScale = options.xScale,
- yScale = options.yScale,
- barWidth = options.barWidth,
- lineWidth = options.lineWidth,
- i;
-
- Flotr._.each(data, function (timeline) {
-
- var
- x = timeline[0],
- y = timeline[1],
- w = timeline[2],
- h = barWidth,
-
- xt = Math.ceil(xScale(x)),
- wt = Math.ceil(xScale(x + w)) - xt,
- yt = Math.round(yScale(y)),
- ht = Math.round(yScale(y - h)) - yt,
-
- x0 = xt - lineWidth / 2,
- y0 = Math.round(yt - ht / 2) - lineWidth / 2;
-
- context.strokeRect(x0, y0, wt, ht);
- context.fillRect(x0, y0, wt, ht);
-
- });
- },
-
- extendRange : function (series) {
-
- var
- data = series.data,
- xa = series.xaxis,
- ya = series.yaxis,
- w = series.timeline.barWidth;
-
- if (xa.options.min === null)
- xa.min = xa.datamin - w / 2;
-
- if (xa.options.max === null) {
-
- var
- max = xa.max;
-
- Flotr._.each(data, function (timeline) {
- max = Math.max(max, timeline[0] + timeline[2]);
- }, this);
-
- xa.max = max + w / 2;
- }
-
- if (ya.options.min === null)
- ya.min = ya.datamin - w;
- if (ya.options.min === null)
- ya.max = ya.datamax + w;
- }
-
-});
diff --git a/addons/web_graph/static/lib/flotr2/lib/base64.js b/addons/web_graph/static/lib/flotr2/lib/base64.js
deleted file mode 100644
index 3306e49f9f7..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/base64.js
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
- * 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/addons/web_graph/static/lib/flotr2/lib/bean-min.js b/addons/web_graph/static/lib/flotr2/lib/bean-min.js
deleted file mode 100644
index 2471420fe25..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/bean-min.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/*!
- * bean.js - copyright Jacob Thornton 2011
- * https://github.com/fat/bean
- * MIT License
- * special thanks to:
- * dean edwards: http://dean.edwards.name/
- * dperini: https://github.com/dperini/nwevents
- * the entire mootools team: github.com/mootools/mootools-core
- *//*global module:true, define:true*/
-!function(a,b,c){typeof module!="undefined"?module.exports=c(a,b):typeof define=="function"&&typeof define.amd=="object"?define(c):b[a]=c(a,b)}("bean",this,function(a,b){var c=window,d=b[a],e=/over|out/,f=/[^\.]*(?=\..*)\.|.*/,g=/\..*/,h="addEventListener",i="attachEvent",j="removeEventListener",k="detachEvent",l=document||{},m=l.documentElement||{},n=m[h],o=n?h:i,p=Array.prototype.slice,q=/click|mouse|menu|drag|drop/i,r=/^touch|^gesture/i,s={one:1},t=function(a,b,c){for(c=0;c<b.length;c++)a[b[c]]=1;return a}({},("click dblclick mouseup mousedown contextmenu mousewheel DOMMouseScroll mouseover mouseout mousemove selectstart selectend keydown keypress keyup orientationchange focus blur change reset select submit load unload beforeunload resize move DOMContentLoaded readystatechange error abort scroll "+(n?"show input invalid touchstart touchmove touchend touchcancel gesturestart gesturechange gestureend message readystatechange pageshow pagehide popstate hashchange offline online afterprint beforeprint dragstart dragenter dragover dragleave drag drop dragend loadstart progress suspend emptied stalled loadmetadata loadeddata canplay canplaythrough playing waiting seeking seeked ended durationchange timeupdate play pause ratechange volumechange cuechange checking noupdate downloading cached updateready obsolete ":"")).split(" ")),u=function(){function a(a,b){while((b=b.parentNode)!==null)if(b===a)return!0;return!1}function b(b){var c=b.relatedTarget;return c?c!==this&&c.prefix!=="xul"&&!/document/.test(this.toString())&&!a(this,c):c===null}return{mouseenter:{base:"mouseover",condition:b},mouseleave:{base:"mouseout",condition:b},mousewheel:{base:/Firefox/.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel"}}}(),v=function(){var a="altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which".split(" "),b=a.concat("button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" ")),c=a.concat("char charCode key keyCode".split(" ")),d=a.concat("touches targetTouches changedTouches scale rotation".split(" ")),f="preventDefault",g=function(a){return function(){a[f]?a[f]():a.returnValue=!1}},h="stopPropagation",i=function(a){return function(){a[h]?a[h]():a.cancelBubble=!0}},j=function(a){return function(){a[f](),a[h](),a.stopped=!0}},k=function(a,b,c){var d,e;for(d=c.length;d--;)e=c[d],!(e in b)&&e in a&&(b[e]=a[e])};return function(n,o){var p={originalEvent:n,isNative:o};if(!n)return p;var s,t=n.type,u=n.target||n.srcElement;p[f]=g(n),p[h]=i(n),p.stop=j(p),p.target=u&&u.nodeType===3?u.parentNode:u;if(o){if(t.indexOf("key")!==-1)s=c,p.keyCode=n.which||n.keyCode;else if(q.test(t)){s=b,p.rightClick=n.which===3||n.button===2,p.pos={x:0,y:0};if(n.pageX||n.pageY)p.clientX=n.pageX,p.clientY=n.pageY;else if(n.clientX||n.clientY)p.clientX=n.clientX+l.body.scrollLeft+m.scrollLeft,p.clientY=n.clientY+l.body.scrollTop+m.scrollTop;e.test(t)&&(p.relatedTarget=n.relatedTarget||n[(t==="mouseover"?"from":"to")+"Element"])}else r.test(t)&&(s=d);k(n,p,s||a)}return p}}(),w=function(a,b){return!n&&!b&&(a===l||a===c)?m:a},x=function(){function a(a,b,c,d,e){this.element=a,this.type=b,this.handler=c,this.original=d,this.namespaces=e,this.custom=u[b],this.isNative=t[b]&&a[o],this.eventType=n||this.isNative?b:"propertychange",this.customType=!n&&!this.isNative&&b,this.target=w(a,this.isNative),this.eventSupport=this.target[o]}return a.prototype={inNamespaces:function(a){var b,c;if(!a)return!0;if(!this.namespaces)return!1;for(b=a.length;b--;)for(c=this.namespaces.length;c--;)if(a[b]===this.namespaces[c])return!0;return!1},matches:function(a,b,c){return this.element===a&&(!b||this.original===b)&&(!c||this.handler===c)}},a}(),y=function(){var a={},b=function(c,d,e,f,g){if(!d||d==="*")for(var h in a)h.charAt(0)==="$"&&b(c,h.substr(1),e,f,g);else{var i=0,j,k=a["$"+d],l=c==="*";if(!k)return;for(j=k.length;i<j;i++)if(l||k[i].matches(c,e,f))if(!g(k[i],k,i,d))return}},c=function(b,c,d){var e,f=a["$"+c];if(f)for(e=f.length;e--;)if(f[e].matches(b,d,null))return!0;return!1},d=function(a,c,d){var e=[];return b(a,c,d,null,function(a){return e.push(a)}),e},e=function(b){return(a["$"+b.type]||(a["$"+b.type]=[])).push(b),b},f=function(c){b(c.element,c.type,null,c.handler,function(b,c,d){return c.splice(d,1),c.length===0&&delete a["$"+b.type],!1})},g=function(){var b,c=[];for(b in a)b.charAt(0)==="$"&&(c=c.concat(a[b]));return c};return{has:c,get:d,put:e,del:f,entries:g}}(),z=n?function(a,b,c,d){a[d?h:j](b,c,!1)}:function(a,b,c,d,e){e&&d&&a["_on"+e]===null&&(a["_on"+e]=0),a[d?i:k]("on"+b,c)},A=function(a,b,d){return function(e){return e=v(e||((this.ownerDocument||this.document||this).parentWindow||c).event,!0),b.apply(a,[e].concat(d))}},B=function(a,b,d,e,f,g){return function(h){if(e?e.apply(this,arguments):n?!0:h&&h.propertyName==="_on"+d||!h)h&&(h=v(h||((this.ownerDocument||this.document||this).parentWindow||c).event,g)),b.apply(a,h&&(!f||f.length===0)?arguments:p.call(arguments,h?0:1).concat(f))}},C=function(a,b,c,d,e){return function(){a(b,c,e),d.apply(this,arguments)}},D=function(a,b,c,d){var e,f,h,i=b&&b.replace(g,""),j=y.get(a,i,c);for(e=0,f=j.length;e<f;e++)j[e].inNamespaces(d)&&((h=j[e]).eventSupport&&z(h.target,h.eventType,h.handler,!1,h.type),y.del(h))},E=function(a,b,c,d,e){var h,i=b.replace(g,""),j=b.replace(f,"").split(".");if(y.has(a,i,c))return a;i==="unload"&&(c=C(D,a,i,c,d)),u[i]&&(u[i].condition&&(c=B(a,c,i,u[i].condition,!0)),i=u[i].base||i),h=y.put(new x(a,i,c,d,j[0]&&j)),h.handler=h.isNative?A(a,h.handler,e):B(a,h.handler,i,!1,e,!1),h.eventSupport&&z(h.target,h.eventType,h.handler,!0,h.customType)},F=function(a,b,c){return function(d){var e,f,g=typeof a=="string"?c(a,this):a;for(e=d.target;e&&e!==this;e=e.parentNode)for(f=g.length;f--;)if(g[f]===e)return b.apply(e,arguments)}},G=function(a,b,c){var d,e,h,i,j,k=D,l=b&&typeof b=="string";if(l&&b.indexOf(" ")>0){b=b.split(" ");for(j=b.length;j--;)G(a,b[j],c);return a}h=l&&b.replace(g,""),h&&u[h]&&(h=u[h].type);if(!b||l){if(i=l&&b.replace(f,""))i=i.split(".");k(a,h,c,i)}else if(typeof b=="function")k(a,null,b);else for(d in b)b.hasOwnProperty(d)&&G(a,d,b[d]);return a},H=function(a,b,c,d,e){var f,g,h,i,j=c,k=c&&typeof c=="string";if(b&&!c&&typeof b=="object")for(f in b)b.hasOwnProperty(f)&&H.apply(this,[a,f,b[f]]);else{i=arguments.length>3?p.call(arguments,3):[],g=(k?c:b).split(" "),k&&(c=F(b,j=d,e))&&(i=p.call(i,1)),this===s&&(c=C(G,a,b,c,j));for(h=g.length;h--;)E(a,g[h],c,j,i)}return a},I=function(){return H.apply(s,arguments)},J=n?function(a,b,d){var e=l.createEvent(a?"HTMLEvents":"UIEvents");e[a?"initEvent":"initUIEvent"](b,!0,!0,c,1),d.dispatchEvent(e)}:function(a,b,c){c=w(c,a),a?c.fireEvent("on"+b,l.createEventObject()):c["_on"+b]++},K=function(a,b,c){var d,e,h,i,j,k=b.split(" ");for(d=k.length;d--;){b=k[d].replace(g,"");if(i=k[d].replace(f,""))i=i.split(".");if(!i&&!c&&a[o])J(t[b],b,a);else{j=y.get(a,b),c=[!1].concat(c);for(e=0,h=j.length;e<h;e++)j[e].inNamespaces(i)&&j[e].handler.apply(a,c)}}return a},L=function(a,b,c){var d=0,e=y.get(b,c),f=e.length;for(;d<f;d++)e[d].original&&H(a,e[d].type,e[d].original);return a},M={add:H,one:I,remove:G,clone:L,fire:K,noConflict:function(){return b[a]=d,this}};if(c[i]){var N=function(){var a,b=y.entries();for(a in b)b[a].type&&b[a].type!=="unload"&&G(b[a].element,b[a].type);c[k]("onunload",N),c.CollectGarbage&&c.CollectGarbage()};c[i]("onunload",N)}return M}) \ No newline at end of file
diff --git a/addons/web_graph/static/lib/flotr2/lib/bean.js b/addons/web_graph/static/lib/flotr2/lib/bean.js
deleted file mode 100644
index 1a854771006..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/bean.js
+++ /dev/null
@@ -1,501 +0,0 @@
-/*!
- * bean.js - copyright Jacob Thornton 2011
- * https://github.com/fat/bean
- * MIT License
- * special thanks to:
- * dean edwards: http://dean.edwards.name/
- * dperini: https://github.com/dperini/nwevents
- * the entire mootools team: github.com/mootools/mootools-core
- */
-/*global module:true, define:true*/
-!function (name, context, definition) {
- context[name] = definition(name, context);
-}('bean', this, function (name, context) {
- var win = window
- , old = context[name]
- , overOut = /over|out/
- , namespaceRegex = /[^\.]*(?=\..*)\.|.*/
- , nameRegex = /\..*/
- , addEvent = 'addEventListener'
- , attachEvent = 'attachEvent'
- , removeEvent = 'removeEventListener'
- , detachEvent = 'detachEvent'
- , doc = document || {}
- , root = doc.documentElement || {}
- , W3C_MODEL = root[addEvent]
- , eventSupport = W3C_MODEL ? addEvent : attachEvent
- , slice = Array.prototype.slice
- , mouseTypeRegex = /click|mouse|menu|drag|drop/i
- , touchTypeRegex = /^touch|^gesture/i
- , ONE = { one: 1 } // singleton for quick matching making add() do one()
-
- , nativeEvents = (function (hash, events, i) {
- for (i = 0; i < events.length; i++)
- hash[events[i]] = 1
- return hash
- })({}, (
- 'click dblclick mouseup mousedown contextmenu ' + // mouse buttons
- 'mousewheel DOMMouseScroll ' + // mouse wheel
- 'mouseover mouseout mousemove selectstart selectend ' + // mouse movement
- 'keydown keypress keyup ' + // keyboard
- 'orientationchange ' + // mobile
- 'focus blur change reset select submit ' + // form elements
- 'load unload beforeunload resize move DOMContentLoaded readystatechange ' + // window
- 'error abort scroll ' + // misc
- (W3C_MODEL ? // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event
- // that doesn't actually exist, so make sure we only do these on newer browsers
- 'show ' + // mouse buttons
- 'input invalid ' + // form elements
- 'touchstart touchmove touchend touchcancel ' + // touch
- 'gesturestart gesturechange gestureend ' + // gesture
- 'message readystatechange pageshow pagehide popstate ' + // window
- 'hashchange offline online ' + // window
- 'afterprint beforeprint ' + // printing
- 'dragstart dragenter dragover dragleave drag drop dragend ' + // dnd
- 'loadstart progress suspend emptied stalled loadmetadata ' + // media
- 'loadeddata canplay canplaythrough playing waiting seeking ' + // media
- 'seeked ended durationchange timeupdate play pause ratechange ' + // media
- 'volumechange cuechange ' + // media
- 'checking noupdate downloading cached updateready obsolete ' + // appcache
- '' : '')
- ).split(' ')
- )
-
- , customEvents = (function () {
- function isDescendant(parent, node) {
- while ((node = node.parentNode) !== null) {
- if (node === parent) return true
- }
- return false
- }
-
- function check(event) {
- var related = event.relatedTarget
- if (!related) return related === null
- return (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isDescendant(this, related))
- }
-
- return {
- mouseenter: { base: 'mouseover', condition: check }
- , mouseleave: { base: 'mouseout', condition: check }
- , mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' }
- }
- })()
-
- , fixEvent = (function () {
- var commonProps = 'altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which'.split(' ')
- , mouseProps = commonProps.concat('button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement'.split(' '))
- , keyProps = commonProps.concat('char charCode key keyCode'.split(' '))
- , touchProps = commonProps.concat('touches targetTouches changedTouches scale rotation'.split(' '))
- , preventDefault = 'preventDefault'
- , createPreventDefault = function (event) {
- return function () {
- if (event[preventDefault])
- event[preventDefault]()
- else
- event.returnValue = false
- }
- }
- , stopPropagation = 'stopPropagation'
- , createStopPropagation = function (event) {
- return function () {
- if (event[stopPropagation])
- event[stopPropagation]()
- else
- event.cancelBubble = true
- }
- }
- , createStop = function (synEvent) {
- return function () {
- synEvent[preventDefault]()
- synEvent[stopPropagation]()
- synEvent.stopped = true
- }
- }
- , copyProps = function (event, result, props) {
- var i, p
- for (i = props.length; i--;) {
- p = props[i]
- if (!(p in result) && p in event) result[p] = event[p]
- }
- }
-
- return function (event, isNative) {
- var result = { originalEvent: event, isNative: isNative }
- if (!event)
- return result
-
- var props
- , type = event.type
- , target = event.target || event.srcElement
-
- result[preventDefault] = createPreventDefault(event)
- result[stopPropagation] = createStopPropagation(event)
- result.stop = createStop(result)
- result.target = target && target.nodeType === 3 ? target.parentNode : target
-
- if (isNative) { // we only need basic augmentation on custom events, the rest is too expensive
- if (type.indexOf('key') !== -1) {
- props = keyProps
- result.keyCode = event.which || event.keyCode
- } else if (mouseTypeRegex.test(type)) {
- props = mouseProps
- result.rightClick = event.which === 3 || event.button === 2
- result.pos = { x: 0, y: 0 }
- if (event.pageX || event.pageY) {
- result.clientX = event.pageX
- result.clientY = event.pageY
- } else if (event.clientX || event.clientY) {
- result.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft
- result.clientY = event.clientY + doc.body.scrollTop + root.scrollTop
- }
- if (overOut.test(type))
- result.relatedTarget = event.relatedTarget || event[(type === 'mouseover' ? 'from' : 'to') + 'Element']
- } else if (touchTypeRegex.test(type)) {
- props = touchProps
- }
- copyProps(event, result, props || commonProps)
- }
- return result
- }
- })()
-
- // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both
- , targetElement = function (element, isNative) {
- return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element
- }
-
- // we use one of these per listener, of any type
- , RegEntry = (function () {
- function entry(element, type, handler, original, namespaces) {
- this.element = element
- this.type = type
- this.handler = handler
- this.original = original
- this.namespaces = namespaces
- this.custom = customEvents[type]
- this.isNative = nativeEvents[type] && element[eventSupport]
- this.eventType = W3C_MODEL || this.isNative ? type : 'propertychange'
- this.customType = !W3C_MODEL && !this.isNative && type
- this.target = targetElement(element, this.isNative)
- this.eventSupport = this.target[eventSupport]
- }
-
- entry.prototype = {
- // given a list of namespaces, is our entry in any of them?
- inNamespaces: function (checkNamespaces) {
- var i, j
- if (!checkNamespaces)
- return true
- if (!this.namespaces)
- return false
- for (i = checkNamespaces.length; i--;) {
- for (j = this.namespaces.length; j--;) {
- if (checkNamespaces[i] === this.namespaces[j])
- return true
- }
- }
- return false
- }
-
- // match by element, original fn (opt), handler fn (opt)
- , matches: function (checkElement, checkOriginal, checkHandler) {
- return this.element === checkElement &&
- (!checkOriginal || this.original === checkOriginal) &&
- (!checkHandler || this.handler === checkHandler)
- }
- }
-
- return entry
- })()
-
- , registry = (function () {
- // our map stores arrays by event type, just because it's better than storing
- // everything in a single array. uses '$' as a prefix for the keys for safety
- var map = {}
-
- // generic functional search of our registry for matching listeners,
- // `fn` returns false to break out of the loop
- , forAll = function (element, type, original, handler, fn) {
- if (!type || type === '*') {
- // search the whole registry
- for (var t in map) {
- if (t.charAt(0) === '$')
- forAll(element, t.substr(1), original, handler, fn)
- }
- } else {
- var i = 0, l, list = map['$' + type], all = element === '*'
- if (!list)
- return
- for (l = list.length; i < l; i++) {
- if (all || list[i].matches(element, original, handler))
- if (!fn(list[i], list, i, type))
- return
- }
- }
- }
-
- , has = function (element, type, original) {
- // we're not using forAll here simply because it's a bit slower and this
- // needs to be fast
- var i, list = map['$' + type]
- if (list) {
- for (i = list.length; i--;) {
- if (list[i].matches(element, original, null))
- return true
- }
- }
- return false
- }
-
- , get = function (element, type, original) {
- var entries = []
- forAll(element, type, original, null, function (entry) { return entries.push(entry) })
- return entries
- }
-
- , put = function (entry) {
- (map['$' + entry.type] || (map['$' + entry.type] = [])).push(entry)
- return entry
- }
-
- , del = function (entry) {
- forAll(entry.element, entry.type, null, entry.handler, function (entry, list, i) {
- list.splice(i, 1)
- if (list.length === 0)
- delete map['$' + entry.type]
- return false
- })
- }
-
- // dump all entries, used for onunload
- , entries = function () {
- var t, entries = []
- for (t in map) {
- if (t.charAt(0) === '$')
- entries = entries.concat(map[t])
- }
- return entries
- }
-
- return { has: has, get: get, put: put, del: del, entries: entries }
- })()
-
- // add and remove listeners to DOM elements
- , listener = W3C_MODEL ? function (element, type, fn, add) {
- element[add ? addEvent : removeEvent](type, fn, false)
- } : function (element, type, fn, add, custom) {
- if (custom && add && element['_on' + custom] === null)
- element['_on' + custom] = 0
- element[add ? attachEvent : detachEvent]('on' + type, fn)
- }
-
- , nativeHandler = function (element, fn, args) {
- return function (event) {
- event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, true)
- return fn.apply(element, [event].concat(args))
- }
- }
-
- , customHandler = function (element, fn, type, condition, args, isNative) {
- return function (event) {
- if (condition ? condition.apply(this, arguments) : W3C_MODEL ? true : event && event.propertyName === '_on' + type || !event) {
- if (event)
- event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, isNative)
- fn.apply(element, event && (!args || args.length === 0) ? arguments : slice.call(arguments, event ? 0 : 1).concat(args))
- }
- }
- }
-
- , once = function (rm, element, type, fn, originalFn) {
- // wrap the handler in a handler that does a remove as well
- return function () {
- rm(element, type, originalFn)
- fn.apply(this, arguments)
- }
- }
-
- , removeListener = function (element, orgType, handler, namespaces) {
- var i, l, entry
- , type = (orgType && orgType.replace(nameRegex, ''))
- , handlers = registry.get(element, type, handler)
-
- for (i = 0, l = handlers.length; i < l; i++) {
- if (handlers[i].inNamespaces(namespaces)) {
- if ((entry = handlers[i]).eventSupport)
- listener(entry.target, entry.eventType, entry.handler, false, entry.type)
- // TODO: this is problematic, we have a registry.get() and registry.del() that
- // both do registry searches so we waste cycles doing this. Needs to be rolled into
- // a single registry.forAll(fn) that removes while finding, but the catch is that
- // we'll be splicing the arrays that we're iterating over. Needs extra tests to
- // make sure we don't screw it up. @rvagg
- registry.del(entry)
- }
- }
- }
-
- , addListener = function (element, orgType, fn, originalFn, args) {
- var entry
- , type = orgType.replace(nameRegex, '')
- , namespaces = orgType.replace(namespaceRegex, '').split('.')
-
- if (registry.has(element, type, fn))
- return element // no dupe
- if (type === 'unload')
- fn = once(removeListener, element, type, fn, originalFn) // self clean-up
- if (customEvents[type]) {
- if (customEvents[type].condition)
- fn = customHandler(element, fn, type, customEvents[type].condition, true)
- type = customEvents[type].base || type
- }
- entry = registry.put(new RegEntry(element, type, fn, originalFn, namespaces[0] && namespaces))
- entry.handler = entry.isNative ?
- nativeHandler(element, entry.handler, args) :
- customHandler(element, entry.handler, type, false, args, false)
- if (entry.eventSupport)
- listener(entry.target, entry.eventType, entry.handler, true, entry.customType)
- }
-
- , del = function (selector, fn, $) {
- return function (e) {
- var target, i, array = typeof selector === 'string' ? $(selector, this) : selector
- for (target = e.target; target && target !== this; target = target.parentNode) {
- for (i = array.length; i--;) {
- if (array[i] === target) {
- return fn.apply(target, arguments)
- }
- }
- }
- }
- }
-
- , remove = function (element, typeSpec, fn) {
- var k, m, type, namespaces, i
- , rm = removeListener
- , isString = typeSpec && typeof typeSpec === 'string'
-
- if (isString && typeSpec.indexOf(' ') > 0) {
- // remove(el, 't1 t2 t3', fn) or remove(el, 't1 t2 t3')
- typeSpec = typeSpec.split(' ')
- for (i = typeSpec.length; i--;)
- remove(element, typeSpec[i], fn)
- return element
- }
- type = isString && typeSpec.replace(nameRegex, '')
- if (type && customEvents[type])
- type = customEvents[type].type
- if (!typeSpec || isString) {
- // remove(el) or remove(el, t1.ns) or remove(el, .ns) or remove(el, .ns1.ns2.ns3)
- if (namespaces = isString && typeSpec.replace(namespaceRegex, ''))
- namespaces = namespaces.split('.')
- rm(element, type, fn, namespaces)
- } else if (typeof typeSpec === 'function') {
- // remove(el, fn)
- rm(element, null, typeSpec)
- } else {
- // remove(el, { t1: fn1, t2, fn2 })
- for (k in typeSpec) {
- if (typeSpec.hasOwnProperty(k))
- remove(element, k, typeSpec[k])
- }
- }
- return element
- }
-
- , add = function (element, events, fn, delfn, $) {
- var type, types, i, args
- , originalFn = fn
- , isDel = fn && typeof fn === 'string'
-
- if (events && !fn && typeof events === 'object') {
- for (type in events) {
- if (events.hasOwnProperty(type))
- add.apply(this, [ element, type, events[type] ])
- }
- } else {
- args = arguments.length > 3 ? slice.call(arguments, 3) : []
- types = (isDel ? fn : events).split(' ')
- isDel && (fn = del(events, (originalFn = delfn), $)) && (args = slice.call(args, 1))
- // special case for one()
- this === ONE && (fn = once(remove, element, events, fn, originalFn))
- for (i = types.length; i--;) addListener(element, types[i], fn, originalFn, args)
- }
- return element
- }
-
- , one = function () {
- return add.apply(ONE, arguments)
- }
-
- , fireListener = W3C_MODEL ? function (isNative, type, element) {
- var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents')
- evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1)
- element.dispatchEvent(evt)
- } : function (isNative, type, element) {
- element = targetElement(element, isNative)
- // if not-native then we're using onpropertychange so we just increment a custom property
- isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++
- }
-
- , fire = function (element, type, args) {
- var i, j, l, names, handlers
- , types = type.split(' ')
-
- for (i = types.length; i--;) {
- type = types[i].replace(nameRegex, '')
- if (names = types[i].replace(namespaceRegex, ''))
- names = names.split('.')
- if (!names && !args && element[eventSupport]) {
- fireListener(nativeEvents[type], type, element)
- } else {
- // non-native event, either because of a namespace, arguments or a non DOM element
- // iterate over all listeners and manually 'fire'
- handlers = registry.get(element, type)
- args = [false].concat(args)
- for (j = 0, l = handlers.length; j < l; j++) {
- if (handlers[j].inNamespaces(names))
- handlers[j].handler.apply(element, args)
- }
- }
- }
- return element
- }
-
- , clone = function (element, from, type) {
- var i = 0
- , handlers = registry.get(from, type)
- , l = handlers.length
-
- for (;i < l; i++)
- handlers[i].original && add(element, handlers[i].type, handlers[i].original)
- return element
- }
-
- , bean = {
- add: add
- , one: one
- , remove: remove
- , clone: clone
- , fire: fire
- , noConflict: function () {
- context[name] = old
- return this
- }
- }
-
- if (win[attachEvent]) {
- // for IE, clean up on unload to avoid leaks
- var cleanup = function () {
- var i, entries = registry.entries()
- for (i in entries) {
- if (entries[i].type && entries[i].type !== 'unload')
- remove(entries[i].element, entries[i].type)
- }
- win[detachEvent]('onunload', cleanup)
- win.CollectGarbage && win.CollectGarbage()
- }
- win[attachEvent]('onunload', cleanup)
- }
-
- return bean
-});
diff --git a/addons/web_graph/static/lib/flotr2/lib/canvas2image.js b/addons/web_graph/static/lib/flotr2/lib/canvas2image.js
deleted file mode 100644
index e064cdac8b9..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/canvas2image.js
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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"),
- sc = String.fromCharCode,
- strDownloadMime = "image/octet-stream",
- bReplaceDownloadMime = false;
-
- // no canvas, bail out.
- if (!oCanvas.getContext) {
- return {
- saveAsBMP : function(){},
- saveAsPNG : function(){},
- saveAsJPEG : function(){}
- }
- }
-
- var bHasImageData = !!(oCanvas.getContext("2d").getImageData),
- bHasDataURL = !!(oCanvas.toDataURL),
- bHasBase64 = !!(window.btoa);
-
- // ok, we're good
- var readCanvasData = function(oCanvas) {
- var iWidth = parseInt(oCanvas.width),
- 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 i, aData, strData = "";
-
- if (typeof data == "string") {
- strData = data;
- } else {
- aData = data;
- for (i = 0; i < aData.length; i++) {
- strData += sc(aData[i]);
- }
- }
- return btoa(strData);
- }
-
- // creates a base64 encoded string containing BMP data takes an imagedata object as argument
- var createBMP = function(oData) {
- var strHeader = '',
- iWidth = oData.width,
- iHeight = oData.height;
-
- strHeader += 'BM';
-
- var iFileSize = iWidth*iHeight*4 + 54; // total header size = 54 bytes
- strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
- strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
- strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
- strHeader += sc(iFileSize % 256);
-
- strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset
- strHeader += sc(40, 0, 0, 0); // info header size
-
- var iImageWidth = iWidth;
- strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
- strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
- strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
- strHeader += sc(iImageWidth % 256);
-
- var iImageHeight = iHeight;
- strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
- strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
- strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
- strHeader += sc(iImageHeight % 256);
-
- strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel
- strHeader += sc(0, 0, 0, 0); // compression = none
-
- var iDataSize = iWidth*iHeight*4;
- strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
- strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
- strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
- strHeader += sc(iDataSize % 256);
-
- strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used
-
- var aImgData = oData.data,
- strPixelData = "",
- c, x, y = iHeight,
- iOffsetX, iOffsetY, strPixelRow;
-
- do {
- iOffsetY = iWidth*(y-1)*4;
- strPixelRow = "";
- for (x = 0; x < iWidth; x++) {
- iOffsetX = 4*x;
- strPixelRow += sc(
- aImgData[iOffsetY + iOffsetX + 2], // B
- aImgData[iOffsetY + iOffsetX + 1], // G
- aImgData[iOffsetY + iOffsetX], // R
- aImgData[iOffsetY + iOffsetX + 3] // A
- );
- }
- strPixelData += strPixelRow;
- } while (--y);
-
- return encodeData(strHeader + strPixelData);
- }
-
- // sends the generated file to the client
- var saveFile = function(strData) {
- if (!window.open(strData)) {
- document.location.href = strData;
- }
- }
-
- var makeDataURI = function(strData, strMime) {
- return "data:" + strMime + ";base64," + strData;
- }
-
- // generates a <img> 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),
- strMime = "image/png",
- strData = oScaledCanvas.toDataURL(strMime);
-
- if (bReturnImg) {
- return makeImageObject(strData);
- } else {
- saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
- }
- return true;
- },
-
- saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
- if (!bHasDataURL) return false;
-
- var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
- strMime = "image/jpeg",
- 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(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
- }
- return true;
- },
-
- saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
- if (!(bHasDataURL && bHasImageData && bHasBase64)) return false;
-
- var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
- strMime = "image/bmp",
- oData = readCanvasData(oScaledCanvas),
- strImgData = createBMP(oData);
-
- if (bReturnImg) {
- return makeImageObject(makeDataURI(strImgData, strMime));
- } else {
- saveFile(makeDataURI(strImgData, strMime));
- }
- return true;
- }
- };
-})(); \ No newline at end of file
diff --git a/addons/web_graph/static/lib/flotr2/lib/canvastext.js b/addons/web_graph/static/lib/flotr2/lib/canvastext.js
deleted file mode 100644
index 2df45bae0d8..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/canvastext.js
+++ /dev/null
@@ -1,429 +0,0 @@
-/**
- * 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 Ménager 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: '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: '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'
- textAlign: 'left', // left, right, center
- textBaseline: 'bottom', // top, middle, 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: {},
-
- extend: function(dest, src) {
- for (var property in src) {
- if (property in dest) continue;
- dest[property] = src[property];
- }
- return dest;
- },
-
- /** 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),
- 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)
- }
- },
-
- /** 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;
- CanvasText.extend(style, CanvasText.style);
-
- 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);
- CanvasText.extend(style, align);
- }
-
- switch (style.textAlign) {
- case 'left': break;
- case 'center': offset.x = -measure / 2; break;
- case 'right': offset.x = -measure; break;
- }
-
- switch (style.textBaseline) {
- case 'bottom': break;
- case 'middle': offset.y = style.size / 2; break;
- case 'top': 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.measure = 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/addons/web_graph/static/lib/flotr2/lib/excanvas.js b/addons/web_graph/static/lib/flotr2/lib/excanvas.js
deleted file mode 100644
index 005bab1186f..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/excanvas.js
+++ /dev/null
@@ -1,1425 +0,0 @@
-// Copyright 2006 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-// Known Issues:
-//
-// * Patterns only support repeat.
-// * Radial gradient are not implemented. The VML version of these look very
-// different from the canvas one.
-// * Clipping paths are not implemented.
-// * Coordsize. The width and height attribute have higher priority than the
-// width and height style values which isn't correct.
-// * Painting mode isn't implemented.
-// * Canvas width/height should is using content-box by default. IE in
-// Quirks mode will draw the canvas using border-box. Either change your
-// doctype to HTML5
-// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
-// or use Box Sizing Behavior from WebFX
-// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
-// * Non uniform scaling does not correctly scale strokes.
-// * Optimize. There is always room for speed improvements.
-
-// Only add this code if we do not already have a canvas implementation
-if (!document.createElement('canvas').getContext) {
-
-(function() {
-
- // alias some functions to make (compiled) code shorter
- var m = Math;
- var mr = m.round;
- var ms = m.sin;
- var mc = m.cos;
- var abs = m.abs;
- var sqrt = m.sqrt;
-
- // this is used for sub pixel precision
- var Z = 10;
- var Z2 = Z / 2;
-
- var IE_VERSION = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];
-
- /**
- * This funtion is assigned to the <canvas> elements as element.getContext().
- * @this {HTMLElement}
- * @return {CanvasRenderingContext2D_}
- */
- function getContext() {
- return this.context_ ||
- (this.context_ = new CanvasRenderingContext2D_(this));
- }
-
- var slice = Array.prototype.slice;
-
- /**
- * Binds a function to an object. The returned function will always use the
- * passed in {@code obj} as {@code this}.
- *
- * Example:
- *
- * g = bind(f, obj, a, b)
- * g(c, d) // will do f.call(obj, a, b, c, d)
- *
- * @param {Function} f The function to bind the object to
- * @param {Object} obj The object that should act as this when the function
- * is called
- * @param {*} var_args Rest arguments that will be used as the initial
- * arguments when the function is called
- * @return {Function} A new function that has bound this
- */
- function bind(f, obj, var_args) {
- var a = slice.call(arguments, 2);
- return function() {
- return f.apply(obj, a.concat(slice.call(arguments)));
- };
- }
-
- function encodeHtmlAttribute(s) {
- return String(s).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
- }
-
- function addNamespace(doc, prefix, urn) {
- if (!doc.namespaces[prefix]) {
- doc.namespaces.add(prefix, urn, '#default#VML');
- }
- }
-
- function addNamespacesAndStylesheet(doc) {
- addNamespace(doc, 'g_vml_', 'urn:schemas-microsoft-com:vml');
- addNamespace(doc, 'g_o_', 'urn:schemas-microsoft-com:office:office');
-
- // Setup default CSS. Only add one style sheet per document
- if (!doc.styleSheets['ex_canvas_']) {
- var ss = doc.createStyleSheet();
- ss.owningElement.id = 'ex_canvas_';
- ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
- // default size is 300x150 in Gecko and Opera
- 'text-align:left;width:300px;height:150px}';
- }
- }
-
- // Add namespaces and stylesheet at startup.
- addNamespacesAndStylesheet(document);
-
- var G_vmlCanvasManager_ = {
- init: function(opt_doc) {
- var doc = opt_doc || document;
- // Create a dummy element so that IE will allow canvas elements to be
- // recognized.
- doc.createElement('canvas');
- doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
- },
-
- init_: function(doc) {
- // find all canvas elements
- var els = doc.getElementsByTagName('canvas');
- for (var i = 0; i < els.length; i++) {
- this.initElement(els[i]);
- }
- },
-
- /**
- * Public initializes a canvas element so that it can be used as canvas
- * element from now on. This is called automatically before the page is
- * loaded but if you are creating elements using createElement you need to
- * make sure this is called on the element.
- * @param {HTMLElement} el The canvas element to initialize.
- * @return {HTMLElement} the element that was created.
- */
- initElement: function(el) {
- if (!el.getContext) {
- el.getContext = getContext;
-
- // Add namespaces and stylesheet to document of the element.
- addNamespacesAndStylesheet(el.ownerDocument);
-
- // Remove fallback content. There is no way to hide text nodes so we
- // just remove all childNodes. We could hide all elements and remove
- // text nodes but who really cares about the fallback content.
- el.innerHTML = '';
-
- // do not use inline function because that will leak memory
- el.attachEvent('onpropertychange', onPropertyChange);
- el.attachEvent('onresize', onResize);
-
- var attrs = el.attributes;
- if (attrs.width && attrs.width.specified) {
- // TODO: use runtimeStyle and coordsize
- // el.getContext().setWidth_(attrs.width.nodeValue);
- el.style.width = attrs.width.nodeValue + 'px';
- } else {
- el.width = el.clientWidth;
- }
- if (attrs.height && attrs.height.specified) {
- // TODO: use runtimeStyle and coordsize
- // el.getContext().setHeight_(attrs.height.nodeValue);
- el.style.height = attrs.height.nodeValue + 'px';
- } else {
- el.height = el.clientHeight;
- }
- //el.getContext().setCoordsize_()
- }
- return el;
- }
- };
-
- function onPropertyChange(e) {
- var el = e.srcElement;
-
- switch (e.propertyName) {
- case 'width':
- el.getContext().clearRect();
- el.style.width = el.attributes.width.nodeValue + 'px';
- // In IE8 this does not trigger onresize.
- if (el.firstChild) {
- el.firstChild.style.width = el.clientWidth + 'px';
- }
- break;
- case 'height':
- el.getContext().clearRect();
- el.style.height = el.attributes.height.nodeValue + 'px';
- if (el.firstChild) {
- el.firstChild.style.height = el.clientHeight + 'px';
- }
- break;
- }
- }
-
- function onResize(e) {
- var el = e.srcElement;
- if (el.firstChild) {
- el.firstChild.style.width = el.clientWidth + 'px';
- el.firstChild.style.height = el.clientHeight + 'px';
- }
- }
-
- G_vmlCanvasManager_.init();
-
- // precompute "00" to "FF"
- var decToHex = [];
- for (var i = 0; i < 16; i++) {
- for (var j = 0; j < 16; j++) {
- decToHex[i * 16 + j] = i.toString(16) + j.toString(16);
- }
- }
-
- function createMatrixIdentity() {
- return [
- [1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]
- ];
- }
-
- function matrixMultiply(m1, m2) {
- var result = createMatrixIdentity();
-
- for (var x = 0; x < 3; x++) {
- for (var y = 0; y < 3; y++) {
- var sum = 0;
-
- for (var z = 0; z < 3; z++) {
- sum += m1[x][z] * m2[z][y];
- }
-
- result[x][y] = sum;
- }
- }
- return result;
- }
-
- function copyState(o1, o2) {
- o2.fillStyle = o1.fillStyle;
- o2.lineCap = o1.lineCap;
- o2.lineJoin = o1.lineJoin;
- o2.lineWidth = o1.lineWidth;
- o2.miterLimit = o1.miterLimit;
- o2.shadowBlur = o1.shadowBlur;
- o2.shadowColor = o1.shadowColor;
- o2.shadowOffsetX = o1.shadowOffsetX;
- o2.shadowOffsetY = o1.shadowOffsetY;
- o2.strokeStyle = o1.strokeStyle;
- o2.globalAlpha = o1.globalAlpha;
- o2.font = o1.font;
- o2.textAlign = o1.textAlign;
- o2.textBaseline = o1.textBaseline;
- o2.arcScaleX_ = o1.arcScaleX_;
- o2.arcScaleY_ = o1.arcScaleY_;
- o2.lineScale_ = o1.lineScale_;
- }
-
- var colorData = {
- aliceblue: '#F0F8FF',
- antiquewhite: '#FAEBD7',
- aquamarine: '#7FFFD4',
- azure: '#F0FFFF',
- beige: '#F5F5DC',
- bisque: '#FFE4C4',
- black: '#000000',
- blanchedalmond: '#FFEBCD',
- blueviolet: '#8A2BE2',
- brown: '#A52A2A',
- burlywood: '#DEB887',
- cadetblue: '#5F9EA0',
- chartreuse: '#7FFF00',
- chocolate: '#D2691E',
- coral: '#FF7F50',
- cornflowerblue: '#6495ED',
- cornsilk: '#FFF8DC',
- crimson: '#DC143C',
- cyan: '#00FFFF',
- darkblue: '#00008B',
- darkcyan: '#008B8B',
- darkgoldenrod: '#B8860B',
- darkgray: '#A9A9A9',
- darkgreen: '#006400',
- darkgrey: '#A9A9A9',
- darkkhaki: '#BDB76B',
- darkmagenta: '#8B008B',
- darkolivegreen: '#556B2F',
- darkorange: '#FF8C00',
- darkorchid: '#9932CC',
- darkred: '#8B0000',
- darksalmon: '#E9967A',
- darkseagreen: '#8FBC8F',
- darkslateblue: '#483D8B',
- darkslategray: '#2F4F4F',
- darkslategrey: '#2F4F4F',
- darkturquoise: '#00CED1',
- darkviolet: '#9400D3',
- deeppink: '#FF1493',
- deepskyblue: '#00BFFF',
- dimgray: '#696969',
- dimgrey: '#696969',
- dodgerblue: '#1E90FF',
- firebrick: '#B22222',
- floralwhite: '#FFFAF0',
- forestgreen: '#228B22',
- gainsboro: '#DCDCDC',
- ghostwhite: '#F8F8FF',
- gold: '#FFD700',
- goldenrod: '#DAA520',
- grey: '#808080',
- greenyellow: '#ADFF2F',
- honeydew: '#F0FFF0',
- hotpink: '#FF69B4',
- indianred: '#CD5C5C',
- indigo: '#4B0082',
- ivory: '#FFFFF0',
- khaki: '#F0E68C',
- lavender: '#E6E6FA',
- lavenderblush: '#FFF0F5',
- lawngreen: '#7CFC00',
- lemonchiffon: '#FFFACD',
- lightblue: '#ADD8E6',
- lightcoral: '#F08080',
- lightcyan: '#E0FFFF',
- lightgoldenrodyellow: '#FAFAD2',
- lightgreen: '#90EE90',
- lightgrey: '#D3D3D3',
- lightpink: '#FFB6C1',
- lightsalmon: '#FFA07A',
- lightseagreen: '#20B2AA',
- lightskyblue: '#87CEFA',
- lightslategray: '#778899',
- lightslategrey: '#778899',
- lightsteelblue: '#B0C4DE',
- lightyellow: '#FFFFE0',
- limegreen: '#32CD32',
- linen: '#FAF0E6',
- magenta: '#FF00FF',
- mediumaquamarine: '#66CDAA',
- mediumblue: '#0000CD',
- mediumorchid: '#BA55D3',
- mediumpurple: '#9370DB',
- mediumseagreen: '#3CB371',
- mediumslateblue: '#7B68EE',
- mediumspringgreen: '#00FA9A',
- mediumturquoise: '#48D1CC',
- mediumvioletred: '#C71585',
- midnightblue: '#191970',
- mintcream: '#F5FFFA',
- mistyrose: '#FFE4E1',
- moccasin: '#FFE4B5',
- navajowhite: '#FFDEAD',
- oldlace: '#FDF5E6',
- olivedrab: '#6B8E23',
- orange: '#FFA500',
- orangered: '#FF4500',
- orchid: '#DA70D6',
- palegoldenrod: '#EEE8AA',
- palegreen: '#98FB98',
- paleturquoise: '#AFEEEE',
- palevioletred: '#DB7093',
- papayawhip: '#FFEFD5',
- peachpuff: '#FFDAB9',
- peru: '#CD853F',
- pink: '#FFC0CB',
- plum: '#DDA0DD',
- powderblue: '#B0E0E6',
- rosybrown: '#BC8F8F',
- royalblue: '#4169E1',
- saddlebrown: '#8B4513',
- salmon: '#FA8072',
- sandybrown: '#F4A460',
- seagreen: '#2E8B57',
- seashell: '#FFF5EE',
- sienna: '#A0522D',
- skyblue: '#87CEEB',
- slateblue: '#6A5ACD',
- slategray: '#708090',
- slategrey: '#708090',
- snow: '#FFFAFA',
- springgreen: '#00FF7F',
- steelblue: '#4682B4',
- tan: '#D2B48C',
- thistle: '#D8BFD8',
- tomato: '#FF6347',
- turquoise: '#40E0D0',
- violet: '#EE82EE',
- wheat: '#F5DEB3',
- whitesmoke: '#F5F5F5',
- yellowgreen: '#9ACD32'
- };
-
-
- function getRgbHslContent(styleString) {
- var start = styleString.indexOf('(', 3);
- var end = styleString.indexOf(')', start + 1);
- var parts = styleString.substring(start + 1, end).split(',');
- // add alpha if needed
- if (parts.length != 4 || styleString.charAt(3) != 'a') {
- parts[3] = 1;
- }
- return parts;
- }
-
- function percent(s) {
- return parseFloat(s) / 100;
- }
-
- function clamp(v, min, max) {
- return Math.min(max, Math.max(min, v));
- }
-
- function hslToRgb(parts){
- var r, g, b, h, s, l;
- h = parseFloat(parts[0]) / 360 % 360;
- if (h < 0)
- h++;
- s = clamp(percent(parts[1]), 0, 1);
- l = clamp(percent(parts[2]), 0, 1);
- if (s == 0) {
- r = g = b = l; // achromatic
- } else {
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
- var p = 2 * l - q;
- r = hueToRgb(p, q, h + 1 / 3);
- g = hueToRgb(p, q, h);
- b = hueToRgb(p, q, h - 1 / 3);
- }
-
- return '#' + decToHex[Math.floor(r * 255)] +
- decToHex[Math.floor(g * 255)] +
- decToHex[Math.floor(b * 255)];
- }
-
- function hueToRgb(m1, m2, h) {
- if (h < 0)
- h++;
- if (h > 1)
- h--;
-
- if (6 * h < 1)
- return m1 + (m2 - m1) * 6 * h;
- else if (2 * h < 1)
- return m2;
- else if (3 * h < 2)
- return m1 + (m2 - m1) * (2 / 3 - h) * 6;
- else
- return m1;
- }
-
- var processStyleCache = {};
-
- function processStyle(styleString) {
- if (styleString in processStyleCache) {
- return processStyleCache[styleString];
- }
-
- var str, alpha = 1;
-
- styleString = String(styleString);
- if (styleString.charAt(0) == '#') {
- str = styleString;
- } else if (/^rgb/.test(styleString)) {
- var parts = getRgbHslContent(styleString);
- var str = '#', n;
- for (var i = 0; i < 3; i++) {
- if (parts[i].indexOf('%') != -1) {
- n = Math.floor(percent(parts[i]) * 255);
- } else {
- n = +parts[i];
- }
- str += decToHex[clamp(n, 0, 255)];
- }
- alpha = +parts[3];
- } else if (/^hsl/.test(styleString)) {
- var parts = getRgbHslContent(styleString);
- str = hslToRgb(parts);
- alpha = parts[3];
- } else {
- str = colorData[styleString] || styleString;
- }
- return processStyleCache[styleString] = {color: str, alpha: alpha};
- }
-
- var DEFAULT_STYLE = {
- style: 'normal',
- variant: 'normal',
- weight: 'normal',
- size: 10,
- family: 'sans-serif'
- };
-
- // Internal text style cache
- var fontStyleCache = {};
-
- function processFontStyle(styleString) {
- if (fontStyleCache[styleString]) {
- return fontStyleCache[styleString];
- }
-
- var el = document.createElement('div');
- var style = el.style;
- try {
- style.font = styleString;
- } catch (ex) {
- // Ignore failures to set to invalid font.
- }
-
- return fontStyleCache[styleString] = {
- style: style.fontStyle || DEFAULT_STYLE.style,
- variant: style.fontVariant || DEFAULT_STYLE.variant,
- weight: style.fontWeight || DEFAULT_STYLE.weight,
- size: style.fontSize || DEFAULT_STYLE.size,
- family: style.fontFamily || DEFAULT_STYLE.family
- };
- }
-
- function getComputedStyle(style, element) {
- var computedStyle = {};
-
- for (var p in style) {
- computedStyle[p] = style[p];
- }
-
- // Compute the size
- var canvasFontSize = parseFloat(element.currentStyle.fontSize),
- fontSize = parseFloat(style.size);
-
- if (typeof style.size == 'number') {
- computedStyle.size = style.size;
- } else if (style.size.indexOf('px') != -1) {
- computedStyle.size = fontSize;
- } else if (style.size.indexOf('em') != -1) {
- computedStyle.size = canvasFontSize * fontSize;
- } else if(style.size.indexOf('%') != -1) {
- computedStyle.size = (canvasFontSize / 100) * fontSize;
- } else if (style.size.indexOf('pt') != -1) {
- computedStyle.size = fontSize / .75;
- } else {
- computedStyle.size = canvasFontSize;
- }
-
- // Different scaling between normal text and VML text. This was found using
- // trial and error to get the same size as non VML text.
- //computedStyle.size *= 0.981;
-
- return computedStyle;
- }
-
- function buildStyle(style) {
- return style.style + ' ' + style.variant + ' ' + style.weight + ' ' +
- style.size + 'px ' + style.family;
- }
-
- var lineCapMap = {
- 'butt': 'flat',
- 'round': 'round'
- };
-
- function processLineCap(lineCap) {
- return lineCapMap[lineCap] || 'square';
- }
-
- /**
- * This class implements CanvasRenderingContext2D interface as described by
- * the WHATWG.
- * @param {HTMLElement} canvasElement The element that the 2D context should
- * be associated with
- */
- function CanvasRenderingContext2D_(canvasElement) {
- this.m_ = createMatrixIdentity();
-
- this.mStack_ = [];
- this.aStack_ = [];
- this.currentPath_ = [];
-
- // Canvas context properties
- this.strokeStyle = '#000';
- this.fillStyle = '#000';
-
- this.lineWidth = 1;
- this.lineJoin = 'miter';
- this.lineCap = 'butt';
- this.miterLimit = Z * 1;
- this.globalAlpha = 1;
- this.font = '10px sans-serif';
- this.textAlign = 'left';
- this.textBaseline = 'alphabetic';
- this.canvas = canvasElement;
-
- var cssText = 'width:' + canvasElement.clientWidth + 'px;height:' +
- canvasElement.clientHeight + 'px;overflow:hidden;position:absolute';
- var el = canvasElement.ownerDocument.createElement('div');
- el.style.cssText = cssText;
- canvasElement.appendChild(el);
-
- var overlayEl = el.cloneNode(false);
- // Use a non transparent background.
- overlayEl.style.backgroundColor = 'red';
- overlayEl.style.filter = 'alpha(opacity=0)';
- canvasElement.appendChild(overlayEl);
-
- this.element_ = el;
- this.arcScaleX_ = 1;
- this.arcScaleY_ = 1;
- this.lineScale_ = 1;
- }
-
- var contextPrototype = CanvasRenderingContext2D_.prototype;
- contextPrototype.clearRect = function() {
- if (this.textMeasureEl_) {
- this.textMeasureEl_.removeNode(true);
- this.textMeasureEl_ = null;
- }
- this.element_.innerHTML = '';
- };
-
- contextPrototype.beginPath = function() {
- // TODO: Branch current matrix so that save/restore has no effect
- // as per safari docs.
- this.currentPath_ = [];
- };
-
- contextPrototype.moveTo = function(aX, aY) {
- var p = getCoords(this, aX, aY);
- this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});
- this.currentX_ = p.x;
- this.currentY_ = p.y;
- };
-
- contextPrototype.lineTo = function(aX, aY) {
- var p = getCoords(this, aX, aY);
- this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});
-
- this.currentX_ = p.x;
- this.currentY_ = p.y;
- };
-
- contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
- aCP2x, aCP2y,
- aX, aY) {
- var p = getCoords(this, aX, aY);
- var cp1 = getCoords(this, aCP1x, aCP1y);
- var cp2 = getCoords(this, aCP2x, aCP2y);
- bezierCurveTo(this, cp1, cp2, p);
- };
-
- // Helper function that takes the already fixed cordinates.
- function bezierCurveTo(self, cp1, cp2, p) {
- self.currentPath_.push({
- type: 'bezierCurveTo',
- cp1x: cp1.x,
- cp1y: cp1.y,
- cp2x: cp2.x,
- cp2y: cp2.y,
- x: p.x,
- y: p.y
- });
- self.currentX_ = p.x;
- self.currentY_ = p.y;
- }
-
- contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
- // the following is lifted almost directly from
- // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
-
- var cp = getCoords(this, aCPx, aCPy);
- var p = getCoords(this, aX, aY);
-
- var cp1 = {
- x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),
- y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)
- };
- var cp2 = {
- x: cp1.x + (p.x - this.currentX_) / 3.0,
- y: cp1.y + (p.y - this.currentY_) / 3.0
- };
-
- bezierCurveTo(this, cp1, cp2, p);
- };
-
- contextPrototype.arc = function(aX, aY, aRadius,
- aStartAngle, aEndAngle, aClockwise) {
- aRadius *= Z;
- var arcType = aClockwise ? 'at' : 'wa';
-
- var xStart = aX + mc(aStartAngle) * aRadius - Z2;
- var yStart = aY + ms(aStartAngle) * aRadius - Z2;
-
- var xEnd = aX + mc(aEndAngle) * aRadius - Z2;
- var yEnd = aY + ms(aEndAngle) * aRadius - Z2;
-
- // IE won't render arches drawn counter clockwise if xStart == xEnd.
- if ((abs(xStart - xEnd) < 10e-8) && !aClockwise) {
- xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
- // that can be represented in binary
- }
- // IE won't render arches drawn clockwise if yStart is very close to yEnd.
- if ((abs(yStart - yEnd) < 10e-8) && aClockwise) {
- yStart -= 0.125; // Offset yStart by 1/80 of a pixel. Use something
- // that can be represented in binary
- }
-
- var p = getCoords(this, aX, aY);
- var pStart = getCoords(this, xStart, yStart);
- var pEnd = getCoords(this, xEnd, yEnd);
-
- this.currentPath_.push({type: arcType,
- x: p.x,
- y: p.y,
- radius: aRadius,
- xStart: pStart.x,
- yStart: pStart.y,
- xEnd: pEnd.x,
- yEnd: pEnd.y});
-
- };
-
- contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
- this.moveTo(aX, aY);
- this.lineTo(aX + aWidth, aY);
- this.lineTo(aX + aWidth, aY + aHeight);
- this.lineTo(aX, aY + aHeight);
- this.closePath();
- };
-
- contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
- var oldPath = this.currentPath_;
- this.beginPath();
-
- this.moveTo(aX, aY);
- this.lineTo(aX + aWidth, aY);
- this.lineTo(aX + aWidth, aY + aHeight);
- this.lineTo(aX, aY + aHeight);
- this.closePath();
- this.stroke();
-
- this.currentPath_ = oldPath;
- };
-
- contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
- var oldPath = this.currentPath_;
- this.beginPath();
-
- this.moveTo(aX, aY);
- this.lineTo(aX + aWidth, aY);
- this.lineTo(aX + aWidth, aY + aHeight);
- this.lineTo(aX, aY + aHeight);
- this.closePath();
- this.fill();
-
- this.currentPath_ = oldPath;
- };
-
- contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
- var gradient = new CanvasGradient_('gradient');
- gradient.x0_ = aX0;
- gradient.y0_ = aY0;
- gradient.x1_ = aX1;
- gradient.y1_ = aY1;
- return gradient;
- };
-
- contextPrototype.createRadialGradient = function(aX0, aY0, aR0,
- aX1, aY1, aR1) {
- var gradient = new CanvasGradient_('gradientradial');
- gradient.x0_ = aX0;
- gradient.y0_ = aY0;
- gradient.r0_ = aR0;
- gradient.x1_ = aX1;
- gradient.y1_ = aY1;
- gradient.r1_ = aR1;
- return gradient;
- };
-
- contextPrototype.drawImage = function(image, var_args) {
- var dx, dy, dw, dh, sx, sy, sw, sh;
-
- // to find the original width we overide the width and height
- var oldRuntimeWidth = image.runtimeStyle.width;
- var oldRuntimeHeight = image.runtimeStyle.height;
- image.runtimeStyle.width = 'auto';
- image.runtimeStyle.height = 'auto';
-
- // get the original size
- var w = image.width;
- var h = image.height;
-
- // and remove overides
- image.runtimeStyle.width = oldRuntimeWidth;
- image.runtimeStyle.height = oldRuntimeHeight;
-
- if (arguments.length == 3) {
- dx = arguments[1];
- dy = arguments[2];
- sx = sy = 0;
- sw = dw = w;
- sh = dh = h;
- } else if (arguments.length == 5) {
- dx = arguments[1];
- dy = arguments[2];
- dw = arguments[3];
- dh = arguments[4];
- sx = sy = 0;
- sw = w;
- sh = h;
- } else if (arguments.length == 9) {
- sx = arguments[1];
- sy = arguments[2];
- sw = arguments[3];
- sh = arguments[4];
- dx = arguments[5];
- dy = arguments[6];
- dw = arguments[7];
- dh = arguments[8];
- } else {
- throw Error('Invalid number of arguments');
- }
-
- var d = getCoords(this, dx, dy);
-
- var w2 = sw / 2;
- var h2 = sh / 2;
-
- var vmlStr = [];
-
- var W = 10;
- var H = 10;
-
- // For some reason that I've now forgotten, using divs didn't work
- vmlStr.push(' <g_vml_:group',
- ' coordsize="', Z * W, ',', Z * H, '"',
- ' coordorigin="0,0"' ,
- ' style="width:', W, 'px;height:', H, 'px;position:absolute;');
-
- // If filters are necessary (rotation exists), create them
- // filters are bog-slow, so only create them if abbsolutely necessary
- // The following check doesn't account for skews (which don't exist
- // in the canvas spec (yet) anyway.
-
- if (this.m_[0][0] != 1 || this.m_[0][1] ||
- this.m_[1][1] != 1 || this.m_[1][0]) {
- var filter = [];
-
- // Note the 12/21 reversal
- filter.push('M11=', this.m_[0][0], ',',
- 'M12=', this.m_[1][0], ',',
- 'M21=', this.m_[0][1], ',',
- 'M22=', this.m_[1][1], ',',
- 'Dx=', mr(d.x / Z), ',',
- 'Dy=', mr(d.y / Z), '');
-
- // Bounding box calculation (need to minimize displayed area so that
- // filters don't waste time on unused pixels.
- var max = d;
- var c2 = getCoords(this, dx + dw, dy);
- var c3 = getCoords(this, dx, dy + dh);
- var c4 = getCoords(this, dx + dw, dy + dh);
-
- max.x = m.max(max.x, c2.x, c3.x, c4.x);
- max.y = m.max(max.y, c2.y, c3.y, c4.y);
-
- vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
- 'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
- filter.join(''), ", sizingmethod='clip');");
-
- } else {
- vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
- }
-
- vmlStr.push(' ">' ,
- '<g_vml_:image src="', image.src, '"',
- ' style="width:', Z * dw, 'px;',
- ' height:', Z * dh, 'px"',
- ' cropleft="', sx / w, '"',
- ' croptop="', sy / h, '"',
- ' cropright="', (w - sx - sw) / w, '"',
- ' cropbottom="', (h - sy - sh) / h, '"',
- ' />',
- '</g_vml_:group>');
-
- this.element_.insertAdjacentHTML('BeforeEnd', vmlStr.join(''));
- };
-
- contextPrototype.stroke = function(aFill) {
- var lineStr = [];
- var lineOpen = false;
-
- var W = 10;
- var H = 10;
-
- lineStr.push('<g_vml_:shape',
- ' filled="', !!aFill, '"',
- ' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
- ' coordorigin="0,0"',
- ' coordsize="', Z * W, ',', Z * H, '"',
- ' stroked="', !aFill, '"',
- ' path="');
-
- var newSeq = false;
- var min = {x: null, y: null};
- var max = {x: null, y: null};
-
- for (var i = 0; i < this.currentPath_.length; i++) {
- var p = this.currentPath_[i];
- var c;
-
- switch (p.type) {
- case 'moveTo':
- c = p;
- lineStr.push(' m ', mr(p.x), ',', mr(p.y));
- break;
- case 'lineTo':
- lineStr.push(' l ', mr(p.x), ',', mr(p.y));
- break;
- case 'close':
- lineStr.push(' x ');
- p = null;
- break;
- case 'bezierCurveTo':
- lineStr.push(' c ',
- mr(p.cp1x), ',', mr(p.cp1y), ',',
- mr(p.cp2x), ',', mr(p.cp2y), ',',
- mr(p.x), ',', mr(p.y));
- break;
- case 'at':
- case 'wa':
- lineStr.push(' ', p.type, ' ',
- mr(p.x - this.arcScaleX_ * p.radius), ',',
- mr(p.y - this.arcScaleY_ * p.radius), ' ',
- mr(p.x + this.arcScaleX_ * p.radius), ',',
- mr(p.y + this.arcScaleY_ * p.radius), ' ',
- mr(p.xStart), ',', mr(p.yStart), ' ',
- mr(p.xEnd), ',', mr(p.yEnd));
- break;
- }
-
-
- // TODO: Following is broken for curves due to
- // move to proper paths.
-
- // Figure out dimensions so we can do gradient fills
- // properly
- if (p) {
- if (min.x == null || p.x < min.x) {
- min.x = p.x;
- }
- if (max.x == null || p.x > max.x) {
- max.x = p.x;
- }
- if (min.y == null || p.y < min.y) {
- min.y = p.y;
- }
- if (max.y == null || p.y > max.y) {
- max.y = p.y;
- }
- }
- }
- lineStr.push(' ">');
-
- if (!aFill) {
- appendStroke(this, lineStr);
- } else {
- appendFill(this, lineStr, min, max);
- }
-
- lineStr.push('</g_vml_:shape>');
-
- this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
- };
-
- function appendStroke(ctx, lineStr) {
- var a = processStyle(ctx.strokeStyle);
- var color = a.color;
- var opacity = a.alpha * ctx.globalAlpha;
- var lineWidth = ctx.lineScale_ * ctx.lineWidth;
-
- // VML cannot correctly render a line if the width is less than 1px.
- // In that case, we dilute the color to make the line look thinner.
- if (lineWidth < 1) {
- opacity *= lineWidth;
- }
-
- lineStr.push(
- '<g_vml_:stroke',
- ' opacity="', opacity, '"',
- ' joinstyle="', ctx.lineJoin, '"',
- ' miterlimit="', ctx.miterLimit, '"',
- ' endcap="', processLineCap(ctx.lineCap), '"',
- ' weight="', lineWidth, 'px"',
- ' color="', color, '" />'
- );
- }
-
- function appendFill(ctx, lineStr, min, max) {
- var fillStyle = ctx.fillStyle;
- var arcScaleX = ctx.arcScaleX_;
- var arcScaleY = ctx.arcScaleY_;
- var width = max.x - min.x;
- var height = max.y - min.y;
- if (fillStyle instanceof CanvasGradient_) {
- // TODO: Gradients transformed with the transformation matrix.
- var angle = 0;
- var focus = {x: 0, y: 0};
-
- // additional offset
- var shift = 0;
- // scale factor for offset
- var expansion = 1;
-
- if (fillStyle.type_ == 'gradient') {
- var x0 = fillStyle.x0_ / arcScaleX;
- var y0 = fillStyle.y0_ / arcScaleY;
- var x1 = fillStyle.x1_ / arcScaleX;
- var y1 = fillStyle.y1_ / arcScaleY;
- var p0 = getCoords(ctx, x0, y0);
- var p1 = getCoords(ctx, x1, y1);
- var dx = p1.x - p0.x;
- var dy = p1.y - p0.y;
- angle = Math.atan2(dx, dy) * 180 / Math.PI;
-
- // The angle should be a non-negative number.
- if (angle < 0) {
- angle += 360;
- }
-
- // Very small angles produce an unexpected result because they are
- // converted to a scientific notation string.
- if (angle < 1e-6) {
- angle = 0;
- }
- } else {
- var p0 = getCoords(ctx, fillStyle.x0_, fillStyle.y0_);
- focus = {
- x: (p0.x - min.x) / width,
- y: (p0.y - min.y) / height
- };
-
- width /= arcScaleX * Z;
- height /= arcScaleY * Z;
- var dimension = m.max(width, height);
- shift = 2 * fillStyle.r0_ / dimension;
- expansion = 2 * fillStyle.r1_ / dimension - shift;
- }
-
- // We need to sort the color stops in ascending order by offset,
- // otherwise IE won't interpret it correctly.
- var stops = fillStyle.colors_;
- stops.sort(function(cs1, cs2) {
- return cs1.offset - cs2.offset;
- });
-
- var length = stops.length;
- var color1 = stops[0].color;
- var color2 = stops[length - 1].color;
- var opacity1 = stops[0].alpha * ctx.globalAlpha;
- var opacity2 = stops[length - 1].alpha * ctx.globalAlpha;
-
- var colors = [];
- for (var i = 0; i < length; i++) {
- var stop = stops[i];
- colors.push(stop.offset * expansion + shift + ' ' + stop.color);
- }
-
- // When colors attribute is used, the meanings of opacity and o:opacity2
- // are reversed.
- lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"',
- ' method="none" focus="100%"',
- ' color="', color1, '"',
- ' color2="', color2, '"',
- ' colors="', colors.join(','), '"',
- ' opacity="', opacity2, '"',
- ' g_o_:opacity2="', opacity1, '"',
- ' angle="', angle, '"',
- ' focusposition="', focus.x, ',', focus.y, '" />');
- } else if (fillStyle instanceof CanvasPattern_) {
- if (width && height) {
- var deltaLeft = -min.x;
- var deltaTop = -min.y;
- lineStr.push('<g_vml_:fill',
- ' position="',
- deltaLeft / width * arcScaleX * arcScaleX, ',',
- deltaTop / height * arcScaleY * arcScaleY, '"',
- ' type="tile"',
- // TODO: Figure out the correct size to fit the scale.
- //' size="', w, 'px ', h, 'px"',
- ' src="', fillStyle.src_, '" />');
- }
- } else {
- var a = processStyle(ctx.fillStyle);
- var color = a.color;
- var opacity = a.alpha * ctx.globalAlpha;
- lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,
- '" />');
- }
- }
-
- contextPrototype.fill = function() {
- this.stroke(true);
- };
-
- contextPrototype.closePath = function() {
- this.currentPath_.push({type: 'close'});
- };
-
- function getCoords(ctx, aX, aY) {
- var m = ctx.m_;
- return {
- x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,
- y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2
- };
- };
-
- contextPrototype.save = function() {
- var o = {};
- copyState(this, o);
- this.aStack_.push(o);
- this.mStack_.push(this.m_);
- this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
- };
-
- contextPrototype.restore = function() {
- if (this.aStack_.length) {
- copyState(this.aStack_.pop(), this);
- this.m_ = this.mStack_.pop();
- }
- };
-
- function matrixIsFinite(m) {
- return isFinite(m[0][0]) && isFinite(m[0][1]) &&
- isFinite(m[1][0]) && isFinite(m[1][1]) &&
- isFinite(m[2][0]) && isFinite(m[2][1]);
- }
-
- function setM(ctx, m, updateLineScale) {
- if (!matrixIsFinite(m)) {
- return;
- }
- ctx.m_ = m;
-
- if (updateLineScale) {
- // Get the line scale.
- // Determinant of this.m_ means how much the area is enlarged by the
- // transformation. So its square root can be used as a scale factor
- // for width.
- var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
- ctx.lineScale_ = sqrt(abs(det));
- }
- }
-
- contextPrototype.translate = function(aX, aY) {
- var m1 = [
- [1, 0, 0],
- [0, 1, 0],
- [aX, aY, 1]
- ];
-
- setM(this, matrixMultiply(m1, this.m_), false);
- };
-
- contextPrototype.rotate = function(aRot) {
- var c = mc(aRot);
- var s = ms(aRot);
-
- var m1 = [
- [c, s, 0],
- [-s, c, 0],
- [0, 0, 1]
- ];
-
- setM(this, matrixMultiply(m1, this.m_), false);
- };
-
- contextPrototype.scale = function(aX, aY) {
- this.arcScaleX_ *= aX;
- this.arcScaleY_ *= aY;
- var m1 = [
- [aX, 0, 0],
- [0, aY, 0],
- [0, 0, 1]
- ];
-
- setM(this, matrixMultiply(m1, this.m_), true);
- };
-
- contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {
- var m1 = [
- [m11, m12, 0],
- [m21, m22, 0],
- [dx, dy, 1]
- ];
-
- setM(this, matrixMultiply(m1, this.m_), true);
- };
-
- contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
- var m = [
- [m11, m12, 0],
- [m21, m22, 0],
- [dx, dy, 1]
- ];
-
- setM(this, m, true);
- };
-
- /**
- * The text drawing function.
- * The maxWidth argument isn't taken in account, since no browser supports
- * it yet.
- */
- contextPrototype.drawText_ = function(text, x, y, maxWidth, stroke) {
- var m = this.m_,
- delta = 1000,
- left = 0,
- right = delta,
- offset = {x: 0, y: 0},
- lineStr = [];
-
- var fontStyle = getComputedStyle(processFontStyle(this.font),
- this.element_);
-
- var fontStyleString = buildStyle(fontStyle);
-
- var elementStyle = this.element_.currentStyle;
- var textAlign = this.textAlign.toLowerCase();
- switch (textAlign) {
- case 'left':
- case 'center':
- case 'right':
- break;
- case 'end':
- textAlign = elementStyle.direction == 'ltr' ? 'right' : 'left';
- break;
- case 'start':
- textAlign = elementStyle.direction == 'rtl' ? 'right' : 'left';
- break;
- default:
- textAlign = 'left';
- }
-
- // 1.75 is an arbitrary number, as there is no info about the text baseline
- switch (this.textBaseline) {
- case 'hanging':
- case 'top':
- offset.y = fontStyle.size / 1.75;
- break;
- case 'middle':
- break;
- default:
- case null:
- case 'alphabetic':
- case 'ideographic':
- case 'bottom':
- offset.y = -fontStyle.size / 2.25;
- break;
- }
-
- switch(textAlign) {
- case 'right':
- left = delta;
- right = 0.05;
- break;
- case 'center':
- left = right = delta / 2;
- break;
- }
-
- var d = getCoords(this, x + offset.x, y + offset.y);
-
- lineStr.push('<g_vml_:line from="', -left ,' 0" to="', right ,' 0.05" ',
- ' coordsize="100 100" coordorigin="0 0"',
- ' filled="', !stroke, '" stroked="', !!stroke,
- '" style="position:absolute;width:1px;height:1px;">');
-
- if (stroke) {
- appendStroke(this, lineStr);
- } else {
- // TODO: Fix the min and max params.
- appendFill(this, lineStr, {x: -left, y: 0},
- {x: right, y: fontStyle.size});
- }
-
- var skewM = m[0][0].toFixed(3) + ',' + m[1][0].toFixed(3) + ',' +
- m[0][1].toFixed(3) + ',' + m[1][1].toFixed(3) + ',0,0';
-
- var skewOffset = mr(d.x / Z) + ',' + mr(d.y / Z);
-
- lineStr.push('<g_vml_:skew on="t" matrix="', skewM ,'" ',
- ' offset="', skewOffset, '" origin="', left ,' 0" />',
- '<g_vml_:path textpathok="true" />',
- '<g_vml_:textpath on="true" string="',
- encodeHtmlAttribute(text),
- '" style="v-text-align:', textAlign,
- ';font:', encodeHtmlAttribute(fontStyleString),
- '" /></g_vml_:line>');
-
- this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
- };
-
- contextPrototype.fillText = function(text, x, y, maxWidth) {
- this.drawText_(text, x, y, maxWidth, false);
- };
-
- contextPrototype.strokeText = function(text, x, y, maxWidth) {
- this.drawText_(text, x, y, maxWidth, true);
- };
-
- contextPrototype.measureText = function(text) {
- if (!this.textMeasureEl_) {
- var s = '<span style="position:absolute;' +
- 'top:-20000px;left:0;padding:0;margin:0;border:none;' +
- 'white-space:pre;"></span>';
- this.element_.insertAdjacentHTML('beforeEnd', s);
- this.textMeasureEl_ = this.element_.lastChild;
- }
- var doc = this.element_.ownerDocument;
- this.textMeasureEl_.innerHTML = '';
- this.textMeasureEl_.style.font = this.font;
- // Don't use innerHTML or innerText because they allow markup/whitespace.
- this.textMeasureEl_.appendChild(doc.createTextNode(text));
- return {width: this.textMeasureEl_.offsetWidth};
- };
-
- /******** STUBS ********/
- contextPrototype.clip = function() {
- // TODO: Implement
- };
-
- contextPrototype.arcTo = function() {
- // TODO: Implement
- };
-
- contextPrototype.createPattern = function(image, repetition) {
- return new CanvasPattern_(image, repetition);
- };
-
- // Gradient / Pattern Stubs
- function CanvasGradient_(aType) {
- this.type_ = aType;
- this.x0_ = 0;
- this.y0_ = 0;
- this.r0_ = 0;
- this.x1_ = 0;
- this.y1_ = 0;
- this.r1_ = 0;
- this.colors_ = [];
- }
-
- CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
- aColor = processStyle(aColor);
- this.colors_.push({offset: aOffset,
- color: aColor.color,
- alpha: aColor.alpha});
- };
-
- function CanvasPattern_(image, repetition) {
- assertImageIsValid(image);
- switch (repetition) {
- case 'repeat':
- case null:
- case '':
- this.repetition_ = 'repeat';
- break
- case 'repeat-x':
- case 'repeat-y':
- case 'no-repeat':
- this.repetition_ = repetition;
- break;
- default:
- throwException('SYNTAX_ERR');
- }
-
- this.src_ = image.src;
- this.width_ = image.width;
- this.height_ = image.height;
- }
-
- function throwException(s) {
- throw new DOMException_(s);
- }
-
- function assertImageIsValid(img) {
- if (!img || img.nodeType != 1 || img.tagName != 'IMG') {
- throwException('TYPE_MISMATCH_ERR');
- }
- if (img.readyState != 'complete') {
- throwException('INVALID_STATE_ERR');
- }
- }
-
- function DOMException_(s) {
- this.code = this[s];
- this.message = s +': DOM Exception ' + this.code;
- }
- var p = DOMException_.prototype = new Error;
- p.INDEX_SIZE_ERR = 1;
- p.DOMSTRING_SIZE_ERR = 2;
- p.HIERARCHY_REQUEST_ERR = 3;
- p.WRONG_DOCUMENT_ERR = 4;
- p.INVALID_CHARACTER_ERR = 5;
- p.NO_DATA_ALLOWED_ERR = 6;
- p.NO_MODIFICATION_ALLOWED_ERR = 7;
- p.NOT_FOUND_ERR = 8;
- p.NOT_SUPPORTED_ERR = 9;
- p.INUSE_ATTRIBUTE_ERR = 10;
- p.INVALID_STATE_ERR = 11;
- p.SYNTAX_ERR = 12;
- p.INVALID_MODIFICATION_ERR = 13;
- p.NAMESPACE_ERR = 14;
- p.INVALID_ACCESS_ERR = 15;
- p.VALIDATION_ERR = 16;
- p.TYPE_MISMATCH_ERR = 17;
-
- // set up externs
- G_vmlCanvasManager = G_vmlCanvasManager_;
- CanvasRenderingContext2D = CanvasRenderingContext2D_;
- CanvasGradient = CanvasGradient_;
- CanvasPattern = CanvasPattern_;
- DOMException = DOMException_;
-})();
-
-} // if
diff --git a/addons/web_graph/static/lib/flotr2/lib/imagediff.js b/addons/web_graph/static/lib/flotr2/lib/imagediff.js
deleted file mode 100644
index ac1d2745018..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/imagediff.js
+++ /dev/null
@@ -1,343 +0,0 @@
-/*! imagediff.js 1.0.2
- * (c) 2011 Carl Sutherland, Humble Software Development
- * imagediff.js is freely distributable under the MIT license.
- * Thanks to Jacob Thornton for the node/amd integration bits.
- * For details and documentation:
- * https://github.com/HumbleSoftware/js-imagediff
- */
-(function (name, definition) {
- var root = this;
- if (typeof module != 'undefined') {
- module.exports = definition();
- } else if (typeof define == 'function' && typeof define.amd == 'object') {
- define(definition);
- } else {
- root[name] = definition(root, name);
- }
-})('imagediff', function (root, name) {
-
- var
- TYPE_ARRAY = '[object Array]',
- TYPE_CANVAS = '[object HTMLCanvasElement]',
- TYPE_CONTEXT = '[object CanvasRenderingContext2D]',
- TYPE_IMAGE = '[object HTMLImageElement]',
-
- OBJECT = 'object',
- UNDEFINED = 'undefined',
-
- canvas = getCanvas(),
- context = canvas.getContext('2d'),
- previous = root[name],
- imagediff, jasmine;
-
- // Creation
- function getCanvas (width, height) {
- var
- canvas = document.createElement('canvas');
- if (width) canvas.width = width;
- if (height) canvas.height = height;
- return canvas;
- }
- function getImageData (width, height) {
- canvas.width = width;
- canvas.height = height;
- context.clearRect(0, 0, width, height);
- return context.createImageData(width, height);
- }
-
-
- // Type Checking
- function isImage (object) {
- return isType(object, TYPE_IMAGE);
- }
- function isCanvas (object) {
- return isType(object, TYPE_CANVAS);
- }
- function isContext (object) {
- return isType(object, TYPE_CONTEXT);
- }
- function isImageData (object) {
- var
- imageData = getImageData(1, 1);
- isImageData = function (object) {
- return (object && imageData.constructor === object.constructor ? true : false);
- };
- return isImageData(object);
- }
- function isImageType (object) {
- return (
- isImage(object) ||
- isCanvas(object) ||
- isContext(object) ||
- isImageData(object)
- );
- }
- function isType (object, type) {
- return typeof (object) === 'object' && Object.prototype.toString.apply(object) === type;
- }
-
-
- // Type Conversion
- function copyImageData (imageData) {
- var
- height = imageData.height,
- width = imageData.width;
- canvas.width = width;
- canvas.height = height;
- context.putImageData(imageData, 0, 0);
- return context.getImageData(0, 0, width, height);
- }
- function toImageData (object) {
- if (isImage(object)) { return toImageDataFromImage(object); }
- if (isCanvas(object)) { return toImageDataFromCanvas(object); }
- if (isContext(object)) { return toImageDataFromContext(object); }
- if (isImageData(object)) { return object; }
- }
- function toImageDataFromImage (image) {
- var
- height = image.height,
- width = image.width;
- canvas.width = width;
- canvas.height = height;
- context.clearRect(0, 0, width, height);
- context.drawImage(image, 0, 0);
- return context.getImageData(0, 0, width, height);
- }
- function toImageDataFromCanvas (canvas) {
- var
- height = canvas.height,
- width = canvas.width,
- context = canvas.getContext('2d');
- return context.getImageData(0, 0, width, height);
- }
- function toImageDataFromContext (context) {
- var
- canvas = context.canvas,
- height = canvas.height,
- width = canvas.width;
- return context.getImageData(0, 0, width, height);
- }
- function toCanvas (object) {
- var
- data = toImageData(object),
- canvas = getCanvas(data.width, data.height),
- context = canvas.getContext('2d');
-
- context.putImageData(data, 0, 0);
- return canvas;
- }
-
-
- // ImageData Equality Operators
- function equalWidth (a, b) {
- return a.width === b.width;
- }
- function equalHeight (a, b) {
- return a.height === b.height;
- }
- function equalDimensions (a, b) {
- return equalHeight(a, b) && equalWidth(a, b);
- }
- function equal (a, b, tolerance) {
-
- var
- aData = a.data,
- bData = b.data,
- length = aData.length,
- tolerance = tolerance || 0,
- i;
-
- if (!equalDimensions(a, b)) return false;
- for (i = length; i--;) if (aData[i] !== bData[i] && Math.abs(aData[i] - bData[i]) > tolerance) return false;
-
- return true;
- }
-
-
- // Diff
- function diff (a, b) {
- return (equalDimensions(a, b) ? diffEqual : diffUnequal)(a, b);
- }
- function diffEqual (a, b) {
-
- var
- height = a.height,
- width = a.width,
- c = getImageData(width, height), // c = a - b
- aData = a.data,
- bData = b.data,
- cData = c.data,
- length = cData.length,
- row, column,
- i, j, k, v;
-
- for (i = 0; i < length; i += 4) {
- cData[i] = Math.abs(aData[i] - bData[i]);
- cData[i+1] = Math.abs(aData[i+1] - bData[i+1]);
- cData[i+2] = Math.abs(aData[i+2] - bData[i+2]);
- cData[i+3] = Math.abs(255 - aData[i+3] - bData[i+3]);
- }
-
- return c;
- }
- function diffUnequal (a, b) {
-
- var
- height = Math.max(a.height, b.height),
- width = Math.max(a.width, b.width),
- c = getImageData(width, height), // c = a - b
- aData = a.data,
- bData = b.data,
- cData = c.data,
- rowOffset,
- columnOffset,
- row, column,
- i, j, k, v;
-
-
- for (i = cData.length - 1; i > 0; i = i - 4) {
- cData[i] = 255;
- }
-
- // Add First Image
- offsets(a);
- for (row = a.height; row--;){
- for (column = a.width; column--;) {
- i = 4 * ((row + rowOffset) * width + (column + columnOffset));
- j = 4 * (row * a.width + column);
- cData[i+0] = aData[j+0]; // r
- cData[i+1] = aData[j+1]; // g
- cData[i+2] = aData[j+2]; // b
- // cData[i+3] = aData[j+3]; // a
- }
- }
-
- // Subtract Second Image
- offsets(b);
- for (row = b.height; row--;){
- for (column = b.width; column--;) {
- i = 4 * ((row + rowOffset) * width + (column + columnOffset));
- j = 4 * (row * b.width + column);
- cData[i+0] = Math.abs(cData[i+0] - bData[j+0]); // r
- cData[i+1] = Math.abs(cData[i+1] - bData[j+1]); // g
- cData[i+2] = Math.abs(cData[i+2] - bData[j+2]); // b
- }
- }
-
- // Helpers
- function offsets (imageData) {
- rowOffset = Math.floor((height - imageData.height) / 2);
- columnOffset = Math.floor((width - imageData.width) / 2);
- }
-
- return c;
- }
-
-
- // Validation
- function checkType () {
- var i;
- for (i = 0; i < arguments.length; i++) {
- if (!isImageType(arguments[i])) {
- throw {
- name : 'ImageTypeError',
- message : 'Submitted object was not an image.'
- };
- }
- }
- }
-
-
- // Jasmine Matchers
- function get (element, content) {
- element = document.createElement(element);
- if (element && content) {
- element.innerHTML = content;
- }
- return element;
- }
- jasmine = {
-
- toBeImageData : function () {
- return imagediff.isImageData(this.actual);
- },
-
- toImageDiffEqual : function (expected, tolerance) {
-
- this.message = function() {
-
- var
- div = get('div'),
- a = get('div', '<div>Actual:</div>'),
- b = get('div', '<div>Expected:</div>'),
- c = get('div', '<div>Diff:</div>'),
- diff = imagediff.diff(this.actual, expected),
- canvas = getCanvas(),
- context;
-
- canvas.height = diff.height;
- canvas.width = diff.width;
-
- context = canvas.getContext('2d');
- context.putImageData(diff, 0, 0);
-
- a.appendChild(toCanvas(this.actual));
- b.appendChild(toCanvas(expected));
- c.appendChild(canvas);
-
- div.appendChild(a);
- div.appendChild(b);
- div.appendChild(c);
-
- return [
- div,
- "Expected not to be equal."
- ];
- };
-
- return imagediff.equal(this.actual, expected, tolerance);
- }
- };
-
- // Definition
- imagediff = {
-
- createCanvas : getCanvas,
- createImageData : getImageData,
-
- isImage : isImage,
- isCanvas : isCanvas,
- isContext : isContext,
- isImageData : isImageData,
- isImageType : isImageType,
-
- toImageData : function (object) {
- checkType(object);
- if (isImageData(object)) { return copyImageData(object); }
- return toImageData(object);
- },
-
- equal : function (a, b, tolerance) {
- checkType(a, b);
- a = toImageData(a);
- b = toImageData(b);
- return equal(a, b, tolerance);
- },
- diff : function (a, b) {
- checkType(a, b);
- a = toImageData(a);
- b = toImageData(b);
- return diff(a, b);
- },
-
- jasmine : jasmine,
-
- // Compatibility
- noConflict : function () {
- root[name] = previous;
- return imagediff;
- }
- };
-
- return imagediff;
-});
diff --git a/addons/web_graph/static/lib/flotr2/lib/jasmine/MIT.LICENSE b/addons/web_graph/static/lib/flotr2/lib/jasmine/MIT.LICENSE
deleted file mode 100644
index 7c435baaec8..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/jasmine/MIT.LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2008-2011 Pivotal Labs
-
-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.
diff --git a/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine-html.js b/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine-html.js
deleted file mode 100644
index 73834010f60..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine-html.js
+++ /dev/null
@@ -1,190 +0,0 @@
-jasmine.TrivialReporter = function(doc) {
- this.document = doc || document;
- this.suiteDivs = {};
- this.logRunningSpecs = false;
-};
-
-jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
- var el = document.createElement(type);
-
- for (var i = 2; i < arguments.length; i++) {
- var child = arguments[i];
-
- if (typeof child === 'string') {
- el.appendChild(document.createTextNode(child));
- } else {
- if (child) { el.appendChild(child); }
- }
- }
-
- for (var attr in attrs) {
- if (attr == "className") {
- el[attr] = attrs[attr];
- } else {
- el.setAttribute(attr, attrs[attr]);
- }
- }
-
- return el;
-};
-
-jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
- var showPassed, showSkipped;
-
- this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
- this.createDom('div', { className: 'banner' },
- this.createDom('div', { className: 'logo' },
- this.createDom('span', { className: 'title' }, "Jasmine"),
- this.createDom('span', { className: 'version' }, runner.env.versionString())),
- this.createDom('div', { className: 'options' },
- "Show ",
- showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
- this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
- showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
- this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
- )
- ),
-
- this.runnerDiv = this.createDom('div', { className: 'runner running' },
- this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
- this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
- this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
- );
-
- this.document.body.appendChild(this.outerDiv);
-
- var suites = runner.suites();
- for (var i = 0; i < suites.length; i++) {
- var suite = suites[i];
- var suiteDiv = this.createDom('div', { className: 'suite' },
- this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
- this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
- this.suiteDivs[suite.id] = suiteDiv;
- var parentDiv = this.outerDiv;
- if (suite.parentSuite) {
- parentDiv = this.suiteDivs[suite.parentSuite.id];
- }
- parentDiv.appendChild(suiteDiv);
- }
-
- this.startedAt = new Date();
-
- var self = this;
- showPassed.onclick = function(evt) {
- if (showPassed.checked) {
- self.outerDiv.className += ' show-passed';
- } else {
- self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
- }
- };
-
- showSkipped.onclick = function(evt) {
- if (showSkipped.checked) {
- self.outerDiv.className += ' show-skipped';
- } else {
- self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
- }
- };
-};
-
-jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
- var results = runner.results();
- var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
- this.runnerDiv.setAttribute("class", className);
- //do it twice for IE
- this.runnerDiv.setAttribute("className", className);
- var specs = runner.specs();
- var specCount = 0;
- for (var i = 0; i < specs.length; i++) {
- if (this.specFilter(specs[i])) {
- specCount++;
- }
- }
- var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
- message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
- this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
-
- this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
-};
-
-jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
- var results = suite.results();
- var status = results.passed() ? 'passed' : 'failed';
- if (results.totalCount === 0) { // todo: change this to check results.skipped
- status = 'skipped';
- }
- this.suiteDivs[suite.id].className += " " + status;
-};
-
-jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
- if (this.logRunningSpecs) {
- this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
- }
-};
-
-jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
- var results = spec.results();
- var status = results.passed() ? 'passed' : 'failed';
- if (results.skipped) {
- status = 'skipped';
- }
- var specDiv = this.createDom('div', { className: 'spec ' + status },
- this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
- this.createDom('a', {
- className: 'description',
- href: '?spec=' + encodeURIComponent(spec.getFullName()),
- title: spec.getFullName()
- }, spec.description));
-
-
- var resultItems = results.getItems();
- var messagesDiv = this.createDom('div', { className: 'messages' });
- for (var i = 0; i < resultItems.length; i++) {
- var result = resultItems[i];
-
- if (result.type == 'log') {
- messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
- } else if (result.type == 'expect' && result.passed && !result.passed()) {
- messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
-
- if (result.trace.stack) {
- messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
- }
- }
- }
-
- if (messagesDiv.childNodes.length > 0) {
- specDiv.appendChild(messagesDiv);
- }
-
- this.suiteDivs[spec.suite.id].appendChild(specDiv);
-};
-
-jasmine.TrivialReporter.prototype.log = function() {
- var console = jasmine.getGlobal().console;
- if (console && console.log) {
- if (console.log.apply) {
- console.log.apply(console, arguments);
- } else {
- console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
- }
- }
-};
-
-jasmine.TrivialReporter.prototype.getLocation = function() {
- return this.document.location;
-};
-
-jasmine.TrivialReporter.prototype.specFilter = function(spec) {
- var paramMap = {};
- var params = this.getLocation().search.substring(1).split('&');
- for (var i = 0; i < params.length; i++) {
- var p = params[i].split('=');
- paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
- }
-
- if (!paramMap.spec) {
- return true;
- }
- return spec.getFullName().indexOf(paramMap.spec) === 0;
-};
diff --git a/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.css b/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.css
deleted file mode 100644
index 6583fe7c66d..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.css
+++ /dev/null
@@ -1,166 +0,0 @@
-body {
- font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
-}
-
-
-.jasmine_reporter a:visited, .jasmine_reporter a {
- color: #303;
-}
-
-.jasmine_reporter a:hover, .jasmine_reporter a:active {
- color: blue;
-}
-
-.run_spec {
- float:right;
- padding-right: 5px;
- font-size: .8em;
- text-decoration: none;
-}
-
-.jasmine_reporter {
- margin: 0 5px;
-}
-
-.banner {
- color: #303;
- background-color: #fef;
- padding: 5px;
-}
-
-.logo {
- float: left;
- font-size: 1.1em;
- padding-left: 5px;
-}
-
-.logo .version {
- font-size: .6em;
- padding-left: 1em;
-}
-
-.runner.running {
- background-color: yellow;
-}
-
-
-.options {
- text-align: right;
- font-size: .8em;
-}
-
-
-
-
-.suite {
- border: 1px outset gray;
- margin: 5px 0;
- padding-left: 1em;
-}
-
-.suite .suite {
- margin: 5px;
-}
-
-.suite.passed {
- background-color: #dfd;
-}
-
-.suite.failed {
- background-color: #fdd;
-}
-
-.spec {
- margin: 5px;
- padding-left: 1em;
- clear: both;
-}
-
-.spec.failed, .spec.passed, .spec.skipped {
- padding-bottom: 5px;
- border: 1px solid gray;
-}
-
-.spec.failed {
- background-color: #fbb;
- border-color: red;
-}
-
-.spec.passed {
- background-color: #bfb;
- border-color: green;
-}
-
-.spec.skipped {
- background-color: #bbb;
-}
-
-.messages {
- border-left: 1px dashed gray;
- padding-left: 1em;
- padding-right: 1em;
-}
-
-.passed {
- background-color: #cfc;
- display: none;
-}
-
-.failed {
- background-color: #fbb;
-}
-
-.skipped {
- color: #777;
- background-color: #eee;
- display: none;
-}
-
-
-/*.resultMessage {*/
- /*white-space: pre;*/
-/*}*/
-
-.resultMessage span.result {
- display: block;
- line-height: 2em;
- color: black;
-}
-
-.resultMessage .mismatch {
- color: black;
-}
-
-.stackTrace {
- white-space: pre;
- font-size: .8em;
- margin-left: 10px;
- max-height: 5em;
- overflow: auto;
- border: 1px inset red;
- padding: 1em;
- background: #eef;
-}
-
-.finished-at {
- padding-left: 1em;
- font-size: .6em;
-}
-
-.show-passed .passed,
-.show-skipped .skipped {
- display: block;
-}
-
-
-#jasmine_content {
- position:fixed;
- right: 100%;
-}
-
-.runner {
- border: 1px solid gray;
- display: block;
- margin: 5px 0;
- padding: 2px 0 2px 10px;
-}
diff --git a/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.js b/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.js
deleted file mode 100644
index c3d2dc7d2d3..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.js
+++ /dev/null
@@ -1,2476 +0,0 @@
-var isCommonJS = typeof window == "undefined";
-
-/**
- * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
- *
- * @namespace
- */
-var jasmine = {};
-if (isCommonJS) exports.jasmine = jasmine;
-/**
- * @private
- */
-jasmine.unimplementedMethod_ = function() {
- throw new Error("unimplemented method");
-};
-
-/**
- * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
- * a plain old variable and may be redefined by somebody else.
- *
- * @private
- */
-jasmine.undefined = jasmine.___undefined___;
-
-/**
- * Show diagnostic messages in the console if set to true
- *
- */
-jasmine.VERBOSE = false;
-
-/**
- * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
- *
- */
-jasmine.DEFAULT_UPDATE_INTERVAL = 250;
-
-/**
- * Default timeout interval in milliseconds for waitsFor() blocks.
- */
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
-
-jasmine.getGlobal = function() {
- function getGlobal() {
- return this;
- }
-
- return getGlobal();
-};
-
-/**
- * Allows for bound functions to be compared. Internal use only.
- *
- * @ignore
- * @private
- * @param base {Object} bound 'this' for the function
- * @param name {Function} function to find
- */
-jasmine.bindOriginal_ = function(base, name) {
- var original = base[name];
- if (original.apply) {
- return function() {
- return original.apply(base, arguments);
- };
- } else {
- // IE support
- return jasmine.getGlobal()[name];
- }
-};
-
-jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
-jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
-jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
-jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
-
-jasmine.MessageResult = function(values) {
- this.type = 'log';
- this.values = values;
- this.trace = new Error(); // todo: test better
-};
-
-jasmine.MessageResult.prototype.toString = function() {
- var text = "";
- for (var i = 0; i < this.values.length; i++) {
- if (i > 0) text += " ";
- if (jasmine.isString_(this.values[i])) {
- text += this.values[i];
- } else {
- text += jasmine.pp(this.values[i]);
- }
- }
- return text;
-};
-
-jasmine.ExpectationResult = function(params) {
- this.type = 'expect';
- this.matcherName = params.matcherName;
- this.passed_ = params.passed;
- this.expected = params.expected;
- this.actual = params.actual;
- this.message = this.passed_ ? 'Passed.' : params.message;
-
- var trace = (params.trace || new Error(this.message));
- this.trace = this.passed_ ? '' : trace;
-};
-
-jasmine.ExpectationResult.prototype.toString = function () {
- return this.message;
-};
-
-jasmine.ExpectationResult.prototype.passed = function () {
- return this.passed_;
-};
-
-/**
- * Getter for the Jasmine environment. Ensures one gets created
- */
-jasmine.getEnv = function() {
- var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
- return env;
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isArray_ = function(value) {
- return jasmine.isA_("Array", value);
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isString_ = function(value) {
- return jasmine.isA_("String", value);
-};
-
-/**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
-jasmine.isNumber_ = function(value) {
- return jasmine.isA_("Number", value);
-};
-
-/**
- * @ignore
- * @private
- * @param {String} typeName
- * @param value
- * @returns {Boolean}
- */
-jasmine.isA_ = function(typeName, value) {
- return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
-};
-
-/**
- * Pretty printer for expecations. Takes any object and turns it into a human-readable string.
- *
- * @param value {Object} an object to be outputted
- * @returns {String}
- */
-jasmine.pp = function(value) {
- var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
- stringPrettyPrinter.format(value);
- return stringPrettyPrinter.string;
-};
-
-/**
- * Returns true if the object is a DOM Node.
- *
- * @param {Object} obj object to check
- * @returns {Boolean}
- */
-jasmine.isDomNode = function(obj) {
- return obj.nodeType > 0;
-};
-
-/**
- * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
- *
- * @example
- * // don't care about which function is passed in, as long as it's a function
- * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
- *
- * @param {Class} clazz
- * @returns matchable object of the type clazz
- */
-jasmine.any = function(clazz) {
- return new jasmine.Matchers.Any(clazz);
-};
-
-/**
- * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
- *
- * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
- * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
- *
- * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
- *
- * Spies are torn down at the end of every spec.
- *
- * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
- *
- * @example
- * // a stub
- * var myStub = jasmine.createSpy('myStub'); // can be used anywhere
- *
- * // spy example
- * var foo = {
- * not: function(bool) { return !bool; }
- * }
- *
- * // actual foo.not will not be called, execution stops
- * spyOn(foo, 'not');
-
- // foo.not spied upon, execution will continue to implementation
- * spyOn(foo, 'not').andCallThrough();
- *
- * // fake example
- * var foo = {
- * not: function(bool) { return !bool; }
- * }
- *
- * // foo.not(val) will return val
- * spyOn(foo, 'not').andCallFake(function(value) {return value;});
- *
- * // mock example
- * foo.not(7 == 7);
- * expect(foo.not).toHaveBeenCalled();
- * expect(foo.not).toHaveBeenCalledWith(true);
- *
- * @constructor
- * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
- * @param {String} name
- */
-jasmine.Spy = function(name) {
- /**
- * The name of the spy, if provided.
- */
- this.identity = name || 'unknown';
- /**
- * Is this Object a spy?
- */
- this.isSpy = true;
- /**
- * The actual function this spy stubs.
- */
- this.plan = function() {
- };
- /**
- * Tracking of the most recent call to the spy.
- * @example
- * var mySpy = jasmine.createSpy('foo');
- * mySpy(1, 2);
- * mySpy.mostRecentCall.args = [1, 2];
- */
- this.mostRecentCall = {};
-
- /**
- * Holds arguments for each call to the spy, indexed by call count
- * @example
- * var mySpy = jasmine.createSpy('foo');
- * mySpy(1, 2);
- * mySpy(7, 8);
- * mySpy.mostRecentCall.args = [7, 8];
- * mySpy.argsForCall[0] = [1, 2];
- * mySpy.argsForCall[1] = [7, 8];
- */
- this.argsForCall = [];
- this.calls = [];
-};
-
-/**
- * Tells a spy to call through to the actual implemenatation.
- *
- * @example
- * var foo = {
- * bar: function() { // do some stuff }
- * }
- *
- * // defining a spy on an existing property: foo.bar
- * spyOn(foo, 'bar').andCallThrough();
- */
-jasmine.Spy.prototype.andCallThrough = function() {
- this.plan = this.originalValue;
- return this;
-};
-
-/**
- * For setting the return value of a spy.
- *
- * @example
- * // defining a spy from scratch: foo() returns 'baz'
- * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
- *
- * // defining a spy on an existing property: foo.bar() returns 'baz'
- * spyOn(foo, 'bar').andReturn('baz');
- *
- * @param {Object} value
- */
-jasmine.Spy.prototype.andReturn = function(value) {
- this.plan = function() {
- return value;
- };
- return this;
-};
-
-/**
- * For throwing an exception when a spy is called.
- *
- * @example
- * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
- * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
- *
- * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
- * spyOn(foo, 'bar').andThrow('baz');
- *
- * @param {String} exceptionMsg
- */
-jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
- this.plan = function() {
- throw exceptionMsg;
- };
- return this;
-};
-
-/**
- * Calls an alternate implementation when a spy is called.
- *
- * @example
- * var baz = function() {
- * // do some stuff, return something
- * }
- * // defining a spy from scratch: foo() calls the function baz
- * var foo = jasmine.createSpy('spy on foo').andCall(baz);
- *
- * // defining a spy on an existing property: foo.bar() calls an anonymnous function
- * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
- *
- * @param {Function} fakeFunc
- */
-jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
- this.plan = fakeFunc;
- return this;
-};
-
-/**
- * Resets all of a spy's the tracking variables so that it can be used again.
- *
- * @example
- * spyOn(foo, 'bar');
- *
- * foo.bar();
- *
- * expect(foo.bar.callCount).toEqual(1);
- *
- * foo.bar.reset();
- *
- * expect(foo.bar.callCount).toEqual(0);
- */
-jasmine.Spy.prototype.reset = function() {
- this.wasCalled = false;
- this.callCount = 0;
- this.argsForCall = [];
- this.calls = [];
- this.mostRecentCall = {};
-};
-
-jasmine.createSpy = function(name) {
-
- var spyObj = function() {
- spyObj.wasCalled = true;
- spyObj.callCount++;
- var args = jasmine.util.argsToArray(arguments);
- spyObj.mostRecentCall.object = this;
- spyObj.mostRecentCall.args = args;
- spyObj.argsForCall.push(args);
- spyObj.calls.push({object: this, args: args});
- return spyObj.plan.apply(this, arguments);
- };
-
- var spy = new jasmine.Spy(name);
-
- for (var prop in spy) {
- spyObj[prop] = spy[prop];
- }
-
- spyObj.reset();
-
- return spyObj;
-};
-
-/**
- * Determines whether an object is a spy.
- *
- * @param {jasmine.Spy|Object} putativeSpy
- * @returns {Boolean}
- */
-jasmine.isSpy = function(putativeSpy) {
- return putativeSpy && putativeSpy.isSpy;
-};
-
-/**
- * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
- * large in one call.
- *
- * @param {String} baseName name of spy class
- * @param {Array} methodNames array of names of methods to make spies
- */
-jasmine.createSpyObj = function(baseName, methodNames) {
- if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
- throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
- }
- var obj = {};
- for (var i = 0; i < methodNames.length; i++) {
- obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
- }
- return obj;
-};
-
-/**
- * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
-jasmine.log = function() {
- var spec = jasmine.getEnv().currentSpec;
- spec.log.apply(spec, arguments);
-};
-
-/**
- * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
- *
- * @example
- * // spy example
- * var foo = {
- * not: function(bool) { return !bool; }
- * }
- * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
- *
- * @see jasmine.createSpy
- * @param obj
- * @param methodName
- * @returns a Jasmine spy that can be chained with all spy methods
- */
-var spyOn = function(obj, methodName) {
- return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
-};
-if (isCommonJS) exports.spyOn = spyOn;
-
-/**
- * Creates a Jasmine spec that will be added to the current suite.
- *
- * // TODO: pending tests
- *
- * @example
- * it('should be true', function() {
- * expect(true).toEqual(true);
- * });
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
-var it = function(desc, func) {
- return jasmine.getEnv().it(desc, func);
-};
-if (isCommonJS) exports.it = it;
-
-/**
- * Creates a <em>disabled</em> Jasmine spec.
- *
- * A convenience method that allows existing specs to be disabled temporarily during development.
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
-var xit = function(desc, func) {
- return jasmine.getEnv().xit(desc, func);
-};
-if (isCommonJS) exports.xit = xit;
-
-/**
- * Starts a chain for a Jasmine expectation.
- *
- * It is passed an Object that is the actual value and should chain to one of the many
- * jasmine.Matchers functions.
- *
- * @param {Object} actual Actual value to test against and expected value
- */
-var expect = function(actual) {
- return jasmine.getEnv().currentSpec.expect(actual);
-};
-if (isCommonJS) exports.expect = expect;
-
-/**
- * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
- *
- * @param {Function} func Function that defines part of a jasmine spec.
- */
-var runs = function(func) {
- jasmine.getEnv().currentSpec.runs(func);
-};
-if (isCommonJS) exports.runs = runs;
-
-/**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
-var waits = function(timeout) {
- jasmine.getEnv().currentSpec.waits(timeout);
-};
-if (isCommonJS) exports.waits = waits;
-
-/**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
-var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
- jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
-};
-if (isCommonJS) exports.waitsFor = waitsFor;
-
-/**
- * A function that is called before each spec in a suite.
- *
- * Used for spec setup, including validating assumptions.
- *
- * @param {Function} beforeEachFunction
- */
-var beforeEach = function(beforeEachFunction) {
- jasmine.getEnv().beforeEach(beforeEachFunction);
-};
-if (isCommonJS) exports.beforeEach = beforeEach;
-
-/**
- * A function that is called after each spec in a suite.
- *
- * Used for restoring any state that is hijacked during spec execution.
- *
- * @param {Function} afterEachFunction
- */
-var afterEach = function(afterEachFunction) {
- jasmine.getEnv().afterEach(afterEachFunction);
-};
-if (isCommonJS) exports.afterEach = afterEach;
-
-/**
- * Defines a suite of specifications.
- *
- * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
- * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
- * of setup in some tests.
- *
- * @example
- * // TODO: a simple suite
- *
- * // TODO: a simple suite with a nested describe block
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
-var describe = function(description, specDefinitions) {
- return jasmine.getEnv().describe(description, specDefinitions);
-};
-if (isCommonJS) exports.describe = describe;
-
-/**
- * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
-var xdescribe = function(description, specDefinitions) {
- return jasmine.getEnv().xdescribe(description, specDefinitions);
-};
-if (isCommonJS) exports.xdescribe = xdescribe;
-
-
-// Provide the XMLHttpRequest class for IE 5.x-6.x:
-jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
- function tryIt(f) {
- try {
- return f();
- } catch(e) {
- }
- return null;
- }
-
- var xhr = tryIt(function() {
- return new ActiveXObject("Msxml2.XMLHTTP.6.0");
- }) ||
- tryIt(function() {
- return new ActiveXObject("Msxml2.XMLHTTP.3.0");
- }) ||
- tryIt(function() {
- return new ActiveXObject("Msxml2.XMLHTTP");
- }) ||
- tryIt(function() {
- return new ActiveXObject("Microsoft.XMLHTTP");
- });
-
- if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
-
- return xhr;
-} : XMLHttpRequest;
-/**
- * @namespace
- */
-jasmine.util = {};
-
-/**
- * Declare that a child class inherit it's prototype from the parent class.
- *
- * @private
- * @param {Function} childClass
- * @param {Function} parentClass
- */
-jasmine.util.inherit = function(childClass, parentClass) {
- /**
- * @private
- */
- var subclass = function() {
- };
- subclass.prototype = parentClass.prototype;
- childClass.prototype = new subclass();
-};
-
-jasmine.util.formatException = function(e) {
- var lineNumber;
- if (e.line) {
- lineNumber = e.line;
- }
- else if (e.lineNumber) {
- lineNumber = e.lineNumber;
- }
-
- var file;
-
- if (e.sourceURL) {
- file = e.sourceURL;
- }
- else if (e.fileName) {
- file = e.fileName;
- }
-
- var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
-
- if (file && lineNumber) {
- message += ' in ' + file + ' (line ' + lineNumber + ')';
- }
-
- return message;
-};
-
-jasmine.util.htmlEscape = function(str) {
- if (!str) return str;
- return str.replace(/&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;');
-};
-
-jasmine.util.argsToArray = function(args) {
- var arrayOfArgs = [];
- for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
- return arrayOfArgs;
-};
-
-jasmine.util.extend = function(destination, source) {
- for (var property in source) destination[property] = source[property];
- return destination;
-};
-
-/**
- * Environment for Jasmine
- *
- * @constructor
- */
-jasmine.Env = function() {
- this.currentSpec = null;
- this.currentSuite = null;
- this.currentRunner_ = new jasmine.Runner(this);
-
- this.reporter = new jasmine.MultiReporter();
-
- this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
- this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
- this.lastUpdate = 0;
- this.specFilter = function() {
- return true;
- };
-
- this.nextSpecId_ = 0;
- this.nextSuiteId_ = 0;
- this.equalityTesters_ = [];
-
- // wrap matchers
- this.matchersClass = function() {
- jasmine.Matchers.apply(this, arguments);
- };
- jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
-
- jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
-};
-
-
-jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
-jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
-jasmine.Env.prototype.setInterval = jasmine.setInterval;
-jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
-
-/**
- * @returns an object containing jasmine version build info, if set.
- */
-jasmine.Env.prototype.version = function () {
- if (jasmine.version_) {
- return jasmine.version_;
- } else {
- throw new Error('Version not set');
- }
-};
-
-/**
- * @returns string containing jasmine version build info, if set.
- */
-jasmine.Env.prototype.versionString = function() {
- if (!jasmine.version_) {
- return "version unknown";
- }
-
- var version = this.version();
- var versionString = version.major + "." + version.minor + "." + version.build;
- if (version.release_candidate) {
- versionString += ".rc" + version.release_candidate;
- }
- versionString += " revision " + version.revision;
- return versionString;
-};
-
-/**
- * @returns a sequential integer starting at 0
- */
-jasmine.Env.prototype.nextSpecId = function () {
- return this.nextSpecId_++;
-};
-
-/**
- * @returns a sequential integer starting at 0
- */
-jasmine.Env.prototype.nextSuiteId = function () {
- return this.nextSuiteId_++;
-};
-
-/**
- * Register a reporter to receive status updates from Jasmine.
- * @param {jasmine.Reporter} reporter An object which will receive status updates.
- */
-jasmine.Env.prototype.addReporter = function(reporter) {
- this.reporter.addReporter(reporter);
-};
-
-jasmine.Env.prototype.execute = function() {
- this.currentRunner_.execute();
-};
-
-jasmine.Env.prototype.describe = function(description, specDefinitions) {
- var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
-
- var parentSuite = this.currentSuite;
- if (parentSuite) {
- parentSuite.add(suite);
- } else {
- this.currentRunner_.add(suite);
- }
-
- this.currentSuite = suite;
-
- var declarationError = null;
- try {
- specDefinitions.call(suite);
- } catch(e) {
- declarationError = e;
- }
-
- if (declarationError) {
- this.it("encountered a declaration exception", function() {
- throw declarationError;
- });
- }
-
- this.currentSuite = parentSuite;
-
- return suite;
-};
-
-jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
- if (this.currentSuite) {
- this.currentSuite.beforeEach(beforeEachFunction);
- } else {
- this.currentRunner_.beforeEach(beforeEachFunction);
- }
-};
-
-jasmine.Env.prototype.currentRunner = function () {
- return this.currentRunner_;
-};
-
-jasmine.Env.prototype.afterEach = function(afterEachFunction) {
- if (this.currentSuite) {
- this.currentSuite.afterEach(afterEachFunction);
- } else {
- this.currentRunner_.afterEach(afterEachFunction);
- }
-
-};
-
-jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
- return {
- execute: function() {
- }
- };
-};
-
-jasmine.Env.prototype.it = function(description, func) {
- var spec = new jasmine.Spec(this, this.currentSuite, description);
- this.currentSuite.add(spec);
- this.currentSpec = spec;
-
- if (func) {
- spec.runs(func);
- }
-
- return spec;
-};
-
-jasmine.Env.prototype.xit = function(desc, func) {
- return {
- id: this.nextSpecId(),
- runs: function() {
- }
- };
-};
-
-jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
- if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
- return true;
- }
-
- a.__Jasmine_been_here_before__ = b;
- b.__Jasmine_been_here_before__ = a;
-
- var hasKey = function(obj, keyName) {
- return obj !== null && obj[keyName] !== jasmine.undefined;
- };
-
- for (var property in b) {
- if (!hasKey(a, property) && hasKey(b, property)) {
- mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
- }
- }
- for (property in a) {
- if (!hasKey(b, property) && hasKey(a, property)) {
- mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
- }
- }
- for (property in b) {
- if (property == '__Jasmine_been_here_before__') continue;
- if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
- mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
- }
- }
-
- if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
- mismatchValues.push("arrays were not the same length");
- }
-
- delete a.__Jasmine_been_here_before__;
- delete b.__Jasmine_been_here_before__;
- return (mismatchKeys.length === 0 && mismatchValues.length === 0);
-};
-
-jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
- mismatchKeys = mismatchKeys || [];
- mismatchValues = mismatchValues || [];
-
- for (var i = 0; i < this.equalityTesters_.length; i++) {
- var equalityTester = this.equalityTesters_[i];
- var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
- if (result !== jasmine.undefined) return result;
- }
-
- if (a === b) return true;
-
- if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
- return (a == jasmine.undefined && b == jasmine.undefined);
- }
-
- if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
- return a === b;
- }
-
- if (a instanceof Date && b instanceof Date) {
- return a.getTime() == b.getTime();
- }
-
- if (a instanceof jasmine.Matchers.Any) {
- return a.matches(b);
- }
-
- if (b instanceof jasmine.Matchers.Any) {
- return b.matches(a);
- }
-
- if (jasmine.isString_(a) && jasmine.isString_(b)) {
- return (a == b);
- }
-
- if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
- return (a == b);
- }
-
- if (typeof a === "object" && typeof b === "object") {
- return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
- }
-
- //Straight check
- return (a === b);
-};
-
-jasmine.Env.prototype.contains_ = function(haystack, needle) {
- if (jasmine.isArray_(haystack)) {
- for (var i = 0; i < haystack.length; i++) {
- if (this.equals_(haystack[i], needle)) return true;
- }
- return false;
- }
- return haystack.indexOf(needle) >= 0;
-};
-
-jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
- this.equalityTesters_.push(equalityTester);
-};
-/** No-op base class for Jasmine reporters.
- *
- * @constructor
- */
-jasmine.Reporter = function() {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecResults = function(spec) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.log = function(str) {
-};
-
-/**
- * Blocks are functions with executable code that make up a spec.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {Function} func
- * @param {jasmine.Spec} spec
- */
-jasmine.Block = function(env, func, spec) {
- this.env = env;
- this.func = func;
- this.spec = spec;
-};
-
-jasmine.Block.prototype.execute = function(onComplete) {
- try {
- this.func.apply(this.spec);
- } catch (e) {
- this.spec.fail(e);
- }
- onComplete();
-};
-/** JavaScript API reporter.
- *
- * @constructor
- */
-jasmine.JsApiReporter = function() {
- this.started = false;
- this.finished = false;
- this.suites_ = [];
- this.results_ = {};
-};
-
-jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
- this.started = true;
- var suites = runner.topLevelSuites();
- for (var i = 0; i < suites.length; i++) {
- var suite = suites[i];
- this.suites_.push(this.summarize_(suite));
- }
-};
-
-jasmine.JsApiReporter.prototype.suites = function() {
- return this.suites_;
-};
-
-jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
- var isSuite = suiteOrSpec instanceof jasmine.Suite;
- var summary = {
- id: suiteOrSpec.id,
- name: suiteOrSpec.description,
- type: isSuite ? 'suite' : 'spec',
- children: []
- };
-
- if (isSuite) {
- var children = suiteOrSpec.children();
- for (var i = 0; i < children.length; i++) {
- summary.children.push(this.summarize_(children[i]));
- }
- }
- return summary;
-};
-
-jasmine.JsApiReporter.prototype.results = function() {
- return this.results_;
-};
-
-jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
- return this.results_[specId];
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
- this.finished = true;
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
- this.results_[spec.id] = {
- messages: spec.results().getItems(),
- result: spec.results().failedCount > 0 ? "failed" : "passed"
- };
-};
-
-//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.log = function(str) {
-};
-
-jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
- var results = {};
- for (var i = 0; i < specIds.length; i++) {
- var specId = specIds[i];
- results[specId] = this.summarizeResult_(this.results_[specId]);
- }
- return results;
-};
-
-jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
- var summaryMessages = [];
- var messagesLength = result.messages.length;
- for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
- var resultMessage = result.messages[messageIndex];
- summaryMessages.push({
- text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
- passed: resultMessage.passed ? resultMessage.passed() : true,
- type: resultMessage.type,
- message: resultMessage.message,
- trace: {
- stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
- }
- });
- }
-
- return {
- result : result.result,
- messages : summaryMessages
- };
-};
-
-/**
- * @constructor
- * @param {jasmine.Env} env
- * @param actual
- * @param {jasmine.Spec} spec
- */
-jasmine.Matchers = function(env, actual, spec, opt_isNot) {
- this.env = env;
- this.actual = actual;
- this.spec = spec;
- this.isNot = opt_isNot || false;
- this.reportWasCalled_ = false;
-};
-
-// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
-jasmine.Matchers.pp = function(str) {
- throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
-};
-
-// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
-jasmine.Matchers.prototype.report = function(result, failing_message, details) {
- throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
-};
-
-jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
- for (var methodName in prototype) {
- if (methodName == 'report') continue;
- var orig = prototype[methodName];
- matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
- }
-};
-
-jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
- return function() {
- var matcherArgs = jasmine.util.argsToArray(arguments);
- var result = matcherFunction.apply(this, arguments);
-
- if (this.isNot) {
- result = !result;
- }
-
- if (this.reportWasCalled_) return result;
-
- var message;
- if (!result) {
- if (this.message) {
- message = this.message.apply(this, arguments);
- if (jasmine.isArray_(message)) {
- message = message[this.isNot ? 1 : 0];
- }
- } else {
- var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
- message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
- if (matcherArgs.length > 0) {
- for (var i = 0; i < matcherArgs.length; i++) {
- if (i > 0) message += ",";
- message += " " + jasmine.pp(matcherArgs[i]);
- }
- }
- message += ".";
- }
- }
- var expectationResult = new jasmine.ExpectationResult({
- matcherName: matcherName,
- passed: result,
- expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
- actual: this.actual,
- message: message
- });
- this.spec.addMatcherResult(expectationResult);
- return jasmine.undefined;
- };
-};
-
-
-
-
-/**
- * toBe: compares the actual to the expected using ===
- * @param expected
- */
-jasmine.Matchers.prototype.toBe = function(expected) {
- return this.actual === expected;
-};
-
-/**
- * toNotBe: compares the actual to the expected using !==
- * @param expected
- * @deprecated as of 1.0. Use not.toBe() instead.
- */
-jasmine.Matchers.prototype.toNotBe = function(expected) {
- return this.actual !== expected;
-};
-
-/**
- * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
- *
- * @param expected
- */
-jasmine.Matchers.prototype.toEqual = function(expected) {
- return this.env.equals_(this.actual, expected);
-};
-
-/**
- * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
- * @param expected
- * @deprecated as of 1.0. Use not.toNotEqual() instead.
- */
-jasmine.Matchers.prototype.toNotEqual = function(expected) {
- return !this.env.equals_(this.actual, expected);
-};
-
-/**
- * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
- * a pattern or a String.
- *
- * @param expected
- */
-jasmine.Matchers.prototype.toMatch = function(expected) {
- return new RegExp(expected).test(this.actual);
-};
-
-/**
- * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
- * @param expected
- * @deprecated as of 1.0. Use not.toMatch() instead.
- */
-jasmine.Matchers.prototype.toNotMatch = function(expected) {
- return !(new RegExp(expected).test(this.actual));
-};
-
-/**
- * Matcher that compares the actual to jasmine.undefined.
- */
-jasmine.Matchers.prototype.toBeDefined = function() {
- return (this.actual !== jasmine.undefined);
-};
-
-/**
- * Matcher that compares the actual to jasmine.undefined.
- */
-jasmine.Matchers.prototype.toBeUndefined = function() {
- return (this.actual === jasmine.undefined);
-};
-
-/**
- * Matcher that compares the actual to null.
- */
-jasmine.Matchers.prototype.toBeNull = function() {
- return (this.actual === null);
-};
-
-/**
- * Matcher that boolean not-nots the actual.
- */
-jasmine.Matchers.prototype.toBeTruthy = function() {
- return !!this.actual;
-};
-
-
-/**
- * Matcher that boolean nots the actual.
- */
-jasmine.Matchers.prototype.toBeFalsy = function() {
- return !this.actual;
-};
-
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was called.
- */
-jasmine.Matchers.prototype.toHaveBeenCalled = function() {
- if (arguments.length > 0) {
- throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
- }
-
- if (!jasmine.isSpy(this.actual)) {
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
- }
-
- this.message = function() {
- return [
- "Expected spy " + this.actual.identity + " to have been called.",
- "Expected spy " + this.actual.identity + " not to have been called."
- ];
- };
-
- return this.actual.wasCalled;
-};
-
-/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
-jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was not called.
- *
- * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
- */
-jasmine.Matchers.prototype.wasNotCalled = function() {
- if (arguments.length > 0) {
- throw new Error('wasNotCalled does not take arguments');
- }
-
- if (!jasmine.isSpy(this.actual)) {
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
- }
-
- this.message = function() {
- return [
- "Expected spy " + this.actual.identity + " to not have been called.",
- "Expected spy " + this.actual.identity + " to have been called."
- ];
- };
-
- return !this.actual.wasCalled;
-};
-
-/**
- * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
- *
- * @example
- *
- */
-jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
- var expectedArgs = jasmine.util.argsToArray(arguments);
- if (!jasmine.isSpy(this.actual)) {
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
- }
- this.message = function() {
- if (this.actual.callCount === 0) {
- // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
- return [
- "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
- "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
- ];
- } else {
- return [
- "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
- "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
- ];
- }
- };
-
- return this.env.contains_(this.actual.argsForCall, expectedArgs);
-};
-
-/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
-
-/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasNotCalledWith = function() {
- var expectedArgs = jasmine.util.argsToArray(arguments);
- if (!jasmine.isSpy(this.actual)) {
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
- }
-
- this.message = function() {
- return [
- "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
- "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
- ];
- };
-
- return !this.env.contains_(this.actual.argsForCall, expectedArgs);
-};
-
-/**
- * Matcher that checks that the expected item is an element in the actual Array.
- *
- * @param {Object} expected
- */
-jasmine.Matchers.prototype.toContain = function(expected) {
- return this.env.contains_(this.actual, expected);
-};
-
-/**
- * Matcher that checks that the expected item is NOT an element in the actual Array.
- *
- * @param {Object} expected
- * @deprecated as of 1.0. Use not.toNotContain() instead.
- */
-jasmine.Matchers.prototype.toNotContain = function(expected) {
- return !this.env.contains_(this.actual, expected);
-};
-
-jasmine.Matchers.prototype.toBeLessThan = function(expected) {
- return this.actual < expected;
-};
-
-jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
- return this.actual > expected;
-};
-
-/**
- * Matcher that checks that the expected item is equal to the actual item
- * up to a given level of decimal precision (default 2).
- *
- * @param {Number} expected
- * @param {Number} precision
- */
-jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
- if (!(precision === 0)) {
- precision = precision || 2;
- }
- var multiplier = Math.pow(10, precision);
- var actual = Math.round(this.actual * multiplier);
- expected = Math.round(expected * multiplier);
- return expected == actual;
-};
-
-/**
- * Matcher that checks that the expected exception was thrown by the actual.
- *
- * @param {String} expected
- */
-jasmine.Matchers.prototype.toThrow = function(expected) {
- var result = false;
- var exception;
- if (typeof this.actual != 'function') {
- throw new Error('Actual is not a function');
- }
- try {
- this.actual();
- } catch (e) {
- exception = e;
- }
- if (exception) {
- result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
- }
-
- var not = this.isNot ? "not " : "";
-
- this.message = function() {
- if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
- return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
- } else {
- return "Expected function to throw an exception.";
- }
- };
-
- return result;
-};
-
-jasmine.Matchers.Any = function(expectedClass) {
- this.expectedClass = expectedClass;
-};
-
-jasmine.Matchers.Any.prototype.matches = function(other) {
- if (this.expectedClass == String) {
- return typeof other == 'string' || other instanceof String;
- }
-
- if (this.expectedClass == Number) {
- return typeof other == 'number' || other instanceof Number;
- }
-
- if (this.expectedClass == Function) {
- return typeof other == 'function' || other instanceof Function;
- }
-
- if (this.expectedClass == Object) {
- return typeof other == 'object';
- }
-
- return other instanceof this.expectedClass;
-};
-
-jasmine.Matchers.Any.prototype.toString = function() {
- return '<jasmine.any(' + this.expectedClass + ')>';
-};
-
-/**
- * @constructor
- */
-jasmine.MultiReporter = function() {
- this.subReporters_ = [];
-};
-jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
-
-jasmine.MultiReporter.prototype.addReporter = function(reporter) {
- this.subReporters_.push(reporter);
-};
-
-(function() {
- var functionNames = [
- "reportRunnerStarting",
- "reportRunnerResults",
- "reportSuiteResults",
- "reportSpecStarting",
- "reportSpecResults",
- "log"
- ];
- for (var i = 0; i < functionNames.length; i++) {
- var functionName = functionNames[i];
- jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
- return function() {
- for (var j = 0; j < this.subReporters_.length; j++) {
- var subReporter = this.subReporters_[j];
- if (subReporter[functionName]) {
- subReporter[functionName].apply(subReporter, arguments);
- }
- }
- };
- })(functionName);
- }
-})();
-/**
- * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
- *
- * @constructor
- */
-jasmine.NestedResults = function() {
- /**
- * The total count of results
- */
- this.totalCount = 0;
- /**
- * Number of passed results
- */
- this.passedCount = 0;
- /**
- * Number of failed results
- */
- this.failedCount = 0;
- /**
- * Was this suite/spec skipped?
- */
- this.skipped = false;
- /**
- * @ignore
- */
- this.items_ = [];
-};
-
-/**
- * Roll up the result counts.
- *
- * @param result
- */
-jasmine.NestedResults.prototype.rollupCounts = function(result) {
- this.totalCount += result.totalCount;
- this.passedCount += result.passedCount;
- this.failedCount += result.failedCount;
-};
-
-/**
- * Adds a log message.
- * @param values Array of message parts which will be concatenated later.
- */
-jasmine.NestedResults.prototype.log = function(values) {
- this.items_.push(new jasmine.MessageResult(values));
-};
-
-/**
- * Getter for the results: message & results.
- */
-jasmine.NestedResults.prototype.getItems = function() {
- return this.items_;
-};
-
-/**
- * Adds a result, tracking counts (total, passed, & failed)
- * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
- */
-jasmine.NestedResults.prototype.addResult = function(result) {
- if (result.type != 'log') {
- if (result.items_) {
- this.rollupCounts(result);
- } else {
- this.totalCount++;
- if (result.passed()) {
- this.passedCount++;
- } else {
- this.failedCount++;
- }
- }
- }
- this.items_.push(result);
-};
-
-/**
- * @returns {Boolean} True if <b>everything</b> below passed
- */
-jasmine.NestedResults.prototype.passed = function() {
- return this.passedCount === this.totalCount;
-};
-/**
- * Base class for pretty printing for expectation results.
- */
-jasmine.PrettyPrinter = function() {
- this.ppNestLevel_ = 0;
-};
-
-/**
- * Formats a value in a nice, human-readable string.
- *
- * @param value
- */
-jasmine.PrettyPrinter.prototype.format = function(value) {
- if (this.ppNestLevel_ > 40) {
- throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
- }
-
- this.ppNestLevel_++;
- try {
- if (value === jasmine.undefined) {
- this.emitScalar('undefined');
- } else if (value === null) {
- this.emitScalar('null');
- } else if (value === jasmine.getGlobal()) {
- this.emitScalar('<global>');
- } else if (value instanceof jasmine.Matchers.Any) {
- this.emitScalar(value.toString());
- } else if (typeof value === 'string') {
- this.emitString(value);
- } else if (jasmine.isSpy(value)) {
- this.emitScalar("spy on " + value.identity);
- } else if (value instanceof RegExp) {
- this.emitScalar(value.toString());
- } else if (typeof value === 'function') {
- this.emitScalar('Function');
- } else if (typeof value.nodeType === 'number') {
- this.emitScalar('HTMLNode');
- } else if (value instanceof Date) {
- this.emitScalar('Date(' + value + ')');
- } else if (value.__Jasmine_been_here_before__) {
- this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
- } else if (jasmine.isArray_(value) || typeof value == 'object') {
- value.__Jasmine_been_here_before__ = true;
- if (jasmine.isArray_(value)) {
- this.emitArray(value);
- } else {
- this.emitObject(value);
- }
- delete value.__Jasmine_been_here_before__;
- } else {
- this.emitScalar(value.toString());
- }
- } finally {
- this.ppNestLevel_--;
- }
-};
-
-jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
- for (var property in obj) {
- if (property == '__Jasmine_been_here_before__') continue;
- fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
- obj.__lookupGetter__(property) !== null) : false);
- }
-};
-
-jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
-jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
-
-jasmine.StringPrettyPrinter = function() {
- jasmine.PrettyPrinter.call(this);
-
- this.string = '';
-};
-jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
-
-jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
- this.append(value);
-};
-
-jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
- this.append("'" + value + "'");
-};
-
-jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
- this.append('[ ');
- for (var i = 0; i < array.length; i++) {
- if (i > 0) {
- this.append(', ');
- }
- this.format(array[i]);
- }
- this.append(' ]');
-};
-
-jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
- var self = this;
- this.append('{ ');
- var first = true;
-
- this.iterateObject(obj, function(property, isGetter) {
- if (first) {
- first = false;
- } else {
- self.append(', ');
- }
-
- self.append(property);
- self.append(' : ');
- if (isGetter) {
- self.append('<getter>');
- } else {
- self.format(obj[property]);
- }
- });
-
- this.append(' }');
-};
-
-jasmine.StringPrettyPrinter.prototype.append = function(value) {
- this.string += value;
-};
-jasmine.Queue = function(env) {
- this.env = env;
- this.blocks = [];
- this.running = false;
- this.index = 0;
- this.offset = 0;
- this.abort = false;
-};
-
-jasmine.Queue.prototype.addBefore = function(block) {
- this.blocks.unshift(block);
-};
-
-jasmine.Queue.prototype.add = function(block) {
- this.blocks.push(block);
-};
-
-jasmine.Queue.prototype.insertNext = function(block) {
- this.blocks.splice((this.index + this.offset + 1), 0, block);
- this.offset++;
-};
-
-jasmine.Queue.prototype.start = function(onComplete) {
- this.running = true;
- this.onComplete = onComplete;
- this.next_();
-};
-
-jasmine.Queue.prototype.isRunning = function() {
- return this.running;
-};
-
-jasmine.Queue.LOOP_DONT_RECURSE = true;
-
-jasmine.Queue.prototype.next_ = function() {
- var self = this;
- var goAgain = true;
-
- while (goAgain) {
- goAgain = false;
-
- if (self.index < self.blocks.length && !this.abort) {
- var calledSynchronously = true;
- var completedSynchronously = false;
-
- var onComplete = function () {
- if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
- completedSynchronously = true;
- return;
- }
-
- if (self.blocks[self.index].abort) {
- self.abort = true;
- }
-
- self.offset = 0;
- self.index++;
-
- var now = new Date().getTime();
- if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
- self.env.lastUpdate = now;
- self.env.setTimeout(function() {
- self.next_();
- }, 0);
- } else {
- if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
- goAgain = true;
- } else {
- self.next_();
- }
- }
- };
- self.blocks[self.index].execute(onComplete);
-
- calledSynchronously = false;
- if (completedSynchronously) {
- onComplete();
- }
-
- } else {
- self.running = false;
- if (self.onComplete) {
- self.onComplete();
- }
- }
- }
-};
-
-jasmine.Queue.prototype.results = function() {
- var results = new jasmine.NestedResults();
- for (var i = 0; i < this.blocks.length; i++) {
- if (this.blocks[i].results) {
- results.addResult(this.blocks[i].results());
- }
- }
- return results;
-};
-
-
-/**
- * Runner
- *
- * @constructor
- * @param {jasmine.Env} env
- */
-jasmine.Runner = function(env) {
- var self = this;
- self.env = env;
- self.queue = new jasmine.Queue(env);
- self.before_ = [];
- self.after_ = [];
- self.suites_ = [];
-};
-
-jasmine.Runner.prototype.execute = function() {
- var self = this;
- if (self.env.reporter.reportRunnerStarting) {
- self.env.reporter.reportRunnerStarting(this);
- }
- self.queue.start(function () {
- self.finishCallback();
- });
-};
-
-jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
- beforeEachFunction.typeName = 'beforeEach';
- this.before_.splice(0,0,beforeEachFunction);
-};
-
-jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
- afterEachFunction.typeName = 'afterEach';
- this.after_.splice(0,0,afterEachFunction);
-};
-
-
-jasmine.Runner.prototype.finishCallback = function() {
- this.env.reporter.reportRunnerResults(this);
-};
-
-jasmine.Runner.prototype.addSuite = function(suite) {
- this.suites_.push(suite);
-};
-
-jasmine.Runner.prototype.add = function(block) {
- if (block instanceof jasmine.Suite) {
- this.addSuite(block);
- }
- this.queue.add(block);
-};
-
-jasmine.Runner.prototype.specs = function () {
- var suites = this.suites();
- var specs = [];
- for (var i = 0; i < suites.length; i++) {
- specs = specs.concat(suites[i].specs());
- }
- return specs;
-};
-
-jasmine.Runner.prototype.suites = function() {
- return this.suites_;
-};
-
-jasmine.Runner.prototype.topLevelSuites = function() {
- var topLevelSuites = [];
- for (var i = 0; i < this.suites_.length; i++) {
- if (!this.suites_[i].parentSuite) {
- topLevelSuites.push(this.suites_[i]);
- }
- }
- return topLevelSuites;
-};
-
-jasmine.Runner.prototype.results = function() {
- return this.queue.results();
-};
-/**
- * Internal representation of a Jasmine specification, or test.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {jasmine.Suite} suite
- * @param {String} description
- */
-jasmine.Spec = function(env, suite, description) {
- if (!env) {
- throw new Error('jasmine.Env() required');
- }
- if (!suite) {
- throw new Error('jasmine.Suite() required');
- }
- var spec = this;
- spec.id = env.nextSpecId ? env.nextSpecId() : null;
- spec.env = env;
- spec.suite = suite;
- spec.description = description;
- spec.queue = new jasmine.Queue(env);
-
- spec.afterCallbacks = [];
- spec.spies_ = [];
-
- spec.results_ = new jasmine.NestedResults();
- spec.results_.description = description;
- spec.matchersClass = null;
-};
-
-jasmine.Spec.prototype.getFullName = function() {
- return this.suite.getFullName() + ' ' + this.description + '.';
-};
-
-
-jasmine.Spec.prototype.results = function() {
- return this.results_;
-};
-
-/**
- * All parameters are pretty-printed and concatenated together, then written to the spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
-jasmine.Spec.prototype.log = function() {
- return this.results_.log(arguments);
-};
-
-jasmine.Spec.prototype.runs = function (func) {
- var block = new jasmine.Block(this.env, func, this);
- this.addToQueue(block);
- return this;
-};
-
-jasmine.Spec.prototype.addToQueue = function (block) {
- if (this.queue.isRunning()) {
- this.queue.insertNext(block);
- } else {
- this.queue.add(block);
- }
-};
-
-/**
- * @param {jasmine.ExpectationResult} result
- */
-jasmine.Spec.prototype.addMatcherResult = function(result) {
- this.results_.addResult(result);
-};
-
-jasmine.Spec.prototype.expect = function(actual) {
- var positive = new (this.getMatchersClass_())(this.env, actual, this);
- positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
- return positive;
-};
-
-/**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
-jasmine.Spec.prototype.waits = function(timeout) {
- var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
- this.addToQueue(waitsFunc);
- return this;
-};
-
-/**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
-jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
- var latchFunction_ = null;
- var optional_timeoutMessage_ = null;
- var optional_timeout_ = null;
-
- for (var i = 0; i < arguments.length; i++) {
- var arg = arguments[i];
- switch (typeof arg) {
- case 'function':
- latchFunction_ = arg;
- break;
- case 'string':
- optional_timeoutMessage_ = arg;
- break;
- case 'number':
- optional_timeout_ = arg;
- break;
- }
- }
-
- var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
- this.addToQueue(waitsForFunc);
- return this;
-};
-
-jasmine.Spec.prototype.fail = function (e) {
- var expectationResult = new jasmine.ExpectationResult({
- passed: false,
- message: e ? jasmine.util.formatException(e) : 'Exception',
- trace: { stack: e.stack }
- });
- this.results_.addResult(expectationResult);
-};
-
-jasmine.Spec.prototype.getMatchersClass_ = function() {
- return this.matchersClass || this.env.matchersClass;
-};
-
-jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
- var parent = this.getMatchersClass_();
- var newMatchersClass = function() {
- parent.apply(this, arguments);
- };
- jasmine.util.inherit(newMatchersClass, parent);
- jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
- this.matchersClass = newMatchersClass;
-};
-
-jasmine.Spec.prototype.finishCallback = function() {
- this.env.reporter.reportSpecResults(this);
-};
-
-jasmine.Spec.prototype.finish = function(onComplete) {
- this.removeAllSpies();
- this.finishCallback();
- if (onComplete) {
- onComplete();
- }
-};
-
-jasmine.Spec.prototype.after = function(doAfter) {
- if (this.queue.isRunning()) {
- this.queue.add(new jasmine.Block(this.env, doAfter, this));
- } else {
- this.afterCallbacks.unshift(doAfter);
- }
-};
-
-jasmine.Spec.prototype.execute = function(onComplete) {
- var spec = this;
- if (!spec.env.specFilter(spec)) {
- spec.results_.skipped = true;
- spec.finish(onComplete);
- return;
- }
-
- this.env.reporter.reportSpecStarting(this);
-
- spec.env.currentSpec = spec;
-
- spec.addBeforesAndAftersToQueue();
-
- spec.queue.start(function () {
- spec.finish(onComplete);
- });
-};
-
-jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
- var runner = this.env.currentRunner();
- var i;
-
- for (var suite = this.suite; suite; suite = suite.parentSuite) {
- for (i = 0; i < suite.before_.length; i++) {
- this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
- }
- }
- for (i = 0; i < runner.before_.length; i++) {
- this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
- }
- for (i = 0; i < this.afterCallbacks.length; i++) {
- this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
- }
- for (suite = this.suite; suite; suite = suite.parentSuite) {
- for (i = 0; i < suite.after_.length; i++) {
- this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
- }
- }
- for (i = 0; i < runner.after_.length; i++) {
- this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
- }
-};
-
-jasmine.Spec.prototype.explodes = function() {
- throw 'explodes function should not have been called';
-};
-
-jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
- if (obj == jasmine.undefined) {
- throw "spyOn could not find an object to spy upon for " + methodName + "()";
- }
-
- if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
- throw methodName + '() method does not exist';
- }
-
- if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
- throw new Error(methodName + ' has already been spied upon');
- }
-
- var spyObj = jasmine.createSpy(methodName);
-
- this.spies_.push(spyObj);
- spyObj.baseObj = obj;
- spyObj.methodName = methodName;
- spyObj.originalValue = obj[methodName];
-
- obj[methodName] = spyObj;
-
- return spyObj;
-};
-
-jasmine.Spec.prototype.removeAllSpies = function() {
- for (var i = 0; i < this.spies_.length; i++) {
- var spy = this.spies_[i];
- spy.baseObj[spy.methodName] = spy.originalValue;
- }
- this.spies_ = [];
-};
-
-/**
- * Internal representation of a Jasmine suite.
- *
- * @constructor
- * @param {jasmine.Env} env
- * @param {String} description
- * @param {Function} specDefinitions
- * @param {jasmine.Suite} parentSuite
- */
-jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
- var self = this;
- self.id = env.nextSuiteId ? env.nextSuiteId() : null;
- self.description = description;
- self.queue = new jasmine.Queue(env);
- self.parentSuite = parentSuite;
- self.env = env;
- self.before_ = [];
- self.after_ = [];
- self.children_ = [];
- self.suites_ = [];
- self.specs_ = [];
-};
-
-jasmine.Suite.prototype.getFullName = function() {
- var fullName = this.description;
- for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
- fullName = parentSuite.description + ' ' + fullName;
- }
- return fullName;
-};
-
-jasmine.Suite.prototype.finish = function(onComplete) {
- this.env.reporter.reportSuiteResults(this);
- this.finished = true;
- if (typeof(onComplete) == 'function') {
- onComplete();
- }
-};
-
-jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
- beforeEachFunction.typeName = 'beforeEach';
- this.before_.unshift(beforeEachFunction);
-};
-
-jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
- afterEachFunction.typeName = 'afterEach';
- this.after_.unshift(afterEachFunction);
-};
-
-jasmine.Suite.prototype.results = function() {
- return this.queue.results();
-};
-
-jasmine.Suite.prototype.add = function(suiteOrSpec) {
- this.children_.push(suiteOrSpec);
- if (suiteOrSpec instanceof jasmine.Suite) {
- this.suites_.push(suiteOrSpec);
- this.env.currentRunner().addSuite(suiteOrSpec);
- } else {
- this.specs_.push(suiteOrSpec);
- }
- this.queue.add(suiteOrSpec);
-};
-
-jasmine.Suite.prototype.specs = function() {
- return this.specs_;
-};
-
-jasmine.Suite.prototype.suites = function() {
- return this.suites_;
-};
-
-jasmine.Suite.prototype.children = function() {
- return this.children_;
-};
-
-jasmine.Suite.prototype.execute = function(onComplete) {
- var self = this;
- this.queue.start(function () {
- self.finish(onComplete);
- });
-};
-jasmine.WaitsBlock = function(env, timeout, spec) {
- this.timeout = timeout;
- jasmine.Block.call(this, env, null, spec);
-};
-
-jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
-
-jasmine.WaitsBlock.prototype.execute = function (onComplete) {
- if (jasmine.VERBOSE) {
- this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
- }
- this.env.setTimeout(function () {
- onComplete();
- }, this.timeout);
-};
-/**
- * A block which waits for some condition to become true, with timeout.
- *
- * @constructor
- * @extends jasmine.Block
- * @param {jasmine.Env} env The Jasmine environment.
- * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
- * @param {Function} latchFunction A function which returns true when the desired condition has been met.
- * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
- * @param {jasmine.Spec} spec The Jasmine spec.
- */
-jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
- this.timeout = timeout || env.defaultTimeoutInterval;
- this.latchFunction = latchFunction;
- this.message = message;
- this.totalTimeSpentWaitingForLatch = 0;
- jasmine.Block.call(this, env, null, spec);
-};
-jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
-
-jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
-
-jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
- if (jasmine.VERBOSE) {
- this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
- }
- var latchFunctionResult;
- try {
- latchFunctionResult = this.latchFunction.apply(this.spec);
- } catch (e) {
- this.spec.fail(e);
- onComplete();
- return;
- }
-
- if (latchFunctionResult) {
- onComplete();
- } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
- var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
- this.spec.fail({
- name: 'timeout',
- message: message
- });
-
- this.abort = true;
- onComplete();
- } else {
- this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
- var self = this;
- this.env.setTimeout(function() {
- self.execute(onComplete);
- }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
- }
-};
-// Mock setTimeout, clearTimeout
-// Contributed by Pivotal Computer Systems, www.pivotalsf.com
-
-jasmine.FakeTimer = function() {
- this.reset();
-
- var self = this;
- self.setTimeout = function(funcToCall, millis) {
- self.timeoutsMade++;
- self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
- return self.timeoutsMade;
- };
-
- self.setInterval = function(funcToCall, millis) {
- self.timeoutsMade++;
- self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
- return self.timeoutsMade;
- };
-
- self.clearTimeout = function(timeoutKey) {
- self.scheduledFunctions[timeoutKey] = jasmine.undefined;
- };
-
- self.clearInterval = function(timeoutKey) {
- self.scheduledFunctions[timeoutKey] = jasmine.undefined;
- };
-
-};
-
-jasmine.FakeTimer.prototype.reset = function() {
- this.timeoutsMade = 0;
- this.scheduledFunctions = {};
- this.nowMillis = 0;
-};
-
-jasmine.FakeTimer.prototype.tick = function(millis) {
- var oldMillis = this.nowMillis;
- var newMillis = oldMillis + millis;
- this.runFunctionsWithinRange(oldMillis, newMillis);
- this.nowMillis = newMillis;
-};
-
-jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
- var scheduledFunc;
- var funcsToRun = [];
- for (var timeoutKey in this.scheduledFunctions) {
- scheduledFunc = this.scheduledFunctions[timeoutKey];
- if (scheduledFunc != jasmine.undefined &&
- scheduledFunc.runAtMillis >= oldMillis &&
- scheduledFunc.runAtMillis <= nowMillis) {
- funcsToRun.push(scheduledFunc);
- this.scheduledFunctions[timeoutKey] = jasmine.undefined;
- }
- }
-
- if (funcsToRun.length > 0) {
- funcsToRun.sort(function(a, b) {
- return a.runAtMillis - b.runAtMillis;
- });
- for (var i = 0; i < funcsToRun.length; ++i) {
- try {
- var funcToRun = funcsToRun[i];
- this.nowMillis = funcToRun.runAtMillis;
- funcToRun.funcToCall();
- if (funcToRun.recurring) {
- this.scheduleFunction(funcToRun.timeoutKey,
- funcToRun.funcToCall,
- funcToRun.millis,
- true);
- }
- } catch(e) {
- }
- }
- this.runFunctionsWithinRange(oldMillis, nowMillis);
- }
-};
-
-jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
- this.scheduledFunctions[timeoutKey] = {
- runAtMillis: this.nowMillis + millis,
- funcToCall: funcToCall,
- recurring: recurring,
- timeoutKey: timeoutKey,
- millis: millis
- };
-};
-
-/**
- * @namespace
- */
-jasmine.Clock = {
- defaultFakeTimer: new jasmine.FakeTimer(),
-
- reset: function() {
- jasmine.Clock.assertInstalled();
- jasmine.Clock.defaultFakeTimer.reset();
- },
-
- tick: function(millis) {
- jasmine.Clock.assertInstalled();
- jasmine.Clock.defaultFakeTimer.tick(millis);
- },
-
- runFunctionsWithinRange: function(oldMillis, nowMillis) {
- jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
- },
-
- scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
- jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
- },
-
- useMock: function() {
- if (!jasmine.Clock.isInstalled()) {
- var spec = jasmine.getEnv().currentSpec;
- spec.after(jasmine.Clock.uninstallMock);
-
- jasmine.Clock.installMock();
- }
- },
-
- installMock: function() {
- jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
- },
-
- uninstallMock: function() {
- jasmine.Clock.assertInstalled();
- jasmine.Clock.installed = jasmine.Clock.real;
- },
-
- real: {
- setTimeout: jasmine.getGlobal().setTimeout,
- clearTimeout: jasmine.getGlobal().clearTimeout,
- setInterval: jasmine.getGlobal().setInterval,
- clearInterval: jasmine.getGlobal().clearInterval
- },
-
- assertInstalled: function() {
- if (!jasmine.Clock.isInstalled()) {
- throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
- }
- },
-
- isInstalled: function() {
- return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
- },
-
- installed: null
-};
-jasmine.Clock.installed = jasmine.Clock.real;
-
-//else for IE support
-jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
- if (jasmine.Clock.installed.setTimeout.apply) {
- return jasmine.Clock.installed.setTimeout.apply(this, arguments);
- } else {
- return jasmine.Clock.installed.setTimeout(funcToCall, millis);
- }
-};
-
-jasmine.getGlobal().setInterval = function(funcToCall, millis) {
- if (jasmine.Clock.installed.setInterval.apply) {
- return jasmine.Clock.installed.setInterval.apply(this, arguments);
- } else {
- return jasmine.Clock.installed.setInterval(funcToCall, millis);
- }
-};
-
-jasmine.getGlobal().clearTimeout = function(timeoutKey) {
- if (jasmine.Clock.installed.clearTimeout.apply) {
- return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
- } else {
- return jasmine.Clock.installed.clearTimeout(timeoutKey);
- }
-};
-
-jasmine.getGlobal().clearInterval = function(timeoutKey) {
- if (jasmine.Clock.installed.clearTimeout.apply) {
- return jasmine.Clock.installed.clearInterval.apply(this, arguments);
- } else {
- return jasmine.Clock.installed.clearInterval(timeoutKey);
- }
-};
-
-jasmine.version_= {
- "major": 1,
- "minor": 1,
- "build": 0,
- "revision": 1315677058
-};
diff --git a/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine_favicon.png b/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine_favicon.png
deleted file mode 100644
index bd147955254..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine_favicon.png
+++ /dev/null
Binary files differ
diff --git a/addons/web_graph/static/lib/flotr2/lib/prototype.js b/addons/web_graph/static/lib/flotr2/lib/prototype.js
deleted file mode 100644
index 41bd8e30e4a..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/prototype.js
+++ /dev/null
@@ -1,4320 +0,0 @@
-/* Prototype JavaScript framework, version 1.6.0.3
- * (c) 2005-2008 Sam Stephenson
- *
- * Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://www.prototypejs.org/
- *
- *--------------------------------------------------------------------------*/
-
-var Prototype = {
- Version: '1.6.0.3',
-
- Browser: {
- IE: !!(window.attachEvent &&
- navigator.userAgent.indexOf('Opera') === -1),
- Opera: navigator.userAgent.indexOf('Opera') > -1,
- WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
- Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
- navigator.userAgent.indexOf('KHTML') === -1,
- MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
- },
-
- BrowserFeatures: {
- XPath: !!document.evaluate,
- SelectorsAPI: !!document.querySelector,
- ElementExtensions: !!window.HTMLElement,
- SpecificElementExtensions:
- document.createElement('div')['__proto__'] &&
- document.createElement('div')['__proto__'] !==
- document.createElement('form')['__proto__']
- },
-
- ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
- JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
-
- emptyFunction: function() { },
- K: function(x) { return x }
-};
-
-if (Prototype.Browser.MobileSafari)
- Prototype.BrowserFeatures.SpecificElementExtensions = false;
-
-
-/* Based on Alex Arnell's inheritance implementation. */
-var Class = {
- create: function() {
- var parent = null, properties = $A(arguments);
- if (Object.isFunction(properties[0]))
- parent = properties.shift();
-
- function klass() {
- this.initialize.apply(this, arguments);
- }
-
- Object.extend(klass, Class.Methods);
- klass.superclass = parent;
- klass.subclasses = [];
-
- if (parent) {
- var subclass = function() { };
- subclass.prototype = parent.prototype;
- klass.prototype = new subclass;
- parent.subclasses.push(klass);
- }
-
- for (var i = 0; i < properties.length; i++)
- klass.addMethods(properties[i]);
-
- if (!klass.prototype.initialize)
- klass.prototype.initialize = Prototype.emptyFunction;
-
- klass.prototype.constructor = klass;
-
- return klass;
- }
-};
-
-Class.Methods = {
- addMethods: function(source) {
- var ancestor = this.superclass && this.superclass.prototype;
- var properties = Object.keys(source);
-
- if (!Object.keys({ toString: true }).length)
- properties.push("toString", "valueOf");
-
- for (var i = 0, length = properties.length; i < length; i++) {
- var property = properties[i], value = source[property];
- if (ancestor && Object.isFunction(value) &&
- value.argumentNames().first() == "$super") {
- var method = value;
- value = (function(m) {
- return function() { return ancestor[m].apply(this, arguments) };
- })(property).wrap(method);
-
- value.valueOf = method.valueOf.bind(method);
- value.toString = method.toString.bind(method);
- }
- this.prototype[property] = value;
- }
-
- return this;
- }
-};
-
-var Abstract = { };
-
-Object.extend = function(destination, source) {
- for (var property in source)
- destination[property] = source[property];
- return destination;
-};
-
-Object.extend(Object, {
- inspect: function(object) {
- try {
- if (Object.isUndefined(object)) return 'undefined';
- if (object === null) return 'null';
- return object.inspect ? object.inspect() : String(object);
- } catch (e) {
- if (e instanceof RangeError) return '...';
- throw e;
- }
- },
-
- toJSON: function(object) {
- var type = typeof object;
- switch (type) {
- case 'undefined':
- case 'function':
- case 'unknown': return;
- case 'boolean': return object.toString();
- }
-
- if (object === null) return 'null';
- if (object.toJSON) return object.toJSON();
- if (Object.isElement(object)) return;
-
- var results = [];
- for (var property in object) {
- var value = Object.toJSON(object[property]);
- if (!Object.isUndefined(value))
- results.push(property.toJSON() + ': ' + value);
- }
-
- return '{' + results.join(', ') + '}';
- },
-
- toQueryString: function(object) {
- return $H(object).toQueryString();
- },
-
- toHTML: function(object) {
- return object && object.toHTML ? object.toHTML() : String.interpret(object);
- },
-
- keys: function(object) {
- var keys = [];
- for (var property in object)
- keys.push(property);
- return keys;
- },
-
- values: function(object) {
- var values = [];
- for (var property in object)
- values.push(object[property]);
- return values;
- },
-
- clone: function(object) {
- return Object.extend({ }, object);
- },
-
- isElement: function(object) {
- return !!(object && object.nodeType == 1);
- },
-
- isArray: function(object) {
- return object != null && typeof object == "object" &&
- 'splice' in object && 'join' in object;
- },
-
- isHash: function(object) {
- return object instanceof Hash;
- },
-
- isFunction: function(object) {
- return typeof object == "function";
- },
-
- isString: function(object) {
- return typeof object == "string";
- },
-
- isNumber: function(object) {
- return typeof object == "number";
- },
-
- isUndefined: function(object) {
- return typeof object == "undefined";
- }
-});
-
-Object.extend(Function.prototype, {
- argumentNames: function() {
- var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
- .replace(/\s+/g, '').split(',');
- return names.length == 1 && !names[0] ? [] : names;
- },
-
- bind: function() {
- if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
- var __method = this, args = $A(arguments), object = args.shift();
- return function() {
- return __method.apply(object, args.concat($A(arguments)));
- }
- },
-
- bindAsEventListener: function() {
- var __method = this, args = $A(arguments), object = args.shift();
- return function(event) {
- return __method.apply(object, [event || window.event].concat(args));
- }
- },
-
- curry: function() {
- if (!arguments.length) return this;
- var __method = this, args = $A(arguments);
- return function() {
- return __method.apply(this, args.concat($A(arguments)));
- }
- },
-
- delay: function() {
- var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
- return window.setTimeout(function() {
- return __method.apply(__method, args);
- }, timeout);
- },
-
- defer: function() {
- var args = [0.01].concat($A(arguments));
- return this.delay.apply(this, args);
- },
-
- wrap: function(wrapper) {
- var __method = this;
- return function() {
- return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
- }
- },
-
- methodize: function() {
- if (this._methodized) return this._methodized;
- var __method = this;
- return this._methodized = function() {
- return __method.apply(null, [this].concat($A(arguments)));
- };
- }
-});
-
-Date.prototype.toJSON = function() {
- return '"' + this.getUTCFullYear() + '-' +
- (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
- this.getUTCDate().toPaddedString(2) + 'T' +
- this.getUTCHours().toPaddedString(2) + ':' +
- this.getUTCMinutes().toPaddedString(2) + ':' +
- this.getUTCSeconds().toPaddedString(2) + 'Z"';
-};
-
-var Try = {
- these: function() {
- var returnValue;
-
- for (var i = 0, length = arguments.length; i < length; i++) {
- var lambda = arguments[i];
- try {
- returnValue = lambda();
- break;
- } catch (e) { }
- }
-
- return returnValue;
- }
-};
-
-RegExp.prototype.match = RegExp.prototype.test;
-
-RegExp.escape = function(str) {
- return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
-};
-
-/*--------------------------------------------------------------------------*/
-
-var PeriodicalExecuter = Class.create({
- initialize: function(callback, frequency) {
- this.callback = callback;
- this.frequency = frequency;
- this.currentlyExecuting = false;
-
- this.registerCallback();
- },
-
- registerCallback: function() {
- this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- execute: function() {
- this.callback(this);
- },
-
- stop: function() {
- if (!this.timer) return;
- clearInterval(this.timer);
- this.timer = null;
- },
-
- onTimerEvent: function() {
- if (!this.currentlyExecuting) {
- try {
- this.currentlyExecuting = true;
- this.execute();
- } finally {
- this.currentlyExecuting = false;
- }
- }
- }
-});
-Object.extend(String, {
- interpret: function(value) {
- return value == null ? '' : String(value);
- },
- specialChar: {
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '\\': '\\\\'
- }
-});
-
-Object.extend(String.prototype, {
- gsub: function(pattern, replacement) {
- var result = '', source = this, match;
- replacement = arguments.callee.prepareReplacement(replacement);
-
- while (source.length > 0) {
- 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;
- },
-
- sub: function(pattern, replacement, count) {
- replacement = this.gsub.prepareReplacement(replacement);
- count = Object.isUndefined(count) ? 1 : count;
-
- return this.gsub(pattern, function(match) {
- if (--count < 0) return match[0];
- return replacement(match);
- });
- },
-
- scan: function(pattern, iterator) {
- this.gsub(pattern, iterator);
- return String(this);
- },
-
- truncate: function(length, truncation) {
- length = length || 30;
- truncation = Object.isUndefined(truncation) ? '...' : truncation;
- return this.length > length ?
- this.slice(0, length - truncation.length) + truncation : String(this);
- },
-
- strip: function() {
- return this.replace(/^\s+/, '').replace(/\s+$/, '');
- },
-
- stripTags: function() {
- return this.replace(/<\/?[^>]+>/gi, '');
- },
-
- stripScripts: function() {
- return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
- },
-
- extractScripts: function() {
- 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];
- });
- },
-
- evalScripts: function() {
- return this.extractScripts().map(function(script) { return eval(script) });
- },
-
- escapeHTML: function() {
- var self = arguments.callee;
- self.text.data = this;
- return self.div.innerHTML;
- },
-
- unescapeHTML: function() {
- var div = new Element('div');
- div.innerHTML = this.stripTags();
- return div.childNodes[0] ? (div.childNodes.length > 1 ?
- $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
- div.childNodes[0].nodeValue) : '';
- },
-
- toQueryParams: function(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;
- });
- },
-
- toArray: function() {
- return this.split('');
- },
-
- succ: function() {
- return this.slice(0, this.length - 1) +
- String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
- },
-
- times: function(count) {
- return count < 1 ? '' : new Array(count + 1).join(this);
- },
-
- camelize: function() {
- 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 < len; i++)
- camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
-
- return camelized;
- },
-
- capitalize: function() {
- return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
- },
-
- underscore: function() {
- return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
- },
-
- dasherize: function() {
- return this.gsub(/_/,'-');
- },
-
- inspect: function(useDoubleQuotes) {
- var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
- var character = String.specialChar[match[0]];
- return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
- });
- if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
- return "'" + escapedString.replace(/'/g, '\\\'') + "'";
- },
-
- toJSON: function() {
- return this.inspect(true);
- },
-
- unfilterJSON: function(filter) {
- return this.sub(filter || Prototype.JSONFilter, '#{1}');
- },
-
- isJSON: function() {
- var str = this;
- if (str.blank()) return false;
- str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
- return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
- },
-
- evalJSON: function(sanitize) {
- var json = this.unfilterJSON();
- try {
- if (!sanitize || json.isJSON()) return eval('(' + json + ')');
- } catch (e) { }
- throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
- },
-
- include: function(pattern) {
- return this.indexOf(pattern) > -1;
- },
-
- startsWith: function(pattern) {
- return this.indexOf(pattern) === 0;
- },
-
- endsWith: function(pattern) {
- var d = this.length - pattern.length;
- return d >= 0 && this.lastIndexOf(pattern) === d;
- },
-
- empty: function() {
- return this == '';
- },
-
- blank: function() {
- return /^\s*$/.test(this);
- },
-
- interpolate: function(object, pattern) {
- return new Template(this, pattern).evaluate(object);
- }
-});
-
-if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
- escapeHTML: function() {
- return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
- },
- unescapeHTML: function() {
- return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
- }
-});
-
-String.prototype.gsub.prepareReplacement = function(replacement) {
- if (Object.isFunction(replacement)) return replacement;
- var template = new Template(replacement);
- return function(match) { return template.evaluate(match) };
-};
-
-String.prototype.parseQuery = String.prototype.toQueryParams;
-
-Object.extend(String.prototype.escapeHTML, {
- div: document.createElement('div'),
- text: document.createTextNode('')
-});
-
-String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
-
-var Template = Class.create({
- initialize: function(template, pattern) {
- this.template = template.toString();
- this.pattern = pattern || Template.Pattern;
- },
-
- evaluate: function(object) {
- if (Object.isFunction(object.toTemplateReplacements))
- object = object.toTemplateReplacements();
-
- return this.template.gsub(this.pattern, function(match) {
- if (object == null) return '';
-
- var before = match[1] || '';
- if (before == '\\') return match[2];
-
- var ctx = object, expr = match[3];
- var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
- match = pattern.exec(expr);
- if (match == null) return before;
-
- while (match != null) {
- var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
- ctx = ctx[comp];
- if (null == ctx || '' == match[3]) break;
- expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
- match = pattern.exec(expr);
- }
-
- return before + String.interpret(ctx);
- });
- }
-});
-Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-
-var $break = { };
-
-var Enumerable = {
- each: function(iterator, context) {
- var index = 0;
- try {
- this._each(function(value) {
- iterator.call(context, value, index++);
- });
- } catch (e) {
- if (e != $break) throw e;
- }
- return this;
- },
-
- eachSlice: function(number, iterator, context) {
- var index = -number, slices = [], array = this.toArray();
- if (number < 1) return array;
- while ((index += number) < array.length)
- slices.push(array.slice(index, index+number));
- return slices.collect(iterator, context);
- },
-
- all: function(iterator, context) {
- iterator = iterator || Prototype.K;
- var result = true;
- this.each(function(value, index) {
- result = result && !!iterator.call(context, value, index);
- if (!result) throw $break;
- });
- return result;
- },
-
- any: function(iterator, context) {
- iterator = iterator || Prototype.K;
- var result = false;
- this.each(function(value, index) {
- if (result = !!iterator.call(context, value, index))
- throw $break;
- });
- return result;
- },
-
- collect: function(iterator, context) {
- iterator = iterator || Prototype.K;
- var results = [];
- this.each(function(value, index) {
- results.push(iterator.call(context, value, index));
- });
- return results;
- },
-
- detect: function(iterator, context) {
- var result;
- this.each(function(value, index) {
- if (iterator.call(context, value, index)) {
- result = value;
- throw $break;
- }
- });
- return result;
- },
-
- findAll: function(iterator, context) {
- var results = [];
- this.each(function(value, index) {
- if (iterator.call(context, value, index))
- results.push(value);
- });
- return results;
- },
-
- grep: function(filter, iterator, context) {
- iterator = iterator || Prototype.K;
- var results = [];
-
- if (Object.isString(filter))
- filter = new RegExp(filter);
-
- this.each(function(value, index) {
- if (filter.match(value))
- results.push(iterator.call(context, value, index));
- });
- return results;
- },
-
- include: function(object) {
- if (Object.isFunction(this.indexOf))
- if (this.indexOf(object) != -1) return true;
-
- var found = false;
- this.each(function(value) {
- if (value == object) {
- found = true;
- throw $break;
- }
- });
- return found;
- },
-
- inGroupsOf: function(number, fillWith) {
- fillWith = Object.isUndefined(fillWith) ? null : fillWith;
- return this.eachSlice(number, function(slice) {
- while(slice.length < number) slice.push(fillWith);
- return slice;
- });
- },
-
- inject: function(memo, iterator, context) {
- this.each(function(value, index) {
- memo = iterator.call(context, memo, value, index);
- });
- return memo;
- },
-
- invoke: function(method) {
- var args = $A(arguments).slice(1);
- return this.map(function(value) {
- return value[method].apply(value, args);
- });
- },
-
- max: function(iterator, context) {
- iterator = iterator || Prototype.K;
- var result;
- this.each(function(value, index) {
- value = iterator.call(context, value, index);
- if (result == null || value >= result)
- result = value;
- });
- return result;
- },
-
- min: function(iterator, context) {
- iterator = iterator || Prototype.K;
- var result;
- this.each(function(value, index) {
- value = iterator.call(context, value, index);
- if (result == null || value < result)
- result = value;
- });
- return result;
- },
-
- partition: function(iterator, context) {
- iterator = iterator || Prototype.K;
- var trues = [], falses = [];
- this.each(function(value, index) {
- (iterator.call(context, value, index) ?
- trues : falses).push(value);
- });
- return [trues, falses];
- },
-
- pluck: function(property) {
- var results = [];
- this.each(function(value) {
- results.push(value[property]);
- });
- return results;
- },
-
- reject: function(iterator, context) {
- var results = [];
- this.each(function(value, index) {
- if (!iterator.call(context, value, index))
- results.push(value);
- });
- return results;
- },
-
- sortBy: function(iterator, context) {
- return this.map(function(value, index) {
- return {
- value: value,
- criteria: iterator.call(context, value, index)
- };
- }).sort(function(left, right) {
- var a = left.criteria, b = right.criteria;
- return a < b ? -1 : a > b ? 1 : 0;
- }).pluck('value');
- },
-
- toArray: function() {
- return this.map();
- },
-
- zip: function() {
- var iterator = Prototype.K, args = $A(arguments);
- if (Object.isFunction(args.last()))
- iterator = args.pop();
-
- var collections = [this].concat(args).map($A);
- return this.map(function(value, index) {
- return iterator(collections.pluck(index));
- });
- },
-
- size: function() {
- return this.toArray().length;
- },
-
- inspect: function() {
- return '#<Enumerable:' + this.toArray().inspect() + '>';
- }
-};
-
-Object.extend(Enumerable, {
- map: Enumerable.collect,
- find: Enumerable.detect,
- select: Enumerable.findAll,
- filter: Enumerable.findAll,
- member: Enumerable.include,
- entries: Enumerable.toArray,
- every: Enumerable.all,
- some: Enumerable.any
-});
-function $A(iterable) {
- if (!iterable) return [];
- if (iterable.toArray) return iterable.toArray();
- var length = iterable.length || 0, results = new Array(length);
- while (length--) results[length] = iterable[length];
- return results;
-}
-
-if (Prototype.Browser.WebKit) {
- $A = function(iterable) {
- if (!iterable) return [];
- // In Safari, only use the `toArray` method if it's not a NodeList.
- // A NodeList is a function, has an function `item` property, and a numeric
- // `length` property. Adapted from Google Doctype.
- if (!(typeof iterable === 'function' && typeof iterable.length ===
- 'number' && typeof iterable.item === 'function') && iterable.toArray)
- return iterable.toArray();
- var length = iterable.length || 0, results = new Array(length);
- while (length--) results[length] = iterable[length];
- return results;
- };
-}
-
-Array.from = $A;
-
-Object.extend(Array.prototype, Enumerable);
-
-if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
-
-Object.extend(Array.prototype, {
- _each: function(iterator) {
- for (var i = 0, length = this.length; i < length; i++)
- iterator(this[i]);
- },
-
- clear: function() {
- this.length = 0;
- return this;
- },
-
- first: function() {
- return this[0];
- },
-
- last: function() {
- return this[this.length - 1];
- },
-
- compact: function() {
- return this.select(function(value) {
- return value != null;
- });
- },
-
- flatten: function() {
- return this.inject([], function(array, value) {
- return array.concat(Object.isArray(value) ?
- value.flatten() : [value]);
- });
- },
-
- without: function() {
- var values = $A(arguments);
- return this.select(function(value) {
- return !values.include(value);
- });
- },
-
- reverse: function(inline) {
- return (inline !== false ? this : this.toArray())._reverse();
- },
-
- reduce: function() {
- return this.length > 1 ? this : this[0];
- },
-
- uniq: function(sorted) {
- return this.inject([], function(array, value, index) {
- if (0 == index || (sorted ? array.last() != value : !array.include(value)))
- array.push(value);
- return array;
- });
- },
-
- intersect: function(array) {
- return this.uniq().findAll(function(item) {
- return array.detect(function(value) { return item === value });
- });
- },
-
- clone: function() {
- return [].concat(this);
- },
-
- size: function() {
- return this.length;
- },
-
- inspect: function() {
- return '[' + this.map(Object.inspect).join(', ') + ']';
- },
-
- toJSON: function() {
- var results = [];
- this.each(function(object) {
- var value = Object.toJSON(object);
- if (!Object.isUndefined(value)) results.push(value);
- });
- return '[' + results.join(', ') + ']';
- }
-});
-
-// use native browser JS 1.6 implementation if available
-if (Object.isFunction(Array.prototype.forEach))
- Array.prototype._each = Array.prototype.forEach;
-
-if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
- i || (i = 0);
- var length = this.length;
- if (i < 0) i = length + i;
- for (; i < length; i++)
- if (this[i] === item) return i;
- return -1;
-};
-
-if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
- i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
- var n = this.slice(0, i).reverse().indexOf(item);
- return (n < 0) ? n : i - n - 1;
-};
-
-Array.prototype.toArray = Array.prototype.clone;
-
-function $w(string) {
- if (!Object.isString(string)) return [];
- string = string.strip();
- return string ? string.split(/\s+/) : [];
-}
-
-if (Prototype.Browser.Opera){
- Array.prototype.concat = function() {
- var array = [];
- for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
- for (var i = 0, length = arguments.length; i < length; i++) {
- if (Object.isArray(arguments[i])) {
- for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
- array.push(arguments[i][j]);
- } else {
- array.push(arguments[i]);
- }
- }
- return array;
- };
-}
-Object.extend(Number.prototype, {
- toColorPart: function() {
- return this.toPaddedString(2, 16);
- },
-
- succ: function() {
- return this + 1;
- },
-
- times: function(iterator, context) {
- $R(0, this, true).each(iterator, context);
- return this;
- },
-
- toPaddedString: function(length, radix) {
- var string = this.toString(radix || 10);
- return '0'.times(length - string.length) + string;
- },
-
- toJSON: function() {
- return isFinite(this) ? this.toString() : 'null';
- }
-});
-
-$w('abs round ceil floor').each(function(method){
- Number.prototype[method] = Math[method].methodize();
-});
-function $H(object) {
- return new Hash(object);
-};
-
-var Hash = Class.create(Enumerable, (function() {
-
- function toQueryPair(key, value) {
- if (Object.isUndefined(value)) return key;
- return key + '=' + encodeURIComponent(String.interpret(value));
- }
-
- return {
- initialize: function(object) {
- this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
- },
-
- _each: function(iterator) {
- for (var key in this._object) {
- var value = this._object[key], pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
- }
- },
-
- set: function(key, value) {
- return this._object[key] = value;
- },
-
- get: function(key) {
- // simulating poorly supported hasOwnProperty
- if (this._object[key] !== Object.prototype[key])
- return this._object[key];
- },
-
- unset: function(key) {
- var value = this._object[key];
- delete this._object[key];
- return value;
- },
-
- toObject: function() {
- return Object.clone(this._object);
- },
-
- keys: function() {
- return this.pluck('key');
- },
-
- values: function() {
- return this.pluck('value');
- },
-
- index: function(value) {
- var match = this.detect(function(pair) {
- return pair.value === value;
- });
- return match && match.key;
- },
-
- merge: function(object) {
- return this.clone().update(object);
- },
-
- update: function(object) {
- return new Hash(object).inject(this, function(result, pair) {
- result.set(pair.key, pair.value);
- return result;
- });
- },
-
- toQueryString: function() {
- return this.inject([], function(results, pair) {
- var key = encodeURIComponent(pair.key), values = pair.value;
-
- if (values && typeof values == 'object') {
- if (Object.isArray(values))
- return results.concat(values.map(toQueryPair.curry(key)));
- } else results.push(toQueryPair(key, values));
- return results;
- }).join('&');
- },
-
- inspect: function() {
- return '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
- },
-
- toJSON: function() {
- return Object.toJSON(this.toObject());
- },
-
- clone: function() {
- return new Hash(this);
- }
- }
-})());
-
-Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
-Hash.from = $H;
-var ObjectRange = Class.create(Enumerable, {
- initialize: function(start, end, exclusive) {
- this.start = start;
- this.end = end;
- this.exclusive = exclusive;
- },
-
- _each: function(iterator) {
- var value = this.start;
- while (this.include(value)) {
- iterator(value);
- value = value.succ();
- }
- },
-
- include: function(value) {
- if (value < this.start)
- return false;
- if (this.exclusive)
- return value < this.end;
- return value <= this.end;
- }
-});
-
-var $R = function(start, end, exclusive) {
- return new ObjectRange(start, end, exclusive);
-};
-
-var Ajax = {
- getTransport: function() {
- return Try.these(
- function() {return new XMLHttpRequest()},
- function() {return new ActiveXObject('Msxml2.XMLHTTP')},
- function() {return new ActiveXObject('Microsoft.XMLHTTP')}
- ) || false;
- },
-
- activeRequestCount: 0
-};
-
-Ajax.Responders = {
- responders: [],
-
- _each: function(iterator) {
- this.responders._each(iterator);
- },
-
- register: function(responder) {
- if (!this.include(responder))
- this.responders.push(responder);
- },
-
- unregister: function(responder) {
- this.responders = this.responders.without(responder);
- },
-
- dispatch: function(callback, request, transport, json) {
- this.each(function(responder) {
- if (Object.isFunction(responder[callback])) {
- try {
- responder[callback].apply(responder, [request, transport, json]);
- } catch (e) { }
- }
- });
- }
-};
-
-Object.extend(Ajax.Responders, Enumerable);
-
-Ajax.Responders.register({
- onCreate: function() { Ajax.activeRequestCount++ },
- onComplete: function() { Ajax.activeRequestCount-- }
-});
-
-Ajax.Base = Class.create({
- initialize: function(options) {
- this.options = {
- method: 'post',
- asynchronous: true,
- contentType: 'application/x-www-form-urlencoded',
- encoding: 'UTF-8',
- parameters: '',
- evalJSON: true,
- evalJS: true
- };
- Object.extend(this.options, options || { });
-
- this.options.method = this.options.method.toLowerCase();
-
- if (Object.isString(this.options.parameters))
- this.options.parameters = this.options.parameters.toQueryParams();
- else if (Object.isHash(this.options.parameters))
- this.options.parameters = this.options.parameters.toObject();
- }
-});
-
-Ajax.Request = Class.create(Ajax.Base, {
- _complete: false,
-
- initialize: function($super, url, options) {
- $super(options);
- this.transport = Ajax.getTransport();
- this.request(url);
- },
-
- request: function(url) {
- this.url = url;
- this.method = this.options.method;
- var params = Object.clone(this.options.parameters);
-
- if (!['get', 'post'].include(this.method)) {
- // simulate other verbs over post
- params['_method'] = this.method;
- this.method = 'post';
- }
-
- this.parameters = params;
-
- if (params = Object.toQueryString(params)) {
- // when GET, append parameters to URL
- if (this.method == 'get')
- this.url += (this.url.include('?') ? '&' : '?') + params;
- else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
- params += '&_=';
- }
-
- try {
- var response = new Ajax.Response(this);
- if (this.options.onCreate) this.options.onCreate(response);
- Ajax.Responders.dispatch('onCreate', this, response);
-
- this.transport.open(this.method.toUpperCase(), this.url,
- this.options.asynchronous);
-
- if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
-
- this.transport.onreadystatechange = this.onStateChange.bind(this);
- this.setRequestHeaders();
-
- this.body = this.method == 'post' ? (this.options.postBody || params) : null;
- this.transport.send(this.body);
-
- /* Force Firefox to handle ready state 4 for synchronous requests */
- if (!this.options.asynchronous && this.transport.overrideMimeType)
- this.onStateChange();
-
- }
- catch (e) {
- this.dispatchException(e);
- }
- },
-
- onStateChange: function() {
- var readyState = this.transport.readyState;
- if (readyState > 1 && !((readyState == 4) && this._complete))
- this.respondToReadyState(this.transport.readyState);
- },
-
- setRequestHeaders: function() {
- var headers = {
- 'X-Requested-With': 'XMLHttpRequest',
- 'X-Prototype-Version': Prototype.Version,
- 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
- };
-
- if (this.method == 'post') {
- headers['Content-type'] = this.options.contentType +
- (this.options.encoding ? '; charset=' + this.options.encoding : '');
-
- /* Force "Connection: close" for older Mozilla browsers to work
- * around a bug where XMLHttpRequest sends an incorrect
- * Content-length header. See Mozilla Bugzilla #246651.
- */
- if (this.transport.overrideMimeType &&
- (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
- headers['Connection'] = 'close';
- }
-
- // user-defined headers
- if (typeof this.options.requestHeaders == 'object') {
- var extras = this.options.requestHeaders;
-
- if (Object.isFunction(extras.push))
- for (var i = 0, length = extras.length; i < length; i += 2)
- headers[extras[i]] = extras[i+1];
- else
- $H(extras).each(function(pair) { headers[pair.key] = pair.value });
- }
-
- for (var name in headers)
- this.transport.setRequestHeader(name, headers[name]);
- },
-
- success: function() {
- var status = this.getStatus();
- return !status || (status >= 200 && status < 300);
- },
-
- getStatus: function() {
- try {
- return this.transport.status || 0;
- } catch (e) { return 0 }
- },
-
- respondToReadyState: function(readyState) {
- var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
-
- if (state == 'Complete') {
- try {
- this._complete = true;
- (this.options['on' + response.status]
- || this.options['on' + (this.success() ? 'Success' : 'Failure')]
- || Prototype.emptyFunction)(response, response.headerJSON);
- } catch (e) {
- this.dispatchException(e);
- }
-
- var contentType = response.getHeader('Content-type');
- if (this.options.evalJS == 'force'
- || (this.options.evalJS && this.isSameOrigin() && contentType
- && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
- this.evalResponse();
- }
-
- try {
- (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
- Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
- } catch (e) {
- this.dispatchException(e);
- }
-
- if (state == 'Complete') {
- // avoid memory leak in MSIE: clean up
- this.transport.onreadystatechange = Prototype.emptyFunction;
- }
- },
-
- isSameOrigin: function() {
- var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
- return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
- protocol: location.protocol,
- domain: document.domain,
- port: location.port ? ':' + location.port : ''
- }));
- },
-
- getHeader: function(name) {
- try {
- return this.transport.getResponseHeader(name) || null;
- } catch (e) { return null }
- },
-
- evalResponse: function() {
- try {
- return eval((this.transport.responseText || '').unfilterJSON());
- } catch (e) {
- this.dispatchException(e);
- }
- },
-
- dispatchException: function(exception) {
- (this.options.onException || Prototype.emptyFunction)(this, exception);
- Ajax.Responders.dispatch('onException', this, exception);
- }
-});
-
-Ajax.Request.Events =
- ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-
-Ajax.Response = Class.create({
- initialize: function(request){
- this.request = request;
- var transport = this.transport = request.transport,
- readyState = this.readyState = transport.readyState;
-
- if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
- this.status = this.getStatus();
- this.statusText = this.getStatusText();
- this.responseText = String.interpret(transport.responseText);
- this.headerJSON = this._getHeaderJSON();
- }
-
- if(readyState == 4) {
- var xml = transport.responseXML;
- this.responseXML = Object.isUndefined(xml) ? null : xml;
- this.responseJSON = this._getResponseJSON();
- }
- },
-
- status: 0,
- statusText: '',
-
- getStatus: Ajax.Request.prototype.getStatus,
-
- getStatusText: function() {
- try {
- return this.transport.statusText || '';
- } catch (e) { return '' }
- },
-
- getHeader: Ajax.Request.prototype.getHeader,
-
- getAllHeaders: function() {
- try {
- return this.getAllResponseHeaders();
- } catch (e) { return null }
- },
-
- getResponseHeader: function(name) {
- return this.transport.getResponseHeader(name);
- },
-
- getAllResponseHeaders: function() {
- return this.transport.getAllResponseHeaders();
- },
-
- _getHeaderJSON: function() {
- var json = this.getHeader('X-JSON');
- if (!json) return null;
- json = decodeURIComponent(escape(json));
- try {
- return json.evalJSON(this.request.options.sanitizeJSON ||
- !this.request.isSameOrigin());
- } catch (e) {
- this.request.dispatchException(e);
- }
- },
-
- _getResponseJSON: function() {
- var options = this.request.options;
- if (!options.evalJSON || (options.evalJSON != 'force' &&
- !(this.getHeader('Content-type') || '').include('application/json')) ||
- this.responseText.blank())
- return null;
- try {
- return this.responseText.evalJSON(options.sanitizeJSON ||
- !this.request.isSameOrigin());
- } catch (e) {
- this.request.dispatchException(e);
- }
- }
-});
-
-Ajax.Updater = Class.create(Ajax.Request, {
- initialize: function($super, container, url, options) {
- this.container = {
- success: (container.success || container),
- failure: (container.failure || (container.success ? null : container))
- };
-
- options = Object.clone(options);
- var onComplete = options.onComplete;
- options.onComplete = (function(response, json) {
- this.updateContent(response.responseText);
- if (Object.isFunction(onComplete)) onComplete(response, json);
- }).bind(this);
-
- $super(url, options);
- },
-
- updateContent: function(responseText) {
- var receiver = this.container[this.success() ? 'success' : 'failure'],
- options = this.options;
-
- if (!options.evalScripts) responseText = responseText.stripScripts();
-
- if (receiver = $(receiver)) {
- if (options.insertion) {
- if (Object.isString(options.insertion)) {
- var insertion = { }; insertion[options.insertion] = responseText;
- receiver.insert(insertion);
- }
- else options.insertion(receiver, responseText);
- }
- else receiver.update(responseText);
- }
- }
-});
-
-Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
- initialize: function($super, container, url, options) {
- $super(options);
- this.onComplete = this.options.onComplete;
-
- this.frequency = (this.options.frequency || 2);
- this.decay = (this.options.decay || 1);
-
- this.updater = { };
- this.container = container;
- this.url = url;
-
- 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(response) {
- if (this.options.decay) {
- this.decay = (response.responseText == this.lastText ?
- this.decay * this.options.decay : 1);
-
- this.lastText = response.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 $(element) {
- if (arguments.length > 1) {
- for (var i = 0, elements = [], length = arguments.length; i < length; i++)
- elements.push($(arguments[i]));
- return elements;
- }
- if (Object.isString(element))
- element = document.getElementById(element);
- return Element.extend(element);
-}
-
-if (Prototype.BrowserFeatures.XPath) {
- document._getElementsByXPath = function(expression, parentElement) {
- var results = [];
- var query = document.evaluate(expression, $(parentElement) || document,
- null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
- for (var i = 0, length = query.snapshotLength; i < length; i++)
- results.push(Element.extend(query.snapshotItem(i)));
- return results;
- };
-}
-
-/*--------------------------------------------------------------------------*/
-
-if (!window.Node) var Node = { };
-
-if (!Node.ELEMENT_NODE) {
- // DOM level 2 ECMAScript Language Binding
- Object.extend(Node, {
- ELEMENT_NODE: 1,
- ATTRIBUTE_NODE: 2,
- TEXT_NODE: 3,
- CDATA_SECTION_NODE: 4,
- ENTITY_REFERENCE_NODE: 5,
- ENTITY_NODE: 6,
- PROCESSING_INSTRUCTION_NODE: 7,
- COMMENT_NODE: 8,
- DOCUMENT_NODE: 9,
- DOCUMENT_TYPE_NODE: 10,
- DOCUMENT_FRAGMENT_NODE: 11,
- NOTATION_NODE: 12
- });
-}
-
-(function() {
- var element = this.Element;
- this.Element = function(tagName, attributes) {
- attributes = attributes || { };
- tagName = tagName.toLowerCase();
- var cache = Element.cache;
- if (Prototype.Browser.IE && attributes.name) {
- tagName = '<' + tagName + ' name="' + attributes.name + '">';
- delete attributes.name;
- return Element.writeAttribute(document.createElement(tagName), attributes);
- }
- if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
- return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
- };
- Object.extend(this.Element, element || { });
- if (element) this.Element.prototype = element.prototype;
-}).call(window);
-
-Element.cache = { };
-
-Element.Methods = {
- visible: function(element) {
- return $(element).style.display != 'none';
- },
-
- toggle: function(element) {
- element = $(element);
- Element[Element.visible(element) ? 'hide' : 'show'](element);
- return element;
- },
-
- hide: function(element) {
- element = $(element);
- element.style.display = 'none';
- return element;
- },
-
- show: function(element) {
- element = $(element);
- element.style.display = '';
- return element;
- },
-
- remove: function(element) {
- element = $(element);
- element.parentNode.removeChild(element);
- return element;
- },
-
- update: function(element, content) {
- element = $(element);
- if (content && content.toElement) content = content.toElement();
- if (Object.isElement(content)) return element.update().insert(content);
- content = Object.toHTML(content);
- element.innerHTML = content.stripScripts();
- content.evalScripts.bind(content).defer();
- return element;
- },
-
- replace: function(element, content) {
- element = $(element);
- if (content && content.toElement) content = content.toElement();
- else if (!Object.isElement(content)) {
- content = Object.toHTML(content);
- var range = element.ownerDocument.createRange();
- range.selectNode(element);
- content.evalScripts.bind(content).defer();
- content = range.createContextualFragment(content.stripScripts());
- }
- element.parentNode.replaceChild(content, element);
- return element;
- },
-
- insert: function(element, insertions) {
- element = $(element);
-
- if (Object.isString(insertions) || Object.isNumber(insertions) ||
- Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
- insertions = {bottom:insertions};
-
- var content, insert, tagName, childNodes;
-
- for (var position in insertions) {
- content = insertions[position];
- position = position.toLowerCase();
- insert = Element._insertionTranslations[position];
-
- if (content && content.toElement) content = content.toElement();
- if (Object.isElement(content)) {
- insert(element, content);
- continue;
- }
-
- content = Object.toHTML(content);
-
- tagName = ((position == 'before' || position == 'after')
- ? element.parentNode : element).tagName.toUpperCase();
-
- childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
-
- if (position == 'top' || position == 'after') childNodes.reverse();
- childNodes.each(insert.curry(element));
-
- content.evalScripts.bind(content).defer();
- }
-
- return element;
- },
-
- wrap: function(element, wrapper, attributes) {
- element = $(element);
- if (Object.isElement(wrapper))
- $(wrapper).writeAttribute(attributes || { });
- else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
- else wrapper = new Element('div', wrapper);
- if (element.parentNode)
- element.parentNode.replaceChild(wrapper, element);
- wrapper.appendChild(element);
- return wrapper;
- },
-
- inspect: function(element) {
- element = $(element);
- var result = '<' + element.tagName.toLowerCase();
- $H({'id': 'id', 'className': 'class'}).each(function(pair) {
- var property = pair.first(), attribute = pair.last();
- var value = (element[property] || '').toString();
- if (value) result += ' ' + attribute + '=' + value.inspect(true);
- });
- return result + '>';
- },
-
- recursivelyCollect: function(element, property) {
- element = $(element);
- var elements = [];
- while (element = element[property])
- if (element.nodeType == 1)
- elements.push(Element.extend(element));
- return elements;
- },
-
- ancestors: function(element) {
- return $(element).recursivelyCollect('parentNode');
- },
-
- descendants: function(element) {
- return $(element).select("*");
- },
-
- firstDescendant: function(element) {
- element = $(element).firstChild;
- while (element && element.nodeType != 1) element = element.nextSibling;
- return $(element);
- },
-
- immediateDescendants: function(element) {
- if (!(element = $(element).firstChild)) return [];
- while (element && element.nodeType != 1) element = element.nextSibling;
- if (element) return [element].concat($(element).nextSiblings());
- return [];
- },
-
- previousSiblings: function(element) {
- return $(element).recursivelyCollect('previousSibling');
- },
-
- nextSiblings: function(element) {
- return $(element).recursivelyCollect('nextSibling');
- },
-
- siblings: function(element) {
- element = $(element);
- return element.previousSiblings().reverse().concat(element.nextSiblings());
- },
-
- match: function(element, selector) {
- if (Object.isString(selector))
- selector = new Selector(selector);
- return selector.match($(element));
- },
-
- up: function(element, expression, index) {
- element = $(element);
- if (arguments.length == 1) return $(element.parentNode);
- var ancestors = element.ancestors();
- return Object.isNumber(expression) ? ancestors[expression] :
- Selector.findElement(ancestors, expression, index);
- },
-
- down: function(element, expression, index) {
- element = $(element);
- if (arguments.length == 1) return element.firstDescendant();
- return Object.isNumber(expression) ? element.descendants()[expression] :
- Element.select(element, expression)[index || 0];
- },
-
- previous: function(element, expression, index) {
- element = $(element);
- if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
- var previousSiblings = element.previousSiblings();
- return Object.isNumber(expression) ? previousSiblings[expression] :
- Selector.findElement(previousSiblings, expression, index);
- },
-
- next: function(element, expression, index) {
- element = $(element);
- if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
- var nextSiblings = element.nextSiblings();
- return Object.isNumber(expression) ? nextSiblings[expression] :
- Selector.findElement(nextSiblings, expression, index);
- },
-
- select: function() {
- var args = $A(arguments), element = $(args.shift());
- return Selector.findChildElements(element, args);
- },
-
- adjacent: function() {
- var args = $A(arguments), element = $(args.shift());
- return Selector.findChildElements(element.parentNode, args).without(element);
- },
-
- identify: function(element) {
- element = $(element);
- var id = element.readAttribute('id'), self = arguments.callee;
- if (id) return id;
- do { id = 'anonymous_element_' + self.counter++ } while ($(id));
- element.writeAttribute('id', id);
- return id;
- },
-
- readAttribute: function(element, name) {
- element = $(element);
- if (Prototype.Browser.IE) {
- var t = Element._attributeTranslations.read;
- if (t.values[name]) return t.values[name](element, name);
- if (t.names[name]) name = t.names[name];
- if (name.include(':')) {
- return (!element.attributes || !element.attributes[name]) ? null :
- element.attributes[name].value;
- }
- }
- return element.getAttribute(name);
- },
-
- writeAttribute: function(element, name, value) {
- element = $(element);
- var attributes = { }, t = Element._attributeTranslations.write;
-
- if (typeof name == 'object') attributes = name;
- else attributes[name] = Object.isUndefined(value) ? true : value;
-
- for (var attr in attributes) {
- name = t.names[attr] || attr;
- value = attributes[attr];
- if (t.values[attr]) name = t.values[attr](element, value);
- if (value === false || value === null)
- element.removeAttribute(name);
- else if (value === true)
- element.setAttribute(name, name);
- else element.setAttribute(name, value);
- }
- return element;
- },
-
- getHeight: function(element) {
- return $(element).getDimensions().height;
- },
-
- getWidth: function(element) {
- return $(element).getDimensions().width;
- },
-
- classNames: function(element) {
- return new Element.ClassNames(element);
- },
-
- hasClassName: function(element, className) {
- if (!(element = $(element))) return;
- var elementClassName = element.className;
- return (elementClassName.length > 0 && (elementClassName == className ||
- new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
- },
-
- addClassName: function(element, className) {
- if (!(element = $(element))) return;
- if (!element.hasClassName(className))
- element.className += (element.className ? ' ' : '') + className;
- return element;
- },
-
- removeClassName: function(element, className) {
- if (!(element = $(element))) return;
- element.className = element.className.replace(
- new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
- return element;
- },
-
- toggleClassName: function(element, className) {
- if (!(element = $(element))) return;
- return element[element.hasClassName(className) ?
- 'removeClassName' : 'addClassName'](className);
- },
-
- // removes whitespace-only text node children
- cleanWhitespace: function(element) {
- element = $(element);
- var node = element.firstChild;
- while (node) {
- var nextNode = node.nextSibling;
- if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
- element.removeChild(node);
- node = nextNode;
- }
- return element;
- },
-
- empty: function(element) {
- return $(element).innerHTML.blank();
- },
-
- descendantOf: function(element, ancestor) {
- element = $(element), ancestor = $(ancestor);
-
- if (element.compareDocumentPosition)
- return (element.compareDocumentPosition(ancestor) & 8) === 8;
-
- if (ancestor.contains)
- return ancestor.contains(element) && ancestor !== element;
-
- while (element = element.parentNode)
- if (element == ancestor) return true;
-
- return false;
- },
-
- scrollTo: function(element) {
- element = $(element);
- var pos = element.cumulativeOffset();
- window.scrollTo(pos[0], pos[1]);
- return element;
- },
-
- getStyle: function(element, style) {
- element = $(element);
- style = style == 'float' ? 'cssFloat' : style.camelize();
- var value = element.style[style];
- if (!value || value == 'auto') {
- var css = document.defaultView.getComputedStyle(element, null);
- value = css ? css[style] : null;
- }
- if (style == 'opacity') return value ? parseFloat(value) : 1.0;
- return value == 'auto' ? null : value;
- },
-
- getOpacity: function(element) {
- return $(element).getStyle('opacity');
- },
-
- setStyle: function(element, styles) {
- element = $(element);
- var elementStyle = element.style, match;
- if (Object.isString(styles)) {
- element.style.cssText += ';' + styles;
- return styles.include('opacity') ?
- element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
- }
- for (var property in styles)
- if (property == 'opacity') element.setOpacity(styles[property]);
- else
- elementStyle[(property == 'float' || property == 'cssFloat') ?
- (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
- property] = styles[property];
-
- return element;
- },
-
- setOpacity: function(element, value) {
- element = $(element);
- element.style.opacity = (value == 1 || value === '') ? '' :
- (value < 0.00001) ? 0 : value;
- return element;
- },
-
- getDimensions: function(element) {
- element = $(element);
- var display = element.getStyle('display');
- if (display != 'none' && display != null) // Safari bug
- return {width: element.offsetWidth, height: element.offsetHeight};
-
- // All *Width and *Height properties give 0 on elements with display none,
- // so enable the element temporarily
- var els = element.style;
- var originalVisibility = els.visibility;
- var originalPosition = els.position;
- var originalDisplay = els.display;
- els.visibility = 'hidden';
- els.position = 'absolute';
- els.display = 'block';
- var originalWidth = element.clientWidth;
- var originalHeight = element.clientHeight;
- els.display = originalDisplay;
- els.position = originalPosition;
- els.visibility = originalVisibility;
- return {width: originalWidth, height: originalHeight};
- },
-
- makePositioned: function(element) {
- element = $(element);
- var pos = Element.getStyle(element, 'position');
- if (pos == 'static' || !pos) {
- element._madePositioned = true;
- element.style.position = 'relative';
- // Opera returns the offset relative to the positioning context, when an
- // element is position relative but top and left have not been defined
- if (Prototype.Browser.Opera) {
- element.style.top = 0;
- element.style.left = 0;
- }
- }
- return element;
- },
-
- undoPositioned: function(element) {
- element = $(element);
- if (element._madePositioned) {
- element._madePositioned = undefined;
- element.style.position =
- element.style.top =
- element.style.left =
- element.style.bottom =
- element.style.right = '';
- }
- return element;
- },
-
- makeClipping: function(element) {
- element = $(element);
- if (element._overflow) return element;
- element._overflow = Element.getStyle(element, 'overflow') || 'auto';
- if (element._overflow !== 'hidden')
- element.style.overflow = 'hidden';
- return element;
- },
-
- undoClipping: function(element) {
- element = $(element);
- if (!element._overflow) return element;
- element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
- element._overflow = null;
- return element;
- },
-
- cumulativeOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
- return Element._returnOffset(valueL, valueT);
- },
-
- positionedOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- if (element) {
- if (element.tagName.toUpperCase() == 'BODY') break;
- var p = Element.getStyle(element, 'position');
- if (p !== 'static') break;
- }
- } while (element);
- return Element._returnOffset(valueL, valueT);
- },
-
- absolutize: function(element) {
- element = $(element);
- if (element.getStyle('position') == 'absolute') return element;
- // Position.prepare(); // To be done manually by Scripty when it needs it.
-
- var offsets = element.positionedOffset();
- var top = offsets[1];
- var left = offsets[0];
- var width = element.clientWidth;
- var height = element.clientHeight;
-
- element._originalLeft = left - parseFloat(element.style.left || 0);
- element._originalTop = top - parseFloat(element.style.top || 0);
- element._originalWidth = element.style.width;
- element._originalHeight = element.style.height;
-
- element.style.position = 'absolute';
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.width = width + 'px';
- element.style.height = height + 'px';
- return element;
- },
-
- relativize: function(element) {
- element = $(element);
- if (element.getStyle('position') == 'relative') return element;
- // Position.prepare(); // To be done manually by Scripty when it needs it.
-
- element.style.position = 'relative';
- var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
- var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
-
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.height = element._originalHeight;
- element.style.width = element._originalWidth;
- return element;
- },
-
- cumulativeScrollOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.scrollTop || 0;
- valueL += element.scrollLeft || 0;
- element = element.parentNode;
- } while (element);
- return Element._returnOffset(valueL, valueT);
- },
-
- getOffsetParent: function(element) {
- if (element.offsetParent) return $(element.offsetParent);
- if (element == document.body) return $(element);
-
- while ((element = element.parentNode) && element != document.body)
- if (Element.getStyle(element, 'position') != 'static')
- return $(element);
-
- return $(document.body);
- },
-
- viewportOffset: function(forElement) {
- var valueT = 0, valueL = 0;
-
- var element = forElement;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
-
- // Safari fix
- if (element.offsetParent == document.body &&
- Element.getStyle(element, 'position') == 'absolute') break;
-
- } while (element = element.offsetParent);
-
- element = forElement;
- do {
- if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- }
- } while (element = element.parentNode);
-
- return Element._returnOffset(valueL, valueT);
- },
-
- clonePosition: function(element, source) {
- var options = Object.extend({
- setLeft: true,
- setTop: true,
- setWidth: true,
- setHeight: true,
- offsetTop: 0,
- offsetLeft: 0
- }, arguments[2] || { });
-
- // find page position of source
- source = $(source);
- var p = source.viewportOffset();
-
- // find coordinate system to use
- element = $(element);
- var delta = [0, 0];
- var parent = null;
- // delta [0,0] will do fine with position: fixed elements,
- // position:absolute needs offsetParent deltas
- if (Element.getStyle(element, 'position') == 'absolute') {
- parent = element.getOffsetParent();
- delta = parent.viewportOffset();
- }
-
- // correct by body offsets (fixes Safari)
- if (parent == document.body) {
- delta[0] -= document.body.offsetLeft;
- delta[1] -= document.body.offsetTop;
- }
-
- // set position
- if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
- if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
- if (options.setWidth) element.style.width = source.offsetWidth + 'px';
- if (options.setHeight) element.style.height = source.offsetHeight + 'px';
- return element;
- }
-};
-
-Element.Methods.identify.counter = 1;
-
-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(proceed, element, style) {
- switch (style) {
- case 'left': case 'top': case 'right': case 'bottom':
- if (proceed(element, 'position') === 'static') return null;
- case 'height': case 'width':
- // returns '0px' for hidden elements; we want it to return null
- if (!Element.visible(element)) return null;
-
- // returns the border-box dimensions rather than the content-box
- // dimensions, so we subtract padding and borders from the value
- var dim = parseInt(proceed(element, style), 10);
-
- if (dim !== element['offset' + style.capitalize()])
- return dim + 'px';
-
- var properties;
- if (style === 'height') {
- properties = ['border-top-width', 'padding-top',
- 'padding-bottom', 'border-bottom-width'];
- }
- else {
- properties = ['border-left-width', 'padding-left',
- 'padding-right', 'border-right-width'];
- }
- return properties.inject(dim, function(memo, property) {
- var val = proceed(element, property);
- return val === null ? memo : memo - parseInt(val, 10);
- }) + 'px';
- default: return proceed(element, style);
- }
- }
- );
-
- Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
- function(proceed, element, attribute) {
- if (attribute === 'title') return element.title;
- return proceed(element, attribute);
- }
- );
-}
-
-else if (Prototype.Browser.IE) {
- // IE doesn't report offsets correctly for static elements, so we change them
- // to "relative" to get the values, then change them back.
- Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
- function(proceed, element) {
- element = $(element);
- // IE throws an error if element is not in document
- try { element.offsetParent }
- catch(e) { return $(document.body) }
- var position = element.getStyle('position');
- if (position !== 'static') return proceed(element);
- element.setStyle({ position: 'relative' });
- var value = proceed(element);
- element.setStyle({ position: position });
- return value;
- }
- );
-
- $w('positionedOffset viewportOffset').each(function(method) {
- Element.Methods[method] = Element.Methods[method].wrap(
- function(proceed, element) {
- element = $(element);
- try { element.offsetParent }
- catch(e) { return Element._returnOffset(0,0) }
- var position = element.getStyle('position');
- if (position !== 'static') return proceed(element);
- // Trigger hasLayout on the offset parent so that IE6 reports
- // accurate offsetTop and offsetLeft values for position: fixed.
- var offsetParent = element.getOffsetParent();
- if (offsetParent && offsetParent.getStyle('position') === 'fixed')
- offsetParent.setStyle({ zoom: 1 });
- element.setStyle({ position: 'relative' });
- var value = proceed(element);
- element.setStyle({ position: position });
- return value;
- }
- );
- });
-
- Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
- function(proceed, element) {
- try { element.offsetParent }
- catch(e) { return Element._returnOffset(0,0) }
- return proceed(element);
- }
- );
-
- Element.Methods.getStyle = function(element, style) {
- element = $(element);
- style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
- var value = element.style[style];
- if (!value && element.currentStyle) value = element.currentStyle[style];
-
- if (style == 'opacity') {
- if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
- if (value[1]) return parseFloat(value[1]) / 100;
- return 1.0;
- }
-
- if (value == 'auto') {
- if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
- return element['offset' + style.capitalize()] + 'px';
- return null;
- }
- return value;
- };
-
- Element.Methods.setOpacity = function(element, value) {
- function stripAlpha(filter){
- return filter.replace(/alpha\([^\)]*\)/gi,'');
- }
- element = $(element);
- var currentStyle = element.currentStyle;
- if ((currentStyle && !currentStyle.hasLayout) ||
- (!currentStyle && element.style.zoom == 'normal'))
- element.style.zoom = 1;
-
- var filter = element.getStyle('filter'), style = element.style;
- if (value == 1 || value === '') {
- (filter = stripAlpha(filter)) ?
- style.filter = filter : style.removeAttribute('filter');
- return element;
- } else if (value < 0.00001) value = 0;
- style.filter = stripAlpha(filter) +
- 'alpha(opacity=' + (value * 100) + ')';
- return element;
- };
-
- Element._attributeTranslations = {
- read: {
- names: {
- 'class': 'className',
- 'for': 'htmlFor'
- },
- values: {
- _getAttr: function(element, attribute) {
- return element.getAttribute(attribute, 2);
- },
- _getAttrNode: function(element, attribute) {
- var node = element.getAttributeNode(attribute);
- return node ? node.value : "";
- },
- _getEv: function(element, attribute) {
- attribute = element.getAttribute(attribute);
- return attribute ? attribute.toString().slice(23, -2) : null;
- },
- _flag: function(element, attribute) {
- return $(element).hasAttribute(attribute) ? attribute : null;
- },
- style: function(element) {
- return element.style.cssText.toLowerCase();
- },
- title: function(element) {
- return element.title;
- }
- }
- }
- };
-
- Element._attributeTranslations.write = {
- names: Object.extend({
- cellpadding: 'cellPadding',
- cellspacing: 'cellSpacing'
- }, Element._attributeTranslations.read.names),
- values: {
- checked: function(element, value) {
- element.checked = !!value;
- },
-
- style: function(element, value) {
- element.style.cssText = value ? value : '';
- }
- }
- };
-
- Element._attributeTranslations.has = {};
-
- $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
- 'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
- Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
- Element._attributeTranslations.has[attr.toLowerCase()] = attr;
- });
-
- (function(v) {
- Object.extend(v, {
- href: v._getAttr,
- src: v._getAttr,
- type: v._getAttr,
- action: v._getAttrNode,
- disabled: v._flag,
- checked: v._flag,
- readonly: v._flag,
- multiple: v._flag,
- onload: v._getEv,
- onunload: v._getEv,
- onclick: v._getEv,
- ondblclick: v._getEv,
- onmousedown: v._getEv,
- onmouseup: v._getEv,
- onmouseover: v._getEv,
- onmousemove: v._getEv,
- onmouseout: v._getEv,
- onfocus: v._getEv,
- onblur: v._getEv,
- onkeypress: v._getEv,
- onkeydown: v._getEv,
- onkeyup: v._getEv,
- onsubmit: v._getEv,
- onreset: v._getEv,
- onselect: v._getEv,
- onchange: v._getEv
- });
- })(Element._attributeTranslations.read.values);
-}
-
-else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
- Element.Methods.setOpacity = function(element, value) {
- element = $(element);
- element.style.opacity = (value == 1) ? 0.999999 :
- (value === '') ? '' : (value < 0.00001) ? 0 : value;
- return element;
- };
-}
-
-else if (Prototype.Browser.WebKit) {
- Element.Methods.setOpacity = function(element, value) {
- element = $(element);
- element.style.opacity = (value == 1 || value === '') ? '' :
- (value < 0.00001) ? 0 : value;
-
- if (value == 1)
- if(element.tagName.toUpperCase() == 'IMG' && element.width) {
- element.width++; element.width--;
- } else try {
- var n = document.createTextNode(' ');
- element.appendChild(n);
- element.removeChild(n);
- } catch (e) { }
-
- return element;
- };
-
- // Safari returns margins on body which is incorrect if the child is absolutely
- // positioned. For performance reasons, redefine Element#cumulativeOffset for
- // KHTML/WebKit only.
- Element.Methods.cumulativeOffset = function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- if (element.offsetParent == document.body)
- if (Element.getStyle(element, 'position') == 'absolute') break;
-
- element = element.offsetParent;
- } while (element);
-
- return Element._returnOffset(valueL, valueT);
- };
-}
-
-if (Prototype.Browser.IE || Prototype.Browser.Opera) {
- // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
- Element.Methods.update = function(element, content) {
- element = $(element);
-
- if (content && content.toElement) content = content.toElement();
- if (Object.isElement(content)) return element.update().insert(content);
-
- content = Object.toHTML(content);
- var tagName = element.tagName.toUpperCase();
-
- if (tagName in Element._insertionTranslations.tags) {
- $A(element.childNodes).each(function(node) { element.removeChild(node) });
- Element._getContentFromAnonymousElement(tagName, content.stripScripts())
- .each(function(node) { element.appendChild(node) });
- }
- else element.innerHTML = content.stripScripts();
-
- content.evalScripts.bind(content).defer();
- return element;
- };
-}
-
-if ('outerHTML' in document.createElement('div')) {
- Element.Methods.replace = function(element, content) {
- element = $(element);
-
- if (content && content.toElement) content = content.toElement();
- if (Object.isElement(content)) {
- element.parentNode.replaceChild(content, element);
- return element;
- }
-
- content = Object.toHTML(content);
- var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
-
- if (Element._insertionTranslations.tags[tagName]) {
- var nextSibling = element.next();
- var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
- parent.removeChild(element);
- if (nextSibling)
- fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
- else
- fragments.each(function(node) { parent.appendChild(node) });
- }
- else element.outerHTML = content.stripScripts();
-
- content.evalScripts.bind(content).defer();
- return element;
- };
-}
-
-Element._returnOffset = function(l, t) {
- var result = [l, t];
- result.left = l;
- result.top = t;
- return result;
-};
-
-Element._getContentFromAnonymousElement = function(tagName, html) {
- var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
- if (t) {
- div.innerHTML = t[0] + html + t[1];
- t[2].times(function() { div = div.firstChild });
- } else div.innerHTML = html;
- return $A(div.childNodes);
-};
-
-Element._insertionTranslations = {
- before: function(element, node) {
- element.parentNode.insertBefore(node, element);
- },
- top: function(element, node) {
- element.insertBefore(node, element.firstChild);
- },
- bottom: function(element, node) {
- element.appendChild(node);
- },
- after: function(element, node) {
- element.parentNode.insertBefore(node, element.nextSibling);
- },
- tags: {
- TABLE: ['<table>', '</table>', 1],
- TBODY: ['<table><tbody>', '</tbody></table>', 2],
- TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
- TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
- SELECT: ['<select>', '</select>', 1]
- }
-};
-
-(function() {
- Object.extend(this.tags, {
- THEAD: this.tags.TBODY,
- TFOOT: this.tags.TBODY,
- TH: this.tags.TD
- });
-}).call(Element._insertionTranslations);
-
-Element.Methods.Simulated = {
- hasAttribute: function(element, attribute) {
- attribute = Element._attributeTranslations.has[attribute] || attribute;
- var node = $(element).getAttributeNode(attribute);
- return !!(node && node.specified);
- }
-};
-
-Element.Methods.ByTag = { };
-
-Object.extend(Element, Element.Methods);
-
-if (!Prototype.BrowserFeatures.ElementExtensions &&
- document.createElement('div')['__proto__']) {
- window.HTMLElement = { };
- window.HTMLElement.prototype = document.createElement('div')['__proto__'];
- Prototype.BrowserFeatures.ElementExtensions = true;
-}
-
-Element.extend = (function() {
- if (Prototype.BrowserFeatures.SpecificElementExtensions)
- return Prototype.K;
-
- var Methods = { }, ByTag = Element.Methods.ByTag;
-
- var extend = Object.extend(function(element) {
- if (!element || element._extendedByPrototype ||
- element.nodeType != 1 || element == window) return element;
-
- var methods = Object.clone(Methods),
- tagName = element.tagName.toUpperCase(), property, value;
-
- // extend methods for specific tags
- if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
-
- for (property in methods) {
- value = methods[property];
- if (Object.isFunction(value) && !(property in element))
- element[property] = value.methodize();
- }
-
- element._extendedByPrototype = Prototype.emptyFunction;
- return element;
-
- }, {
- refresh: function() {
- // extend methods for all tags (Safari doesn't need this)
- if (!Prototype.BrowserFeatures.ElementExtensions) {
- Object.extend(Methods, Element.Methods);
- Object.extend(Methods, Element.Methods.Simulated);
- }
- }
- });
-
- extend.refresh();
- return extend;
-})();
-
-Element.hasAttribute = function(element, attribute) {
- if (element.hasAttribute) return element.hasAttribute(attribute);
- return Element.Methods.Simulated.hasAttribute(element, attribute);
-};
-
-Element.addMethods = function(methods) {
- var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
-
- if (!methods) {
- 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 tagName = methods;
- methods = arguments[1];
- }
-
- if (!tagName) Object.extend(Element.Methods, methods || { });
- else {
- if (Object.isArray(tagName)) tagName.each(extend);
- else extend(tagName);
- }
-
- function extend(tagName) {
- tagName = tagName.toUpperCase();
- if (!Element.Methods.ByTag[tagName])
- Element.Methods.ByTag[tagName] = { };
- Object.extend(Element.Methods.ByTag[tagName], methods);
- }
-
- function copy(methods, destination, onlyIfAbsent) {
- onlyIfAbsent = onlyIfAbsent || false;
- for (var property in methods) {
- var value = methods[property];
- if (!Object.isFunction(value)) continue;
- if (!onlyIfAbsent || !(property in destination))
- destination[property] = value.methodize();
- }
- }
-
- function findDOMClass(tagName) {
- var klass;
- var trans = {
- "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 (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
- if (window[klass]) return window[klass];
- klass = 'HTML' + tagName + 'Element';
- if (window[klass]) return window[klass];
- klass = 'HTML' + tagName.capitalize() + 'Element';
- if (window[klass]) return window[klass];
-
- window[klass] = { };
- window[klass].prototype = document.createElement(tagName)['__proto__'];
- return window[klass];
- }
-
- if (F.ElementExtensions) {
- copy(Element.Methods, HTMLElement.prototype);
- copy(Element.Methods.Simulated, HTMLElement.prototype, true);
- }
-
- if (F.SpecificElementExtensions) {
- for (var tag in Element.Methods.ByTag) {
- var klass = findDOMClass(tag);
- if (Object.isUndefined(klass)) continue;
- copy(T[tag], klass.prototype);
- }
- }
-
- Object.extend(Element, Element.Methods);
- delete Element.ByTag;
-
- if (Element.extend.refresh) Element.extend.refresh();
- Element.cache = { };
-};
-
-document.viewport = {
- getDimensions: function() {
- var dimensions = { }, B = Prototype.Browser;
- $w('width height').each(function(d) {
- var D = d.capitalize();
- if (B.WebKit && !document.evaluate) {
- // Safari <3.0 needs self.innerWidth/Height
- dimensions[d] = self['inner' + D];
- } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
- // Opera <9.5 needs document.body.clientWidth/Height
- dimensions[d] = document.body['client' + D]
- } else {
- dimensions[d] = document.documentElement['client' + D];
- }
- });
- return dimensions;
- },
-
- getWidth: function() {
- return this.getDimensions().width;
- },
-
- getHeight: function() {
- return this.getDimensions().height;
- },
-
- getScrollOffsets: function() {
- return Element._returnOffset(
- window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
- window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
- }
-};
-/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
- * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
- * license. Please see http://www.yui-ext.com/ for more information. */
-
-var Selector = Class.create({
- initialize: function(expression) {
- this.expression = expression.strip();
-
- if (this.shouldUseSelectorsAPI()) {
- this.mode = 'selectorsAPI';
- } else if (this.shouldUseXPath()) {
- this.mode = 'xpath';
- this.compileXPathMatcher();
- } else {
- this.mode = "normal";
- this.compileMatcher();
- }
-
- },
-
- shouldUseXPath: function() {
- if (!Prototype.BrowserFeatures.XPath) return false;
-
- var e = this.expression;
-
- // Safari 3 chokes on :*-of-type and :empty
- if (Prototype.Browser.WebKit &&
- (e.include("-of-type") || e.include(":empty")))
- return false;
-
- // XPath can't do namespaced attributes, nor can it read
- // the "checked" property from DOM nodes
- if ((/(\[[\w-]*?:|:checked)/).test(e))
- return false;
-
- return true;
- },
-
- shouldUseSelectorsAPI: function() {
- if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
-
- if (!Selector._div) Selector._div = new Element('div');
-
- // Make sure the browser treats the selector as valid. Test on an
- // isolated element to minimize cost of this check.
- try {
- Selector._div.querySelector(this.expression);
- } catch(e) {
- return false;
- }
-
- return true;
- },
-
- compileMatcher: function() {
- var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
- c = Selector.criteria, le, p, m;
-
- 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 in ps) {
- p = ps[i];
- if (m = e.match(p)) {
- this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
- new Template(c[i]).evaluate(m));
- e = e.replace(m[0], '');
- break;
- }
- }
- }
-
- this.matcher.push("return h.unique(n);\n}");
- eval(this.matcher.join('\n'));
- Selector._cache[this.expression] = this.matcher;
- },
-
- compileXPathMatcher: function() {
- var e = this.expression, ps = Selector.patterns,
- x = Selector.xpath, le, m;
-
- if (Selector._cache[e]) {
- this.xpath = Selector._cache[e]; return;
- }
-
- this.matcher = ['.//*'];
- while (e && le != e && (/\S/).test(e)) {
- le = e;
- for (var i in ps) {
- if (m = e.match(ps[i])) {
- this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
- new Template(x[i]).evaluate(m));
- e = e.replace(m[0], '');
- break;
- }
- }
- }
-
- this.xpath = this.matcher.join('');
- Selector._cache[this.expression] = this.xpath;
- },
-
- findElements: function(root) {
- root = root || document;
- var e = this.expression, results;
-
- switch (this.mode) {
- case 'selectorsAPI':
- // querySelectorAll queries document-wide, then filters to descendants
- // of the context element. That's not what we want.
- // Add an explicit context to the selector if necessary.
- if (root !== document) {
- var oldId = root.id, id = $(root).identify();
- e = "#" + id + " " + e;
- }
-
- results = $A(root.querySelectorAll(e)).map(Element.extend);
- root.id = oldId;
-
- return results;
- case 'xpath':
- return document._getElementsByXPath(this.xpath, root);
- default:
- return this.matcher(root);
- }
- },
-
- match: function(element) {
- this.tokens = [];
-
- var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
- var le, p, m;
-
- while (e && le !== e && (/\S/).test(e)) {
- le = e;
- for (var i in ps) {
- p = ps[i];
- if (m = e.match(p)) {
- // use the Selector.assertions methods unless the selector
- // is too complex.
- if (as[i]) {
- this.tokens.push([i, Object.clone(m)]);
- e = e.replace(m[0], '');
- } else {
- // reluctantly do a document-wide search
- // and look for a match in the array
- return this.findElements(document).include(element);
- }
- }
- }
- }
-
- var match = true, name, matches;
- for (var i = 0, token; token = this.tokens[i]; i++) {
- name = token[0], matches = token[1];
- if (!Selector.assertions[name](element, matches)) {
- match = false; break;
- }
- }
-
- return match;
- },
-
- toString: function() {
- return this.expression;
- },
-
- inspect: function() {
- return "#<Selector:" + this.expression.inspect() + ">";
- }
-});
-
-Object.extend(Selector, {
- _cache: { },
-
- xpath: {
- descendant: "//*",
- child: "/*",
- adjacent: "/following-sibling::*[1]",
- laterSibling: '/following-sibling::*',
- tagName: function(m) {
- if (m[1] == '*') return '';
- return "[local-name()='" + m[1].toLowerCase() +
- "' or local-name()='" + m[1].toUpperCase() + "']";
- },
- className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
- id: "[@id='#{1}']",
- attrPresence: function(m) {
- m[1] = m[1].toLowerCase();
- return new Template("[@#{1}]").evaluate(m);
- },
- attr: function(m) {
- m[1] = m[1].toLowerCase();
- m[3] = m[5] || m[6];
- return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
- },
- pseudo: function(m) {
- var h = Selector.xpath.pseudos[m[1]];
- if (!h) return '';
- if (Object.isFunction(h)) return h(m);
- return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
- },
- 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(m) {
- var e = m[6], p = Selector.patterns,
- x = Selector.xpath, le, v;
-
- var exclusion = [];
- while (e && le != e && (/\S/).test(e)) {
- le = e;
- for (var i in p) {
- if (m = e.match(p[i])) {
- v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
- exclusion.push("(" + v.substring(1, v.length - 1) + ")");
- e = e.replace(m[0], '');
- break;
- }
- }
- }
- return "[not(" + exclusion.join(" and ") + ")]";
- },
- 'nth-child': function(m) {
- return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
- },
- 'nth-last-child': function(m) {
- return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
- },
- 'nth-of-type': function(m) {
- return Selector.xpath.pseudos.nth("position() ", m);
- },
- 'nth-last-of-type': function(m) {
- return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
- },
- 'first-of-type': function(m) {
- m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
- },
- 'last-of-type': function(m) {
- m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
- },
- 'only-of-type': function(m) {
- var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
- },
- nth: function(fragment, m) {
- var mm, formula = m[6], predicate;
- if (formula == 'even') formula = '2n+0';
- if (formula == 'odd') formula = '2n+1';
- if (mm = formula.match(/^(\d+)$/)) // digit only
- return '[' + fragment + "= " + mm[1] + ']';
- if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
- if (mm[1] == "-") mm[1] = -1;
- var a = mm[1] ? Number(mm[1]) : 1;
- var b = mm[2] ? Number(mm[2]) : 0;
- predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
- "((#{fragment} - #{b}) div #{a} >= 0)]";
- return new Template(predicate).evaluate({
- fragment: fragment, a: a, b: b });
- }
- }
- }
- },
-
- 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(m) {
- m[3] = (m[5] || m[6]);
- return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
- },
- pseudo: function(m) {
- if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
- return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
- },
- descendant: 'c = "descendant";',
- child: 'c = "child";',
- adjacent: 'c = "adjacent";',
- laterSibling: 'c = "laterSibling";'
- },
-
- patterns: {
- // combinators must be listed first
- // (and descendant needs to be last combinator)
- laterSibling: /^\s*~\s*/,
- child: /^\s*>\s*/,
- adjacent: /^\s*\+\s*/,
- descendant: /^\s/,
-
- // selectors follow
- tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
- id: /^#([\w\-\*]+)(\b|$)/,
- className: /^\.([\w\-\*]+)(\b|$)/,
- pseudo:
-/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
- attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
- attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
- },
-
- // for Selector.match and Element#match
- assertions: {
- tagName: function(element, matches) {
- return matches[1].toUpperCase() == element.tagName.toUpperCase();
- },
-
- className: function(element, matches) {
- return Element.hasClassName(element, matches[1]);
- },
-
- id: function(element, matches) {
- return element.id === matches[1];
- },
-
- attrPresence: function(element, matches) {
- return Element.hasAttribute(element, matches[1]);
- },
-
- attr: function(element, matches) {
- var nodeValue = Element.readAttribute(element, matches[1]);
- return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
- }
- },
-
- handlers: {
- // UTILITY FUNCTIONS
- // joins two collections
- concat: function(a, b) {
- for (var i = 0, node; node = b[i]; i++)
- a.push(node);
- return a;
- },
-
- // marks an array of nodes for counting
- mark: function(nodes) {
- var _true = Prototype.emptyFunction;
- for (var i = 0, node; node = nodes[i]; i++)
- node._countedByPrototype = _true;
- return nodes;
- },
-
- unmark: function(nodes) {
- for (var i = 0, node; node = nodes[i]; i++)
- node._countedByPrototype = undefined;
- return nodes;
- },
-
- // mark each child node with its position (for nth calls)
- // "ofType" flag indicates whether we're indexing for nth-of-type
- // rather than nth-child
- index: function(parentNode, reverse, ofType) {
- parentNode._countedByPrototype = Prototype.emptyFunction;
- if (reverse) {
- for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
- var node = nodes[i];
- if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
- }
- } else {
- for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
- if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
- }
- },
-
- // filters out duplicates and extends all nodes
- unique: function(nodes) {
- if (nodes.length == 0) return nodes;
- var results = [], n;
- for (var i = 0, l = nodes.length; i < l; i++)
- if (!(n = nodes[i])._countedByPrototype) {
- n._countedByPrototype = Prototype.emptyFunction;
- results.push(Element.extend(n));
- }
- return Selector.handlers.unmark(results);
- },
-
- // COMBINATOR FUNCTIONS
- descendant: function(nodes) {
- var h = Selector.handlers;
- for (var i = 0, results = [], node; node = nodes[i]; i++)
- h.concat(results, node.getElementsByTagName('*'));
- return results;
- },
-
- child: function(nodes) {
- var h = Selector.handlers;
- for (var i = 0, results = [], node; node = nodes[i]; i++) {
- for (var j = 0, child; child = node.childNodes[j]; j++)
- if (child.nodeType == 1 && child.tagName != '!') results.push(child);
- }
- return results;
- },
-
- adjacent: function(nodes) {
- for (var i = 0, results = [], node; node = nodes[i]; i++) {
- var next = this.nextElementSibling(node);
- if (next) results.push(next);
- }
- return results;
- },
-
- laterSibling: function(nodes) {
- var h = Selector.handlers;
- for (var i = 0, results = [], node; node = nodes[i]; i++)
- h.concat(results, Element.nextSiblings(node));
- return results;
- },
-
- nextElementSibling: function(node) {
- while (node = node.nextSibling)
- if (node.nodeType == 1) return node;
- return null;
- },
-
- previousElementSibling: function(node) {
- while (node = node.previousSibling)
- if (node.nodeType == 1) return node;
- return null;
- },
-
- // TOKEN FUNCTIONS
- tagName: function(nodes, root, tagName, combinator) {
- var uTagName = tagName.toUpperCase();
- var results = [], h = Selector.handlers;
- if (nodes) {
- if (combinator) {
- // fastlane for ordinary descendant combinators
- if (combinator == "descendant") {
- for (var i = 0, node; node = nodes[i]; i++)
- h.concat(results, node.getElementsByTagName(tagName));
- return results;
- } else nodes = this[combinator](nodes);
- if (tagName == "*") return nodes;
- }
- for (var i = 0, node; node = nodes[i]; i++)
- if (node.tagName.toUpperCase() === uTagName) results.push(node);
- return results;
- } else return root.getElementsByTagName(tagName);
- },
-
- id: function(nodes, root, id, combinator) {
- var targetNode = $(id), h = Selector.handlers;
- if (!targetNode) return [];
- if (!nodes && root == document) return [targetNode];
- if (nodes) {
- if (combinator) {
- if (combinator == 'child') {
- for (var i = 0, node; node = nodes[i]; i++)
- if (targetNode.parentNode == node) return [targetNode];
- } else if (combinator == 'descendant') {
- for (var i = 0, node; node = nodes[i]; i++)
- if (Element.descendantOf(targetNode, node)) return [targetNode];
- } else if (combinator == 'adjacent') {
- for (var i = 0, node; node = nodes[i]; i++)
- if (Selector.handlers.previousElementSibling(targetNode) == node)
- return [targetNode];
- } else nodes = h[combinator](nodes);
- }
- for (var i = 0, node; node = nodes[i]; i++)
- if (node == targetNode) return [targetNode];
- return [];
- }
- return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
- },
-
- className: function(nodes, root, className, combinator) {
- if (nodes && combinator) nodes = this[combinator](nodes);
- return Selector.handlers.byClassName(nodes, root, className);
- },
-
- byClassName: function(nodes, root, className) {
- if (!nodes) nodes = Selector.handlers.descendant([root]);
- var needle = ' ' + className + ' ';
- for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
- nodeClassName = node.className;
- if (nodeClassName.length == 0) continue;
- if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
- results.push(node);
- }
- return results;
- },
-
- attrPresence: function(nodes, root, attr, combinator) {
- if (!nodes) nodes = root.getElementsByTagName("*");
- if (nodes && combinator) nodes = this[combinator](nodes);
- var results = [];
- for (var i = 0, node; node = nodes[i]; i++)
- if (Element.hasAttribute(node, attr)) results.push(node);
- return results;
- },
-
- attr: function(nodes, root, attr, value, operator, combinator) {
- if (!nodes) nodes = root.getElementsByTagName("*");
- if (nodes && combinator) nodes = this[combinator](nodes);
- var handler = Selector.operators[operator], results = [];
- for (var i = 0, node; node = nodes[i]; i++) {
- var nodeValue = Element.readAttribute(node, attr);
- if (nodeValue === null) continue;
- if (handler(nodeValue, value)) results.push(node);
- }
- return results;
- },
-
- pseudo: function(nodes, name, value, root, combinator) {
- if (nodes && combinator) nodes = this[combinator](nodes);
- if (!nodes) nodes = root.getElementsByTagName("*");
- return Selector.pseudos[name](nodes, value, root);
- }
- },
-
- pseudos: {
- 'first-child': function(nodes, value, root) {
- for (var i = 0, results = [], node; node = nodes[i]; i++) {
- if (Selector.handlers.previousElementSibling(node)) continue;
- results.push(node);
- }
- return results;
- },
- 'last-child': function(nodes, value, root) {
- for (var i = 0, results = [], node; node = nodes[i]; i++) {
- if (Selector.handlers.nextElementSibling(node)) continue;
- results.push(node);
- }
- return results;
- },
- 'only-child': function(nodes, value, root) {
- var h = Selector.handlers;
- for (var i = 0, results = [], node; node = nodes[i]; i++)
- if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
- results.push(node);
- return results;
- },
- 'nth-child': function(nodes, formula, root) {
- return Selector.pseudos.nth(nodes, formula, root);
- },
- 'nth-last-child': function(nodes, formula, root) {
- return Selector.pseudos.nth(nodes, formula, root, true);
- },
- 'nth-of-type': function(nodes, formula, root) {
- return Selector.pseudos.nth(nodes, formula, root, false, true);
- },
- 'nth-last-of-type': function(nodes, formula, root) {
- return Selector.pseudos.nth(nodes, formula, root, true, true);
- },
- 'first-of-type': function(nodes, formula, root) {
- return Selector.pseudos.nth(nodes, "1", root, false, true);
- },
- 'last-of-type': function(nodes, formula, root) {
- return Selector.pseudos.nth(nodes, "1", root, true, true);
- },
- 'only-of-type': function(nodes, formula, root) {
- var p = Selector.pseudos;
- return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
- },
-
- // handles the an+b logic
- getIndices: function(a, b, total) {
- if (a == 0) return b > 0 ? [b] : [];
- return $R(1, total).inject([], function(memo, i) {
- if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
- return memo;
- });
- },
-
- // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
- nth: function(nodes, formula, root, reverse, ofType) {
- if (nodes.length == 0) return [];
- if (formula == 'even') formula = '2n+0';
- if (formula == 'odd') formula = '2n+1';
- var h = Selector.handlers, results = [], indexed = [], m;
- h.mark(nodes);
- for (var i = 0, node; node = nodes[i]; i++) {
- if (!node.parentNode._countedByPrototype) {
- h.index(node.parentNode, reverse, ofType);
- indexed.push(node.parentNode);
- }
- }
- if (formula.match(/^\d+$/)) { // just a number
- formula = Number(formula);
- for (var i = 0, node; node = nodes[i]; i++)
- if (node.nodeIndex == formula) results.push(node);
- } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
- if (m[1] == "-") m[1] = -1;
- var a = m[1] ? Number(m[1]) : 1;
- var b = m[2] ? Number(m[2]) : 0;
- var indices = Selector.pseudos.getIndices(a, b, nodes.length);
- for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
- for (var j = 0; j < l; j++)
- if (node.nodeIndex == indices[j]) results.push(node);
- }
- }
- h.unmark(nodes);
- h.unmark(indexed);
- return results;
- },
-
- 'empty': function(nodes, value, root) {
- for (var i = 0, results = [], node; node = nodes[i]; i++) {
- // IE treats comments as element nodes
- if (node.tagName == '!' || node.firstChild) continue;
- results.push(node);
- }
- return results;
- },
-
- 'not': function(nodes, selector, root) {
- var h = Selector.handlers, selectorType, m;
- var exclusions = new Selector(selector).findElements(root);
- h.mark(exclusions);
- for (var i = 0, results = [], node; node = nodes[i]; i++)
- if (!node._countedByPrototype) results.push(node);
- h.unmark(exclusions);
- return results;
- },
-
- 'enabled': function(nodes, value, root) {
- for (var i = 0, results = [], node; node = nodes[i]; i++)
- if (!node.disabled && (!node.type || node.type !== 'hidden'))
- results.push(node);
- return results;
- },
-
- 'disabled': function(nodes, value, root) {
- for (var i = 0, results = [], node; node = nodes[i]; i++)
- if (node.disabled) results.push(node);
- return results;
- },
-
- 'checked': function(nodes, value, root) {
- for (var i = 0, results = [], node; node = nodes[i]; i++)
- if (node.checked) results.push(node);
- return results;
- }
- },
-
- operators: {
- '=': function(nv, v) { return nv == v; },
- '!=': function(nv, v) { return nv != v; },
- '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
- '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
- '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
- '$=': function(nv, v) { return nv.endsWith(v); },
- '*=': function(nv, v) { return nv.include(v); },
- '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
- '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
- '-').include('-' + (v || "").toUpperCase() + '-'); }
- },
-
- split: function(expression) {
- var expressions = [];
- expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
- expressions.push(m[1].strip());
- });
- return expressions;
- },
-
- matchElements: function(elements, expression) {
- var matches = $$(expression), h = Selector.handlers;
- h.mark(matches);
- for (var i = 0, results = [], element; element = elements[i]; i++)
- if (element._countedByPrototype) results.push(element);
- h.unmark(matches);
- return results;
- },
-
- findElement: function(elements, expression, index) {
- if (Object.isNumber(expression)) {
- index = expression; expression = false;
- }
- return Selector.matchElements(elements, expression || '*')[index || 0];
- },
-
- findChildElements: function(element, expressions) {
- expressions = Selector.split(expressions.join(','));
- var results = [], h = Selector.handlers;
- for (var i = 0, l = expressions.length, selector; i < l; i++) {
- selector = new Selector(expressions[i].strip());
- h.concat(results, selector.findElements(element));
- }
- return (l > 1) ? h.unique(results) : results;
- }
-});
-
-if (Prototype.Browser.IE) {
- Object.extend(Selector.handlers, {
- // IE returns comment nodes on getElementsByTagName("*").
- // Filter them out.
- concat: function(a, b) {
- for (var i = 0, node; node = b[i]; i++)
- if (node.tagName !== "!") a.push(node);
- return a;
- },
-
- // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
- unmark: function(nodes) {
- for (var i = 0, node; node = nodes[i]; i++)
- node.removeAttribute('_countedByPrototype');
- return nodes;
- }
- });
-}
-
-function $$() {
- return Selector.findChildElements(document, $A(arguments));
-}
-var Form = {
- reset: function(form) {
- $(form).reset();
- return form;
- },
-
- serializeElements: function(elements, options) {
- if (typeof options != 'object') options = { hash: !!options };
- else if (Object.isUndefined(options.hash)) options.hash = true;
- var key, value, submitted = false, submit = options.submit;
-
- var data = elements.inject({ }, function(result, element) {
- if (!element.disabled && element.name) {
- key = element.name; value = $(element).getValue();
- if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
- submit !== false && (!submit || key == submit) && (submitted = true)))) {
- if (key in result) {
- // a key is already present; construct an array of values
- if (!Object.isArray(result[key])) result[key] = [result[key]];
- result[key].push(value);
- }
- else result[key] = value;
- }
- }
- return result;
- });
-
- return options.hash ? data : Object.toQueryString(data);
- }
-};
-
-Form.Methods = {
- serialize: function(form, options) {
- return Form.serializeElements(Form.getElements(form), options);
- },
-
- getElements: function(form) {
- return $A($(form).getElementsByTagName('*')).inject([],
- function(elements, child) {
- if (Form.Element.Serializers[child.tagName.toLowerCase()])
- elements.push(Element.extend(child));
- return elements;
- }
- );
- },
-
- getInputs: function(form, typeName, name) {
- form = $(form);
- var inputs = form.getElementsByTagName('input');
-
- if (!typeName && !name) return $A(inputs).map(Element.extend);
-
- for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
- var input = inputs[i];
- if ((typeName && input.type != typeName) || (name && input.name != name))
- continue;
- matchingInputs.push(Element.extend(input));
- }
-
- return matchingInputs;
- },
-
- disable: function(form) {
- form = $(form);
- Form.getElements(form).invoke('disable');
- return form;
- },
-
- enable: function(form) {
- form = $(form);
- Form.getElements(form).invoke('enable');
- return form;
- },
-
- findFirstElement: function(form) {
- var elements = $(form).getElements().findAll(function(element) {
- return 'hidden' != element.type && !element.disabled;
- });
- var firstByIndex = elements.findAll(function(element) {
- return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
- }).sortBy(function(element) { return element.tabIndex }).first();
-
- return firstByIndex ? firstByIndex : elements.find(function(element) {
- return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
- });
- },
-
- focusFirstElement: function(form) {
- form = $(form);
- form.findFirstElement().activate();
- return form;
- },
-
- request: function(form, options) {
- form = $(form), options = Object.clone(options || { });
-
- var params = options.parameters, action = form.readAttribute('action') || '';
- if (action.blank()) action = window.location.href;
- options.parameters = form.serialize(true);
-
- if (params) {
- if (Object.isString(params)) params = params.toQueryParams();
- Object.extend(options.parameters, params);
- }
-
- if (form.hasAttribute('method') && !options.method)
- options.method = form.method;
-
- return new Ajax.Request(action, options);
- }
-};
-
-/*--------------------------------------------------------------------------*/
-
-Form.Element = {
- focus: function(element) {
- $(element).focus();
- return element;
- },
-
- select: function(element) {
- $(element).select();
- return element;
- }
-};
-
-Form.Element.Methods = {
- serialize: function(element) {
- element = $(element);
- if (!element.disabled && element.name) {
- var value = element.getValue();
- if (value != undefined) {
- var pair = { };
- pair[element.name] = value;
- return Object.toQueryString(pair);
- }
- }
- return '';
- },
-
- getValue: function(element) {
- element = $(element);
- var method = element.tagName.toLowerCase();
- return Form.Element.Serializers[method](element);
- },
-
- setValue: function(element, value) {
- element = $(element);
- var method = element.tagName.toLowerCase();
- Form.Element.Serializers[method](element, value);
- return element;
- },
-
- clear: function(element) {
- $(element).value = '';
- return element;
- },
-
- present: function(element) {
- return $(element).value != '';
- },
-
- activate: function(element) {
- element = $(element);
- try {
- element.focus();
- if (element.select && (element.tagName.toLowerCase() != 'input' ||
- !['button', 'reset', 'submit'].include(element.type)))
- element.select();
- } catch (e) { }
- return element;
- },
-
- disable: function(element) {
- element = $(element);
- element.disabled = true;
- return element;
- },
-
- enable: function(element) {
- element = $(element);
- element.disabled = false;
- return element;
- }
-};
-
-/*--------------------------------------------------------------------------*/
-
-var Field = Form.Element;
-var $F = Form.Element.Methods.getValue;
-
-/*--------------------------------------------------------------------------*/
-
-Form.Element.Serializers = {
- input: function(element, value) {
- switch (element.type.toLowerCase()) {
- case 'checkbox':
- case 'radio':
- return Form.Element.Serializers.inputSelector(element, value);
- default:
- return Form.Element.Serializers.textarea(element, value);
- }
- },
-
- inputSelector: function(element, value) {
- if (Object.isUndefined(value)) return element.checked ? element.value : null;
- else element.checked = !!value;
- },
-
- textarea: function(element, value) {
- if (Object.isUndefined(value)) return element.value;
- else element.value = value;
- },
-
- select: function(element, value) {
- if (Object.isUndefined(value))
- return this[element.type == 'select-one' ?
- 'selectOne' : 'selectMany'](element);
- else {
- var opt, currentValue, single = !Object.isArray(value);
- for (var i = 0, length = element.length; i < length; i++) {
- opt = element.options[i];
- currentValue = this.optionValue(opt);
- if (single) {
- if (currentValue == value) {
- opt.selected = true;
- return;
- }
- }
- else opt.selected = value.include(currentValue);
- }
- }
- },
-
- selectOne: function(element) {
- var index = element.selectedIndex;
- return index >= 0 ? this.optionValue(element.options[index]) : null;
- },
-
- selectMany: function(element) {
- var values, length = element.length;
- if (!length) return null;
-
- for (var i = 0, values = []; i < length; i++) {
- var opt = element.options[i];
- if (opt.selected) values.push(this.optionValue(opt));
- }
- return values;
- },
-
- optionValue: function(opt) {
- // extend element because hasAttribute may not be native
- return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
- }
-};
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
- initialize: function($super, element, frequency, callback) {
- $super(callback, frequency);
- this.element = $(element);
- this.lastValue = this.getValue();
- },
-
- execute: function() {
- var value = this.getValue();
- if (Object.isString(this.lastValue) && Object.isString(value) ?
- this.lastValue != value : String(this.lastValue) != String(value)) {
- this.callback(this.element, value);
- this.lastValue = value;
- }
- }
-});
-
-Form.Element.Observer = Class.create(Abstract.TimedObserver, {
- getValue: function() {
- return Form.Element.getValue(this.element);
- }
-});
-
-Form.Observer = Class.create(Abstract.TimedObserver, {
- getValue: function() {
- return Form.serialize(this.element);
- }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.EventObserver = Class.create({
- initialize: function(element, callback) {
- this.element = $(element);
- this.callback = callback;
-
- this.lastValue = this.getValue();
- if (this.element.tagName.toLowerCase() == 'form')
- this.registerFormCallbacks();
- else
- this.registerCallback(this.element);
- },
-
- onElementEvent: function() {
- var value = this.getValue();
- if (this.lastValue != value) {
- this.callback(this.element, value);
- this.lastValue = value;
- }
- },
-
- registerFormCallbacks: function() {
- Form.getElements(this.element).each(this.registerCallback, this);
- },
-
- registerCallback: function(element) {
- if (element.type) {
- switch (element.type.toLowerCase()) {
- case 'checkbox':
- case 'radio':
- Event.observe(element, 'click', this.onElementEvent.bind(this));
- break;
- default:
- Event.observe(element, 'change', this.onElementEvent.bind(this));
- break;
- }
- }
- }
-});
-
-Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
- getValue: function() {
- return Form.Element.getValue(this.element);
- }
-});
-
-Form.EventObserver = Class.create(Abstract.EventObserver, {
- getValue: function() {
- return Form.serialize(this.element);
- }
-});
-if (!window.Event) var Event = { };
-
-Object.extend(Event, {
- KEY_BACKSPACE: 8,
- KEY_TAB: 9,
- KEY_RETURN: 13,
- KEY_ESC: 27,
- KEY_LEFT: 37,
- KEY_UP: 38,
- KEY_RIGHT: 39,
- KEY_DOWN: 40,
- KEY_DELETE: 46,
- KEY_HOME: 36,
- KEY_END: 35,
- KEY_PAGEUP: 33,
- KEY_PAGEDOWN: 34,
- KEY_INSERT: 45,
-
- cache: { },
-
- relatedTarget: function(event) {
- var element;
- switch(event.type) {
- case 'mouseover': element = event.fromElement; break;
- case 'mouseout': element = event.toElement; break;
- default: return null;
- }
- return Element.extend(element);
- }
-});
-
-Event.Methods = (function() {
- var isButton;
-
- if (Prototype.Browser.IE) {
- var buttonMap = { 0: 1, 1: 4, 2: 2 };
- isButton = function(event, code) {
- return event.button == buttonMap[code];
- };
-
- } else if (Prototype.Browser.WebKit) {
- isButton = function(event, code) {
- switch (code) {
- case 0: return event.which == 1 && !event.metaKey;
- case 1: return event.which == 1 && event.metaKey;
- default: return false;
- }
- };
-
- } else {
- isButton = function(event, code) {
- return event.which ? (event.which === code + 1) : (event.button === code);
- };
- }
-
- return {
- isLeftClick: function(event) { return isButton(event, 0) },
- isMiddleClick: function(event) { return isButton(event, 1) },
- isRightClick: function(event) { return isButton(event, 2) },
-
- element: function(event) {
- event = Event.extend(event);
-
- var node = event.target,
- type = event.type,
- currentTarget = event.currentTarget;
-
- if (currentTarget && currentTarget.tagName) {
- // Firefox screws up the "click" event when moving between radio buttons
- // via arrow keys. It also screws up the "load" and "error" events on images,
- // reporting the document as the target instead of the original image.
- if (type === 'load' || type === 'error' ||
- (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
- && currentTarget.type === 'radio'))
- node = currentTarget;
- }
- if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
- return Element.extend(node);
- },
-
- findElement: function(event, expression) {
- var element = Event.element(event);
- if (!expression) return element;
- var elements = [element].concat(element.ancestors());
- return Selector.findElement(elements, expression, 0);
- },
-
- pointer: function(event) {
- var docElement = document.documentElement,
- body = document.body || { scrollLeft: 0, scrollTop: 0 };
- return {
- x: event.pageX || (event.clientX +
- (docElement.scrollLeft || body.scrollLeft) -
- (docElement.clientLeft || 0)),
- y: event.pageY || (event.clientY +
- (docElement.scrollTop || body.scrollTop) -
- (docElement.clientTop || 0))
- };
- },
-
- pointerX: function(event) { return Event.pointer(event).x },
- pointerY: function(event) { return Event.pointer(event).y },
-
- stop: function(event) {
- Event.extend(event);
- event.preventDefault();
- event.stopPropagation();
- event.stopped = true;
- }
- };
-})();
-
-Event.extend = (function() {
- var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
- m[name] = Event.Methods[name].methodize();
- return m;
- });
-
- if (Prototype.Browser.IE) {
- Object.extend(methods, {
- stopPropagation: function() { this.cancelBubble = true },
- preventDefault: function() { this.returnValue = false },
- inspect: function() { return "[object Event]" }
- });
-
- return function(event) {
- if (!event) return false;
- if (event._extendedByPrototype) return event;
-
- event._extendedByPrototype = Prototype.emptyFunction;
- var pointer = Event.pointer(event);
- Object.extend(event, {
- target: event.srcElement,
- relatedTarget: Event.relatedTarget(event),
- pageX: pointer.x,
- pageY: pointer.y
- });
- return Object.extend(event, methods);
- };
-
- } else {
- Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
- Object.extend(Event.prototype, methods);
- return Prototype.K;
- }
-})();
-
-Object.extend(Event, (function() {
- var cache = Event.cache;
-
- function getEventID(element) {
- if (element._prototypeEventID) return element._prototypeEventID[0];
- arguments.callee.id = arguments.callee.id || 1;
- return element._prototypeEventID = [++arguments.callee.id];
- }
-
- function getDOMEventName(eventName) {
- if (eventName && eventName.include(':')) return "dataavailable";
- return eventName;
- }
-
- function getCacheForID(id) {
- return cache[id] = cache[id] || { };
- }
-
- function getWrappersForEventName(id, eventName) {
- var c = getCacheForID(id);
- return c[eventName] = c[eventName] || [];
- }
-
- function createWrapper(element, eventName, handler) {
- var id = getEventID(element);
- var c = getWrappersForEventName(id, eventName);
- if (c.pluck("handler").include(handler)) return false;
-
- var wrapper = function(event) {
- if (!Event || !Event.extend ||
- (event.eventName && event.eventName != eventName))
- return false;
-
- Event.extend(event);
- handler.call(element, event);
- };
-
- wrapper.handler = handler;
- c.push(wrapper);
- return wrapper;
- }
-
- function findWrapper(id, eventName, handler) {
- var c = getWrappersForEventName(id, eventName);
- return c.find(function(wrapper) { return wrapper.handler == handler });
- }
-
- function destroyWrapper(id, eventName, handler) {
- var c = getCacheForID(id);
- if (!c[eventName]) return false;
- c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
- }
-
- function destroyCache() {
- for (var id in cache)
- for (var eventName in cache[id])
- cache[id][eventName] = null;
- }
-
-
- // Internet Explorer needs to remove event handlers on page unload
- // in order to avoid memory leaks.
- if (window.attachEvent) {
- window.attachEvent("onunload", destroyCache);
- }
-
- // Safari has a dummy event handler on page unload so that it won't
- // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
- // object when page is returned to via the back button using its bfcache.
- if (Prototype.Browser.WebKit) {
- window.addEventListener('unload', Prototype.emptyFunction, false);
- }
-
- return {
- observe: function(element, eventName, handler) {
- element = $(element);
- var name = getDOMEventName(eventName);
-
- var wrapper = createWrapper(element, eventName, handler);
- if (!wrapper) return element;
-
- if (element.addEventListener) {
- element.addEventListener(name, wrapper, false);
- } else {
- element.attachEvent("on" + name, wrapper);
- }
-
- return element;
- },
-
- stopObserving: function(element, eventName, handler) {
- element = $(element);
- var id = getEventID(element), name = getDOMEventName(eventName);
-
- if (!handler && eventName) {
- getWrappersForEventName(id, eventName).each(function(wrapper) {
- element.stopObserving(eventName, wrapper.handler);
- });
- return element;
-
- } else if (!eventName) {
- Object.keys(getCacheForID(id)).each(function(eventName) {
- element.stopObserving(eventName);
- });
- return element;
- }
-
- var wrapper = findWrapper(id, eventName, handler);
- if (!wrapper) return element;
-
- if (element.removeEventListener) {
- element.removeEventListener(name, wrapper, false);
- } else {
- element.detachEvent("on" + name, wrapper);
- }
-
- destroyWrapper(id, eventName, handler);
-
- return element;
- },
-
- fire: function(element, eventName, memo) {
- element = $(element);
- if (element == document && document.createEvent && !element.dispatchEvent)
- element = document.documentElement;
-
- var event;
- if (document.createEvent) {
- event = document.createEvent("HTMLEvents");
- event.initEvent("dataavailable", true, true);
- } else {
- event = document.createEventObject();
- event.eventType = "ondataavailable";
- }
-
- event.eventName = eventName;
- event.memo = memo || { };
-
- if (document.createEvent) {
- element.dispatchEvent(event);
- } else {
- element.fireEvent(event.eventType, event);
- }
-
- return Event.extend(event);
- }
- };
-})());
-
-Object.extend(Event, Event.Methods);
-
-Element.addMethods({
- fire: Event.fire,
- observe: Event.observe,
- stopObserving: Event.stopObserving
-});
-
-Object.extend(document, {
- fire: Element.Methods.fire.methodize(),
- observe: Element.Methods.observe.methodize(),
- stopObserving: Element.Methods.stopObserving.methodize(),
- loaded: false
-});
-
-(function() {
- /* Support for the DOMContentLoaded event is based on work by Dan Webb,
- Matthias Miller, Dean Edwards and John Resig. */
-
- var timer;
-
- function fireContentLoadedEvent() {
- if (document.loaded) return;
- if (timer) window.clearInterval(timer);
- document.fire("dom:loaded");
- document.loaded = true;
- }
-
- if (document.addEventListener) {
- if (Prototype.Browser.WebKit) {
- timer = window.setInterval(function() {
- if (/loaded|complete/.test(document.readyState))
- fireContentLoadedEvent();
- }, 0);
-
- Event.observe(window, "load", fireContentLoadedEvent);
-
- } else {
- document.addEventListener("DOMContentLoaded",
- fireContentLoadedEvent, false);
- }
-
- } else {
- document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
- $("__onDOMContentLoaded").onreadystatechange = function() {
- if (this.readyState == "complete") {
- this.onreadystatechange = null;
- fireContentLoadedEvent();
- }
- };
- }
-})();
-/*------------------------------- DEPRECATED -------------------------------*/
-
-Hash.toQueryString = Object.toQueryString;
-
-var Toggle = { display: Element.toggle };
-
-Element.Methods.childOf = Element.Methods.descendantOf;
-
-var Insertion = {
- Before: function(element, content) {
- return Element.insert(element, {before:content});
- },
-
- Top: function(element, content) {
- return Element.insert(element, {top:content});
- },
-
- Bottom: function(element, content) {
- return Element.insert(element, {bottom:content});
- },
-
- After: function(element, content) {
- return Element.insert(element, {after:content});
- }
-};
-
-var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
-
-// This should be moved to script.aculo.us; notice the deprecated methods
-// further below, that map to the newer Element methods.
-var Position = {
- // set to true if needed, warning: firefox performance problems
- // NOT neeeded for page scrolling, only if draggable contained in
- // scrollable elements
- includeScrollOffsets: false,
-
- // must be called before calling withinIncludingScrolloffset, every time the
- // page is scrolled
- prepare: function() {
- this.deltaX = window.pageXOffset
- || document.documentElement.scrollLeft
- || document.body.scrollLeft
- || 0;
- this.deltaY = window.pageYOffset
- || document.documentElement.scrollTop
- || document.body.scrollTop
- || 0;
- },
-
- // caches x/y coordinate pair to use with overlap
- within: function(element, x, y) {
- if (this.includeScrollOffsets)
- return this.withinIncludingScrolloffsets(element, x, y);
- this.xcomp = x;
- this.ycomp = y;
- this.offset = Element.cumulativeOffset(element);
-
- return (y >= this.offset[1] &&
- y < this.offset[1] + element.offsetHeight &&
- x >= this.offset[0] &&
- x < this.offset[0] + element.offsetWidth);
- },
-
- withinIncludingScrolloffsets: function(element, x, y) {
- var offsetcache = Element.cumulativeScrollOffset(element);
-
- this.xcomp = x + offsetcache[0] - this.deltaX;
- this.ycomp = y + offsetcache[1] - this.deltaY;
- this.offset = Element.cumulativeOffset(element);
-
- return (this.ycomp >= this.offset[1] &&
- this.ycomp < this.offset[1] + element.offsetHeight &&
- this.xcomp >= this.offset[0] &&
- this.xcomp < this.offset[0] + element.offsetWidth);
- },
-
- // within must be called directly before
- overlap: function(mode, element) {
- if (!mode) return 0;
- if (mode == 'vertical')
- return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
- element.offsetHeight;
- if (mode == 'horizontal')
- return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
- element.offsetWidth;
- },
-
- // Deprecation layer -- use newer Element methods now (1.5.2).
-
- cumulativeOffset: Element.Methods.cumulativeOffset,
-
- positionedOffset: Element.Methods.positionedOffset,
-
- absolutize: function(element) {
- Position.prepare();
- return Element.absolutize(element);
- },
-
- relativize: function(element) {
- Position.prepare();
- return Element.relativize(element);
- },
-
- realOffset: Element.Methods.cumulativeScrollOffset,
-
- offsetParent: Element.Methods.getOffsetParent,
-
- page: Element.Methods.viewportOffset,
-
- clone: function(source, target, options) {
- options = options || { };
- return Element.clonePosition(target, source, options);
- }
-};
-
-/*--------------------------------------------------------------------------*/
-
-if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
- function iter(name) {
- return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
- }
-
- instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
- function(element, className) {
- className = className.toString().strip();
- var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
- return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
- } : function(element, className) {
- className = className.toString().strip();
- var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
- if (!classNames && !className) return elements;
-
- var nodes = $(element).getElementsByTagName('*');
- className = ' ' + className + ' ';
-
- for (var i = 0, child, cn; child = nodes[i]; i++) {
- if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
- (classNames && classNames.all(function(name) {
- return !name.toString().blank() && cn.include(' ' + name + ' ');
- }))))
- elements.push(Element.extend(child));
- }
- return elements;
- };
-
- return function(className, parentElement) {
- return $(parentElement || document.body).getElementsByClassName(className);
- };
-}(Element.Methods);
-
-/*--------------------------------------------------------------------------*/
-
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
- initialize: function(element) {
- this.element = $(element);
- },
-
- _each: function(iterator) {
- this.element.className.split(/\s+/).select(function(name) {
- return name.length > 0;
- })._each(iterator);
- },
-
- set: function(className) {
- this.element.className = className;
- },
-
- add: function(classNameToAdd) {
- if (this.include(classNameToAdd)) return;
- this.set($A(this).concat(classNameToAdd).join(' '));
- },
-
- remove: function(classNameToRemove) {
- if (!this.include(classNameToRemove)) return;
- this.set($A(this).without(classNameToRemove).join(' '));
- },
-
- toString: function() {
- return $A(this).join(' ');
- }
-};
-
-Object.extend(Element.ClassNames.prototype, Enumerable);
-
-/*--------------------------------------------------------------------------*/
-
-Element.addMethods(); \ No newline at end of file
diff --git a/addons/web_graph/static/lib/flotr2/lib/underscore-min.js b/addons/web_graph/static/lib/flotr2/lib/underscore-min.js
deleted file mode 100644
index 5983694cfbb..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/underscore-min.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Underscore.js 1.1.7
-// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore is freely distributable under the MIT license.
-// Portions of Underscore are inspired or borrowed from Prototype,
-// Oliver Steele's Functional, and John Resig's Micro-Templating.
-// For all details and documentation:
-// http://documentcloud.github.com/underscore
-(function(){var p=this,C=p._,m={},i=Array.prototype,n=Object.prototype,f=i.slice,D=i.unshift,E=n.toString,l=n.hasOwnProperty,s=i.forEach,t=i.map,u=i.reduce,v=i.reduceRight,w=i.filter,x=i.every,y=i.some,o=i.indexOf,z=i.lastIndexOf;n=Array.isArray;var F=Object.keys,q=Function.prototype.bind,b=function(a){return new j(a)};typeof module!=="undefined"&&module.exports?(module.exports=b,b._=b):p._=b;b.VERSION="1.1.7";var h=b.each=b.forEach=function(a,c,b){if(a!=null)if(s&&a.forEach===s)a.forEach(c,b);else if(a.length===
-+a.length)for(var e=0,k=a.length;e<k;e++){if(e in a&&c.call(b,a[e],e,a)===m)break}else for(e in a)if(l.call(a,e)&&c.call(b,a[e],e,a)===m)break};b.map=function(a,c,b){var e=[];if(a==null)return e;if(t&&a.map===t)return a.map(c,b);h(a,function(a,g,G){e[e.length]=c.call(b,a,g,G)});return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var k=d!==void 0;a==null&&(a=[]);if(u&&a.reduce===u)return e&&(c=b.bind(c,e)),k?a.reduce(c,d):a.reduce(c);h(a,function(a,b,f){k?d=c.call(e,d,a,b,f):(d=a,k=!0)});if(!k)throw new TypeError("Reduce of empty array with no initial value");
-return d};b.reduceRight=b.foldr=function(a,c,d,e){a==null&&(a=[]);if(v&&a.reduceRight===v)return e&&(c=b.bind(c,e)),d!==void 0?a.reduceRight(c,d):a.reduceRight(c);a=(b.isArray(a)?a.slice():b.toArray(a)).reverse();return b.reduce(a,c,d,e)};b.find=b.detect=function(a,c,b){var e;A(a,function(a,g,f){if(c.call(b,a,g,f))return e=a,!0});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(w&&a.filter===w)return a.filter(c,b);h(a,function(a,g,f){c.call(b,a,g,f)&&(e[e.length]=a)});return e};
-b.reject=function(a,c,b){var e=[];if(a==null)return e;h(a,function(a,g,f){c.call(b,a,g,f)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=!0;if(a==null)return e;if(x&&a.every===x)return a.every(c,b);h(a,function(a,g,f){if(!(e=e&&c.call(b,a,g,f)))return m});return e};var A=b.some=b.any=function(a,c,d){c=c||b.identity;var e=!1;if(a==null)return e;if(y&&a.some===y)return a.some(c,d);h(a,function(a,b,f){if(e|=c.call(d,a,b,f))return m});return!!e};b.include=b.contains=function(a,c){var b=
-!1;if(a==null)return b;if(o&&a.indexOf===o)return a.indexOf(c)!=-1;A(a,function(a){if(b=a===c)return!0});return b};b.invoke=function(a,c){var d=f.call(arguments,2);return b.map(a,function(a){return(c.call?c||a:a[c]).apply(a,d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);var e={computed:-Infinity};h(a,function(a,b,f){b=c?c.call(d,a,b,f):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,
-c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};h(a,function(a,b,f){b=c?c.call(d,a,b,f):a;b<e.computed&&(e={value:a,computed:b})});return e.value};b.sortBy=function(a,c,d){return b.pluck(b.map(a,function(a,b,f){return{value:a,criteria:c.call(d,a,b,f)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,b){var d={};h(a,function(a,f){var g=b(a,f);(d[g]||(d[g]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||
-(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){if(!a)return[];if(a.toArray)return a.toArray();if(b.isArray(a))return f.call(a);if(b.isArguments(a))return f.call(a);return b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=b.head=function(a,b,d){return b!=null&&!d?f.call(a,0,b):a[0]};b.rest=b.tail=function(a,b,d){return f.call(a,b==null||d?1:b)};b.last=function(a){return a[a.length-1]};b.compact=function(a){return b.filter(a,
-function(a){return!!a})};b.flatten=function(a){return b.reduce(a,function(a,d){if(b.isArray(d))return a.concat(b.flatten(d));a[a.length]=d;return a},[])};b.without=function(a){return b.difference(a,f.call(arguments,1))};b.uniq=b.unique=function(a,c){return b.reduce(a,function(a,e,f){if(0==f||(c===!0?b.last(a)!=e:!b.include(a,e)))a[a.length]=e;return a},[])};b.union=function(){return b.uniq(b.flatten(arguments))};b.intersection=b.intersect=function(a){var c=f.call(arguments,1);return b.filter(b.uniq(a),
-function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a,c){return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=f.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d)return d=b.sortedIndex(a,c),a[d]===c?d:-1;if(o&&a.indexOf===o)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,
-b){if(a==null)return-1;if(z&&a.lastIndexOf===z)return a.lastIndexOf(b);for(var d=a.length;d--;)if(a[d]===b)return d;return-1};b.range=function(a,b,d){arguments.length<=1&&(b=a||0,a=0);d=arguments[2]||1;for(var e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;)g[f++]=a,a+=d;return g};b.bind=function(a,b){if(a.bind===q&&q)return q.apply(a,f.call(arguments,1));var d=f.call(arguments,2);return function(){return a.apply(b,d.concat(f.call(arguments)))}};b.bindAll=function(a){var c=f.call(arguments,1);
-c.length==0&&(c=b.functions(a));h(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var b=c.apply(this,arguments);return l.call(d,b)?d[b]:d[b]=a.apply(this,arguments)}};b.delay=function(a,b){var d=f.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(f.call(arguments,1)))};var B=function(a,b,d){var e;return function(){var f=this,g=arguments,h=function(){e=null;
-a.apply(f,g)};d&&clearTimeout(e);if(d||!e)e=setTimeout(h,b)}};b.throttle=function(a,b){return B(a,b,!1)};b.debounce=function(a,b){return B(a,b,!0)};b.once=function(a){var b=!1,d;return function(){if(b)return d;b=!0;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(f.call(arguments));return b.apply(this,d)}};b.compose=function(){var a=f.call(arguments);return function(){for(var b=f.call(arguments),d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=
-function(a,b){return function(){if(--a<1)return b.apply(this,arguments)}};b.keys=F||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)l.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){h(f.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){h(f.call(arguments,
-1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,c){if(a===c)return!0;var d=typeof a;if(d!=typeof c)return!1;if(a==c)return!0;if(!a&&c||a&&!c)return!1;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual)return a.isEqual(c);if(c.isEqual)return c.isEqual(a);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return!1;
-if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return!1;if(a.length&&a.length!==c.length)return!1;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return!1;for(var f in a)if(!(f in c)||!b.isEqual(a[f],c[f]))return!1;return!0};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(l.call(a,c))return!1;return!0};b.isElement=function(a){return!!(a&&a.nodeType==
-1)};b.isArray=n||function(a){return E.call(a)==="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return!(!a||!l.call(a,"callee"))};b.isFunction=function(a){return!(!a||!a.constructor||!a.call||!a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===!0||a===!1};b.isDate=function(a){return!(!a||!a.getTimezoneOffset||
-!a.setUTCFullYear)};b.isRegExp=function(a){return!(!a||!a.test||!a.exec||!(a.ignoreCase||a.ignoreCase===!1))};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){p._=C;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.mixin=function(a){h(b.functions(a),function(c){H(c,b[c]=a[c])})};var I=0;b.uniqueId=function(a){var b=I++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g};
-b.template=function(a,c){var d=b.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return c?d(c):d};
-var j=function(a){this._wrapped=a};b.prototype=j.prototype;var r=function(a,c){return c?b(a).chain():a},H=function(a,c){j.prototype[a]=function(){var a=f.call(arguments);D.call(a,this._wrapped);return r(c.apply(b,a),this._chain)}};b.mixin(b);h(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var b=i[a];j.prototype[a]=function(){b.apply(this._wrapped,arguments);return r(this._wrapped,this._chain)}});h(["concat","join","slice"],function(a){var b=i[a];j.prototype[a]=function(){return r(b.apply(this._wrapped,
-arguments),this._chain)}});j.prototype.chain=function(){this._chain=!0;return this};j.prototype.value=function(){return this._wrapped}})();
diff --git a/addons/web_graph/static/lib/flotr2/lib/underscore.js b/addons/web_graph/static/lib/flotr2/lib/underscore.js
deleted file mode 100644
index 4f56013259b..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/underscore.js
+++ /dev/null
@@ -1,839 +0,0 @@
-// Underscore.js 1.1.7
-// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore is freely distributable under the MIT license.
-// Portions of Underscore are inspired or borrowed from Prototype,
-// Oliver Steele's Functional, and John Resig's Micro-Templating.
-// For all details and documentation:
-// http://documentcloud.github.com/underscore
-
-(function() {
-
- // Baseline setup
- // --------------
-
- // Establish the root object, `window` in the browser, or `global` on the server.
- var root = this;
-
- // Save the previous value of the `_` variable.
- var previousUnderscore = root._;
-
- // Establish the object that gets returned to break out of a loop iteration.
- var breaker = {};
-
- // Save bytes in the minified (but not gzipped) version:
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
-
- // Create quick reference variables for speed access to core prototypes.
- var slice = ArrayProto.slice,
- unshift = ArrayProto.unshift,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty;
-
- // All **ECMAScript 5** native function implementations that we hope to use
- // are declared here.
- var
- nativeForEach = ArrayProto.forEach,
- nativeMap = ArrayProto.map,
- nativeReduce = ArrayProto.reduce,
- nativeReduceRight = ArrayProto.reduceRight,
- nativeFilter = ArrayProto.filter,
- nativeEvery = ArrayProto.every,
- nativeSome = ArrayProto.some,
- nativeIndexOf = ArrayProto.indexOf,
- nativeLastIndexOf = ArrayProto.lastIndexOf,
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind;
-
- // Create a safe reference to the Underscore object for use below.
- var _ = function(obj) { return new wrapper(obj); };
-
- // Export the Underscore object for **CommonJS**, with backwards-compatibility
- // for the old `require()` API. If we're not in CommonJS, add `_` to the
- // global object.
- if (typeof module !== 'undefined' && module.exports) {
- module.exports = _;
- _._ = _;
- } else {
- // Exported as a string, for Closure Compiler "advanced" mode.
- root['_'] = _;
- }
-
- // Current version.
- _.VERSION = '1.1.7';
-
- // Collection Functions
- // --------------------
-
- // The cornerstone, an `each` implementation, aka `forEach`.
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
- var each = _.each = _.forEach = function(obj, iterator, context) {
- if (obj == null) return;
- if (nativeForEach && obj.forEach === nativeForEach) {
- obj.forEach(iterator, context);
- } else if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
- }
- } else {
- for (var key in obj) {
- if (hasOwnProperty.call(obj, key)) {
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
- }
- }
- }
- };
-
- // Return the results of applying the iterator to each element.
- // Delegates to **ECMAScript 5**'s native `map` if available.
- _.map = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
- each(obj, function(value, index, list) {
- results[results.length] = iterator.call(context, value, index, list);
- });
- return results;
- };
-
- // **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
- var initial = memo !== void 0;
- if (obj == null) obj = [];
- if (nativeReduce && obj.reduce === nativeReduce) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
- }
- each(obj, function(value, index, list) {
- if (!initial) {
- memo = value;
- initial = true;
- } else {
- memo = iterator.call(context, memo, value, index, list);
- }
- });
- if (!initial) throw new TypeError("Reduce of empty array with no initial value");
- return memo;
- };
-
- // The right-associative version of reduce, also known as `foldr`.
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
- if (obj == null) obj = [];
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
- if (context) iterator = _.bind(iterator, context);
- return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
- }
- var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
- return _.reduce(reversed, iterator, memo, context);
- };
-
- // Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, iterator, context) {
- var result;
- any(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) {
- result = value;
- return true;
- }
- });
- return result;
- };
-
- // Return all the elements that pass a truth test.
- // Delegates to **ECMAScript 5**'s native `filter` if available.
- // Aliased as `select`.
- _.filter = _.select = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
- each(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
-
- // Return all the elements for which a truth test fails.
- _.reject = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- each(obj, function(value, index, list) {
- if (!iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
-
- // Determine whether all of the elements match a truth test.
- // Delegates to **ECMAScript 5**'s native `every` if available.
- // Aliased as `all`.
- _.every = _.all = function(obj, iterator, context) {
- var result = true;
- if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
- each(obj, function(value, index, list) {
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
- });
- return result;
- };
-
- // Determine if at least one element in the object matches a truth test.
- // Delegates to **ECMAScript 5**'s native `some` if available.
- // Aliased as `any`.
- var any = _.some = _.any = function(obj, iterator, context) {
- iterator = iterator || _.identity;
- var result = false;
- if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
- each(obj, function(value, index, list) {
- if (result |= iterator.call(context, value, index, list)) return breaker;
- });
- return !!result;
- };
-
- // Determine if a given value is included in the array or object using `===`.
- // Aliased as `contains`.
- _.include = _.contains = function(obj, target) {
- var found = false;
- if (obj == null) return found;
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
- any(obj, function(value) {
- if (found = value === target) return true;
- });
- return found;
- };
-
- // Invoke a method (with arguments) on every item in a collection.
- _.invoke = function(obj, method) {
- var args = slice.call(arguments, 2);
- return _.map(obj, function(value) {
- return (method.call ? method || value : value[method]).apply(value, args);
- });
- };
-
- // Convenience version of a common use case of `map`: fetching a property.
- _.pluck = function(obj, key) {
- return _.map(obj, function(value){ return value[key]; });
- };
-
- // Return the maximum element or (element-based computation).
- _.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
- var result = {computed : -Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed >= result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Return the minimum element (or element-based computation).
- _.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
- var result = {computed : Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed < result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, iterator, context) {
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value : value,
- criteria : iterator.call(context, value, index, list)
- };
- }).sort(function(left, right) {
- var a = left.criteria, b = right.criteria;
- return a < b ? -1 : a > b ? 1 : 0;
- }), 'value');
- };
-
- // Groups the object's values by a criterion produced by an iterator
- _.groupBy = function(obj, iterator) {
- var result = {};
- each(obj, function(value, index) {
- var key = iterator(value, index);
- (result[key] || (result[key] = [])).push(value);
- });
- return result;
- };
-
- // Use a comparator function to figure out at what index an object should
- // be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iterator) {
- iterator || (iterator = _.identity);
- var low = 0, high = array.length;
- while (low < high) {
- var mid = (low + high) >> 1;
- iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
- }
- return low;
- };
-
- // Safely convert anything iterable into a real, live array.
- _.toArray = function(iterable) {
- if (!iterable) return [];
- if (iterable.toArray) return iterable.toArray();
- if (_.isArray(iterable)) return slice.call(iterable);
- if (_.isArguments(iterable)) return slice.call(iterable);
- return _.values(iterable);
- };
-
- // Return the number of elements in an object.
- _.size = function(obj) {
- return _.toArray(obj).length;
- };
-
- // Array Functions
- // ---------------
-
- // Get the first element of an array. Passing **n** will return the first N
- // values in the array. Aliased as `head`. The **guard** check allows it to work
- // with `_.map`.
- _.first = _.head = function(array, n, guard) {
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
- };
-
- // Returns everything but the first entry of the array. Aliased as `tail`.
- // Especially useful on the arguments object. Passing an **index** will return
- // the rest of the values in the array from that index onward. The **guard**
- // check allows it to work with `_.map`.
- _.rest = _.tail = function(array, index, guard) {
- return slice.call(array, (index == null) || guard ? 1 : index);
- };
-
- // Get the last element of an array.
- _.last = function(array) {
- return array[array.length - 1];
- };
-
- // Trim out all falsy values from an array.
- _.compact = function(array) {
- return _.filter(array, function(value){ return !!value; });
- };
-
- // Return a completely flattened version of an array.
- _.flatten = function(array) {
- return _.reduce(array, function(memo, value) {
- if (_.isArray(value)) return memo.concat(_.flatten(value));
- memo[memo.length] = value;
- return memo;
- }, []);
- };
-
- // Return a version of the array that does not contain the specified value(s).
- _.without = function(array) {
- return _.difference(array, slice.call(arguments, 1));
- };
-
- // Produce a duplicate-free version of the array. If the array has already
- // been sorted, you have the option of using a faster algorithm.
- // Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted) {
- return _.reduce(array, function(memo, el, i) {
- if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
- return memo;
- }, []);
- };
-
- // Produce an array that contains the union: each distinct element from all of
- // the passed-in arrays.
- _.union = function() {
- return _.uniq(_.flatten(arguments));
- };
-
- // Produce an array that contains every item shared between all the
- // passed-in arrays. (Aliased as "intersect" for back-compat.)
- _.intersection = _.intersect = function(array) {
- var rest = slice.call(arguments, 1);
- return _.filter(_.uniq(array), function(item) {
- return _.every(rest, function(other) {
- return _.indexOf(other, item) >= 0;
- });
- });
- };
-
- // Take the difference between one array and another.
- // Only the elements present in just the first array will remain.
- _.difference = function(array, other) {
- return _.filter(array, function(value){ return !_.include(other, value); });
- };
-
- // Zip together multiple lists into a single array -- elements that share
- // an index go together.
- _.zip = function() {
- var args = slice.call(arguments);
- var length = _.max(_.pluck(args, 'length'));
- var results = new Array(length);
- for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
- return results;
- };
-
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
- // we need this function. Return the position of the first occurrence of an
- // item in an array, or -1 if the item is not included in the array.
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
- // If the array is large and already in sort order, pass `true`
- // for **isSorted** to use binary search.
- _.indexOf = function(array, item, isSorted) {
- if (array == null) return -1;
- var i, l;
- if (isSorted) {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
- for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
- return -1;
- };
-
-
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
- _.lastIndexOf = function(array, item) {
- if (array == null) return -1;
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
- var i = array.length;
- while (i--) if (array[i] === item) return i;
- return -1;
- };
-
- // Generate an integer Array containing an arithmetic progression. A port of
- // the native Python `range()` function. See
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
- _.range = function(start, stop, step) {
- if (arguments.length <= 1) {
- stop = start || 0;
- start = 0;
- }
- step = arguments[2] || 1;
-
- var len = Math.max(Math.ceil((stop - start) / step), 0);
- var idx = 0;
- var range = new Array(len);
-
- while(idx < len) {
- range[idx++] = start;
- start += step;
- }
-
- return range;
- };
-
- // Function (ahem) Functions
- // ------------------
-
- // Create a function bound to a given object (assigning `this`, and arguments,
- // optionally). Binding with arguments is also known as `curry`.
- // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
- // We check for `func.bind` first, to fail fast when `func` is undefined.
- _.bind = function(func, obj) {
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- var args = slice.call(arguments, 2);
- return function() {
- return func.apply(obj, args.concat(slice.call(arguments)));
- };
- };
-
- // Bind all of an object's methods to that object. Useful for ensuring that
- // all callbacks defined on an object belong to it.
- _.bindAll = function(obj) {
- var funcs = slice.call(arguments, 1);
- if (funcs.length == 0) funcs = _.functions(obj);
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
- return obj;
- };
-
- // Memoize an expensive function by storing its results.
- _.memoize = function(func, hasher) {
- var memo = {};
- hasher || (hasher = _.identity);
- return function() {
- var key = hasher.apply(this, arguments);
- return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
- };
- };
-
- // Delays a function for the given number of milliseconds, and then calls
- // it with the arguments supplied.
- _.delay = function(func, wait) {
- var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(func, args); }, wait);
- };
-
- // Defers a function, scheduling it to run after the current call stack has
- // cleared.
- _.defer = function(func) {
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
- };
-
- // Internal function used to implement `_.throttle` and `_.debounce`.
- var limit = function(func, wait, debounce) {
- var timeout;
- return function() {
- var context = this, args = arguments;
- var throttler = function() {
- timeout = null;
- func.apply(context, args);
- };
- if (debounce) clearTimeout(timeout);
- if (debounce || !timeout) timeout = setTimeout(throttler, wait);
- };
- };
-
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time.
- _.throttle = function(func, wait) {
- return limit(func, wait, false);
- };
-
- // Returns a function, that, as long as it continues to be invoked, will not
- // be triggered. The function will be called after it stops being called for
- // N milliseconds.
- _.debounce = function(func, wait) {
- return limit(func, wait, true);
- };
-
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- return memo = func.apply(this, arguments);
- };
- };
-
- // Returns the first function passed as an argument to the second,
- // allowing you to adjust arguments, run code before and after, and
- // conditionally execute the original function.
- _.wrap = function(func, wrapper) {
- return function() {
- var args = [func].concat(slice.call(arguments));
- return wrapper.apply(this, args);
- };
- };
-
- // Returns a function that is the composition of a list of functions, each
- // consuming the return value of the function that follows.
- _.compose = function() {
- var funcs = slice.call(arguments);
- return function() {
- var args = slice.call(arguments);
- for (var i = funcs.length - 1; i >= 0; i--) {
- args = [funcs[i].apply(this, args)];
- }
- return args[0];
- };
- };
-
- // Returns a function that will only be executed after being called N times.
- _.after = function(times, func) {
- return function() {
- if (--times < 1) { return func.apply(this, arguments); }
- };
- };
-
-
- // Object Functions
- // ----------------
-
- // Retrieve the names of an object's properties.
- // Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = nativeKeys || function(obj) {
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
- var keys = [];
- for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
- return keys;
- };
-
- // Retrieve the values of an object's properties.
- _.values = function(obj) {
- return _.map(obj, _.identity);
- };
-
- // Return a sorted list of the function names available on the object.
- // Aliased as `methods`
- _.functions = _.methods = function(obj) {
- var names = [];
- for (var key in obj) {
- if (_.isFunction(obj[key])) names.push(key);
- }
- return names.sort();
- };
-
- // Extend a given object with all the properties in passed-in object(s).
- _.extend = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- if (source[prop] !== void 0) obj[prop] = source[prop];
- }
- });
- return obj;
- };
-
- // Fill in a given object with default properties.
- _.defaults = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- if (obj[prop] == null) obj[prop] = source[prop];
- }
- });
- return obj;
- };
-
- // Create a (shallow-cloned) duplicate of an object.
- _.clone = function(obj) {
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
- };
-
- // Invokes interceptor with the obj, and then returns obj.
- // The primary purpose of this method is to "tap into" a method chain, in
- // order to perform operations on intermediate results within the chain.
- _.tap = function(obj, interceptor) {
- interceptor(obj);
- return obj;
- };
-
- // Perform a deep comparison to check if two objects are equal.
- _.isEqual = function(a, b) {
- // Check object identity.
- if (a === b) return true;
- // Different types?
- var atype = typeof(a), btype = typeof(b);
- if (atype != btype) return false;
- // Basic equality test (watch out for coercions).
- if (a == b) return true;
- // One is falsy and the other truthy.
- if ((!a && b) || (a && !b)) return false;
- // Unwrap any wrapped objects.
- if (a._chain) a = a._wrapped;
- if (b._chain) b = b._wrapped;
- // One of them implements an isEqual()?
- if (a.isEqual) return a.isEqual(b);
- if (b.isEqual) return b.isEqual(a);
- // Check dates' integer values.
- if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
- // Both are NaN?
- if (_.isNaN(a) && _.isNaN(b)) return false;
- // Compare regular expressions.
- if (_.isRegExp(a) && _.isRegExp(b))
- return a.source === b.source &&
- a.global === b.global &&
- a.ignoreCase === b.ignoreCase &&
- a.multiline === b.multiline;
- // If a is not an object by this point, we can't handle it.
- if (atype !== 'object') return false;
- // Check for different array lengths before comparing contents.
- if (a.length && (a.length !== b.length)) return false;
- // Nothing else worked, deep compare the contents.
- var aKeys = _.keys(a), bKeys = _.keys(b);
- // Different object sizes?
- if (aKeys.length != bKeys.length) return false;
- // Recursive comparison of contents.
- for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
- return true;
- };
-
- // Is a given array or object empty?
- _.isEmpty = function(obj) {
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
- for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
- return true;
- };
-
- // Is a given value a DOM element?
- _.isElement = function(obj) {
- return !!(obj && obj.nodeType == 1);
- };
-
- // Is a given value an array?
- // Delegates to ECMA5's native Array.isArray
- _.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) === '[object Array]';
- };
-
- // Is a given variable an object?
- _.isObject = function(obj) {
- return obj === Object(obj);
- };
-
- // Is a given variable an arguments object?
- _.isArguments = function(obj) {
- return !!(obj && hasOwnProperty.call(obj, 'callee'));
- };
-
- // Is a given value a function?
- _.isFunction = function(obj) {
- return !!(obj && obj.constructor && obj.call && obj.apply);
- };
-
- // Is a given value a string?
- _.isString = function(obj) {
- return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
- };
-
- // Is a given value a number?
- _.isNumber = function(obj) {
- return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
- };
-
- // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
- // that does not equal itself.
- _.isNaN = function(obj) {
- return obj !== obj;
- };
-
- // Is a given value a boolean?
- _.isBoolean = function(obj) {
- return obj === true || obj === false;
- };
-
- // Is a given value a date?
- _.isDate = function(obj) {
- return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
- };
-
- // Is the given value a regular expression?
- _.isRegExp = function(obj) {
- return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
- };
-
- // Is a given value equal to null?
- _.isNull = function(obj) {
- return obj === null;
- };
-
- // Is a given variable undefined?
- _.isUndefined = function(obj) {
- return obj === void 0;
- };
-
- // Utility Functions
- // -----------------
-
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
- // previous owner. Returns a reference to the Underscore object.
- _.noConflict = function() {
- root._ = previousUnderscore;
- return this;
- };
-
- // Keep the identity function around for default iterators.
- _.identity = function(value) {
- return value;
- };
-
- // Run a function **n** times.
- _.times = function (n, iterator, context) {
- for (var i = 0; i < n; i++) iterator.call(context, i);
- };
-
- // Add your own custom functions to the Underscore object, ensuring that
- // they're correctly added to the OOP wrapper as well.
- _.mixin = function(obj) {
- each(_.functions(obj), function(name){
- addToWrapper(name, _[name] = obj[name]);
- });
- };
-
- // Generate a unique integer id (unique within the entire client session).
- // Useful for temporary DOM ids.
- var idCounter = 0;
- _.uniqueId = function(prefix) {
- var id = idCounter++;
- return prefix ? prefix + id : id;
- };
-
- // By default, Underscore uses ERB-style template delimiters, change the
- // following template settings to use alternative delimiters.
- _.templateSettings = {
- evaluate : /<%([\s\S]+?)%>/g,
- interpolate : /<%=([\s\S]+?)%>/g
- };
-
- // JavaScript micro-templating, similar to John Resig's implementation.
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
- // and correctly escapes quotes within interpolated code.
- _.template = function(str, data) {
- var c = _.templateSettings;
- var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
- 'with(obj||{}){__p.push(\'' +
- str.replace(/\\/g, '\\\\')
- .replace(/'/g, "\\'")
- .replace(c.interpolate, function(match, code) {
- return "'," + code.replace(/\\'/g, "'") + ",'";
- })
- .replace(c.evaluate || null, function(match, code) {
- return "');" + code.replace(/\\'/g, "'")
- .replace(/[\r\n\t]/g, ' ') + "__p.push('";
- })
- .replace(/\r/g, '\\r')
- .replace(/\n/g, '\\n')
- .replace(/\t/g, '\\t')
- + "');}return __p.join('');";
- var func = new Function('obj', tmpl);
- return data ? func(data) : func;
- };
-
- // The OOP Wrapper
- // ---------------
-
- // If Underscore is called as a function, it returns a wrapped object that
- // can be used OO-style. This wrapper holds altered versions of all the
- // underscore functions. Wrapped objects may be chained.
- var wrapper = function(obj) { this._wrapped = obj; };
-
- // Expose `wrapper.prototype` as `_.prototype`
- _.prototype = wrapper.prototype;
-
- // Helper function to continue chaining intermediate results.
- var result = function(obj, chain) {
- return chain ? _(obj).chain() : obj;
- };
-
- // A method to easily add functions to the OOP wrapper.
- var addToWrapper = function(name, func) {
- wrapper.prototype[name] = function() {
- var args = slice.call(arguments);
- unshift.call(args, this._wrapped);
- return result(func.apply(_, args), this._chain);
- };
- };
-
- // Add all of the Underscore functions to the wrapper object.
- _.mixin(_);
-
- // Add all mutator Array functions to the wrapper.
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
- var method = ArrayProto[name];
- wrapper.prototype[name] = function() {
- method.apply(this._wrapped, arguments);
- return result(this._wrapped, this._chain);
- };
- });
-
- // Add all accessor Array functions to the wrapper.
- each(['concat', 'join', 'slice'], function(name) {
- var method = ArrayProto[name];
- wrapper.prototype[name] = function() {
- return result(method.apply(this._wrapped, arguments), this._chain);
- };
- });
-
- // Start chaining a wrapped Underscore object.
- wrapper.prototype.chain = function() {
- this._chain = true;
- return this;
- };
-
- // Extracts the result from a wrapped and chained object.
- wrapper.prototype.value = function() {
- return this._wrapped;
- };
-
-})();
diff --git a/addons/web_graph/static/lib/flotr2/lib/yepnope.js b/addons/web_graph/static/lib/flotr2/lib/yepnope.js
deleted file mode 100644
index e856225343a..00000000000
--- a/addons/web_graph/static/lib/flotr2/lib/yepnope.js
+++ /dev/null
@@ -1 +0,0 @@
-/*yepnope1.0.2|WTFPL*/(function(a,b,c){function H(){var a=z;a.loader={load:G,i:0};return a}function G(a,b,c){var e=b=="c"?r:q;i=0,b=b||"j",u(a)?F(e,a,b,this.i++,d,c):(h.splice(this.i++,0,a),h.length==1&&E());return this}function F(a,c,d,g,j,l){function q(){!o&&A(n.readyState)&&(p.r=o=1,!i&&B(),n.onload=n.onreadystatechange=null,e(function(){m.removeChild(n)},0))}var n=b.createElement(a),o=0,p={t:d,s:c,e:l};n.src=n.data=c,!k&&(n.style.display="none"),n.width=n.height="0",a!="object"&&(n.type=d),n.onload=n.onreadystatechange=q,a=="img"?n.onerror=q:a=="script"&&(n.onerror=function(){p.e=p.r=1,E()}),h.splice(g,0,p),m.insertBefore(n,k?null:f),e(function(){o||(m.removeChild(n),p.r=p.e=o=1,B())},z.errorTimeout)}function E(){var a=h.shift();i=1,a?a.t?e(function(){a.t=="c"?D(a):C(a)},0):(a(),B()):i=0}function D(a){var c=b.createElement("link"),d;c.href=a.s,c.rel="stylesheet",c.type="text/css";if(!a.e&&(o||j)){var g=function(a){e(function(){if(!d)try{a.sheet.cssRules.length?(d=1,B()):g(a)}catch(b){b.code==1e3||b.message=="security"||b.message=="denied"?(d=1,e(function(){B()},0)):g(a)}},0)};g(c)}else c.onload=function(){d||(d=1,e(function(){B()},0))},a.e&&c.onload();e(function(){d||(d=1,B())},z.errorTimeout),!a.e&&f.parentNode.insertBefore(c,f)}function C(a){var c=b.createElement("script"),d;c.src=a.s,c.onreadystatechange=c.onload=function(){!d&&A(c.readyState)&&(d=1,B(),c.onload=c.onreadystatechange=null)},e(function(){d||(d=1,B())},z.errorTimeout),a.e?c.onload():f.parentNode.insertBefore(c,f)}function B(){var a=1,b=-1;while(h.length- ++b)if(h[b].s&&!(a=h[b].r))break;a&&E()}function A(a){return!a||a=="loaded"||a=="complete"}var d=b.documentElement,e=a.setTimeout,f=b.getElementsByTagName("script")[0],g={}.toString,h=[],i=0,j="MozAppearance"in d.style,k=j&&!!b.createRange().compareNode,l=j&&!k,m=k?d:f.parentNode,n=a.opera&&g.call(a.opera)=="[object Opera]",o="webkitAppearance"in d.style,p=o&&"async"in b.createElement("script"),q=j?"object":n||p?"img":"script",r=o?"img":q,s=Array.isArray||function(a){return g.call(a)=="[object Array]"},t=function(a){return Object(a)===a},u=function(a){return typeof a=="string"},v=function(a){return g.call(a)=="[object Function]"},w=[],x={},y,z;z=function(a){function h(a,b){function i(a){if(u(a))g(a,f,b,0,c);else if(t(a))for(h in a)a.hasOwnProperty(h)&&g(a[h],f,b,h,c)}var c=!!a.test,d=c?a.yep:a.nope,e=a.load||a.both,f=a.callback,h;i(d),i(e),a.complete&&b.load(a.complete)}function g(a,b,d,e,g){var h=f(a),i=h.autoCallback;if(!h.bypass){b&&(b=v(b)?b:b[a]||b[e]||b[a.split("/").pop().split("?")[0]]);if(h.instead)return h.instead(a,b,d,e,g);d.load(h.url,h.forceCSS||!h.forceJS&&/css$/.test(h.url)?"c":c,h.noexec),(v(b)||v(i))&&d.load(function(){H(),b&&b(h.origUrl,g,e),i&&i(h.origUrl,g,e)})}}function f(a){var b=a.split("!"),c=w.length,d=b.pop(),e=b.length,f={url:d,origUrl:d,prefixes:b},g,h;for(h=0;h<e;h++)g=x[b[h]],g&&(f=g(f));for(h=0;h<c;h++)f=w[h](f);return f}var b,d,e=this.yepnope.loader;if(u(a))g(a,0,e,0);else if(s(a))for(b=0;b<a.length;b++)d=a[b],u(d)?g(d,0,e,0):s(d)?z(d):t(d)&&h(d,e);else t(a)&&h(a,e)},z.addPrefix=function(a,b){x[a]=b},z.addFilter=function(a){w.push(a)},z.errorTimeout=1e4,b.readyState==null&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",y=function(){b.removeEventListener("DOMContentLoaded",y,0),b.readyState="complete"},0)),a.yepnope=H()})(this,this.document)