You found a bug! We've classified it as EXTJS-9686 . We encourage you to continue the discussion and to find an acceptable workaround while we work on a permanent fix.
  1. #1
    Sencha User Daniil's Avatar
    Join Date
    Jun 2010
    Location
    Saint-Petersburg, Russia
    Posts
    977
    Vote Rating
    113
    Daniil is a name known to all Daniil is a name known to all Daniil is a name known to all Daniil is a name known to all Daniil is a name known to all Daniil is a name known to all

      0  

    Default [4.2.1 beta] Chart ScatterSeries and LineSeries can render incorrect labels

    [4.2.1 beta] Chart ScatterSeries and LineSeries can render incorrect labels


    REQUIRED INFORMATION

    Ext version tested:
    • Ext 4.2.1 beta
    Browser versions tested against:
    • IE9
    • Chrome
    DOCTYPE tested against:
    • <!DOCTYPE html>
    Description:
    • A ScatterSeries and LineSeries render incorrect labels if some of the points are missed (i.e. its yField is undefined).
    Steps to reproduce the problem:
    • Just run the test case
    The result that was expected:
    • "Item 0", "Item 2", "Item 4" labels
    The result that occurs instead:
    • "Item 0", "Item 1", "Item 2" labels
    Test Case:

    Code:
    <!DOCTYPE html>
    <html>
    <head>
        <title>ScatterSeries and LineSeries renders incorrect labels</title>
    
        <link rel="stylesheet" href="../resources/css/ext-all.css" />
        
        <script src="../ext-all-debug.js"></script>    
    
        <script>
            Ext.onReady(function () {
                var store = Ext.create("Ext.data.Store", {
                    autoLoad: true,
                    fields: [{
                        name: "x"
                    }, {
                        name: "y"
                    }, {
                        name: "label"    
                    }],
                    data: [{
                        x: 0,
                        y: 0,
                        label: "Item 0"
                    }, {
                        x: 1,
                        y: undefined,
                        label: "Item 1"
                    }, {
                        x: 2,
                        y: 2,
                        label: "Item 2"
                    }, {
                        x: 3,
                        y: undefined,
                        label: "Item 3"
                    }, {
                        x: 4,
                        y: 4,
                        label: "Item 4"
                    }]
                });
    
                Ext.create("Ext.chart.Chart", {
                    renderTo: Ext.getBody(),
                    width: 300,
                    height: 300,
                    store: store,
                    axes: [{
                        type: "Numeric",
                        position: "bottom",
                        title: "X",
                        fields: ["x"],
                        maximum: 5
                    }, {
                        type: "Numeric",
                        position: "left",
                        title: "Y",
                        fields: ["y"],
                        maximum: 5
                    }],
                    series: [{
                        type: "scatter",
                        xField: "x",
                        yField: "y",
                        label: {
                            field: "label",
                            display: "over"
                        }
                    }]
                });
            });
        </script>
    </head>
    <body>
    
    </body>
    </html>

    HELPFUL INFORMATION

    Possible fix:
    • I think the problem is in the Ext.chart.Label's renderLabels method. See the red text. Tested with a Line and a Scatter series. I have not tested with another types of series.
    Code:
    Ext.chart.series.Series.override({
        renderLabels: function () {
            var me = this,
                chart = me.chart,
                gradients = chart.gradients,
                items = me.items,
                animate = chart.animate,
                config = me.label,
                display = config.display,
                stackedDisplay = config.stackedDisplay,
                format = config.renderer,
                color = config.color,
                field = [].concat(config.field),
                group = me.labelsGroup,
                groupLength = (group || 0) && group.length,
                store = me.chart.getChartStore(),
                len = store.getCount(),
                itemLength = (items || 0) && items.length,
                ratio = itemLength / len,
                gradientsCount = (gradients || 0) && gradients.length,
                Color = Ext.draw.Color,
                hides = [],
                gradient, i, count, groupIndex, index, j, k, colorStopTotal, colorStopIndex, colorStop, item, label,
                storeItem, sprite, spriteColor, spriteBrightness, labelColor, colorString,
                total, totalPositive, totalNegative, topText, bottomText;
    
            if (display == 'none') {
                return;
            }
            // no items displayed, hide all labels
            if (itemLength == 0) {
                while (groupLength--) {
                    hides.push(groupLength);
                }
            } else {
                for (i = 0, count = 0, groupIndex = 0; i < len; i++) {
                    index = 0;
                    for (j = 0; j < ratio; j++) {
                        item = items[count];
                        label = group.getAt(groupIndex);
                        storeItem = item && item.storeItem; //storeItem = store.getAt(i); - replaced
                        //check the excludes
                        while (this.__excludes && this.__excludes[index]) {
                            index++;
                        }
    
                        if (!item && label) {
                            label.hide(true);
                            groupIndex++;
                        }
    
                        if (item && field[j]) {
                            if (!label) {
                                label = me.onCreateLabel(storeItem, item, i, display);
                            }
                            me.onPlaceLabel(label, storeItem, item, i, display, animate, index);
                            groupIndex++;
    
                            //set contrast
                            if (config.contrast && item.sprite) {
                                sprite = item.sprite;
                                //set the color string to the color to be set, only read the
                                // _endStyle/_to if we're animating, otherwise they're not relevant
                                if (animate && sprite._endStyle) {
                                    colorString = sprite._endStyle.fill;
                                } else if (animate && sprite._to) {
                                    colorString = sprite._to.fill;
                                } else {
                                    colorString = sprite.attr.fill;
                                }
                                colorString = colorString || sprite.attr.fill;
    
                                spriteColor = Color.fromString(colorString);
                                //color wasn't parsed property maybe because it's a gradient id
                                if (colorString && !spriteColor) {
                                    colorString = colorString.match(me.colorStringRe)[1];
                                    for (k = 0; k < gradientsCount; k++) {
                                        gradient = gradients[k];
                                        if (gradient.id == colorString) {
                                            //avg color stops
                                            colorStop = 0;
                                            colorStopTotal = 0;
                                            for (colorStopIndex in gradient.stops) {
                                                colorStop++;
                                                colorStopTotal += Color.fromString(gradient.stops[colorStopIndex].color).getGrayscale();
                                            }
                                            spriteBrightness = (colorStopTotal / colorStop) / 255;
                                            break;
                                        }
                                    }
                                } else {
                                    spriteBrightness = spriteColor.getGrayscale() / 255;
                                }
                                if (label.isOutside) {
                                    spriteBrightness = 1;
                                }
                                labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
                                labelColor[2] = spriteBrightness > 0.5 ? 0.2 : 0.8;
                                label.setAttributes({
                                    fill: String(Color.fromHSL.apply({}, labelColor))
                                }, true);
                            }
    
                            // display totals on stacked charts
                            if (me.stacked && stackedDisplay && (item.totalPositiveValues || item.totalNegativeValues)) {
                                totalPositive = (item.totalPositiveValues || 0);
                                totalNegative = (item.totalNegativeValues || 0);
                                total = totalPositive + totalNegative;
    
                                if (stackedDisplay == 'total') {
                                    topText = format(total);
                                } else if (stackedDisplay == 'balances') {
                                    if (totalPositive == 0 && totalNegative == 0) {
                                        topText = format(0);
                                    } else {
                                        topText = format(totalPositive);
                                        bottomText = format(totalNegative);
                                    }
                                }
    
                                if (topText) {
                                    label = group.getAt(groupIndex);
                                    if (!label) {
                                        label = me.onCreateLabel(storeItem, item, i, 'over');
                                    }
                                    label.setAttributes({
                                        text: topText
                                    });
                                    me.onPlaceLabel(label, storeItem, item, i, 'over', animate, index);
                                    groupIndex++;
    
                                    labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
                                    label.setAttributes({
                                        fill: String(Color.fromHSL.apply({}, labelColor))
                                    }, true);
                                }
    
                                if (bottomText) {
                                    label = group.getAt(groupIndex);
                                    if (!label) {
                                        label = me.onCreateLabel(storeItem, item, i, 'under');
                                    }
                                    label.setAttributes({
                                        text: bottomText
                                    });
                                    me.onPlaceLabel(label, storeItem, item, i, 'under', animate, index);
                                    groupIndex++;
    
                                    labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
                                    label.setAttributes({
                                        fill: String(Color.fromHSL.apply({}, labelColor))
                                    }, true);
                                }
                            }
                        }
                        count++;
                        index++;
                    }
                }
                groupLength = group.length;
    
                while (groupLength > groupIndex) {
                    hides.push(groupIndex);
                    groupIndex++;
                }
            }
            me.hideLabels(hides);
        }    
    });

    *EDIT BY SLEMMON
    tested in 4.1.1
    tested in 4.1.3
    tested in 4.2.1.799
    Last edited by Daniil; 2 May 2013 at 8:44 PM. Reason: Added Possible Fix
    Ext.NET - ASP.NET for Ext JS
    MVC and WebForms
    Examples | Twitter

  2. #2
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    6,062
    Vote Rating
    215
    slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of

      0  

    Default


    Thanks for the report! I have opened a bug in our bug tracker.

  3. #3
    Sencha User Daniil's Avatar
    Join Date
    Jun 2010
    Location
    Saint-Petersburg, Russia
    Posts
    977
    Vote Rating
    113
    Daniil is a name known to all Daniil is a name known to all Daniil is a name known to all Daniil is a name known to all Daniil is a name known to all Daniil is a name known to all

      0  

    Default


    I think the problem is in the Ext.chart.Label's renderLabels method. I have updated the initial post with a Possible Fix section.
    Ext.NET - ASP.NET for Ext JS
    MVC and WebForms
    Examples | Twitter

Thread Participants: 1