Share 'Selector API' on Delicious Share 'Selector API' on Facebook Share 'Selector API' on Google Bookmarks Share 'Selector API' on Twitter

  1. Select example
  2. Selecting components
  3. Single selectors
    1. Component selector
    2. ID selector
    3. Class selector
    4. State selector
  4. Descendant selectors
    1. Child combinator ">"
    2. Descendant selector example
  5. Style specifities priorities
    1. Style specifity
    2. Style priorities
  6. Leave a Comment

Selector API

JCSS allows you to specify complex style rules in order to address your styles in style sheets and style declarations. This reference briefly describes all the basics and possibilities to build selectors in JCSS.

Select example

SelectorTest.swf

Click the checkbox in the top left corner of each box to activate.

Selecting components

In JCSS you always have to declare a style to the component that defines the style. For example, if you want to set a custom label color, you need to specify a selector that matchs the label for that the color should apply.

If we know the label, we simply write:

1
myLabel.setStyle("This", "color", "blue");

In the most cases we don’t know and we don’t want to know the actual label instance.

1
2
3
4
5
6
7
8
9
10
11
jcss.setStyleSheet(<styles><![CDATA[
  Label {
    color: blue;
  }
]]></styles>);

myLabelAncestor.setStyleSheet(<styles><![CDATA[
  Label {
    color: blue;
  }
]]></styles>);

or

1
2
3
jcss.setStyle("Label", "color", "blue");

myLabelAncestor.setStyle("Label", "color", "blue");

The “This” selector

Selectors work relative to the component to that we add a style rule. To set a style for the current instance directly, we use the “This” selector.

1
2
3
4
5
component.setStyle("This", "styleName", "styleValue");
component.setStyle("", "styleName", "styleValue"); // both equal

component.setStyle("This:over", "styleName", "styleValue");
component.setStyle(":over", "styleName", "styleValue"); // both equal

A selector is either a single selector or a combination of single selectors (descendant or complex selector).

Single selectors

A single selector consists at least of a component selector and may optional have ID, class or state refinements.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Label {
  size: 14;
  color: red;
}

Label#title {
  size: 20;
  bold: true;
}

Label.small {
  size: 12;
}

Label#title.small {
  size: 16;
}

Label:over {
  color: brighter;
}

Label:over:down {
  underline: true;
}

Label#title.small:over:down {
  underline: false;
}

Component selector

Also called the component name. A component selector must at least include the component name. The component name can not be changed at runtime.

1
2
3
jcssAdapter.cssName = "Box";
...
jcss.setStyle("Box", "styleName", "styleValue");

ID selector

If a container has multiple children of the same component type and if these children have a different semantic, the container may assign specific ID attributes to enable them to be styled separately. The ID attribute of a component can not be changed at runtime. It is possible to give different components the same ID.

1
2
3
jcssAdapter.cssID = "boxID";
...
jcss.setStyle("Box#boxID", "styleName", "styleValue");

Class selector

Sometimes we need a subset of the occurence of a component to be styled differently. In this case we may assign these components a value for the class attribute. This attribute may be changed at runtime. In such a case JCSS performs an automatic style update of all related view elements (e.g. depending children).

1
2
3
jcssAdapter.cssClass = "boxClass";
...
jcss.setStyle("Box#boxClass", "styleName", "styleValue");

State selector

States are a very powerful feature. States reduce code and enable components to be really independent. States can be set to a component at any time. JCSS internally manages the state of all components for that a stateful style rule has been declared.

1
2
3
jcssAdapter.setState("state", "value");
...
jcss.setStyle("Box:state=value", "styleName", "styleValue");

If the state value is a boolean value you may use the shorter variant:

1
2
3
4
5
6
7
jcssAdapter.setState("over", "true");
jcss.setStyle("Box:over=true", "styleName", "styleValue");
jcss.setStyle("Box:over", "styleName", "styleValue"); // both equal

jcssAdapter.setState("over", "false");
jcss.setStyle("Box:over=false", "styleName", "styleValue");
jcss.setStyle("Box:!over", "styleName", "styleValue"); // both equal

There can be multiple states for a single selector.

1
2
3
4
5
jcssAdapter.setState("over", "true");
jcssAdapter.setState("down", "true");
jcssAdapter.setState("active", "true");
jcss.setStyle("Box:over=true:down=true:active=true", "styleName", "styleValue");
jcss.setStyle("Box:over:down:active", "styleName", "styleValue"); // both equal

Descendant selectors

Descendant selectors can be used without restrictions to achieve a more specific component selection.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Label {
  color: red;
}

Button Label {
  color: red;
}

Alert Button Label {
  color: red;
}

Alert Button#cancel Label {
  color: red;
}

Alert.error Button#cancel Label {
  color: red;
}

Child combinator “>”

There are situations, when we have nested instances of the same component. These may be boxes, panels or any other container. Using the child combinator we can restrict styles to be applied only to direct children of a specified component. To apply styles only to the first box of a box hierarchy, we write:

1
> Box

Note, the child combinator matchs descendants of the declarator even if they are later children.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Selector: A > D

Display list:
A
  B
    D#1
      C
        D#2
Selector matchs D#1

Display list:
A
  D#1
    B
      C
        D#2
Selector matchs D#1

Display list:
A
  D#1
  B
    C
      D#2
Selector matchs D1 and D2

Descendant selector example

StyleEditor.swf

The example above lets you add or update style rules at runtime. Use the select boxes as typing shortcuts. You may combine ID and class as well as multiple states. Box#1.a:over:down is a valid selector.

Style specifities priorities

What happens if different style rules declare a value for the same style property?

1
2
3
jcss.setStyle("Box", "borderSize", "4");
boxAncestor.setStyle("Box", "borderSize", "4");
box.setStyle("This", "borderSize", "4");

JCSS calculates the style precedence in two steps:

  • Calculation of the style specifity
  • Evaluating the style priority

Style specifity

The specifiy of a style results from its selector specifity and the time the style has been added or modified.

Selector specifity

The concept of selector specifities is known from CSS. Here the value table:

Entity Example Weight
Component selector Label, Button 1
State :o ver, :down 10
Class attribute .small, .red 100
ID attribute #top, #cancel 1000
Declarator depth 0, 1, 2 10000

The selector specifity is then calculated:

1
2
3
4
5
6
7
selectorSpecifity = (
  numComponentSelectors
  + numStates * 10
  + numClassAttributes * 100
  + numIDAttributes * 1000
  + declaratorDepth * 10000;
);

Declarator depth

The depth of the global style manager is defined with zero. A component without any ancestor that is registered in JCSS gets the depth 1. The depth of any other component is their ancestor depth + 1.

Specifity examples

Display list: A B C

Global style rules (depth 0):
Box // 1
Box Box // 2
Box:over // 11
Box#comments:over Label // 1012
Box.big Label // 102

Style rules declared in A (depth 1):
Box // 10001
Box Box // 10002
Box:over // 10011
Box#comments:over Label // 11012
Box.big Label // 10102

Style rules declared in C (depth 3):
Box // 30001
Box Box // 30002
Box:over // 30011
Box#comments:over Label // 31012
Box.big Label // 30102

Style timestamp

Whenever a style has been declared or an already present style has been updated, a timestamp is stored to that style. This enables to weight different styles even if their selector specifities equal. In that case, later modified styles become a higher specifity.

box.setStyle("Label:over", "color", "blue"); // timestamp 123
box.setStyle("Label:active", "color", "red"); // timestamp 124 - higher specifity

In the example above, if the mouse enters an active label, the label will remain red (:active wins). Both selectors have the same specifity, but second rule was later added.

Style priorities

Nevertheless, there are ways to override styles set in descendant components. Style priorities can be engaged to dupe the specifity system. There are 3 priorities to be used in any style declaration.

  • JCSS.PRIORITY_DEFAULT
    Ancestor or global style rules may override this style.
  • JCSS.PRIORITY_FIX
    Ancestor or global style rules can override this style only with an important style.
  • JCSS.PRIORITY_IMPORTANT
    Ancestor or global style rules must not override this style. This priority can be used to
    seal or finalize styles.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jcss.setStyleSheet(<styles><![CDATA[
  Label {
    color: blue default;
    size: 16 !important;
    font: Arial; /* default is fix */
  }
]]></styles>);

myLabelAncestor.setStyleSheet(<styles><![CDATA[
  Label {
    color: blue default;
    size: 16 !important
    font: Arial; /* default is fix */
  }
]]></styles>);

or

1
2
3
4
5
6
7
8
9
jcss.setStyle("Label", "color", "blue", JCSS.PRIORITY_DEFAULT);
jcss.setStyle("Label", "size", 16 , JCSS.PRIORITY_IMPORTANT);
jcss.setStyle("Label", "font", "Arial", JCSS.PRIORITY_FIX);
jcss.setStyle("Label", "font", "Arial"); // Fix by default

myLabelAncestor.setStyle("Label", "color", "blue", JCSS.PRIORITY_DEFAULT);
myLabelAncestor.setStyle("Label", "size", 16 , JCSS.PRIORITY_DEFAULT);
myLabelAncestor.setStyle("Label", "font", "Arial", JCSS.PRIORITY_DEFAULT);
myLabelAncestor.setStyle("Label", "font", "Arial"); // Fix by default


Leave a Comment

You have a question or have experienced an issue? Please post it in the forum: http://sibirjak.tenderapp.com/ in order to make the discussion available at a more central place.