Seasons - Load JavaScript function after page load ($ is undefined)

55 views
Skip to first unread message

Jared

unread,
Dec 3, 2019, 10:04:09 AM12/3/19
to weewx-user
Hi,

I made a little JavaScript function (wind.js) that will update the Seasons current_widget table with wind values from CRT realtime.txt.  The function works perfectly fine if I drop it into the browser console after the page loads, but for the life of me I cannot get this thing loaded by itself.  The console always shows the error $ is not defined in wind.js.  The errant line is tbl = $('.widget_contents', $('current_widget')); where I am grabbing the table object.

The index.html.tmpl <body> sections runs the setup(); function "onload" from the seasons.js file, which looks like it establishes the widgets.  If I drop <script src="wind.js"></script> after </body>, why are the widget objects still undefined?  I've tried various methods of deferring this script from being run, but nothing is working.

This is literally the first thing I've ever created in JavaScript and am a complete newbie in working with web programming, so go easy on me :)

Pat

unread,
Dec 3, 2019, 10:25:50 AM12/3/19
to weewx-user
$ is a shortcut for the word jQuery. Make sure you have the jquery library loaded in the header, or just replace $ with the word jQuery

Jared

unread,
Dec 3, 2019, 10:43:08 AM12/3/19
to weewx-user
Adding jQuery actually breaks the whole function haha.  I was trying to avoid jQuery because I'm so close without it (plus it's just more stuff I've never worked with).

And again, the function works perfectly fine if I load it into the browser myself after the page loads.  I don't think it's the function, I think it's the timing of it being loaded.

If you want to see what I mean, here is my page:  http://108.40.120.73:28926/weewx/index.html

You can see the undefined error in the console, but if you re-load the function into the console yourself after the page loads, you'll see it works fine.  It updates Wind in the Current Conditions window.

function get_realtime() {

  tbl = $('.widget_contents', $('current_widget'));
  r4 = tbl.getElementsByTagName("tr")[4];
  r4d1 = r4.getElementsByTagName("td")[1];
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      rt = this.responseText.split(" ")
      if (rt[6] && rt[13] && rt[11]) {
        rt = this.responseText.split(" ")
        rtstr = rt[6].split(".")[0]+" "+rt[13]+" "+rt[11];
        if ((parseInt(rt[6], 10) < 10)) {
          r4d1.innerHTML = rtstr;
        }
        else if ((parseInt(rt[6], 10) >= 20)) {
          r4d1.innerHTML = rtstr.fontcolor("red");
        }
        else {
          r4d1.innerHTML = rtstr.fontcolor("green");
        }
      }
    }
  };
  xhttp.open("GET", "realtime.txt", true);
  xhttp.send();
}

Pat

unread,
Dec 3, 2019, 10:51:35 AM12/3/19
to weewx-user
Strange, not sure how it's working for you in console. 

In my Chrome console I get this when I manually try it:

tbl = $('.widget_contents', $('current_widget'));
91wind.js:2 Uncaught ReferenceError: $ is not defined
    at get_realtime
(wind.js:2)
    at wind
.js:27

Jared

unread,
Dec 3, 2019, 10:57:44 AM12/3/19
to weewx-user
That is weird :)  Here is my console window in Firefox.  It shows the error at first, and then I paste the function in to reload it.  After that, Wind updates!  It's driving me crazy that I'm so close it working haha!

Pat

unread,
Dec 3, 2019, 10:58:42 AM12/3/19
to weewx-user
So it works, I assume you want the color to be green? You're still getting that error though. 

This function confuses me a bit. What is your end goal?

Jared

unread,
Dec 3, 2019, 11:05:30 AM12/3/19
to weewx-user
I only get the error at first, when the page attempts to load the JavaScript file.  Error at line 2.  tbl = $('.widget_contents', $('current_widget'));

The widget object is not yet available and is undefined.  But after the page loads, all of the page elements are available.  So when I paste the function and attempt to reload it, it properly finds the widget table and can continue.

The function updates the exact cell in the Current Conditions table for the current Wind value.  I want this Wind value to update in real time, without refreshing the page.  I have CRT dropping realtime.txt in the page root, so I grab the .txt file, parse out the Wind elements, and update that cell in the HTML table.

mwall

unread,
Dec 3, 2019, 11:08:06 AM12/3/19
to weewx-user


On Tuesday, December 3, 2019 at 10:04:09 AM UTC-5, Jared wrote:

I made a little JavaScript function (wind.js) that will update the Seasons current_widget table with wind values from CRT realtime.txt.  The function works perfectly fine if I drop it into the browser console after the page loads, but for the life of me I cannot get this thing loaded by itself.  The console always shows the error $ is not defined in wind.js.  The errant line is tbl = $('.widget_contents', $('current_widget')); where I am grabbing the table object.

first of all, nice work so far!

$ is used by jquery.  as far as i know it does nothing in pure javascript.



you probably want something like this:

var tbl = document.getElementById('current_widget')

then traverse the DOM from there to get the object you want.

you might want to put an id on each DOM element that you want to modify - then there is no need to traverse the DOM.  if you use the observation name for each id then that makes it even easier.

Jared

unread,
Dec 3, 2019, 11:09:25 AM12/3/19
to weewx-user
The green text shows if the wind speed is >= than 10 mph, and red if >= 20 mph.

Jared

unread,
Dec 3, 2019, 11:16:58 AM12/3/19
to weewx-user
Hi Matt, thanks a lot.  That's great info - I think I'm starting to see what you guys are saying about jQuery.  And I didn't even know what DOM was until today but I think that advice makes sense too :)  I haven't seriously looked at HTML in ... gotta be 20 years, and never CSS or JavaScript.

I'll keep working on it!  Thanks for the help.

Jared

unread,
Dec 3, 2019, 11:39:04 AM12/3/19
to weewx-user
Got it!  Combining the unique Id suggestion with using document.getElementById did the trick.  I had a feeling you could do something with Ids like that, but I didn't know how to do it, and of course I had other issues as well haha. 

Thanks a lot!

Jared

unread,
Dec 3, 2019, 7:57:14 PM12/3/19
to weewx-user
This is what I ultimately came up with, in case anyone ever comes across this in the future... A quick way to frequently update individual table fields from realtime.txt.  I went with two functions, one for each update cycle interval; the thought being to minimize GET requests to realtime.txt.  I have it updating every 2 seconds for wind and rain rate (I'm actually not even sure how often CRT updates this value in realtime.txt), and 30 seconds for everything else.  Just have to give the data tags unique IDs in the HTML and then reference them here in the getElementById methods.  Then the output is a matter of parsing CRT realtime.txt.  Not sure if any of this is poor form, but it seems to be working well. 

Thanks again for the push in the right direction.




function update_cycle1() {
  windcellobj = document.getElementById("rt_wind");
  rainratecellobj = document.getElementById("rt_rainrate");

  xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      rt = this.responseText.split(" ");
      if (rt[2]) {
        // Start Wind
        if (rt[6] != ("0.0")){

            rtstr = rt[6].split(".")[0]+" "+rt[13]+" °"+rt[11];
        } else {
            rtstr = rt[6].split(".")[0]+" "+rt[13];

        }
        if ((parseInt(rt[6], 10) < 10)) {
          windcellobj.innerHTML = rtstr;

        } else if ((parseInt(rt[6], 10) >= 20)) {
          windcellobj.innerHTML = rtstr.fontcolor("red");
        } else {
          windcellobj.innerHTML = rtstr.fontcolor("green");
        }
        // End Wind
        rtstr = rt[8]+" "+rt[16]+"/hr";
        rainratecellobj.innerHTML = rtstr;

      }
    }
  };
  xhttp.open("GET", "realtime.txt", true);
  xhttp.send();
}

function update_cycle2() {
  outtempcellobj = document.getElementById("rt_outtemp");
  dewpointcellobj = document.getElementById("rt_dewpoint");
  humiditycellobj = document.getElementById("rt_humidity");
  barocellobj = document.getElementById("rt_baro");
  windruncellobj = document.getElementById("rt_windrun");
  heatindexcellobj = document.getElementById("rt_heatindex");
  windchillcellobj = document.getElementById("rt_windchill");
  raintodaycellobj = document.getElementById("rt_raintoday");
  intempcellobj = document.getElementById("rt_intemp");

  xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      rt = this.responseText.split(" ");
      if (rt[2]) {
        rtstr = rt[2]+" °"+rt[14];
        outtempcellobj.innerHTML = rtstr;
        rtstr = rt[4]+" °"+rt[14];
        dewpointcellobj.innerHTML = rtstr;
        rtstr = rt[3]+"%";
        humiditycellobj.innerHTML = rtstr;
        rtstr = rt[10]+" "+rt[15];
        barocellobj.innerHTML = rtstr;
        rtstr = rt[17]+" mile";
        windruncellobj.innerHTML = rtstr;
        rtstr = rt[41]+" °"+rt[14];
        heatindexcellobj.innerHTML = rtstr;
        rtstr = rt[24]+" °"+rt[14];
        windchillcellobj.innerHTML = rtstr;
        rtstr = rt[9]+" "+rt[16];
        raintodaycellobj.innerHTML = rtstr;
        rtstr = rt[22]+" °"+rt[14];
        intempcellobj.innerHTML = rtstr;

      }
    }
  };
  xhttp.open("GET", "realtime.txt", true);
  xhttp.send();
}

// Run everything once, immediately.
update_cycle1();
update_cycle2();

// Start update intervals.
window.setInterval(function(){update_cycle1();}, 2000);
window.setInterval(function(){update_cycle2();}, 30000);

Reply all
Reply to author
Forward
0 new messages