https://wiki.greasespot.net/api.php?action=feedcontributions&user=Ecmanaut&feedformat=atomGreaseSpot Wiki - User contributions [en]2024-03-28T14:36:59ZUser contributionsMediaWiki 1.41.0https://wiki.greasespot.net/index.php?title=Talk:Location_hack&diff=5681Talk:Location hack2010-09-26T23:58:45Z<p>Ecmanaut: /* Alternate solution sketch for reading page scope variables */ new section</p>
<hr />
<div>== GM_eval vs. eval(s, unsafeWindow) vs. LocationHack ==<br />
<br />
<code>GM_eval()</code> will not be implemented.<br />
<br />
# [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/eval#Cross-implementation_compatibility The second argument of eval was removed].<br />
# Running <code>eval()</code> in chrome scope is a very dangerous thing to do.<br />
# I'm not confident that it actually worked to solve the problems that the location hack does. (I'm confident that it does not, on FF 3.0.13 on Linux. Perhaps it did in older versions, before it was removed.)<br />
<br />
== Location Hack Broken ==<br />
<br />
-Removed-<br />
<br />
Fromp: You are confused about what the location hack is supposed to accomplish.<br />
It's for letting a user script call into a function (for example) defined in the page.<br />
Your example which I just removed was doing the opposite.<br />
As written that example should never have worked.<br />
[[User:Arantius|Arantius]] 12:41, 16 September 2009 (EDT)<br />
<br />
== Polling ==<br />
<br />
[[User:Arantius|Arantius]] has removed the following passage that I had added:<br />
<br />
: It is possible that the location.href code is excuted (much) later than the readout code in the following lines. This breaks the location hack. (Observed in Firefox 3.6.8)<br />
<br />
This happened with Firefox 3.6.8 and broke the Wikipedia editor [http://en.wikipedia.org/wiki/User:Cacycle/wikEd wikEd]. The only work around was to poll the location hack element after having set location.href. Independent of the poll delay time the results arrives usually with the 1st or 2nd poll. I have to apply the location hack during the page loading period before the load event fires. Event triggering instead of polling was not possible because during the page loading none of the tested events fired (e.g. click) (Arantius also reverted that remark [http://wiki.greasespot.net/index.php?title=Generate_Click_Events&curid=1943&diff=5592&oldid=5591]). Please see the current working code and testcase below. [[User:Cacycle|Cacycle]] 00:53, 5 September 2010 (UTC)<br />
<br />
<pre>// ==UserScript==<br />
// @name location hack polling<br />
// @include *wiki*<br />
// ==/UserScript==<br />
<br />
window.Polling = function() {<br />
if (globalNode.value != '') {<br />
GM_log(globalNode.value);<br />
}<br />
else {<br />
GM_log('polling');<br />
setTimeout(Polling, 10);<br />
}<br />
}<br />
<br />
window.globalNode = document.createElement('textarea');<br />
globalNode.id = 'globalNode'<br />
document.body.appendChild(globalNode);<br />
location.href = 'javascript:document.getElementById(\'globalNode\').value = skin; void(0);';<br />
Polling();<br />
</pre><br />
<br />
== Alternate solution sketch for reading page scope variables ==<br />
<br />
While I don't know why Arantius removed the location hack helper (even the tersest change message would be useful), I can guess that it wasn't a dependable solution.<br />
<br />
I think some asynchronous solution might be more backwards-and-forwards compatible and dependable, even though the API is less friendly to javascript beginners, and the code size explodes. Maybe something like this (untested):<br />
<br />
// Query page javascript for the identifier "name", and call callback(value),<br />
// when found, or undefined, if not found or some error occurred. This works<br />
// only for values that can be JSON serialized -- numbers, strings, booleans,<br />
// null, or nested structures like Arrays and Objects that only contain above<br />
// mentioned types of data.<br />
function queryContentVar(name, callback) {<br />
// makes a random 20-char lowercase id<br />
function random() {<br />
var rand = '';<br />
while (rand.length < 20)<br />
rand += String.fromCharCode(97 + Math.random() * 26 | 0);<br />
return rand;<br />
}<br />
<br />
// Creates a mostly anonymous <meta> tag in the <head> section, giving it a<br />
// secret id we'll use for messaging back and forth with content space, and<br />
// fires pageInit() in the page scope (to listen and respond to queries from<br />
// us about variables) and registers reply() for answers from it at this end.<br />
function privInit() {<br />
var node = document.createElement('meta'), secret,<br />
head = document.getElementsByTagName('head')[0];<br />
node.id = secret = random();<br />
node.addEventListener(id, reply, false);<br />
head.appendChild(node);<br />
location.href = 'javascript:('+ pageInit +')('+ JSON.stringify(secret) +')';<br />
return node;<br />
}<br />
<br />
// Grabs the meta tag, anonymizes it and listens for incoming queries from us.<br />
function pageInit(secret) {<br />
// Replaces given <meta content="variable.name"> with <meta content="value"><br />
// (after JSON encoding it) and then alerts the caller to grab the response.<br />
function reply() {<br />
var name = node.getAttribute('content'),<br />
mesg = document.createEvent('Events'),<br />
val;<br />
try {<br />
val = eval(node.getAttribute('content'));<br />
val = JSON.stringify(val);<br />
} catch(e) { val = ''; }<br />
<br />
node.setAttribute('content', val);<br />
mesg.initEvent(secret, true, false);<br />
node.dispatchEvent(mesg);<br />
}<br />
<br />
var node = document.getElementById(secret);<br />
node.addEventListener(secret + '?', reply, false);<br />
node.removeAttribute('id');<br />
}<br />
<br />
var self = queryContentVar,<br />
node = self.node = self.node || privInit(),<br />
id = self.secret = self.secret || node.id,<br />
mesg = document.createEvent('Events');<br />
<br />
mesg.initEvent(secret + '?', true, false);<br />
node.setAttribute('content', name);<br />
self.callback = callback;<br />
node.dispatchEvent(mesg);<br />
<br />
// Picks up the response from content space, decodes it, passes it on to given<br />
// response callback and resets everything (just in case) to handle new calls.<br />
function reply() {<br />
var cb = self.callback,<br />
is = node.getAttribute('content');<br />
if (cb) cb(is === '' ? undefined : JSON.parse(is));<br />
node.removeAttribute('name');<br />
delete self.callback;<br />
}<br />
}<br />
<br />
<br />
--[[User:Ecmanaut|Ecmanaut]] 23:58, 26 September 2010 (UTC)</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Content_Scope_Runner&diff=5680Content Scope Runner2010-09-26T20:41:15Z<p>Ecmanaut: Noted suggestion to change the __PAGE_SCOPE_RUN__ identifier.</p>
<hr />
<div>An extension of the [[Content Script Injection]] technique, this snippet automatically runs the ''entire'' user script in the content scope.<br />
<br />
<pre class="sample">if ('undefined' == typeof __PAGE_SCOPE_RUN__) {<br />
(function page_scope_runner() {<br />
// If we're _not_ already running in the page, grab the full source<br />
// of this script.<br />
var my_src = "(" + page_scope_runner.caller.toString() + ")();";<br />
<br />
// Create a script node holding this script, plus a marker that lets us<br />
// know we are running in the page scope (not the Greasemonkey sandbox).<br />
// Note that we are intentionally *not* scope-wrapping here.<br />
var script = document.createElement('script');<br />
script.setAttribute("type", "application/javascript");<br />
script.setAttribute("src",<br />
"data:,"+escape("var __PAGE_SCOPE_RUN__ = true;\n" + my_src));<br />
<br />
// Insert the script node into the page, so it will run, and immediately<br />
// remove it to clean up. Use setTimeout to force execution "outside" of<br />
// the user script scope completely.<br />
setTimeout(function() {<br />
document.body.appendChild(script);<br />
document.body.removeChild(script);<br />
}, 0);<br />
})();<br />
<br />
// Stop running, because we know Greasemonkey actually runs us in<br />
// an anonymous wrapper.<br />
return;<br />
}</pre><br />
<br />
As soon as execution reaches this code, the entire script will be injected into the page and re-run. Thus you need not worry about any of the [[security]] restrictions from [[XPCNativeWrappers]] in the Greasemonkey [[sandbox]]. You also will, of course, not have access to any of the [[API]]s.<br />
<br />
== Tips ==<br />
<br />
* This code must not be wrapped in a function, or the <code>return</code> will fail to work. It may be wrapped in a conditional.<br />
* Any code before (and including) this block will be run twice: Once in GreaseMonkey context, once in page context.<br />
* Any code after this block will only be run once, in the page context.<br />
* You should change __PAGE_SCOPE_RUN__ to another identifier not present in web pages you run on and unique to your script, or only one of potentially multiple scripts the user has installed running on the current page will actually run.<br />
<br />
== Explanation ==<br />
<br />
The code block first checks to see if it is being run inside the page by looking for a marker it knows about.<br />
If the marker is not present, the block creates and injects a script element that starts by setting the aforementioned marker variable and finishes by executing the text of the user script.<br />
Finally, the block calls <code>return</code>, ending execution.<br />
<br />
== @require ==<br />
<br />
Since it must run before the rest of the script, this snipped functions best as the first [[Metadata Block#.40require|@require]].<br />
Try it by adding this line as the first @require in the [[Metadata Block]]:<br />
<br />
<nowiki>// @require http://userscripts.org/scripts/source/68059.user.js</nowiki><br />
<br />
[[Category:Coding Tips:Interacting With The Page]]<br />
[[Category:@require Library]]</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Greasemonkey_Manual:Environment&diff=3093Greasemonkey Manual:Environment2009-03-08T23:40:21Z<p>Ecmanaut: Additional note on function-in-function declarations, for the javascript unsavvy.</p>
<hr />
<div>{{Greasemonkey Manual TOC}}<br />
<br />
== Why a Special Environment? ==<br />
<br />
When [[Greasemonkey]] executes a [[user script]] it does so in a special [[sandbox]] environment.<br />
[[Greasemonkey]] takes advantage of a Firefox feature called [[XPCNativeWrappers]] to insulate the [[user script]] from the content web page, which it references.<br />
<br />
Although this makes it more difficult, or impossible, to do certain things in your script, it is a necessary evil.<br />
Earlier [[version history|versions]] of [[Greasemonkey]] had no such sandbox, and as a result, [[security]] holes were uncovered.<br />
<br />
[[Greasemonkey]] provides certain enhanced [[Greasemonkey Manual:APIs|APIs]] to the [[user script]], so that it may accomplish things that a regular web page's javascript cannot.<br />
This useful feature has enabled some of the most popular scripts.<br />
Unfortunately, when abused, these powerful features can create serious problems.<br />
No exploits were ever uncovered in the wild, but the potential was too great, so the sandbox environment was created.<br />
<br />
Luckily, for almost all the difficulties that the sandbox environment provides, there are ways to still accomplish the desired goal.<br />
The article [http://www.oreillynet.com/pub/a/network/2005/11/01/avoid-common-greasemonkey-pitfalls.html Avoid Common Pitfalls in Greasemonkey] does a wonderful job explaining what the most common snags are, and for each one explains the way to work around the problem.<br />
It is essential reading for any script author.<br />
<br />
Finally, of note is the [[unsafeWindow]] object present in the sandbox.<br />
As the name implies, use of this object is ''unsafe''!<br />
This is the raw, un-sandboxed "window" of the content page.<br />
Certain limited tasks can only be accomplished by referencing this raw window directly, but be warned!<br />
Javascript is a complicated and intricate language, even the most basic operations can be redefined by the content page to perform other actions.<br />
The sandbox environment is provided for your safety, and the safety of any user of your script.<br />
If at all possible, use of [[unsafeWindow]] should be avoided.<br />
<br />
== What's Missing? ==<br />
<br />
Depending on your usage, the special [[Greasemonkey]] environment may seem perfectly normal, or excessively limiting.<br />
<br />
The Greasemonkey environment is a vanilla [[XPCNativeWrapper]] of the content window, with only certain extra bits added in to emulate a normal environment, or changed. Specifically:<br />
<br />
:* <code>window</code> is an [[XPCNativeWrapper|XPCNativeWrapper]] of the content window.<br />
:* <code>document</code> is the document object of the XPCNativeWrapper window object.<br />
:* [[XPathResult]] is added so that <code>document.evaluate()</code> works.<br />
:* Unless the @unwrap metadata imperative is present in the user script header, the entire script is wrapped inside an [http://en.wikipedia.org/wiki/Anonymous_function anonymous function], to guarantee the script's identifiers do not collide with identifiers present in the Mozilla javascript sandbox, resulting in [http://greasemonkey.devjavu.com/ticket/108 confusing breakage]. This function wrapper captures any function definitions and <code>var</code> variable declarations you make (e g <code>var i = 5;</code>) into the function's local scope. Declarations you make without <code>var</code> will however end up on the script's <code>this</code> object, which in Greasemonkey is the global object, contrary to in the normal browser object model, where the <code>window</code> object fills this function. In effect, after <code>i = 5;</code>, the values of <code>window['i']</code> and <code>window.i</code> remain undefined, whereas <code>this['i']</code> and <code>this.i</code> will be 5. See also: [[Global_object]]<br />
:* In order to access variables on the page, you need to use the [[unsafeWindow]] object. To use values defined in your script, simply reference them by their names.<br />
<br />
Since Mozilla provides a rich environment, there are a wide variety of things that have ''not'' been imported from the general content scope into the Greasemonkey sandbox.<br />
Including, but not limited to:<br />
<br />
:* [http://developer.mozilla.org/en/docs/DOM:document.createTreeWalker document.createTreeWalker]<br />
:* [http://www.xulplanet.com/references/objref/SOAPCall.html SOAPCall]<br />
<br />
The more esoteric the method, the ''less likely'' that it has been included in the Greasemonkey sandbox.<br />
<br />
== See also ==<br />
<br />
* Wikipedia: [http://en.wikipedia.org/wiki/Sandbox_(computer_security) Sandbox]<br />
* [[Security]]<br />
* [http://www.oreillynet.com/pub/a/network/2005/11/01/avoid-common-greasemonkey-pitfalls.html Avoid Common Pitfalls in Greasemonkey]</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Greasemonkey_Manual:Environment&diff=3092Greasemonkey Manual:Environment2009-03-08T23:38:32Z<p>Ecmanaut: Better info on the global object, default function wrapper and @unwrap.</p>
<hr />
<div>{{Greasemonkey Manual TOC}}<br />
<br />
== Why a Special Environment? ==<br />
<br />
When [[Greasemonkey]] executes a [[user script]] it does so in a special [[sandbox]] environment.<br />
[[Greasemonkey]] takes advantage of a Firefox feature called [[XPCNativeWrappers]] to insulate the [[user script]] from the content web page, which it references.<br />
<br />
Although this makes it more difficult, or impossible, to do certain things in your script, it is a necessary evil.<br />
Earlier [[version history|versions]] of [[Greasemonkey]] had no such sandbox, and as a result, [[security]] holes were uncovered.<br />
<br />
[[Greasemonkey]] provides certain enhanced [[Greasemonkey Manual:APIs|APIs]] to the [[user script]], so that it may accomplish things that a regular web page's javascript cannot.<br />
This useful feature has enabled some of the most popular scripts.<br />
Unfortunately, when abused, these powerful features can create serious problems.<br />
No exploits were ever uncovered in the wild, but the potential was too great, so the sandbox environment was created.<br />
<br />
Luckily, for almost all the difficulties that the sandbox environment provides, there are ways to still accomplish the desired goal.<br />
The article [http://www.oreillynet.com/pub/a/network/2005/11/01/avoid-common-greasemonkey-pitfalls.html Avoid Common Pitfalls in Greasemonkey] does a wonderful job explaining what the most common snags are, and for each one explains the way to work around the problem.<br />
It is essential reading for any script author.<br />
<br />
Finally, of note is the [[unsafeWindow]] object present in the sandbox.<br />
As the name implies, use of this object is ''unsafe''!<br />
This is the raw, un-sandboxed "window" of the content page.<br />
Certain limited tasks can only be accomplished by referencing this raw window directly, but be warned!<br />
Javascript is a complicated and intricate language, even the most basic operations can be redefined by the content page to perform other actions.<br />
The sandbox environment is provided for your safety, and the safety of any user of your script.<br />
If at all possible, use of [[unsafeWindow]] should be avoided.<br />
<br />
== What's Missing? ==<br />
<br />
Depending on your usage, the special [[Greasemonkey]] environment may seem perfectly normal, or excessively limiting.<br />
<br />
The Greasemonkey environment is a vanilla [[XPCNativeWrapper]] of the content window, with only certain extra bits added in to emulate a normal environment, or changed. Specifically:<br />
<br />
:* <code>window</code> is an [[XPCNativeWrapper|XPCNativeWrapper]] of the content window.<br />
:* <code>document</code> is the document object of the XPCNativeWrapper window object.<br />
:* [[XPathResult]] is added so that <code>document.evaluate()</code> works.<br />
:* Unless the @unwrap metadata imperative is present in the user script header, the entire script is wrapped inside an [http://en.wikipedia.org/wiki/Anonymous_function anonymous function], to guarantee the script's identifiers do not collide with identifiers present in the Mozilla javascript sandbox, resulting in [http://greasemonkey.devjavu.com/ticket/108 confusing breakage]. This function wrapper captures any <code>var</code> variable declarations you make (e g <code>var i = 5;</code>) into the function's local variables. Declarations you make without <code>var</code> will however end up on the script's <code>this</code> object, which in Greasemonkey is the global object, contrary to the normal browser object model, where the <code>window</code> object fills this function. In effect, after <code>i = 5;</code>, the values of <code>window['i']</code> and <code>window.i</code> remain undefined, whereas <code>this['i']</code> and <code>this.i</code> will be 5. See also: [[Global_object]]<br />
:* In order to access variables on the page, you need to use the [[unsafeWindow]] object. To use values defined in your script, simply reference them by their names.<br />
<br />
Since Mozilla provides a rich environment, there are a wide variety of things that have ''not'' been imported from the general content scope into the Greasemonkey sandbox.<br />
Including, but not limited to:<br />
<br />
:* [http://developer.mozilla.org/en/docs/DOM:document.createTreeWalker document.createTreeWalker]<br />
:* [http://www.xulplanet.com/references/objref/SOAPCall.html SOAPCall]<br />
<br />
The more esoteric the method, the ''less likely'' that it has been included in the Greasemonkey sandbox.<br />
<br />
== See also ==<br />
<br />
* Wikipedia: [http://en.wikipedia.org/wiki/Sandbox_(computer_security) Sandbox]<br />
* [[Security]]<br />
* [http://www.oreillynet.com/pub/a/network/2005/11/01/avoid-common-greasemonkey-pitfalls.html Avoid Common Pitfalls in Greasemonkey]</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=CSS_Independent_Content&diff=2544CSS Independent Content2008-02-28T18:17:56Z<p>Ecmanaut: More correct.</p>
<hr />
<div>Any HTML you inject into a site is subject to the CSS rules of that site. This is often what you want: the elements you inject will fit in nicely. But if you inject something – perhaps a configuration panel – that should look the same to pages where styles can vary wildly (e.g. MySpace, eBay) or across multiple sites (e.g. @include *), you may find that you want it exempt from the site CSS.<br />
<br />
The solution is to add your panel inside an iframe. Example code:<br />
<br />
// position:fixed means stay fixed even the page scrolls. z-index keeps your iframe on top.<br />
// The remainder of the line smacks the panel into the bottom left corner, out of your way.<br />
// Overflow (in combination with the setTimeout) ensures the iframe fits your entire panel.<br />
var css = 'position:fixed; z-index:9999; bottom:0; left:0; border:0; margin:0; padding:0; ' +<br />
'overflow:hidden;'<br />
<br />
var iframe = document.createElement('iframe');<br />
iframe.setAttribute('style', css);<br />
<br />
// The about:blank page becomes a blank(!) canvas to modify<br />
iframe.src = 'about:blank';<br />
<br />
document.body.appendChild(iframe);<br />
<br />
// Make sure Firefox initializes the DOM before we try to use it.<br />
iframe.addEventListener("load", function() {<br />
var doc = iframe.contentDocument;<br />
doc.body.style.background = 'red';<br />
doc.body.innerHTML = 'Test.';<br />
iframe.style.width = doc.body.offsetWidth + "px";<br />
iframe.style.height = doc.body.offsetHeight + "px";<br />
}, false);<br />
<br />
The above code will result in a minimal panel always-on-top in the bottom left corner, that grows to contain its contents. For a more intrusive lightbox-style panel mid-screen, just drop the two <code>iframe.style</code> lines and change the CSS to e.g.:<br />
<br />
// Margin, top, left, width and height center the iframe horizontally and vertically:<br />
var css = 'position:fixed; z-index:9999; border:1px solid black; ' +<br />
'top:50%; left:50%; width:30em; margin:-15em; 0 0 -10em; height:20em;';<br />
<br />
As Firefox's iframe handling is [https://bugzilla.mozilla.org/show_bug.cgi?id=295813 rather] [https://bugzilla.mozilla.org/show_bug.cgi?id=388714 buggy], you may want to spare yourself much pain by using [http://ecmanaut.googlecode.com/svn/trunk/lib/make-iframe.js this handy library] for roughly the above, though better pampering those bugs, and use code like this instead:<br />
<br />
makeFrame(gotFrame);<br />
<br />
function gotGrame(iframe, win, doc) {<br />
iframe.height = "50";<br />
iframe.style.position = "fixed";<br />
frame.style.bottom = iframe.style.left = "0";<br />
doc.body.innerHTML = "Hello world!";<br />
}</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=CSS_Independent_Content&diff=2543CSS Independent Content2008-02-28T18:12:59Z<p>Ecmanaut: A handy library.</p>
<hr />
<div>Any HTML you inject into a site is subject to the CSS rules of that site. This is often what you want: the elements you inject will fit in nicely. But if you inject something – perhaps a configuration panel – that should look the same to pages where styles can vary wildly (e.g. MySpace, eBay) or across multiple sites (e.g. @include *), you may find that you want it exempt from the site CSS.<br />
<br />
The solution is to add your panel inside an iframe. Example code:<br />
<br />
// position:fixed means stay fixed even the page scrolls. z-index keeps your iframe on top.<br />
// The remainder of the line smacks the panel into the bottom left corner, out of your way.<br />
// Overflow (in combination with the setTimeout) ensures the iframe fits your entire panel.<br />
var css = 'position:fixed; z-index:9999; bottom:0; left:0; border:0; margin:0; padding:0; ' +<br />
'overflow:hidden;'<br />
<br />
var iframe = document.createElement('iframe');<br />
iframe.setAttribute('style', css);<br />
<br />
// The about:blank page becomes a blank(!) canvas to modify<br />
iframe.src = 'about:blank';<br />
<br />
document.body.appendChild(iframe);<br />
<br />
// Make sure Firefox initializes the DOM before we try to use it.<br />
iframe.addEventListener("load", function() {<br />
var doc = iframe.contentDocument;<br />
doc.body.style.background = 'red';<br />
doc.body.innerHTML = 'Test.';<br />
iframe.style.width = doc.body.offsetWidth + "px";<br />
iframe.style.height = doc.body.offsetHeight + "px";<br />
}, false);<br />
<br />
The above code will result in a minimal panel always-on-top in the bottom left corner, that grows to contain its contents. For a more intrusive lightbox-style panel mid-screen, just drop the two <code>iframe.style</code> lines and change the CSS to e.g.:<br />
<br />
// Margin, top, left, width and height center the iframe horizontally and vertically:<br />
var css = 'position:fixed; z-index:9999; border:1px solid black; ' +<br />
'top:50%; left:50%; width:30em; margin:-15em; 0 0 -10em; height:20em;';<br />
<br />
As Firefox's iframe handling is [https://bugzilla.mozilla.org/show_bug.cgi?id=295813 rather] [https://bugzilla.mozilla.org/show_bug.cgi?id=388714 buggy], you may want to spare yourself some pain by using [http://ecmanaut.googlecode.com/svn/trunk/lib/make-iframe.js a handy library] for the above, and use code like this instead:<br />
<br />
makeFrame(gotFrame);<br />
<br />
function gotGrame(iframe, win, doc) {<br />
iframe.height = "50";<br />
iframe.style.position = "fixed";<br />
frame.style.bottom = iframe.style.left = "0";<br />
doc.body.innerHTML = "Hello world!";<br />
}</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=UnsafeWindow&diff=2534UnsafeWindow2008-02-06T17:21:48Z<p>Ecmanaut: Another explicit mention of affected GM_* APIs vs unsafeWindow compat.</p>
<hr />
<div>{{lowercase}}<br />
{{security}}<br />
__NOTOC__<br />
<br />
== Description ==<br />
<br />
This [[API_reference|API]] object allows a [[User script]] to access "custom" properties--variable and functions defined in the page--set by the web page.<br />
<br />
This is done by bypassing [[Greasemonkey]]'s [[XPCNativeWrapper]]-based [[security]] model.<br />
The unsafeWindow object is shorthand for <code>window.wrappedJSObject</code>. It is the raw window object inside the XPCNativeWrapper provided by the Greasemonkey [[sandbox]].<br />
<br />
:*'''USE OF UNSAFEWINDOW IS INSECURE, AND IT SHOULD BE AVOIDED WHENEVER POSSIBLE.'''<br />
User scripts absolutely should not use unsafeWindow if they are executed for arbitrary web pages, such as those with <code>@[[Include and exclude rules|include]] *</code>.<br />
[[User script]] authors are '''strongly''' encouraged to learn how [[XPCNativeWrapper]]s work, and how to perform the desired function within their security context, instead of using unsafeWindow to break out.<br />
<br />
[[#Examples|Examples]] | [[#Alternatives_to_unsafeWindow|Alternatives to unsafeWindow]] | [[#Notes|Notes]]<br />
<br />
== Syntax ==<br />
<br />
'''unsafeWindow'''<br />
<br />
:Value: Object<br />
:Returns: Variant<br />
:Compatibility: [[Version_history#0.5_beta|Greasemonkey 0.5b+]], [[Version_history#0.7.20080121.0|Greasemonkey 0.7.20080121.0+]]<br />
<br />
[[#top|top]]<br />
<br />
== Examples ==<br />
<code><pre><br />
unsafeWindow.SomeVarInPage = "Testing";<br />
</pre></code><br />
<br />
<code><pre><br />
unsafeWindow.SomeFunctionInPage("Test");<br />
</pre></code><br />
<br />
<code><pre><br />
var oldFunction = unsafeWindow.SomeFunctionInPage;<br />
unsafeWindow.SomeFunctionInPage = function(text) {<br />
alert("Hijacked! Argument was " + text + ".");<br />
return oldFunction(text);<br />
};<br />
</pre></code><br />
<br />
For issues with GM_getValue, GM_setValue and GM_xmlhttpRequest, see see [[http://wiki.greasespot.net/0.7.20080121.0_compatibility]].<br />
<br />
[[#top|top]]<br />
<br />
== Alternatives to unsafeWindow ==<br />
<br />
[[#Events|Events]] | [[#Functions_defined_in_the_page|Functions defined in the page]]<br />
<br />
=== Events ===<br />
<br />
:Event listeners never need to be created on unsafeWindow. Rather than using <code>unsafeWindow.onclick = function(event) { ... };</code>, use:<br />
<br />
:<code><pre>window.addEventListener("click", function(event) { /* some code */ }, false);</pre></code><br />
<br />
:*[http://developer.mozilla.org/en/docs/DOM:element.addEventListener addEventListener at MDC]<br />
<br />
[[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]<br />
<br />
=== Functions defined in the page ===<br />
<br />
:If a user script must execute a page function, it can use the '''[[location hack]]''' to call it safely. This involves setting location.href to a <code>javascript:</code> URL, which is like using a bookmarklet. For example:<br />
<br />
:<code><pre>location.href = "javascript:void(pageFunc(123));";</pre></code><br />
<br />
:Larger blocks of code independent of the Greasemonkey context/APIs can also be executed this way:<br />
<br />
:<code><pre>location.href = "javascript:(" + encodeURI(uneval(function() { /* some code */ })) + ")();";</pre></code><br />
<br />
:This code will run in the page context without leaking the [[sandbox]]. This code is completely separate from the rest of the script scope, sometimes limiting its usefulness. For example, data cannot be returned by the function.<br />
<br />
:Another drawback is that this technique is rather ugly. Still, it is preferred over unsafeWindow.<br />
<br />
[[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]<br />
<br />
== Notes ==<br />
[[#top|top]]<br />
<br />
[[Category:API_Reference|U]] <br />
[[Category:Scripting context]]<br />
[[Category:Security]]</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=UnsafeWindow&diff=2533UnsafeWindow2008-02-06T17:13:44Z<p>Ecmanaut: Minor mention of obvious-to-wizards limitations of the location hack.</p>
<hr />
<div>{{lowercase}}<br />
{{security}}<br />
__NOTOC__<br />
<br />
== Description ==<br />
<br />
This [[API_reference|API]] object allows a [[User script]] to access "custom" properties--variable and functions defined in the page--set by the web page.<br />
<br />
This is done by bypassing [[Greasemonkey]]'s [[XPCNativeWrapper]]-based [[security]] model.<br />
The unsafeWindow object is shorthand for <code>window.wrappedJSObject</code>. It is the raw window object inside the XPCNativeWrapper provided by the Greasemonkey [[sandbox]].<br />
<br />
:*'''USE OF UNSAFEWINDOW IS INSECURE, AND IT SHOULD BE AVOIDED WHENEVER POSSIBLE.'''<br />
User scripts absolutely should not use unsafeWindow if they are executed for arbitrary web pages, such as those with <code>@[[Include and exclude rules|include]] *</code>.<br />
[[User script]] authors are '''strongly''' encouraged to learn how [[XPCNativeWrapper]]s work, and how to perform the desired function within their security context, instead of using unsafeWindow to break out.<br />
<br />
[[#Examples|Examples]] | [[#Alternatives_to_unsafeWindow|Alternatives to unsafeWindow]] | [[#Notes|Notes]]<br />
<br />
== Syntax ==<br />
<br />
'''unsafeWindow'''<br />
<br />
:Value: Object<br />
:Returns: Variant<br />
:Compatibility: [[Version_history#0.5_beta|Greasemonkey 0.5b+]], [[Version_history#0.7.20080121.0|Greasemonkey 0.7.20080121.0+]]<br />
<br />
[[#top|top]]<br />
<br />
== Examples ==<br />
<code><pre><br />
unsafeWindow.SomeVarInPage = "Testing";<br />
</pre></code><br />
<br />
<code><pre><br />
unsafeWindow.SomeFunctionInPage("Test");<br />
</pre></code><br />
<br />
<code><pre><br />
var oldFunction = unsafeWindow.SomeFunctionInPage;<br />
unsafeWindow.SomeFunctionInPage = function(text) {<br />
alert("Hijacked! Argument was " + text + ".");<br />
return oldFunction(text);<br />
};<br />
</pre></code><br />
<br />
[[#top|top]]<br />
<br />
== Alternatives to unsafeWindow ==<br />
<br />
[[#Events|Events]] | [[#Functions_defined_in_the_page|Functions defined in the page]]<br />
<br />
=== Events ===<br />
<br />
:Event listeners never need to be created on unsafeWindow. Rather than using <code>unsafeWindow.onclick = function(event) { ... };</code>, use:<br />
<br />
:<code><pre>window.addEventListener("click", function(event) { /* some code */ }, false);</pre></code><br />
<br />
:*[http://developer.mozilla.org/en/docs/DOM:element.addEventListener addEventListener at MDC]<br />
<br />
[[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]<br />
<br />
=== Functions defined in the page ===<br />
<br />
:If a user script must execute a page function, it can use the '''[[location hack]]''' to call it safely. This involves setting location.href to a <code>javascript:</code> URL, which is like using a bookmarklet. For example:<br />
<br />
:<code><pre>location.href = "javascript:void(pageFunc(123));";</pre></code><br />
<br />
:Larger blocks of code independent of the Greasemonkey context/APIs can also be executed this way:<br />
<br />
:<code><pre>location.href = "javascript:(" + encodeURI(uneval(function() { /* some code */ })) + ")();";</pre></code><br />
<br />
:This code will run in the page context without leaking the [[sandbox]]. This code is completely separate from the rest of the script scope, sometimes limiting its usefulness. For example, data cannot be returned by the function.<br />
<br />
:Another drawback is that this technique is rather ugly. Still, it is preferred over unsafeWindow.<br />
<br />
[[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]<br />
<br />
== Notes ==<br />
[[#top|top]]<br />
<br />
[[Category:API_Reference|U]] <br />
[[Category:Scripting context]]<br />
[[Category:Security]]</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=UnsafeWindow&diff=2532UnsafeWindow2008-02-06T17:09:44Z<p>Ecmanaut: Additional important compatibility reference.</p>
<hr />
<div>{{lowercase}}<br />
{{security}}<br />
__NOTOC__<br />
<br />
== Description ==<br />
<br />
This [[API_reference|API]] object allows a [[User script]] to access "custom" properties--variable and functions defined in the page--set by the web page.<br />
<br />
This is done by bypassing [[Greasemonkey]]'s [[XPCNativeWrapper]]-based [[security]] model.<br />
The unsafeWindow object is shorthand for <code>window.wrappedJSObject</code>. It is the raw window object inside the XPCNativeWrapper provided by the Greasemonkey [[sandbox]].<br />
<br />
:*'''USE OF UNSAFEWINDOW IS INSECURE, AND IT SHOULD BE AVOIDED WHENEVER POSSIBLE.'''<br />
User scripts absolutely should not use unsafeWindow if they are executed for arbitrary web pages, such as those with <code>@[[Include and exclude rules|include]] *</code>.<br />
[[User script]] authors are '''strongly''' encouraged to learn how [[XPCNativeWrapper]]s work, and how to perform the desired function within their security context, instead of using unsafeWindow to break out.<br />
<br />
[[#Examples|Examples]] | [[#Alternatives_to_unsafeWindow|Alternatives to unsafeWindow]] | [[#Notes|Notes]]<br />
<br />
== Syntax ==<br />
<br />
'''unsafeWindow'''<br />
<br />
:Value: Object<br />
:Returns: Variant<br />
:Compatibility: [[Version_history#0.5_beta|Greasemonkey 0.5b+]], [[Version_history#0.7.20080121.0|Greasemonkey 0.7.20080121.0+]]<br />
<br />
[[#top|top]]<br />
<br />
== Examples ==<br />
<code><pre><br />
unsafeWindow.SomeVarInPage = "Testing";<br />
</pre></code><br />
<br />
<code><pre><br />
unsafeWindow.SomeFunctionInPage("Test");<br />
</pre></code><br />
<br />
<code><pre><br />
var oldFunction = unsafeWindow.SomeFunctionInPage;<br />
unsafeWindow.SomeFunctionInPage = function(text) {<br />
alert("Hijacked! Argument was " + text + ".");<br />
return oldFunction(text);<br />
};<br />
</pre></code><br />
<br />
[[#top|top]]<br />
<br />
== Alternatives to unsafeWindow ==<br />
<br />
[[#Events|Events]] | [[#Functions_defined_in_the_page|Functions defined in the page]]<br />
<br />
=== Events ===<br />
<br />
:Event listeners never need to be created on unsafeWindow. Rather than using <code>unsafeWindow.onclick = function(event) { ... };</code>, use:<br />
<br />
:<code><pre>window.addEventListener("click", function(event) { /* some code */ }, false);</pre></code><br />
<br />
:*[http://developer.mozilla.org/en/docs/DOM:element.addEventListener addEventListener at MDC]<br />
<br />
[[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]<br />
<br />
=== Functions defined in the page ===<br />
<br />
:If a user script must execute a page function, it can use the '''[[location hack]]''' to call it safely. This involves setting location.href to a <code>javascript:</code> URL, which is like using a bookmarklet. For example:<br />
<br />
:<code><pre>location.href = "javascript:void(pageFunc(123));";</pre></code><br />
<br />
:Larger blocks of code can also be executed this way:<br />
<br />
:<code><pre>location.href = "javascript:(" + encodeURI(uneval(function() { /* some code */ })) + ")();";</pre></code><br />
<br />
:This code will run in the page context without leaking the [[sandbox]]. This code is completely separate from the rest of the script scope, sometimes limiting its usefulness. For example, data cannot be returned by the function.<br />
<br />
:Another drawback is that this technique is rather ugly. Still, it is preferred over unsafeWindow.<br />
<br />
[[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]<br />
<br />
== Notes ==<br />
[[#top|top]]<br />
<br />
[[Category:API_Reference|U]] <br />
[[Category:Scripting context]]<br />
[[Category:Security]]</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Version_history&diff=2531Version history2008-02-06T17:07:14Z<p>Ecmanaut: Updated with info on the 0.7.20080121.0 security release. (Updating this page probably ought to go into some kind of release workflow reminder somewhere.)</p>
<hr />
<div>''(What was the earliest version? I know it's lower than 0.2.5.)''<br />
<br />
''(Details needed especially for versions 0.4.x and 0.5.x.)''<br />
<br />
== 0.2.5 ==<br />
<br />
March 28th, 2005<br />
[http://greaseblog.blogspot.com/2005/03/greasemonkey-025-xmlhttp-across.html]<br />
[http://greasemonkey.mozdev.org/changes/0.2.5.html]<br />
<br />
Introduced:<br />
* [[GM_xmlhttpRequest]]<br />
* [[GM_registerMenuCommand]]<br />
<br />
Also, the default user scripts that were bundled with [[Greasemonkey]] by default until this point were removed.<br />
<br />
== 0.2.6 ==<br />
<br />
March 30th, 2005<br />
[http://greaseblog.blogspot.com/2005/03/greasemonkey-026-now-with-less-fatal.html]<br />
[http://greasemonkey.mozdev.org/changes/0.2.6.html]<br />
<br />
Bugfix release.<br />
<br />
== 0.3 beta ==<br />
<br />
April 23rd, 2005<br />
[http://greaseblog.blogspot.com/2005/04/greasemonkey-03b-beta.html]<br />
[http://greasemonkey.mozdev.org/changes/0.3b.html]<br />
<br />
Introduced:<br />
* Edit button in the manage dialog.<br />
* Monkey icon in the status bar, click to enable/disable.<br />
* [[GM_getValue]], [[GM_setValue]], [[GM_log]]<br />
<br />
== 0.3.3 ==<br />
<br />
May 10th, 2005<br />
[http://greaseblog.blogspot.com/2005/05/greasemonkey-033-beta.html]<br />
[http://greasemonkey.mozdev.org/changes/0.3.3.html]<br />
<br />
Primarily bugfix release.<br />
<br />
== 0.3.4 ==<br />
<br />
May 12th, 2005<br />
[http://greasemonkey.mozdev.org/changes/0.3.4.html]<br />
<br />
Introduced:<br />
* ".tld" support in @include/@exclude, allowing things like <code>@include http://www.google.tld/</code> for all international permutations.<br />
* Log level option for [[GM_log]]<br />
* Minor enhancements and bugfixes.<br />
<br />
== 0.3.5 ==<br />
<br />
July 19th, 2005<br />
[http://greaseblog.blogspot.com/2005/07/mandatory-greasemonkey-update.html]<br />
[http://greasemonkey.mozdev.org/changes/0.3.5.html]<br />
<br />
[[Security]] flaw release.<br />
Contained no fixes, rather removed all vulnerable features.<br />
Intended for (limited) continued use while fixes were being performed.<br />
<br />
== 0.4.x ==<br />
<br />
''Details needed.''<br />
<br />
The 0.4 branch was an internal development version, where experimentation for security fixes happened.<br />
<br />
== 0.5 beta ==<br />
<br />
July 30th, 2005<br />
[http://greaseblog.blogspot.com/2005/07/greasemonkey-05-beta.html]<br />
[http://greasemonkey.mozdev.org/changes/0.5.html]<br />
<br />
The first release containing [[security]] fixes over 0.3.5 intended for public consumption.<br />
"Greasemonkey 0.5 is actually the combination of a massive security audit and all the new code which was planned for 0.4."<br />
<br />
Introduced:<br />
* [[GM_openInTab]], [[unsafeWindow]]<br />
* Enhancements to [[GM_registerMenuCommand]]: keyboard shortcuts, stability.<br />
* Memory leak fixes.<br />
* "New User Script" menu item, shortcut to a new blank template for [[user script]] authors.<br />
* Restricted [[GM_xmlhttpRequest]] from accessing local <code>file://</code> URLs.<br />
<br />
== 0.5.1 ==<br />
<br />
August 25, 2005<br />
[http://greaseblog.blogspot.com/2005/08/greasemonkey-051-final.html]<br />
[http://greasemonkey.mozdev.org/changes/0.5.1.html]<br />
<br />
Introduced:<br />
* Security fix wherein a [[user script]] could elevate itself to chrome privileges.<br />
* User can select the editor to use for "Edit" in manage, and "New User Script".<br />
* Unicode support for non-english characters.<br />
<br />
== 0.5.2 ==<br />
<br />
September 1st, 2005<br />
[http://greaseblog.blogspot.com/2005/09/035-051-migration-madness.html]<br />
<br />
Released to the [[Greasemonkey]] [[mailing list]], fixed bugs in the automatic migration system for the changes between the 0.3 and 0.5 branches.<br />
<br />
== 0.5.3 ==<br />
<br />
September 3rd, 2005<br />
[http://greaseblog.blogspot.com/2005/09/053-available.html]<br />
[http://greasemonkey.mozdev.org/changes/0.5.3.html]<br />
<br />
== 0.6.1 ==<br />
September 9th'ish, 2005<br />
<br />
"The Lost Version"<br />
<br />
Prerelease showing of:<br />
* [[GM_addStyle|GM_addStyle]] (From release 0.6.1.4... I probably have this archived somewhere LOL)<br />
* The [[Greasemonkey_Manual:Monkey_Menu|Monkey Menu]], a context menu for the status bar item added in 0.3 beta.<br />
* Simplified script installation dialogs.<br />
<br />
Some sort of mad scramble occurred on this week when Firefox 1.5b1 was released and this version was lost but not forgotten.<br />
<br />
== 0.6.2 ==<br />
<br />
September 12th, 2005<br />
[http://greaseblog.blogspot.com/2005/09/firefox-15-compatible-greasemonkey.html]<br />
<br />
Introduced:<br />
* Compatibility with Firefox 1.5.<br />
* The [[Greasemonkey_Manual:Monkey_Menu|Monkey Menu]], a context menu for the status bar item added in 0.3 beta.<br />
* Simplified script installation dialogs.<br />
<br />
== 0.6.4 ==<br />
<br />
November 30th, 2005<br />
[http://greaseblog.blogspot.com/2005/11/greasemonkey-064_30.html]<br />
[http://greasemonkey.mozdev.org/changes/0.6.4.html]<br />
<br />
Introduced:<br />
??<br />
<br />
== 0.6.5 ==<br />
<br />
July 28th, 2006<br />
[http://greasemonkey.mozdev.org/changes/0.6.5.20060727.html]<br />
<br />
Multiple versions released in separate places; largely to the [[Greasemonkey]] [[mailing list]].<br />
Introduced:<br />
* Compatibility with Firefox 2.0.<br />
* Foreign language support for Czech, Dutch, and German.<br />
<br />
== 0.6.6 ==<br />
<br />
October 16th, 2006<br />
[http://greaseblog.blogspot.com/2006/10/greasemonkey-066-firefox-2-support-and.html]<br />
<br />
Introduced:<br />
* Spiffy new installation dialog which more closely resembles the extension installation dialog, and presents more details in a user-friendly way.<br />
* Spanish language support.<br />
<br />
== 0.6.7 ==<br />
<br />
February 7th, 2007<br />
[http://www.greasespot.net/2007/02/greasemonkey-067-minor-ui-tweaks-new.html]<br />
<br />
Introduced:<br />
<br />
* Fixed the manage dialog so that it doesn't bounce around when you select different user scripts (thanks Anthony Lieuallen)<br />
* Added Basque translation (thanks 3ARRANO)<br />
* Updated German translation (thanks Matthias Bauer)<br />
* Middle-click on monkey icon now opens manage dialog, right-click on scripts in monkey menu opens them in an editor (thanks LouCypher and pile0nades)<br />
<br />
== 0.6.8 ==<br />
<br />
March 17th, 2007<br />
[http://www.greasespot.net/2007/03/greasemonkey-068-new-script-ui-now.html]<br />
<br />
Introduced:<br />
<br />
* Rewrite of 'New Script...' UI. It now pops up a nice UI to get the script details and then generates and opens a script which is already installed that you can edit in one step. This is a huge improvement in the usability of this feature. Thanks to Anthony Lieuallen for the implementation.<br />
* Improvements to error reporting. Most types of errors in user scripts now give the correct line number in the error message. You can also click on the filename in Firebug to view the script, as with other types of errors in Firefox. Anthony is also responsible for this improvement.<br />
* Added support for [[GM_xmlhttpRequest#overrideMimeType|overrideMimeType]] to [[GM_xmlhttpRequest]]. Thanks to Lior Zur for the patch. To use, add overrideMimeType: "yourmimetypehere" to the object you pass to GM_xmlhttpRequest.<br />
* New translations for Finnish, Japanese, and Russian. The Greasemonkey UI looks particularly cool in Japanese. Thanks to Tommi Rautava, Hisateru Tanaka, and Александр Соколов for their contributions.<br />
<br />
== 0.6.9 ==<br />
<br />
May 9th, 2007<br />
[http://www.greasespot.net/2007/05/greasemonkey-069-gmscripts-directory.html]<br />
<br />
Introduced:<br />
* You can now reorder the scripts in the manage dialog with drag drop or the arrow keys.<br />
* You can now use Firebug's console object to debug Greasemonkey if you have Firebug installed.<br />
* Fix bug where install dialog would pop up when Greasemonkey is disabled.<br />
* Make Greasemonkey enable/disable keyboard accessible. [http://greasemonkey.devjavu.com/projects/greasemonkey/ticket/9 #9]<br />
<br />
== 0.7.0 ==<br />
<br />
May 24th, 2007<br />
[http://www.greasespot.net/2007/05/greasemonkey-07-candidate.html]<br />
<br />
* Fixed the bug where you can't install scripts if you have never disabled Greasemonkey.<br />
* Fixed the bug where drag and drop in the manage dialog only works once per view.<br />
* Fixed the bug where removing a script in the manage dialog also removes the last script.<br />
<br />
== 0.7.20080121.0 ==<br />
<br />
Jan 21st, 2008<br />
[http://www.greasespot.net/2008/01/greasemonkey-security-update.html]<br />
<br />
* Security release where GM_xmlhttpRequest, GM_getValue and GM_setValue were hardened against a privilege escalation attack targeting specific user scripts accessing anything through unsafeWindow, thus gaining content code unrestricted access to those methods (thanks Anthony Lieuallen).<br />
<br />
This change breaks backwards compatibility for scripts granting page code direct or limited access to either method via function references on unsafeWindow; see [http://wiki.greasespot.net/0.7.20080121.0_compatibility] for available workarounds.</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Talk:CSS_Independent_Content&diff=2119Talk:CSS Independent Content2007-06-15T23:50:45Z<p>Ecmanaut: More input on the data: URL idea, which works great.</p>
<hr />
<div>This might be more suitable in [[Code snippets]]?<br />
:I agree. --[[User:Henrik|Henrik]] 05:47, 5 June 2007 (EDT)<br />
<br />
== sometimes its blank ==<br />
<br />
Hi, I have a problem with this.<br />
It could be that I do something wrong.<br />
However: about 1 out of 5 times the content stays blank.<br />
I tried to change the timeout to 1000.<br />
I tested it 20 times, and it worked all the time.<br />
<br />
Isn't there a "domIsNowCreatedAndYouCanGoAhead" event that we can listen to instead of using setTimeout?<br />
<br />
== How about this instead? ==<br />
It seems it works better<br />
function $(id) {return document.getElementById(id)};<br />
var iframe = document.createElement("iframe");<br />
iframe.setAttribute("id", "settings");<br />
iframe.setAttribute("style", "display:block;z-index:1002;position:fixed;overflow:auto;left:30px;top:30px;right:30px;bottom:30px;background-color:white;padding:15px;border:1px solid black");<br />
iframe.addEventListener('load', showSettings2, false);<br />
function showSettings2() { <br />
$('LIU_settings').contentDocument.body.innerHTML = '<html><body>test</body></html>';<br />
}<br />
<br />
== Data URI ==<br />
<br />
Isn't this a prime time to use a data URI?<br />
<br />
iframe.src = 'data:text/html;charset=utf-8,'+escape('<html><body>...</body><html>');<br />
<br />
Thus avoid all the issues with the DOM rendering and having to wait for load?<br />
<br />
:I don't think so. Just working with the iframe contents as a string would probably get frustrating. The <code>load</code> event happens pretty quickly since we're just waiting for <code>about:blank</code> to load, with no external resources, and once we're there, we can work with that DOM any way we please. Suppose you could mention it in the article as an option, but I don't really see the point. --[[User:Henrik|Henrik]] 04:37, 7 June 2007 (EDT)<br />
<br />
::Actually a rather good idea, IMO, with a few tweaks to the suggestion. The case when it's useful to do node by node creation is when you need to attach event handlers on your own for things, but when you don't, it's a lot easier just writing the markup, rather than coding to the DOM API (even if it was somewhat less bothersome with the tools I quoted in the initial revision). I think this is what you want to do:<br />
<nowiki><br />
iframe.addEventListener("load", function() { ... });<br />
iframe.src = "data:text/html;charset=utf-8,"+(<body><br />
<ul><br />
<li><a href={items[0].url}>{items[0].title}</a></li><br />
<li><a href={items[1].url}>{items[1].title}</a></li><br />
</ul><br />
</body>).toXMLString();<br />
document.body.appendChild(iframe);<br />
</nowiki><br />
::and similar, here assuming the UI is an unordered list with two items, rendered from properties of an "items" array. Constructing more advanced UI:s is of course readily doable by setting up an e4x variable you craft mixing code and e4x literals any way you want prior to serializing the e4x variable to XML for the data URL, and adding event handlers works well by stuffing id:s to the nodes you want and fetching them in the load callback via doc.getElementById. Overall a great suggestion, IMO; feel free to improve this even further.<br />
--[[User:Ecmanaut|Ecmanaut]] 19:50, 15 June 2007 (EDT)</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=CSS_Independent_Content&diff=2096CSS Independent Content2007-06-05T04:23:30Z<p>Ecmanaut: I think the more common use case is a panel that doesn't cover center screen.</p>
<hr />
<div>Any HTML you inject into a site is subject to the CSS rules of that site. This is often what you want: the elements you inject will fit in nicely. But if you inject something – perhaps a configuration panel – that should look the same to pages where styles can vary wildly (e.g. MySpace, eBay) or across multiple sites (e.g. @include *), you may find that you want it exempt from the site CSS.<br />
<br />
The solution is to add your panel inside an iframe. Example code:<br />
<br />
// Position:fixed means stay fixed even the page scrolls. z-index keeps your iframe on top.<br />
// The remainder of the line smacks the panel into the bottom left corner, out of your way.<br />
// Overflow (in combination with the setTimeout) ensures the iframe fits your entire panel.<br />
var css = 'position:fixed; z-index:9999; bottom:0; left:0; border:0; margin:0; padding:0; ' +<br />
'overflow:hidden;'<br />
<br />
var iframe = document.createElement('iframe');<br />
iframe.setAttribute('style', css);<br />
<br />
// The about:blank page becomes a blank(!) canvas to modify<br />
iframe.src = 'about:blank');<br />
<br />
document.body.appendChild(iframe);<br />
<br />
// setTimeout( cb, 0 ) lets Firefox initialize the DOM before we try to use it.<br />
setTimeout( function() {<br />
<br />
var doc = iframe.contentDocument;<br />
doc.body.style.background = 'red';<br />
doc.body.innerHTML = 'Test.';<br />
iframe.style.height = doc.body.offsetHeight + "px";<br />
iframe.style.width = doc.body.offsetWidth + "px";<br />
<br />
}, 0 );<br />
<br />
A variant on a more intrusive interface (perhaps invoked from a menu item) might be a lightbox style panel, mid-screen. Just drop the last two iframe.style lines and change the CSS to:<br />
<br />
// Margin, top, left, width and height centers the iframe horizontally and vertically:<br />
var css = 'position:fixed; z-index:9999; border:1px solid black; ' +<br />
'top:50%; left:50%; width:30em; margin:-15em; 0 0 -10em; height:20em;';</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=CSS_Independent_Content&diff=2091CSS Independent Content2007-06-03T01:22:45Z<p>Ecmanaut: </p>
<hr />
<div>If you have ever tried appending some neat HTML user interface to web pages with a script set to run on not just one site, but perhaps anywhere (a button that invokes some feature in your script, perhaps), after using it some time, you will probably have noticed that it doesn't look the same way everywhere. This is because the CSS rules of the page author's apply to your interface HTML too, overriding the default CSS rules (there are dozens of CSS rules, all of which may be overridden for every single tag you add).<br />
<br />
One solution: do your stugg in an iframes; sketchy code example:<br />
<br />
function tag( name, attr ) {<br />
var node = doc.createElement( name );<br />
attr = attr || {};<br />
for( var i in attr )<br />
node.setAttribute( i, attr[i] );<br />
return node;<br />
}<br />
<br />
var css = "opacity:0.95; position:fixed; left:0; bottom:0; border:0; " +<br />
"margin:0; padding:0; overflowY:auto; overflowX:hidden";<br />
<br />
var doc = document;<br />
var iframe = tag( "iframe", { style:css, src:"about:blank" } );<br />
doc.body.appendChild( iframe );<br />
var win = unsafeWindow.frames[unsafeWindow.frames.length-1];<br />
doc = win.document;<br />
/* add things to doc.body */<br />
iframe.style.height = (16 + doc.body.offsetHeight) + "px";<br />
iframe.style.width = (16 + doc.body.offsetWidth) + "px";</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Main_Page&diff=2090Main Page2007-06-02T21:01:33Z<p>Ecmanaut: /* Authoring Tips */</p>
<hr />
<div>__NOTOC__<br />
'''GreaseSpot''' is community documentation for [[user script]]ing with [[Greasemonkey]]. Please [[GreaseSpot:Editor portal|contribute]].<br />
<br />
== Getting Started ==<br />
<br />
* [[Greasemonkey Manual]]<br />
* [[Tutorials]]<br />
* [[Mailing list]]<br />
<br />
== Scripting References ==<br />
<br />
* [[API reference]]<br />
* [[Metadata block]]<br />
* [[:Category:Scripting context|Scripting context]]<br />
** [[Sandbox]]<br />
** [[Global object]]<br />
** [[XPCNativeWrapper]]<br />
** [[Scriptable content]]<br />
** [[DOMContentLoaded]]<br />
* [[Security]]<br />
** [[unsafeWindow]]<br />
<br />
== Authoring Tips ==<br />
* [[Useful Tools for Script Writers]]<br />
* [[Troubleshooting]]<br />
* [[Code snippets]]: useful staple functions.<br />
* [[Coding tips]]: things you might not have thought of.<br />
* [[HTML injection tips]]: how to add your html anywhere, dodging page CSS invading yours<br />
* [[:Category:Site-specific tips|Site-specific tips]]<br />
** [[:Category:Ajax site tips|Ajax site tips]]<br />
* [[Security tips]]<br />
* [[Etiquette]]<br />
* [[Cross-browser userscripting]]<br />
<br />
== Extension Development ==<br />
<br />
* [[Contributing to Greasemonkey]]<br />
<br />
== Also ==<br />
<br />
* [[FAQ]]<br />
* [[Links]]</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Troubleshooting_(Script_Authors)&diff=1792Troubleshooting (Script Authors)2007-03-28T07:05:53Z<p>Ecmanaut: Added a link to a good, thorough intro on lexical closures, argument binding and so on.</p>
<hr />
<div>The article [http://www.oreillynet.com/pub/a/network/2005/11/01/avoid-common-greasemonkey-pitfalls.html Avoid Common Pitfalls in Greasemonkey] covers some of the most common problems people come across when writing [[user script]]s.<br />
<br />
If your problem is not listed, please ask on the [[mailing list]].<br />
<br />
__TOC__<br />
<br />
= When using GM_xmlhttpRequest or setTimeout, variables change before the callback runs =<br />
<br />
Problem example:<br />
<br />
for (var i=0; i < document.links.length; i++) {<br />
var link = document.links[i];<br />
<br />
GM_xmlhttpRequest({<br />
method: "GET",<br />
url: 'http://example.com/lookup?url=' + link.href,<br />
onload: function(result) {<br />
link.href = result.responseText;<br />
}<br />
});<br />
}<br />
<br />
The request is asynchronous, meaning the rest of the code doesn't wait for it to complete. The <code>for</code> keeps running as the request loads. When the request for the first link on the page completes and the <code>onload</code> callback function runs, the <code>link</code> variable might point to a different link altogether, typically the last one (since the <code>for</code> loop completes much quicker than the HTTP requests).<br />
<br />
One solution is to pass those values that you want unchanged into a function surrounding the request, as arguments. Then they will be in a different scope, and will no longer be changed from the outside.<br />
<br />
Solution example with named function:<br />
<br />
function do_it(link_inside) {<br />
GM_xmlhttpRequest({<br />
method: "GET",<br />
url: 'http://example.com/lookup?url=' + link.href,<br />
onload: function(result) {<br />
link_inside.href = result.responseText;<br />
}<br />
});<br />
}<br />
<br />
for (var i=0; i < document.links.length; i++) {<br />
var link = document.links[i];<br />
<br />
do_it(link);<br />
}<br />
<br />
Solution example with anonymous function:<br />
<br />
for (var i=0; i < document.links.length; i++) {<br />
var link = document.links[i];<br />
<br />
(function (link_inside) {<br />
<br />
GM_xmlhttpRequest({<br />
method: "GET",<br />
url: 'http://example.com/lookup?url=' + link.href,<br />
onload: function(result) {<br />
link_inside.href = result.responseText;<br />
}<br />
});<br />
<br />
})(link);<br />
}<br />
<br />
= Links =<br />
<br />
* http://greaseblog.blogspot.com/2005/12/troubleshooting-064.html<br />
* http://dunck.us/collab/GreaseMonkeyUserScripts#head-010b85ad56b34c34c7c2a3b2436c740e30428ed5<br />
* http://dunck.us/collab/GreaseMonkeyUserScripts#head-4ac4d1e80f8bbd66bf4f1fbea77ea2390b6a2870<br />
* http://www.brockman.se/writing/method-references.html.utf8<br />
<br />
{{stub}}</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Talk:Include_and_exclude_rules&diff=1669Talk:Include and exclude rules2006-12-16T14:39:25Z<p>Ecmanaut: /* Pseudo-code */</p>
<hr />
<div>== Pseudo-code ==<br />
<br />
It's huge and unhelpful. +1 for removal. Replace with a link to the list of TLDs and mention that two-level "TLDs" are included. --[[User:Ldrhcp|Ldrhcp]] 23:09, 14 December 2006 (EST)<br />
<br />
----<br />
<br />
+1 for removing pseudocode section.<br />
possible, direct link: http://www.mozdev.org/source/browse/greasemonkey/src/chrome/chromeFiles/content/convert2RegExp.js?rev=1.5&content-type=text/x-cvsweb-markup<br />
[[User:Arantius|Arantius]] 10:33, 15 December 2006 (EST)<br />
<br />
----<br />
<br />
Agreed; +1 for pseudocode removal. (I added the two-level mention already; not much use discussing something small like that.) --[[User:Ecmanaut|Ecmanaut]] 09:38, 16 December 2006 (EST)</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Talk:Include_and_exclude_rules&diff=1668Talk:Include and exclude rules2006-12-16T14:38:46Z<p>Ecmanaut: </p>
<hr />
<div>== Pseudo-code ==<br />
<br />
It's huge and unhelpful. +1 for removal. Replace with a link to the list of TLDs and mention that two-level "TLDs" are included. --[[User:Ldrhcp|Ldrhcp]] 23:09, 14 December 2006 (EST)<br />
<br />
----<br />
<br />
+1 for removing pseudocode section.<br />
possible, direct link: http://www.mozdev.org/source/browse/greasemonkey/src/chrome/chromeFiles/content/convert2RegExp.js?rev=1.5&content-type=text/x-cvsweb-markup<br />
[[User:Arantius|Arantius]] 10:33, 15 December 2006 (EST)<br />
<br />
Agreed; +1 for pseudocode removal. (I added the two-level mention already; not much use discussing something small like that.)<br />
--[[User:Ecmanaut|Ecmanaut]] 09:38, 16 December 2006 (EST)</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Talk:Include_and_exclude_rules&diff=1667Talk:Include and exclude rules2006-12-16T14:36:54Z<p>Ecmanaut: /* Pseudo-code */</p>
<hr />
<div>== Pseudo-code ==<br />
<br />
It's huge and unhelpful. +1 for removal. Replace with a link to the list of TLDs and mention that two-level "TLDs" are included. --[[User:Ldrhcp|Ldrhcp]] 23:09, 14 December 2006 (EST)<br />
<br />
----<br />
<br />
+1 for removing pseudocode section.<br />
possible, direct link: http://www.mozdev.org/source/browse/greasemonkey/src/chrome/chromeFiles/content/convert2RegExp.js?rev=1.5&content-type=text/x-cvsweb-markup<br />
[[User:Arantius|Arantius]] 10:33, 15 December 2006 (EST)</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Talk:Include_and_exclude_rules&diff=1666Talk:Include and exclude rules2006-12-16T14:36:35Z<p>Ecmanaut: </p>
<hr />
<div>== Pseudo-code ==<br />
<br />
It's huge and unhelpful. +1 for removal. Replace with a link to the list of TLDs and mention that two-level "TLDs" are included. --[[User:Ldrhcp|Ldrhcp]] 23:09, 14 December 2006 (EST)<br />
<br />
----<br />
<br />
+1 for removing pseudocode section.<br />
possible, direct link: http://www.mozdev.org/source/browse/greasemonkey/src/chrome/chromeFiles/content/convert2RegExp.js?rev=1.5&content-type=text/x-cvsweb-markup<br />
[[User:Arantius|Arantius]] 10:33, 15 December 2006 (EST)<br />
<br />
----<br />
<br />
Agreed; +1 for pseudocode removal. (I added the two-level mention already; not much use discussing something small like that.)<br />
<br />
Agreed; +1 for pseudocode removal. (I added the two-level mention already; not much use discussing something small like that.)</div>Ecmanauthttps://wiki.greasespot.net/index.php?title=Talk:Include_and_exclude_rules&diff=1665Talk:Include and exclude rules2006-12-16T14:35:51Z<p>Ecmanaut: /* Pseudo-code */</p>
<hr />
<div>== Pseudo-code ==<br />
<br />
It's huge and unhelpful. +1 for removal. Replace with a link to the list of TLDs and mention that two-level "TLDs" are included. --[[User:Ldrhcp|Ldrhcp]] 23:09, 14 December 2006 (EST)<br />
<br />
----<br />
<br />
+1 for removing pseudocode section.<br />
possible, direct link: http://www.mozdev.org/source/browse/greasemonkey/src/chrome/chromeFiles/content/convert2RegExp.js?rev=1.5&content-type=text/x-cvsweb-markup<br />
[[User:Arantius|Arantius]] 10:33, 15 December 2006 (EST)<br />
<br />
----<br />
<br />
Agreed; +1 for pseudocode removal. (I added the two-level mention already; not much use discussing something small like that.)</div>Ecmanaut