Closed Bug 112854 Opened 24 years ago Closed 23 years ago

Empty styles not included in cssRules[]

Categories

(Core :: DOM: CSS Object Model, defect)

x86
All
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla1.0

People

(Reporter: robert, Assigned: bzbarsky)

References

Details

(Whiteboard: [DIGBug][eapp])

Attachments

(1 file)

From Bugzilla Helper: User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.5) Gecko/20011011 BuildID: 2001101117 The cssRules collection will not does not contain CSS rules that don't have any properties specified. See the attached test case for an example of this - It illustrates how the empty '.style2' rule is not included. Reproducible: Always Steps to Reproduce: 1. See attached test case
*sigh* The attachment page in bugzilla isn't working for me, so here's the html source of the test: ================ SNIP =============== <html> <head> <style type="text/css"> <!-- .style1 { color:red; } .style2 { } .style3 { color:blue; } --> </style> </head> <body bgcolor="#FFFFFF"> <div class=style1> Some text written in style 1 <span style="text-decoration:underline" onclick="boldify('.style1')">(make this class bold!)<span> </div> <div class=style2> Some text written in style 2 <span style="text-decoration:underline" onclick="boldify('.style2')">(make this class bold!)<span> </div> <div class=style3> Some text written in style 3 <span style="text-decoration:underline" onclick="boldify('.style3')">(make this class bold!)<span> </div> <script> // Do a quick pass of the style sheets to see what styles we find for (var i=0; i < document.styleSheets.length; i++) { var myRules = document.styleSheets[i].cssRules; for (var j=0; j < myRules.length; j++) { var myRule = myRules[j]; document.write('Found rule with selector, "' + myRules[j].selectorText + '"<br>'); } } </script> <script> /** * Find the selector for a style and make it bold */ function boldify(aSelector) { var myStyle = findStyle(aSelector); if (myStyle) { } else { alert('Hey, can\'t find style for "' + aSelector + '"'); } myStyle.fontWeight = 'bold'; } /** * General method for finding a style by selector in a document */ function findStyle(aSelector, aDocument) { aDocument = aDocument ? aDocument : document; for (var i=0; i < aDocument.styleSheets.length; i++) { var myRules = aDocument.styleSheets[i].cssRules; for (var j=0; j < myRules.length; j++) { var myRule = myRules[j]; if (myRule.selectorText == aSelector) return myRule.style; } } return null; } </script> </body> </html> ================ SNIP ===============
That's because we don't bother creating css rule objects for rules that will have no effect.... Those rules are just no present in our internal stylesheet representation.
Status: UNCONFIRMED → NEW
Ever confirmed: true
OS: Windows 2000 → All
Unfortunately, this means I can't assign an element a CSS class and then assign style properties to it dynamically. I *have* to assign stuff to it in the CSS sheet, which I really don't want to do... especially if I want it to inherit all of it's CSS styles by default. You can workaround this by finding some CSS property that isn't used and setting that in the style sheet, but what "isn't used" changes from one application to another. You end up having to figure this out each time based on what the style is applied to and what properties you'll want to set. Yuck! Anyhow, that's my $.02 on this.
For performance, you're better off swapping classes in and out on the element and leaving the rules in the stylesheet static. Probably we could fix this if we start to make our DOM CSS object more wrappers than direct access to our internal structures, which we'll have to do when we restructure things.
I think you're overlooking the fact that the whole point of having a CSS rule is that can apply it to more than 1 element. Otherwise you just set the style for the element itself. Trying to find all the elements you need to change the class name on seems much less efficient then modifying the stylesheet rule. For example, imagine a form with optional and required fields where the user can click a button to hide the optional fields. The easiest way to do this would be to assign optional fields the "optionalFieldStyle" and then set the 'display' property to 'none' on this rule in the style sheet. The real-world case that I'm trying to solve is even more extreme. I have a log of messages (100's of them) that my script is generating. Each message is displayed in a span with the class set according to the severity of the message (info/warning/error). I want to conditionally display/hide messages based on their severity.
True, true. The CSSOM is just such a mess and a pain to implement that I try to advocate avoiding it.
Future.
Target Milestone: --- → Future
jst: how big a pain is this to fix? kieffer: for the example you quote, can you work around the issue by giving the rule some property which will make the rule appear in cssRules[]? e.g. .msg { display: inline; } ?
Whiteboard: [DIGBug][eapp]
bz: Do you have an answer for Bob's question above? I can't really tell w/o digging into the CSS internals...
> how big a pain is this to fix? I _think_ this may be fixable by just changing the following code in ParseDeclarationBlock in the CSS Parser: if (dropDeclaration || (0 == count)) { // didn't get any XXX is this ok with the DOM? if (nsnull != declaration) { declaration->RuleAbort(); declaration = nsnull; } } The thing to do would be to remove the |0 == count| part (and of course the comment). David? What do you think?
It seems like it should just work, although we might want to double-check that the index / bits stuff still works.
Major corporations depend on eapp bugs, and need them to be fixed before they can recommend Mozilla-based products to their customers. Adding nsbeta1+ keyword and making sure the bugs get re-evaluated if they are targeted beyond 1.0.
Keywords: nsbeta1+
Target Milestone: Future → ---
eapp was incorrectly used to change this to nsbeta1+. Resetting to nsbeta1 to nominate. This is an important issue and deserves to be nsbeta1+ by the ADT.
Keywords: nsbeta1+nsbeta1
I've been playing around with this some more and found a better workaround. A style object can be created programatically using the sheet.insertRule() method. So, as long as you have a <STYLE> block in your document, you can add blank rules to it. E.g: window.mySheet = document.getElementsByTagName('style')[0].sheet; mySheet.insertRule('.foobar {background-color:red}', 0); Given that this is not too painful a workaround, the priority of this bug might be lowered.
Comment on attachment 69894 [details] [diff] [review] Patch. Tested this for a bit and everything seems to be working correctly... r=dbaron
Attachment #69894 - Flags: review+
Comment on attachment 69894 [details] [diff] [review] Patch. Tested this for a bit and everything seems to be working correctly... sr=attinasi
Attachment #69894 - Flags: superreview+
Since Boris made the fix he can have the glory. Reassigning and setting milestone to 1.0 (shouldn't be a problem I hope, since there is a fix). Boris, if you haven't done so already could you ask for drivers' approval?
Assignee: jst → bzbarsky
Keywords: mozilla1.0
Target Milestone: --- → mozilla1.0
Oops. I checked this in a month ago... :) nsCSSParser.cpp revision 3.174 date: 2002/02/19 02:27:38; author: bzbarsky%mit.edu; state: Exp; lines: +1 -2 Leave rules with empty decl blocks in the sheet so they're picked up by the DOM. Bug 112854, r=dbaron, sr=attinasi
Status: NEW → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: