CSSS! is an extension of classic CSS (Cascading Style Sheets) by the scripting to give it the ability to define some basic behavioral styles of elements.
CSSS! script can appear in a) attributes with names ending with '!' (exclamation) mark and b) inside the calc()
function.
Here is list of active CSS attributes supported by h-smile core engine intrinsically.
Example, implementation of <label for="id">
functionality but for any element that has attribute for="id"
defined:
[for] { hover-on! : $1(#< self.for >):hover = true; hover-off! : $1(#< self.for >):hover = false; active-on! : $1(#< self.for >):focus = true; cursor:pointer; } input:hover { outline: 4px glow blue 1px; }
Rules hover-on
and hover-off
are causing bound element of this label to get :hover state. Therefore mouse hover on the label is the same as hovering bound element itself. The rule active-on!:
does the magic - it sets focus on the bound element.
For the meaning of $1(...)
see chapter Selector pseudo-functions below.
CSSS! is used as embedded in host CSS syntax and grammar. This limits list of symbols/construction that can by used by the CSSS!. CSSS! is not using symbols: ';'
, '{'
and '}'
in its notation. To be precise symbol ';' is used as an end of script statement ending script text.
Identifiers (nmtokens) start with a alphabetic character, '-', '_' or '$' followed by any number of alphabetic characters, '-', '_', '$' or digits ([0-9]). Note the symbol '-' here, as in CSS syntax it is allowed to be a part of the name. To solve conflicts with sign '-' as an operator minus always enclose it by spaces.
nmtoken -> [a-zA-Z_\-$]+[a-zA-Z_\-$0-9]*
CSSS! has following keywords:
true false null self
< > <= == != >= && || + - * / % ^ | &
[tbd]
Operators that will be supported in next versions:
~= ~/ ~% %~ /~
Ternary operator:
<condition> ? <true-part> [ # <false-part> ]
Note that ternary operators can be used as conditional statements (if ... then ... else ...):
self:value > 12 ?( self:current = true, self.scroll-to-view())
; - if value of self element is larger than 12 make self current and scroll it to the view.
CSSS! is a typeless language. All variables can hold following values:
No aggregate types (like array) are supported. Intentionally.
accepts integer numbers, floating point numbers, stings literals, length units and regexp literals:
integer-literal -> [0-9]+ | '0x' [0-9A-Fa-f]+ | ''' character ''' | key-code-literal float-literal -> [0-9]+ '.' [0-9]+ float-literal -> [0-9]+ '.' 'e'|'E' '+'|'-' [0-9]+ string-literal -> '"' [.]* '"' regexp-literal -> '/' <single line regular expression> ['/ig'] ';' length-literal -> <integer-literal> | <float-literal> immediately followed by one of: 'pt' | 'px' | 'pc' | '%' | 'em' | 'ex' | 'in' | 'cm' | 'mm'
Key-code-literal is a single character enclosed by single quote or one of the following:
'RETURN' | 'LEFT' | 'RIGHT' | 'UP' | 'DOWN' | 'PRIOR' | 'NEXT' | 'TAB' | 'HOME' | 'END' | 'DELETE' | 'INSERT' | 'BACK'
To define key combinations Ctrl+X like prepend name of the key with symbol '^'
.
Examples:
34 - Integer 0xAFED1234 - Integer 1.52 - Float 1.e2 - Float 1.e-2 - Float "Hello world!" - String 12pt - Length value that is getting resolved to number of pixels in arithmetic expressions. 'A' - Code of character 'A', IntegerExample of key-code-literals:
key-on!: key-code() == '^A'? ... # // Ctrl+A pressed key-code() == '^NEXT'? ... ; // Ctrl+PgDown pressed
Comment is a sequence of characters ignored by compiler. There are two types of comments:
'//' <text-no-crlf> end-of-line
'/*' <text> '*/'
CSSS! program is a sequence of statements separated by ','
(comma) symbols. And ends by symbol ';'
. Following statements are supported by the CSSS! script:
<left-side-expression> '=' <expression>.
<name> '=' <expression>
Block is a list of comma separated expressions:
'(' <expression> [, <expression>]* ')'
Value of the block equals to the value of last expression executed in the list.
<logical-expresion> '?' <when-true-expression> [ '#' <when-false-expression> ]
Logical expression is getting evaluated and if it is true
then expression on the right side of '?' is getting evaluated. In case of false
expresion on the right side of '#' (a.k.a. not equal) is geting evaluated. '#' part can be ommited.
No loops in CSSS!. Intentionally. (But there is a tail recursion in functions for that purposes)
return
statement is used for returning values from functions:
return <expression-or-value-to-return>
<object-set> '->' <reference-to-function-with-single-parameter>
Enumeration is used for invocation of function on the right for each element of object-set-expression on the left. Such pseudo functions as $()
, $p()
and $c()
produce sets - collection of DOM elements satisfying their selectors.
Example:
input.number { value-changed! : total = 0, $(input.number) -> @(el) total = total + el:value, $1(td#total):value = total; }
Code above means following:
When value of some <input class="number">
is getting changed do the following:
@(el) total = total + el:value
,input.number
selector,td#total
.Attributes of DOM elements can be accessed by using dot notation:
<object-or-object-set> '.' <attribute-name>
Example, for the element <input type="text">
following:
t = self.type
will retrieve value of DOM attribute named "type" (that has "text" here) and assign it to the variable t
.
State fields (runtime values) of DOM elements can be accessed by using following notation:
<object-or-object-set> ':' <state-name>
Where state-name is a name of one of state flags recognized by CSS: :hover
, :active
, :link
, :checked
, :current
, etc.
CSS attributes of DOM elements can be accessed by using '::' accessor:
<object> '::' <css-attribute-name>
Example, following timer even handler will gradually make element transparent:
timer!: self::opacity < 1.0? self::opacity = self::opacity + 0.1 # return cancel;
Keyword self
designates object - DOM element that has this rule applied to.
Keyword cancel
designates special value that is used with return
statement to instruct runtime to stop event propagation further.
CSSS! intentionally supports only anonymous custom defined functions.
Functions are declared as:
'@(' <parameter-list> ')' <statement> | <block>
Where <parameter-list>
is a comma separated list of names.
Function can be assigned to variable:
foo = @(p1, p2) p1 + p2, ...
That will declare function with two parameters p1
and p2
and body p1 + p2
and assign reference of the function to the foo
variable.
Invocation of functions is as usual
<variable> '(' <expression-1> , ... <expression-n> ')'
Example, following will invoke function foo above and assign its return value to variable bar:
bar = foo(1,2)
There are two global selector functions:
$(selector)
- select elements globally with the :root
set to the root node of the document. $1(selector)
- returns object - first element matching the selector with the :root set to the root node of the document.Function $() return set (possible empty) of DOM element selected. $1() function returns single DOM element - first element that matches the selector.
Selector functions support value concatenation in the form $( ... <value> ... )
where '<' and '>' parameter inclusion brackets.
Example, followng statemets:
ncol = 2, $( table td:nth-child(< ncol >)).some-attr = "hi!";
will set "hi!" to attribute some-attr for all elements satisfying the selector: table td:nth-child(2)
int(val)
- converts value val into integer; float(val)
- converts value val into float number; length(val)
- converts value val into length unit number; min(val1, val2 ... valN)
- returns minimal value of parameters passed; max(val1, val2 ... valN)
- returns maximum value of parameters passed; limit(val, minval, maxval)
- returns val if it is inside [minval...maxval] range, minval if val is less than minval or maxval otherwise. string.length
- property, length of the string object; string.toUpper()
- method, returns upper case version of the string; string.toLower()
- method, returns lover case version of the string; string.substr(start[, length = -1])
- method, returns fragment of the string, if length is less than zero returns rest of the string.