├── LICENSE
├── README.md
├── index.bs
└── index.html
/LICENSE:
--------------------------------------------------------------------------------
1 | Creative Commons Legal Code
2 |
3 | CC0 1.0 Universal
4 |
5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
12 | HEREUNDER.
13 |
14 | Statement of Purpose
15 |
16 | The laws of most jurisdictions throughout the world automatically confer
17 | exclusive Copyright and Related Rights (defined below) upon the creator
18 | and subsequent owner(s) (each and all, an "owner") of an original work of
19 | authorship and/or a database (each, a "Work").
20 |
21 | Certain owners wish to permanently relinquish those rights to a Work for
22 | the purpose of contributing to a commons of creative, cultural and
23 | scientific works ("Commons") that the public can reliably and without fear
24 | of later claims of infringement build upon, modify, incorporate in other
25 | works, reuse and redistribute as freely as possible in any form whatsoever
26 | and for any purposes, including without limitation commercial purposes.
27 | These owners may contribute to the Commons to promote the ideal of a free
28 | culture and the further production of creative, cultural and scientific
29 | works, or to gain reputation or greater distribution for their Work in
30 | part through the use and efforts of others.
31 |
32 | For these and/or other purposes and motivations, and without any
33 | expectation of additional consideration or compensation, the person
34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she
35 | is an owner of Copyright and Related Rights in the Work, voluntarily
36 | elects to apply CC0 to the Work and publicly distribute the Work under its
37 | terms, with knowledge of his or her Copyright and Related Rights in the
38 | Work and the meaning and intended legal effect of CC0 on those rights.
39 |
40 | 1. Copyright and Related Rights. A Work made available under CC0 may be
41 | protected by copyright and related or neighboring rights ("Copyright and
42 | Related Rights"). Copyright and Related Rights include, but are not
43 | limited to, the following:
44 |
45 | i. the right to reproduce, adapt, distribute, perform, display,
46 | communicate, and translate a Work;
47 | ii. moral rights retained by the original author(s) and/or performer(s);
48 | iii. publicity and privacy rights pertaining to a person's image or
49 | likeness depicted in a Work;
50 | iv. rights protecting against unfair competition in regards to a Work,
51 | subject to the limitations in paragraph 4(a), below;
52 | v. rights protecting the extraction, dissemination, use and reuse of data
53 | in a Work;
54 | vi. database rights (such as those arising under Directive 96/9/EC of the
55 | European Parliament and of the Council of 11 March 1996 on the legal
56 | protection of databases, and under any national implementation
57 | thereof, including any amended or successor version of such
58 | directive); and
59 | vii. other similar, equivalent or corresponding rights throughout the
60 | world based on applicable law or treaty, and any national
61 | implementations thereof.
62 |
63 | 2. Waiver. To the greatest extent permitted by, but not in contravention
64 | of, applicable law, Affirmer hereby overtly, fully, permanently,
65 | irrevocably and unconditionally waives, abandons, and surrenders all of
66 | Affirmer's Copyright and Related Rights and associated claims and causes
67 | of action, whether now known or unknown (including existing as well as
68 | future claims and causes of action), in the Work (i) in all territories
69 | worldwide, (ii) for the maximum duration provided by applicable law or
70 | treaty (including future time extensions), (iii) in any current or future
71 | medium and for any number of copies, and (iv) for any purpose whatsoever,
72 | including without limitation commercial, advertising or promotional
73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
74 | member of the public at large and to the detriment of Affirmer's heirs and
75 | successors, fully intending that such Waiver shall not be subject to
76 | revocation, rescission, cancellation, termination, or any other legal or
77 | equitable action to disrupt the quiet enjoyment of the Work by the public
78 | as contemplated by Affirmer's express Statement of Purpose.
79 |
80 | 3. Public License Fallback. Should any part of the Waiver for any reason
81 | be judged legally invalid or ineffective under applicable law, then the
82 | Waiver shall be preserved to the maximum extent permitted taking into
83 | account Affirmer's express Statement of Purpose. In addition, to the
84 | extent the Waiver is so judged Affirmer hereby grants to each affected
85 | person a royalty-free, non transferable, non sublicensable, non exclusive,
86 | irrevocable and unconditional license to exercise Affirmer's Copyright and
87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the
88 | maximum duration provided by applicable law or treaty (including future
89 | time extensions), (iii) in any current or future medium and for any number
90 | of copies, and (iv) for any purpose whatsoever, including without
91 | limitation commercial, advertising or promotional purposes (the
92 | "License"). The License shall be deemed effective as of the date CC0 was
93 | applied by Affirmer to the Work. Should any part of the License for any
94 | reason be judged legally invalid or ineffective under applicable law, such
95 | partial invalidity or ineffectiveness shall not invalidate the remainder
96 | of the License, and in such case Affirmer hereby affirms that he or she
97 | will not (i) exercise any of his or her remaining Copyright and Related
98 | Rights in the Work or (ii) assert any associated claims and causes of
99 | action with respect to the Work, in either case contrary to Affirmer's
100 | express Statement of Purpose.
101 |
102 | 4. Limitations and Disclaimers.
103 |
104 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
105 | surrendered, licensed or otherwise affected by this document.
106 | b. Affirmer offers the Work as-is and makes no representations or
107 | warranties of any kind concerning the Work, express, implied,
108 | statutory or otherwise, including without limitation warranties of
109 | title, merchantability, fitness for a particular purpose, non
110 | infringement, or the absence of latent or other defects, accuracy, or
111 | the present or absence of errors, whether or not discoverable, all to
112 | the greatest extent permissible under applicable law.
113 | c. Affirmer disclaims responsibility for clearing rights of other persons
114 | that may apply to the Work or any use thereof, including without
115 | limitation any person's Copyright and Related Rights in the Work.
116 | Further, Affirmer disclaims responsibility for obtaining any necessary
117 | consents, permissions or other rights required for any use of the
118 | Work.
119 | d. Affirmer understands and acknowledges that Creative Commons is not a
120 | party to this document and has no duty or obligation with respect to
121 | this CC0 or use of the Work.
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # css-toggle
2 | Proposal for a CSS Toggle spec
3 |
--------------------------------------------------------------------------------
/index.bs:
--------------------------------------------------------------------------------
1 |
2 | Title: CSS Toggles
3 | Group: CSSWG
4 | Status: UD
5 | Work Status: exploring
6 | ED: http://tabatkins.github.io/css-toggle/
7 | Shortname: css-toggle
8 | Level: 1
9 | Editor: Tab Atkins Jr., Google, http://xanthir.com/contact
10 | Editor: Miriam E. Suzanne, Invited Expert, http://miriamsuzanne.com/contact
11 | Abstract: This specification defines a way to associate a "toggleable value" with an element which can be used in Selectors to select an element, and declarative ways to set and modify this value on the element.
12 | Ignored Terms: spoiler-text
13 | Warning: custom
14 | Custom Warning Title: Abandoned
15 | Custom Warning Text: This spec attempted to handle too many things at once; the distinct behaviors may have an underlying mechanic driving them, but end up needing very different interaction/accessibility behaviors to be usable in practice. Instead, multiple more targeted proposals (`` groups, carousel styling, etc) are being pursued.
16 |
17 |
18 |
19 | spec:css-display-3; type:dfn; text:element
20 | spec:css-contain-2; type:property; text:content-visiblity
21 |
22 |
23 |
40 |
41 |
42 | Introduction
43 |
44 | This section is not normative.
45 |
46 | Many user-interface languages define elements which can have "toggleable state",
47 | which can be modified by user interaction
48 | and responded to by the element.
49 | For example, in HTML, the <input type=checkbox>
has a "checked" state
50 | which toggles between true and false when the user activates the element,
51 | and which is selected by the '':checked'' pseudoclass.
52 |
53 | These sorts of elements are extremely useful,
54 | to the point that authors sometimes abuse them
55 | to get the same functionality on other elements:
56 |
57 |
58 | The following markup example shows how to lightly abuse HTML semantics
59 | to declaratively use toggleable state:
60 |
61 |
62 |
67 |
76 |
77 |
78 | In this markup,
79 | one can cross out ingredients as they're used in the recipe
80 | by simply clicking on them,
81 | without any scripting being involved.
82 | The <{label}> "transfers" the activation
83 | to the (hidden) checkboxes,
84 | which are then used to style the span.
85 |
86 |
87 | This module generalizes this ability
88 | and allows it to be applied to any element via CSS,
89 | so authors do not have to abuse host language semantics for styling purposes.
90 | It defines a a way of attaching lightweight "state" to an element via CSS
91 | ('toggle-root'),
92 | defining how user interactions can change that state
93 | ('toggle-trigger'),
94 | and responding to that state from CSS
95 | ('':toggle()'' pseudo-class).
96 | Scripting can also create, modify, and respond to this state,
97 | to accommodate more complicated scenarios.
98 |
99 | It also defines how to infer reasonable accessibility semantics
100 | from the toggle structure,
101 | making it simpler and more reliable
102 | to produce accessible pages
103 | using these sorts of basic interactivity
104 | without the author having to manually annotate a page
105 | with ARIA attributes or similar.
106 |
107 |
108 | Terminology
109 |
110 | Any element can become a toggle root,
111 | meaning it hosts one or more [=toggles=].
112 | Each [=toggle=] has a name,
113 | a value between 0 and some maximum,
114 | and a few other bits of metadata,
115 | all of which can be set via the 'toggle-root' property.
116 | The toggle is visible to the [=toggle root=],
117 | its descendants,
118 | and possibly its siblings and their descendants
119 | (if the toggle says they can);
120 | any element that can "see" a [=toggle=]
121 | can use the '':toggle()'' pseudo-class
122 | to select the element based on the toggle's value.
123 |
124 | Any element that can see a [=toggle=]
125 | can also trigger the toggle,
126 | changing its value when the element is "activated",
127 | via the 'toggle-trigger' property.
128 | This means you can have elements that self-trigger their own toggle,
129 | like checkboxes,
130 | but also have toggles that are visible to wide sections of a page
131 | and are triggered by buttons (or tabs, or headings, etc)
132 | inside that section,
133 | so multiple elements can use '':toggle()'' to respond to the toggle.
134 |
135 | Toggles can also be grouped together,
136 | so that only one of the toggles in the group
137 | can have a non-zero value at a time,
138 | like how radio buttons work in HTML.
139 |
140 |
141 |
142 | Toggle Concepts
143 |
144 | A toggle is a [=struct=] associated with an [=element=],
145 | which represents something that can be toggled on or off by user action,
146 | and matched with Selectors.
147 | Toggles have the following [=struct/items=]:
148 |
149 |
150 | : name
151 | :: A <>.
152 |
153 | : value
154 | ::
155 | A <> or non-negative <>:
156 | either 0 (the inactive value)
157 | or a value 1 or higher (the active values).
158 |
159 |
160 | : states
161 | ::
162 | Either an integer greater than or equal to 1,
163 | indicating the nominally maximum integer [=toggle/value=],
164 | or a [=/list=] of unique state names,
165 | each of which are <>s.
166 |
167 | This also defines the maximum state of a toggle,
168 | as either the [=toggle/states=] value (if it's an integer)
169 | or the length of [=toggle/states=] minus 1 (if it's a list).
170 |
171 | Note: Toggles can be set to integer values larger than than the "maximum",
172 | or to ident values not given in the list of names,
173 | but when a toggle is incremented or decremented
174 | it will treat all such values as out-of-bounds
175 | and bring the value back within the range defined by [=toggle/states=].
176 |
177 | : group
178 | ::
179 | A [=boolean=] indicating whether the [=toggle=] is part of a [=toggle group=]
180 | (of the same [=toggle/name=])
181 | or not.
182 |
183 | : scope
184 | ::
185 | An enum indicating what sort of [=toggle/scope=] the [=toggle=] uses.
186 | It can have two values:
187 |
188 | * "wide", indicating the toggle has [=toggle/wide scope=]
189 | (it's visible to the element, its descendants,
190 | and its following siblings and their descendants).
191 | * "narrow", indicating the toggle has [=toggle/narrow scope=]
192 | (it's visible to the element and its descendants only).
193 |
194 | : overflow
195 | :: An enum
196 | (either "cycle", "cycle-on" or "sticky"),
197 | specifying how to react when a [=toggle activation=]
198 | would increment the [=toggle/value=]
199 | above its maximum
200 | or below its minimum.
201 |
202 |
203 | The precise details are defined in [=change a toggle=],
204 | but in short:
205 |
206 | * For ''cycle'',
207 | incrementing past the maximum
208 | resets the value to 0,
209 | and decrementing below 0
210 | resets it to the maximum.
211 |
212 | * For ''cycle-on'',
213 | incrementing past the maximum
214 | resets the value to 1,
215 | and decrementing it below 1
216 | resets it to the maximum.
217 |
218 | (In other words,
219 | the toggle "stays on"
220 | once it reaches an [=active value=],
221 | rather than cycling back to an [=inactive value=].)
222 |
223 | * For ''sticky'',
224 | incrementing past the maximum value
225 | resets the value to the maximum,
226 | and decrementing it below 0
227 | resets it to 0.
228 |
229 |
230 |
231 | [=Toggles=] are persistent state on an element.
232 | Once created, none of their items are affected by CSS,
233 | and only their [=toggle/value=] can be changed by user interaction.
234 | (Scripting can change the other items, however;
235 | see [[#dom]].)
236 | An element can have any number of [=toggles=].
237 |
238 |
239 | To match values,
240 | given |toggle| (a [=toggle=]),
241 | a test value |test value| (an integer or <>),
242 | and optionally |states|
243 | (a [=toggle/states=] value):
244 |
245 | 1. If |states| was not passed,
246 | let |states| be |toggle|'s own [=toggle/states=] value.
247 |
248 | 2. Let |toggle value| be |toggle|'s value.
249 |
250 | 3. If |toggle value| and |test value| are both integers,
251 | and the same integer,
252 | return true.
253 |
254 | 4. If |toggle value| and |test value| are both <>s,
255 | and are [=identical to=] each other,
256 | return true.
257 |
258 | 5. If |states| is a list of <>s,
259 | and |toggle value| is a <> in the list,
260 | set |toggle value| to its index in the list.
261 |
262 | Do the same for |test value| if it is a <>.
263 |
264 | If |toggle value| and |test value| are now both the same integer,
265 | return true.
266 |
267 | 6. Otherwise, return false.
268 |
269 |
270 | ----
271 |
272 | A toggle specifier is a [=struct=]
273 | associated with an element,
274 | with the same structure as a [=toggle=].
275 | They serve multiple roles:
276 | they specify what [=toggles=] the element is expected to have on it
277 | (creating fresh ones if they don't exist),
278 | provide default values for the newly-created [=toggle's=] items,
279 | and override a [=toggle's=] default behavior when it receives a [=toggle activation=].
280 |
281 | [=Toggle specifiers=] are defined by the 'toggle-root' property;
282 | they are not persistent state on the element.
283 | An element can have any number of [=toggle specifiers=].
284 |
285 | ----
286 |
287 | A toggle group is a [=struct=] associated with an [=element=],
288 | which groups together toggles of the same name
289 | so that only one can be in an [=active value=] at a time.
290 | [=Toggle groups=] have the following [=struct/items=]:
291 |
292 |
293 | : name
294 | :: A <>.
295 |
296 | : scope
297 | ::
298 | An enum indicating what sort of [=toggle/scope=] the [=toggle group=] uses.
299 | It can have two values:
300 |
301 | * "wide", indicating the toggle has [=toggle/wide scope=]
302 | (it's visible to the element, its descendants,
303 | and its following siblings and their descendants).
304 | * "narrow", indicating the toggle has [=toggle/narrow scope=]
305 | (it's visible to the element and its descendants only).
306 |
307 |
308 | [=Toggle groups=] are defined by the 'toggle-group' property;
309 | they are not persistent state on an element.
310 | An element can have any number of [=toggle groups=].
311 |
312 | A [=toggle=] is in a toggle group
313 | if its [=toggle/group=] boolean is true;
314 | if the element is [=in scope=] for a [=toggle group=]
315 | with the same [=toggle/name=] as the [=toggle=],
316 | it's in that group;
317 | otherwise, it's in a document-wide implicit toggle group
318 | with the same [=toggle/name=].
319 |
320 | ----
321 |
322 | [=Toggles=] and [=toggle groups=] have a scope,
323 | defining what additional elements
324 | (beyond the element the [=toggle=]/[=toggle group=] is on)
325 | can see and interact with the [=toggle=]/[=toggle group=].
326 |
327 | If the [=toggle=] ([=toggle group=]) has wide scope,
328 | it's visible to the element it's defined on,
329 | its descendants
330 | its [=tree/following=] [=tree/siblings=],
331 | and their [=tree/descendants=].
332 |
333 | If the [=toggle=] ([=toggle group=]) has narrow scope,
334 | it's visible to the element it's defined on
335 | and its descendants.
336 |
337 | [=Toggles=] of the same [=toggle/name=] "shadow" earlier ones;
338 | if multiple toggles of a given [=toggle/name=] would have overlapping scopes,
339 | an element is only in scope
340 | for the [=toggle=] created by the nearest [=preceding=] element in [=tree order=].
341 | The same applies to [=toggle groups=].
342 | However, [=toggles=] and [=toggle groups=] do not interfere with each other's scopes;
343 | an element can "see past" a [=toggle=] to find a [=toggle group=] of the same name it's [=in scope=] for,
344 | and vice versa.
345 |
346 |
347 |
348 | Toggles and CSS Properties
349 |
350 | To allow for toggles to be responded to by Selectors
351 | without causing any circularity issues,
352 | [=toggles=] themselves are invisible state on an element,
353 | separate from any CSS properties that might apply.
354 | The CSS properties merely define which elements can activate a toggle,
355 | and which elements can respond to a toggle activation
356 | (and how they do so).
357 |
358 |
359 | For example, while an element needs 'toggle-root' to establish a toggle,
360 | once a toggle is created,
361 | removing the 'toggle-root' property does not affect the toggle.
362 |
363 |
364 | .toggleable {
365 | toggle-root: --foo 1;
366 | toggle-trigger: --foo;
367 | }
368 | .toggleable:toggle(--foo) {
369 | toggle-root: none;
370 | toggle-trigger: none;
371 | }
372 |
373 |
374 | In this example, the toggleable element declares that it can establish a ''foo'' toggle,
375 | and activate it.
376 | During a rendering update,
377 | the ''foo'' toggle is created on the element
378 | (initially with a value of 0, its [=inactive value=]);
379 | when the element is clicked, it's incremented to its [=active value=] (1).
380 |
381 | At this point, the '':toggle(--foo)'' rule begins to match,
382 | and removes the ''toggle-*'' properties.
383 | This does not remove the ''foo'' toggle or affect its value, however;
384 | it still exists and is still set to ''1'',
385 | so the '':toggle()'' pseudo-class will continue matching.
386 | However, further activations of the element
387 | will no longer affect the ''foo'' toggle,
388 | since 'toggle-trigger' was changed to ''toggle-trigger/none''.
389 |
390 | The ''foo'' toggle is thus "frozen" in the activated state
391 | (unless the author has other elements in the toggle's [=toggle/scope=] that can also affect it,
392 | or tweaks the value manually via JS).
393 |
394 |
395 |
396 |
405 |
406 |
407 | Creating a Toggle: the 'toggle-root' property
408 |
409 |
410 | Name: toggle-root
411 | Value: none | <>#
412 | Initial: none
413 | Applies to: all elements
414 | Inherited: no
415 | Percentages: n/a
416 | Media: interactive
417 | Computed value: as specified
418 | Animatable: no
419 |
420 |
421 |
422 | <> =
423 | <>
424 | [
425 | <> [at <>]? ||
426 | <> ||
427 | group ||
428 | self
429 | ]?
430 | <> = <> | '[' <>{2,} ']'
431 | <> = <> | <>
432 | <> = cycle | cycle-on | sticky
433 |
434 |
435 | The 'toggle-root' property causes [=toggles=] to be created on an element,
436 | and controls how the [=toggles=] are updated when they are activated.
437 |
438 |
439 | - none
440 |
-
441 | The element has no [=toggle specifiers=].
442 |
443 | (This does not remove any [=toggles=] that have already been established
444 | on the element.)
445 |
446 |
- <>#
447 |
-
448 | The element has one or more [=toggle specifiers=],
449 | one per <>,
450 | which determine how toggles will be initially created
451 | if they don't already exist on the element,
452 | and how they react to being activated.
453 |
454 | Each <> is composed of several parts,
455 | most of which are optional,
456 | corresponding to the [=struct/items=] of a [=toggle specifier=].
457 | They specify how the newly-created [=toggle=]
458 | will be set up:
459 |
460 | * The initial <>
461 | specifies the [=toggle specifier/name=].
462 |
463 | * The <> specifies the [=toggle specifier/states=].
464 | If specified as an <>,
465 | it sets [=toggle specifier/states=] to the given number;
466 | if specified as a bracketed list of <>s,
467 | it sets [=toggle specifier/states=]
468 | to a list containing those identifiers.
469 | If omitted, defaults to ''1''.
470 |
471 | If <> is a bracketed list,
472 | and there are any repeated <>s among its items,
473 | the property is invalid.
474 |
475 | * The <>, if specified,
476 | specifies the initial [=toggle specifier/value=].
477 | If omitted, it's set to 0.
478 |
479 | * The <> keyword, if specified,
480 | specifies the [=toggle specifier/overflow=] enum.
481 | If omitted, it's set to "cycle".
482 |
483 | * The group keyword, if specified,
484 | sets the [=toggle specifier/group=] boolean to true.
485 | If omitted, it's set to false.
486 |
487 | * The self keyword, if specified,
488 | sets the [=toggle specifier/scope=] enum to "narrow".
489 | If omitted, it's set to "wide".
490 |
491 | In addition to specifying how to create new [=toggles=],
492 | a [=toggle specifier=] overrides the existing [=toggle's=]
493 | [=toggle/states=],
494 | [=toggle/overflow=],
495 | and [=toggle/group=],
496 | if they differ,
497 | allowing an existing [=toggle=] to have its behavior changed
498 | if necessary.
499 |
500 |
501 |
502 | Revisiting the example in the Introduction,
503 | the same ingredient list can be specified in simple HTML and CSS:
504 |
505 |
506 |
507 | - 1 banana
508 |
- 1 cup blueberries
509 | ...
510 |
511 |
520 |
521 |
522 | The effect is identical to what was specified in the Introduction example,
523 | except the markup is much simpler and more semantic.
524 |
525 |
526 |
527 | Toggle Creation Details
528 |
529 | Each [=element=] has a list of established toggles,
530 | representing [=toggles=] on the element.
531 | These are created automatically by the 'toggle-root' property,
532 | and/or manually by interacting with the {{Element/toggles|Element.toggles}} map.
533 |
534 | Issue: Define the precise point in [=update the rendering=]
535 | when toggles are created
536 | if 'toggle-root' names a toggle that doesn't exist on the element yet.
537 |
538 |
539 |
548 |
549 |
550 | Linking Toggle Values: the 'toggle-group' property
551 |
552 |
553 | Name: toggle-group
554 | Value: none | [ <> self? ]#
555 | Initial: none
556 | Applies to: all elements
557 | Inherited: no
558 | Percentages: n/a
559 | Media: interactive
560 | Computed value: as specified
561 | Animatable: no
562 |
563 |
564 | By default, each [=toggle's=] [=toggle/value=] is independent;
565 | incrementing one has no effect an any other.
566 | The 'toggle-group' property allows elements to link their [=toggles=] together:
567 | all [=toggles=] with the same [=toggle/name=] as the [=toggle group=]
568 | that are on elements [=toggle/in scope=] for the [=toggle group=]
569 | are linked,
570 | such that only one can be in an [=active value=] at a time,
571 | similar to HTML's <input type=radio>
element.
572 |
573 |
574 | - none
575 |
-
576 | The element does not define a [=toggle group=].
577 |
578 |
- [<> self?]#
579 |
-
580 | The element defines one or more [=toggle groups=],
581 | one per comma-separated item:
582 |
583 | * The <>
584 | specifies the [=toggle group/name=],
585 | as the item's value.
586 |
587 | * The ''toggle-group/self'' keyword, if specified,
588 | sets the [=toggle group/scope=] enum to "narrow".
589 | If omitted, it's set to "wide".
590 |
591 | Only one [=toggle=] [=in a toggle group=] can be in an [=active value=] at a time;
592 | see 'toggle-trigger' for details.
593 |
594 |
595 |
596 | For example, 'toggle-group' can be used to control a tabbed display,
597 | so that only one panel is displayed at a time:
598 |
599 |
600 |
601 | first tab
602 | first panel
603 | second tab
604 | second card
605 | ...
606 |
607 |
635 |
636 |
637 | Clicking on any tab will increment its corresponding [=toggle's=] [=toggle/value=] from 0 to 1
638 | (and the ''cycle-on'' keyword will keep it at 1 if activated multiple times),
639 | while resetting the rest of the tabs' [=toggle/values=] to 0.
640 | Each panel is [=in scope=] for the [=toggle=] defined by its preceding tab,
641 | so it can respond to the [=toggle/value=] as well.
642 |
643 | Issue: Using 'toggle-visibility' rather than 'display'
644 | is a much better practice;
645 | I should probably change this to that.
646 |
647 |
648 |
649 | Radio buttons have one particular tabbing/switching/activation behavior
650 | (they occupy a single tabindex spot;
651 | once reached you can move between them with arrow keys;
652 | moving to one auto-activates it),
653 | but not all groups will want that behavior.
654 | Accordions, in particular, probably don't,
655 | and instead just want to effectively be independent checkboxes
656 | that happen to only have one active at a time.
657 |
658 | We probably want to add a bool to toggle groups dictating this;
659 | are there more than these two behaviors to deal with?
660 |
661 |
662 |
663 |
672 |
673 |
674 | Activating a Toggle: the 'toggle-trigger' property
675 |
676 |
677 | Name: toggle-trigger
678 | Value: none | <>#
679 | Initial: none
680 | Applies to: elements without existing activation behavior (see prose)
681 | Inherited: no
682 | Percentages: n/a
683 | Media: interactive
684 | Computed value: the keyword ''toggle-trigger/none'', or a list of <> values
685 | Animatable: no
686 |
687 |
688 |
689 | <> = <> <>?
690 | <> =
691 | [prev | next] <>? |
692 | set <>
693 |
694 |
695 | The 'toggle-trigger' property specifies that an element can be activated
696 | to change the value of one or more [=toggles=].
697 | It has the following values:
698 |
699 | ISSUE: Consider adding support for an at-rule that defines machine states,
700 | the available events to trigger from each state,
701 | and the resulting state of each event.
702 | In that case <> would need to also accept custom events,
703 | possibly marked by a new keyword or function.
704 |
705 |
706 | : none
707 | ::
708 | The element does not manipulate any [=toggles=].
709 |
710 | : <>
711 | ::
712 | If the <> is omitted,
713 | it defaults to ''next 1''.
714 | If the <> specifies ''prev'' or ''next'',
715 | but omits the following <>,
716 | it defaults to ''1''.
717 |
718 | If the element already has existing activation behavior from the host language,
719 | this value does nothing.
720 |
721 | Otherwise, the element becomes activatable,
722 | and when activated,
723 | for each comma-separated entry in the list,
724 | [=fires a toggle activation=]
725 | with the given <> as a [=toggle activation/name=],
726 | and the <> [=toggle activation/action=].
727 |
728 |
729 | A toggle activation is a struct with the following items:
730 |
731 |
732 | : name
733 | :: The [=toggle/name=] of the [=toggle=]
734 | this is intended to activate.
735 |
736 | : action
737 | :: A <> value.
738 |
739 |
740 |
741 | To fire a toggle activation
742 | on an element |initial element|
743 | with a [=toggle activation=] |activation|:
744 |
745 | 1. Let |el| initially be |initial element|.
746 |
747 | 2. If |el| has a [=toggle=]
748 | with the same [=toggle/name=] as |activation|,
749 | and |initial element| is [=in scope=] for the [=toggle=],
750 | proceed to the next step.
751 | Otherwise, continue searching for a [=toggle=]:
752 |
753 | * If |el| has a [=previous sibling=],
754 | set |el| to that element
755 | and return to step 2.
756 | * Otherwise, if |el| has a [=parent=] element,
757 | set |el| to that element
758 | and return to step 2.
759 | * Otherwise, return. (No toggle was found, so nothing happens.)
760 |
761 | 3. Let |t| be the [=toggle=] on |el|
762 | with the same [=toggle/name=] as |activation|.
763 |
764 | Let |old value| be |t|'s [=toggle/value=].
765 |
766 | Let |tSpec| be the [=toggle specifier=] on |el|
767 | with the same [=toggle specifier/name=] as |activation|,
768 | if one exists.
769 |
770 | [=Change a toggle=] |t|,
771 | passing |activation|'s [=toggle activation/action=],
772 | and an override spec of |tSpec|
773 | if it exists.
774 |
775 | Let |new value| be |t|'s [=toggle/value=].
776 |
777 | 4. If |old value| and |new value| are different,
778 | [=fire a toggle change event=] at |el| for the toggle |t|.
779 |
780 |
781 |
782 | To
change a toggle |t|,
783 | given an [=toggle activation/action=] |action|,
784 | and optionally a [=toggle specifier=] |override spec|:
785 |
786 | 1. If |override spec| was passed,
787 | let |states|, |group|, and |overflow|
788 | be the correspondingly-named items from |override spec|.
789 |
790 | Otherwise, let |states|, |group|, and |overflow|
791 | be the correspondingly-named items from |t|.
792 |
793 | 2. If |action| starts with the keyword ''set'',
794 | then change |t|'s value
795 | to the value specified by |action|.
796 |
797 | If |t| does not [=match values|match=] 0,
798 | given |states|,
799 | and |group| is true,
800 | then set the [=toggle/value=] of all other [=toggles=]
801 | [=in a toggle group|in the same toggle group=] as |t|
802 | to 0.
803 |
804 | Return.
805 |
806 | 3. If |t|'s [=toggle/value=] is an integer,
807 | let |index| be that integer.
808 | Otherwise, if |states| is a list of idents
809 | and |t|'s [=toggle/value=] is in the list,
810 | let |index| be the index of the first occurence of the value.
811 | Otherwise, let |index| be infinity.
812 |
813 | 4. If |states| is an integer,
814 | let |max index| be that integer.
815 | Otherwise, let |max index|
816 | be one less than the length of |states|.
817 |
818 | 5. If |action| starts with the keyword ''next'',
819 | then increment |index| by |action|'s value.
820 | Then, based on the value of |overflow|:
821 |
822 |
823 | : ''cycle''
824 | :: If |index| is greater than |maximum index|,
825 | set |index| to 0.
826 |
827 | : ''cycle-on''
828 | :: If |index| is greater than |maximum index|,
829 | set |index| to 1.
830 |
831 | : ''sticky''
832 | :: If |index| is greater than |maximum index|,
833 | set |index| to |maximum index|.
834 |
835 |
836 | Otherwise, if |action| starts with the keyword ''prev'',
837 | then decrement |index| by |action|'s value.
838 | Then, based on the value of |overflow|:
839 |
840 |
841 | : ''cycle''
842 | :: If |index| is less than 0
843 | or greater than |maximum index|,
844 | set |index| to |maximum index|.
845 |
846 | : ''cycle-on''
847 | :: If |index| is less than 1
848 | or greater than |maximum index|,
849 | set |index| to |maximum index|.
850 |
851 | : ''sticky''
852 | :: If |index| is less than 0,
853 | set |index| to 0.
854 |
855 | If |index| is greater than |maximum index|,
856 | set |index| to |maximum index|.
857 |
858 |
859 | 6. If |states| is a list of idents,
860 | and |index| is the index of one of the entries in that list,
861 | set |t|'s [=toggle/value=] to that entry.
862 |
863 | Otherwise, set [=toggle/value=] to |index|.
864 |
865 | 7. If |t| does not [=match values|match=] 0,
866 | given |states|,
867 | and |group| is true,
868 | then set the [=toggle/value=] of all other [=toggles=]
869 | [=in a toggle group|in the same toggle group=] as |t|
870 | to 0.
871 |
872 |
873 | Issue: Define in much greater precision what it means to "become activatable".
874 | The element must become focusable
875 | (with a default spot in the focus order)
876 | and become capable of being activated by mouse/keyboard/etc.
877 | Similarly define the "already activatable" prose in more detail;
878 | we want to exclude things like text inputs,
879 | which would confuse a11y tooling,
880 | but include buttons that aren't, like, submit buttons.
881 |
882 |
883 |
892 |
893 |
894 | Creating and Activating Toggles Simultaneously: the 'toggle' shorthand
895 |
896 |
897 | Name: toggle
898 | Value: <<'toggle-root'>>
899 |
900 |
901 | While some cases require setting up a [=toggle=] on an ancestor
902 | of the elements that will activate and respond to the toggle,
903 | in many cases the [=toggle/scope=] rules for [=toggles=]
904 | are such that it's fine to create the [=toggle=]
905 | on the element intended to activate the toggle as well.
906 |
907 | The 'toggle' shorthand sets both the 'toggle-root' and 'toggle-trigger' properties on an element together.
908 | The entire value of the property is assigned to 'toggle-root',
909 | while 'toggle-trigger' is assigned to just the <>s specified in the list,
910 | if any.
911 |
912 |
913 | For example,
914 | in the following code for an <{spoiler-text}> element,
915 | the show/hide button precedes the content it will show and hide,
916 | so we can just create the toggle on it as well:
917 |
918 |
919 |
920 | ...
921 | ...
922 |
923 |
931 |
932 |
933 |
934 |
935 | Accessibility Implications of Toggles
936 |
937 |
938 | TODO
939 |
940 | * a 'toggle-trigger' element needs to become activatable/focusable/etc,
941 | and communicate in the a11y tree that it's a checkbox/radio/etc
942 | * we can infer what type of control it is
943 | by examining the properties of the toggle:
944 | if it's part of a group, cycle-on, etc.
945 | * if 'toggle-visibility' is in use,
946 | we can also automatically infer all the tab-set ARIA roles
947 |
948 |
949 |
950 |
959 |
960 |
961 | Selecting Elements Based on Toggle Value: the '':toggle()'' pseudo-class
962 |
963 | [[SELECTORS-4]] defines the '':checked'' pseudo-class,
964 | which allows author to match certain elements
965 | (as defined by the host language)
966 | depending on their "checked" state.
967 |
968 | [=Toggles=] provides a very similar functionality,
969 | allowing elements to be selected based on their [=toggle=] [=toggle/value=],
970 | the :toggle() pseudo-class:
971 |
972 |
973 | :toggle( <> <>? )
974 |
975 |
976 | An element matches '':toggle()''
977 | if the element is [=in scope=] for a [=toggle=]
978 | with the [=toggle/name=] given by <>,
979 | and either the [=toggle=]
980 | [=match values|matches=] the provided <>,
981 | or the <> is omitted
982 | and the [=toggle=] is in any [=active value=].
983 |
984 |
985 | For example, if a [=toggle=] named "used"
986 | is defined on each element in an recipe's ingredient list,
987 | the ingredients can respond to being clicked on easily:
988 |
989 |
990 | .ingredient {
991 | toggle: --used;
992 | }
993 | .ingredient:toggle(--used) {
994 | color: silver;
995 | text-decoration: line-through;
996 | }
997 |
998 |
999 |
1000 |
1001 | A checkbox that can represent an "indeterminate" value
1002 | might have two active values.
1003 |
1004 |
1005 | .tristate-check {
1006 | toggle: --check 2 at 0;
1007 | }
1008 | .tristate-check:toggle(--check 1) {
1009 | /* "checked" styles */
1010 | }
1011 | .tristate-check:toggle(--check 2) {
1012 | /* "indeterminate" styles */
1013 | }
1014 |
1015 |
1016 |
1017 |
1018 | While '':not(:toggle(--foo))'' will correctly match an element
1019 | whose "foo" toggle is in an [=inactive value=],
1020 | it will
also match any element
1021 | that doesn't see a "foo" toggle at all.
1022 |
1023 | If this is inconvenient,
1024 | only elements that actually know about a particular toggle
1025 | can be targeted by specifying the [=inactive value=] specifically:
1026 |
1027 |
1028 | .card:toggle(--show 0) {
1029 | /* Definitely *not* shown */
1030 | }
1031 |
1032 |
1033 |
1034 |
1035 |
1044 |
1045 |
1046 | Automatically Hiding With A Toggle
1047 |
1048 | The 'content-visibility' property
1049 | allows an element to suppress the layout and rendering of its contents,
1050 | similar to ''display: none'';
1051 | however, its ''content-visibility/auto'' value allows the contents
1052 | to still be visible to various searching and accessibility features,
1053 | like find-in-page,
1054 | hash-navigation,
1055 | or tab order,
1056 | and then to automatically become visible
1057 | when the element becomes [=relevant to the user=].
1058 |
1059 | A common use-case for [=toggles=] is also to control whether an element is shown or hidden,
1060 | and in many cases it would also be useful to allow the contents of elements "hidden" in this way
1061 | to be accessible in the same ways.
1062 | To allow for this,
1063 | the 'toggle-visibility' property allows an element
1064 | to both respond to and control a toggle
1065 | with its visibility.
1066 |
1067 |
1068 | Name: toggle-visibility
1069 | Value: normal | <>
1070 | Initial: normal
1071 | Inherited: no
1072 | Applies to: all elements
1073 | Computed value: as specified
1074 | Animation type: not animatable
1075 |
1076 |
1077 | The 'toggle-visibility' property
1078 | allows an element to automatically tie its display to a particular [=toggle=] bi-directionally,
1079 | while still exposing its contents to be focused, found-in-page, etc.,
1080 | automatically showing itself when relevant.
1081 |
1082 |
1083 | : normal
1084 | ::
1085 | The property has no effect.
1086 |
1087 | : <>
1088 | ::
1089 | If the element is [=in scope=]
1090 | for a [=toggle=] whose name matches the <>,
1091 | and that [=toggle=] is in the [=inactive value=],
1092 | then the element acts as if ''content-visibility: auto'' is specified,
1093 | except that being on-screen does not make it [=relevant to the user=].
1094 |
1095 | If the element starts being [=relevant to the user=],
1096 | it [=fires=] a [=toggle activation=],
1097 | with a [=toggle activation/name=] of the given <>
1098 | and a [=toggle activation/action=] of ''set 1''.
1099 |
1100 | Note: If the [=toggle=] is in an [=active value=],
1101 | or the element can't see the specified [=toggle=] at all,
1102 | the element renders normally.
1103 |
1104 |
1105 |
1106 | For example, an "accordion" display,
1107 | such as used for a page of FAQs,
1108 | can use 'toggle-visibility' to hide the answers by default,
1109 | but still make them accessible to find-in-page:
1110 |
1111 |
1112 |
1113 | - Question 1?
1114 |
- Long answer......
1115 |
- Question 2?
1116 |
- Another long answer.....
1117 |
1118 |
1126 |
1127 |
1128 | Each <{dt}> establishes a separate "show" [=toggle=],
1129 | with all the defaults filling in to produce a standard "checkbox"-like behavior,
1130 | all initially in the [=inactive value=].
1131 | Each <{dt}> can be activated to show or hide the following answer.
1132 |
1133 | Each <{dd}> can see the [=toggle=] established by its preceding <{dt}>,
1134 | and will start out not rendering.
1135 | If the user searches on the page for a term,
1136 | or visits the page from a link with an #anchor linking into one of the answers,
1137 | the relevant answer will automatically activate the [=toggle=],
1138 | causing the <{dd}> to become visible.
1139 |
1140 |
1141 | Issue: Define ordering of activations,
1142 | so if multiple elements become relevant at the same time
1143 | and they're all part of a [=toggle group=],
1144 | which one "wins" is well-defined.
1145 |
1146 |
1147 |
1148 |
1157 |
1158 |
1159 | Scripting API
1160 |
1161 |
1162 | {{CSSToggleMap}}
1163 |
1164 |
1165 | partial interface Element {
1166 | [SameObject] readonly attribute CSSToggleMap toggles;
1167 | };
1168 |
1169 | interface CSSToggleMap {
1170 | maplike;
1171 | CSSToggleMap set(DOMString key, CSSToggle value);
1172 | };
1173 |
1174 |
1175 | The {{Element/toggles}} attribute on {{Element}}s
1176 | represents the [=established toggles=] on the element:
1177 | each [=toggle=] is represented by an [=map/entry=] in the map,
1178 | with its key equal to its [=toggle/name=]
1179 | and its value a {{CSSToggle}} representing the rest of the [=toggle's=] data.
1180 |
1181 | Entries can be automatically added to {{Element/toggles}}
1182 | by the 'toggle-root' property
1183 | when [=update the rendering=] occurs,
1184 | if 'toggle-root' defines a [=toggle specifier=]
1185 | whose name doesn't exist in {{Element/toggles}} yet;
1186 | see [[#toggle-creation]] for details.
1187 |
1188 |
1189 | The set(|key|, |value|)
1190 | [=method steps=] are:
1191 |
1192 | 1. If |key| does not start with "--" (two U+002D HYPHEN-MINUS characters),
1193 | [=throw=] a {{SyntaxError}}.
1194 |
1195 | 2. If |value|'s {{[[ToggleMap]]}} internal slot is non-{{undefined}},
1196 | then let |oldMap| be the [=map entries=] of the slot's value,
1197 | and [=map/remove=] the entry from |oldMap| whose value is |value|.
1198 |
1199 | 3. Set |value|'s {{[[ToggleMap]]}} internal slot to [=this=].
1200 |
1201 | 4. Let |map| be [=this's=] [=map entries=]. Set |map|[|key|] to |value|.
1202 |
1203 | 5. Return [=this=].
1204 |
1205 | Note: A given {{CSSToggle}} can only live in one {{CSSToggleMap}} at a time.
1206 | This avoids some otherwise confusing or ambiguous situations.
1207 |
1208 |
1209 |
1210 | {{CSSToggle}}
1211 |
1212 |
1213 | interface CSSToggle {
1214 | attribute (unsigned long or DOMString) value;
1215 | attribute unsigned long? valueAsNumber;
1216 | attribute DOMString? valueAsString;
1217 |
1218 | attribute (unsigned long or FrozenArray) states;
1219 | attribute boolean group;
1220 | attribute CSSToggleScope scope;
1221 | attribute CSSToggleCycle cycle;
1222 |
1223 | constructor(optional CSSToggleData options);
1224 | };
1225 |
1226 | dictionary CSSToggleData {
1227 | (unsigned long or DOMString) value = 0;
1228 | (unsigned long or sequence) states = 1;
1229 | boolean group = false;
1230 | CSSToggleScope scope = "wide";
1231 | CSSToggleCycle cycle = "cycle";
1232 | };
1233 |
1234 | enum CSSToggleScope {
1235 | "narrow",
1236 | "wide",
1237 | };
1238 |
1239 | enum CSSToggleCycle {
1240 | "cycle",
1241 | "cycle-on",
1242 | "sticky",
1243 | };
1244 |
1245 |
1246 | A {{CSSToggle}} represents a [=toggle=];
1247 | changing any attribute on the {{CSSToggle}}
1248 | will change the corresponding items of the [=toggle=] it represents,
1249 | and vice versa.
1250 |
1251 | Note: Only the [=toggle/value=] will change directly on a [=toggle=]
1252 | and get reflected back to the {{CSSToggle}};
1253 | the rest of its items are fixed on creation
1254 | unless manually changed on its associated {{CSSToggle}}.
1255 |
1256 | A {{CSSToggle}} will usually be an [=established toggle=] on an element,
1257 | present in the element's {{Element/toggles}} attribute,
1258 | but can also be used independently.
1259 | This is tracked by a \[[ToggleMap]] internal slot,
1260 | containing either {{undefined}} (the initial value)
1261 | or a weak reference to the {{CSSToggleMap}} the {{CSSToggle}} is in.
1262 |
1263 |
1264 | The new CSSToggle(|options|)
[=constructor steps=] are:
1265 |
1266 | 1. [=map/For each=] |name|→|value| in |options|:
1267 |
1268 | 1. If |name| is "states"
1269 | and |value| is a [=/list=]:
1270 |
1271 | * If any of the [=list/items=] of |value|
1272 | are [=string/identical to=] each other,
1273 | [=throw=] a {{SyntaxError}}.
1274 | * If |value|'s [=list/size=] is less than 2,
1275 | [=throw=] a {{SyntaxError}}.
1276 |
1277 | 3. Set the internal slot named |name| of [=this=]
1278 | to |value|.
1279 |
1280 | 2. Return [=this=].
1281 |
1282 |
1283 |
1284 | The valueAsNumber [=getter steps=] are:
1285 |
1286 | 1. If [=this's=] {{CSSToggle/value}} slot contains an integer,
1287 | return that.
1288 |
1289 | 2. If [=this's=] {{CSSToggle/value}} slot contains a string,
1290 | [=this's=] {{CSSToggle/states}} internal slot is a list,
1291 | and the string is present in that list,
1292 | return the index of the first instance of that string in the list.
1293 |
1294 | 3. Otherwise, return null
.
1295 |
1296 | The {{valueAsNumber}} [=setter steps=] are:
1297 |
1298 | 1. If [=the given value=] is an integer,
1299 | [=update the value slot=] of [=this=] to [=the given value=]
1300 | and return.
1301 |
1302 | 2. Otherwise, [=throw=] a {{TypeError}} exception.
1303 |
1304 | The {{valueAsNumber}} attribute does not have a corresponding internal slot.
1305 |
1306 |
1307 |
1308 | The valueAsString [=getter steps=]
1309 | are:
1310 |
1311 | 1. If [=this's=] {{CSSToggle/value}} internal slot contains an string,
1312 | return that.
1313 |
1314 | 2. If [=this's=] {{CSSToggle/value}} internal slot contains an index,
1315 | and [=this's=] {{CSSToggle/states}} internal slot is a list
1316 | and has an entry corresponding to that index,
1317 | return that entry.
1318 |
1319 | 3. Otherwise, return null
.
1320 |
1321 | The {{valueAsString}} [=setter steps=] are:
1322 |
1323 | 1. If [=the given value=] is an string,
1324 | [=update the value slot=] of [=this=] to [=the given value=]
1325 | and return.
1326 |
1327 | 2. Otherwise, [=throw=] a {{TypeError}} exception.
1328 |
1329 | The {{valueAsString}} attribute does not have a corresponding internal slot.
1330 |
1331 |
1332 |
1333 | The value [=setter steps=]
1334 | are to [=update the value slot=] of [=this=] to [=the given value=].
1335 |
1336 |
1337 |
1338 | To update the value slot
1339 | of a {{CSSToggle}} [=this=]
1340 | to a new value |val|:
1341 |
1342 | 1. If [=this=] is an [=established toggle=],
1343 | then [=change a toggle=] [=this=],
1344 | with an [=toggle activation/action=]
1345 | of ''set'' followed by |val|.
1346 |
1347 | Note: Due to the reflection,
1348 | this will automatically update
1349 | the {{CSSToggle/value}} internal slot of [=this=] as well.
1350 |
1351 | 2. Otherwise,
1352 | set the {{CSSToggle/value}} internal slot of [=this=]
1353 | to |val|.
1354 |
1355 |
1356 |
1357 | The states [=setter steps=] are:
1358 |
1359 | 1. If [=the given value=] is a sequence of {{DOMString}}s:
1360 |
1361 | * If any of the [=list/items=] of [=the given value=]
1362 | are [=string/identical to=] each other,
1363 | [=throw=] a {{SyntaxError}}.
1364 | * If [=the given value's=] [=list/size=] is less than 2,
1365 | [=throw=] a {{SyntaxError}}.
1366 |
1367 | 2. Set [=this's=] {{CSSToggle/states}} internal slot to [=the given value=].
1368 |
1369 |
1370 |
1371 | {{CSSToggleEvent}}
1372 |
1373 |
1374 | interface CSSToggleEvent : Event {
1375 | constructor(DOMString type, optional CSSToggleEventInit eventInitDict = {});
1376 | readonly attribute DOMString toggleName;
1377 | readonly attribute CSSToggle? toggle;
1378 | };
1379 |
1380 | dictionary CSSToggleEventInit : EventInit {
1381 | DOMString toggleName = "";
1382 | CSSToggle? toggle = null;
1383 | };
1384 |
1385 |
1386 | Issue: whatwg/dom#600
1387 | means apparently events don't yet work
1388 | if their init dictionaries have required members.
1389 | Neither of these have reasonable defaults,
1390 | especially the toggle part,
1391 | but oh well I guess.
1392 |
1393 |
1394 | To fire a toggle change event
1395 | at an {{Element}} |el|
1396 | for a [=toggle=] |toggle|
1397 | means to
1398 | [=fire an event=] named "togglechange"
1399 | using {{CSSToggleEvent}},
1400 | setting {{CSSToggleEvent/toggleName}} to |toggle|'s [=toggle/name=]
1401 | and {{CSSToggleEvent/toggle}} to the entry of |el|'s {{Element/toggles}} map
1402 | with |toggle|'s [=toggle/name=] as the key.
1403 |
--------------------------------------------------------------------------------