Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha User
    Join Date
    Mar 2012
    Posts
    3
    Vote Rating
    0
    rpech is on a distinguished road

      0  

    Default Time Axis adds +1 tick and changes step length when minimum/maximum is defined

    Time Axis adds +1 tick and changes step length when minimum/maximum is defined


    For example, I have a chart (Ext4.chart.Chart) in which I want to display data for last 2 hour's traffic (i.e. last time is 'now' and first time is 'now - 2 hours') and want to have ticks per 15 minutes in format 'now', '15 minutes ago', '30 minutes ago', etc. (in right-to-left order)

    So this is what I set for the time axis (Ext4.chart.axis.Time):
    Code:
    axis.minimum = chartData[0].time; //chartData is simple array loaded via JSON-RPC
    axis.maximum = chartData[chartData.length-1].time;
    axis.step = [Ext.Date.MINUTE, 15];
    chart.refresh();
    I would expect to see chart with 9 ticks: 120 minutes ago, 105m ago, ..., 15m ago, now
    However Ext generates chart with 10 ticks: 120 minutes ago, 107m ago, 93m ago, ...

    As I've discovered, problem is in the method Ext4.chart.axis.Time.calcEnds() which calls Ext4.draw.Draw.snapEndsByDateAndStep(), which uses condition "while (testTo < to)" and since "testTo === to" (i.e. last time exactly match the 15 minute steps) it adds one more step and increases the maximum. Method calcEnds() then uses this number of steps but keeps own maximum and changes the step length (from 15 minutes to 13 minutes and 20 seconds).

    It can be fixed by overriding method Ext4.chart.TimeAxis.prototype.calcEnds() and adding the last param to the snapEndsByDateAndStep(..., true) to force the method to keep the defined maximum for all the calculations.

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    36,754
    Vote Rating
    827
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Can I get a locally runnable test case? Also what Ext JS 4 version and have you tested outside of the sandbox?
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  3. #3
    Sencha User
    Join Date
    Mar 2012
    Posts
    3
    Vote Rating
    0
    rpech is on a distinguished road

      0  

    Default


    Tested in ExtJS 4.1 RC
    Modified from sample Live Updated Chart
    Min/Max set to last 2 minutes
    Steps set to 15 seconds
    (It's exactly same situation as with 2 hours and 15 minute steps)

    Current result:
    chart_13s.jpg
    Expected result:
    chart_15s.jpg
    Comparison:
    chart_bug.jpg

    Code:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Chart</title>
    
        <script type="text/javascript" src="ext-all-debug.js"></script>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    
        <link rel="stylesheet" type="text/css" media="screen, projection, print" href="ext-all.css" />
    
        <script type="text/javascript">
    Ext.require([
        'Ext.window.Window',
        'Ext.chart.*'
    ]);
    
    Ext.onReady(function () {
    ////FIX - uncomment to get it right
    //Ext.chart.TimeAxis.prototype.calcEnds = function() {
    //            var me = this, range, step = me.step;
    //
    //            if (step) {
    //                range = me.getRange();
    //                range = Ext.draw.Draw.snapEndsByDateAndStep(new Date(range.min), new Date(range.max), Ext.isNumber(step) ? [Date.MILLI, step] : step, true);
    //                return range;
    //            }
    //            else {
    //                return me.callParent(arguments);
    //            }
    //        };
    ////END of FIX
    
        var chart;
        var generateData = (function() {
            var data = [],
                last = false,
                min = Math.min,
                max = Math.max,
                random = Math.random;
            return function() {
                data = data.slice();
                data.push({
                    date: new Date(),
                    visits: min(100, max(last? last.visits + (random() - 0.5) * 20 : random() * 100, 0)),
                    views: min(100, max(last? last.views + (random() - 0.5) * 10 : random() * 100, 0)),
                    veins: min(100, max(last? last.veins + (random() - 0.5) * 20 : random() * 100, 0))
                });
                last = data[data.length -1];
                return data;
            };
        })();
    
        var store = Ext.create('Ext.data.JsonStore', {
            fields: ['date', 'visits', 'views', 'veins'],
            data: generateData()
        });
    
        var intr = setInterval(function() {
    //        debugger;
            var data = generateData();
            timeAxis.maximum = +data[data.length-1].date;
            timeAxis.minimum = +data[data.length-1].date - 2*60*1000; //2 minutes
            timeAxis.step = [Ext.Date.SECOND, 15];
            store.loadData(data);
        }, 1000);
    
        Ext.create('Ext.Window', {
            width: 800,
            height: 600,
            minHeight: 400,
            minWidth: 550,
            maximizable: true,
            title: 'Live Updated Chart',
            layout: 'fit',
            items: [{
                xtype: 'chart',
                style: 'background:#fff',
                store: store,
                grid: true,
                id: 'chartCmp',
                axes: [{
                    type: 'Numeric',
                    grid: true,
                    minimum: 0,
                    maximum: 100,
                    position: 'left',
                    fields: ['views', 'visits', 'veins'],
                    title: 'Number of Hits',
                    grid: {
                        odd: {
                            fill: '#dedede',
                            stroke: '#ddd',
                            'stroke-width': 0.5
                        }
                    }
                }, {
                    type: 'Time',
                    position: 'bottom',
                    fields: 'date',
                    title: 'Time',
                    label: {
                        renderer: function(value) {
                            if (!timeAxis) { return ''; }
    
                            var
                                max = timeAxis.maximum,
                                e = Ext.Date.getElapsed(value, max),
                                s = Math.floor(e/1000);
    
                             return (0 === s) ? 'now' : s + 's ago';
                        }
                    },
                    constrain: true
                }],
                series: [{
                    type: 'line',
                    axis: ['left', 'bottom'],
                    xField: 'date',
                    yField: 'visits',
                    label: {
                        display: 'none',
                        field: 'visits',
                        renderer: function(v) { return v >> 0; },
                        'text-anchor': 'middle'
                    },
                    markerConfig: {
                        radius: 5,
                        size: 5
                    }
                },{
                    type: 'line',
                    axis: ['left', 'bottom'],
                    xField: 'date',
                    yField: 'views',
                    label: {
                        display: 'none',
                        field: 'visits',
                        renderer: function(v) { return v >> 0; },
                        'text-anchor': 'middle'
                    },
                    markerConfig: {
                        radius: 5,
                        size: 5
                    }
                },{
                    type: 'line',
                    axis: ['left', 'bottom'],
                    xField: 'date',
                    yField: 'veins',
                    label: {
                        display: 'none',
                        field: 'visits',
                        renderer: function(v) { return v >> 0; },
                        'text-anchor': 'middle'
                    },
                    markerConfig: {
                        radius: 5,
                        size: 5
                    }
                }]
            }]
        }).show();
        chart = Ext.getCmp('chartCmp');
        var timeAxis = chart.axes.get(1);
    });
        </script>
    
    </head>
    <body>
    <h1>Chart</h1>
    </body>
    </html>
    Fix included in the code.

    //edit:
    tested in:
    Windows 7 x64: Firefox 11, IE9 x64, Safari 5.1, Chrome 18
    MaxOS 10.6.8: Safari 5.1, Chrome 17, Firefox 3.6

    Live sample:
    http://ext-chart.chobits.ch/bad.html
    http://ext-chart.chobits.ch/good.html
    Last edited by rpech; 2 Apr 2012 at 2:53 AM. Reason: live samples
    Kerio Control Administration developer
    http://www.kerio.com/control

Thread Participants: 1

Tags for this Thread