Numbering of <ol> items NOT using <li> value property - html

I have a (jquery ui) sortable list with li-elements, that hold information (an id for further processing) in their value-attribute.
However, I want my list to show numbering next to it, similar to this fiddle: http://jsfiddle.net/knj92mvu/
(Of course I mean the numbering of #correctList, to be sure ...)
$("#myOL").sortable({
update: function (event, ui) {
console.log('new index of dropped item:' + ui.item.index());
}
});
Now the OL elements think theyre smart by getting their position number from the value-property of the li. But, as said, the value-property is important for me and I can not overwrite it.
Is there a way I can display correct numbering of the items (1, 2, 3 for my example link given above) ignoring the value-property?
A possible workaround I can imagine: use one of the events of the .sortable(), get the index of the items and write it to the innerText of the li.
However I want to ensure there is no "clean" workaround for this, where I can assign certain numbering to lists, ignoring the value-property. Basically also for information how I could solve this WITHOUT jquery ui.

You can use CSS Counters
CSS:
#myOL{
list-style-position: inside;
list-style-type: none;
}
#myOL ol{
counter-reset: list 1;
}
#myOL li:before {
content: counter(list) '. ';
}
#myOL li{
padding: 4px;
border: 1px solid #ccc;
counter-increment: list 1;
}
JSFiddle demo

You can circumvent the counting logic entirely by using <div>s instead of <li>s:
<ol>
<div style="display:list-item;" value="whatever">Text</div>
<ol>
Here's your fiddle updated: http://jsfiddle.net/mbw41oj5/

Related

Match alignment of list bullets with text in `<div>`

I am injecting html from an editor into my site. How can I 'inherit' the alignment from a child element like this:
<li>
<div align="right">one</div>
</li>
the issue is that the bullets are aligned left and text is right , I would like to get the alignment from whatever is set on the div in this case 'right'. This can be different since it is coming from an html-editor.
css:
ul, ol, li {
list-style: disc !important;
}
jsfiddle:http://jsfiddle.net/bfu20zhq/
There is no way to select a parent according to this and the MDN has nothing to suggest that this has changed recently.
However, as indicated in related posts, this can be achieved through javascript (and must be, since css can't do it yet). You can do this by walking the DOM tree and finding all the div elements that have a parent li and then make their align attributes the same:
// create the filter for the tree walker
var div_filter = {
acceptNode: function (node) {
if ( node.tagName == 'DIV' && node.parentElement.tagName == 'LI' ) {
return NodeFilter.FILTER_ACCEPT;
}
}
};
// create the tree walker so we can
// find all the divs
var treeWalker = document.createTreeWalker( document.body,
NodeFilter.SHOW_ELEMENT,
div_filter,
false);
// walk the DOM tree for the nodes we want
// and make the `li` elements have the same `align` as the `div`s
while (treeWalker.nextNode()) {
console.log(treeWalker.currentNode);
treeWalker.currentNode.parentElement.setAttribute('align',
/* fetch the div's align attribute */
treeWalker.currentNode.getAttribute('align') );
}
Unfortunately, while this correctly sets the align attribute, it doesn't give the desired result as you can see in this fiddle. I'm leaving this here however because we need it for the full solution.
Setting float: right on the list elements has an effect, but a horrible one.
After a bit of tweaking, I found that adding inside to list-style and adjusting text-align to right or left accordingly, the desired result is achieved:
This is what we want, if the div has align = "right"
li {
list-style: disc inside;
text-align: right;
}
We also need to change the divs to display: inline-block so they don't act like non-text elements:
li > div {
display: inline-block;
}
If you want to align the bullets vertically, you need to give the divs a definite width, such as width: 30% or something like that.
So our while loop changes to:
while (treeWalker.nextNode()) {
console.log(treeWalker.currentNode);
treeWalker.currentNode.parentElement.style.textAlign =
treeWalker.currentNode.getAttribute('align');
}
Here is the complete fiddle.
If you want the same alignment simply add "list-style-position: inside;" to your css like this fiddle.
li
{
list-style: disc;
list-style-position: inside;
}

How can I select every other element that does not have a specific class?

I have a list of <div>s. Each <div> has class zebra. Until now I've used the following to stripe the list:
.zebra:nth-child(2n) { /* colors */ }
Now I'm implementing a filtering feature, such that some of these <div>s will have a class hidden. I tried updating my css to
.zebra:not(.hidden):nth-child(2n) { /* colors */ }
But that had no effect. What am I missing? How can I combine these selectors so that only the showing .zebra <div>s are considered in the :nth-child(2n)?
Here's a fiddle of what I'm describing.
UPDATE:
there is an unknown number of .hidden elements, and an unknown total number of elements. (the list is data-driven, not static).
I'd really rather not do any of:
run a javascript every time a filter control is touched, just to re-color the showing list items.
remove an element entirely when it's hiding. this makes re-adding it non-trivial (afaict).
Instead of removing the element as Justin suggested, you could replace it with an element of a different tag. We could use details, for example:
var placemarker = document.createElement("details");
node.parentNode.replaceChild(placemarker, node);
placemarker.appendChild(node);
Then, instead of using :nth-child, use :nth-of-type.
details { display:none; }
div.zebra:nth-of-type(2n) { /* colors */ }
Unhiding the element can then be done with:
placemarker.parentNode.replaceChild(placemarker.firstChild);
See this static example.
if you don't mind delving into jquery..
$('#yourHiddenElement').remove();
will remove it so that your css shades alternate.
http://jsfiddle.net/NYvcv/1/
I would suggest using this instead of applying the class 'hidden' to the element you want to hide.
If you know there will be a limited number of .hidden items, you can do something like this:
.zebra2:nth-child(2n) {
background: lightgrey;
}
.zebra2.hidden ~ .zebra2:nth-child(2n) {
background: inherit;
}
.zebra2.hidden ~ .zebra2:nth-child(2n+1) {
background: lightgrey;
}
.zebra2.hidden ~ .zebra2.hidden ~ .zebra2:nth-child(2n) {
background: lightgrey;
}
.zebra2.hidden ~ .zebra2.hidden ~ .zebra2:nth-child(2n+1) {
background: inherit;
}
And so on. This particular example breaks if there are more than 2 hidden items.
​
One possible solution:
use jQuery to change the .hidden element's type to, say, <li>. Use :nth-of-type instead of :nth-child.
http://jsfiddle.net/Nb68T/1/

Referencing class with additional class

I've got a jquery slider function on a page, and when the slide rotates I need the style of a LI tag to change.
So when the slider goes onto a li the class looks like this:
<li class="first sliderkit-selected">
And when it moves off it looks like this:
<li class="first">
But when the class goes to "first sliderkit-selected" I need it to be referenced from the style sheet but not sure how it is constructed, so far I've played around with:
li.sliderkit-selected li.first {
background-color: red;
}
But it doesn't seem to pick it up.
I know you could use a comma inbetween each class, but I want a style to be referenced exclusively when those two class's are together, if that makes any sense.
Thanks.
You're looking for li.sliderit-selected.first:
li.sliderkit-selected.first{
background-color: red;
}
See also:
CSS Selectors Level 3: Class selectors
The following rule matches any P element whose class attribute has been assigned a list of whitespace-separated values that includes both pastoral and marine:
p.pastoral.marine { color: green }
This rule matches when class="pastoral blue aqua marine" but does not match for class="pastoral blue".
To select a DOM element with multiple classes, concatenate the classes in the selector:
li.sliderkit-selected.first {
background-color: red;
}
If you want to select an element with multiple classes, you simply append the classes with a dot, like this:
li.first.sliderkit-selected { /* your rules */ }
This means "a li tag with the class first and the class sliderkit-selected".
You can write like this:
.sliderkit-selected.first {
background-color: red;
}
OR
.first.sliderkit-selected {
background-color: red;
}

Can I stop an element scrolling off the screen with CSS3?

I have a nested shopping-type list that is grouped by type (and has descriptions for each item).
What I'm wanting to do is have the last type scrolling in the list, until the point that it would scroll off the top of the list.
A list may declared as
<div id="items">
<item-type>Type A</item-type>
<description>a</description>
<description>b</description>
<description>c</description>
<item-type>Type B</item-type>
<description>d</description>
<description>e</description>
<description>f</description>
<description>g</description>
<description>h</description>
</div>
I'm using element types so that I can use #items > item-type:last-of-type in CSS3 to select the last element.
#items {
word-wrap: break-word;
overflow: auto;
height: 100%;
}
#items > * {
display: block;
}
#items > item-type:last-of-type {
position:absolute;
bottom: 100px;
}
So the only point now, is how do I keep it (effectively) position: relative; top: 0 to position: absolute; top: 0 using only CSS3?
I'm using FF4 and HTML5, so you can go all out; this won't be supported on older browsers. Also, using calc() is fine.
The valid view options are be something like:
______________________________________
Type A a Type B
a b e
b c f
c Type B g
d h
---------------------------------------
Where the lines are the visible area, and each column shows how it would appear given a certain amount of data (progression left to right)
If I understand the problem correctly, you want to create something like the iPhone Contacts list. Looking at the solution someone already built it uses JavaScript. Also, I've thought about it and gone through all the CSS3 specs but cannot determine anything that could be used here to achieve the same affect without JavaScript.
I knocked up a small demo, but again this uses JavaScript. I just don't think it's possible with pure CSS, although I'm sure someone will correct me if that's not the case :-)
HTML
<div id="items">
<item-type>Type A</item-type>
<description>a</description>
<description>b</description>
<description>c</description>
<item-type>Type B</item-type>
<description>d</description>
<description>e</description>
<description>f</description>
<description>g</description>
<description>h</description>
<description>i</description>
<description>j</description>
<description>k</description>
<description>l</description>
</div>
CSS
#items {
word-wrap: break-word;
overflow: auto;
height:100px;
border:1px dashed red;
width:200px;
}
#items > * {
display: block;
}
#items > item-type {
border:1px dashed blue;
background-color:#fff;
width:180px;
}
JavaScript (jQuery 1.6+)
var itemsTop = $('#items').position().top;
var itemTypeHeight = $('item-type').height();
var itemTypeBottom = itemsTop + itemTypeHeight;
$('#items').scroll(function() {
$('item-type').each(function() {
$(this).css({position:''});
if ($(this).position().top < itemsTop + itemTypeHeight) {
$(this).css({position:'fixed',top:itemsTop});
}
});
});
I think it's not possible for the following reasons (which may or may not be related):
When in normal viewing, a relative position is needed; at the top of the visible area, it would need to change to absolute
you could use calc() and min() or max() with the visible height, the current element's height and the current scroll position; except that none of these calculated properties are available to css
Another idea is making more absolute positioning of the 2nd item level, but there's no way of referencing the absolute-parent's height as well as the absolute-grandparent's height.
I think the first point is the easiest way to convince myself that it's not possible. The other two convince me that combinations of fancy css functions and absolute positioning are sunk as well.

Which attribute of a <div> tag should reference the CSS?

This is probably a case of trying to run before I can walk, however... I have the following code:
<div class="hidden" id="repair_complete">
// some code
</div>
I was under the impression that if my CSS file contained:
#hidden {
display: none;
}
... then the div content wouldn't display. However, it seems to only adopt this behaviour if the CSS file contains a reference to the div id:
#repair_complete {
display: none;
}
In a book I'm working through the opposite seems to be true - the style sheet refers to the class name, not the id.
Any ideas where I'm going wrong?!
Your CSS syntax is incorrect.
If you want to access this div, you can do it like this:
/* By class: */
.hidden {
display: none;
}
/* By ID: */
#repair_complete {
display: none;
}
Note that to access an element by class you use a dot before the class name. You use a hash before the ID.
The other answers have the technical stuff right: you need .hidden, not #hidden.
Now you have to decide whether you want to attach CSS to divs by class or id. I find classes are better in the long run, unless you are really certain that there will ever really and truly be one of the thing you are making.
Also, don't forget that you can attach more than one class to an element:
<div class="red fat shallow">blah blah</div>
Then you can style this element with any of these selectors:
.red {...}
.fat {...}
.shallow {...}
.red.fat {...} /* Applies only to things that are both red and fat */
.red.fat.shallow {...} /* Very specific */
/* etc. */
A "." before the name will refer to classes, and a "#" will refer to ids:
.hidden
{
display: none;
}
You need:
.hidden{
display:none;
}
period is a class specifier, pound sign is for id's.
To use class name use the dot.
i.e.
.hidden refers to the class name
#repair_complete refers to the id.
To refer to an element's ID you use the # selector, to refer to it's class name you use the . selector.
So in your example you would use
#repair_complete {
display:none;
}
or
.hidden {
display:none;
}