I have a list that is kind of like this:
<li class="listElement semiUniqueCLassOne" unique-class="semiUniqueCLassOne" style="display:none;">one</li>
<li class="listElement semiUniqueCLassOne" unique-class="semiUniqueCLassOne" style="display:none;">two</li>
<li class="listElement semiUniqueCLassOne" unique-class="semiUniqueCLassOne" style="display:none;">three</li>
<li class="listElement semiUniqueCLassTwo" unique-class="semiUniqueCLassTwo" style="display:none;">four</li>
<li class="listElement semiUniqueCLassTwo" unique-class="semiUniqueCLassTwo" style="display:none;">five</li>
<li class="listElement semiUniqueCLassThree" unique-class="semiUniqueCLassThree" style="display:none;">six</li>
I'm trying to only show the first of each of the semiUniqueCLass so I'm attempting to do it like this:
$('.listElement').each(function(){
var uniqueClass = $(this).attr('unique-class');
if($('.'+uniqueClass).is(':first')){
$(this).show();
}
});
this doesn't work... what ways can I make it work? tried several, a bit stuck.
This should do the trick:
$('.listElement').hide();
$('.listElement:first-child').show();
If there's more elements with the listElement class:
$('.listElement[#class*=semiUniqueCLass]').hide();
$('.listElement[#class*=semiUniqueCLass]:first-child').show();
(Only shows / hides listElements that have a class that contains semiUniqueCLass)
To show the first of each unique semiUniqueCLass* item, take a look at Jack's Answer or xdazz's answer.
Just use the .first() method.
$('.listElement').each(function(){
var uniqueClass = $(this).attr('unique-class');
$('.'+uniqueClass).first().show();
});
And the working demo.
Another solution is shown as below:
var clazzs = $('.listElement').map(function() {
return $(this).attr('unique-class');
});
$.unique(clazzs).each(function() {
$('.'+this).first().show();
});
Also the working demo.
To show the first of each unique semiUniqueCLass* item, you'd have to iterate over all relevant .listElement nodes manually:
var shown = {}; // keep track of which class has already been shown
$('.listElement[unique-class]').each(function() {
var className = this.getAttribute('unique-class');
if (!shown[className]) {
// this class has not been seen before, show the first only
shown[className] = true;
$(this).show();
}
});
It shows elements one, four and six.
Update
I've pitted this answer against the two solutions by xdazz using this jsperf benchmark. This answer comes out on top with the runner up being ~30% slower (in Chrome).
This code shows the first item :
$('[class^=listElement]').first().show();
Related
The comparison table I am using is here:
https://codepen.io/adrianjacob/pen/KdVLXY
When I duplicate the tables and the viewer goes mobile responsive; the buttons are only working for the first table.
Is there any classes or such I can add to the JavaScript and HTML so I can make each group of buttons specific to their table?
Button code:
<ul>
<li class="bg-purple">
<button>Self-Employed</button>
</li>
<li class="bg-blue">
<button>Simple Start</button>
</li>
<li class="bg-blue active">
<button>Essentials</button>
</li>
<li class="bg-blue">
<button>Plus</button>
</li>
JavaScript code:
// DIRTY Responsive pricing table JS
$( "ul" ).on( "click", "li", function() {
var pos = $(this).index()+2;
$("tr").find('td:not(:eq(0))').hide();
$('td:nth-child('+pos+')').css('display','table-cell');
$("tr").find('th:not(:eq(0))').hide();
$('li').removeClass('active');
$(this).addClass('active');
});
// Initialize the media query
var mediaQuery = window.matchMedia('(min-width: 640px)');
// Add a listen event
mediaQuery.addListener(doSomething);
// Function to do something with the media query
function doSomething(mediaQuery) {
if (mediaQuery.matches) {
$('.sep').attr('colspan',5);
} else {
$('.sep').attr('colspan',2);
}
}
// On load
doSomething(mediaQuery);
I'd really appreciate any help, thanks for your time.
The problem is that your jQuery targets are currently too generic, so when you have multiples, it only finds content from the first one and puts it in both. What your script does is update both tables.
I've forked the Codepen, added a second table, and tweaked a couple of values on our comparison table, so you should see different things in each (and each set of tabs acts separately)
https://codepen.io/CapnHammered/pen/QzBbqN
Key part you're missing is some form of parent selector - in this case, we've used an article tag to wrap our table:
$( "ul" ).on("click", "li", function() {
var pos = $(this).index()+2;
$parent = $(this).closest('article');
$parent.find("tr").find('td:not(:eq(0))').hide();
$parent.find('td:nth-child('+pos+')').css('display','table-cell');
$parent.find("tr").find('th:not(:eq(0))').hide();
$parent.find('li').removeClass('active');
$(this).addClass('active');
});
Try this:
$("ul").on("click", "li", function(e) {
var $clicked = $(e.currentTarget); // This will give you the clicked <li>
var $ul = $clicked.parent();
var $table = $ul.next(); // Only works if the table immediately follows the <ul>
var pos = $clicked.index() + 2;
$table.find("tr").find("td:not(:eq(0))").hide();
$table.find("td:nth-child(" + pos + ")").css("display", "table-cell");
$table.find("tr").find("th:not(:eq(0))").hide();
$clicked.siblings().removeClass("active");
$clicked.addClass("active");
});
Basically, when you click a <li> you should search the next table and show/hide the information only on that table. Before you were selecting all <tr> elements so it would affect all tables in the page.
EDIT: after re-reading your question this sentence left me confused:
When I duplicate the tables and the viewer goes mobile responsive; the buttons are only working for the first table.
When I try to duplicate the tables in your codepen the buttons work for both tables, not sure if I'm understanding your problem.
I'm trying to filter collections of data using quicksand.js. However, I'm having problems getting my data to appear. I have been able to get the data to disappear. Yet, it won't re-appear. I've created a jsfiddle, which is available here. Basically, my JavaScript looks like this:
var $content = $('#stage');
var $data = $content.clone();
function filterData(tag) {
var data = [];
if (tag === null) {
data = $data.find('li');
} else {
data = $data.find('li[data-tags=' + tag + ']');
}
console.log(data);
$content.quicksand(data, {
duration: 800,
easing: 'easeInOutQuad'
});
return false;
}
Everything looks correct to me. I can't figure out what I'm doing wrong.
First, your fiddle is broken. One, you link quicksand 1.3 and pair it with a recent jquery version it doesn't support. Two, you call out the easeInOutQuad without linking the jquery.easing.1.3.js. Three, you have scope issues, the filterData function is not defined globally.
Your real problem, though, is this line in the documentation:
attribute – attribute containing unique value able to identify same item within source and destination collection, default: 'data-id'
None of your "stage" data lis have this attribute so it won't filter them properly. Add it and all seems to work:
<ul id="stage">
<li data-tags="A" data-id="1">Item A-1</li>
<li data-tags="A" data-id="2">Item A-2</li>
<li data-tags="B" data-id="3">Item B-1</li>
<li data-tags="B" data-id="4">Item B-2</li>
</ul>
Updated fiddle.
I have a typical menu structure -
<Ul class="nav">
<li>Menu1</li>
<li>menu2</li>
-------
</ul>
When I click on certain menu, as per my jquery written on load of layout.html, it selects particular menu.
<script>
jQuery(function(){
jQuery('.nav>li>a').each(function(){
if(this.href.trim() == window.location)
$(this).addClass("selected");
});
</script>
But on that page if I click on certain link which takes me on some other page and then when I come back the menu item does not remain selected.
How can I modify my jquery to achieve this?
Thanks in advance !
As SJ-B is saying, HTML5 Web Storage is a good solution.
If you don't intend to click more than one or two pages away from the page with your list menu, you could add a query to the link that takes you away form the page e.g. the id of one of your list menus.
href="somepage.html could become something like this href="somepage.html?menu_id=menu5
When using window.history.back(), you could then fish the id out of the URL using window.location.search and use id to select the list menu.
You can use simple css code. Use active attribute like
a:active
{
//Some style
}
You can use below code to achieve this.
var lastele=siteurl.substring(siteurl.lastIndexOf("/")+1);
jQuery(".nav>li> a").each(function(){
var anchorhref=jQuery(this).attr("href");
var finalhref=anchorhref.substring(anchorhref.lastIndexOf("/")+1);
if(finalhref==lastele){
jQuery(this).addClass("selected");
}
});
I would do something like this :
<ul class="nav">
<li id="home">Home</li>
<li id="contact">Contact</li>
</ul>
Javascript :
// http://mywebsite.com#home
// location.hash === '#home'
jQuery('.nav ' + location.hash).addClass('selected');
Try to use Session Object of HTML5.
sessionStorage.varName = id of selected item.
on load just check if the sessionStorage.varName has value or undefined, if not then get the value
`var value = sessionStorage.varName;` and set it.
Well there could be many ways, on which is this which i like and always use:
It works when you path name is same as your link name For e.g. yourwebsite.com/Menu1
function setNavigation() {
var n = window.location.pathname,t;
n = n.replace("/", "");
t = $("ul li:contains(" + n + ")");
t.addClass("active");
}
You can than define styling in your active class as you like.
I stumbled upon this when googling for something similar. I have a JQueryUI accordion menu. My menu is in an included script (classic asp), so it is on every page but I think it is a similar situation. I cobbled something together based on SJ-B's answer (don't know why it was down voted).
I have this:
function saveSession(id) {
if (window.sessionStorage) {
sessionStorage.activeMenu = $("#jqmenu").accordion("option", "active") ;
sessionStorage.activeLink = id ;
}
}
and this
$(function() {
//give every li in the menu a unique id
$('#jqmenu a').attr('id', function(i) {
return 'link'+(i+1);
});
var activeMenu = 0;
var activeLink = "";
if (window.sessionStorage) {
activeMenu = parseInt(sessionStorage.activeMenu);
activeLink = sessionStorage.activeLink;
}
$("#" + activeLink).parent().addClass("selectedmenu");
$("#jqmenu").accordion({collapsible: true, active: activeMenu, heightStyle: "content", header: "h3"});
$("#jqmenu a").click(function() { saveSession($(this).attr('id')); });
});
OK, a bit untidy and cobbled together from various suggestions (I'm still learning), but it seems to work. Tried on IE11 and Firefox. Chrome can't find localhost but that's another story.
add lines below
<script>
$(function(){
$("a[href='"+window.location+"']").addClass("selected");
});
</script>
var url = window.location.pathname,
urlRegExp = new RegExp(url.replace(/\/$/, '') + "$");
$('.nav li').each(function () {
if (urlRegExp.test(this.href.replace(/\/$/, ''))) {
$(this).addClass('active');
}
});
I have jQuery read some text then add a class based on the value of this text. (The text read is rendered by my CMS).
The HTML Looks like this:
<ul class="zoneSubscriptions">
<li>
<ul>
<li class="zoneName">Professional</li>
<li>Never</li>
</ul>
</li>
<li>
<ul>
<li class="zoneName">RTTM</li>
<li>Never</li>
</ul>
</li>
</ul>
I want to read the text of class="zoneName"and add a class based on this.
JS to do this:
$(function() {
var zone = $( ".zoneName" ).text();
$( "#zones" ).addClass( zone );
});
This works without issue, however, I need it to add two classes, Professional and RTTM. What it adds is ProfessionalRTTM.
My question is how would I add the classes while keeping a space between the words?
In other words it should render like this: class="Professional RTTM" not class="ProfessionalRTTM"
Note: In my example there are two "zoneName"s. There could be anywhere from 1 to 5 or more when used live.
Try iterating the tags:
var $zones = $("#zones");
$(".zoneName").each(function () {
$zones.addClass( $(this).text() );
});
Also possible (if you want to reuse the list of class names)
var classes = [];
$(".zoneName").each(function () {
classes.push($(this).text());
});
$("#zones").addClass(classes.join(" "));
You're calling .text() on multiple results which is joining them together.
Why not do something like this instead:
var zone = $( ".zoneName" ).each(function(){
$("#zones").addClass($(this).text());
});
Find all your .zoneNames and then call addClass for each one.
jsFiddle example
You need to iterate across the .zoneNames, otherwise your .text() will be a one undivided string (unless you have whitespace in there)
$(".zoneName").each(function() {
$("#zones").addClass($(this).text());
});
You can use the callback function of addClass(), and use map() to get an array of the text, then simply join with a space:
$('#zones').addClass(function() {
return $('.zoneName').map(function() {
return $(this).text();
}).get().join(' ');
});
Here's a fiddle
The easiest way to see the problem is checking the code here: http://www.studioimbrue.com/beta
What I need to do is once a thumbnail is clicked, to removed the "selected" class from all other thumbnails that are in this same or without removing them from the other galleries on the page. Right now, I have everything working except the class removal. Someone helped me in another question but wasn't quite specific enough (my javascript skills aren't all that great!) I'm using jQuery. Thanks for the help.
Well in that case, I'm not sure why this doesn't work properly:
$(document).ready(function(){
var activeOpacity = 1.0,
inactiveOpacity = 0.6,
fadeTime = 100,
clickedClass = "selected",
thumbs = ".thumbscontainer ul li img";
$(thumbs).fadeTo(1, inactiveOpacity);
$(thumbs).hover(
function(){
$(this).fadeTo(fadeTime, activeOpacity);
},
function(){
// Only fade out if the user hasn't clicked the thumb
if(!$(this).hasClass(clickedClass)) {
$(this).fadeTo(fadeTime, inactiveOpacity);
}
});
$(thumbs).click(function() {
// Remove selected class from any elements other than this
var previous = $(thumbs+'.'+clickedClass).eq();
var clicked = $(this);
if(clicked !== previous) {
previous.removeClass(clickedClass);
}
clicked.addClass(clickedClass).fadeTo(fadeTime, activeOpacity);
});
});
I see you're using jQuery (and have edited your question accordingly).
With jQuery, it's really easy to get a list of matching elements using CSS syntax:
var list = $('#parentId > .selected');
That gets a list of the direct children of the element with the ID "parentId" that have the class "selected". You can then do things with them, such as:
list.removeClass("selected");
Then add "selected" to the element you want to select.
Edit I think this should do it:
$(thumbs).click(function() {
// Remove selected class from any elements other than this
var clicked, previous;
clicked = $(this);
if (!clicked.hasClass(clickedClass)) {
previous = $(thumbs+'.'+clickedClass);
previous.removeClass(clickedClass).fadeTo(fadeTime, inactiveOpacity);
clicked.addClass(clickedClass).fadeTo(fadeTime, activeOpacity);
}
});
I'm assuming there that the "selected" class isn't necessary for the fade effect to look right.
Note how the above will completely ignore the click if the clicked element already has the class. If you don't want that, remove the hasClass check and add .not(clicked) to the end of the previous = $(thumbs+'.'+clickedClass) line, but I don't know what your fade in would do at that point if you've already done it once.
I'm not getting the hover stuff; I thought you wanted this to happen on click, not hover.
You should take a look at
jQuery.removeClass()
So the point would be to first iterate trough all the images and unset the classname and than set the class on the active one.
Use .closest('.jcarousel-clip') to get the parent div,
then find all the thumbnails and use .removeClass('selected').
Hi Andy it isn't clear your question, but I am going to try to help you.
I am trying to help, and my skills on javascript arent that good either, plus I am not sure if I undertood the question right, please, dont vote me down.
function focusme(){
document.getElementById("focusme").focus();
}
function changeToCurrent(obj){
var menucont = document.getElementById('menu');
var arrLink = menucont.getElementsByTagName('a');
for (var i = 0 ; i < arrLink.length; i++){
arrLink[i].className='';
}
obj.className = "current";
}
<div class="menu" id="menu" >
<a href='' id='focusme' onclick='changeToCurrent(this)'>link1</a>
<a href='' onclick='changeToCurrent(this)'>Once Only link2</a>
<a href='' onclick='changeToCurrent(this)'>link3</a>
<a href='' onclick='changeToCurrent(this)'>link4</a>
<a href='' onclick='changeToCurrent(this)'>link5</
link6
</div>
Hope it helps.