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
Bodhi Tea
Oct 2, 2006

seconds are secular, moments are mine, self is illusion, music's divine.
Thanks for the input guys. That was enlightening, especially the speed test.

Adbot
ADBOT LOVES YOU

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.

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.

Blinkz0rz posted:

Can you elaborate a little bit more on the web app you're working on? I've been thinking about developing a similar system and I'm curious if you could discuss issues you've run into with with offline data.

Sure, I'm building a GTD style task management + notetaking application, a lot of the application is built upon a text parser which means you can set your appointments, project, errands, as you think of them in your notes. The app does the organizing. My thinking is to build an offline prototype that shows off the ethos behind the interaction and the execution, and I'm planning on running a kickstarter to help fund the remainder of development, to see whether what I'm building is actually worth knuckling down and finish.

The storage layer is very much experimental, I wrote all the indexedDB by hand, from having never done any javascript storage work before. The biggest obstacle was getting past the asynchronous nature of indexedDB calls. I made a little library to handle that using callbacks, so I can do multiple queries in the one request and get it back only when all asynchronous calls were done.

It's in coffeescript, hacky as poo poo, but you should be able to get the picture.
https://gist.github.com/5d34635659a79014cec3

Realistically this problem will be solved much better by others so if I'm successful with the prototype I'd rip out the storage layer and look into library options. Maybe JayData. This is especially important for mobile support since most browsers have not yet adopted indexedDB.

IndexedDB can be slowww, but my queries could be made much more efficient so I could improve things there, there is a lot of talk about how it is much less efficient with large data stores though.

IndexedDB won't accept boolean values for indexed attributes (bahhh), so some of what would be booleans are unfortunately "true" or "false" strings at the moment. Which is annoying.

As I said, I would very likely move to a library that can do all the nitty gritty for me. I was learning javascript as I was making this, and the storage layer was made in an early part of the game so it's pretty poo poo. Gets the job done for the moment but getting slow with a large data store.

Dunno whether this helps any, as I said I'm pretty new to javascript applications where it is actually used extensively.

Boz0r
Sep 7, 2006
The Rocketship in action.

Wheany posted:

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.

In the w3school's examples they use "Text". I tried with "text/plain", though, and it still doesn't work :(

code:
function drag(event) {
	event.dataTransfer.setData("text/plain", event.target.id);
	alert(event.dataTransfer.getData("text/plain"));
}
still returns "";

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Boz0r posted:

In the w3school's examples they use "Text". I tried with "text/plain", though, and it still doesn't work :(

code:
function drag(event) {
 event.dataTransfer.setData("text/plain", event.target.id);
 alert(event.dataTransfer.getData("text/plain"));
}
still returns "";

Is event.target.id actually something (and not "")?

The Gripper
Sep 14, 2004
i am winner
Can you even use getData on a drag event? I thought that was a drop event method.
JavaScript code:
<script>
  function drag(event) {
      var dt = event.dataTransfer;
      dt.setData('text/plain', event.target.id);
  }
  function drop(event) {
      var dt = event.dataTransfer;
      alert(dt.getData('text/plain'));
  }
</script>

<body>
  <div draggable="true" id="what" ondragstart="drag(event)">
    <strong>DRAG ME</strong>
  </div>

  <div id="wangs" ondragover="event.preventDefault()" ondrop="drop(event)">
    Drop here!
  </div>
</body>

The Gripper fucked around with this message at 07:36 on Nov 21, 2012

Sergeant Rock
Apr 28, 2002

"... call the expert at kissing and stuff..."
The Release Notes for FF17 (just released) claim that it supports ECMAScript's String.contains : https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/contains

But I can’t get it to work. Is this because I am stupid?

Edit: It got backed out of 17 and 18 because of a collision with bloody MooTools!

Sergeant Rock fucked around with this message at 17:39 on Nov 21, 2012

Boz0r
Sep 7, 2006
The Rocketship in action.

Jabor posted:

Is event.target.id actually something (and not "")?

Yeah, it's "div3", and the setData() returns true when assigning.

The Gripper posted:

Can you even use getData on a drag event? I thought that was a drop event method.

I don't really know, but why wouldn't it? In my situtation it doesn't return anything in the drop method either.

Fluue
Jan 2, 2008
I'm having trouble wrapping my head around looping through JS objects.

I have a 2D object that holds the valid & invalid locations for a player. If the location is valid, it calls a JS closure holding location information. If it's invalid, the value of the direction is -1.

I want to have navigation buttons (n, s, e, w) disable for invalid locations. I'm using jQuery for this right now, but I'm at a loss for how to loop through my 2D object.

Here's what I have in mind with pseudo code:
code:
loop through 2D array using locationMatrix[currentLocation]
	for locationMatrix[currentLocation][direction] === -1
		disable corresponding direction button


and here's my 2D object: (incomplete, but you get the idea)
code:
var locationMatrix = {};
var locationMatrix = { 
    startingLocation:   { north: globalLocations[1], south: globalLocations[3], east: -1, west: globalLocations[1] }, 
    windowwall:         { north: 0, south: 0, east: 0, west: 0 }, 
    arthall:            { north: 0, south: 0, east: 0, west: 0 },
    kitchen:            { north: 0, south: 0, east: 0, west: 0 }
}

Am I just missing something with my for loop? I've read about hasOwnProperty, but I don't think that fulfills what I'm trying to accomplish.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Fluue posted:

I'm having trouble wrapping my head around looping through JS objects.

I have a 2D object that holds the valid & invalid locations for a player. If the location is valid, it calls a JS closure holding location information. If it's invalid, the value of the direction is -1.

I want to have navigation buttons (n, s, e, w) disable for invalid locations. I'm using jQuery for this right now, but I'm at a loss for how to loop through my 2D object.

Here's what I have in mind with pseudo code:
code:
loop through 2D array using locationMatrix[currentLocation]
	for locationMatrix[currentLocation][direction] === -1
		disable corresponding direction button


and here's my 2D object: (incomplete, but you get the idea)
code:
var locationMatrix = {};
var locationMatrix = { 
    startingLocation:   { north: globalLocations[1], south: globalLocations[3], east: -1, west: globalLocations[1] }, 
    windowwall:         { north: 0, south: 0, east: 0, west: 0 }, 
    arthall:            { north: 0, south: 0, east: 0, west: 0 },
    kitchen:            { north: 0, south: 0, east: 0, west: 0 }
}

Am I just missing something with my for loop? I've read about hasOwnProperty, but I don't think that fulfills what I'm trying to accomplish.

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] );
    }
}
You will then need to iterate through those objects to get the directions.

Life might be easier if you do use arrays, and constants for the directions (ex: windowAll[DIRECTION_NORTH])


Here's some terrible, terrible code I hasitly wrote that iterates through your objects: http://jsfiddle.net/d9RLh/

EDIT: The reason you use / test for hasOwnProperty is to avoid processing properties that exist on the object prototype, and only dealing with the one you've defined on the object.

Lumpy fucked around with this message at 18:06 on Nov 21, 2012

Boz0r
Sep 7, 2006
The Rocketship in action.
I got my poo poo working. Apparently I set drop() to ondragend instead of ondrop.

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.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Jabor posted:

What attack are you actually protecting against here?

If an attacker is running javascript on your page, you've already lost the XSS game and not letting them override Array.push isn't going to save you. If you're embedding user data in your javascript and letting someone else execute it, you're also playing with fire and you're better off doing that in a more secure way instead of trying to protect yourself with some cute tricks.

And if neither of those are true, you shouldn't really care if someone messes with it because it doesn't expose any new security vulnerabilities.

You can use Javascript closures in order to keep the variables scoped to that closure, if you use something like Array.push within that closure however it can be overriden and revealed to Javascript outside the closure. If someone has managed to include Javascript on your page it will be able to access the internal members of that closure. I agree that it's probably nothing you should particularly concern yourself with because - like you said - there are bigger problems afoot if someone has injected Javascript into your page. But someone asked why they would do that, and that's literally the only potential reason I can think of.

Peanut and the Gang
Aug 24, 2009

by exmarx

Gnack posted:

You can use Javascript closures in order to keep the variables scoped to that closure, if you use something like Array.push within that closure however it can be overriden and revealed to Javascript outside the closure. If someone has managed to include Javascript on your page it will be able to access the internal members of that closure. I agree that it's probably nothing you should particularly concern yourself with because - like you said - there are bigger problems afoot if someone has injected Javascript into your page. But someone asked why they would do that, and that's literally the only potential reason I can think of.

That would be cool as hell for getting access to a site's js closures from greasemonkey, but I dont think its possible because scope is based on where functions are defined.
For example, in this script, you wont have access to secret from the custom push() function, and instead it throws an error:
http://jsfiddle.net/t65hD/

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Wheany posted:

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.

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:

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

barbarianbob posted:

That would be cool as hell for getting access to a site's js closures from greasemonkey, but I dont think its possible because scope is based on where functions are defined.
For example, in this script, you wont have access to secret from the custom push() function, and instead it throws an error:
http://jsfiddle.net/t65hD/

Yeah I wish I could remember the example I saw presented - after looking at your example I'm wondering if I'm misremembering something.

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.

Bob Morales
Aug 18, 2006


Just wear the fucking mask, Bob

I don't care how many people I probably infected with COVID-19 while refusing to wear a mask, my comfort is far more important than the health and safety of everyone around me!

I've been playing with a little chat site, and I'm trying to get the chat view to scroll to the bottom of the messages after the initial messages (will eventually be the last 10-20 or so) are loaded when you join a room.

I'm using Angular, and my controller loads the messages fine, but I'm pretty sure what happens is that the scrollTop happens before the messages are all loaded.
code:
function MessageListCtrl($scope, $routeParams, $http) {
  $http.get('chat_messages' + '.json').success(function(data) {
    $scope.messages = data;
    $("#chat").scrollTop($("#chat")[0].scrollHeight);
  });
..
}
I'm new to Javascript so how would I rig the calls up to not return or whatever until the loading is done so the messages can be scrolled after they are in the view?

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
The problem is that you're using a scope item in a callback. Because of that, the angular $scope is not actually watching for changes during that callback, so the scope is updating later than the end of the callback. Of course this type of code is common as hell so you just need to tell angular to apply the scope changes by using $scope.$apply()

code:
function MessageListCtrl($scope, $routeParams, $http) {
  $http.get('chat_messages' + '.json').success(function(data) {
    $scope.messages = data;
    $scope.$apply()
    $("#chat").scrollTop($("#chat")[0].scrollHeight);
  });
..
}

dizzywhip
Dec 23, 2005

Actually, the $http service should be calling $apply automatically, so manipulating the scope should be fine. In general, any time you're integrating directly with a built-in Angular service, you don't need to worry about calling $apply manually.

The more likely problem is that the DOM doesn't re-render immediately after you set messages, so your scrollHeight is off. I could be wrong, but I don't think calling $apply will cause the DOM to re-render immediately. It's hacky, but I believe the only solution I've been able to come up with for this particular situation is to wrap the scrolling code in a setTimeout of 0.

Also, you might not care about this, but it's considered bad form to deal with the DOM in Angular controllers. The "proper" way to implement this kind of behavior would be to set up a directive for the scrolling and fire off an event that the directive handles to tell it to scroll to the bottom. This way you keep your DOM code separate from your controllers, which makes it easier to write tests. If you're just doing this for kicks or whatever it's not that big of a deal though.

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
Ah okay, admittedly I've mainly been working with offline storage so I didn't even twig that it was an angular service. Duh, still learning. That said though, the scope application wouldn't happen til after completion of the callback, or is that wrong?

dizzywhip
Dec 23, 2005

Yeah that's correct, so it won't be happening until after scrollTop is called. Again, I'm not sure if $apply will somehow cause the DOM to be rerendered immediately, but if that's the case, then your solution should work.

Actually, one thing I forgot to take into account is that if the callback is wrapped in a $digest (which works like $apply, but it wraps the code that is affecting the scope), then Angular will throw an exception if you try to call $apply or $digest. They'll have to test it out to see how it works.

Bob Morales
Aug 18, 2006


Just wear the fucking mask, Bob

I don't care how many people I probably infected with COVID-19 while refusing to wear a mask, my comfort is far more important than the health and safety of everyone around me!

Gordon Cole posted:

Also, you might not care about this, but it's considered bad form to deal with the DOM in Angular controllers. The "proper" way to implement this kind of behavior would be to set up a directive for the scrolling and fire off an event that the directive handles to tell it to scroll to the bottom. This way you keep your DOM code separate from your controllers, which makes it easier to write tests. If you're just doing this for kicks or whatever it's not that big of a deal though.

Right, I originally was appending the new message to the DOM but then I learned Angular automatically does it for me (I render it in a ng-repeat), so I'm not sure why I went back to doing it that way. Durr.

opt
Oct 10, 2007
I am pretty new to javascript/jQuery and have a quick question about how to handle some AJAX.

So basically I have a form for deleting items that consists of a select box and a button, right now I have it so that when the button is clicked it uses the .post() method and calls a seperate php file to process it and delete what was selected from the database. Now comes the issue of having the select box reflect the changes (since an item just got deleted), I tried just doing a .replaceWith() on the div with a new select box, which shows correctly but the button no longer works. What is the optimal way of having your form elements reflect changes through ajax and the form work through multiple submits?

theratking
Jan 18, 2012
I'm trying to write a boids-like application (e.g. https://www.youtube.com/watch?v=M028vafB0l8) in javascript, but I've never done any graphics in js before.

Any suggestions? I'm looking mainly for speed + ease of use. Portability would also be nice.

I don't need anything complicated. Easy circle and square drawing is probably enough.

edit: a major thing is drawing *many* shapes at once quickly. Many meaning on the scale of hundreds (hopefully)

theratking fucked around with this message at 04:36 on Nov 30, 2012

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Basic <canvas> should be friendly enough.

theratking
Jan 18, 2012
Yeah actually that'll work just fine. A library would probably be overkill for this. Thanks!

gandlethorpe
Aug 16, 2008

:gowron::m10:
Anyone familiar with AutoIt know whether you can use it to fill out a web form coded in Javascript?

Bodhi Tea
Oct 2, 2006

seconds are secular, moments are mine, self is illusion, music's divine.
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?

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.

Bodhi Tea
Oct 2, 2006

seconds are secular, moments are mine, self is illusion, music's divine.

Wheany posted:

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

Thanks, I suspected as much. That's what that ".delay(1800)" was put in for, but I think I'm using that command wrong. Any ideas on how I can slow it down enough for each update to be visible?

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
http://jsfiddle.net/F5NC3/9/

Try this, rather than using a while function you could recur the calls using setTimeout. That said, other people know much more than js than me so I may be misguided.

edit: I left delay in the jQuery call cause I'm slack, but it doesn't need to be there anymore.

Maluco Marinero fucked around with this message at 23:33 on Nov 30, 2012

Mogomra
Nov 5, 2005

simply having a wonderful time

Bodhi Tea posted:

...That's what that ".delay(1800)" was put in for, but I think I'm using that command wrong...
Not that this is the "correct" way to do it, but you could look into using jQuery's .queue().

It's mostly for effects, and it makes it easy to serialize steps like this. Instead of a for loop, where you can't pause between iterations, you can keep adding to the queue until the letters are where they should be. You can also add delays between steps in the queue.

A more sane way to do something like this would probably be to use setInterval(), and have it clearInterval() when the letters are in the correct order.

dizzywhip
Dec 23, 2005

Just glancing over it quickly, it appears that the problem is that the delays are getting queued up immediately after each other, so they're essentially getting run in parallel instead of consecutively.

Here's basically what you're doing, conceptually:

JavaScript code:
for (var i = 0; i < 10; i++) {
  setTimeout(function() {
    alert(i);
  }, 1000);
}
You might expect this to alert 0 through 9 in one second intervals, but what will actually happen is it will wait 1 second, then alert "11" 10 times in immediate succession. The reason is that each iteration of the loop happens immediately -- setTimeout is asynchronous, so it doesn't wait for the first timeout to finish before moving to the next one.

This is basically what you'd want to do instead:

JavaScript code:
var alertSomeNumbers = function(number, max) {
  setTimeout(function() {
    alert(number);
    
    if (number < max) {
      alertSomeNumbers(number + 1, max);
    }
  }, 1000);
};

alertSomeNumbers(0, 10);
Fake edit: Beaten badly, but hopefully this explanation is helpful. The setInterval suggestion is probably actually the cleanest way to go in this case.

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
Yeah. I wasn't aware of setInterval, js noob here. I'd probably use that, I prefer to use guard conditionals when I'm using if else stuff so I'd prefer that.

edit: It also reminds me of troubles I had with recursion when I was getting started with javascript and asynchronous stuff. You can't use a while loop to wait for a result because while loops own the whole process until they finish. That means anything asynchronous (like a jquery delay call), won't run at all until the while loop is actually finished. I've got that right yeah?

Maluco Marinero fucked around with this message at 23:51 on Nov 30, 2012

Bodhi Tea
Oct 2, 2006

seconds are secular, moments are mine, self is illusion, music's divine.
Thanks everyone for the help. It's exactly what I needed.

Adraeus
Jan 25, 2008

by Y Kant Ozma Post
I'm having trouble getting this Greasemonkey/Tampermonkey script to work.

http://pastebin.com/kaFtTgy3

This script is supposed to change the "#" links in this forum's author column to single-page post links. But I don't know JS all that well. This would be easy with PHP! Help!

Replace:
code:
http://forums.somethingawful.com/newreply.php?action=newreply&threadid=3070034#post410103222
With:
code:
http://forums.somethingawful.com/showthread.php?action=showpost&postid=410103222

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Adraeus posted:

I'm having trouble getting this Greasemonkey/Tampermonkey script to work.

http://pastebin.com/kaFtTgy3

This script is supposed to change the "#" links in this forum's author column to single-page post links. But I don't know JS all that well. This would be easy with PHP! Help!

Replace:
code:
http://forums.somethingawful.com/newreply.php?action=newreply&threadid=3070034#post410103222
With:
code:
http://forums.somethingawful.com/showthread.php?action=showpost&postid=410103222

Obviously write this smarter, but this should work (paste into your browsers javascript console to see!)

JavaScript code:
var str = "http://forums.somethingawful.com/newreply.php?action=newreply&threadid=3070034#post410103222";
var bloo = str.replace(/newreply\.php\?action=newreply&threadid=\d+#post(\d+)/, "showthread.php?action=showpost&postid=$1");
console.log(bloo);
EDIT: You could also split the original URL on '#post' and get the post number that way, and plug it into whatever you need to as well.

Lumpy fucked around with this message at 22:00 on Dec 2, 2012

Movac
Oct 31, 2012

Adraeus posted:

I'm having trouble getting this Greasemonkey/Tampermonkey script to work.

http://pastebin.com/kaFtTgy3

This script is supposed to change the "#" links in this forum's author column to single-page post links. But I don't know JS all that well. This would be easy with PHP! Help!

code:
// Your first stab at collecting post links didn't work.
// getElementById() is used to fetch a single element from the document by its ID.
// There's actually no ID or class for the <a> elements we want to gather,
// so we'll need to use the more-complex querySelectorAll().
// querySelectorAll() gathers all elements that match a CSS selector.
// This selector matches the second <a> after an element with the "postdate" class.
var postLinks = document.querySelectorAll(".postdate a:nth-child(2)");
for (var i = 0, postLink; postLink = postLinks[i]; i++) {
	// We find the post ID by slicing the hash of the link.
	// The hash attribute of an <a> contains everything including and after the "#".
	// string.slice(n) slices off everything before the n-th index of the string.
	// 0-indexed, of course, so to cut off the first 5 chars ("#post") we need slice(5)
	var postID = postLink.hash.slice(5);
	// Then just replace the href.
	postLink.href = "http://forums.somethingawful.com/showthread.php?action=showpost&postid=" + postID;
}
This code passed my copy-paste-into-console test, so it might work for you.

Adbot
ADBOT LOVES YOU

Adraeus
Jan 25, 2008

by Y Kant Ozma Post

Lumpy posted:

Obviously write this smarter, but this should work (paste into your browsers javascript console to see!)

I wasn't sure if JS allowed you to use $1, $2, etc., variables in strings. Now I see how that's done. And clearly I didn't escape the catch-all RegEx that I tried. Thank you!

Movac posted:

code:
// Your first stab at collecting post links didn't work.
// getElementById() is used to fetch a single element from the document by its ID.
// There's actually no ID or class for the <a> elements we want to gather,
// so we'll need to use the more-complex querySelectorAll().
// querySelectorAll() gathers all elements that match a CSS selector.
// This selector matches the second <a> after an element with the "postdate" class.
This code passed my copy-paste-into-console test, so it might work for you.

Oh, gosh. querySelectorAll() sounds like a really useful function. I thought about using slice(), but I didn't quite understand whether I should use slice(), extract(), or replace(). Your code works great! Thank you, too.

Now to turn this into a copy-to-clipboard onclick deal. EDIT: Apparently, that's not possible without Flash.

Adraeus fucked around with this message at 23:38 on Dec 2, 2012

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