2

Am trying to generate multiple line charts at one go using the code below. However, it isn't working. What would be the best way to generate graphs using a for/while or any other looping mechanism? I have many charts to generate.

   var db_query = Array();
    db_query[1] = <?php echo json_encode($db_query_1) ?>;
    db_query[2] = <?php echo json_encode($db_query_2) ?>;

    var chartConfig1 = clone(chartConfigLineOne);
    var chartConfig2 = clone(chartConfigLineOne);

    for(var i=1, len=2; i <= len; i++) {
        /* chart initialization */
        var chart_num = "chart" + i.toString();
        var plot_num =  "plot" + i.toString();
        var chartConfig_num = "chartConfig" + i.toString();
        /*alert(chart_num);
        alert(plot_num);
        alert(chartConfig_num);*/
        chart_num = AmCharts.makeChart(plot_num, chartConfig_num);

        $.ajax({
            type: 'POST',
            url: "query_db.php",
            data: {'db_que': db_query[i]},
            dataType: 'json',
            context: document.body,
            global: false,
            async:  true,
            success: function(data) {
                //alert(data);
                chart_num.dataProvider = data;
                chart_num.validateNow();
            }
        });
    }

UPDATED CODE

        <script type="text/javascript">

            var chartNameList = ['chart1','chart2'];
            var divId = ['plot1','plot2'];
            var configList = ['chartConfig1','chartConfig2'];
            var dbQuery = [];

            var chartConfig1 = clone(chartConfigLineOne);
            var chartConfig2 = clone(chartConfigLineOne);

             dbQuery[0] = <?php echo json_encode($db_query_1) ?>;
             dbQuery[1] = <?php echo json_encode($db_query_2) ?>;

            /* chart initialization */
            for(var i =0; i < 2; i += 1)   {
                //window["chart"+i] = createChartObj(divId[i],configList[i]);
                execDbQuery(divId[i],configList[i],dbQuery[i],chartNameList[i]);
            }
        </script>

/**
 * Execute of DB query
 */

function execDbQuery(divId, configObj, dbQuery, chartObj) {
    chartObj = AmCharts.makeChart(divId, configObj);
    $.ajax({
        type: 'POST',
        url: "query_db.php",
        data: {'db_que': dbQuery},
        dataType: 'json',
        context: document.body,
        global: false,
        async:  true,
        success: function(data) {
            //alert(data);
            chartObj.dataProvider = data;
            chartObj.validateNow();
        }
    });
} 
User12345
  • 325
  • 1
  • 7
  • 20
  • Don't mix `JavaScript` with `PHP` like `db_query[1] = ;`. It is terribly awful. And try not to use multiple `var a; var b; var c;`, but instead just use `var a = 123, b = 345, ...`. If you don't change your style of programming, some day your code will look like spagetti. – Jacobian Aug 29 '15 at 21:24
  • And instead of alerting, like `alert(data)` use `console.log(data)`. The style you are programming has become obsolete several years ago. So, you'd better read some books about professional programming in `JavaScript`. – Jacobian Aug 29 '15 at 21:27
  • Hello Jacobian - Thank you for the directions. Am a newbie in programming. THere's definitely a steep learning curve. Could I request your help to understand how to do what I'm trying to achieve? Also, if you could quickly brief me on how to access PHP data inside a javascript or another way of doing that altogether, that would be really helpful – User12345 Aug 29 '15 at 21:31
  • You already know how to access `PHP` data inside `Javascript`. This is actually what `ajax` does in your example. – Jacobian Aug 29 '15 at 21:33
  • Taking one step back, I have a main page where user chooses values. Then upon clicking submit, those values get posted to a PHP page where a SQL is constructed dynamically ( The receiving of data posed & building SQL query happens between section. After this section, I have a javascript section inside which I have ajax code. So, to access the SQL built int he PHP code, am using db_query[1] = Could you suggest a different way of doing this altogether please? – User12345 Aug 29 '15 at 21:39
  • I don't mind even getting rid of PHP if you recon using jquery/ajax altogether to receive the POST data from main page & then query the DB please.. – User12345 Aug 29 '15 at 21:39
  • And take some time to rethink what you are doing. It's not a good idea to pass db queries around - from client to server and vice versa. – Jacobian Aug 29 '15 at 21:46
  • Several years pass by and you will even start isolating `SQL` from `PHP` as much as possible, thinking of different application layers. But the sooner you start thinking in this direction, the furtherer you progress. – Jacobian Aug 29 '15 at 21:50
  • @user5274065 Your way to use the configuration does not work. You try to access the objects by passing their name as `String`. You should really start with basics in `JavaScript`. Read some books or at least take the time to go through some tutorials. – gerric Aug 30 '15 at 00:18
  • Hello Gerric - I looked around for ways to create dynamic variables such as the one here - http://stackoverflow.com/questions/2413414/is-there-an-easy-way-to-create-dynamic-variables-with-javascript but it still doesn't help my cause. I've updated the question with my updated code. Even though am trying to create the chart object in the function so as to avoid string/object problem, why is it not working? Even when I do chart_1= makeAmChart, "chart1" is a variable before the Amchart object is created & assigned to it isn't it? – User12345 Aug 30 '15 at 09:59

2 Answers2

2

As many comments correctly pointed out, you should probably start with rethinking your approach to data loading. Passing SQL queries in from client-side is asking for trouble. Will you be able to properly sanitize your queries to guard against malicious code? You can't be sure.

It's far more reasonable to move your DB access layer to PHP. You can pass in parameters needed for PHP script running on server to identify what needs to be loaded from DB and construct and execute actual SQL queries.

I.e.: query_db.php?chart_id=5

It would be up for PHP script to determine what to do. Given that you're currently using PHP to format those SQL queries, I can hardly image it can be a problem.

This brings us to another issue. Your current setup will run multiple AJAX requests simultaneously. While it's probably OK in the example you posted which has two charts, it can bog down the performance if you you have, say, 30 charts you need to load data for.

The solution would be to daisy-chain the loading. Do not start loading of another chart, until the previous one finishes loading. I.e.:

var charts = [ {
  "name": "chart1",
  "div": "plot1",
  "config": clone( chartConfigLineOne ),
  "query": <? php echo json_encode( $db_query_1 ) ?>
}, {
  "name": "chart2",
  "div": "plot2",
  "config": clone( chartConfigLineOne ),
  "query": <? php echo json_encode( $db_query_2 ) ?>
} ];

// do whatever modifications to each chart's config you need here
// ...

// function that creates the chart
function processNextChart() {
  if ( charts.length ) {
    var chart = charts.shift();
    $.ajax( {
      type: 'POST',
      url: "query_db.php",
      data: {
        'db_que': chart.query
      },
      dataType: 'json',
      context: document.body,
      global: false,
      async: true,
      success: function( data ) {
        chart.config.dataProvider = data;
        chartObj = AmCharts.makeChart( chart.div, chart.config );
        setTimeout( processNextChart, 100 );
      }
    } );
  }
}

// process first chart
processNextChart();

Please note how I simplified your whole chart array with a single array that holds all applicable data.

Please note, that the above code is not live-tested and is meant as a guiding point for your own implementation.

martynasma
  • 8,542
  • 2
  • 28
  • 45
  • Thank you very much Martyn. I appreciate your help very much. I'm learning a whole new way of doing things. Thank you for this. With reference to passing SQL queries around, i don't pass them from client/browser to PHP. I only pass things such as date range & option selected & post it to PHP which builds the SQL & executes it via ajax & plots the graph. To clarify, if I did a "view page source" or used to tools such as firebug, I wouldn't be able to see any SQL. I'll refer to your example & implement. Will let you know how I get on soon. – User12345 Aug 30 '15 at 10:21
  • Definitely. Just made some updates to the code. (noticed a bug) – martynasma Aug 30 '15 at 10:23
  • Hello Martyn - Could you please accept the "Edit". I've changed the sql query name for consistency. – User12345 Aug 30 '15 at 10:28
  • It was rejected by other editors before I could get to it. So I just made the same edits myself. – martynasma Aug 30 '15 at 17:06
  • Thank you Martin. Alongside this, I managed to create 3 layers of hierarchy. A layer where user input is taken, a layer where PHP receives the user input & makes ajax call to another layer where PHP builds the SQL, executes & returns a jSON array back to layer 2 which plots the graphs. Does this sound a good/better way of doing things? – User12345 Aug 30 '15 at 23:34
  • Sounds good. Except you probably meant that JavaScript makes AJAX calls, not PHP. Right? – martynasma Aug 31 '15 at 04:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/88347/discussion-between-user5274065-and-martynasma). – User12345 Aug 31 '15 at 07:35
0

Do not make ajax calls inside the for loop. It's a burden on server. The less calls you make, the more responsive is your ui. So, the better way to implement what you want is to get all data for all graphs in one ajax call and on success to iterate through the data building your graphs with AmCharts.makeChart.

Jacobian
  • 10,122
  • 29
  • 128
  • 221
  • I would love to implement it the way you suggest. Unfortunately, the SQL queries are all different ( They return different number of columns). That's why I'm after looping :-( – User12345 Aug 29 '15 at 21:49
  • 1
    Move this database logic to the server side. – Jacobian Aug 29 '15 at 21:52
  • I mean I have a bunch of SQL queries that I execute one after another & plot graphs for each of those query results. The SQL output has different number of columns. Example, Date, COUNT(A) as output of first SQL, DATE,COUNT(C) for 2nd, DATE, NAME, COUNT(F) for 3rd and many more combinations. – User12345 Aug 30 '15 at 10:02
  • I know this is not related to the question. But I just could not ignore the user: gerric's willingness to help User12345. Really awesome to see such a good coding community. Gerric started to help him out in this thread, http://stackoverflow.com/questions/32256442/amcharts-graph-not-displaying-values-use-ajax-to-plot-amcharrt-how-to-plot-amc and I followed the rabbit hole till here.. Awesome – DR. Jul 09 '16 at 20:19