I always wanted to be able to access and customize the bullets or numbers in HTML lists.
For example...in the following list:
<ol type="1" start="42" reversed>
<li>AAA</li>
<li>BBB</li>
<li>CCC</li>
<li>DDD</li>
<li>EEE</li>
<li>FFF</li>
</ol>This proposal will also work well when appending, prepending or replacing childs in lists.
The user can see the number in the list, but if I want to know the number of the item the user has clicked, for example, I have to count their previous siblings. And have to think about reverse and start as well. And all that ignoring other things like "list-style-position", "list-style-type" and "list-style-image", which would apply different rules using css, instead of HTML attributes.
Decorating bullets/numbers
If I want a specific bullet or number to be in a different color or type, I can't.
I believe we could have access to something like decorators in in HTML_LIST_ELEMENT. By accessing someListElement.decorator we would have access to a HTML_LISTITEM_DECORATOR_ELEMENT instance.
{
type: '' // (readonly) the list type, like number, circle, etc
toString: '' // the value, like "C" or "34", or the utf8 symbol for Unordered lists
value: '' // the value itself, like "C" or 34 (of type integer), or the utf8 symbol for Unordered lists
index: 0 // the real index number of this item
separator: "." // the separator between the decorator and the list item content
style: {} // a CSS style for that prticular bullet/number
item: HTML_LISTITEM_ELEMENT // a reference to the list item this decorator is being applied to
list: HTML_LIST_ELEMENT // a reference to the parent list element for this item
}| Method | Description | Arguments | Return |
|---|---|---|---|
| isLast | True if current listItem is the last in its list | -- | Boolean |
| isFirst | True if current listItem is the first in its list | -- | Boolean |
| isFallback | True if it was of type image, but failed loading the image | -- | false of the path for the image that failed |
| getPrevious | Gets the previous decorator, or null if it is the first | -- | HTML_LISTITEM_DECORATOR |
| getNext | Gets the next decorator, or null if this is the last one | -- | HTML_LISTITEM_DECORATOR |
This way, developers would be able to customize that particular bullet or number, as well as read the current number, for example.
console.log(someOLItem.decorator) // 33, for example
console.log(someULItem.decorator) // utf8 code for circle, for exampleIf the decorator is an image, we would see its path in the value
We could have a HTML_LISTITEM_DECORATOR class that could be extended and implemented like so:
class myListIteDecorator extends HTML_LISTITEM_DECORATOR {
get () {
return this.value
}
}And then (that's the part I'm really not comfortable with, yet)
<ol type="1" start="42" reversed implements="myListDecorator">
...
</ol>That shall allow us to do something like this, for an useful example:
class qAndA extends HTML_LISTITEM_DECORATOR {
get () {
if (this.index % 2 === 0) {
// even
this.value = "A"
this.separator = ': '
} else {
// odd
this.value = "Q" + this.value
this.separator = ') '
this.style.fontWeight = 'bold'
}
return this
}
}Then, we could use it like this:
<ol type="1" implements="qAndA">
<li>Is the Earth flat?</li>
<li>Nope, it isn't!</li>
<li>Why is six affraid of seven?</li>
<li>Because seven eight nine</li>
<li>Why did the chicken cross the street?</li>
<li>Because it was bored</li>
</ol>And see as the result:
Q1) Is the Earth flat?
A: Nope, it isn't!
Q2) Why is six affraid of seven?
A: Because seven eight nine
Q3) Why did the chicken cross the street?
A: Because it was bored
And in that example, the questions should be bold
Styling wouldn't change a bit, as we already have some basic style properties to work with, like "list-style-position", "list-style-type" and "list-style-image".
The difference is that now, we can customize it decorators one by one or, use a pseudo-element for that.
The decorator pseudo element:
.someList:decorator {
color: red;
}
.someList li:nth-child(3):decorator {
color: blue;
}
.someList li:first-child:decorator:before {
content: "Follow these steps";
}Although it looks like an HTML element, it will not repaint or redraw in different moments.
For example, changing the innerHTML or innerText of a decorator should not work as it is merely a decorator for its list item.
In order to redraw a decorator, something that reflects into it should be changed in the list item it's related to.
For example, if you have the following implementation:
class todoList extends HTML_LISTITEM_DECORATOR {
get () {
if (this.item.classList.has('done')) {
// even
this.style.color = '#f0f0f0'
}
return this
}
}You could update the decorator style by adding or removing the class "done" in your list items:
<ol type="1" implements="todoList">
<li class="done">Buy bread</li>
<li>Buy milk</li>
<li class="done">Aniversary</li>
<li>Pay bills</li>
<li>Send some important e-mail</li>
<li>Call mom</li>
</ol>listItem.addEventListener('click', event => {
this.classList.toggle('done')
})Feel free to leave your comments in the GIST of this proposal.