1. #1
    Sencha User Daniil's Avatar
    Join Date
    Jun 2010
    Location
    Saint-Petersburg, Russia
    Posts
    974
    Vote Rating
    110
    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

      1  

    Default Chart CategoryAxis groups its values by uniqueness

    Chart CategoryAxis groups its values by uniqueness


    Initial problem

    We faced the problem that a CategoryAxis doesn't group its value by uniqueness.

    Example of Problem
    Code:
    <!DOCTYPE html>
    <html>
    <head>
        <title>Chart CategoryAxis grouping - problem</title>
    
        <link rel="stylesheet" href="../resources/css/ext-all.css" />
    
        <script src="../ext-all-dev.js"></script>
    
        <script>
            Ext.onReady(function () {
                Ext.create("Ext.chart.Chart", {
                    renderTo: Ext.getBody(),
                    height: 400,
                    width: 400,
                    store: {
                        fields: [ "category", "value" ],
                        data: [{
                            category: "category 1",
                            value: 20
                        }, {
                            category: "category 2",
                            value: 50
                        }, {
                            category: "category 1",
                            value: 5
                        }, {
                            category: "category 2",
                            value: 70
                        },]
                    },
                    axes: [{
                        type: "category",
                        position: "bottom",
                        title: "Category",
                        fields: [ "category" ]
                    }, {
                        type: "numeric",
                        position: "left",
                        title: "Value",
                        fields: [ "value" ]
                    }],
                    series: [{
                        type: "scatter",
                        xField: "category",
                        yField: "value"
                    }]                
                });
            });
        </script>
    </head>
    <body>
    </body>
    </html>
    It produces:
    Problem.JPG
    As far as I can see there is no functionality to group those categories by uniqueness. Searching the forum I found that other people also concern on this problem or on a similar one.
    http://www.sencha.com/forum/showthread.php?254698
    http://www.sencha.com/forum/showthread.php?237288
    http://www.sencha.com/forum/showthread.php?187522

    There is no solution in those threads. So, I am trying to come with a solution.

    Solution

    As far as I can see the changes are required in both: CategoryAxis and a Series being used (unless I don't see a more clear solution). So, I started with a ScatterSeries. Here I am posting an example with some overrides. I made the actual overrides and other key points being red to allow you to review it easily.

    It is not fully tested and will probably require some (maybe, a lot) tweaking, but I hope you will find it helpful. Any feedback would be appreciated.

    To test it with your page please take the overrides and set up group: true for a CategoryAxis and groupXValues: true or groupYValues: true for a ScatterSeries.

    Example of Solution
    Code:
    <!DOCTYPE html>
    <html>
    <head>
        <title>Chart CategoryAxis grouping - solution</title>
    
        <link rel="stylesheet" href="../resources/css/ext-all.css" />
    
        <script src="../ext-all-dev.js"></script>
    
        <%-- Overrides --%>
        <script>
            Ext.chart.series.Scatter.override({
                groupXValues: false,
                groupYValues: false,
    
                getPaths: function () {
                    var me = this,
                        chart = me.chart,
                        enableShadows = chart.shadow,
                        store = chart.getChartStore(),
                        data = store.data.items,
                        i, ln, record,
                        group = me.group,
                        bounds = me.bounds = me.getBounds(),
                        bbox = me.bbox,
                        xScale = bounds.xScale,
                        yScale = bounds.yScale,
                        minX = bounds.minX,
                        minY = bounds.minY,
                        boxX = bbox.x,
                        boxY = bbox.y,
                        boxHeight = bbox.height,
                        items = me.items = [],
                        attrs = [],
                        x, y, xValue, yValue, sprite,
                        cacheXValues = [],
                        cacheYValues = [],
                        indexInCache;
    
                    for (i = 0, ln = data.length; i < ln; i++) {
                        record = data[i];
                        xValue = record.get(me.xField);
                        yValue = record.get(me.yField);
                        //skip undefined or null values
                        if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)
                            || xValue == null || yValue == null) {
                            if (Ext.isDefined(Ext.global.console)) {
                                Ext.global.console.warn("[Ext.chart.series.Scatter]  Skipping a store element with a value which is either undefined or null  at ", record, xValue, yValue);
                            }
                            continue;
                        }
    
                        // Ensure a value
                        if (typeof xValue == 'string' || typeof xValue == 'object' && !Ext.isDate(xValue)) {
                            if (me.groupXValues) {
                                indexInCache = cacheXValues.indexOf(xValue);
    
                                if (indexInCache > -1) {
                                    xValue = indexInCache;
                                } else {
                                    cacheXValues.push(xValue);
                                    xValue = i;
                                }
                            } else {
                                xValue = i;
                            }
                        }
    
                        if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)) {
                            if (me.groupYValues) {
                                indexInCache = cacheYValues.indexOf(yValue);
    
                                if (indexInCache > -1) {
                                    yValue = indexInCache;
                                } else {
                                    cacheYValues.push(yValue);
                                    yValue = i;
                                }
                            } else {
                                yValue = i;
                            }
                        }
    
                        x = boxX + (xValue - minX) * xScale;
                        y = boxY + boxHeight - (yValue - minY) * yScale;
                        attrs.push({
                            x: x,
                            y: y
                        });
    
                        me.items.push({
                            series: me,
                            value: [xValue, yValue],
                            point: [x, y],
                            storeItem: record
                        });
    
                        // When resizing, reset before animating
                        if (chart.animate && chart.resizing) {
                            sprite = group.getAt(i);
                            if (sprite) {
                                me.resetPoint(sprite);
                                if (enableShadows) {
                                    me.resetShadow(sprite);
                                }
                            }
                        }
                    }
                    return attrs;
                }
            });
    
            Ext.chart.axis.Category.override({
                group: false,
                
                // @private creates an array of labels to be used when rendering.
                setLabels: function () {
                    var store = this.chart.getChartStore(),
                        data = store.data.items,
                        d, dLen, record,
                        fields = this.fields,
                        ln = fields.length,
                        labels,
                        name,
                        i;
    
                    labels = this.labels = [];
                    for (d = 0, dLen = data.length; d < dLen; d++) {
                        record = data[d];
                        for (i = 0; i < ln; i++) {
                            name = record.get(fields[i]);
                            
                            if (Ext.Array.indexOf(labels, name) > -1) {
                                if (!this.group) { // add a label only if it is unique
                                    //<debug>
                                    Ext.log.warn('Duplicate category in axis, ' + name);
                                    //</debug>
    
                                    labels.push(name);
                                }
                            } else {
                                labels.push(name);
                            }
                        }
                    }
                },
    
                // @private calculates labels positions and marker positions for rendering.
                applyData: function() {
                    this.callParent();
                    this.setLabels();
                    var count = this.group ? this.labels.length : this.chart.getChartStore().getCount();
    
                    return {
                        from: 0,
                        to: count - 1,
                        power: 1,
                        step: 1,
                        steps: count - 1
                    };
                }
            });
        </script>
    
        <%-- End of Overrides --%>
    
        <script>
            Ext.onReady(function () {
                Ext.create("Ext.chart.Chart", {
                    renderTo: Ext.getBody(),
                    height: 400,
                    width: 400,
                    store: {
                        fields: ["category", "value"],
                        data: [{
                            category: "category 1",
                            value: 20
                        }, {
                            category: "category 2",
                            value: 50
                        }, {
                            category: "category 1",
                            value: 5
                        }, {
                            category: "category 2",
                            value: 70
                        }]
                    },
                    axes: [{
                        type: "category",
                        position: "bottom",
                        title: "Category",
                        fields: ["category"],
                        group: true
                    }, {
                        type: "numeric",
                        position: "left",
                        title: "Value",
                        fields: ["value"]
                    }],
                    series: [{
                        type: "scatter",
                        xField: "category",
                        yField: "value",
                        groupXValues: true
                    }]
                });
            });
        </script>
    </head>
    <body>
    </body>
    </html>
    It produces:
    Solution.JPG
    Ext.NET - ASP.NET for Ext JS
    MVC and WebForms
    Examples | Twitter

  2. #2
    Sencha - Support Team
    Join Date
    Feb 2013
    Location
    California
    Posts
    3,280
    Vote Rating
    63
    Gary Schlosberg is a jewel in the rough Gary Schlosberg is a jewel in the rough Gary Schlosberg is a jewel in the rough

      0  

    Default


    Thanks for sharing with the community!

  3. #3
    Sencha User
    Join Date
    Apr 2010
    Location
    Houston, TX, USA
    Posts
    25
    Vote Rating
    2
    keithhackworth is on a distinguished road

      0  

    Default


    This is exactly what I was looking for. Thank you!!! It's pretty bad the chart can't do this by default.

  4. #4
    Sencha User Daniil's Avatar
    Join Date
    Jun 2010
    Location
    Saint-Petersburg, Russia
    Posts
    974
    Vote Rating
    110
    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

      1  

    Default


    Thank you for the feedback. I am so glad it helped one person, at least
    Ext.NET - ASP.NET for Ext JS
    MVC and WebForms
    Examples | Twitter

  5. #5
    Sencha User
    Join Date
    Apr 2010
    Location
    Houston, TX, USA
    Posts
    25
    Vote Rating
    2
    keithhackworth is on a distinguished road

      2  

    Default


    I made one minor tweak to your code:
    Code:
                        if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)) {
                            if (me.groupYValues) {
                                indexInCache = cacheYValues.indexOf(yValue);
    
                                if (indexInCache > -1) {
                                    yValue = indexInCache;
                                } else {
                                    cacheYValues.push(yValue);
                                    yValue = cacheYValues.indexOf(yValue);
                                }
                            } else {
                                yValue = i;
                            }
                        }
    This needs to be done to the x axis as well.

    One thing to note: This works really well as long as the grouping category you're using doesn't have a null value. If it is null, then it skips those, and the indexing is all off and data gets plotted where it shouldn't be.

    Thank you!
    Keith

  6. #6
    Sencha User Daniil's Avatar
    Join Date
    Jun 2010
    Location
    Saint-Petersburg, Russia
    Posts
    974
    Vote Rating
    110
    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


    Yes, I didn't claim my solution is the final one It was rather to demonstrate a possibility and to start a discussion if someone is really interested on implement it.

    So, your input is really appreciated. Thank you.
    Ext.NET - ASP.NET for Ext JS
    MVC and WebForms
    Examples | Twitter

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi