简体   繁体   中英

A block of JavaScript does not work when I add it to a function. can anybody help explain why?

I have managed to produce this

仪表板示例

When I click the 'Randomize' button, it produces 5 random integers which are used for the data points in the three graphs and the 'Count' list, and the charts are all instantly refreshed/updated. That part works fine.

However, at the bottom of the list on the right you will see it says "The Animal Is:..." with an animal name and a number. This data is pulled from a Google Sheet using the following:

function getRndInteger (min, max) {
  return Math.floor(Math.random() * (max - min)) + min
}

var k
var r

r = getRndInteger(2, 6)
const onDataLoaded = (data) => {
  const gscontent = data.feed.entry.find((entry) => entry.title.$t == 'A' + r).content.$t
  k = gscontent
  document.getElementById('data').innerHTML = 'The Animal Is: ' + k + ' (' + r + ')'
}

With this also present further down the page:

<script src="https://spreadsheets.google.com/feeds/cells/1dy1jneioOYWWanx2iW_FdaSxfXIf1h_d5sO7FB1LG4Q/1/public/basic?alt=json-in-script&callback=onDataLoaded"></script>

It basically looks up a random cell between A2 and A5 in my Google Spreadsheet and returns the name of the animal in that cell. The spreadsheet can be found here: https://docs.google.com/spreadsheets/d/1dy1jneioOYWWanx2iW_FdaSxfXIf1h_d5sO7FB1LG4Q

This works when the page loads, and when I refresh (F5) the page, but what I am trying to do is make it so that when I hit the Randomize button, as well as generating new data points and refreshing the three graphs, it also returns another animal name. However, when I try to add the code above to the relevant function, it does not seem to work.

The entire page looks like:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="mystyle.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-sm-3">
                <div class="corner"><h1>Bar & Line</h1><canvas id="myChart" height="200"></canvas></div>
            </div>
            <div class="col-sm-3">
                <div class="corner"><h1>Doughnut</h1><canvas id="myDoughnutChart" height="200"></canvas></div>
            </div>
            <div class="col-sm-3">
                <div class="corner"><h1>Pie</h1><canvas id="myPieChart" height="200"></div>
            </div>
            <div class="col-sm-3">
                <div class="corner">
                    <h2>Count</h2>
                    <p id="numa"></p>
                    <p id="numb"></p>
                    <p id="numc"></p>
                    <p id="numd"></p>
                    <p id="nume"></p>
                    <p id="data"></p>
                    <button type="button" class="btn btn-success" onclick="myFunction()">Randomize</button>
                </div>
            </div>
        </div>
    </div>

    <script>
        var a
        var b
        var c
        var d
        var e

        a = Math.floor(Math.random() * 101);
        b = Math.floor(Math.random() * 101);
        c = Math.floor(Math.random() * 101);
        d = Math.floor(Math.random() * 101);
        e = Math.floor(Math.random() * 101);

        document.getElementById("numa").innerHTML = 'Africa: ' + a;
        document.getElementById("numb").innerHTML = 'Asia: ' + b;
        document.getElementById("numc").innerHTML = 'Europe: ' + c;
        document.getElementById("numd").innerHTML = 'Latin America: ' + d;
        document.getElementById("nume").innerHTML = 'North America: ' + e;

        function myFunction() {
            a = Math.floor(Math.random() * 101);
            b = Math.floor(Math.random() * 101);
            c = Math.floor(Math.random() * 101);
            d = Math.floor(Math.random() * 101);
            e = Math.floor(Math.random() * 101);

            document.getElementById("numa").innerHTML = 'Africa: ' + a;
            document.getElementById("numb").innerHTML = 'Asia: ' + b;
            document.getElementById("numc").innerHTML = 'Europe: ' + c;
            document.getElementById("numd").innerHTML = 'Latin America: ' + d;
            document.getElementById("nume").innerHTML = 'North America: ' + e;

            myChart.data.datasets[0].data[0] = a;
            myChart.data.datasets[0].data[1] = b;
            myChart.data.datasets[0].data[2] = c;
            myChart.data.datasets[0].data[3] = d;
            myChart.data.datasets[0].data[4] = e;
            myChart.data.datasets[1].data[0] = a;
            myChart.data.datasets[1].data[1] = b;
            myChart.data.datasets[1].data[2] = c;
            myChart.data.datasets[1].data[3] = d;
            myChart.data.datasets[1].data[4] = e;

            myChart.update();

            myDoughnutChart.data.datasets[0].data[0] = a;
            myDoughnutChart.data.datasets[0].data[1] = b;
            myDoughnutChart.data.datasets[0].data[2] = c;
            myDoughnutChart.data.datasets[0].data[3] = d;
            myDoughnutChart.data.datasets[0].data[4] = e;

            myDoughnutChart.update();

            myPieChart.data.datasets[0].data[0] = a;
            myPieChart.data.datasets[0].data[1] = b;
            myPieChart.data.datasets[0].data[2] = c;
            myPieChart.data.datasets[0].data[3] = d;
            myPieChart.data.datasets[0].data[4] = e;

            myPieChart.update();

        }

    </script>

    <script>
        function getRndInteger(min, max) {
            return Math.floor(Math.random() * (max - min)) + min;
        }

        var k
        var r

        r = getRndInteger(2, 6)
        const onDataLoaded = (data) => {
            const gscontent = data.feed.entry.find((entry) => entry.title.$t == 'A' + r).content.$t
            k = gscontent
            document.getElementById('data').innerHTML = 'The Animal Is: ' + k + ' (' + r + ')'
        }
    </script>
    <script src="https://spreadsheets.google.com/feeds/cells/1dy1jneioOYWWanx2iW_FdaSxfXIf1h_d5sO7FB1LG4Q/1/public/basic?alt=json-in-script&callback=onDataLoaded"></script>
    <script src="ctx.js"></script>
    <script src="ctx2.js"></script>
    <script src="ctx3.js"></script>
</body>
</html>

When you load the spreadsheet you pass a query parameter called callback , this parameter basically tells the spread sheet to call a global function when its done loading so onDataLoaded is a function that gets the data when the spread sheet is loaded.

In order for that data to be accessible by any other function you first have to expose that data as a global variable.

Here is an example of the script section only (Without the chart code):

var spreadSheetData;
function myFunction() {
    var a = Math.floor(Math.random() * 101);
    var b = Math.floor(Math.random() * 101);
    var c = Math.floor(Math.random() * 101);
    var d = Math.floor(Math.random() * 101);
    var e = Math.floor(Math.random() * 101);

    document.getElementById("numa").innerHTML = 'Africa: ' + a;
    document.getElementById("numb").innerHTML = 'Asia: ' + b;
    document.getElementById("numc").innerHTML = 'Europe: ' + c;
    document.getElementById("numd").innerHTML = 'Latin America: ' + d;
    document.getElementById("nume").innerHTML = 'North America: ' + e;
    var r = getRndInteger(2, 6);
    const gscontent = spreadSheetData.feed.entry.find((entry) => entry.title.$t == 'A' + r).content.$t;
    document.getElementById('data').innerHTML = 'The Animal Is: ' + gscontent + ' (' + r + ')';
}

function getRndInteger(min, max) {
    return Math.floor(Math.random() * (max - min)) + min;
}

function onDataLoaded(data) {
    spreadSheetData = data;
    myFunction();
}

Here is a jsfiddle based on your code ( Note: I commented out code that wont work without your chart files): https://jsfiddle.net/z6bfs7wk/13/

There are multiple issues with the code in itself but I only made changes that affected your issue. Here is a small rundown of what changed:

  • I added a new variable called spreadSheetData that acts as the global variable that holds the spreadsheet data
  • onDataLoaded only sets the global variable and calls myFunction
  • myFunction now includes all of the randomization logic including the animal selection logic
  • A random row is selected every time myFunction is called so that you can reuse the spreadsheet data

I might suggest moving to an ajax call in the future so that you can handle loading errors and have more control over the data that is passed but that's just a suggestion.

@Rewire Thank you for the above response, that works great. Before I saw your reply, I found another solution in another SO post as follows (I have amended slightly to fit my needs):

 getCell = function(){
var r
r = Math.floor(Math.random() * (6 - 2)) + 2;
var api = 'https://spreadsheets.google.com/feeds/cells/';
var spreadsheet = '1dy1jneioOYWWanx2iW_FdaSxfXIf1h_d5sO7FB1LG4Q';
/*var worksheet =   $('#wID').val();*/
/*var row =         $('#r').val();*/
var col =         '1';
var url = api+spreadsheet+'/'+'1'+'/public/basic/R'+r+'C'+col+'?alt=json';
$.getJSON(url)
    .done(function(data){
        console.log(data)
        var jrest = data.entry.content['$t']
        document.getElementById("animal").innerHTML = jrest
        /*if(data.entry){
            $('#results').append(data.entry.title['$t']+': '+data.entry.content['$t']+' <br />');
        }else{
            $('#results').append('Failed to fetch data <br />');
        }
    })
    .fail(function(){
        $('#results').prepend('Failed to fetch data <br />');*/
    });
    }

Am I correct in my understanding that your solution is 'pure' JS whereas the solution I used above uses JQuery? Does either method have an advantage/disadvantage?

every time you call r it will give you a random value, so you can store one r value at a time in x for example and then use it as following:

r = getRndInteger(2,6)
const onDataLoaded = (data) => {
const x = r;
const gscontent = data.feed.entry.find((entry) => entry.title.$t == 'A'+x).content.$t
k = gscontent
document.getElementById('data').innerHTML = 'The Animal Is: ' + k + ' (' + x + ')'
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM