Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
necrotic
Aug 2, 2005
I owe my brother big time for this!

Dangerllama posted:

This code always returns the empty JSON via the API: [{}]

Because you are returning the initial value ({}) from getDuData. To make it work asynchronously you need to do something like:

code:
exports.index = function(req, res) {
  getDuData(function(data) {
    res.json([data]):
  });
};
function getDuData(cb) {
  var request_url = 'http://denveruniv-web.ungerboeck.com/coe/coe_p1_all.aspx?oc=01&cc=ICEDI30';

  request(request_url, function (error, response, html) {
    cb(response);
  });
}
Also yeah, look at something like async linked above.

Adbot
ADBOT LOVES YOU

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Given a stupid structure like:

JavaScript code:
var data = [
  {
    info: {id:'a'}
  },
  {
    info: {id: 'b'},
    children: [
      {
        info: {id: 'c'},
        children: [
          {
            info: {id: 'd'}
          },
          {
            info: {id: 'e'}
          }
        ]
      }
    ]
  },
  {
    info: {id: 'f'}
  },
  {
    info: {id: 'g'},
    children: [
      {
        info: {id: 'h'},
        children: [
          {
            info: {id: 'i'}
          }
        ]
      }
    ]
  }
];

So, you have an array of objects. All objects have an info property which points to an object with an id property. Some of these objects have a children property which is another array of these same type of objects all of which may or may not have children of their own.

The question is how to get a list of all parent objects info.id given a particular id.

It easy to write a function to recurse in and find any given id, but for some reason I'm having difficulty getting the parents ids which actually seems like it should be easy on first blush.

So...
  • Given 'i', I'd want to get ['h', 'g'].
  • Given 'e' or 'd', I'd get ['c', 'b'].
  • Given 'a', I'd get [].
  • Given 'c', I'd get ['b'].

For reference, my depth-first recursion function works just like you'd think:

JavaScript code:
function findId(data, id) {
  _.forEach(data, function(item) {
    if (item.info.id == id) {
      console.log("here it is");
      return false
    }
    if (item.children) {
      findId(item.children, id)
    }
  })
}
(I'm using lodash, thus the _.forEach)

waffle enthusiast
Nov 16, 2007



necrotic posted:

Because you are returning the initial value ({}) from getDuData. To make it work asynchronously you need to do something like:

code:
exports.index = function(req, res) {
  getDuData(function(data) {
    res.json([data]):
  });
};
function getDuData(cb) {
  var request_url = 'http://denveruniv-web.ungerboeck.com/coe/coe_p1_all.aspx?oc=01&cc=ICEDI30';

  request(request_url, function (error, response, html) {
    cb(response);
  });
}
Also yeah, look at something like async linked above.

Ahh…This makes a lot more sense. Thanks to you both.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Thermopyle posted:

For reference, my depth-first recursion function works just like you'd think:

JavaScript code:
function findId(data, id) {
  _.forEach(data, function(item) {
    if (item.info.id == id) {
      console.log("here it is");
      return false
    }
    if (item.children) {
      findId(item.children, id)
    }
  })
}

A good first step would be to modify this so you can actually make use of it in your program instead of just printing something out. A typical example for a "find" function would be returning true if the value is found, or false if it is not.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Jabor posted:

A good first step would be to modify this so you can actually make use of it in your program instead of just printing something out. A typical example for a "find" function would be returning true if the value is found, or false if it is not.

Sorry, that's not my actual function. I do lots of other things to the data structure so I just whipped up a quick example of how I recurse through it. I do actually do useful things with my actual code.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Thermopyle posted:

Sorry, that's not my actual function. I do lots of other things to the data structure so I just whipped up a quick example of how I recurse through it. I do actually do useful things with my actual code.

Okay then, so let's set about solving your problem. We solve recursive problems in two steps - our first step is to solve the base case(s).

Our first base case is when we've found the node we're after.
code:
function findPath(node, target) {
  if (node.id == target)
    return [];
}
Our second base case is if we've run out of nodes to search, and we still haven't found it. Adding that in gives us:
code:
function findPath(node, target) {
  if (node.id == target)
    return [];
  if (!node.children)
    return null;
}
The next step is to solve the incremental case - you want to write a function that invokes some other function to get the solution to a subproblem, and then modifies that result in order to get the solution to the bigger problem.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Heh, I guess I wasn't clear enough. I know the principles of writing recursive functions.

I kept screwing myself because I forgot about the difference between passing primitive values and objects in js as I don't write in js enough.

After taking a break I realized that I was passing a reference to the same array around to accumulate parents.

All sorted now. Sorry to waste your time.

Pollyanna
Mar 5, 2005

Milk's on them.


Okay, you know how XORing a byte by 0b0000 0000 (0x00) will flip the bits, right? e.g. 0b1010 1010 (0xAA) ^ 0b0000 0000 (0x00) -> 0b0101 0101 (0x55). You'd expect the same behavior in Javascript, since it's basic computer science and logic, right?

WRONG

code:
> 0xFF ^ 0x00
=> 255
What the gently caress? Why is this not flipping? What could possibly be loving this all up-

" MDN posted:

Bitwise XORing any number x with 0 yields x. Bitwise XORing any number x with -1 yields ~x.

:psyduck:

You have got to be kidding me.

Sedro
Dec 31, 2008
That's a great find, you should post in the coding horrors thread

YO MAMA HEAD
Sep 11, 2007

Sedro posted:

That's a great find, you should post in the coding horrors thread

That wasn't very nice

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.

Pollyanna posted:

Okay, you know how XORing a byte by 0b0000 0000 (0x00) will flip the bits, right?

What's 1 XOR 0?

You're not gonna have enough faces or palms when you get this all sorted out.

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
I've let this bang around in my head for a few days but I'm still confused. One of the early listings from Secrets of the JS Ninja has a line of code that doesn't seem to me to do anything (it's an assignment) but the code fails when it's omitted. Here's a fiddle.

JavaScript code:
<script>
    (function(){
			var queue = [], paused = false, results;
			
			this.test = function (name, fn) {
				queue.push(function (argument) {
					results = document.getElementById("results"); // what does this do?
					results = assert(true, name).appendChild(
						document.createElement("ul"));
					fn();
				});
				runTest();
			};

			this.pause = function() {
				paused = true;
				setTimeout(runTest, 1);
			};
			this.resume = function  () {
				paused = false;
				setTimeout(runTest, 1);
			}

			function runTest () {
				if (!paused && queue.length){
					queue.shift()();
					if(!paused){
						resume();
					}
				}
			}

			this.assert = function assert (value, desc) {
				var li = document.createElement("li");
				li.className = value ? "pass" : "fail";
				li.appendChild(document.createTextNode(desc));
				results.appendChild(li);

				if (!value){
					li.parentNode.parentNode.className = "fail";
				}
				return li;
			};
		})(); // inline declare-run

		window.onload = function  () {
			test("Async Test #1", function () {
				pause();
				setTimeout(function(){
					assert(true, "First test completed");
					resume();
				}, 1000);
			});
			test("Async Test #2", function () {
				pause();
				setTimeout(function(){
					assert(true, "Second test completed");
					resume();
				}, 1000);
			});
		}
</script>

<style> // this is SA's broken syntax highlighting - the code works
#results li.pass { color: green; }
#results li.fail { color: red; }
</style>
<body>
	<ul id="results"></ul>
</body>
The line commented What does this do? is the question. It sets results equal to something, with a method that I think should have no side effects, and then results is overwritten immediately with something else. But for some reason the page breaks when it's removed.

Please explain.

ostills
Oct 10, 2012

Newf posted:

JavaScript code:
	// snip snap

	var queue = [], paused = false, results;
			
	this.test = function (name, fn) {
		queue.push(function (argument) {
			
			// Notice the declaration above 'test' function
			results = document.getElementById("results"); // what does this do?
			
			// Notice 'assert' gets called here
			results = assert(true, name).appendChild(
				document.createElement("ul"));
			fn();
		});
		runTest();
	}

	this.assert = function assert (value, desc) {
		var li = document.createElement("li");
		li.className = value ? "pass" : "fail";
		li.appendChild(document.createTextNode(desc));
		
		// Here!
		results.appendChild(li);

		if (!value){
			li.parentNode.parentNode.className = "fail";
		}
		return li;
	}
Please explain.

The page breaks because the assert function tries to use the results variable, which will be undefined if you comment out the line you specified.

EDIT
If you take a look at the actual tests being run, you can see that the calling order will be something like test -> assert -> assert -> test -> assert -> ...

This in essence means that calling test will create a list under the #results DOM element, and subsequent calls to assert will append stuff to the created list. Calling test again will create another list under the #results DOM element, and so on.

ostills fucked around with this message at 12:02 on Dec 16, 2014

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

ostills posted:

The page breaks because the assert function tries to use the results variable, which will be undefined if you comment out the line you specified.

This is pretty terrible code.

ostills
Oct 10, 2012

Wheany posted:

This is pretty terrible code.

Yeah. I feel like there is a lesson about functions having side effects here.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

ostills posted:

Yeah. I feel like there is a lesson about functions having side effects here.

To me, it's more a lesson in naming your variables.

I would have probably used var resultsElem = document.getElementById("results"); and then testResult = assert()

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
Christ, this is obvious now, thanks. This sort of shared-scoping/variable re-use bites me constantly with js. Will probably keep getting me until my brain changes shape entirely.

Newf fucked around with this message at 13:01 on Dec 16, 2014

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?
It seems like results was never declared with a var (unless I missed it) so automatic globals strikes again. If you use "use strict" then you'd be forced to declare "results" in the relevant scope which would hopefully have made this more clear.

Edit: nevermind, it's declared at the top. Anyway, did you attempt to use the the browser's debug feature? It will point you to the line the error occurred on which should've helped you track this down. Trying to figure out what's going on when all you have is the page working or breaking is just going to lead to frustration.

HappyHippo fucked around with this message at 16:27 on Dec 16, 2014

Tomed2000
Jun 24, 2002

I'm working on a JS app that basically sits in other peoples' websites where we're compiling/minifying a local jQuery and various plugins into one file. This has been working fine but we've been trying to reduce the footprint of our app. The idea is to load jQuery only if the website we're in doesn't already have it. So basically I ended up with something like this when jQuery doesn't exist:

code:
var jqTag = document.createElement('script');
jqTag.type = 'text/javascript';
jqTag.src = 'https://code.jquery.com/jquery-1.10.2.min.js';
document.getElementsByTagName("head")[0].appendChild(jqTag);
The problem I'm having is that jQuery is now available at a later time than before thus the compressed/minified JavaScript plugins that I previously mentioned are trying to extend jQuery before it's being created. What is the usual solution to this problem? Do I need to move the declaration of our plugins into the jqTag.onload event? Usually I don't run into this because I'm just including JS in the HTML and the ordering matters but in this case all of the plugins and poo poo are compiled into one file.

Tomed2000 fucked around with this message at 23:14 on Dec 22, 2014

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Tomed2000 posted:

I'm working on a JS app that basically sits in other peoples' websites where we're compiling/minifying a local jQuery and various plugins into one file. This has been working fine but we've been trying to reduce the footprint of our app. The idea is to load jQuery only if the website we're in doesn't already have it. So basically I ended up with something like this when jQuery doesn't exist:

code:
var jqTag = document.createElement('script');
jqTag.type = 'text/javascript';
jqTag.src = 'https://code.jquery.com/jquery-1.10.2.min.js';
document.getElementsByTagName("head")[0].appendChild(jqTag);
The problem I'm having is that jQuery is now available at a later time than before thus the compressed/minified JavaScript plugins that I previously mentioned are trying to extend jQuery before it's being created. What is the usual solution to this problem? Do I need to move the declaration of our plugins into the jqTag.onload event? Usually I don't run into this because I'm just including JS in the HTML and the ordering matters but in this case all of the plugins and poo poo are compiled into one file.

You should start looking into a script loader - something like require.js (although there are many others.) A lot of work has been done on automating script loading and making it so pages load faster already, you probably shouldn't roll your own.

Storgar
Oct 31, 2011
Hey guys, uh someone in another thread told me to use Bootstrap or Foundation to handle my html/css templating and stuff. It looks like they both required jquery and use some javascript for certain features. Do any of you know how they behave with javascript disabled?

Hughmoris
Apr 21, 2007
Let's go to the abyss!
I have a simple, single webpage that has a button called "Start Over" with coding of:
code:
<INPUT type=reset value="Start Over" name=resetButton>&nbsp;
Is it possible to add a hidden functionality to that, using javascript? I have a JS function called "TestFunction". Is there a way to have "TestFunction" execute if I hold the Shift key + click on the "Start Over" button?

Gounads
Mar 13, 2013

Where am I?
How did I get here?

Storgar posted:

Hey guys, uh someone in another thread told me to use Bootstrap or Foundation to handle my html/css templating and stuff. It looks like they both required jquery and use some javascript for certain features. Do any of you know how they behave with javascript disabled?

For bootstrap, just stay away from the list of features under the "javascript" tab of the website.
http://getbootstrap.com/javascript/
Everything else will work fine.

But very few people even worry about browsers with no JS these days. The internet is just broken without it.

necrotic
Aug 2, 2005
I owe my brother big time for this!

Hughmoris posted:

I have a simple, single webpage that has a button called "Start Over" with coding of:
code:
<INPUT type=reset value="Start Over" name=resetButton>&nbsp;
Is it possible to add a hidden functionality to that, using javascript? I have a JS function called "TestFunction". Is there a way to have "TestFunction" execute if I hold the Shift key + click on the "Start Over" button?

Add a click event listener and check for the shiftKey modifier: http://jsfiddle.net/m9zy63v9/1/

Hughmoris
Apr 21, 2007
Let's go to the abyss!

necrotic posted:

Add a click event listener and check for the shiftKey modifier: http://jsfiddle.net/m9zy63v9/1/

Perfect, thank you.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Please use the "input" event, not "click", just in case someone uses the Enter or Space keys to activate your button. Unless those activate "click" now. They didn't used to.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Storgar posted:

Hey guys, uh someone in another thread told me to use Bootstrap or Foundation to handle my html/css templating and stuff. It looks like they both required jquery and use some javascript for certain features. Do any of you know how they behave with javascript disabled?

Disable javascript in your browser and check out their demo pages. Should give you a decent idea.

5pitf1re
Oct 4, 2014

space ninja in space

Storgar posted:

Hey guys, uh someone in another thread told me to use Bootstrap or Foundation to handle my html/css templating and stuff. It looks like they both required jquery and use some javascript for certain features. Do any of you know how they behave with javascript disabled?

Also I will never actually actively tell someone to use jQuery over vanillaJS, however if it gets the job done and you know why and how you are using it then that's fine. It's all about getting the job done right and in a timely manner.

necrotic
Aug 2, 2005
I owe my brother big time for this!

Suspicious Dish posted:

Please use the "input" event, not "click", just in case someone uses the Enter or Space keys to activate your button. Unless those activate "click" now. They didn't used to.

If he wants shift-enter to accomplish the same thing then yes. To mean that seems like an odd input combo as enter usually submits a form and its not that hard to accidentally hold shift in the process.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

5pitf1re posted:

Also I will never actually actively tell someone to use jQuery over vanillaJS, however if it gets the job done and you know why and how you are using it then that's fine. It's all about getting the job done right and in a timely manner.

I'm all like this except I always end up using jQuery for something and then I might as well use it for everything.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Thermopyle posted:

I'm all like this except I always end up using jQuery for something and then I might as well use it for everything.

I end up wanting to re-create chunks of jQuery in shim methods that just let me avoid all the tedium involved in dealing with the DOM.

Also, just using an example on the joke page
JavaScript code:
$.ajax({
  type: 'POST',
  url: "path/to/api",
  data: "banana=yellow",
  success: function (data) {
    alert("Success: " + data);
  },
});
still reads clearer than
JavaScript code:
var r = new XMLHttpRequest();
r.open("POST", "path/to/api", true);
r.onreadystatechange = function () {
  if (r.readyState != 4 || r.status != 200) return;
  alert("Success: " + r.responseText);
};
r.send("banana=yellow");
even though I can puzzle out what a readyState of 4 means in that context, because those numbers mean different things in different places (because of course they do) and they probably should have used r.DONE for clarity.

The usefulness of jQ as a band aid over all the incompatible mess in older browsers is fading with their market share, but I'll just replace it with something that lets me avoid dealing directly with the DOM because :effort:

5pitf1re
Oct 4, 2014

space ninja in space
Absolutely. VanillaJS can be tedious as hell, I agree.

With promises I tend to care less about those ugly parts as you can simply shim them away and have the bonus of promises so that you don't have to deal with spaghetti code and ugly callback handlers.

e: Just wondering, who in here ever used the Stack Overflow JavaScript chat?

5pitf1re fucked around with this message at 13:28 on Dec 31, 2014

Hughmoris
Apr 21, 2007
Let's go to the abyss!
Trying to teach myself Javascript using the book "A Smarter Way To Learn Javascript" and I'm already stumped. I'm trying to call a function, and I've copied/pasted it from the book but it is not working for me. When I click on "Click", nothing happens. Where am I going wrong?

http://jsfiddle.net/m9zy63v9/2/

spiritual bypass
Feb 19, 2008

Grimey Drawer
Two problems: there's line numbers in your JS and the JS was set to run onLoad, but your binding of the behavior is right in the HTML. Binding a function in an attribute only works for functions that are already declared, not tied to the load event, so switching it to <head> solves the problem.

You might not understand that second part at this point in your learning, which is perfectly normal.

Hughmoris
Apr 21, 2007
Let's go to the abyss!

rt4 posted:

Two problems: there's line numbers in your JS and the JS was set to run onLoad, but your binding of the behavior is right in the HTML. Binding a function in an attribute only works for functions that are already declared, not tied to the load event, so switching it to <head> solves the problem.

You might not understand that second part at this point in your learning, which is perfectly normal.

Can't believe I didn't see the numbers in the JS. :doh:

Thanks, I pasted everything into notepad and got it working.

spiritual bypass
Feb 19, 2008

Grimey Drawer
An editor with better syntax highlighting would've put some sort of error notification there :)

5pitf1re
Oct 4, 2014

space ninja in space

rt4 posted:

An editor with better syntax highlighting would've put some sort of error notification there :)

You just have to click the JSHint button and it will tell you that your JS was all messed up. ;)

Hughmoris
Apr 21, 2007
Let's go to the abyss!

5pitf1re posted:

You just have to click the JSHint button and it will tell you that your JS was all messed up. ;)

Just started using the JSFiddle site, that is pretty neat!

Smerdyakov
Jul 8, 2008

I've read a bunch of different answers but for some reason I can't wrap my head around the best way to access/iterate/loop through values that are nested but not in arrays.

As an example:

code:
var classroom = {
  room1: {
    students: {
      jim: {
       homework: "incomplete",
       grade: 50 
    },
      tim: {
       homework: "complete",
        grade: 100
      }
  }
    }
};

var extraCredit = function(student1, student2) {
console.log(eval("classroom.room1.students." + student1 +".grade") + 5);
console.log(eval("classroom.room1.students." + student2 +".grade") + 5);  
};
 
extraCredit("jim", "tim");
So this is bad for a huge number of reasons, but it at least shows what I want to do, though obviously I want to be able to modify the values, not just make them show up differently in the consoles. Still, that's not the problem.

What I'm trying to understand is a real way to loop through to these from the top down, preferably with something that would work recursively or would be able to keep drilling down through an unknown number of layers/splits. Say there were two classrooms and I wanted to give "flem" extra credit, but I don't know what classroom they're in and I'd like the function to figure it out. I've been googling it for a few hours and I'm still not sure how to use a for in loop to solve this, or if that's even the right tool.

Smerdyakov fucked around with this message at 11:30 on Jan 1, 2015

Adbot
ADBOT LOVES YOU

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Smerdyakov posted:

I've read a bunch of different answers but for some reason I can't wrap my head around the best way to access/iterate/loop through values that are nested but not in arrays.

As an example:

code:
var classroom = {
  room1: {
    students: {
      jim: {
       homework: "incomplete",
       grade: 50 
    },
      tim: {
       homework: "complete",
        grade: 100
      }
  }
    }
};

var extraCredit = function(student1, student2) {
console.log(eval("classroom.room1.students." + student1 +".grade") + 5);
console.log(eval("classroom.room1.students." + student2 +".grade") + 5);  
};
 
extraCredit("jim", "tim");
So this is bad for a huge number of reasons, but it at least shows what I want to do, though obviously I want to be able to modify the values, not just make them show up differently in the consoles. Still, that's not the problem.

What I'm trying to understand is a real way to loop through to these from the top down, preferably with something that would work recursively or would be able to keep drilling down through an unknown number of layers/splits. Say there were two classrooms and I wanted to give "flem" extra credit, but I don't know what classroom they're in and I'd like the function to figure it out. I've been googling it for a few hours and I'm still not sure how to use a for in loop to solve this, or if that's even the right tool.

Phone posting so not much detail for you but you want to use a "for in" loop, coupled with hasOWnProperty.

code:
for (var blah in classroom) {
    If classroom.hasOwnProperty(blah) {
        // do your thing
    }
}
The hasOWnProperty thing keeps you from running your checks on inherited proprties that come along with Object. That gives you a loop over your rooms, then you loop over the stuff in each room in a similar fashion. My assumption is that you'll have more than one room per "classrom", otherwise you can just iterate over the single room node inside instead.

Lumpy fucked around with this message at 18:31 on Jan 1, 2015

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply