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
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

Adbot
ADBOT LOVES YOU

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Yeah, you should just tell her exactly that. It's horribly outdated and browsers don't support it for security reasons.

Although, knowing the current browser trends, some kind of "bookmarks api for html5" might appear at any moment :v:

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Fluue posted:

I'm having some trouble with a project I'm working on. The end goal is to make a text adventure game that keeps score and is, obviously, location aware.

I'm having trouble adding more locations outside of the 4 initial locations I already have. The javascript is failing to recognize my global variable of "currentLocation" and when using an if command, it also causes the score to not update.

Here is my javascript on GitHub:
https://github.com/verkaufer/TextAdventureGame/blob/master/script.js

(Yes, I know that switch statement is ugly. I'll be cleaning it up later).

Where am I going wrong with my global var and condition checking?

Before this project gets too big, it could be wise to start using jQuery and maybe some other library, like underscore.
Writing code like document.getElementById('score').innerHTML = score instead of $('#score').html(score) gets old pretty fast.

Also making sure the code goes through jslint or jshint without errors will probably make long-term development easier.

You are using a debugger, right?

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Fluue posted:

Wheany - I'm using Firebug w/DOM view as my debugger right now. Do you have a suggestion for a better one?

No, I was just worried that you would be debugging by alert() ing variables instead of setting breakpoints and watching variable states.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Uziel posted:

code:
<head>
<script type="text/javascript">
       function closeIt() {
            var count = 0;
            tpMods.getRootNode().cascade(function (node) {
                if (!node.hidden) {
                    count++;
                }
            });
            if (count > 0) {
                return "You currently have unsaved pending mods.";
            }
        }
        window.onbeforeunload = closeIt;
</script>
</head>
This doesn't work and I'm confused as to where to go next. Do I need to set some global variable for the count that is updated when the treepanel is? Any ideas?

Try putting a breakpoint on the first row of closeIt (var count = 0).

Does the breakpoint ever trigger?

What is the value of tpMods when paused on the above breakpoint?

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Just a guess, because I don't know anything about xfa script, but maybe
JavaScript code:
xfa.form.formname.page1.resolveNode("field_name[" + count + "]").presence = "invisible";

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Also, it looks like you make a local variable "table" at the start of your code, then use a global variable "i".

Assuming you only changed your inner loop to use j instead of i, you also use a global variable there.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Golbez posted:

code:
for (i = 0; i < 100; i++)
{
    for (j = 0; j < 100; j++)
    {
        echo i+j;
    }
}
If the above is valid code, then you can't expect to reuse i for the second look and expect anything to work. Can you really have two 'i's coexist just because of a for loop? This is not something I've run in to because I don't reuse 'i' just for the hell of it. :v:

Edit: Also that. One weirdness about JS I learned from Crockford is that it internally moves variable declarations to the top, leading to weirdness if you were operating on the assumption that they were being declared in place.

When you use a var declaration, the variables you declare have function scope. So this:
JavaScript code:
function someFunction() {
	console.log('butts');
	for (var i = 0; i < 100; i++)
	{
	    for (var j = 0; j < 100; j++)
	    {
	        echo i+j;
	    }
	}
}
becomes this
JavaScript code:
function someFunction() {
	var i;
	var j;
	console.log('butts');
	for (i = 0; i < 100; i++)
	{
	    for (j = 0; j < 100; j++)
	    {
	        echo i+j;
	    }
	}
}
if you dont't use a var declaration (and the code runs in a web browser):
JavaScript code:
function someFunction() {
	for (i = 0; i < 100; i++)
	{
	    for (j = 0; j < 100; j++)
	    {
	        echo i+j;
	    }
	}
}
becomes:
JavaScript code:
function someFunction() {
	for (window.i = 0; window.i < 100; window.i++)
	{
	    for (window.j = 0; window.j < 100; window.j++)
	    {
	        echo window.i+window.j;
	    }
	}
}
To use two i's, you'd have to do this:
JavaScript code:
function someFunction() {
	var i; // outer i
	for (var i = 0; i < 3; i++)
	{
		(function () {
			var i; // shadows outer i
			for (var i = 0; i < 4; i++)
			{
				console.log("you cannot access the outer i here:" + i);
			}
		}());
	}
}
That outputs:
code:
you cannot access the outer i here:0
you cannot access the outer i here:1
you cannot access the outer i here:2
you cannot access the outer i here:3
you cannot access the outer i here:0
you cannot access the outer i here:1
you cannot access the outer i here:2
you cannot access the outer i here:3
you cannot access the outer i here:0
you cannot access the outer i here:1
you cannot access the outer i here:2
you cannot access the outer i here:3

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Atom posted:

The trick is that Javascript's var keyword does the exact opposite of PHP's global keyword, since PHP assumes local, and Javascript assumes global. (PHP's design is probably superior in this aspect, I can't count how many times I've polluted global in JS.)

Which is why you always use strict mode and jslint or jshint.

And more functions.

MrHyde posted:

I ran into this interesting problem at work. <snip> Anyone have any ideas why this behavior happens?

My guess is that for security reasons you might not be able to access script tags maybe?

But you definitely can edit the head tag. That exactly how for example LESS works.

Also, please use console.log instead of alert if you must dump the state of some variable.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Can I actually stop the loading of page elements with javascript? I have made a user script for the PYF gif thread that convert img tags in read messages to links. That works, but the original purpose was to not even load all the gifs in the read posts.

Well, looking at the network tab in the debugger shows that the images are still being downloadad :mad:

This userscript is made for Opera, but can be easily made to work with Greasemonkey and Chrome as well.

The original code is in the readReplacer function, but that runs only after the DOM content has loaded. So my second idea was listening to DOMNodeInserted and intercepting the body tag and then the image tags inside it.

Except Opera does not fire a DOMNodeInserted for body or any tags inside it (in the first pass?). document.body just appears suddenly. That's why I'm testing for document.body in loadingReplacer.

So my next idea was using Opera's user script specific functions, and to listen to BeforeEvent, which fires before any actual events.

Except document.body suddenly simply materializes there as well.

So I tried one more thing. First I replace all the read images with links, then stop page loading (window.stop()), then I reset the remaining image srcs. The theory was that it would resume loading the images.

Except it never even stops loading them.

So here is the resulting trainwreck of code:
JavaScript code:
// ==UserScript==
// @name read gifs to links
// @description Make gifs in read messages into links on some of Something Awful's image heavy threads
// @include http://forums.somethingawful.com/showthread.php*threadid=3457178*
// ==/UserScript==
/*jslint browser: true, plusplus: true, continue: true, devel: true */

(function () {
	"use strict";
	var beforeReplacer,
		loadingReplacer,
		readReplacer,
		readReplacerRun = false;

	beforeReplacer = function (userJSEvent) {
		//console.log('beforeReplacer');
		if (userJSEvent.srcElement.nodeName && userJSEvent.srcElement.nodeName === 'BODY') {
			//console.warn('srcElement = body');
		}
		if (userJSEvent.target.nodeName && userJSEvent.target.nodeName === 'BODY') {
			//console.warn('target = body');
		}
		if (userJSEvent.event.relatedNode && userJSEvent.event.relatedNode.nodeName === 'BODY') {
			//console.warn('relatedNode = body');
		} else if (userJSEvent.event.target && userJSEvent.event.target.nodeName === 'BODY') {
			//console.warn('target = body');
		}
		if (document.body) {
			//console.info('body exists, running readReplacer, event:' + userJSEvent.event.type);
			readReplacer();
		}
	};

	loadingReplacer = function (event) {
		//console.log('loadingReplacer');
		if (event.relatedNode.nodeName === 'BODY') {
			//console.warn('relatedNode = body');
		} else if (event.target.nodeName === 'BODY') {
			//console.warn('target = body');
		}
		if (document.body) {
			//console.info('body exists, running readReplacer');
			readReplacer();
		}
	};

	readReplacer = function () {
		var readImgs = document.querySelectorAll(".post .seen2 .postbody img, .post .seen1 .postbody img"),
			allImgs,
			i,
			img,
			a,
			sa_pattern = /https?:\/\/\w*\.?somethingawful\.com\//,
			src;

		if (readReplacerRun) {
			return;
		}

		document.removeEventListener('DOMNodeInserted', loadingReplacer, true);
		opera.removeEventListener('BeforeEvent', beforeReplacer, true);


		for (i = 0; i < readImgs.length; i++) {
			img = readImgs[i];
			if (sa_pattern.test(img.src)) { // skip emoticons and avatars
				continue;
			}
			src = img.src;
			img.src = '';
			img.removeAttribute('src');

			a = document.createElement('a');
			a.href = src;

			a.target = '_blank';
			a.textContent = src;
			img.parentNode.replaceChild(a, img);
		}

		//console.log('stopping');
		window.stop();

		allImgs = document.querySelectorAll("img");

		//console.log('resetting remaining image src');
		for (i = 0; i < allImgs.length; i++) {
			img = allImgs[i];

			src = img.src;
			img.src = '';

			//console.log('src:' + src);
			img.src = src;
		}
		readReplacerRun = true;
		window.removeEventListener('DOMContentLoaded', readReplacer);
	};

	opera.addEventListener('BeforeEvent', beforeReplacer, true);
	document.addEventListener('DOMNodeInserted', loadingReplacer, true);
	window.addEventListener('DOMContentLoaded', readReplacer, false);

	if (document.readyState === 'complete' || document.readySate === 'loaded' || document.readyState === 'interactive') {
		window.removeEventListener('DOMContentLoaded', readReplacer);
		readReplacer();
	}
}());
And here is the non-trainwreck version, if someone else wants read images in the PYF gif thread to be links.
JavaScript code:
// ==UserScript==
// @name read gifs to links
// @description Make gifs in read messages into links on some of Something Awful's image heavy threads
// @include http://forums.somethingawful.com/showthread.php*threadid=3457178*
// ==/UserScript==
/*jslint browser: true, plusplus: true, continue: true */

(function () {
	"use strict";
	var readReplacer;

	readReplacer = function () {
		var readImgs = document.querySelectorAll(".post .seen2 .postbody img, .post .seen1 .postbody img"),
			i,
			img,
			a,
			sa_pattern = /https?:\/\/\w*\.?somethingawful\.com\//,
			src;

		for (i = 0; i < readImgs.length; i++) {
			img = readImgs[i];
			if (sa_pattern.test(img.src)) { // skip emoticons and avatars
				continue;
			}
			src = img.src;
			img.src = '';
			img.removeAttribute('src');

			a = document.createElement('a');
			a.href = src;

			a.target = '_blank';
			a.textContent = src;
			img.parentNode.replaceChild(a, img);
		}

		window.removeEventListener('DOMContentLoaded', readReplacer, false);
	};

	window.addEventListener('DOMContentLoaded', readReplacer, false);

	if (document.readyState === 'complete' || document.readySate === 'loaded' || document.readyState === 'interactive') {
		window.removeEventListener('DOMContentLoaded', readReplacer, false);
		readReplacer();
	}
}());

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Boz0r posted:

I'm trying to get a function called every time a checkbox is changed and it's driving me nuts.

This is my code:
code:
checkbox.onclick(OnChangeCheckbox (this));

function OnChangeCheckbox (checkbox) {
   if (checkbox.checked) {
      alert(allowCookies);
   } else {
      alert(allowCookies);
   }
}
When I try to check whether the script is assigned in Chrome, it just gives me this:
code:
document.getElementById("checkbox").onclick

null
What gives?

EDIT: It tells me this:
code:
TypeError: Property 'onchange' of object #<HTMLInputElement> is not a function

code:
checkbox.onclick(OnChangeCheckbox (this));
Actually does this:

1) You call the function OnChangeCheckbox with this.
2) you then call the function onclick (which is probably null) of checkbox with whatever OnChangeCheckbox returned (which is probably undefined, or because it looks like OnChangeCheckbox is undefined when you call it, it will just throw an error)

What you probably want is to declare OnChangeCheckbox first, then assign: checkbox.onclick = OnChangeCheckbox;

And for the love of god, use console.log instead of alert if you need to dump some variable.

e: And when OnChangeCheckbox is called after checkbox.onclick, this will point to the checkbox.

Wheany fucked around with this message at 12:55 on Nov 5, 2012

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Yes.

JavaScript code:
//first create a function:
var someFunction = function (){
	console.log("hello from someFunction");
};
//Then either 
checkbox.onclick = someFunction;
//or (better)
checkbox.addEventListener('click', someFunction);

Wheany fucked around with this message at 08:55 on Nov 6, 2012

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Begall posted:

code:
              {% for entry in dcentries %} 
              <tr>
                <td name="DName-{{ loop.index }}" id="DName-{{ loop.index }}">{{ entry.name }}</td>
                <td name="DPrice-{{ loop.index }}" id="DPrice-{{ loop.index }}">{{ FormatCurrency( entry.price )|safe }}</td> 
                <td><input name="DQuantity-{{ entry.name }}" type="number" id="DQuantity-{{ entry.name }}" placeholder="0"></td>
              </tr>
              {% endfor %}  
Could anyone point me in the right direction for this? Not really sure how I can do it properly rather than hardcoding in each sum.

Guessing from the code, since I have never programmed in whatever that is, and because I don't know what kind of values entry.name can contain, instead of <input id="DQuantity-{{ entry.name }}">, I'd use <input name="DQuantity-{{ entry.name }}" type="number" id="DQuantity-{{ loop.index }}" placeholder="0" class="quantity">.

For <td name="DPrice-{{ loop.index }}" id="DPrice-{{ loop.index }}">, I would also add data-price attribute, so <td name="DPrice-{{ loop.index }}" id="DPrice-{{ loop.index }}" data-price="{{ entry.price }}"> (again, guessing the syntax).

Then I would do this:
JavaScript code:
var quantities = document.querySelectorAll(".quantity");

//quantities is now a NodeList, which looks like an array and behaves mostly the same. Iterating over it is left as an exercise for the reader.

// declare changeListener outside your loop

var changeListener = function () {
	// calculate your new price here, "this" is the changed input.
	console.log(this.value);
};

// so, for all inputs in quantities:
// an_input assumed to be an input from quantities

an_input.addEventListener('change', changeListener);

Maybe this will help you get started?

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Begall posted:

Sorry for not being quite clear on the code, but that was of great help, thanks!

Here's what I've done, I think this is what you intended?

JavaScript code:
              var quantities = document.querySelectorAll(".quantity");
              // Used the same method to get the price list as the quantity list 
              var prices = document.querySelectorAll(".price");
              
              var changeListener = function () {
                var total = 0 
                for(var i=0; i<quantities.length; i++)
                  {
                    total += quantities[i].value*prices[i].getAttribute("data-price");
                  };
                document.getElementById('cost').innerHTML = total; 
             };
             
             document.addEventListener('change', changeListener);
Now to go away and work out how to make it ignore negative numbers. Or better yet, disallow them from being input, hmm...

Well, almost. Actually I didn't even think of having to update the total cost of the shopping cart, but the reason I added the change listener to all inputs was to update just the row's price, with this.value * <the same row's price>. And the reason I wanted you to use data- attribute, is because they are special:
https://developer.mozilla.org/en-US/docs/DOM/element.dataset
No need to getAttribute("data-price"), just use dataset["price"]. Not that it matters a whole lot.

And updating the innerHTML is probably not a problem in this case, since you are uppading a number, but if the string you are inserting into an element is not supposed to be HTML, you should use .textContent (non-IE browsers) or .innerText (non-gecko browsers) (if element.textContent === undefined, use innerText)

Or, use jQuery and let them worry about those kinds of things.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Sergeant Rock posted:

Just in case you don't know - the native dataset API isn't implemented in any version of IE, and you have to fall back to getAttribute... yes, even for IE10.

Well, at least getAttribute works across all browsers :(

Oh well, it's poo poo like this why you should use libraries.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Boz0r posted:

I'm trying to do a drag'n'drop functionality on a website, but JavaScript is messing with me.

code:
function drag(event) {
	event.dataTransfer.setData("Text", event.target.id);
	alert(event.dataTransfer.getData("Text", event.target.id));
}
event.target.id is "div3", but the getData just returns "". What gives?

Well, after quickly lookng at https://developer.mozilla.org/en-US/docs/DragDrop/Drag_Operations , it looks like the first argument in setData should be the data type, so "text/plain" and not "Text". And getData only takes one argument, the type of data to get.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Lumpy posted:

1. Those are objects, not arrays (you use the term 'array' in your pseudo code)
2. To iterate through an object, you can use a for loop like so:
JavaScript code:
for (var my_property in my_obj) {
    if (my_obj.hasOwnProperty(my_property)) {
        console.log( my_obj_[my_property] );
    }
}

Once again, life is made easier by using a library, like underscore, where _.each doesn't care whether you are iterating over an object or an array.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Lumpy posted:

Absolutely, but one should understand what one is doing before using libraries to make life easier. Otherwise one winds up working with an army of people who "know javascript" but who can't comprehend any code that doesn't start with jQuery(

:cry:

Which is why I told him to use underscore :smuggo:

Well, using for... in is just fine, except for two gotchas, I think: The first one is hasOwnProperty, which you covered already, the other is that in for (p in someObject), p doesn't get assigned the actual properties, only their names, so you need to do theActualProperty = someObject[p];, which has burned me several times in the past.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Bodhi Tea posted:

I'm trying to create a text effect where the letters of a string get scrambled until they are all in the right place.

Here's the code thus far: http://jsfiddle.net/F5NC3/

The problem is that it seems that only the final, correct string is output, but I need the <span> to update upon each random shuffling of the original string.

I hope that made sense. Any ideas?

You overwrite the existing text with your current iteration's text.

Try this:
JavaScript code:
// snip
var correct=0;
   
var outputString = '';
// snip
				correct++;
			}
		}
	}
	outputString += output.join("") + '\n';

    //output the output
    $("#l1").text(outputString);
And then change the span to a pre so the \n has a visible effect.

edit: The span is actually updating after each loop, but the loop runs fast enough for it to not be visible.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Maluco Marinero posted:

I'm already persisting data using IndexedDB. I want to provide a way to export that data into a text file, which is why I had a look in at the Flash project. While the link that SD provides seems interesting I'd still have to have a server precompile the resource I'm after for it to come out right, yeah?

The download attribute is supported only by Chrome, at the moment. But, that got me thinking that maybe you could make a data url and get Chrome to download that.

edit:
:stare: it works:

JavaScript code:
 
var a = document.createElement('a');
a.href='data:text/plain;base64,' + btoa('test data');
a.download = 'file name here apparently';
document.body.appendChild(a);
a.textContent = 'click me to download some text';

Wheany fucked around with this message at 17:39 on Dec 6, 2012

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Well, you can definitely scrape that information from the page when a player visits the page with their browser. Then you could save the data into the browser's local storage automatically.

If you did this, the player would have to visit each other player's profile page (or wherever that data in the screenshots are stored), then after visiting all the interesting pages, you might click on a "dump data" button which would show some text box with the collected data formatted in some way (probably comma- or tab-separated), which you might be able to paste into Google docs.

I'd say that the above should at least be doable without relying on any sort of external APIs.

e:

Munkeymon posted:

I was thinking you wanted to scrape a whole lot of other peoples' information in mass by visiting their profiles with a script enabled, which would be fairly silly.

:(

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Loving Africa Chaps posted:

I want to write what should be a fairly simple web app that generates forrest plots like this


That data input side is pretty simple as it's just a form and could be done very easily in PHP which i've used before but reading up it seems javascript might be a better option as it would allow for a bit more tinkering and make some of the functionality i want to add later (like being able to see how removing certain studies effects the result) on look abit neater. Is my thinking right?

With Javascript you could do that client-side, so the plots would change immediately, instead of having to do the calculations and graph updates on server.

You probably should study if some graphing library already offers forest graphs and if not, then look at the canvas element.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
The Request a tiny custom app again thread might be a better place to ask for that.

What you are asking sounds like it would take several hours of actual work, and not just a couple of minutes of dicking around with javascript.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Gordon Cole posted:

Cool, so I guess all static analysis tools are completely useless. And what's the deal with compiler warnings?! It's not like a computer is going to find any problems with our code, so why even bother!

The most important thing he is actually saying is "Global variables are totally cool and the more you use them, the better"

Gordon Cole posted:

The "only real problem" with leaving out semicolons that he mentions is actually a pretty big problem:

This is my favorite part. I'd say that "always use semicolons" is a bit easier to remember and less error prone than "never use semicolons, except..."

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Karthe posted:

JavaScript code:
alert(getLastSegment("c1-3", false));

Are you using your browser's Javascript debugger? Because if you are not, you should(*.

Using alert like that is pretty 2002.

* Depending on browser:
In Chrome and Opera, right click somewhere on the page and select "inspect element"
in Internet Explorer, press F12
in Firefox, you need to install Firebug, then right click anywhere and select Inspect element with Firebug

You can set breakpoints and watches and such in the debugger and see what the values of any variables are without having to "alert" them.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Karthe posted:

Yeah, you're right...those were just easier for me to work with. I'd never tried until now to use Chrome's advanced debugging tools under the Source tab, but now that I've discovered it and figured out how to load up a script for analysis, I'll end up using it more often.

alert() is not easier to work with than console functions, though. Like if you want to output the value of x and y in this loop:
JavaScript code:
var x, y;
for(y = 0; y < 10; y++) {
	for(x = 0; x < 10; x++) {
	console.log('x:' + x + ' y:' + y);
		if (x === 10 && y === 10) {
			console.info("lol, off by one");
		}
		if (isNaN(x) || isNaN(y)) {
			console.error('the laws of mathematics have changed suddenly and x or y has become NaN');
		}
		if (x === 6 && y === 6) {
			console.warn('look out, only one more 6 before the dark lord rises');
		}
	}
}
Imagine having to click ok on that alert window for 100 times only to realize that x and y are never 10, instead of looking at your console and seeing 100 lines of output, which are output instantly without you having to keep on clicking.

And besides log(), console has info(), warn() and error(), which you can use to print out different kinds of messages. They show up in different color, so as soon as you see red in your console, you know there was some error somewhere.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
I think my favorite is still "stupid". It used to complain to you if you had a function that contained "Sync" anywhere in its name (indexOf("Sync") > -1), but it was changed so that it only matches names ending in "Sync".

But not before a coworker decided that instead of using the "stupid" option, he renamed a function named something like "checkSynchronizationComplete" to something else.

Of course the option's documentation is "tolerate stupidity" instead of, let's say, "tolerate synchronous functions." Of course if the documentation said that, he might have to change the option to "synchronous" or something.

e: Wait, so using tabs is not even an option? It just straight-up does not allow the tab character anywhere? :laffo:

Wheany fucked around with this message at 08:19 on Dec 17, 2012

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Deus Rex posted:

where did he say anything like this?

In the part where he says "My advice on JSLint: don’t use it. Why would you use it? If you believed that it helps you have less bugs in your code, here’s a newsflash; only people can detect and solve software bugs, not tools."

var someNumber = 3;
soemNumber = 4;

Now you have a local variable called "someNumber" and a global named "soemNumber"

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Deus Rex posted:

enabling strict mode is even better than jslint for detecting this, since the second line throws an exception:

http://jsbin.com/omefen/2/edit

"static analysis tools can't detect bugs" is a pretty dumb thing to say for sure, but i hardly think that equates to "Global variables are totally cool and the more you use them, the better".

http://jsbin.com/omefen/3/edit

JSLint catches the typo even in the delayed function without having to wait for the code to run. Of course instead of a delayed function, that mistake could be in you ajax failure callback or somewhere else which is rarely run.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
newcell.onClick = function() {myFunction(newcell);};

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
I am guessing here that you should put reader.onloadend before reader.readAsDataURL.

Also: file, reader and img are global variables.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

gandlethorpe posted:

Can I use bookmarklets to fill out web forms that are themselves coded in javascript?

Yes

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

gandlethorpe posted:

Since it's not html, I'm assuming document.getElementById isn't going to cut it.

document.getElementById will work if the element has an id attribute. It doesn't matter if the element is created from html or dynamically through javascript.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

gandlethorpe posted:

Dumb question: Do bookmarklets persist when loading a new page? If they don't, will I have to use some external script to run different bookmarklets for each page?

What do you mean?

Bookmarklets are short javascript snippets you run by selecting a bookmark in your browser. So in that case, they persist. Any variables you declare inside the bookmarklet do not persist, they will disappear when the page is reloaded.

If you never cause the page to be reloaded, ou can use global variables to store data.

If you want to store values between page loads, you can write them in a cookie and then read the value from the cookie when running your bookmarklet.

gandlethorpe posted:

So far, populating elements is pretty straightforward. The real annoying thing is that there are navigation and submission buttons I need to click often, and the only way I know how to access them is by their tag name A. Something tells me there's a more efficient method than counting each A element until I get to one I want.

Probably not in IE7.

With more modern browsers you might be able to use querySelectorAll / querySelector or even xpath. Or, if the page happens to be xml, you can use xpath in IE7 as well.

You could try getting some parent element with first selecting some higher-level element with getElementById, then calling getElementsByTagName on that parent-element.

so something like:
JavaScript code:
var commonParent = document.getElementById('parentElement');

var aTagsInsideParent = commonParent.getElementsByTagName('a');
But most likely there is no need to do so just for "efficiency".

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

gandlethorpe posted:

One particular section of my project involves diary logs, which is just the same form done multiple times. I need to do 28 of those, so I have an array of strings for each log that determine how to fill out the form. There's a hub page that lists each completed form and has a button to start a new form, which loads a new page. I want to be able to start a new form, read the string to fill out the form, and submit (which brings me back to the hub page) then start the next form reading the next string, repeating until all the logs are done. Can I accomplish that using only one bookmarklet?

I don't think so.

That is more of a job for a user javascript, but for that you would need any other browser. User javascript runs automatically on page load, which means you could automate the process entirely.

Does IE7 have a bookmarks toolbar built in? You could use that to simplify your task somewhat. Instead of having to open a menu to run your bookmarklet, you could just press a button on the toolbar.

Also if you can add/replace an onclick handler on the hub page, you could append the current index in the array or even the data itself to be filled into the url of the form page, like so:
"#firstname=John,initials=J.Q.P,lastname=Public"

Then your bookmarklet could extract the data from the url (location.hash)

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Asynchronous code can be a bit of a pain in the rear end, but that's how it is, so just get used to writing function (param, callback) all the time.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Is there user script/bookmarklet thread? If not, is anyone else interested in such a thread?

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Boz0r posted:

Thanks. Another question(This time it's actually JavaScript and not JQuery :p):
code:
var f = function() {
	g = function() {return 1;}
	var g;
	if (true) {
		function g() {return 2;}
	}
	else {
		function g() {return 3;}
	}
	return g();
	function g() {return 4;}
}
var result = f();
Why should this return 1? It seems as though g gets overwritten, but according to my lecturer, the result is 1.

First of all: that code is a horrible manufactured mess.

Okay: Variables in javascript have function scope and exist everywhere within the function regardless of where they are declared. So that var g on the second line declares a local variable named g that exists for the duration of the f function call.

So, the assignment g = function() {return 1;} assigns that function to the local variable g, even if if it looks like the variable has not been declared yet. It's silly, but so is the example.

Inside the if (true) { block, a function is defined, given the name "g" and then assigned nowhere. It's an empty statement. (That g would be visible inside the function itself(*)

The else branch is unreachable code, but it's the same as the if-block.

Then the function f returns the result of function g (still as defined on line 1).

The line after the return is once again unreachable code, and identical in practice to the if and else blocks.

(* If you name a function, you can recursively call the function using that name:
JavaScript code:
//variable name  function name
var fibonacci  = function fib(value) { 
	if (value < 2) {
		return value; 
	}
	return fib(value - 1) + fibonacci(value - 2);
	// you can use both if you absolutely want to, but it's silly.

};

// this works:
console.log(fibonacci(10));

// outside of the function this does not work:
console.log(fib(10)); // Unhandled Error: Undefined variable: fib 
Edit:

Haha, actually, those are all function statements, which have an almost exactly the same syntax as function declarations, except function declarations make the name visible outside the function itself, while function statements are usually anonymous, but if they have a name, it is only visible within the function itself.

Wheany fucked around with this message at 18:43 on Jan 22, 2013

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

DreadCthulhu posted:

Total noob question: I'm trying to teach myself proper JavaScript this time, after having hosed around with it for a couple of days at a time over the years. I powered through Crockford's "The Good Parts" and I'm now going to go ahead and start putting something together, or I will forget most of that in a week.

I have a minimal feel for what the language should look like, but now I have to put it in the context of a web page and the browser, which Crockford spends pretty much 0 time on. Are there any good resources on that one? I'd love to know the best practices of shoving your scripts into web pages. I remember doing unobtrusive JS back in my Rails days and that felt a bit cleaner than stuffing everything in the <script> tag, but I don't know if that's still considered a good practice etc.

My first pet project is a static web page served from my S3 bucket which will be fetching a bunch of information from my "app" on parse.com and displaying it on the screen. Hoping I don't cause too many atrocities.
HTML code:
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<title>My first web page</title>
		<link rel="stylesheet" href="style.css">
		<script src="script.js"></script>
	</head>
	<body></body>
</html>
If you have any significant amount of Javascript, put it into an external script file. If you have several scripts, concatenate them into one file on deployment. The bad thing is that the external script loading blocks page load, so it will take longer to show the page. You can download javascript files asynchronously with some libraries to show the page faster.

BTW, you might have some trouble fetching any data across domains in Javascript. It can be done, but not as easily as data hosted on the same domain.

Adbot
ADBOT LOVES YOU

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Daynab posted:

I feel like tearing my hair out, I hope someone can shed some light on this. I'm making a userscript that converts Youtube links to show their titles, but for some reason the regex stops working on pages/in my script while working in every example and even on jsbin.

Here's the Regex: /(https?:\/\/w*\.?youtu\.?be\.?[com]*\/[a-z0-9\?\-\=\_]+)/i
You can try it here http://scriptular.com/, just put in some youtube links as strings.

and here's the [url="https://"http://jsbin.com/udofuw/1/edit"]jsbin with working example.[/url]

The issue is that when I put it on a userscript, it actually works on jsbin, but then any other page it just doesn't return anything. Now, I've tried going back through the regex character by character, but it just stops working once I put in the first letter (y, or really anything else) and I don't understand what the gently caress.

Okay, If I understood the gist of your script correctly ("first", "second" etc are not very good variable names, btw), you want the video id out of the link https://www.youtube.com/watch?feature=player_embedded&v=8xttr_ILd6A#t=6s, so "8xttr_ILd6A" from that url.

If you're on Windows, and doing anything with regular expressions, try The regex coach

As for the regex, try /(youtu\.be\/|v=)([a-zA-Z0-9_\-]*)/, it seems to work on all of your examples.

JavaScript code:
var getVideoId = function (url) {
	var idPattern = /(youtu\.be\/|v=)([a-zA-Z0-9_\-]*)/;
	var idMatch = idPattern.exec(url);

	return idMatch ? idMatch[2] : '';
}

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