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
Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

Snodar posted:

That leads to a second question, is there any god-damned reason to be using offsetLeft/offsetTop/offsetParent when getBoundingClientRect does the same thing without a loop? I only started doing it because I had a page in Gecko flat-out fail when I tried the offset method, and AFAICT it always produces the correct result.

getBoundingClientRect hasn't always been available in Gecko, iirc. But as long as it's there, you should definitely use it.

Adbot
ADBOT LOVES YOU

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Forgive me argz, I ended up doing a wholesale rewrite of your script. It was fun, but possibly not that helpful to you for figuring out the original issue.

It works though! And it's kind of novel, if a little awkward, to write in continuation-passing style.

code:
// ==UserScript==
// @name           gnome-look.org thumbnail enlarger
// @author         Nigglypuff
// @namespace      meta.ironi.st
// @include        http://gnome-look.org*
// @include        http://*.gnome-look.org*
// ==/UserScript==

var thumbnailPath = '/CONTENT/content-m1/m',
	fullSizePath = '/CONTENT/content-pre1/';

function fixImageExtension(url, callback) {
	// remove extension from original url
	url = url.slice(0, -3);
	
	var extensions = ['jpg', 'gif', 'png'];
	
	function tryNextExtension(){
		var extension = extensions.shift();
		
		if (extension) {
			testImageExists(url + extension, function (exists) {
				if (exists) {
					callback(url + extension);
				} else {
					tryNextExtension();
				}
			});
		} else {
			callback(null);
		}
	};
	
	tryNextExtension();
	
};

function testImageExists(url, callback) {
	var testImg = document.createElement('img');
	
	testImg.addEventListener('load', function () {
		callback(true);
	}, false);
	
	testImg.addEventListener('error', function () {
		callback(false);
	}, false);
	
	testImg.src = url;
};

[].forEach.call(document.images, function(img) {
	var thumbnailName = img.src.split(thumbnailPath)[1];
	
	if (thumbnailName) {
		img.style.maxWidth = '300px';
		fixImageExtension(fullSizePath + thumbnailName, function(fixedUrl) {
			if (fixedUrl) img.src = fixedUrl;
		});
	}
});

Nigglypuff fucked around with this message at 08:24 on Apr 20, 2009

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Oops, good point — like a goofball I only tested it in Chrome. Have updated the code slightly in the previous post, just moving the function definitions up before the code that uses them. It seems to be working for me in Firefox now.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Third time's a charm. Turns out that in firefox, userscripts can't add event handlers by assigning element.onload = handler. Instead, you have to do element.addEventListener('event', handler, false), or else an error is thrown. Curious. Maybe the old-fashioned event handler assignment relies on some kind of XPCOM magic that doesn't exist in the greasemonkey sandbox.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Why are you listening for beforeunload events, if not to potentially stop the document unloading? Could you listen for unload instead?

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
The only way to see which button the user pressed is to test whether the unload event follows the beforeunload event. Browsers deliberately restrict the author's choices in this scenario, and always display a standardized UI for the close-tab confirmation dialog, because they don't want to let malicious sites confuse users about the basic mechanics of navigating and closing/opening windows. I guess this is partly fallout from the well-established tradition of making banner ads or popups look like system dialog boxes, to fool users into clicking or obeying them.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
I think Lumpy means to suggest you treat us to a glimpse at the source code.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
You might start by viewing the source of this.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

Fehler posted:

Is there any way I can allow an iframe to call a Javascript function in the parent window if it is on a different host? I'm getting something like "Permission denied for <http://host1> to get property Window.func from <http://host2>." in my console.

Short answer: no.

Long answer: the frames *can* communicate with each other, but cannot directly call functions or retrieve variables.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Look at the page URL before and after clicking the profile link. If everything before the hash (#) is the same, then a real page load has not occurred.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
In newer browsers, you can also listen for the hashchange event.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

ATLbeer posted:

So I'm building a list of messages on screen that the user will be interacting with. Moving in between different queues etc...

I want to have a master array of all "messages" and that array is objects which are the messages themselves.

If you want an associative array in javascript, just use a plain old Object instance. As you have seen, it may be technically possible to treat Array instances as sparse arrays with arbitrarily high numeric keys, but it will ruin iteration. The built-in Array class is spooky, and will automatically adjust its own length property — meaning that most of its methods will behave as if the array contains a whole lot of undefined items in-between the ones you actually assigned. In general, you only want to use an Array instance if you are actully iterating over or manipulating the contents as a dense list, eg pushing/popping items.

Also: you don't need to be generating keys with Math.random(). Just do something like
code:
function Comment() {
        this.id = Comment.next_id++;
};

Comment.next_id = 1;

Nigglypuff fucked around with this message at 10:35 on Nov 7, 2009

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
javascript:location = "http://www.website.com/page.cfm?country=" + prompt("Country code?")

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

Soks posted:

I don't know JavaScript, but I was able to bumble my way around the code just fine. I just have no idea how this could be smoothed out, or why it's choppy in the first place.

I haven't checked this in Safari, but it looks like Chrome and Firefox implement the onscroll event differently. Basically, Chrome emits many more onscroll events than Firefox does, and most importantly, it emits an event every time the page is redrawn while scrolling. Firefox, on the other hand, boasts a 'smooth scrolling' feature. Smooth scrolling means rendering many brief, incremental frames while scrolling — but the onscroll does not fire every time one of these frames is drawn to the screen. Rather, the event is only fired during pauses in the movement of the scrollbar, when there is no incremental movement to render. This means that in Firefox, during the act of scrolling, many small changes in scroll-height are rendered to the screen before your handler is called, and so the movement of the different layers will appear to be jerky and out of sync.

I have not yet found a solution to this problem. My first impulse was calling setInterval() to check the scrollY property of the page at a high frequency, and call your handler when its value changes, regardless of whether an onscroll event has occurred yet. Unfortunately, it looks like Firefox also does not update the scrollY property smoothly during scrolling. In other words, there appears to be no way of testing whether or not a visible scroll has occurred until the actual onscroll event has fired, and by that point too much scrolling may already have occurred to make the parallax effect seem smooth.

Sorry to not be more helpful!

Nigglypuff fucked around with this message at 10:14 on Nov 25, 2009

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
There is an event queue. Callbacks don't get executed in parallel; they run immediately if nothing else is executing, or else they are scheduled to run when the main thread falls idle again. When you set a timeout or an interval, there is no guarantee that the callback will run exactly at the specified time — you can only provide a minimum wait. Likewise, onload event handlers are not necessarily called at the instant an asset loads, and if many events occur simultaneously their handlers will still execute in a sequence.

oops, beaten to a pulp

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
The document parameter inside DivWindowObject is undefined because you are not calling the function with any arguments. The windowTitle, width, height, xOrigin, and yOrigin parameters are all going to be undefined too, for the same reason :confused:

It looks like maybe you are calling the .show() method with those arguments instead of DivWindowObject itself.

Or maybe you are trying to access the global document variable, in which case you need to rename your local document variable to something else.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Are you calling setAttributeNS on DOM nodes from the page itself, or external XML nodes? I don't think it's possible to reimplement the method on nodes that don't already support it, but you might be able to work around the need to use it. Post some code!!!!! :bubblewoop:

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
How about replacing this line:
code:
            dummyelt = document.createElementNS(svgns,'image');
  
... with this?


code:
            var mockDocument =  document.getElementById('boardSVG').contentDocument;
            dummyelt = mockDocument.createElementNS(svgns,'image');
  

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
You don't need to be generating JS source as a string from existing JS code. It's an escaping nightmare, it's harder to read, and it severely increases the potential for XSS vulnerabilities in your app. It's almost never helpful.

Instead of the above, you could do this:
code:
        newdiv.innerHTML = "<blockquote><div></div></blockquote>";
        var subdiv = newdiv.firstChild.firstChild;
        subdiv.onclick = function () {
                calcRoute(postalAddress);
                hideContacts();
        };
        subdiv.innerHTML = contactEntry.getTitle().getText();

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Every element on a page can be uniquely identified by at least one CSS selector, even if it does not have an ID of its own. For example:
code:
html>body>h1
#container>.nav
#player>ul>li:nth-child(1)
I don't know of any library that generates these, but it wouldn't be hard to write one. You would just walk up the DOM, recording the tag/class of each parent element (and its index if it has siblings of the same type), until you reach either the root or an element with an explicit ID attribute.
You could of course store the resultant key differently, but if you express it as a normal CSS selector, you gain the advantage of being able to use a library like jQuery to find the element again by searching for it.

As long as the basic structure of the document doesn't change between reloads, such a CSS selector should always identify the same element.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

mit_senf posted:

I'm very doubtful at this point, but is there any way to do proper sound effects in a browser with Javascript? It's kind of depressing because making games in Javascript is a lot of fun :(

SoundManager2 is a full-featured sound library for the browser environment. Its interface is pure Javascript, but internally it is implemented using an invisible flash file, so it is not 100% native. Hopefully the scriptable <audio> element will gain traction soon, and provide an alternative backend for the library :)

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Try $(window).load(...) instead.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
The same-origin policy is a very good idea. Many of the major web security problems — CSRF, clickjacking etc — exist because it does not go far enough.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

Lamb-Blaster 4000 posted:

I've installed greasemetal, and put my user script (which works in greasemonkey) in the userjs folder, how do I tie the script to the site(s) its supposed to work on?

You don't need to use greasemetal. Chrome has supported userscripts natively for a while now. Internally, they get converted into extensions when you install them. Be aware, though, that the GM_method API is not fully supported.

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

geeves posted:

I don't know if this is a jQuery thing or not, but has anyone every successfully made a variable inside an anonymous function readable outside of it?

Any ideas?
code:
var exported = {};
(function() {
   var foo = {
       bar : function(sa) {}
   };
   exported.foo = foo;
})();
var foo = exported.foo;

Nigglypuff fucked around with this message at 16:44 on Oct 9, 2010

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

almostkorean posted:

Thanks, you are right :doh:. With that said, I'm 90% sure I'm going to finish making this extension using GWT. I really can't stand Javascript
Care to elaborate?

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL

Tres Burritos posted:

So I'm making my first ever webpage (yay!) and I've gotten to the point where I want to start adding some animations and stuff, the webdesign megathread recommended scriptaculous so I went with that.

So what I'm doing is when a user clicks on a link in the navigation bar, the 'CenterDoc' fades out and then fades back in with the relevant information. The solution that I have works, but not if you pound on one of the links, that breaks it. So what can I do to stop that? is there some sort of error checking or something I can do? I'm feeling like using setTimeout() is the wrong thing to do, but I'm at a loss.

I'd do something like this, to "lock" the function and make it non-reentrant while it has pending async callbacks in setTimeout:
code:
var centerDocVisible = true;

function centerDocSwitcher(switchTo) {
	if (centerDocSwitcher.locked) return;
	centerDocSwitcher.locked = true;
	
	Effect.Fold('centerDoc');
	
	setTimeout(function(){
		setContent('<p>' + switchTo + '</p>');
		Effect.BlindDown('centerDoc');
		centerDocSwitcher.locked = false;
	}, 2500);
};

function setContent(html) {
	document.getElementById('centerDoc').innerHTML = html;
};

Nigglypuff fucked around with this message at 03:51 on Jan 5, 2011

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
I don't think <script> tags inside a <frameset> are evaluated at all.

Adbot
ADBOT LOVES YOU

Nigglypuff
Nov 9, 2006


BUY ME BONESTORM
OR
GO TO HELL
Pretty sure the XPath selector backend was removed from jQuery, since the browsers who supported it all support document.querySelectorAll now anyway.

And since we're on the subject of jQuery:
code:
// ==UserScript==
// @name           SA: Open New Posts in New Tabs
// @include        htt*://forums.somethingawful.com/*
// ==/UserScript==

var $ = unsafeWindow.jQuery;

var button = $("<a href=# style='float:right;margin-right:8px'>Open New Posts in New Tabs</a>");

button.prependTo("th.title").click(function (event) {
	event.preventDefault();
	var nodes = $(".count").toArray();
	new function() {
		if (! nodes.length) return;
		GM_openInTab(nodes.shift().href);
		setTimeout(arguments.callee, 110);
	};
});

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