tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

state-pseudo-class.html (4699B)


      1 <!DOCTYPE html>
      2 <link rel=help href="https://html.spec.whatwg.org/multipage/custom-elements.html#custom-state-pseudo-class">
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <style>
      6 #state-and-part::part(inner) {
      7  opacity: 0;
      8 }
      9 #state-and-part::part(inner):state(innerFoo) {
     10  opacity: 0.5;
     11 }
     12 #state-and-part:state(outerFoo)::part(inner) {
     13  opacity: 0.25;
     14 }
     15 :state( \(escaped\ state  ) {}
     16 </style>
     17 <body>
     18 <script>
     19 class TestElement extends HTMLElement {
     20  constructor() {
     21    super();
     22    this._internals = this.attachInternals();
     23  }
     24 
     25  get i() {
     26    return this._internals;
     27  }
     28 }
     29 customElements.define('test-element', TestElement);
     30 
     31 class ContainerElement extends HTMLElement {
     32  constructor() {
     33    super();
     34    this._internals = this.attachInternals();
     35    this._shadow = this.attachShadow({mode:'open'});
     36    this._shadow.innerHTML = `
     37 <style>
     38 :host {
     39  border-style: solid;
     40 }
     41 :host(:state(dotted)) {
     42  border-style: dotted;
     43 }
     44 </style>
     45 <test-element part="inner"></test-element>`;
     46  }
     47 
     48  get i() {
     49    return this._internals;
     50  }
     51  get innerElement() {
     52    return this._shadow.querySelector('test-element');
     53  }
     54 }
     55 customElements.define('container-element', ContainerElement);
     56 
     57 test(() => {
     58  document.querySelector(':state(foo)');
     59  document.querySelector(':state(--foo)');
     60  document.querySelector(':state(--)');
     61  document.querySelector(':state(--16px)');
     62 }, ':state() parsing passes');
     63 
     64 test(() => {
     65  assert_throws_dom('SyntaxError', () => { document.querySelector(':state'); });
     66  assert_throws_dom('SyntaxError', () => { document.querySelector(':state('); });
     67  assert_throws_dom('SyntaxError', () => { document.querySelector(':state()'); });
     68  assert_throws_dom('SyntaxError', () => { document.querySelector(':state(=)'); });
     69  assert_throws_dom('SyntaxError', () => { document.querySelector(':state(name=value)'); });
     70  assert_throws_dom('SyntaxError', () => { document.querySelector(':state( foo bar)'); });
     71  assert_throws_dom('SyntaxError', () => { document.querySelector(':state(16px)'); });
     72 }, ':state() parsing failures');
     73 
     74 test(() => {
     75  assert_throws_dom('SyntaxError', () => { document.querySelector(':--('); });
     76  assert_throws_dom('SyntaxError', () => { document.querySelector(':--()'); });
     77  assert_throws_dom('SyntaxError', () => { document.querySelector(':--)'); });
     78  assert_throws_dom('SyntaxError', () => { document.querySelector(':--='); });
     79  assert_throws_dom('SyntaxError', () => { document.querySelector(':--name=value'); });
     80 }, 'deprecated :--state parsing failures');
     81 
     82 test(() => {
     83  assert_equals(document.styleSheets[0].cssRules[1].cssText,
     84      '#state-and-part::part(inner):state(innerFoo) { opacity: 0.5; }');
     85  assert_equals(document.styleSheets[0].cssRules[3].selectorText,
     86      ':state(\\(escaped\\ state)');
     87 }, ':state(foo) serialization');
     88 
     89 test(() => {
     90  let element = new TestElement();
     91  let states = element.i.states;
     92 
     93  assert_false(element.matches(':state(foo)'));
     94  assert_true(element.matches(':not(:state(foo))'));
     95  states.add('foo');
     96  assert_true(element.matches(':state(foo)'));
     97  assert_true(element.matches(':is(:state(foo))'));
     98  element.classList.add('c1', 'c2');
     99  assert_true(element.matches('.c1:state(foo)'));
    100  assert_true(element.matches(':state(foo).c1'));
    101  assert_true(element.matches('.c2:state(foo).c1'));
    102 }, ':state(foo) in simple cases');
    103 
    104 test(() => {
    105  let element = new TestElement();
    106  element.tabIndex = 0;
    107  document.body.appendChild(element);
    108  element.focus();
    109  let states = element.i.states;
    110 
    111  states.add('foo');
    112  assert_true(element.matches(':focus:state(foo)'));
    113  assert_true(element.matches(':state(foo):focus'));
    114 }, ':state(foo) and other pseudo classes');
    115 
    116 test(() => {
    117  let outer = new ContainerElement();
    118  outer.id = 'state-and-part';
    119  document.body.appendChild(outer);
    120  let inner = outer.innerElement;
    121  let innerStates = inner.i.states;
    122 
    123  innerStates.add('innerFoo');
    124  assert_equals(getComputedStyle(inner).opacity, '0.5',
    125      '::part() followed by :state()');
    126  innerStates.delete('innerFoo');
    127  innerStates.add('innerfoo');
    128  assert_equals(getComputedStyle(inner).opacity, '0',
    129      ':state() matching should be case-sensitive');
    130  innerStates.delete('innerfoo');
    131 
    132  outer.i.states.add('outerFoo');
    133  assert_equals(getComputedStyle(inner).opacity, '0.25',
    134      ':state(foo) followed by ::part()');
    135 }, ':state(foo) and ::part()');
    136 
    137 test(() => {
    138  let outer = new ContainerElement();
    139  document.body.appendChild(outer);
    140 
    141  assert_equals(getComputedStyle(outer).borderStyle, 'solid');
    142  outer.i.states.add('dotted');
    143  assert_equals(getComputedStyle(outer).borderStyle, 'dotted');
    144 }, ':state(foo) and :host()');
    145 </script>
    146 </body>