1. #1
    Sencha User
    Join Date
    Sep 2008
    Location
    Netherlands
    Posts
    106
    Vote Rating
    1
    buz is on a distinguished road

      1  

    Lightbulb Highcharts adapter and plugin for ExtJS

    Highcharts adapter and plugin for ExtJS


    Hello,

    Since many others are asking for this plugin, i'm posting the plugin and adapter for highcharts here.

    For people who don't know Highcharts:
    Highcharts is a charting library written in pure JavaScript, offering an easy way of adding interactive charts to your web site or web application. Highcharts currently supports line, spline, area, areaspline, column, bar, pie and scatter chart types.


    Regards, Daniël


    [Last update 09-11-2010: Highcharts 2+ required!]
    Code:
     * 09-11-2010
     * Version 2.+
     * 
     * 08-06-2010
     * Fixed the refresh bug. (Do not render if chart is not ready yet) 
     *
     * 28-04-2010
     * + Added class: Ext.ux.HighChart.Serie, Ext.ux.HighChart.LineSerie,  Ext.ux.HighChart.PieSerie, etc..
     * - Fixed: Wait for the panel to be resized to its correct size  (Instead of 0,0) after that create the chart.
     *
     * 19-04-2010
     * - Fixed: Series keep hidden after resize.
     * + bindComponent - Fixes the issue with the fitlayout.
     * + setTitle, setSubTitle - Change the title/subtitle of the chart
     * + addSeries - Add new series to the chart
    Attached Files
    Last edited by buz; 9 Nov 2010 at 12:33 AM. Reason: Update.

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,548
    Vote Rating
    873
    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


    First impression was looks good.

    Second was I like the tool tip that goes up or down with the actual chart!
    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
    Jun 2009
    Posts
    750
    Vote Rating
    0
    meroy is on a distinguished road

      0  

    Default


    This is very nice. Thank you.

  4. #4
    Sencha - Community Support Team mystix's Avatar
    Join Date
    Mar 2007
    Location
    Singapore
    Posts
    6,236
    Vote Rating
    5
    mystix will become famous soon enough

      0  

    Default


    sweet

    spotted one bug though: in the windowed chart, the tip doesn't get updated properly (i.e. it appears to be "stuck" once you're past a certain point) when the mouse cursor moves horizontally across the the, say, 20k line.

  5. #5
    Sencha Premium Member
    Join Date
    Jun 2008
    Posts
    324
    Vote Rating
    10
    Scorpie will become famous soon enough

      0  

    Default


    Nice work!
    I`m from Holland!

  6. #6
    Ext JS Premium Member
    Join Date
    Nov 2008
    Posts
    293
    Vote Rating
    3
    wki01 is on a distinguished road

      0  

    Default


    Is it possible to read data from a JsonStore?
    Someone has to put a small example here in the forum?

    Thank you very much

  7. #7
    Ext User
    Join Date
    Sep 2008
    Posts
    23
    Vote Rating
    0
    leonardb is on a distinguished road

      0  

    Default problem with adding series dynamically

    problem with adding series dynamically


    Hitting a problem with the current implementation of the renderChart method in Ext.ux.HighchartPanel.js

    Hoping someone has an idea of how to fix the behavior.

    Use case:
    Create base line graph with 1 plot.
    Add new series to graph on button click.
    resize graph.
    Result, 2nd series is missing as the renderChart method discards the existing chart and reloads the initial config.

    This is of course a bit of an issue if you want to have dynamic graphs in re-sizable windows or panels.

    Example (replaces line-basic.js in the examples):

    Code:
    Ext.onReady(function(){
    
        var graphWin = new Ext.Window({
            title: 'Resizeable Graph Window',
            resizeable: true,
            width: 800,
            height: 450,
            items: [
                {
                    xtype: 'button',
                    text: 'Add line',
                    handler: function(){
                        var add = {
                            name: 'London',
                            data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
                        };
                        Ext.getCmp('thechart').chart.addSeries(add,true);
                    }
                },
                new Ext.ux.HighchartPanel({
                    titleCollapse: true,
                    layout:'fit',
                    border: true,
                    id: 'thechart',
                    chartConfig: {
                        chart: {
                            id: 'thechart',
                            defaultSeriesType: 'line',
                            margin: [50, 150, 60, 80]
                        },
                        title: {
                            text: 'Monthly Average Temperature',
                            style: {
                                margin: '10px 100px 0 0' // center it
                            }
                        },
                        subtitle: {
                            text: 'Source: WorldClimate.com',
                            style: {
                                margin: '0 100px 0 0' // center it
                            }
                        },
                        xAxis: {
                            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 
                                'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
                            title: {
                                text: 'Month'
                            }
                        },
                        yAxis: {
                            title: {
                                text: 'Temperature (°C)'
                            },
                            plotLines: [
                                {
                                    value: 0,
                                    width: 1,
                                    color: '#808080'
                                }
                            ]
                        },
                        tooltip: {
                            formatter: function() {
                                return '<b>'+ this.series.name +'</b><br/>'+
                                    this.x +': '+ this.y +'°C';
                            }
                        },
                        legend: {
                            layout: 'vertical',
                            style: {
                                left: 'auto',
                                bottom: 'auto',
                                right: '10px',
                                top: '100px'
                            }
                        },
                        series: [
                            {
                                name: 'Tokyo',
                                data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
                            }
                        ]
                    }
                })
            ]
        });
        graphWin.show();
    });

  8. #8
    Sencha User
    Join Date
    Sep 2008
    Location
    Netherlands
    Posts
    106
    Vote Rating
    1
    buz is on a distinguished road

      0  

    Default


    I have created a simple fix for this problem. This will fix the problem of re-rendering the chart but only when the panel is not in a fitlayout. The content of the panel (the chart) wont resize. The highcharts developers should develop a function that can handle onResize.

    Code:
    /**
    * See http://www.extjs.com/forum/showthread.php?t=93669
    */
    Ext.ns('Ext.ux');
    
    Ext.ux.HighchartPanel = Ext.extend(Ext.Panel, {
    
        /**
         * Chart object
         */
        //chart: null,
        width: this.width || 600, //width should be greater then height, 2x works well
        height: this.height || 300,
    
        initComponent: function() {
            this.on('afterlayout', this.renderChart, this);
    
            Ext.ux.HighchartPanel.superclass.initComponent.call(this);
        },
    
        /**
         * Renders the chart
         */
        renderChart: function() {
            /**
             * This will recreate the chart when the layout has changed.
             * The highchart lib should have functions like resize(w,h).
             * since it doesnt have these functions yet, we have to do it this
             * dirty way.
             */
            //this.removeChart();
            if (this.chart) this.chart.calculatePositions()
                else {
                var currConfig = this.chartConfig;
    
                Ext.apply(currConfig.chart, {
                    renderTo: this.body.dom
                });
    
                this.chart = new Highcharts.Chart(currConfig);
    
                // In case of a window
                if (this.ownerCt){
                    this.ownerCt.on('move', function(){
                        this.chart.calculatePositions()
                    },
                    this);
                }
            }
        },
    
        removeChart: function() {
            if (this.chart) {
                this.chart.remove();
                this.chart = null;
            }
        }
        
        destroy: function() {
            if(this.chart) {
                this.chart.options.chart.renderTo = null;
                delete this.chart;
            }
    
            Ext.ux.HighchartPanel.superclass.destroy.call(this);
        }
         
    });
    And you need to add this to the Highcharts.chart class. at +/- line 1500
    Code:
            function calculatePositions(){
                position = updatePosition(container)
            }
    And add this at line 4050
    Code:
    chart.calculatePositions = calculatePositions
    Hopefully this will be added to the lib in 1.2.4

    I will continue development of a version that can handle resizing and moving of objects.
    Last edited by buz; 9 Mar 2010 at 1:03 PM. Reason: Fix

  9. #9
    Ext User
    Join Date
    Sep 2008
    Posts
    23
    Vote Rating
    0
    leonardb is on a distinguished road

      0  

    Default calculatePositions

    calculatePositions


    Thanks @buz, far more efficient than what I was doing in copying series to temp location and re-adding them to the config :-P

    One bug, need to add
    Code:
    chart.calculatePositions = calculatePositions;
    to the API methods in highcharts.src.js around line 3985 to expose the method. I have multiple graphs on page and was erroring out without this.

    Leonard

  10. #10
    Ext User
    Join Date
    Sep 2008
    Posts
    23
    Vote Rating
    0
    leonardb is on a distinguished road

      0  

    Default the resize issue

    the resize issue


    @buz

    Well, it seems the fix prevents the redraw of the graph, but unfortunately that does not solve my problem.

    I've opted to go with the shallow copy of the series and re-applying them to the new graph as I need the graphs to resize inside the layout:'fit' containers we use.

    I'm sure there has got to be a better way of doing this, but as you've previously commented and I discovered there is no mechanism in highcharts for resizing a rendered chart.

    For anyone else wanting to do this, the code I'm using below. Caveat. You my be defining unique Ids for all Series.

    Code:
    /**
    * See http://www.extjs.com/forum/showthread.php?t=93669
    */
    Ext.ns('Ext.ux');
    
    Ext.ux.HighchartPanel = Ext.extend(Ext.Panel, {
    
        /**
         * Chart object
         */
        //chart: null,
    
        initComponent: function() {
            this.on('afterlayout', this.renderChart, this);
    
            Ext.ux.HighchartPanel.superclass.initComponent.call(this);
        },
        /**
         * Hold a copy of series objects for re-adding after re-rendering
         */
        backupSeries: [],
        /**
         * Renders the chart
         */
        renderChart: function() {
            /**
             * Create a somewhat limited copy of existing series data
             * for re-applying after re-rendering
             */
            if (undefined != this.chart) {
                //console.log('this.chart',this.chart);
                this.backupSeries = [];
                for (var i = 0, len = this.chart.series.length; i < len; i++) {
                    var data = [], s = this.chart.series[i];
                    for (var c = 0, dlen = s.data.length; c < dlen; c++) {
                        data.push([s.data[c].x,s.data[c].y]);
                    }
                    var opt = {id:'',name:s.name,data:data};
                    if (typeof s.options != undefined && typeof s.options.id != undefined) opt.id = s.options.id;
                    if (typeof s.options  != undefined) Ext.apply(opt.options,s.options);
                    if (typeof s.color    != undefined) opt.color = s.color;
                    if (typeof s.selected != undefined) opt.selected = (s.selected) ? true:false;
                    if (typeof s.type     != undefined) opt.type  = s.type;
                    if (typeof s.visible  != undefined) opt.visible = (s.visible) ? true:false;
                    if (typeof s.xAxis    != undefined) Ext.apply(opt.xAxis, s.xAxis);
                    if (typeof s.yAxis    != undefined) Ext.apply(opt.yAxis,s.yAxis);
                    this.backupSeries.push(opt);
                }
            }
    
            /**
             * This will recreate the chart when the layout has changed.
             * The highchart lib should have functions like resize(w,h).
             * since it doesnt have these functions yet, we have to do it this
             * dirty way.
             */
            this.removeChart();
    
            var currConfig = this.chartConfig;
    
            Ext.apply(currConfig.chart, {
                renderTo: this.body.dom
                // To add event to the chart place them in the chart config section
                //,events: {
                //    beforerender: function(){
                //        alert('=beforeload')
                //    }
                //}
            });
    
            this.chart = new Highcharts.Chart(currConfig);
            //this.chart.showLoading();
            this.getEl().mask('Building graph...','x-mask-loading');
            // need to wait for chart to exist before adding series
            (function(el,chart,bs){
                if (bs.length > 0) {
                    for (var i=0;i<chart.series.length;i++) {
                        //remove series defined in default config
                        chart.get(chart.series[i].options.id).remove();
                    }
                }
                for (var i=0, l=bs.length;i<l;i++) {
                    chart.addSeries(bs[i]);
                }
                el.unmask();
            }).defer(5,this, [this.getEl(),this.chart,this.backupSeries]);
        },
    
        removeChart: function() {
            if (this.chart) {
                this.chart.remove();
                this.chart = null;
            }
        }
        /*
        destroy: function() {
            if(this.chart) {
                this.chart.options.chart.renderTo = null;
                delete this.chart;
            }
    
            Ext.ux.HighchartPanel.superclass.destroy.call(this);
        }
         */
    });
    
    Highcharts.Chart.prototype.remove = function () {
    
        /**
         * Clear certain attributes from the element
         * @param {Object} d
         */
        function purge(d) {
            var a = d.attributes, i, l, n;
            if (a) {
                l = a.length-1;
                for (i = l; i >= 0; i -= 1) {
                    n = a[i].name;
                    //if (typeof d[n] !== ‘object’) {
                    if (n == 'coords') {
                        //d.parentNode.removeChild(d);
                        d[n] = '0,0,0,0';
                    } else if (typeof d[n] != 'object') {
                        d[n] = null;
                    }
                }
            }
            a = d.childNodes;
            if (a) {
                l = a.length;
                for (i = 0; i < l; i += 1) {
                    purge(d.childNodes[i]);
    
                }
            }
    
        }
    
        // get the container element
        var container = this.imagemap.parentNode;
    
        // purge potential leaking attributes
        purge(container);
    
        // remove the HTML
        container.innerHTML = '';
    };
    
    Ext.reg('highchartpanel', Ext.ux.HighchartPanel);

Thread Participants: 125

  1. mystix (1 Post)
  2. medusadelft (5 Posts)
  3. marcing (2 Posts)
  4. sj137 (3 Posts)
  5. lossendae (1 Post)
  6. brookd (4 Posts)
  7. ccquiles (1 Post)
  8. jmass (1 Post)
  9. robin30 (2 Posts)
  10. Hemlock (1 Post)
  11. vahid4134 (1 Post)
  12. Sesshomurai (1 Post)
  13. pawelb1973 (1 Post)
  14. tonedeaf (2 Posts)
  15. mm_202 (1 Post)
  16. PTG (2 Posts)
  17. buergi (18 Posts)
  18. dorgan (18 Posts)
  19. mitchellsimoens (5 Posts)
  20. BlueCamel (1 Post)
  21. ganchsg (1 Post)
  22. Shaguar (5 Posts)
  23. enpasos (2 Posts)
  24. Eitschman (1 Post)
  25. Remy (1 Post)
  26. Urkman (4 Posts)
  27. bdunkin (1 Post)
  28. gthe (4 Posts)
  29. ttbgwt (1 Post)
  30. nathand (1 Post)
  31. Scorpie (1 Post)
  32. soulgen (6 Posts)
  33. leonardb (13 Posts)
  34. christophe67 (4 Posts)
  35. wki01 (1 Post)
  36. wemerson.januario (1 Post)
  37. nego2 (1 Post)
  38. tolichsvs (1 Post)
  39. xstegner (2 Posts)
  40. Alex84 (2 Posts)
  41. nxminh (1 Post)
  42. edykstra (3 Posts)
  43. neuralys (1 Post)
  44. r_honey (13 Posts)
  45. tvik (1 Post)
  46. xiongzhijian51 (1 Post)
  47. plaak (1 Post)
  48. meroy (1 Post)
  49. tryingextjs (2 Posts)
  50. talha06 (4 Posts)
  51. stephen.friedrich (1 Post)
  52. lpastor (1 Post)
  53. Manoharan (9 Posts)
  54. f.wolfsjaeger (2 Posts)
  55. shinkenno (2 Posts)
  56. asagala (2 Posts)
  57. DirkWei (1 Post)
  58. ralphmyers420 (12 Posts)
  59. ChiefDanGeorge (7 Posts)
  60. dvuja2 (1 Post)
  61. tripEXITo (1 Post)
  62. dr1811 (4 Posts)
  63. ljankowski (1 Post)
  64. robindel (1 Post)
  65. lj2008 (1 Post)
  66. ipebaikbanget (1 Post)
  67. cq.yangyu@gmail.com (1 Post)
  68. suntaek (1 Post)
  69. kurt schrauwen (1 Post)
  70. lalllall (1 Post)
  71. bdom (2 Posts)
  72. jackygurui (4 Posts)
  73. MeeMMeeM (6 Posts)
  74. denise (5 Posts)
  75. prabhu_patil (1 Post)
  76. araiczyk (1 Post)
  77. ferns (1 Post)
  78. yvestan (2 Posts)
  79. BigSeanDawg (1 Post)
  80. fabads (19 Posts)
  81. babaqga123 (1 Post)
  82. Mayus (1 Post)
  83. Christiand (3 Posts)
  84. greenst (2 Posts)
  85. SpinoWeb (4 Posts)
  86. vanessa_ng (2 Posts)
  87. toma (1 Post)
  88. 4fan (1 Post)
  89. donp (1 Post)
  90. karthik085 (7 Posts)
  91. aminaq (1 Post)
  92. fabiojpoli (8 Posts)
  93. sosy (1 Post)
  94. ericsmith66 (2 Posts)
  95. rebeccapeltz (4 Posts)
  96. kyrillos52 (2 Posts)
  97. guessit (7 Posts)
  98. israel.galan (5 Posts)
  99. Joe Kuan (12 Posts)
  100. Erci (5 Posts)
  101. liechtir (1 Post)
  102. wump (2 Posts)
  103. jprakash (1 Post)
  104. smkkiran (1 Post)
  105. framazz (4 Posts)
  106. pauldugas (1 Post)
  107. ToddJB (2 Posts)
  108. kaendsle (2 Posts)
  109. epimerde (1 Post)
  110. muralikr (1 Post)
  111. logon68 (1 Post)
  112. x0ner (1 Post)
  113. agus.delonge (1 Post)
  114. wuming444 (3 Posts)
  115. willigogs (4 Posts)
  116. Nicodemuz (1 Post)
  117. cmhampton (3 Posts)
  118. es3analytics (5 Posts)
  119. dgotty (2 Posts)
  120. spradeepv (1 Post)
  121. AshNathan (2 Posts)
  122. hassane (1 Post)
  123. Mr.Solomon (1 Post)
  124. senRsl (2 Posts)
  125. lbrutti (1 Post)