Avoiding styles for last element containing a certain class element - javascript

I have this following hierarchy, and this is used at several places (so to add a class to them via jQuery is not feasable).
<li class="paginable">
<span id="step-1" class="done"></span>
</li>
<li class="paginable">
<span id="step-2" class="done"></span>
</li>
<li class="paginable">
<span id="step-3" class="done"></span>
</li>
<li class="paginable">
<span id="step-4" class="not-done"></span>
</li>
<li class="paginable">
<span id="step-5" class="not-done"></span>
</li>
On the basis of the class done on element span, I have to provide certain style to those span[id^="step-"] which are also having the class done.
But not including the last span with class done.
How can I exclude the last span with class done. The classes done and not-dont changes in order like a series of steps.
I've tried:
span[id^="step-"].done:not(-- with lots of combinations of last child on parent as well as child --)
But it won't work and I logically know why.
Any suggestions CSS ONLY? or should I go and add class everywhere it is switched using jQuery?

I don't think a css only solution is available.
Using jQuery
$('span.done[id^="step-"]').not(':last').css('color', 'red')
Demo: Fiddle

Related

How would I apply classes to elements that are generated through a loop?

I have created some components through a loop
<li v-for="card in cardID" :key="card">
<app-profile class="profile" :id="cardID[i++]"></app-profile>
</li>
I want to have a div around all of them so that i can centre the div, but I can't seem to get it working. Any help would be appreciated!
To add a class to the generated list elements, you can use :class="someClassName" like this:
<li v-for="card in cardID" :key="card" :class="someClassName">
<app-profile class="profile" :id="cardID[i++]"></app-profile>
</li>
And you don't need to wrap a div around the list elements to center them. Just add the center styles to the parent <ul> element instead.

jQuery first element of type click

I am working through an issue where I have a menu that is mutli levels deep. I am trying to get it so that if a first level element is clicked (add class .ubermenu-active) it will look for any other first level element with that class and remove it.
$('.ubermenu-item-level-0 span').on('click',function() {
var target = $('.ubermenu-item-level-0');
$('.ubermenu li.ubermenu-item-level-0').removeClass('ubermenu-active');
target.parents('.ubermenu li.ubermenu-item-level-0').toggleClass('ubermenu-active');
});
HTML (mock):
<ul class="ubermenu">
<li class="ubermenu-item-level-0">
<a class="ubermenu-target">
<span class="ubermenu-target-title">Level 1</span>
</a>
<ul class="ubermenu-submenu">
<li class="ubermenu-item-level-1">
<a class="ubermenu-target">
<span class="ubermenu-target-title">Level 2</span>
</a>
</li>
<li class="ubermenu-item-level-1">
<a class="ubermenu-target">
<span class="ubermenu-target-title">Level 2</span>
</a>
<ul class="ubermenu-submenu">
<li class="ubermenu-item-level-2">
<a class="ubermenu-target">
<span class="ubermenu-target-title">Level 3</span>
</a>
</li>
</ul>
</li>
</ul>
<li class="ubermenu-item-level-0">
<a class="ubermenu-target">
<span class="ubermenu-target-title">Level 1</span>
</a>
</li>
</li>
</ul>
Right now if any of the sub elements are clicked the parent closes
Currently your target var is selecting all elements with class .ubermenu-item-level-0, so when you toggle the class you're toggling all parent elements. Your target var should be something relative to the element clicked, like var target = $(this).closest('.ubermenu-item-level-0');
So, your sample HTML isn't what I expected to see . . . specifically, your second <li class="ubermenu-item-level-0" . . . element is currently showing as a child under the first one, while your description makes it sound like they should be siblings.
For the sake of the solution I'm going to assume that those two lis are supposed to be siblings of each other and that somehow the code got mixed up. :)
So, here's how I would handle it . . .
var sFirstLevelMenuClass = ".ubermenu-item-level-0";
var sActiveMenuClass = "ubermenu-active";
var $firstLevelMenuOptions = $(".ubermenu").find(sFirstLevelMenuClass);
$firstLevelMenuOptions.children("a").children("span").on("click", function() {
$firstLevelMenuOptions.removeClass(sActiveMenuClass);
$(this).closest(sFirstLevelMenuClass).addClass(sActiveMenuClass);
});
Basically, I've simplified your logic and fixed one small issue that you had in your jQuery code.
Detailed Explanation
The issue was that when you used $('.ubermenu-item-level-0 span') as your selector for your change event. That translates to "any span element that is a descendant of a ubermenu-item-level-0 element". So, in addition to the spans that are directly under the ubermenu-item-level-0 list items, it was also picking up the ones under the ubermenu-item-level-1 and ubermenu-item-level-2 elements, since they are also descendants.
So, I changed your selector to $firstLevelMenuOptions.children("a").children("span") which translates to "all spans, that are direct children of an a, that is the direct child of an ubermenu-item-level-0 element" (Note: $firstLevelMenuOptions is set to equal $(".ubermenu").find(".ubermenu-active"); through the logic earlier in the code). This stops the selector from picking up the lower level spans.
Outside of that and trimming down some of your selectors to be more efficient, the only other thing that I changed was the flow of how the ubermenu-active class is manipulated. In my solution, there are two steps:
Remove ubermenu-active from ALL ubermenu-item-level-0 elements
Add ubermenu-active to the closest ubermenu-item-level-0 element to the span that was clicked (i.e., $(this))
That basically resets the list and then reselects the appropriate menu item to me active.
You can stop the event propagation:
event.stopPropagation()
Without seeing the full HTML, I was going to suggest trying this:
$('.ubermenu-item-level-0 span').on('click',function(e) {
e.stopPropagation();
var target = $('.ubermenu-item-level-0');
$('.ubermenu li.ubermenu-item-level-0').removeClass('ubermenu-active');
target.parents('.ubermenu li.ubermenu-item-level-0').toggleClass('ubermenu-active');
});

Something instead of <span> to wrap over an <ul> in a valid way

I have a dropdown <ul> inside a <span>. The reason is because I want the dropdown list to be as wide as the <span> text using width: 100%, and not hard px values, since the text varies in length on different pages.
Using an <ul> inside a <span> works but is not valid. What is valid is <u>, <small>, <b>, <strong> etc. but they have effects/style on the text which I don't want.
What I need is a dummy element like span, with no effects on the text that I can add my own classes to (for highlight). But it has to be a valid container for an <ul>.
Or some other good idea.
Currently:
<span class="hightlight"> My highlighted text
<ul class="dropdown">
<li> .. </li>
<li> .. </li>
<li> .. </li>
</ul>
</span>
The block-level counterpart of span is div. Neither of them has any impact on default rendering except that span is an inline element, div is a block element.
It is not clear why you need a container, since there is presumably some styling that causes some problem that you try to fix with a container. By default, ul is full-width, i.e. its width is the available width, i.e. width: 100%. And you can assign a class and properties directly on the ul element.
Regarding the other approaches considered in the question, u, small etc. cannot contain ul any more than span can, as per the specs. They have the same content model.
A <div> would be the equal. The <span> element is basically in inline <div> element.
You can use a DIV and display it as inline to not disrupt your current flow.
HTML:
<div class="hightlight"> My highlighted text
<ul class="dropdown">
<li> .. </li>
<li> .. </li>
<li> .. </li>
</ul>
</div>
CSS:
.highlight {
display: inline;
}
you can use strong if you want, and in css specify that .highlight { font-weight: normal } so it won't be bold anymore.

Styling a parent element of a child in CSS

I would really appreciate any help you could provide on this matter. I am trying to style the parent of a specific child element.
It seems that this might not be possible in CSS due to technical restraints, but I was wondering if there was a solution available in JavaScript that could achieve this?
I am trying to alter the parent <a> element of a <ul class="children"> child element, only when that <a> element has class="active". e.g. there will be other <a> elements with <ul> child elements which are not active that I don't want to be styled.
If you know of any solution that would be able to achieve this that would be much appreciated! Whilst I am familiar with CSS I am not competent enough in JavaScript to write this myself.
<ul class="menu">
<li>
<a class="active">Active Page</a>
<ul class="children">
<a>Something here </a>
</ul>
</li>
<li>
<a>Some Other Page</a>
<ul class="children">
<a>Something here</a>
</ul>
</li>
</ul>
I suggest you style a.active. (Or haven't I understood the question?)
I.e.
a.active {
background-color: pink;
}
There is no css selector to select parent elements. You should also give the parent element a selector you can use to style it.
Also see Is there a CSS parent selector? for more information on the parent selector subject.
May be you want this:
if($('ul.children a').hasClass('active')){
$('ul.children').sibling('a').addClass('active');
}
see:
I am trying to alter the parent <a> element of a <ul class="children">
while this is not true, <a> is the sibling in your case.
Why can't you do a style for the class active?
.active {
background-color: red;
}
As per your HTML you could style the exact parent element.
Your HTML nested tags are Ok.
No need of javascript
Your css rule should look something like this
a.active+ul.children { ...what ever .... }
(In order to style the UL class children when its sibling is a class active
I'm really confused by your question but your could give two class names to the same element. Like for the
<ul class="children">
You could name it to:
<ul class="children active">
Sorry, I read it again and again, and now I got it!
.menu>li>a.active{
font-weight:bold
}
It will select only the first-level "a.active" children from the first-level "li" children from ".menu" ;)
Hope it helps!

mcDropDown plugin: how to show parent node attributes?

I'm using the mcDropDown plugin which is very effective.
Without reporting all the code, I just put the jsfiddle example. http://jsfiddle.net/SwxP3/
What I want to do, and I wasted hours of trials, is to get the parent of the selected node.
Example
<li rel="1">
Arts & Humanities
<ul>
<li rel="2">
Photography
<ul>
<li rel="3">
3D
</li>
<li rel="4">
Digital
</li>
</ul>
</li>
<li rel="5">
History
</li>
<li rel="6">
Literature
</li>
</ul>
</li>
In such example, if I select "3D" I want to be able to retrieve the rel property of its parent.
I played a bit with the getValue function of mcDropDown plugin, without any success.
I saw that this plugin, in the dom tree, creates hidden elements reporting the list tree structure, and also the getValue functions uses them, but I couldn't find a way of retrieving the parent (I tried with the parent() function of jquery of course)...
Does anybody have an idea of how to get the parent?
I really need this feature, so if somebody has some sulution which includes NOT using mcDropDown but any other plugin (or creating a dropdown natively with css and jquery) it is wellcomed.
$(document).ready(function (){
$("#current_rev").html("v"+$.mcDropdown.version);
$("#category").mcDropdown("#categorymenu",{
select: function(value,name){
alert($("[rel="+value+"]").parents('li').attr("rel"))
}
});
});
This get's the rel of the parent. Undefined if the selected element doesn't have a parent.

Categories