Added: openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/geometry.js
URL: 
http://svn.apache.org/viewvc/openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/geometry.js?rev=1791131&view=auto
==============================================================================
--- openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/geometry.js 
(added)
+++ openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/geometry.js 
Wed Apr 12 15:06:22 2017
@@ -0,0 +1,879 @@
+/**
+ * Geometries
+ * 
+ * @fileOverview Geometries
+ * @name Geometries
+ */
+
+/**
+ * This is the constructor for the default value geometry.
+ * A value geometry is what regulates mapping of the plot values to the screen 
y coordinate.
+ * If two plots share the same value geometry, they will be drawn using the 
same scale.
+ * If "min" and "max" parameters are not set, the geometry will stretch itself 
automatically
+ * so that the entire plot will be drawn without overflowing. The stretching 
happens also
+ * when a geometry is shared between multiple plots, the one with the biggest 
range will
+ * win over the others.
+ * 
+ * @constructor
+ */
+Timeplot.DefaultValueGeometry = function(params) {
+    if (!params) params = {};
+    this._id = ("id" in params) ? params.id : "g" + Math.round(Math.random() * 
1000000);
+    this._axisColor = ("axisColor" in params) ? ((typeof params.axisColor == 
"string") ? new Timeplot.Color(params.axisColor) : params.axisColor) : new 
Timeplot.Color("#606060"),
+    this._gridColor = ("gridColor" in params) ? ((typeof params.gridColor == 
"string") ? new Timeplot.Color(params.gridColor) : params.gridColor) : null,
+    this._gridLineWidth = ("gridLineWidth" in params) ? params.gridLineWidth : 
0.5;
+    this._axisLabelsPlacement = ("axisLabelsPlacement" in params) ? 
params.axisLabelsPlacement : "right";
+    this._gridSpacing = ("gridSpacing" in params) ? params.gridStep : 50;
+    this._gridType = ("gridType" in params) ? params.gridType : "short";
+    this._gridShortSize = ("gridShortSize" in params) ? params.gridShortSize : 
10;
+    this._minValue = ("min" in params) ? params.min : null;
+    this._maxValue = ("max" in params) ? params.max : null;
+    this._linMap = {
+        direct: function(v) {
+            return v;
+        },
+        inverse: function(y) {
+            return y;
+        }
+    }
+    this._map = this._linMap;
+    this._labels = [];
+    this._grid = [];
+}
+
+Timeplot.DefaultValueGeometry.prototype = {
+
+    /**
+     * Since geometries can be reused across timeplots, we need to call this 
function
+     * before we can paint using this geometry.
+     */
+    setTimeplot: function(timeplot) {
+        this._timeplot = timeplot;
+        this._canvas = timeplot.getCanvas();
+        this.reset();
+    },
+
+    /**
+     * Called by all the plot layers this geometry is associated with
+     * to update the value range. Unless min/max values are specified
+     * in the parameters, the biggest value range will be used.
+     */
+    setRange: function(range) {
+        if ((this._minValue == null) || ((this._minValue != null) && 
(range.min < this._minValue))) {
+            this._minValue = range.min;
+        }
+        if ((this._maxValue == null) || ((this._maxValue != null) && 
(range.max * 1.05 > this._maxValue))) {
+            this._maxValue = range.max * 1.05; // get a little more head room 
to avoid hitting the ceiling
+        }
+
+        this._updateMappedValues();
+
+        if (!(this._minValue == 0 && this._maxValue == 0)) {
+            this._grid = this._calculateGrid();
+        }
+    },
+
+    /**
+     * Called after changing ranges or canvas size to reset the grid values
+     */
+    reset: function() {
+        this._clearLabels();
+        this._updateMappedValues();
+        this._grid = this._calculateGrid();
+    },
+
+    /**
+     * Map the given value to a y screen coordinate.
+     */
+    toScreen: function(value) {
+        if (this._canvas && this._maxValue) {
+            var v = value - this._minValue;
+            return this._canvas.height * (this._map.direct(v)) / 
this._mappedRange;
+        } else {
+            return -50;
+        }
+    },
+
+    /**
+     * Map the given y screen coordinate to a value
+     */
+    fromScreen: function(y) {
+        if (this._canvas) {
+            return this._map.inverse(this._mappedRange * y / 
this._canvas.height) + this._minValue;
+        } else {
+            return 0;
+        }
+    },
+
+    /**
+     * Each geometry is also a painter and paints the value grid and grid 
labels.
+     */
+    paint: function() {
+        if (this._timeplot) {
+            var ctx = this._canvas.getContext('2d');
+    
+            ctx.lineJoin = 'miter';
+    
+            // paint grid
+            if (this._gridColor) {        
+                var gridGradient = 
ctx.createLinearGradient(0,0,0,this._canvas.height);
+                gridGradient.addColorStop(0, this._gridColor.toHexString());
+                gridGradient.addColorStop(0.3, this._gridColor.toHexString());
+                gridGradient.addColorStop(1, "rgba(255,255,255,0.5)");
+
+                ctx.lineWidth = this._gridLineWidth;
+                ctx.strokeStyle = gridGradient;
+    
+                for (var i = 0; i < this._grid.length; i++) {
+                    var tick = this._grid[i];
+                    var y = Math.floor(tick.y) + 0.5;
+                    if (typeof tick.label != "undefined") {
+                        if (this._axisLabelsPlacement == "left") {
+                            var div = this._timeplot.putText(this._id + "-" + 
i, tick.label,"timeplot-grid-label",{
+                                left: 4,
+                                bottom: y + 2,
+                                color: this._gridColor.toHexString(),
+                                visibility: "hidden"
+                            });
+                            this._labels.push(div);
+                        } else if (this._axisLabelsPlacement == "right") {
+                            var div = this._timeplot.putText(this._id + "-" + 
i, tick.label, "timeplot-grid-label",{
+                                right: 4,
+                                bottom: y + 2,
+                                color: this._gridColor.toHexString(),
+                                visibility: "hidden"
+                            });
+                            this._labels.push(div);
+                        }
+                        if (y + div.clientHeight < this._canvas.height + 10) {
+                            div.style.visibility = "visible"; // avoid the 
labels that would overflow
+                        }
+                    }
+
+                    // draw grid
+                    ctx.beginPath();
+                    if (this._gridType == "long" || tick.label == 0) {
+                        ctx.moveTo(0, y);
+                        ctx.lineTo(this._canvas.width, y);
+                    } else if (this._gridType == "short") {
+                        if (this._axisLabelsPlacement == "left") {
+                            ctx.moveTo(0, y);
+                            ctx.lineTo(this._gridShortSize, y);
+                        } else if (this._axisLabelsPlacement == "right") {
+                            ctx.moveTo(this._canvas.width, y);
+                            ctx.lineTo(this._canvas.width - 
this._gridShortSize, y);
+                        }                       
+                    }
+                    ctx.stroke();
+                }
+            }
+        
+            // paint axis
+            var axisGradient = 
ctx.createLinearGradient(0,0,0,this._canvas.height);
+            axisGradient.addColorStop(0, this._axisColor.toString());
+            axisGradient.addColorStop(0.5, this._axisColor.toString());
+            axisGradient.addColorStop(1, "rgba(255,255,255,0.5)");
+            
+            ctx.lineWidth = 1;
+            ctx.strokeStyle = axisGradient;
+    
+            // left axis
+            ctx.beginPath();
+            ctx.moveTo(0,this._canvas.height);
+            ctx.lineTo(0,0);
+            ctx.stroke();
+            
+            // right axis
+            ctx.beginPath();
+            ctx.moveTo(this._canvas.width,0);
+            ctx.lineTo(this._canvas.width,this._canvas.height);
+            ctx.stroke();
+        }
+    },
+    
+    /**
+     * Removes all the labels that were added by this geometry
+     */
+    _clearLabels: function() {
+        for (var i = 0; i < this._labels.length; i++) {
+            var l = this._labels[i];
+            var parent = l.parentNode;
+            if (parent) parent.removeChild(l);
+        }
+    },
+    
+    /*
+     * This function calculates the grid spacing that it will be used 
+     * by this geometry to draw the grid in order to reduce clutter. 
+     */
+    _calculateGrid: function() {
+        var grid = [];
+        
+        if (!this._canvas || this._valueRange == 0) return grid;
+                
+        var power = 0;
+        if (this._valueRange > 1) {
+            while (Math.pow(10,power) < this._valueRange) {
+                power++;
+            }
+            power--;
+        } else {
+            while (Math.pow(10,power) > this._valueRange) {
+                power--;
+            }
+        }
+
+        var unit = Math.pow(10,power);
+        var inc = unit;
+        while (true) {
+            var dy = this.toScreen(this._minValue + inc);
+
+            while (dy < this._gridSpacing) {
+                inc += unit;
+                dy = this.toScreen(this._minValue + inc);
+            }
+
+            if (dy > 2 * this._gridSpacing) { // grids are too spaced out
+                unit /= 10;
+                inc = unit;
+            } else {
+                break;
+            }
+        }
+        
+        var v = 0;
+        var y = this.toScreen(v);
+        if (this._minValue >= 0) {
+            while (y < this._canvas.height) {
+                if (y > 0) {
+                    grid.push({ y: y, label: v });
+                }
+                v += inc;
+                y = this.toScreen(v);
+            }
+        } else if (this._maxValue <= 0) {
+            while (y > 0) {
+                if (y < this._canvas.height) {
+                    grid.push({ y: y, label: v });
+                }
+                v -= inc;
+                y = this.toScreen(v);
+            }
+        } else {
+            while (y < this._canvas.height) {
+                if (y > 0) {
+                    grid.push({ y: y, label: v });
+                }
+                v += inc;
+                y = this.toScreen(v);
+            }
+            v = -inc;
+            y = this.toScreen(v);
+            while (y > 0) {
+                if (y < this._canvas.height) {
+                    grid.push({ y: y, label: v });
+                }
+                v -= inc;
+                y = this.toScreen(v);
+            }
+        }
+        
+        return grid;
+    },
+
+    /*
+     * Update the values that are used by the paint function so that
+     * we don't have to calculate them at every repaint.
+     */
+    _updateMappedValues: function() {
+        this._valueRange = Math.abs(this._maxValue - this._minValue);
+        this._mappedRange = this._map.direct(this._valueRange);
+    }
+    
+}
+
+// --------------------------------------------------
+
+/**
+ * This is the constructor for a Logarithmic value geometry, which
+ * is useful when plots have values in different magnitudes but 
+ * exhibit similar trends and such trends want to be shown on the same
+ * plot (here a cartesian geometry would make the small magnitudes 
+ * disappear).
+ * 
+ * NOTE: this class extends Timeplot.DefaultValueGeometry and inherits
+ * all of the methods of that class. So refer to that class. 
+ * 
+ * @constructor
+ */
+Timeplot.LogarithmicValueGeometry = function(params) {
+    Timeplot.DefaultValueGeometry.apply(this, arguments);
+    this._logMap = {
+        direct: function(v) {
+            return Math.log(v + 1) / Math.log(10);
+        },
+        inverse: function(y) {
+            return Math.exp(Math.log(10) * y) - 1;
+        }
+    }
+    this._mode = "log";
+    this._map = this._logMap;
+    this._calculateGrid = this._logarithmicCalculateGrid;
+};
+
+Timeplot.LogarithmicValueGeometry.prototype._linearCalculateGrid = 
Timeplot.DefaultValueGeometry.prototype._calculateGrid;
+
+Object.extend(Timeplot.LogarithmicValueGeometry.prototype,Timeplot.DefaultValueGeometry.prototype);
+
+/*
+ * This function calculates the grid spacing that it will be used 
+ * by this geometry to draw the grid in order to reduce clutter. 
+ */
+Timeplot.LogarithmicValueGeometry.prototype._logarithmicCalculateGrid = 
function() {
+    var grid = [];
+    
+    if (!this._canvas || this._valueRange == 0) return grid;
+
+    var v = 1;
+    var y = this.toScreen(v);
+    while (y < this._canvas.height || isNaN(y)) {
+        if (y > 0) {
+            grid.push({ y: y, label: v });
+        }
+        v *= 10;
+        y = this.toScreen(v);
+    }
+    
+    return grid;
+};
+
+/**
+ * Turn the logarithmic scaling off. 
+ */
+Timeplot.LogarithmicValueGeometry.prototype.actLinear = function() {
+    this._mode = "lin";
+    this._map = this._linMap;
+    this._calculateGrid = this._linearCalculateGrid;
+    this.reset();
+}
+
+/**
+ * Turn the logarithmic scaling on. 
+ */
+Timeplot.LogarithmicValueGeometry.prototype.actLogarithmic = function() {
+    this._mode = "log";
+    this._map = this._logMap;
+    this._calculateGrid = this._logarithmicCalculateGrid;
+    this.reset();
+}
+
+/**
+ * Toggle logarithmic scaling seeting it to on if off and viceversa. 
+ */
+Timeplot.LogarithmicValueGeometry.prototype.toggle = function() {
+    if (this._mode == "log") {
+        this.actLinear();
+    } else {
+        this.actLogarithmic();
+    }
+}
+
+// -----------------------------------------------------
+
+/**
+ * This is the constructor for the default time geometry.
+ * 
+ * @constructor
+ */
+Timeplot.DefaultTimeGeometry = function(params) {
+    if (!params) params = {};
+    this._id = ("id" in params) ? params.id : "g" + Math.round(Math.random() * 
1000000);
+    this._locale = ("locale" in params) ? params.locale : "en";
+    this._timeZone = ("timeZone" in params) ? params.timeZone : 
SimileAjax.DateTime.getTimezone();
+    this._labeler = ("labeller" in params) ? params.labeller : null;
+    this._axisColor = ("axisColor" in params) ? ((params.axisColor == 
"string") ? new Timeplot.Color(params.axisColor) : params.axisColor) : new 
Timeplot.Color("#606060"),
+    this._gridColor = ("gridColor" in params) ? ((params.gridColor == 
"string") ? new Timeplot.Color(params.gridColor) : params.gridColor) : null,
+    this._gridLineWidth = ("gridLineWidth" in params) ? params.gridLineWidth : 
0.5;
+    this._axisLabelsPlacement = ("axisLabelsPlacement" in params) ? 
params.axisLabelsPlacement : "bottom";
+    this._gridStep = ("gridStep" in params) ? params.gridStep : 100;
+    this._gridStepRange = ("gridStepRange" in params) ? params.gridStepRange : 
20;
+    this._min = ("min" in params) ? params.min : null;
+    this._max = ("max" in params) ? params.max : null;
+    this._timeValuePosition =("timeValuePosition" in params) ? 
params.timeValuePosition : "bottom";
+    this._unit = ("unit" in params) ? params.unit : Timeline.NativeDateUnit;
+    this._linMap = {
+        direct: function(t) {
+            return t;
+        },
+        inverse: function(x) {
+            return x;
+        }
+    }
+    this._map = this._linMap;
+    if (!this._labeler)
+        this._labeler = this._unit.createLabeller(this._locale, 
this._timeZone);
+    var dateParser = this._unit.getParser("iso8601");
+    if (this._min && !this._min.getTime) {
+        this._min = dateParser(this._min);
+    }
+    if (this._max && !this._max.getTime) {
+        this._max = dateParser(this._max);
+    }
+    this._labels = [];
+    this._grid = [];
+}
+
+Timeplot.DefaultTimeGeometry.prototype = {
+
+    /**
+     * Since geometries can be reused across timeplots, we need to call this 
function
+     * before we can paint using this geometry.
+     */
+    setTimeplot: function(timeplot) {
+        this._timeplot = timeplot;
+        this._canvas = timeplot.getCanvas();
+        this.reset();
+    },
+
+    /**
+     * Called by all the plot layers this geometry is associated with
+     * to update the time range. Unless min/max values are specified
+     * in the parameters, the biggest range will be used.
+     */
+    setRange: function(range) {
+        if (this._min) {
+            this._earliestDate = this._min;
+        } else if (range.earliestDate && ((this._earliestDate == null) || 
((this._earliestDate != null) && (range.earliestDate.getTime() < 
this._earliestDate.getTime())))) {
+            this._earliestDate = range.earliestDate;
+        }
+        
+        if (this._max) {
+            this._latestDate = this._max;
+        } else if (range.latestDate && ((this._latestDate == null) || 
((this._latestDate != null) && (range.latestDate.getTime() > 
this._latestDate.getTime())))) {
+            this._latestDate = range.latestDate;
+        }
+
+        if (!this._earliestDate && !this._latestDate) {
+            this._grid = [];
+        } else {
+            this.reset(); 
+        }
+    },
+    
+    /**
+     * Called after changing ranges or canvas size to reset the grid values
+     */
+    reset: function() {
+        this._updateMappedValues();
+        if (this._canvas) this._grid = this._calculateGrid();
+    },
+    
+    /**
+     * Map the given date to a x screen coordinate.
+     */
+    toScreen: function(time) {
+        if (this._canvas && this._latestDate) {
+            var t = time - this._earliestDate.getTime();
+            var fraction = (this._mappedPeriod > 0) ? this._map.direct(t) / 
this._mappedPeriod : 0;
+            return this._canvas.width * fraction;
+        } else {
+            return -50;
+        } 
+    },
+
+    /**
+     * Map the given x screen coordinate to a date.
+     */
+    fromScreen: function(x) {
+        if (this._canvas) {
+            return this._map.inverse(this._mappedPeriod * x / 
this._canvas.width) + this._earliestDate.getTime();
+        } else {
+            return 0;
+        } 
+    },
+    
+    /**
+     * Get a period (in milliseconds) this time geometry spans.
+     */
+    getPeriod: function() {
+        return this._period;
+    },
+    
+    /**
+     * Return the labeler that has been associated with this time geometry
+     */
+    getLabeler: function() {
+        return this._labeler;
+    },
+
+    /**
+     * Return the time unit associated with this time geometry
+     */
+    getUnit: function() {
+        return this._unit;
+    },
+
+   /**
+    * Each geometry is also a painter and paints the value grid and grid 
labels.
+    */
+    paint: function() {
+        if (this._canvas) {
+            var unit = this._unit;
+            var ctx = this._canvas.getContext('2d');
+    
+            var gradient = ctx.createLinearGradient(0,0,0,this._canvas.height);
+    
+            ctx.strokeStyle = gradient;
+            ctx.lineWidth = this._gridLineWidth;
+            ctx.lineJoin = 'miter';
+    
+            // paint grid
+            if (this._gridColor) {        
+                gradient.addColorStop(0, this._gridColor.toString());
+                gradient.addColorStop(1, "rgba(255,255,255,0.9)");
+    
+                for (var i = 0; i < this._grid.length; i++) {
+                    var tick = this._grid[i];
+                    var x = Math.floor(tick.x) + 0.5;
+                    if (this._axisLabelsPlacement == "top") {
+                        var div = this._timeplot.putText(this._id + "-" + i, 
tick.label,"timeplot-grid-label",{
+                            left: x + 4,
+                            top: 2,
+                            visibility: "hidden"
+                        });
+                        this._labels.push(div);
+                    } else if (this._axisLabelsPlacement == "bottom") {
+                        var div = this._timeplot.putText(this._id + "-" + i, 
tick.label, "timeplot-grid-label",{
+                            left: x + 4,
+                            bottom: 2,
+                            visibility: "hidden"
+                        });
+                        this._labels.push(div);
+                    }
+                    if (x + div.clientWidth < this._canvas.width + 10) {
+                        div.style.visibility = "visible"; // avoid the labels 
that would overflow
+                    }
+
+                    // draw separator
+                    ctx.beginPath();
+                    ctx.moveTo(x,0);
+                    ctx.lineTo(x,this._canvas.height);
+                    ctx.stroke();
+                }
+            }
+    
+            // paint axis
+            gradient.addColorStop(0, this._axisColor.toString());
+            gradient.addColorStop(1, "rgba(255,255,255,0.5)");
+            
+            ctx.lineWidth = 1;
+            gradient.addColorStop(0, this._axisColor.toString());
+    
+            ctx.beginPath();
+            ctx.moveTo(0,0);
+            ctx.lineTo(this._canvas.width,0);
+            ctx.stroke();
+        }
+    },
+    
+    /*
+     * This function calculates the grid spacing that it will be used 
+     * by this geometry to draw the grid in order to reduce clutter. 
+     */
+    _calculateGrid: function() {
+        var grid = [];
+        
+        var time = SimileAjax.DateTime;
+        var u = this._unit;
+        var p = this._period;
+        
+        if (p == 0) return grid;
+        
+        // find the time units nearest to the time period
+        if (p > time.gregorianUnitLengths[time.MILLENNIUM]) {
+            unit = time.MILLENNIUM; 
+        } else {
+            for (var unit = time.MILLENNIUM; unit > 0; unit--) {
+                if (time.gregorianUnitLengths[unit-1] <= p && p < 
time.gregorianUnitLengths[unit]) {
+                    unit--;
+                    break;
+                }
+            }
+        }
+
+        var t = u.cloneValue(this._earliestDate);
+
+        do {
+            time.roundDownToInterval(t, unit, this._timeZone, 1, 0);
+            var x = this.toScreen(u.toNumber(t));
+            switch (unit) {
+                case time.SECOND:
+                  var l = t.toLocaleTimeString();
+                  break;
+                case time.MINUTE:
+                  var m = t.getMinutes();
+                  var l = t.getHours() + ":" + ((m < 10) ? "0" : "") + m;
+                  break;
+                case time.HOUR:
+                  var l = t.getHours() + ":00";
+                  break;
+                case time.DAY:
+                case time.WEEK:
+                case time.MONTH:
+                  var l = t.toLocaleDateString();
+                  break;  
+                case time.YEAR:
+                case time.DECADE:
+                case time.CENTURY:
+                case time.MILLENNIUM:
+                  var l = t.getUTCFullYear();
+                  break;
+            }
+            if (x > 0) { 
+                grid.push({ x: x, label: l });
+            }
+            time.incrementByInterval(t, unit, this._timeZone);
+        } while (t.getTime() < this._latestDate.getTime());
+        
+        return grid;
+    },
+
+    /*
+     * Clear labels generated by this time geometry.
+     */
+    _clearLabels: function() {
+        for (var i = 0; i < this._labels.length; i++) {
+            var l = this._labels[i];
+            var parent = l.parentNode;
+            if (parent) parent.removeChild(l);
+        }
+    },
+        
+    /*
+     * Update the values that are used by the paint function so that
+     * we don't have to calculate them at every repaint.
+     */
+    _updateMappedValues: function() {
+        if (this._latestDate && this._earliestDate) {
+            this._period = this._latestDate.getTime() - 
this._earliestDate.getTime();
+            this._mappedPeriod = this._map.direct(this._period);
+        } else {
+            this._period = 0;
+            this._mappedPeriod = 0;
+        }
+    }
+    
+}
+
+// --------------------------------------------------------------
+
+/**
+ * This is the constructor for the magnifying time geometry.
+ * Users can interact with this geometry and 'magnify' certain areas of the
+ * plot to see the plot enlarged and resolve details that would otherwise
+ * get lost or cluttered with a linear time geometry.
+ * 
+ * @constructor
+ */
+Timeplot.MagnifyingTimeGeometry = function(params) {
+    Timeplot.DefaultTimeGeometry.apply(this, arguments);
+        
+    var g = this;
+    this._MagnifyingMap = {
+        direct: function(t) {
+            if (t < g._leftTimeMargin) {
+                var x = t * g._leftRate;
+            } else if ( g._leftTimeMargin < t && t < g._rightTimeMargin ) {
+                var x = t * g._expandedRate + g._expandedTimeTranslation;
+            } else {
+                var x = t * g._rightRate + g._rightTimeTranslation;
+            }
+            return x;
+        },
+        inverse: function(x) {
+            if (x < g._leftScreenMargin) {
+                var t = x / g._leftRate;
+            } else if ( g._leftScreenMargin < x && x < g._rightScreenMargin ) {
+                var t = x / g._expandedRate + g._expandedScreenTranslation;
+            } else {
+                var t = x / g._rightRate + g._rightScreenTranslation;
+            }
+            return t;
+        }
+    }
+
+    this._mode = "lin";
+    this._map = this._linMap;
+};
+
+Object.extend(Timeplot.MagnifyingTimeGeometry.prototype,Timeplot.DefaultTimeGeometry.prototype);
+
+/**
+ * Initialize this geometry associating it with the given timeplot and 
+ * register the geometry event handlers to the timeplot so that it can
+ * interact with the user.
+ */
+Timeplot.MagnifyingTimeGeometry.prototype.initialize = function(timeplot) {
+    Timeplot.DefaultTimeGeometry.prototype.initialize.apply(this, arguments);
+
+    if (!this._lens) {
+        this._lens = this._timeplot.putDiv("lens","timeplot-lens");
+    }
+
+    var period = 1000 * 60 * 60 * 24 * 30; // a month in the magnifying lens
+
+    var geometry = this;
+    
+    var magnifyWith = function(lens) {
+        var aperture = lens.clientWidth;
+        var loc = geometry._timeplot.locate(lens);
+        geometry.setMagnifyingParams(loc.x + aperture / 2, aperture, period);
+        geometry.actMagnifying();
+        geometry._timeplot.paint();
+    }
+    
+    var canvasMouseDown = function(elmt, evt, target) {
+        geometry._canvas.startCoords = 
SimileAjax.DOM.getEventRelativeCoordinates(evt,elmt);
+        geometry._canvas.pressed = true;
+    }
+    
+    var canvasMouseUp = function(elmt, evt, target) {
+        geometry._canvas.pressed = false;
+        var coords = SimileAjax.DOM.getEventRelativeCoordinates(evt,elmt);
+        if (Timeplot.Math.isClose(coords,geometry._canvas.startCoords,5)) {
+            geometry._lens.style.display = "none";
+            geometry.actLinear();
+            geometry._timeplot.paint();
+        } else {
+            geometry._lens.style.cursor = "move";
+            magnifyWith(geometry._lens);
+        }
+    }
+
+    var canvasMouseMove = function(elmt, evt, target) {
+        if (geometry._canvas.pressed) {
+            var coords = SimileAjax.DOM.getEventRelativeCoordinates(evt,elmt);
+            if (coords.x < 0) coords.x = 0;
+            if (coords.x > geometry._canvas.width) coords.x = 
geometry._canvas.width;
+            geometry._timeplot.placeDiv(geometry._lens, {
+                left: geometry._canvas.startCoords.x,
+                width: coords.x - geometry._canvas.startCoords.x,
+                bottom: 0,
+                height: geometry._canvas.height,
+                display: "block"
+            });
+        }
+    }
+
+    var lensMouseDown = function(elmt, evt, target) {
+        geometry._lens.startCoords = 
SimileAjax.DOM.getEventRelativeCoordinates(evt,elmt);;
+        geometry._lens.pressed = true; 
+    }
+    
+    var lensMouseUp = function(elmt, evt, target) {
+        geometry._lens.pressed = false;
+    }
+    
+    var lensMouseMove = function(elmt, evt, target) {
+        if (geometry._lens.pressed) {
+            var coords = SimileAjax.DOM.getEventRelativeCoordinates(evt,elmt);
+            var lens = geometry._lens;
+            var left = lens.offsetLeft + coords.x - lens.startCoords.x;
+            if (left < geometry._timeplot._paddingX) left = 
geometry._timeplot._paddingX;
+            if (left + lens.clientWidth > geometry._canvas.width - 
geometry._timeplot._paddingX) left = geometry._canvas.width - lens.clientWidth 
+ geometry._timeplot._paddingX;
+            lens.style.left = left;
+            magnifyWith(lens);
+        }
+    }
+    
+    if (!this._canvas.instrumented) {
+        SimileAjax.DOM.registerEvent(this._canvas, "mousedown", 
canvasMouseDown);
+        SimileAjax.DOM.registerEvent(this._canvas, "mousemove", 
canvasMouseMove);
+        SimileAjax.DOM.registerEvent(this._canvas, "mouseup"  , canvasMouseUp);
+        SimileAjax.DOM.registerEvent(this._canvas, "mouseup"  , lensMouseUp);
+        this._canvas.instrumented = true;
+    }
+    
+    if (!this._lens.instrumented) {
+        SimileAjax.DOM.registerEvent(this._lens, "mousedown", lensMouseDown);
+        SimileAjax.DOM.registerEvent(this._lens, "mousemove", lensMouseMove);
+        SimileAjax.DOM.registerEvent(this._lens, "mouseup"  , lensMouseUp);
+        SimileAjax.DOM.registerEvent(this._lens, "mouseup"  , canvasMouseUp);
+        this._lens.instrumented = true;
+    }
+}
+
+/**
+ * Set the Magnifying parameters. c is the location in pixels where the 
Magnifying
+ * center should be located in the timeplot, a is the aperture in pixel of
+ * the Magnifying and b is the time period in milliseconds that the Magnifying 
+ * should span.
+ */
+Timeplot.MagnifyingTimeGeometry.prototype.setMagnifyingParams = 
function(c,a,b) {
+    a = a / 2;
+    b = b / 2;
+
+    var w = this._canvas.width;
+    var d = this._period;
+
+    if (c < 0) c = 0;
+    if (c > w) c = w;
+    
+    if (c - a < 0) a = c;
+    if (c + a > w) a = w - c;
+    
+    var ct = this.fromScreen(c) - this._earliestDate.getTime();
+    if (ct - b < 0) b = ct;
+    if (ct + b > d) b = d - ct;
+
+    this._centerX = c;
+    this._centerTime = ct;
+    this._aperture = a;
+    this._aperturePeriod = b;
+    
+    this._leftScreenMargin = this._centerX - this._aperture;
+    this._rightScreenMargin = this._centerX + this._aperture;
+    this._leftTimeMargin = this._centerTime - this._aperturePeriod;
+    this._rightTimeMargin = this._centerTime + this._aperturePeriod;
+        
+    this._leftRate = (c - a) / (ct - b);
+    this._expandedRate = a / b;
+    this._rightRate = (w - c - a) / (d - ct - b);
+
+    this._expandedTimeTranslation = this._centerX - this._centerTime * 
this._expandedRate; 
+    this._expandedScreenTranslation = this._centerTime - this._centerX / 
this._expandedRate;
+    this._rightTimeTranslation = (c + a) - (ct + b) * this._rightRate;
+    this._rightScreenTranslation = (ct + b) - (c + a) / this._rightRate;
+
+    this._updateMappedValues();
+}
+
+/*
+ * Turn magnification off.
+ */
+Timeplot.MagnifyingTimeGeometry.prototype.actLinear = function() {
+    this._mode = "lin";
+    this._map = this._linMap;
+    this.reset();
+}
+
+/*
+ * Turn magnification on.
+ */
+Timeplot.MagnifyingTimeGeometry.prototype.actMagnifying = function() {
+    this._mode = "Magnifying";
+    this._map = this._MagnifyingMap;
+    this.reset();
+}
+
+/*
+ * Toggle magnification.
+ */
+Timeplot.MagnifyingTimeGeometry.prototype.toggle = function() {
+    if (this._mode == "Magnifying") {
+        this.actLinear();
+    } else {
+        this.actMagnifying();
+    }
+}
+

Added: openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/math.js
URL: 
http://svn.apache.org/viewvc/openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/math.js?rev=1791131&view=auto
==============================================================================
--- openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/math.js (added)
+++ openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/math.js Wed 
Apr 12 15:06:22 2017
@@ -0,0 +1,193 @@
+/**
+ * Math Utility functions
+ * 
+ * @fileOverview Math Utility functions
+ * @name Math
+ */
+
+Timeplot.Math = { 
+
+    /**
+     * Evaluates the range (min and max values) of the given array
+     */
+    range: function(f) {
+        var F = f.length;
+        var min = Number.MAX_VALUE;
+        var max = Number.MIN_VALUE;
+
+        for (var t = 0; t < F; t++) {
+            var value = f[t];
+            if (value < min) {
+                min = value;
+            }
+            if (value > max) {
+                max = value;
+            }    
+        }
+
+        return {
+            min: min,
+            max: max
+        }
+    },
+
+    /**
+     * Evaluates the windows average of a given array based on the
+     * given window size
+     */
+    movingAverage: function(f, size) {
+        var F = f.length;
+        var g = new Array(F);
+        for (var n = 0; n < F; n++) {
+            var value = 0;
+            for (var m = n - size; m < n + size; m++) {
+                if (m < 0) {
+                    var v = f[0];
+                } else if (m >= F) {
+                    var v = g[n-1];
+                } else {
+                    var v = f[m];
+                }
+                value += v;
+            }
+            g[n] = value / (2 * size);
+        }
+        return g;
+    },
+
+    /**
+     * Returns an array with the integral of the given array
+     */
+    integral: function(f) {
+        var F = f.length;
+
+        var g = new Array(F);
+        var sum = 0;
+
+        for (var t = 0; t < F; t++) {
+           sum += f[t];
+           g[t] = sum;  
+        }
+
+        return g;
+    },
+
+    /**
+     * Normalizes an array so that its complete integral is 1.
+     * This is useful to obtain arrays that preserve the overall
+     * integral of a convolution. 
+     */
+    normalize: function(f) {
+        var F = f.length;
+        var sum = 0.0;
+
+        for (var t = 0; t < F; t++) {
+            sum += f[t];
+        }
+
+        for (var t = 0; t < F; t++) {
+            f[t] /= sum;
+        }
+
+        return f;
+    },
+
+    /**
+     * Calculates the convolution between two arrays
+     */
+    convolution: function(f,g) {
+        var F = f.length;
+        var G = g.length;
+
+        var c = new Array(F);
+
+        for (var m = 0; m < F; m++) {
+            var r = 0;
+            var end = (m + G < F) ? m + G : F;
+            for (var n = m; n < end; n++) {
+                var a = f[n - G];
+                var b = g[n - m];
+                r += a * b;
+            }
+            c[m] = r;
+        }
+
+        return c;
+    },
+
+    // ------ Array generators 
------------------------------------------------- 
+    // Functions that generate arrays based on mathematical functions
+    // Normally these are used to produce operators by convolving them with 
the input array
+    // The returned arrays have the property of having 
+
+    /**
+     * Generate the heavyside step function of given size
+     */
+    heavyside: function(size) {
+        var f =  new Array(size);
+        var value = 1 / size;
+        for (var t = 0; t < size; t++) {
+            f[t] = value;
+        }
+        return f;
+    },
+
+    /**
+     * Generate the gaussian function so that at the given 'size' it has value 
'threshold'
+     * and make sure its integral is one.
+     */
+    gaussian: function(size, threshold) {
+        with (Math) {
+            var radius = size / 2;
+            var variance = radius * radius / log(threshold); 
+            var g = new Array(size);
+            for (var t = 0; t < size; t++) {
+                var l = t - radius;
+                g[t] = exp(-variance * l * l);
+            }
+        }
+
+        return this.normalize(g);
+    },
+
+    // ---- Utility Methods --------------------------------------------------
+
+    /**
+     * Return x with n significant figures 
+     */
+    round: function(x,n) {
+        with (Math) {
+            if (abs(x) > 1) {
+                var l = floor(log(x)/log(10));
+                var d = round(exp((l-n+1)*log(10)));
+                var y = round(round(x / d) * d);
+                return y;
+            } else {
+                log("FIXME(SM): still to implement for 0 < abs(x) < 1");
+                return x;
+            }
+        }
+    },
+    
+    /**
+     * Return the hyperbolic tangent of x
+     */
+    tanh: function(x) {
+        if (x > 5) {
+            return 1;
+        } else if (x < 5) {
+            return -1;
+        } else {
+            var expx2 = Math.exp(2 * x);
+            return (expx2 - 1) / (expx2 + 1);
+        }
+    },
+    
+    /** 
+     * Returns true if |a.x - b.x| < value && | a.y - b.y | < value
+     */
+    isClose: function(a,b,value) {
+        return (a && b && Math.abs(a.x - b.x) < value && Math.abs(a.y - b.y) < 
value);
+    }
+
+}
\ No newline at end of file

Added: openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/plot.js
URL: 
http://svn.apache.org/viewvc/openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/plot.js?rev=1791131&view=auto
==============================================================================
--- openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/plot.js (added)
+++ openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/plot.js Wed 
Apr 12 15:06:22 2017
@@ -0,0 +1,400 @@
+/**
+ * Plot Layer
+ * 
+ * @fileOverview Plot Layer
+ * @name Plot
+ */
+ 
+/**
+ * A plot layer is the main building block for timeplots and it's the object
+ * that is responsible for painting the plot itself. Each plot needs to have
+ * a time geometry, either a DataSource (for time series
+ * plots) or an EventSource (for event plots) and a value geometry in case 
+ * of time series plots. Such parameters are passed along
+ * in the 'plotInfo' map.
+ * 
+ * @constructor
+ */
+Timeplot.Plot = function(timeplot, plotInfo) {
+    this._timeplot = timeplot;
+    this._canvas = timeplot.getCanvas();
+    this._plotInfo = plotInfo;
+    this._id = plotInfo.id;
+    this._timeGeometry = plotInfo.timeGeometry;
+    this._valueGeometry = plotInfo.valueGeometry;
+    this._theme = new Timeline.getDefaultTheme();
+    this._dataSource = plotInfo.dataSource;
+    this._eventSource = plotInfo.eventSource;
+    this._bubble = null;
+};
+
+Timeplot.Plot.prototype = {
+    
+    /**
+     * Initialize the plot layer
+     */
+    initialize: function() {
+        if (this._dataSource && this._dataSource.getValue) {
+            this._timeFlag = 
this._timeplot.putDiv("timeflag","timeplot-timeflag");
+            this._valueFlag = this._timeplot.putDiv(this._id + 
"valueflag","timeplot-valueflag");
+            this._valueFlagLineLeft = this._timeplot.putDiv(this._id + 
"valueflagLineLeft","timeplot-valueflag-line");
+            this._valueFlagLineRight = this._timeplot.putDiv(this._id + 
"valueflagLineRight","timeplot-valueflag-line");
+            if (!this._valueFlagLineLeft.firstChild) {
+                
this._valueFlagLineLeft.appendChild(SimileAjax.Graphics.createTranslucentImage(Timeplot.urlPrefix
 + "images/line_left.png"));
+                
this._valueFlagLineRight.appendChild(SimileAjax.Graphics.createTranslucentImage(Timeplot.urlPrefix
 + "images/line_right.png"));
+            }
+            this._valueFlagPole = this._timeplot.putDiv(this._id + 
"valuepole","timeplot-valueflag-pole");
+
+            var opacity = this._plotInfo.valuesOpacity;
+            
+            SimileAjax.Graphics.setOpacity(this._timeFlag, opacity);
+            SimileAjax.Graphics.setOpacity(this._valueFlag, opacity);
+            SimileAjax.Graphics.setOpacity(this._valueFlagLineLeft, opacity);
+            SimileAjax.Graphics.setOpacity(this._valueFlagLineRight, opacity);
+            SimileAjax.Graphics.setOpacity(this._valueFlagPole, opacity);
+
+            var plot = this;
+            
+            var mouseOverHandler = function(elmt, evt, target) {
+                if (plot._plotInfo.showValues) { 
+                       plot._valueFlag.style.display = "block";
+                       mouseMoveHandler(elmt, evt, target);
+                   }
+            }
+        
+            var day = 24 * 60 * 60 * 1000;
+            var month = 30 * day;
+            
+            var mouseMoveHandler = function(elmt, evt, target) {
+                if (typeof SimileAjax != "undefined" && 
plot._plotInfo.showValues) {
+                    var c = plot._canvas;
+                    var x = 
Math.round(SimileAjax.DOM.getEventRelativeCoordinates(evt,plot._canvas).x);
+                    if (x > c.width) x = c.width;
+                    if (isNaN(x) || x < 0) x = 0;
+                    var t = plot._timeGeometry.fromScreen(x);
+                    if (t == 0) { // something is wrong
+                        plot._valueFlag.style.display = "none";
+                        return;
+                    }
+                    
+                    var validTime = plot._dataSource.getClosestValidTime(t);
+                    x = plot._timeGeometry.toScreen(validTime);
+                    var v = plot._dataSource.getValue(validTime);
+                    if (plot._plotInfo.roundValues) v = Math.round(v);
+                    plot._valueFlag.innerHTML = new String(v);
+                    var d = new Date(validTime);
+                    var p = plot._timeGeometry.getPeriod(); 
+                    if (p < day) {
+                        plot._timeFlag.innerHTML = d.toLocaleTimeString();
+                    } else if (p > month) {
+                        plot._timeFlag.innerHTML = d.toLocaleDateString();
+                    } else {
+                        plot._timeFlag.innerHTML = d.toLocaleString();
+                    }
+
+                    var tw = plot._timeFlag.clientWidth;
+                    var th = plot._timeFlag.clientHeight;
+                    var tdw = Math.round(tw / 2);
+                    var vw = plot._valueFlag.clientWidth;
+                    var vh = plot._valueFlag.clientHeight;
+                    var y = plot._valueGeometry.toScreen(v);
+
+                    if (x + tdw > c.width) {
+                        var tx = c.width - tdw;
+                    } else if (x - tdw < 0) {
+                        var tx = tdw;
+                    } else {
+                        var tx = x;
+                    }
+
+                    if (plot._timeGeometry._timeValuePosition == "top") {
+                        plot._timeplot.placeDiv(plot._valueFlagPole, {
+                            left: x,
+                            top: th - 5,
+                            height: c.height - y - th + 6,
+                            display: "block"
+                        });
+                        plot._timeplot.placeDiv(plot._timeFlag,{
+                            left: tx - tdw,
+                            top: -6,
+                            display: "block"
+                        });
+                    } else {
+                        plot._timeplot.placeDiv(plot._valueFlagPole, {
+                            left: x,
+                            bottom: th - 5,
+                            height: y - th + 6,
+                            display: "block"
+                        });
+                        plot._timeplot.placeDiv(plot._timeFlag,{
+                            left: tx - tdw,
+                            bottom: -6,
+                            display: "block"
+                        });
+                    }
+
+                    if (x + vw + 14 > c.width && y + vh + 4 > c.height) {
+                        plot._valueFlagLineLeft.style.display = "none";
+                        plot._timeplot.placeDiv(plot._valueFlagLineRight,{
+                            left: x - 14,
+                            bottom: y - 14,
+                            display: "block"
+                        });
+                        plot._timeplot.placeDiv(plot._valueFlag,{
+                            left: x - vw - 13,
+                            bottom: y - vh - 13,
+                            display: "block"
+                        });
+                    } else if (x + vw + 14 > c.width && y + vh + 4 < c.height) 
{
+                        plot._valueFlagLineRight.style.display = "none";
+                        plot._timeplot.placeDiv(plot._valueFlagLineLeft,{
+                            left: x - 14,
+                            bottom: y,
+                            display: "block"
+                        });
+                        plot._timeplot.placeDiv(plot._valueFlag,{
+                            left: x - vw - 13,
+                            bottom: y + 13,
+                            display: "block"
+                        });
+                    } else if (x + vw + 14 < c.width && y + vh + 4 > c.height) 
{
+                        plot._valueFlagLineRight.style.display = "none";
+                        plot._timeplot.placeDiv(plot._valueFlagLineLeft,{
+                            left: x,
+                            bottom: y - 13,
+                            display: "block"
+                        });
+                        plot._timeplot.placeDiv(plot._valueFlag,{
+                            left: x + 13,
+                            bottom: y - 13,
+                            display: "block"
+                        });
+                    } else {
+                        plot._valueFlagLineLeft.style.display = "none";
+                        plot._timeplot.placeDiv(plot._valueFlagLineRight,{
+                            left: x,
+                            bottom: y,
+                            display: "block"
+                        });
+                        plot._timeplot.placeDiv(plot._valueFlag,{
+                            left: x + 13,
+                            bottom: y + 13,
+                            display: "block"
+                        });
+                    }
+                }
+            }
+
+            var timeplotElement = this._timeplot.getElement();
+            SimileAjax.DOM.registerEvent(timeplotElement, "mouseover", 
mouseOverHandler);
+            SimileAjax.DOM.registerEvent(timeplotElement, "mousemove", 
mouseMoveHandler);
+        }
+    },
+
+    /**
+     * Dispose the plot layer and all the data sources and listeners 
associated to it
+     */
+    dispose: function() {
+        if (this._dataSource) {
+            this._dataSource.removeListener(this._paintingListener);
+            this._paintingListener = null;
+            this._dataSource.dispose();
+            this._dataSource = null;
+        }
+    },
+
+    /**
+     * Hide the values
+     */
+    hideValues: function() {
+        if (this._valueFlag) this._valueFlag.style.display = "none";
+        if (this._timeFlag) this._timeFlag.style.display = "none";
+        if (this._valueFlagLineLeft) this._valueFlagLineLeft.style.display = 
"none";
+        if (this._valueFlagLineRight) this._valueFlagLineRight.style.display = 
"none";
+        if (this._valueFlagPole) this._valueFlagPole.style.display = "none";
+    },
+    
+    /**
+     * Return the data source of this plot layer (it could be either a 
DataSource or an EventSource)
+     */
+    getDataSource: function() {
+        return (this._dataSource) ? this._dataSource : this._eventSource;
+    },
+
+    /**
+     * Return the time geometry associated with this plot layer
+     */
+    getTimeGeometry: function() {
+        return this._timeGeometry;
+    },
+
+    /**
+     * Return the value geometry associated with this plot layer
+     */
+    getValueGeometry: function() {
+        return this._valueGeometry;
+    },
+
+    /**
+     * Paint this plot layer
+     */
+    paint: function() {
+        var ctx = this._canvas.getContext('2d');
+
+        ctx.lineWidth = this._plotInfo.lineWidth;
+        ctx.lineJoin = 'miter';
+
+        if (this._dataSource) {     
+            if (this._plotInfo.fillColor) {
+                if (this._plotInfo.fillGradient) {
+                    var gradient = 
ctx.createLinearGradient(0,this._canvas.height,0,0);
+                    
gradient.addColorStop(0,this._plotInfo.fillColor.toString());
+                    
gradient.addColorStop(0.5,this._plotInfo.fillColor.toString());
+                    gradient.addColorStop(1, 'rgba(255,255,255,0)');
+
+                    ctx.fillStyle = gradient;
+                } else {
+                    ctx.fillStyle = this._plotInfo.fillColor.toString();
+                }
+
+                ctx.beginPath();
+                ctx.moveTo(0,0);
+                this._plot(function(x,y) {
+                    ctx.lineTo(x,y);
+                });
+                if (this._plotInfo.fillFrom == Number.NEGATIVE_INFINITY) {
+                    ctx.lineTo(this._canvas.width, 0);
+                } else if (this._plotInfo.fillFrom == 
Number.POSITIVE_INFINITY) {
+                    ctx.lineTo(this._canvas.width, this._canvas.height);
+                    ctx.lineTo(0, this._canvas.height);
+                } else {
+                    ctx.lineTo(this._canvas.width, 
this._valueGeometry.toScreen(this._plotInfo.fillFrom));
+                    ctx.lineTo(0, 
this._valueGeometry.toScreen(this._plotInfo.fillFrom));
+                }
+                ctx.fill();
+            }
+                    
+            if (this._plotInfo.lineColor) {
+                ctx.strokeStyle = this._plotInfo.lineColor.toString();
+                ctx.beginPath();
+                var first = true;
+                this._plot(function(x,y) {
+                        if (first) {
+                             first = false;
+                             ctx.moveTo(x,y);
+                        }
+                    ctx.lineTo(x,y);
+                });
+                ctx.stroke();
+            }
+
+            if (this._plotInfo.dotColor) {
+                ctx.fillStyle = this._plotInfo.dotColor.toString();
+                var r = this._plotInfo.dotRadius;
+                this._plot(function(x,y) {
+                    ctx.beginPath();
+                    ctx.arc(x,y,r,0,2*Math.PI,true);
+                    ctx.fill();
+                });
+            }
+        }
+
+        if (this._eventSource) {
+            var gradient = ctx.createLinearGradient(0,0,0,this._canvas.height);
+            gradient.addColorStop(1, 'rgba(255,255,255,0)');
+
+            ctx.strokeStyle = gradient;
+            ctx.fillStyle = gradient; 
+            ctx.lineWidth = this._plotInfo.eventLineWidth;
+            ctx.lineJoin = 'miter';
+            
+            var i = this._eventSource.getAllEventIterator();
+            while (i.hasNext()) {
+                var event = i.next();
+                var color = event.getColor();
+                color = (color) ? new Timeplot.Color(color) : 
this._plotInfo.lineColor;
+                var eventStart = event.getStart().getTime();
+                var eventEnd = event.getEnd().getTime();
+                if (eventStart == eventEnd) {
+                    var c = color.toString();
+                    gradient.addColorStop(0, c);
+                    var start = this._timeGeometry.toScreen(eventStart);
+                    start = Math.floor(start) + 0.5; // center it between two 
pixels (makes the rendering nicer)
+                    var end = start;
+                    ctx.beginPath();
+                    ctx.moveTo(start,0);
+                    ctx.lineTo(start,this._canvas.height);
+                    ctx.stroke();
+                    var x = start - 4;
+                    var w = 7;
+                } else {
+                    var c = color.toString(0.5);
+                    gradient.addColorStop(0, c);
+                    var start = this._timeGeometry.toScreen(eventStart);
+                    start = Math.floor(start) + 0.5; // center it between two 
pixels (makes the rendering nicer)
+                    var end = this._timeGeometry.toScreen(eventEnd);
+                    end = Math.floor(end) + 0.5; // center it between two 
pixels (makes the rendering nicer)
+                    ctx.fillRect(start,0,end - start, this._canvas.height);
+                    var x = start;
+                    var w = end - start - 1;
+                }
+
+                var div = 
this._timeplot.putDiv(event.getID(),"timeplot-event-box",{
+                    left: Math.round(x),
+                    width: Math.round(w),
+                    top: 0,
+                    height: this._canvas.height - 1
+                });
+
+                var plot = this;
+                var clickHandler = function(event) { 
+                    return function(elmt, evt, target) { 
+                        var doc = plot._timeplot.getDocument();
+                        plot._closeBubble();
+                        var coords = 
SimileAjax.DOM.getEventPageCoordinates(evt);
+                        var elmtCoords = 
SimileAjax.DOM.getPageCoordinates(elmt);
+                        plot._bubble = 
SimileAjax.Graphics.createBubbleForPoint(coords.x, elmtCoords.top + 
plot._canvas.height, plot._plotInfo.bubbleWidth, plot._plotInfo.bubbleHeight, 
"bottom");
+                        event.fillInfoBubble(plot._bubble.content, 
plot._theme, plot._timeGeometry.getLabeler());
+                    }
+                };
+                var mouseOverHandler = function(elmt, evt, target) {
+                    elmt.oldClass = elmt.className;
+                    elmt.className = elmt.className + " 
timeplot-event-box-highlight";
+                };
+                var mouseOutHandler = function(elmt, evt, target) {
+                    elmt.className = elmt.oldClass;
+                    elmt.oldClass = null;
+                }
+                
+                if (!div.instrumented) {
+                    SimileAjax.DOM.registerEvent(div, "click"    , 
clickHandler(event));
+                    SimileAjax.DOM.registerEvent(div, "mouseover", 
mouseOverHandler);
+                    SimileAjax.DOM.registerEvent(div, "mouseout" , 
mouseOutHandler);
+                    div.instrumented = true;
+                }
+            }
+        }
+    },
+
+    _plot: function(f) {
+        var data = this._dataSource.getData();
+        if (data) {
+            var times = data.times;
+            var values = data.values;
+            var T = times.length;
+            for (var t = 0; t < T; t++) {
+                var x = this._timeGeometry.toScreen(times[t]);
+                var y = this._valueGeometry.toScreen(values[t]);
+                f(x, y);
+            }
+        }
+    },
+    
+    _closeBubble: function() {
+        if (this._bubble != null) {
+            this._bubble.close();
+            this._bubble = null;
+        }
+    }
+
+}
\ No newline at end of file

Added: openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/processor.js
URL: 
http://svn.apache.org/viewvc/openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/processor.js?rev=1791131&view=auto
==============================================================================
--- openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/processor.js 
(added)
+++ openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/processor.js 
Wed Apr 12 15:06:22 2017
@@ -0,0 +1,122 @@
+/**
+ * Processing Data Source
+ * 
+ * @fileOverview Processing Data Source and Operators
+ * @name Processor
+ */
+
+/* 
-----------------------------------------------------------------------------
+ * Operators
+ * 
+ * These are functions that can be used directly as Timeplot.Processor 
operators
+ * 
----------------------------------------------------------------------------- */
+
+Timeplot.Operator = { 
+
+    /**
+     * This is the operator used when you want to draw the cumulative sum
+     * of a time series and not, for example, their daily values.
+     */
+    sum: function(data, params) {
+        return Timeplot.Math.integral(data.values);
+    },
+
+    /**
+     * This is the operator that is used to 'smooth' a given time series
+     * by taking the average value of a moving window centered around
+     * each value. The size of the moving window is influenced by the 'size'
+     * parameters in the params map.
+     */
+    average: function(data, params) {
+        var size = ("size" in params) ? params.size : 30;
+        var result = Timeplot.Math.movingAverage(data.values, size);
+        return result;
+    }
+}
+
+/*==================================================
+ *  Processing Data Source
+ *==================================================*/
+
+/**
+ * A Processor is a special DataSource that can apply an Operator
+ * to the DataSource values and thus return a different one.
+ * 
+ * @constructor
+ */
+Timeplot.Processor = function(dataSource, operator, params) {
+    this._dataSource = dataSource;
+    this._operator = operator;
+    this._params = params;
+
+    this._data = {
+        times: new Array(),
+        values: new Array()
+    };
+
+    this._range = {
+        earliestDate: null,
+        latestDate: null,
+        min: 0,
+        max: 0
+    };
+
+    var processor = this;
+    this._processingListener = {
+        onAddMany: function() { processor._process(); },
+        onClear:   function() { processor._clear(); }
+    }
+    this.addListener(this._processingListener);
+};
+
+Timeplot.Processor.prototype = {
+
+    _clear: function() {
+        this.removeListener(this._processingListener);
+        this._dataSource._clear();
+    },
+
+    _process: function() {
+        // this method requires the dataSource._process() method to be
+        // called first as to setup the data and range used below
+        // this should be guaranteed by the order of the listener registration 
 
+
+        var data = this._dataSource.getData();
+        var range = this._dataSource.getRange();
+
+        var newValues = this._operator(data, this._params);
+        var newValueRange = Timeplot.Math.range(newValues);
+
+        this._data = {
+            times: data.times,
+            values: newValues
+        };
+
+        this._range = {
+            earliestDate: range.earliestDate,
+            latestDate: range.latestDate,
+            min: newValueRange.min,
+            max: newValueRange.max
+        };
+    },
+
+    getRange: function() {
+        return this._range;
+    },
+
+    getData: function() {
+        return this._data;
+    },
+    
+    getValue: Timeplot.DataSource.prototype.getValue,
+
+    getClosestValidTime: Timeplot.DataSource.prototype.getClosestValidTime,
+
+    addListener: function(listener) {
+        this._dataSource.addListener(listener);
+    },
+
+    removeListener: function(listener) {
+        this._dataSource.removeListener(listener);
+    }
+}

Added: openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/sources.js
URL: 
http://svn.apache.org/viewvc/openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/sources.js?rev=1791131&view=auto
==============================================================================
--- openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/sources.js 
(added)
+++ openoffice/ooo-site/trunk/content/stats/timeplot/1.1/scripts/sources.js Wed 
Apr 12 15:06:22 2017
@@ -0,0 +1,371 @@
+/**
+ * Sources
+ * 
+ * @fileOverview Sources
+ * @name Sources
+ */
+
+/**
+ * Timeplot.DefaultEventSource is an extension of Timeline.DefaultEventSource
+ * and therefore reuses the exact same event loading subsystem that
+ * Timeline uses.
+ * 
+ * @constructor
+ */
+Timeplot.DefaultEventSource = function(eventIndex) {
+    Timeline.DefaultEventSource.apply(this, arguments);
+};
+
+Object.extend(Timeplot.DefaultEventSource.prototype, 
Timeline.DefaultEventSource.prototype);
+
+/**
+ * Function used by Timeplot to load time series data from a text file.
+ */
+Timeplot.DefaultEventSource.prototype.loadText = function(text, separator, 
url, filter, format) {
+
+    if (text == null) {
+        return;
+    }
+
+    this._events.maxValues = new Array();
+    var base = this._getBaseURL(url);
+
+    if (!format) format = 'iso8601';
+    var parseDateTimeFunction = this._events.getUnit().getParser(format);
+
+    var data = this._parseText(text, separator);
+
+    var added = false;
+
+    if (filter) {
+        data = filter(data);
+    }
+
+    if (data) {
+        for (var i = 0; i < data.length; i++){
+            var row = data[i];
+            if (row.length > 1) {
+                var dateStr = SimileAjax.jQuery.trim(row[0]);
+                var date = parseDateTimeFunction(dateStr);
+                if (date) {
+                    var evt = new 
Timeplot.DefaultEventSource.NumericEvent(date,row.slice(1));
+                    this._events.add(evt);
+                    added = true;
+                }
+            }
+        }
+    }
+
+    if (added) {
+        this._fire("onAddMany", []);
+    }
+}
+
+/*
+ * Parse the data file.
+ * 
+ * Adapted from http://www.kawa.net/works/js/jkl/js/jkl-parsexml.js by Yusuke 
Kawasaki
+ */
+Timeplot.DefaultEventSource.prototype._parseText = function (text, separator) {
+    text = text.replace( /\r\n?/g, "\n" ); // normalize newlines
+    var pos = 0;
+    var len = text.length;
+    var table = [];
+    while (pos < len) {
+        var line = [];
+        if (text.charAt(pos) != '#') { // if it's not a comment, process
+            while (pos < len) {
+                if (text.charAt(pos) == '"') {            // "..." quoted 
column
+                    var nextquote = text.indexOf('"', pos+1 );
+                    while (nextquote<len && nextquote > -1) {
+                        if (text.charAt(nextquote+1) != '"') {
+                            break;                          // end of column
+                        }
+                        nextquote = text.indexOf('"', nextquote + 2);
+                    }
+                    if ( nextquote < 0 ) {
+                        // unclosed quote
+                    } else if (text.charAt(nextquote + 1) == separator) { // 
end of column
+                        var quoted = text.substr(pos + 1, nextquote-pos - 1);
+                        quoted = quoted.replace(/""/g,'"');
+                        line[line.length] = quoted;
+                        pos = nextquote + 2;
+                        continue;
+                    } else if (text.charAt(nextquote + 1) == "\n" || // end of 
line
+                               len == nextquote + 1 ) {              // end of 
file
+                        var quoted = text.substr(pos + 1, nextquote-pos - 1);
+                        quoted = quoted.replace(/""/g,'"');
+                        line[line.length] = quoted;
+                        pos = nextquote + 2;
+                        break;
+                    } else {
+                        // invalid column
+                    }
+                }
+                var nextseparator = text.indexOf(separator, pos);
+                var nextnline = text.indexOf("\n", pos);
+                if (nextnline < 0) nextnline = len;
+                if (nextseparator > -1 && nextseparator < nextnline) {
+                    line[line.length] = text.substr(pos, nextseparator-pos);
+                    pos = nextseparator + 1;
+                } else {                                    // end of line
+                    line[line.length] = text.substr(pos, nextnline-pos);
+                    pos = nextnline + 1;
+                    break;
+                }
+            }
+        } else { // if it's a comment, ignore
+            var nextnline = text.indexOf("\n", pos);
+            pos = (nextnline > -1) ? nextnline + 1 : cur;
+        }
+        if (line.length > 0) {
+            table[table.length] = line;                 // push line
+        }
+    }
+    if (table.length < 0) return;                     // null data
+    return table;
+}
+
+/**
+ * Return the range of the loaded data
+ */
+Timeplot.DefaultEventSource.prototype.getRange = function() {
+    var earliestDate = this.getEarliestDate();
+    var latestDate = this.getLatestDate();
+    return {
+        earliestDate: (earliestDate) ? earliestDate : null,
+        latestDate: (latestDate) ? latestDate : null,
+        min: 0,
+        max: 0
+    };
+}
+
+// -----------------------------------------------------------------------
+
+/**
+ * A NumericEvent is an Event that also contains an array of values, 
+ * one for each columns in the loaded data file.
+ * 
+ * @constructor
+ */
+Timeplot.DefaultEventSource.NumericEvent = function(time, values) {
+    this._id = "e" + Math.round(Math.random() * 1000000);
+    this._time = time;
+    this._values = values;
+};
+
+Timeplot.DefaultEventSource.NumericEvent.prototype = {
+    getID:          function() { return this._id; },
+    getTime:        function() { return this._time; },
+    getValues:      function() { return this._values; },
+
+    // these are required by the EventSource
+    getStart:       function() { return this._time; },
+    getEnd:         function() { return this._time; }
+};
+
+// -----------------------------------------------------------------------
+
+/**
+ * A DataSource represent an abstract class that represents a monodimensional 
time series.
+ * 
+ * @constructor
+ */
+Timeplot.DataSource = function(eventSource) {
+    this._eventSource = eventSource;
+    var source = this;
+    this._processingListener = {
+        onAddMany: function() { source._process(); },
+        onClear:   function() { source._clear(); }
+    }
+    this.addListener(this._processingListener);
+    this._listeners = [];
+    this._data = null;
+    this._range = null;
+};
+
+Timeplot.DataSource.prototype = {
+  
+    _clear: function() {
+        this._data = null;
+        this._range = null;
+    },
+
+    _process: function() {
+        this._data = {
+            times: new Array(),
+            values: new Array()
+        };
+        this._range = {
+            earliestDate: null,
+            latestDate: null,
+            min: 0,
+            max: 0
+        };
+    },
+
+    /**
+     * Return the range of this data source
+     */
+    getRange: function() {
+        return this._range;
+    },
+
+    /**
+     * Return the actual data that this data source represents.
+     * NOTE: _data = { times: [], values: [] }
+     */
+    getData: function() {
+        return this._data;
+    },
+    
+    /**
+     * Return the value associated with the given time in this time series
+     */
+    getValue: function(t) {
+        if (this._data) {
+            for (var i = 0; i < this._data.times.length; i++) {
+                var l = this._data.times[i];
+                if (l >= t) {
+                    return this._data.values[i];
+                }
+            }
+        }
+        return 0;
+    },
+
+    /**
+     * Return the time of the data point closest to the given time.
+     */
+    getClosestValidTime: function(t) {
+        if (this._data) {
+            for (var i = 0; i < this._data.times.length; i++) {
+                var currentTime = this._data.times[i];
+                if (currentTime >= t) {
+                    if (i <= 0) {
+                        return currentTime;
+                    } else {
+                        var lastTime = this._data.times[i - 1];
+                        // t must be between currentTime and lastTime.
+                        // Find the closest one.
+                        if (t - lastTime < currentTime - t) {
+                            return lastTime;
+                        } else {
+                            return currentTime;
+                        }
+                    }
+                }
+            }
+        }
+        return 0;
+    },
+
+    /**
+     * Add a listener to the underlying event source
+     */
+    addListener: function(listener) {
+        this._eventSource.addListener(listener);
+    },
+
+    /**
+     * Remove a listener from the underlying event source
+     */
+    removeListener: function(listener) {
+        this._eventSource.removeListener(listener);
+    },
+
+    /**
+     * Replace a listener from the underlying event source
+     */
+    replaceListener: function(oldListener, newListener) {
+        this.removeListener(oldListener);
+        this.addListener(newListener);
+    }
+
+}
+
+// -----------------------------------------------------------------------
+
+/**
+ * Implementation of a DataSource that extracts the time series out of a 
+ * single column from the events
+ * 
+ * @constructor
+ */
+Timeplot.ColumnSource = function(eventSource, column) {
+    Timeplot.DataSource.apply(this, arguments);
+    this._column = column - 1;
+};
+
+Object.extend(Timeplot.ColumnSource.prototype,Timeplot.DataSource.prototype);
+
+Timeplot.ColumnSource.prototype.dispose = function() {
+    this.removeListener(this._processingListener);
+    this._clear();
+}
+
+Timeplot.ColumnSource.prototype._process = function() {
+    var count = this._eventSource.getCount();
+    var times = new Array(count);
+    var values = new Array(count);
+    var min = Number.MAX_VALUE;
+    var max = Number.MIN_VALUE;
+    var i = 0;
+
+    var iterator = this._eventSource.getAllEventIterator();
+    while (iterator.hasNext()) {
+        var event = iterator.next();
+        var time = event.getTime();
+        times[i] = time;
+        var value = this._getValue(event);
+        if (!isNaN(value)) {
+           if (value < min) {
+               min = value;
+           }
+           if (value > max) {
+               max = value;
+           }    
+            values[i] = value;
+        }
+        i++;
+    }
+
+    this._data = {
+        times: times,
+        values: values
+    };
+
+    if (max == Number.MIN_VALUE) max = 1;
+    
+    this._range = {
+        earliestDate: this._eventSource.getEarliestDate(),
+        latestDate: this._eventSource.getLatestDate(),
+        min: min,
+        max: max
+    };
+}
+
+Timeplot.ColumnSource.prototype._getValue = function(event) {
+    return parseFloat(event.getValues()[this._column]);
+}
+
+// ---------------------------------------------------------------
+
+/**
+ * Data Source that generates the time series out of the difference
+ * between the first and the second column
+ * 
+ * @constructor
+ */
+Timeplot.ColumnDiffSource = function(eventSource, column1, column2) {
+    Timeplot.ColumnSource.apply(this, arguments);
+    this._column2 = column2 - 1;
+};
+
+Object.extend(Timeplot.ColumnDiffSource.prototype,Timeplot.ColumnSource.prototype);
+
+Timeplot.ColumnDiffSource.prototype._getValue = function(event) {
+    var a = parseFloat(event.getValues()[this._column]);
+    var b = parseFloat(event.getValues()[this._column2]);
+    return a - b;
+}


Reply via email to