How do I select only the first instance of a link containing a specific href, the solution can be css or javascript, I would prefer css as I need to make styling changes once I have selected the right link but I'm not even sure css can do what I need.
<ul class="digital-downloads">
<li> Link</li>
<li> Link</li>
<li> Link</li>
<li> Link</li>
<li> Link</li>
</ul>
As you can see by the code above, the first two links aren't identical but they have the same ending. I need a way to select only the first instance of a link containing download_file=936 or download_file=935 or download_file=932 etc.
The number of li's will always be different as well as the number of same links so I can't select the third li for example as the link href wont always be 935 on the third li, it could be 936 or 932 depending on the situation.
You can apply a filter against a jQuery selection, looping over them while comparing against the href from before:
var last;
var firsts = $(".digital-downloads li a").filter(function(){
var link = this.href.match(/download_file=\d+$/)[0];
if (link == last)
return false; // we had this before, don't select
else {
last = link;
return true; // we've found a new one!
}
});
In short and taking care of mismatched regex:
…
var m = this.href.match(/download_file=\d+$/);
return m && m[0] != last && (last=m[0],true);
…
$('a[href*="download_file=935"]:first')
To do it in just CSS gets really complicated.
Using JavaScript:
var first = document.querySelector('a[href$="936"]');
first.className = 'first';
JS Fiddle demo.
This approach adds a CSS class-name in order to allow CSS styling, so should combine the benefits of each approach, so long as the browser supports document.querySelector().
Use Regex:
$(function() {
var count = 0;
$('a').each(function() {
var match = $(this).attr('href').match(/(.*download_file=\d+)/);
if (match !== null && count == 0) {
alert(match.pop());
count++;
}
});
});
http://jsfiddle.net/vzJVa/
Related
I have a navagation list written with bootstrap css:
<ul class="nav navbar-nav navbar-right">
<li class="">Home</li>
<li class="">About</li>
</ul>
My question is how can I use javascript to add the class "active" to the "li" tags using javascript? I want it to have the active class on index.html for home and the same for about.html
Is this possible?
JavaScript
var siteList = document.URL.split("/");
var site = siteList[siteList.length - 1];
var list = document.getElementsByTagName("li");
for (var index = 0; index < list.length; index++) {
var item = list[index];
var link = item.firstElementChild;
var href = link ? String(link.href) : "-";
if (href.replace(".html","") === site) {
item.classList.add("open");
} else {
item.classList.remove("open");
}
}
Explanation
You can get the current URL using document.URL, you probably want the just the last part, so you'll have to split it and get the last part, which in your case will be index, about etc.
Then get all the li elements and iterate through them.
If they don't have an a child then ignore it.
If they do get the href attribute and remove the .html at the end.
If that text is the same as the site variable, then that means you should open the element, otherwise close it.
It's not clean, and there's probably a better way to do it, but:
HTML
<ul class="nav navbar-nav navbar-right">
<li id="navIndex" class="">Home</li>
<li id="navAbout" class="">About</li>
</ul>
JS (somewhere)
// Map ids with html page names
var pages = {
navIndex: "index.html",
navAbout: "about.html"
};
// Iterate over map
for(var property in pages) {
// Check to make sure that the property we're iterating on is one we defined
if(pages.hasOwnProperty(property)) {
// indexOf will be 0+ if it appears in the string
if(window.location.href.indexOf(pages[i]) > -1) {
// we can use property because we defined the map to be same as ids
// From https://stackoverflow.com/questions/2739667/add-another-class-to-a-div-with-javascript
var el = document.getElementById(property);
el.className += el.className ? ' active' : 'active';
break; // no need to keep iterating, we're done!
}
}
}
This is more or less a "dirty" approach because it requires more than just JavaScript to get to work (see Nick's answer for a cleaner implementation).
First we set identifiers on our <li> elements, then we map out those identifiers with their respective href attributes.
Once we have the <li>s mapped out, we then iterate over the map's keys (which we set to be the id attributes on our <li>s) and check if the href attribute is present within the site's window.location.href, if it is: add the active class and stop searching, otherwise we keep on trucking.
I'm trying to make controls for category list with sub-category and sub-sub-category lists.
Here's HTML:
<ul class="selectbox-ul">
<li>
<div>Category</div>
<ul class="selectbox-ul-child">
<li>
<div>Subcategory</div>
<ul class="selectbox-ul-child">
<li>
<div>Sub-subcategory</div>
</li>
</ul>
<span id="trigger">icon</span>
</li>
</ul>
<span id="trigger">icon</span>
</li>
....
</ul>
So my shot was to add class for ul.selectbox-ul-child :
var trigger = document.getElementById("trigger");
function subCatStatus() {
if(this.parentElement.children[1].className != "... expanded") {
this.parentElement.children[1].className += " expanded"
} else {
this.parentElement.children[1].className == "..."
};
};
trigger.addEventListener("click", subCatStatus);
And it works only for first span#trigger(that shows subcategories), next one (for sub-subcategories) does nothing (I've also tried to use .getElementsByClassName it didn't work for any of triggers) . So i'd like to get some explanation why doesn't this one work. And some advice how to make it work.
As others have already mentioned, you can't stack multiple elements with the same ID since document.getElementById() is not supposed to return more than one value.
You may try instead to assign the "trigger" class to each of those spans instead of IDs and then try the following code
var triggers = document.getElementsByClassName("trigger");
function subCatStatus() {
if(this.parentElement.children[1].className != "... expanded") {
this.parentElement.children[1].className += " expanded"
} else {
this.parentElement.children[1].className == "..."
};
};
for(var i = 0; i < triggers.length; i++) {
triggers[i].addEventListener("click", subCatStatus);
}
javascript getElementById returns only single element so it will only work with your first found element with the ID.
getElementsByClassName returns an array of found elements with the same class, so when adding listener to the event on element you would require to loop through this array and add individually to it.
I have two unordered lists, each filled with list items that have a DYNAMIC class name. When I say "dynamic" I mean they are not generated by me, but they don't change once the lists have been created. These class names are id's I'm getting from an API, so they're just random numbers. A simple example would be something like...
<ul class="listA">
<li class="123"></li>
<li class="456"></li>
<li class="789"></li>
</ul>
<ul class="listB">
<li class="789"></li>
<li class="101"></li>
<li class="112"></li>
</ul>
What I'm trying to do is compare the two lists, and have any matches be highlighted, in this case the items with the class "789" would match. When I say highlighted, I just mean I'll probably apply some css after a match is found, like maybe a background color or something (not too important yet). The problem really lies in the fact that the lists can be somewhat long (maybe 50 items) and the classes are just random numbers I don't choose, so I can't do any specific searches. Also, there will most likely be cases with multiple matches, or no matches at all.
I'm pretty new to jQuery, so there may be a fairly simple answer, but everything I find online refers to searching by a specific class, such as the .find() method. If anyone needs more info or a better example, I'll be happy to give more info, I'm just trying to keep it simple now.
Thanks so much in advance!
var $first = $('ul.listA li'),
$second = $('ul.listB li');
$first.each(function(){
var cls = this.className,
$m = $second.filter(function(){
return this.className === cls;
});
if ($m.length) {
$(this).add($m).addClass('matched');
}
});
http://jsfiddle.net/b4vFn/
Try it this way:
$("ul.listA li").each(function(){
var listAval = $(this).attr('class');
$("ul.listB li").each(function(){
if(listAval == $(this).attr('class')){
//matched..
return false; //exit loop..
}
}
}
you can find the code here: jsFiddle
var listA=$('.listA li')
var listB=$('.listB li')
listA.each(function(){
var classInA=$(this).attr('class');
listB.each(function(){
var classInB=$(this).attr('class');
if(classInA === classInB){
console.log(classInA);
//now you found the same one
}
})
})
Demo at http://jsfiddle.net/habo/kupd3/
highlightDups();
function highlightDups(){
var classes = [] ;
$('ul[class^="list"]').each(function(k,v){
//alert(v.innerHTML);
$($(this).children()).each(function(nK,nV){
// alert($(this).attr("class"));
classes.push($(this).attr("class"));
});
});
hasDuplicate(classes);
}
//Find duplicate picked from fastest way to detect if duplicate entry exists in javascript array?
function hasDuplicate(arr) {
var i = arr.length, j, val;
while (i--) {
val = arr[i];
j = i;
while (j--) {
if (arr[j] === val) {
// you can write your code here to handle when you find a match
$("."+val).text("This is Duplicate").addClass("match");
}
}
}
}
A slightly less verbose variant of Nix's answer:
$("ul.listA li").each(function(){
var a = $("ul.listB li").filter("." + $(this).attr('class'));
if (a.size()) {
a.add($(this)).css("background", "red");
}
});
I have the navigation bar as below
<ul>
<li class="selected"><a href=">My Profile</a></li>
<li>xxxx</li>
<li>mybook</li>
<li>Photos <span>4</span></li>
<li>Profile List</li>
</ul>
I want that if the url is www.abc.com/user/profile then profile tab class should have class selected attached
If photos then photo tab.
If we can have partial match that will be good but i am not sure if thats possible
like in url i have /user/book and myBook gets selected
Some elegant variant:
<ul class="menu">
<li><a class="profile" href="/user/profile">My Profile</a></li>
<li><a class="book" href="/user/book">My Book</a></li>
</ul>
$(document).ready(function () {
var page = document.location.href.split('/').slice(-1)[0];
$('.menu .' + page).addClass('selected');
});
You can grab the part you want with regex:
var userPage = /user\/(.+)/.exec(location.href)[1];
That will give you the part after user/. Then you could use a switch statement:
switch (userPage) {
case 'profile':
...
break;
case 'book':
...
break;
}
You would want to switch off of location.pathname. Granted that you give that <ul> a class of nav:
$(function () {
if (location.pathname.search("/user/profile") != -1) {
// page is /user/profile
$("#nav li").eq(0).addClass("selected");
} else if (location.pathname.search("/user/photos") != -1) {
// page is some/thing
$("#nav li").eq(3).addClass("selected");
}
... etc
});
Things to notice
We use $(function () {...}); as opposed to $(document).ready(function() {...});. It is less typing and more efficient
We use String.search(), which returns the index at which the string "/user/profile" appears. If the string is not found, String.search() will return -1, so if it != -1, it exists.
We also use jQuery.eq( index ) this treats elements selected by a jQuery selector as an array and returns the element of the specified index.
References
Check out jQuery's .eq here, and JavaScript's String.search here
I have ul list and I need to change the class of one of <li> tags with javascript:
<ul>
<li>...</li>
<li class="something"> <- need to change this class to "myclass" (javascript goes here)</li>
<li>..</li>
</ul>
Thank you.
using jQuery (naturally):
$(function(){
$("li.something").removeClass("something").addClass("myclass");
});
As there seems to be alot of jquery answers and it's not always possible to use jquery (for example if your customer/company won't let you use it arrgh!), here is a plain javascript example.
// Where 'e' is the element in question, I'd advise using document.getElementById
// Unless this isn't possible.
// to remove
if ( e.className.match(/something/) ) {
e.className = e.className.replace("something", "")
}
// to add back in
if ( !e.className.match(/something/) ) {
e.className += " something"
}
This will work with multiple classes, for example:
<li class="something another">...</li>
Using regular javascript:
var listitems = document.getElementsByTagName("li");
for (int i = 0; i < listitems.length; i++)
{
if (listitems[i].className == "something")
{
listitems[i].className = "new class name";
break;
}
}
If your <li> tag had an id attribute, it would be easier, you could just do
document.getElementById("liID").className = "newclassname";
Using JQuery:
$('ul li:nth-child(2)').attr('class', 'myclass');