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
Mindisgone
May 18, 2011

Yeah, well you know...
That's just like, your opinion man.

Suspicious Dish posted:

The API returns a LatLng, so you would still have to call toUrlValue() on it anyway.

I guess I don't see why adding an extra layer of application/x-www-form-urlencoded is a good idea. If you POST to /save-geolocation.php with geolocation data like 32.5,28.9, I think it's fairly clear.

how is this:
code:
myLatlng.lat().toFixed(6) + ',' + myLatlng.lng().toFixed(6) 

Adbot
ADBOT LOVES YOU

Mindisgone
May 18, 2011

Yeah, well you know...
That's just like, your opinion man.
So here is the new code (crossing my fingers here):
JavaScript code:
var geocoder;

function codeAddress() {
    var address = document.getElementById("zip").value;
    geocoder.geocode( { 'address': address}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
		  var latlong = results[0].geometry.location;
			newlatlong = latlong.lat().toFixed(6) + ',' + latlong.lng().toFixed(6) 
		  params = "latlng=" + encodeURIComponent(JSON.stringify(newlatlong))
		  request = new ajaxrequest()
		  request.open("POST","cwerksignup.php",true);
          request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
		  request.send(params);
      } else {
        alert("Geocode was not successful for the following reason: " + status);
      }
    });
  }
Which should POST: lat,long to the form element latlng correct? Also do I need the "var geocoder;" at the beginning or is that really just for clarity?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Gnack posted:

Because it's clearer. Labelling data just makes sense, I'm surprised this is at all controversial.
The URL should already be clearly labeling the data.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Mindisgone posted:

how is this:
code:
myLatlng.lat().toFixed(6) + ',' + myLatlng.lng().toFixed(6) 

Why? LatLng.toUrlValue() already takes a precision argument if you need that.

And you do not need to be using JSON.stringify, it's not a complex data structure, but a string. Sorry to lead you on a false trail like that.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Mindisgone posted:

So here is the new code (crossing my fingers here):
JavaScript code:
var geocoder;

function codeAddress() {
    var address = document.getElementById("zip").value;
    geocoder.geocode( { 'address': address}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
		  var latlong = results[0].geometry.location;
			newlatlong = latlong.lat().toFixed(6) + ',' + latlong.lng().toFixed(6) 
		  params = "latlng=" + encodeURIComponent(JSON.stringify(newlatlong))
		  request = new ajaxrequest()
		  request.open("POST","cwerksignup.php",true);
          request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
		  request.send(params);
      } else {
        alert("Geocode was not successful for the following reason: " + status);
      }
    });
  }
Which should POST: lat,long to the form element latlng correct? Also do I need the "var geocoder;" at the beginning or is that really just for clarity?

Where is geocoder declared originally?

If this is your whole code, you now have declared a global variable "geocoder", whose value is undefined.

Then, in function codeAddress, you call geocoder.geocode(), which would not work if geocoder is undefined.

If geocoder in declared somewhere else, you don't need to declare that variable at all.

More issues:
You declare the local variable address in codeAddress and latlong in the anonymous inner function. Then you just stop declaring local variables.

That means that newlatlong, params and request become global variables.

You don't use address anywhere except in the inner function, so you should move that declaration there. e: Nevermind, you use it as a parameter in the geocode function call.

Wheany fucked around with this message at 19:04 on Jul 10, 2012

Mindisgone
May 18, 2011

Yeah, well you know...
That's just like, your opinion man.

Wheany posted:

Awesome information

code:
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map;

function codeAddress() {
    var address = document.getElementById("zip").value;
    geocoder.geocode( { 'address': address}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
          var latlong = results[0].geometry.location;
        var newlatlong = LatLng.toUrlValue(latlong) 
       var params = "latlng=" + encodeURIComponent(JSON.stringify(newlatlong))
          request = new ajaxrequest()
          request.open("POST","cwerksignup.php",true);
          request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
          request.send(params);
      } else {
        alert("Geocode was not successful for the following reason: " + status);
      }
    });
  }
Hows this? I forgot I am not really posting the whole script so you didn't see some declarations.

This is a combination of me being stupid / javascript incompetent / and having to use google's code (not that there is anything wrong with google).

Mindisgone fucked around with this message at 21:51 on Jul 10, 2012

prom candy
Dec 16, 2005

Only I may dance
(My comments are in the code)

code:
function codeAddress() {
  
  // You can declare your vars like this, it's nice and clean.
  // Note the commas at the end of each line except the last one
  
  var geocoder = new google.maps.Geocoder(),
      maps     = new google.maps.Map,
      address  = document.getElementById("zip").value;

  geocoder.geocode( { 'address': address}, function(results, status) {
    
    // Variables have function scope so it's a good idea to declare them
    // at the beginning of the function, even if you're not going to be
    // setting them until you're inside a conditional.  Variables do not
    // have block scope, so while it's perfectly valid to declare them
    // inside your conditional it's not considered best practice to do so.
    
    var latlong, newlatlong, params, request;
    if (status == google.maps.GeocoderStatus.OK) {
      
      // I like to align my assignment operators when I'm doing a lot of
      // assignment at once.  You also need to make sure your indentation
      // is consistent.
      
      latlong    = results[0].geometry.location,
      newlatlong = LatLng.toUrlValue(latlong),
      params     = "latlng=" + encodeURIComponent(JSON.stringify(newlatlong));
      request    = new ajaxrequest();
      
      request.open("POST","cwerksignup.php",true);
      request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
      request.send(params);
    } else {
      alert("Geocode was not successful for the following reason: " + status);
    }
  });
}

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
It would be latlong.toUrlValue(6), and you should lose the JSON.stringify.

I also don't actually know if XMLHttpRequest will URL-encode the parameters automatically. I thought it wouldn't, but then I realized how silly that would be. If it already does it, the component will be double-encoded, which is a bad idea. But since we're guaranteed to not use any "off-limits" characters, it's a no-op anyway.

Mindisgone
May 18, 2011

Yeah, well you know...
That's just like, your opinion man.
This is stressing me out at this point and I really appreciate everyone's input, it has been very helpful. This is what I am working with:
code:
function codeAddress() {
	
	 // You can declare your vars like this, it's nice and clean.
  // Note the commas at the end of each line except the last one
  
  var geocoder = new google.maps.Geocoder(),
      maps     = new google.maps.Map,
      address  = document.getElementById("zip").value;

  geocoder.geocode( { 'address': address}, function(results, status) {
    
    // Variables have function scope so it's a good idea to declare them
    // at the beginning of the function, even if you're not going to be
    // setting them until you're inside a conditional.  Variables do not
    // have block scope, so while it's perfectly valid to declare them
    // inside your conditional it's not considered best practice to do so.
    
    var latlong, newlatlong, params, request;
    if (status == google.maps.GeocoderStatus.OK) {
      
      // I like to align my assignment operators when I'm doing a lot of
      // assignment at once.  You also need to make sure your indentation
      // is consistent.
      
      latlong    = results[0].geometry.location,
      newlatlong = latlong.toUrlValue(6),
      params     = "latlng=" + encodeURIComponent(newlatlong);
      request    = new ajaxrequest();
      
      request.open("POST","cworksignup.php",true);
      request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
      request.send(params);
			
     } else {
       	alert("Geocode was not successful for the following reason: " + status);
      }
    });
  }
What I have is a sign up form called cworksignup.php which has an include_once 'cworkheader.php'; which contains my javascript via an echo <<<_END statement. The sign up form has a zip code text field which when the form is submitted is supposed to pass the zip code to this javascript and the script should pass the lat and long back to the php script so it can insert it into the mysql table. What gets me down about this is I wrote a whole dynamic php website which works beautifully and the minute I try and implement javascript I'm failing. I still think this is an issue with my javascript but if anyone can confirm this code works it would help me narrow down the problem.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
What is the error?

Mindisgone
May 18, 2011

Yeah, well you know...
That's just like, your opinion man.

quote:

A form was submitted in the windows-1252 encoding which cannot encode all Unicode characters, so user input may get corrupted. To avoid this problem, the page should be changed so that the form is submitted in the UTF-8 encoding either by changing the encoding of the page itself to UTF-8 or by specifying accept-charset=utf-8 on the form element.

that was a warning and:


is an error and the link is the following which is a lot to swallow:

quote:

function Ig(a){return(a=a.b[2])?new tg(a):Og}var Pg=new ug,Qg=new vg;var Lg;function Rg(){this.b=new S(128,128);this.j=256/360;this.e=256/(2*n.PI)}Rg[F].fromLatLngToPoint=function(a,b){var c=b||new S(0,0),d=this.b;c.x=d.x+a.lng()*this.j;var e=Jd(n.sin(Md(a.lat())),-(1-1E-15),1-1E-15);c.y=d.y+0.5*n.log((1+e)/(1-e))*-this.e;return c};Rg[F].fromPointToLatLng=function(a,b){var c=this.b;return new P(Nd(2*n[Tb](n.exp((a.y-c.y)/-this.e))-n.PI/2),(a.x-c.x)/this.j,b)};function Sg(a,b,c){if(a=a[fb](b))c=n.pow(2,c),a.x*=c,a.y*=c;return a};function Tg(a,b){var c=a.lat()+Nd(b);90<c&&(c=90);var d=a.lat()-Nd(b);-90>d&&(d=-90);var e=n.sin(b),f=n.cos(Md(a.lat()));if(90==c||-90==d||1E-6>f)return new oe(new P(d,-180),new P(c,180));e=Nd(n[ec](e/f));return new oe(new P(d,a.lng()-e),new P(c,a.lng()+e))};function Ug(a){this.bc=a||0;this.nc=Q[u](this,Ve,this,this.H)}K(Ug,W);Ug[F].P=function(){var a=this;a.l||(a.l=m[Kb](function(){a.l=ba;a.Z()},a.bc))};Ug[F].H=function(){this.l&&m[db](this.l);this.l=ba;this.Z()};Ug[F].Z=Zc();Ug[F].R=bd(2);function Vg(a,b){var c=a[x];sa(c,b[s]+b.L);Ma(c,b[A]+b.l)}function Wg(a){return new V(a[jb],a[hc])};function Xg(a){this.b=a||[]}var Yg;function Zg(a){this.b=a||[]}var $g;function ah(a){this.b=a||[]}var bh;function ch(a){this.b=a||[]}var dh;Ya(ch[F],function(){var a=this.b[2];return a!=k?a:0});ya(ch[F],function(a){this.b[2]=a});function eh(a,b,c){Ug[Gc](this);this.B=b;this.A=new Rg;this.D=c+"/maps/api/js/StaticMapService.GetMapImage";this.set("div",a)}K(eh,Ug);var fh={roadmap:0,satellite:2,hybrid:3,terrain:4},gh={"0":1,2:2,3:2,4:2};G=eh[F];G.Gf=If("center");G.Hf=If("zoom");function hh(a){var b=a.get("tilt")||a.get("mapMaker")||I(a.get("styles")),a=a.get("mapTypeId");return b?k:fh[a]}

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
The first is because of a bad charset. Add <meta charset=utf8> inside your <head> tag.

The second is you using the Google API wrong. Using Firebug (or the JavaScript Debugger included in the latest Firefox Nightlies), can you get a stack trace and see where that error comes from in your code?

smug forum asshole
Jan 15, 2005
Have you guys seen this js-assessment repo?

Pretty neat test IMO: https://github.com/rmurphey/js-assessment

EVGA Longoria
Dec 25, 2005

Let's go exploring!

Does anyone have experience with Tempo.js? I'm having the oddest issue.

I've got the following template:

code:
			<div id="queuesTableDiv" style="display:none">
				<table id="queuesTable" class="table table-striped table-bordered table-condensed">
					<tbody data-template>
						<tr class="item-{{_tempo.index}}"><th>Successful Syncs</th><td>{{SUCCESS}}</td></tr>
						<tr><th>Failed Syncs</th><td>{{FAILED}}</td></tr>
						<tr><th>Final Failures</th><td>{{FINALFAILED}}</td></tr>
						<tr><th>Queue Length</th><td>{{QUEUE}}</td></tr>
				</table>
			</div>
And the below JS for it:

JavaScript code:
var omsQueueString = [% omsQueues %];
Tempo.prepare('queuesTable').render(omsQueueString);
$('#queuesTableDiv').fadeIn('fast');

$(document).ready(function()
    {

		$('#queuesTableReload').click(function() {
				$('#queuesTableDiv').fadeTo('slow', 0, function() {
					var qutr = $.ajax('[% request.uri_base %]/omsQueues')
					qutr.done(function(data) {
						var queuesJson = data;
						console.log(queuesJson);
						Tempo.prepare('queuesTable').render(queuesJson);
						$('#queuesTableDiv').fadeTo('slow',1);
				})
		})
	})

});
Returned JSON:
JavaScript code:
[
   {
      "FINALFAILED" : "2",
      "QUEUE" : "0",
      "SUCCESS" : "3410",
      "FAILED" : "13"
   }
]
So on the initial load, it works great:

code:
<table id="queuesTable" class="table table-striped table-bordered table-condensed">
					<tbody data-template="">
						<tr class="item-0"><th>Successful Syncs</th><td>3866</td></tr>
						<tr><th>Failed Syncs</th><td>12</td></tr>
						<tr><th>Final Failures</th><td>2</td></tr>
						<tr><th>Queue Length</th><td>0</td></tr>
				</tbody></table>
On reload, however, it goes absolutely nuts, repeating itself nearly 100 times:

code:
<table id="queuesTable" class="table table-striped table-bordered table-condensed">
					<tbody data-template="">
						<tr class="item-0"><th>Successful Syncs</th><td>3866</td></tr>
						<tr><th>Failed Syncs</th><td>12</td></tr>
						<tr><th>Final Failures</th><td>2</td></tr>
						<tr><th>Queue Length</th><td>0</td></tr>
				</tbody><tbody data-template="">
						<tr class="item-0"><th>Successful Syncs</th><td>3866</td></tr>
						<tr><th>Failed Syncs</th><td>12</td></tr>
						<tr><th>Final Failures</th><td>2</td></tr>
						<tr><th>Queue Length</th><td>0</td></tr>
				</tbody><tbody data-template="">
						<tr class="item-0"><th>Successful Syncs</th><td>3866</td></tr>
						<tr><th>Failed Syncs</th><td>12</td></tr>
						<tr><th>Final Failures</th><td>2</td></tr>
						<tr><th>Queue Length</th><td>0</td></tr>
				</tbody><tbody data-template="">
						<tr class="item-0"><th>Successful Syncs</th><td>3866</td></tr>
						<tr><th>Failed Syncs</th><td>12</td></tr>
						<tr><th>Final Failures</th><td>2</td></tr>
						<tr><th>Queue Length</th><td>0</td></tr>
				</tbody>[snip]</table>
The {{_tempo.index}} shows the iteration for Tempo. As you can see, it's the initial iteration.

I'm using identical javascript somewhere else, and it works absolutely fine. The only differences are in the template and the data being returned. In the other case, it's supposed to repeat.

Does anyone have any experience with this? Or have any ideas how to go about debugging it?

DrunkenAstronaut
Dec 2, 2005
Have you logged how many times the click-event is triggered?

Throw a console.log("Click event triggered"); in there somewhere.

Seems a bit weird that it would trigger that many times, but I've seen it trigger multiple times before.

You could try putting down some breakpoints in Firebug or Chrome Developer Tools, and step through the process. However, if it's the click event triggering multiple times, this will probably not show up when breaking and stepping through.

Kallikrates
Jul 7, 2002
Pro Lurker
I suppose I have a webapp architecture question: I have three JSON files that represent a couple different data models of different objects.

The main JSON is parsed, and I pull display Data out: element SVG representation, and title, then display the SVG with Raphael. I also bind certain events of that SVG's DOM node, to load and unload data in a detail view.

The webpage is twitter bootstrap, and the detail info is just loaded and unloaded into selectors within a modal view.

I'm wondering if theres a better way to do this, load -> get json -> parse JSON into Raphael svgs -> bind events -> events load 'x' data in selector https://gist.github.com/3145532

Can anyone think of a better approach? I thought of just having the 'summary' view SVG's static and having the detailed data for each object in the JSON and no SVG data. (load detail graphics via ajax, versus Raphael from JSON). Some detail views look like they might require templates and many of these objects are also connected via relationships I would like to exploit in visually appealing ways.

I keep bumping up against my inexperience with JS, and areas where jquery doesnt play nice with Raphael objects.

Edit: I thought of moving to Backbone to handle stuff, but I wonder if that is overkill.

Kallikrates fucked around with this message at 19:04 on Jul 19, 2012

EVGA Longoria
Dec 25, 2005

Let's go exploring!

DrunkenAstronaut posted:

Have you logged how many times the click-event is triggered?

Throw a console.log("Click event triggered"); in there somewhere.

Seems a bit weird that it would trigger that many times, but I've seen it trigger multiple times before.

You could try putting down some breakpoints in Firebug or Chrome Developer Tools, and step through the process. However, if it's the click event triggering multiple times, this will probably not show up when breaking and stepping through.

I ended up figuring this out in the middle of filing a bug report. I set the content-type wrong (application/ajax instead of application/json) which meant the browser was putting it inside a string. Chrome was dealing with this and displaying it as a full object in the Developer tools, had to use Firebug to see the "s.

dadrips
Jan 8, 2010

everything you do is a balloon
College Slice
I have an animated canvas element shimmed to act as a page background on my website which is exhibiting a frustrating problem. I recently added a new "fade-out" effect based on this example, where the alpha value of the pixels in the raw ImageData is subtracted at each tick until they reach zero. The effect itself works well but results in ballooning memory usage in both Chrome and Firefox - in both cases, the usage builds up to around 250MB+ before sharply dropping and starting to build up again. IE9 seems to exhibit the same problem but over a much smaller range, with its usage violently fluctuating between 15-30MB. When I comment out the call to the fading routine, the memory usage remains constant in all three browsers. After a bit of searching I came a few posts on stackoverflow about similar issues, each with various solutions which were ineffective. I also came across this bug report for Chrome which seems to say it's a resolved issue. Has anybody else come across this before?

dizzywhip
Dec 23, 2005

I don't know the specifics of how your canvas drawing is implemented, but you could just try implementing the fade out in a different way. Try using canvas's globalOpacity property.

Jo
Jan 24, 2005

:allears:
Soiled Meat
My retarded question:

JavaScript code:
			function(){ // On Enter
				display.innerHTML += "What's your name?  ";
				var textfield = document.createElement('input');
				textfield.type = 'text';
				textfield.id = "player_name_field";
				display.appendChild(textfield);
			},
			function() { // On Exit
				var namefield = document.getElementById("player_name_field");
				player.name = namefield.text;
			},
In the OnExit function, the namefield is null despite adding the textfield to the document.

On a tangentially related note, I'm curious about why textfield.onchange = function(){blah;} isn't working.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





Jo posted:

My retarded question:

JavaScript code:
			function(){ // On Enter
				display.innerHTML += "What's your name?  ";
				var textfield = document.createElement('input');
				textfield.type = 'text';
				textfield.id = "player_name_field";
				display.appendChild(textfield);
			},
			function() { // On Exit
				var namefield = document.getElementById("player_name_field");
				player.name = namefield.text;
			},
In the OnExit function, the namefield is null despite adding the textfield to the document.

On a tangentially related note, I'm curious about why textfield.onchange = function(){blah;} isn't working.

You don't really provide that much information but I'm going to assume that display is actually attached to the DOM, correct?

Jo
Jan 24, 2005

:allears:
Soiled Meat

Strong Sauce posted:

You don't really provide that much information but I'm going to assume that display is actually attached to the DOM, correct?

Yes. You are correct.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





Jo posted:

Yes. You are correct.

Can you post the whole code onto jsfiddle then?

Jo
Jan 24, 2005

:allears:
Soiled Meat

Strong Sauce posted:

Can you post the whole code onto jsfiddle then?

Sure. Thank you much. I'm having a bit of trouble getting it to show up correctly, but this should provide a good idea. I'm fairly sure it's something simple that I'm just missing out on, but can't figure out why it's not behaving.

EDIT: Found the problem. I'm clearing the item before executing onExit.

JavaScript code:
...
		function goToLocation(newLoc) {
			clearDisplay();
			if(currentLocation != null) {
				if(currentLocation.onExit != null) { currentLocation.onExit(); }
...
Unfortunately, this rules out a few things I'd hoped to be able to do and means I need to rely on attaching an event listener to a text box.

textfield.onchange = func; fails. textfield.addEventListener("change", func, false); fails. Lost as to why neither works.

Jo fucked around with this message at 06:49 on Jul 25, 2012

TildeATH
Oct 21, 2010

by Lowtax
Alright, stopPropagation() is killing me. It's literally killing me. I put event.target.stopPropagation() in the function where I want the bubbling to stop (it's also the top event) but it makes no difference. I put it in the bottom function, no difference. I changed it to event.stopPropagation() and event.stopImmediatePropagation() and nothing changed. I played a fiddle while I started dropping stopPropagation() all over my code and nothing happened. I've read so much about bubbling and capturing and event listeners that I could shoot myself, and I still can't figure it out.

Must calm down, JavaScript making me want to kill myself...

To be clear, I'm calling a click event on an SVG <g> object that's the child of an SVG <svg> object. The <g> click event calls function foo(), the <svg> click event calls function bar()

code:
function foo() {
    console.log("I want this function to work.")
    event.target.stopPropagation() //Here?
}

function bar() {
    console.log("If you can read this, just shoot yourself, it's the easy way out."
}

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

TildeATH posted:

code:
function foo() {
    console.log("I want this function to work.")
    event.target.stopPropagation() //Here?
}

function bar() {
    console.log("If you can read this, just shoot yourself, it's the easy way out."
}

Just in case you missed it, you are doing this?

code:
function foo(event) {
...
}

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

TildeATH posted:

Alright, stopPropagation() is killing me. It's literally killing me. I put event.target.stopPropagation() in the function where I want the bubbling to stop (it's also the top event) but it makes no difference. I put it in the bottom function, no difference. I changed it to event.stopPropagation() and event.stopImmediatePropagation() and nothing changed. I played a fiddle while I started dropping stopPropagation() all over my code and nothing happened. I've read so much about bubbling and capturing and event listeners that I could shoot myself, and I still can't figure it out.

Must calm down, JavaScript making me want to kill myself...

To be clear, I'm calling a click event on an SVG <g> object that's the child of an SVG <svg> object. The <g> click event calls function foo(), the <svg> click event calls function bar()

code:
function foo() {
    console.log("I want this function to work.")
    event.target.stopPropagation() //Here?
}

function bar() {
    console.log("If you can read this, just shoot yourself, it's the easy way out."
}

What is the global variable "event" you are referencing in your foo function set to when it's called? My guess is, not the click event you are trying to stop propagation on.

TildeATH
Oct 21, 2010

by Lowtax

Fruit Smoothies posted:

Just in case you missed it, you are doing this?

code:
function foo(event) {
...
}

Right, now I understand why I can't seem to understand this. I'm using d3.js, which overrides the traditional event listener with one that binds the data and position in the array of the object that I'm clicking. It uses a global d3.event that should give me the ability to stopPropagation() with, but isn't, so I really do need to figure out how to do it in d3 versus in js. I had assumed that the structure was the same and that there was an "event" global that I was accessing, and not that d3 had modified that. No wonder all the generic information about handling stopPropagation() wasn't making sense to me. I guess this is how I learns JavaScript.

If anyone here has experience doing this in d3.js, that would be great, otherwise, no worries, this has pointed me (finally) in the right direction.

All Hat
Jul 11, 2008

He that is without int among you, let him first cast a long

I'm doing something stupid, that is, making a snake game in html and javascript sans jquery and canvas.

It's working surprisingly well so far, except for one little thing. I'm adding a board editor, which is simply a 70 x 40 grid of checkboxes, which corresponds to blocks on the board, and that can be used to add walls.

For some reason, adding these checkboxes are quite slow in Opera. I first stored references to them in an two-dimensional array. That took approximately 3.4 seconds.

After I removed the arrays, it takes ~2.5 - ~2.9 seconds doing layout.

This snippet is responsible for the checkboxes. Anyone see what is wrong?

code:
bobble.boardEditor = function () {
	//wrapping element for checkboxes
	var boardEditor = document.createElement("div"),
		i,
		j,
	//temp variable for checkboxes
		cBox;
	boardEditor.id = "boardEditor";
	boardEditor.style.clear = "both";
	
	// 40 rows deep
	for (j = 0; j < 40; j += 1) {
		// 70 columns wide
		for (i = 0; i < 70; i += 1) {
			cBox = document.createElement("input");
			cBox.type = "checkbox";
			//coordinates for "hit" "detection"  
			cBox.setAttribute("data-x", i);
			cBox.setAttribute("data-y", j);
			//appends to wrapping element to minimize interaction with the dom
			boardEditor.appendChild(cBox);
		}
		boardEditor.appendChild(document.createElement("br"));
	}
	// appends everything to the document, and adds an eventlistener.
	document.getElementById("main").appendChild(boardEditor);
	if (document.addEventListener) {
		document.getElementById("boardEditor").addEventListener('click', bobble.updateBoard, false);
	} else if (document.attachEvent) {
		document.getElementById("boardEditor").attachEvent('onclick', bobble.updateBoard);
	}
};
If anyone has a better idea for this kind of level editing, let me know. I'm only doing this to feel more confident in javascript.

All Hat fucked around with this message at 23:54 on Aug 3, 2012

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

All Hat posted:

I'm doing something stupid, that is, making a snake game in html and javascript sans jquery and canvas.

It's working surprisingly well so far, except for one little thing. I'm adding a board editor, which is simply a 70 x 40 grid of checkboxes, which corresponds to blocks on the board, and that can be used to add walls.

For some reason, adding these checkboxes are quite slow in Opera. I first stored references to them in an two-dimensional array. That took approximately 3.4 seconds.

After I removed the arrays, it takes ~2.5 - ~2.9 seconds doing layout.

This snippet is responsible for the checkboxes. Anyone see what is wrong?

code:
bobble.boardEditor = function () {
	//wrapping element for checkboxes
	var boardEditor = document.createElement("div"),
		i,
		j,
	//temp variable for checkboxes
		cBox;
	boardEditor.id = "boardEditor";
	boardEditor.style.clear = "both";
	
	// 40 rows deep
	for (j = 0; j < 40; j += 1) {
		// 70 columns wide
		for (i = 0; i < 70; i += 1) {
			cBox = document.createElement("input");
			cBox.type = "checkbox";
			//coordinates for "hit" "detection"  
			cBox.setAttribute("data-x", i);
			cBox.setAttribute("data-y", j);
			//appends to wrapping element to minimize interaction with the dom
			boardEditor.appendChild(cBox);
		}
		boardEditor.appendChild(document.createElement("br"));
	}
	// appends everything to the document, and adds an eventlistener.
	document.getElementById("main").appendChild(boardEditor);
	if (document.addEventListener) {
		document.getElementById("boardEditor").addEventListener('click', bobble.updateBoard, false);
	} else if (document.attachEvent) {
		document.getElementById("boardEditor").attachEvent('onclick', bobble.updateBoard);
	}
};
If anyone has a better idea for this kind of level editing, let me know. I'm only doing this to feel more confident in javascript.

Generate all your HTML as a string and pop it into the DOM all at once.

All Hat
Jul 11, 2008

He that is without int among you, let him first cast a long

Lumpy posted:

Generate all your HTML as a string and pop it into the DOM all at once.

Thank you for the tip, it reminded me about a few other optimisations I'd forgotten about. However, doing this (concatenating strings, assigning to array instead of using push) actually slowed it down in Opera. In IE and Chrome (and Firefox, I'm sure), it moves fast enough that I can't notice any difference:

code:
for (j = 0; j < 40; j += 1) {
	for (i = 0; i < 70; i += 1) {
	c[cc++] = '<input type="checkbox" data-x="' + i + '" data-y="' + j + '" />';
	}
	c[cc++] = '<br>';
}
document.getElementById("main").appendChild(boardEditor);
var x = c.join('')
document.getElementById("boardEditor").innerHTML = x;
I guess Opera isn't the fastest browser anymore, but it is still the most featureheavy. :)

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Don't use innerHTML. Instead, use the DOM APIs. Also, DocumentFragment.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

All Hat posted:

Thank you for the tip, it reminded me about a few other optimisations I'd forgotten about. However, doing this (concatenating strings, assigning to array instead of using push) actually slowed it down in Opera. In IE and Chrome (and Firefox, I'm sure), it moves fast enough that I can't notice any difference:

code:
for (j = 0; j < 40; j += 1) {
	for (i = 0; i < 70; i += 1) {
	c[cc++] = '<input type="checkbox" data-x="' + i + '" data-y="' + j + '" />';
	}
	c[cc++] = '<br>';
}
document.getElementById("main").appendChild(boardEditor);
var x = c.join('')
document.getElementById("boardEditor").innerHTML = x;
I guess Opera isn't the fastest browser anymore, but it is still the most featureheavy. :)

And don't store your strings in an array... create a string and use += to concatenate.

http://jsperf.com/array-join-vs-string-connect

All Hat
Jul 11, 2008

He that is without int among you, let him first cast a long

Lumpy posted:

Generate all your HTML as a string and pop it into the DOM all at once.


Suspicious Dish posted:

Don't use innerHTML. Instead, use the DOM APIs. Also, DocumentFragment.

I'm just gonna admit my stupid and say I can't find out how to reconcile these statements. I would really appreciate a link explaining it, as I can't find much about DocumentFragment without innerHTML.

Re: concatenation vs. join - I've read about this at some point, but mixed up which was faster and assumed that the "easiest" way was the slowest. Didn't make much of a difference, anyway.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

All Hat posted:

I'm just gonna admit my stupid and say I can't find out how to reconcile these statements. I would really appreciate a link explaining it, as I can't find much about DocumentFragment without innerHTML.

I'm saying not to use innerHTML, as the parsing is a bit slower. Basically, build an INPUT DOM node with all the attributes, and then run cloneNode() for each checkbox and insert it into the fragment, and then insert the fragment into the DOM.

Alligator
Jun 10, 2009

LOCK AND LOAF
So i've got this piece of javascript to load a bunch of audio files.

JavaScript code:
function LoadAudio(sources, cb) {
  var result = {}
  var loaded = 0;
  var toLoad = 0;

  for (var key in sources) {
    if (!sources.hasOwnProperty(key)) continue;
    toLoad++;
  }

  for (var key in sources) {
    if (!sources.hasOwnProperty(key)) continue;
    var n = new Audio();
    n.addEventListener('canplaythrough', function(evt) {
      console.log(evt);
      if (++loaded >= toLoad) {
        cb(result);
      }
    }, false);
    n.src = sources[key];
    result[key] = n;
  }
}

window.onload = function() {
  LoadAudio({
    'C': '/C.mp3',
    'G': '/G.mp3',
    'F': '/F.mp3'
  }, function(sounds) {
    console.log(sounds)
  });
}
I've got a browser specific problem with it. In Chrome when i navigate to the page it all works fine, three events and then the final object get logged. When i refresh none of that happens, no events and no final object.

If i close the tab and reopen the page in a new tab it works fine, sometimes. Sometimes it works fine and I get the stuff logged every refresh.

I disabled the cache in the dev tools to see if that was part of it but it didn't make a difference.

Works fine in IE (only other browser I've got handy).

All Hat
Jul 11, 2008

He that is without int among you, let him first cast a long

Suspicious Dish posted:

I'm saying not to use innerHTML, as the parsing is a bit slower. Basically, build an INPUT DOM node with all the attributes, and then run cloneNode() for each checkbox and insert it into the fragment, and then insert the fragment into the DOM.

I appreciate your input, but this suggests my original choice of creating a node, appending to that node and finally appending that node to the DOM is the fastest: http://jsperf.com/appendchild-vs-documentfragment-vs-innerhtml/7. (e: radium! :argh:)

There seems to be some benefits to DocumentFragment, and I'm thankful you brought it up, but they don't seem to apply significantly for this case.

Again: Flaunting my stupid, why would it be faster to clone an element and then change its attributes than creating an element? I have little need for 2800 checkboxes reporting the same values.

All Hat fucked around with this message at 08:40 on Aug 5, 2012

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

All Hat posted:

I appreciate your input, but this suggests my original choice of creating a node, appending to that node and finally appending that node to the DOM is the fastest: http://jsperf.com/appendchild-vs-documentfragment-vs-innerhtml/7.

That to me shows that DocumentFragment is faster.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

All Hat posted:

I'm just gonna admit my stupid and say I can't find out how to reconcile these statements. I would really appreciate a link explaining it, as I can't find much about DocumentFragment without innerHTML.

Re: concatenation vs. join - I've read about this at some point, but mixed up which was faster and assumed that the "easiest" way was the slowest. Didn't make much of a difference, anyway.

Generate your HTML through string concatenation, then put that string into the DOM. That will be faster than creating nodes (cloning or not.) If the element you are inserting to is EMPTY, then .innerHTML is very, very fast. That's why you do it all at once at the end. innerHTML slows down when dealing with non-empty nodes.

http://jsperf.com/innerhtml-vs-createelement-test

Adbot
ADBOT LOVES YOU

All Hat
Jul 11, 2008

He that is without int among you, let him first cast a long

I think SA included the period in the url and sent you to the wrong page.
http://jsperf.com/appendchild-vs-documentfragment-vs-innerhtml/7 compares inserting to an "offline" node, which was what I tried first.

Even so, after trying all these methods, I get the same results. No noticable change in the browsers that already append the elements fast, and Opera is still slow, much slower than the differences jsperf.com shows for the different methods.

The element is definitely empty until I appendChild or innerHTML it.
Again, I really appreciate your time and answers, but something is still off, and I don't understand why.

Fiddle: http://jsfiddle.net/X8AFv/5/

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