Page 1 of 2

disqus reply.html iframe placeholder out of place

Posted: Fri Jun 24, 2011 4:46 pm
by al_9x
http://torrentfreak.com/utorrent-gets-c ... se-110623/

It shifts about on every load, always out of place. Does it not makes sense to position placeholders relative to the container (in this case dsq-textarea-wrapper), if the blocked embedding is so positioned?

Re: disqus reply.html iframe placeholder out of place

Posted: Wed Jul 06, 2011 10:21 pm
by Giorgio Maone
Yes it does, but the placeholder already copies all the original object computed styles.
Maybe something that gets added later?

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 12:46 am
by al_9x
another example: http://www.ibtimes.com/

open any article

The disqus placeholder frequently ends up in the middle of the article. ctrl-f5 to repro more consistently.

Disqus is pretty popular, so this is worth addressing.

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 4:49 am
by al_9x
Here's the disqus.js code that creates the iframe

Code: Select all

function z(a) {
	if (r(P)) {
		var d = b.createElement("iframe");
		d.name = B + "TEST";
		q(d.style, {
			position: "absolute",
			left: "-2000px",
			top: "0px"
		});
		b.body.appendChild(d);
		P = d.contentWindow !== c.frames[d.name];
		b.body.removeChild(d)
	}
	P && !~navigator.userAgent.indexOf("Firefox") ? d = b.createElement('<iframe name="' + a.props.name + '"/>') : (d = b.createElement("IFRAME"), d.name = a.props.name);
	d.id = d.name = a.props.name;
	delete a.props.name;
	a.onLoad && C(d, "load", a.onLoad);
	if (typeof a.container == "string") a.container = b.getElementById(a.container);
	if (!a.container)
		d.style.position = "absolute", d.style.top = "-2000px", d.style.left = "0px", a.container = b.body;
	var e = a.props.src;
	delete a.props.src;
	q(d, a.props);
	d.border = d.frameBorder = 0;
	a.container.appendChild(d);
	d.src = e;
	a.props.src = e;
	return d
}
doesn't seem like there's any smoking gun here,

when it works, the placeholder (root div) computed style position is "static" and top, left, bottom, right are "auto"
when it fails (placeholder out of place), the position is "absolute" and top, left, bottom, right have px values, but it's not due to:

Code: Select all

if (!a.container)
	d.style.position = "absolute", d.style.top = "-2000px", d.style.left = "0px", a.container = b.body;

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 7:28 am
by al_9x
I found the culprit.

t_c4ca4238a0b923820dcc509a6f75849b.js has the following events:

Code: Select all

h("comments.reply.new.onLoadingStart", function (m) {
	var l = b.nodes.get("#dsq-textarea-wrapper" + (m ? "-" + m : ""));
	b.nodes.addClass(l, "dsq-textarea-loading ");
	var k = b.nodes.get("iframe", l)[0];
	if (k) {
		k.style.position = "absolute";
		k.style.top = "-2000px"
	}
});
h("comments.reply.new.onLoadingEnd", function (m) {
	var l = b.nodes.get("#dsq-textarea-wrapper" + (m ? "-" + m : ""));
	b.nodes.removeClass(l, "dsq-textarea-loading");
	var k = b.nodes.get("iframe", l)[0];
	if (k) {
		k.style.position = "relative";
		k.style.top = "0px"
	}
});
The first one screws up the placeholder style (depending on the timing), and the second one never gets called when the iframe is blocked, and even if it were called it probably wouldn't do any good (is that right?)

So one solution that comes to mind is unregistering one or both:

Code: Select all

DISQUS.dtpl.actions.remove('comments.reply.new.onLoadingStart');
I verified that with these events disabled in the source, the problem goes away.

The question is how to get the timing right, and how to invoke it for all pages with specific allowed script inclusions (disqus), as opposed to a fixed list of orgins (page level surrogates)

The event is registered in t_c4ca4238a0b923820dcc509a6f75849b.js and invoked in the onload of this script element. Perhaps a new type of surrogate for allowed rather than blocked scripts, is worth considering, that gets called in the onload of the script before any other onload handler from content. What do you think?

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 12:01 pm
by al_9x
I was wrong, the events (comments.reply.new.onLoadingStart, comments.reply.new.onLoadingEnd) are not registered in the script. They are both registered and invoked and from the load event of the script element. So here's a page level surrogate that demonstrates the feasibility of curing this problem, it simulates a "surrogate" for allowed scripts I proposed in the previous post.

Code: Select all

document.addEventListener('load', function(e) { if (e.target.tagName === 'SCRIPT' && e.target.src === 'http://mediacdn.disqus.com/1312320489/build/themes/t_c4ca4238a0b923820dcc509a6f75849b.js?1') DISQUS.dtpl.actions.register('comments.reply.new.onLoadingStart', function() { DISQUS.dtpl.actions.remove('comments.reply.new.onLoadingStart'); }); }, true);

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 9:20 pm
by al_9x
Here's a universal disqus surrogate

Code: Select all

user_pref("noscript.surrogate.disqus.sources", "@^http:");
user_pref("noscript.surrogate.disqus.replacement", "document.addEventListener('load', function(e) { if (e.target.tagName === 'SCRIPT' && /^http:\/\/mediacdn\.disqus\.com\/\d+\/build\/themes\/t_c4ca4238a0b923820dcc509a6f75849b\.js/.test(e.target.src)) DISQUS.dtpl.actions.register('comments.reply.new.onLoadingStart', function() { DISQUS.dtpl.actions.remove('comments.reply.new.onLoadingStart'); DISQUS.dtpl.actions.remove('comments.reply.new.onLoadingEnd');}); }, true);");
But like I said, this does not seem like the optimal way to do this, intercepting load events for everything, testing for a particular script. It's duplicating what NS is already probably doing, so NS could expose a script load surrogate in a more efficient manner.

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 10:29 pm
by Giorgio Maone
al_9x wrote:But like I said, this does not seem like the optimal way to do this, intercepting load events for everything, testing for a particular script. It's duplicating what NS is already probably doing, so NS could expose a script load surrogate in a more efficient manner.
Yes, any universal page surrogate should be avoided if possible, and this is surely a case in favor of surrogates to be run just before a matching external script is loaded.

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 10:39 pm
by al_9x
Giorgio Maone wrote:
al_9x wrote:But like I said, this does not seem like the optimal way to do this, intercepting load events for everything, testing for a particular script. It's duplicating what NS is already probably doing, so NS could expose a script load surrogate in a more efficient manner.
Yes, any universal page surrogate should be avoided if possible, and this is surely a case in favor of surrogates to be run just before a matching external script is loaded.
Here it would need to be after, not before, my disqus surrogate does its work in the load event for the script element, before the page's own script load handler has run, and wouldn't work otherwise.

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 10:47 pm
by Giorgio Maone
al_9x wrote:Here it would need to be after, not before, my disqus surrogate does its work in the load event for the script element, before the page's own script load handler has run
I don't get it. Your page-level surrogate currently runs before any other script runs (@), why running just before would be different than running long before?
Furthermore, running before is not just easier to implement, but is also more flexible than running after, as you can modify the environment for the code about to run and possibly prepare some code to run after.

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 11:10 pm
by al_9x
Giorgio Maone wrote:
al_9x wrote:Here it would need to be after, not before, my disqus surrogate does its work in the load event for the script element, before the page's own script load handler has run
I don't get it. Your page-level surrogate currently runs before any other script runs (@), why running just before would be different than running long before?
If it runs before, I am assuming I would still have to attach a capturing load handler to the document, and still have to match the script src in the handler for the second time (the first time is the surrogate matching the script) That's doesn't seem ideal, considering that for now this is the primary use case.

As to implementation, it should be possible to do both, if the surrogate is configured for before, run it, if after, add it as a load handler to the script element (hopefully you can do that earlier than any content)

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 11:25 pm
by al_9x
al_9x wrote: if after, add it as a load handler to the script element
Although that probably doesn't guarantee it runs ahead of all other possible load handlers for that script.

Are you able to register for a script load that guarantees you'll be first?

Re: disqus reply.html iframe placeholder out of place

Posted: Thu Aug 04, 2011 11:40 pm
by Giorgio Maone
al_9x wrote:Are you able to register for a script load that guarantees you'll be first?
A capture event handler attached to an element higher than content (i.e. in chrome) will run first (capture handlers are ran "topmost first").
Unfortunately a surrogate, being ran entirely in content, can't attach event handlers higher than the window object.
However, if you're suggesting that NoScript should hook the event on its side and run "after" surrogate from its handler, I'm not sure the added complexity is worth the benefits, considering as you said that this is the only use case so far.

Re: disqus reply.html iframe placeholder out of place

Posted: Fri Aug 05, 2011 12:06 am
by al_9x
I would say that running before is less useful than after. If you want to mod the behavior of an external script library (don't you think this could be generally useful?) you have to let it do its internal construction/init first and then patch the established objects and functions before they are used. Running before, there is nothing yet to mod.

Disqus is the first use case, but I am sure not the last. If patching/modding based on origins (page level) is useful then so will patching script libraries be (regardless of origin, before they can be used). Also disqus is quite popular, and it needs this (better than page level) surrogate solution. I am hoping you will implement the after surrogate.

Re: disqus reply.html iframe placeholder out of place

Posted: Fri Aug 12, 2011 2:59 pm
by Giorgio Maone
al_9x wrote:I am hoping you will implement the after surrogate.
A "before" surrogate can be easily turned into an "after" surrogate by registering a throw away capturing onload event handler, while the opposite (an "after" surrogate to modify the environment for the included script) is impossible.
So implementing the "before" surrogate only should cover all use cases without unnecessary complications.