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
    974
    Vote Rating
    108
    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
    4,800
    Vote Rating
    167
    slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold

      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
    974
    Vote Rating
    108
    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