More Frontal Style Sheets
From Frontal Wiki
Contents |
Ordering of Selectors
Note that the order of the selectors is important. We presented this example earlier:
<style><![CDATA[ text:focus { color: green; } text:hover { color: red; } text:active { color: blue; } ]]></style> <text style="tab-enabled: true;">click me 1</text> <text style="tab-enabled: true;">click me 2</text>
Try this code in the Workspace, noting that when you press and hold the mouse button down over one of the text lines, the text turns blue. This is because of the selector: "text:active".
Now switch the order of the lines "text:hover { color: red; }" and "text:active { color: blue; }" and try the result in the Workspace. Note that now the text does not turn blue when pressed. This is because selectors are weighted and then applied in the order of their weights -- light to heavy. In this case, after switching the selectors, the order causes the "text:active" selector to be applied before the "text:hover" selector. The reason for this is that while the element is active, it's also in the hover state. So both selectors match, which means that the order of application determines which one's styles will win out. In this case, it means the text stays red.
The weight of a selector is determined by its "specificity". Here are the gory details:
- Count the number of ID selectors in the selector and call this A.
- Count the number of class selectors, attribute selectors, and pseudo-class selectors (except for :not()) in the selector and call this B.
- Count the number of element selectors and call this C.
Now concatenate these numbers together (don't add them). This becomes the selector's specificity or, weight. The higher the specificity of a selector, the more likely its styles will be applied. For example, what color will the text be?
<style><![CDATA[ #myText { color: blue; } text { color: green; } ]]></style> <text id="myText">What color will I be?</text>
The specificity of the first selector is 100 (A=1 because there's an ID selector, B and C are both 0). The specificity of the second selector is 1 (C=1 because there's one element selector and A and B are both zero). So in this case the text will be blue because that selector has the higher specificity. If we changed that second selector to "text#myText", however, then it would be applied (its specificity would be 101) and the text would be green.
Taking Action when Selectors Match
Looking back a few sections to our general rule set, we see a few other possible declaration entries: +onMatch, +onMismatch and +rulesetId. These are unique to Frontal and allow us to run a script whenever a document element is matched by a rule set (via +onMatch), or becomes mismatched by a rule set (via +onMismatch). Here's an example of how we could use the onMatch to set the color of each div element randomly, instead of to green:
<style><![CDATA[ div { background-shape: ellipse; width: 25%; height: 25%; float: left; @onClick { sS ( 'background-color', Math.floor ( 0xffffff * Math.random ( ) ) ); document.write ( "<div />"); } +onMatch { sS ( 'background-color', Math.floor ( 0xffffff * Math.random ( ) ) ); } } ]]></style> <div /><div /><div /><div />
+rulesetId allows us to give a rule set an identifier so that we can find it easily with a script and manipulate it. This can come in handy if we want to manipulate a rule set via a script.
To find the selectors associated with a rulesetId, we use the function "document.stylesManager.getStylesheetSelectors( )", passing it the rulesetId of interest. What's returned is an array of style sheet selectors. (This is an array because as we've seen before, any number of selectors may be part of a single rule set.) With a style sheet selector, we may manipulate its attribute and style declarations. We'll see more details of this when discussing the Frontal object model, but for now we leave the reader with this example:
<style><![CDATA[ text#myText { +rulesetId: myTextRuleset color: blue; } text#myButton { @onClick { var selector = document.stylesManager.getStylesheetSelectors ( "myTextRuleset" ) [ 0 ]; selector.attributes.styles.setStyle ( "color", Math.floor ( 0xffffff * Math.random ( ) ) ); selector.attributes.styles.dispatchEvent ( new com.frontalcode.FrontalEvent ( com.frontalcode.FrontalEvent.CHANGE ) ); } } ]]></style> <text id="myText">Hello, world!</text> <text id="myButton">click me</text>
The final call to dispatchEvent tells those elements that are dependent on this rule set to reapply its declarations.
Sending Signals to Elements that Match a Selector
It can also be handy to broadcast a message to all of the elements that match a particular selector, and then have each of those elements act on that message. Here's an example of a button that sends a notification to the div elements with the style class "target", along with the value they should use for their background.
<style><![CDATA[ div { width: 20px; height: 20px; background-color: white; } div.target { +rulesetId: divTarget background-color: blue; @onSelectorNotification { sS ( "background-color", event.details.color ); } } text#myButton { @onClick { var selector = document.stylesManager.getStylesheetSelectors ( "divTarget" ) [ 0 ]; selector.dispatchEvent ( new com.frontalcode.FrontalEvent ( com.frontalcode.FrontalEvent.NOTIFICATION, { color: Math.floor ( 0xffffff * Math.random ( ) ) } ) ); } } ]]></style> <text id="myButton">click me</text> <div class="target" /><div /><div class="target" /><div /><div class="target" />
In this example, we again use the rulesetId to identify the selector we're interested in. Then we dispatch a Frontal event with the NOTIFICATION type from it. With this event, we're including the color that we want the matching elements to use for their background. The result of dispatching the event is that the onSelectorNotification interaction is run on each of the elements that match the selector, and in their scope, they can find the color sent with the notification at event.details.color.
Learn More about Styles
You can learn more about styles in Styles Reference.