Page 1 of 1

Greasemonkey, XPath, Setting Element Properties in a Loop

Posted: Tue Jun 30, 2009 11:08 am
by McInfo
I am working on a Greasemonkey script to act as a temporary fix for the Expand/Contract links on this forum. For details on this issue, read this post.

The script is able to find all of the codeholder divs and iterate through them with a while loop. However, if I try to set any of the div properties such as style.maxHeight or innerHTML, the loop breaks after the property is set for the first div. My attempts at setting the div properties have been commented out.

Code: Select all

// ==UserScript==
// @name             Debugging DevNetwork.net Expand Code Link Fix
// @namespace        https://snydev.com/greasemonkey/
// @description      Fixes a bug on devnetwork.net forum related to the Expand/Contract links
// @include          http://forums.devnetwork.net/viewtopic.php*
// ==/UserScript==
 
var codeHolders = document.evaluate("//div[@class='codeholder']", document, null, XPathResult.ANY_TYPE, null);
var ch = codeHolders.iterateNext();
var i = 0;
while (ch) {
    i++;
    //ch.style.maxHeight = '600px';
    //ch.style.cssText = 'max-height: 600px';
    //ch.style.setProperty('max-height', '600px' , 'important');
    //ch.innerHTML = '';
    window.alert('Count: ' + i + "\n" +
                 'ch.style.cssText: ' + ch.style.cssText + "\n" +
                 'ch.style.maxHeight: ' + ch.style.maxHeight);
    ch = codeHolders.iterateNext();
}
I cannot find the max-height property of the codeholder div in document.styeSheets[0].cssRules because it is an inline style, so I assume I must access it through the element. Does anyone have any ideas about how to do this?

Two code blocks are required to debug this, so here is a second dummy code block.

Code: Select all

A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
Edit: This post was recovered from search engine cache.

Re: Greasemonkey, XPath, Setting Element Properties in a Loop

Posted: Tue Jun 30, 2009 2:49 pm
by Weirdan
I'd suggest using specific return type instead of XPathResult.ANY_TYPE. You need any of SNAPSHOT types (https://developer.mozilla.org/en/DOM/do ... #section_5), since you want to both iterate over the collection and change nodes, belonging to it. Then again, you need to remember that what you're getting are not real dom nodes, but nodes wrapped in XPCNativeWrappers, which means that method access on them is allowed (you may call their methods and it leads to methods being called on actual nodes) but you can't set their properties (you can, but property changes won't be forwarded to real nodes).

To summarize, you'd better use node methods rather than node properties (e.g. aNode.setAttribute('style', 'display:none') vs. aNode.style.display = 'none';). And of course you can't change nodes when iterating over ITERATOR resultset (you need SNAPSHOT resultset for this).

Re: Greasemonkey, XPath, Setting Element Properties in a Loo

Posted: Tue Jun 30, 2009 6:01 pm
by McInfo
Thanks for pointing me in the right direction. After a little digging, I came up with something that works.

Code: Select all

// ==UserScript==
// @name             Debugging DevNetwork.net Expand Code Link Fix
// @namespace        https://snydev.com/greasemonkey/
// @description      Fixes a bug on devnetwork.net forum related to the Expand/Contract links
// @include          http://forums.devnetwork.net/viewtopic.php*
// ==/UserScript==
 
var codeHolders = document.evaluate("//div[@class='codeholder']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var ch = null;
var i = 0;
while (ch = codeHolders.snapshotItem(i)) {
    ch.setAttribute('style', 'max-height: 600px');
    i++;
}
Do you have any thoughts on how to set the max-height style without affecting other inline styles that an element might have? I thought about using getAttribute and performing a string replacement, but maybe there is a cleaner way.

Edit: This post was recovered from search engine cache.