So i'm just starting to discover how awesome jquery is and how a basic function can drive me nuts to understand. I'm trying to highlight a div with a specific "id" generated via backend
<br/><br/><br/><br/>
<div id="id_1">
<h2>id_1 -
<a class="marker_id_1" href="#top" name="id_1" id="id_1">Top</a>
</h2>
</div>
<div id="id_1">
<h2>id_1 -
<a class="marker_id_1" href="#top" name="id_1" id="id_1">Bottom</a>
</h2>
</div>
<div id="id_2">
<h2>id_2 -
<a class="marker_id_2" href="#top" name="id_2" id="id_2">Top</a>
</h2>
</div>
<div id="id_2">
<h2>id_2 -
<a class="marker_id_2" href="#top" name="id_2" id="id_2">Bottom</a>
</h2>
</div>
So if I hover over the "id_1" Top , I want to highlight both the "id_1" Top and Bottom. Below is a link to that so it'll be easier to understand.
http://jsfiddle.net/4PgC6/66/
Thanks!!
You must not use same id for different element.
Using name you can do
$('a').hover(function() {
var name = this.name;
$('a[name='+ name +']').css('color', '#f00')
},function() {
var name = this.name;
$('a[name='+ name +']').css('color', 'blue')
});
DEMO
Using class
$('a').hover(function() {
var className = this.className;
$('a.' + className).css('color', '#f00')
},function() {
var className = this.className;
$('a.' + className).css('color', 'blue')
});
DEMO
if you want to use .on() for hover then use
$('a').on('hover', function(e) {
if (e.type == 'mouseenter') {
var divName = this.name;
console.log(divName);
$('div', 'td.' + divName).addClass('match-highlight');
} else {
var divName = this.name;
$('div', 'td.' + divName).removeClass('match-highlight');
}
});
DEMO
$('div').mouseenter(function() {
var hoveredid = $(this).attr('id');
$('[id='+hoveredid+']').each(function() {
$(this).addClass("highlighted");
});
}).mouseleave(function() {
var hoveredid = $(this).attr('id');
$('[id='+hoveredid+']').each(function() {
$(this).removeClass("highlighted");
});
});
As mentioned, id should be unique. But if it isn't I found accessing using '[id=' rather than '#' you are able to access all divs, since you are looking at id as an attribute. (See: http://jsfiddle.net/4PgC6/68/)
First of all you cant have same same ID for a and div. Id should be unique.
Use data for that instead. Like that:
and then read it in script like that:
$('a').hover(function() {
divID = $(this).data('id');
$('#'+divId).css('color', '#f00');
},function() {
divID = $(this).data('id');
$('#'+divId).css('color', 'blue');
});
http://jsfiddle.net/acrashik/4PgC6/69/
Related
I'm pretty new to the world of jQuery and having some difficulty with a cart feature I am trying to add to a website.
I have created a function to add an element (based on its id) to the cart. This works fine. However when I try to reverse it (say someone clicks on the cart icon again to remove it) the cart count increases more and the class doesn't change back.
You will see in my code I am changing the classes for visual representation (unselected = svg with no fill & selected = svg with fill).
I have tried toggling the class, removing and adding the class but I can't think of much more. Any help would be greatly appreciated!
$(document).ready(function() {
var cart = [];
$("a.addToCart").click(function(event) {
var pressedId = event.target.id;
$("#cart_button").removeClass("hidden");
$("#" + pressedId).removeClass("addToCart");
$("#" + pressedId).addClass("addedToCart");
cart.push(pressedId)
$('.cart--counter').html(cart.length);
});
});
$(document).ready(function() {
$("a.addedToCart").click(function(event) {
var unpressedId = event.target.id;
$("#" + unpressedId).addClass("addToCart");
$("#" + unpressedId).removeClass("addedToCart");
cart.splice( $.inArray(unpressedID,cart) ,1 );
$('.cart--counter').html(cart.length);
});
});
Here is an example of the HTML with a class and ID.
<a id="12" class="addToCart">
Again, for clarification: the class changes appropriately from "addToCart" to "addedToCart" but is not reversible & the array is successfully updated with appropriate "ID" but can not be removed again.
Your issue is that when you add your event handlers, there are no elements with class addedToCart, so no event handlers get assigned. You need to use a delegated event handler instead:
var cart = [];
$(document).ready(function() {
$(document).on('click', "a.addToCart", function(event) {
var pressedId = event.target.id;
$("#cart_button").removeClass("hidden");
$("#" + pressedId).removeClass("addToCart");
$("#" + pressedId).addClass("addedToCart");
cart.push(pressedId)
$('.cart--counter').html(cart.length);
$('#cart').html(cart.toString());
});
});
$(document).ready(function() {
$(document).on('click', "a.addedToCart", function(event) {
var unpressedId = event.target.id;
$("#" + unpressedId).addClass("addToCart");
$("#" + unpressedId).removeClass("addedToCart");
cart.splice($.inArray(unpressedId, cart), 1);
$('.cart--counter').html(cart.length);
$('#cart').html(cart.toString());
});
});
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a id="12" class="addToCart">Item 12</a><br />
<a id="13" class="addToCart">Item 13</a>
<div class="cart--counter">**</div>
<br />
<div id="cart"></div>
<br />
<div id="cart_button" class="hidden">cart button</div>
I have an HTML structure like this:
<div id="tip1">
<div class="tip-icon"></div>
</div>
<div id="tip2">
<div class="tip-icon"></div>
</div>
<div id="tip3">
<div class="tip-icon"></div>
</div>
<div class="1 content"></div>
<div class="2 content"></div>
<div class="3 content"></div>
And I have a jQuery function like this:
$('.tip-icon').mouseenter(function() {
$('.1').addClass('tip-show'); //Change .1 to a variable
});
$('.tip-icon').mouseleave(function() {
$('.1').removeClass('tip-show2'); //Change .1 to a variable
});
But instead of having $('.1'), I want it to be the class numbers 1-3 depending on which "tip-icon" was hovered. I need to make is so that on "tip-icon" mouseenter it will take the parent div's id and delete the first 3 letters so that it is just the number left and store it into a variable. I then want to take this variable and use it in $('???').addClass('tip-show'); so that the ??? are replaced by the variable to make it so that one of divs with the classes 1-3 will get the 'tip-show' class added depending on which 'tip-icon' was hovered.
https://jsfiddle.net/oak4L9ga/
Dont do all that string mashing just to get the id out of the class. Instead tie your elements/functionality together using data-* attributes
<div id="tip1" data-tipid="1">
<div class="tip-icon"></div>
</div>
Then you can use that within your code to get the right id (actually, in your case class name)
$('.tip-icon').mouseenter(function () {
var tipId = $(this).parent().data('tipid');
$('.' + tipId).addClass('tip-show'); //Change .1 to a variable
});
Live example: https://jsfiddle.net/oak4L9ga/6/
You don't need to hack around the string of the class attribute as you can simply use index() to retrieve a numerical value representing the position of an element within a selector. Try this:
$('.tip-icon').on({
mouseenter: function () {
$('.' + ($(this).index('.tip-icon') + 1)).addClass('tip-show');
},
mouseleave: function () {
$('.' + ($(this).index('.tip-icon') + 1)).removeClass('tip-show');
}
});
Example fiddle
This can then be made shorter by using hover and toggleClass:
$('.tip-icon').hover(function () {
$('.' + ($(this).index('.tip-icon') + 1)).toggleClass('tip-show');
});
Example fiddle
Just make use of html5 data attribute:
Fiddle here: https://jsfiddle.net/oak4L9ga/8/
you can use hover for this as combination of mouseenter and mouseleave. Use regex to get the number in the id of parent.
$('.tip-icon').hover(function () {
var id = $(this).parent().attr('id').replace(/[a-z]/ig, '');
// Get the number from the id
$('.' + id).addClass('tip-show').show();
}, function () {
$('.content').removeClass('tip-show').hide();
});
Demo: https://jsfiddle.net/tusharj/oak4L9ga/9/
try
$(".tip-icon").hover(
function () {
$('.' + $(this).parent().attr("id").replace('tip', '')).addClass('tip-show');
}, function () {
$('.' + $(this).parent().attr("id").replace("tip", "")).removeClass('tip-show');
});
Updated Fiddle
Like this you mean?
$('.tip-icon').mouseenter(function() {
var id = $(this).parent().attr('id').substring(3, 1);
$('#'+id).addClass('tip-show');
});
Using JQuery chaining concept.
Check JQuery:
$('.tip-icon').mouseenter(function () {
var idValue = $(this).parent('div').attr('id').substr(3, 4);
$('.'+idValue).addClass('tip-show');
});
$('.tip-icon').mouseleave(function () {
var id_Value = $(this).parent('div').attr('id').substr(3, 4);
$('.'+id_Value).removeClass('tip-show');
});
Demo:
https://jsfiddle.net/oak4L9ga/11/
I have a selection of divs with the exact markup below and I want to create an unordered list above those divs that will provide the ground work for a 'tab' system - all without modifying the below markup.
<div id="category_1">
<h3 class="maintitle">
<a class="toggle">..</a>
Cat 1 Title
</h3>
<div>
...
</div>
</div>
<div id="category_2">
<h3 class="maintitle">
<a class="toggle">..</a>
Cat 2 Title
</h3>
<div>
...
</div>
</div>
<div id="category_3">
<h3 class="maintitle">
<a class="toggle">..</a>
Cat 3 Title
</h3>
<div>
...
</div>
</div>
And I want to create with jQuery or just pure JS if easy enough:
<ul>
<li>Cat 1 Title</li>
<li>Cat 2 Title</li>
<li>Cat 3 Title</li>
</ul>
The rel would be the ID of the div so I know which tabs to show / hide later on.
The value of the LI item would be the text of the second anchor within the H3 of the original code.
Cheers.
Try this:
$(function () {
var $uls = $('<ul/>');
$('[id^=category]').each(function () { // Provide a container that hold the div as context.
var anch = $(this).find('h3 a').eq(1).clone(); //clone your anchor the second one in h3
anch[0].rel = this.id; // set the rel with the id
$('<li/>').append(anch).appendTo($uls); // append to temp ul
});
$('body').append($uls); // Append anywhere you want
});
http://jsfiddle.net/XmarF/
If you don't want to clone your anchor then you can try this too..
$(function () {
var $uls = $('<ul/>');
$('[id^=category]').each(function () {
$('<li/>').append($('<a/>', {
href: '#',
rel: this.id,
text: $(this).find('h3 a').eq(1).text()
})).appendTo($uls);
});
$('body').append($uls);
});
$('body').prepend($("<ul class='menu'>"));
$('div a[href]').each(function () {
var el = $(this).clone().attr('rel', $(this).closest('div').attr('id'))
el = $('<li></li>').append(el);
$('ul.menu').append(el);
});
Demo ---> http://jsfiddle.net/ht3Y7/
You could do something like this:
$('div[id^="category_"]').each(function(){
var id = $(this).attr('id');
var title = $(this).children('h3').find('a').eq(1).text();
var listItem = $("<li><a href='#'></a></li>");
listItem.find('a').attr('rel',id).text(title);
$('ul').append(listItem);
});
Fiddle
You could try using jQuery's .replaceWith() method. It will replace a current HTML with one you desire. So if your divs were in a wrapper with a name you could do something like:
$("#wrapperID > div").each(function(i) {
var li = $("<li />").html($(this).html());
$(this).replaceWith(li);
});
var ul = $("<ul />", { id: 'wrapperID ' }).html($("#wrapperID ").html());
$("#wrapperID ").replaceWith(ul);
|OR| if you're looking to convert to that exact markup, again I assume all divs in some type of wrapper with ID (for simplicity):
$("#wrapperID > div").each(function(i) {
var li = $("<li />"),
a = $("<a />", { href: "#", rel: $(this).prop("id"), text: $(this).find("a").last().text() }).appendTo(li);
$(this).replaceWith(li);
});
var ul = $("<ul />", { id: 'wrapperID ' }).html($("#wrapperID ").html());
$("#wrapperID ").replaceWith(ul);
See Working Example Here
With no jQuery, this will work in IE8 and up.
var divs = document.querySelectorAll("div[id^=category_]");
var ul = divs[0].parentNode.insertBefore(document.createElement("ul"), divs[0]);
for (var i = 0; i < divs.length; i++) {
ul.appendChild(document.createElement("li"))
.appendChild(divs[i].querySelector("a[href='#']").cloneNode(true))
.rel = divs[i].id
}
DEMO: http://jsfiddle.net/ENvNq/1/
You can do it in three lines (and maybe less):
var html='';
$('div[id^="category"]').each(function () {html += '<li>' + $(this).find('a.toggle').next().text() + '</li>';});
$('#category_1').before('<ul>'+html);
jsFiddle example
I'm trying to select a specific class (in this case page1, page2, page3 etc.)
I've written this code that works fine for a single class, i've tried using .match() to exclude the .plink class picked up in dis but can't get it working.
$(function(){
$("a.plink").click(function() {
var dis = $(this).attr("class"); // This is the problem line, I need it to contain 'page1' ONLY. Not 'page1 plink'.
$("#page1,#page2,#page3").hide();
$("#" + dis).show();
return false;
});
});
The HTML that is associated with this is:
<div id="page-links">
<a class="page1 plink" href="#">About</a>
<a class="page2 plink" href="#">History</a>
<a class="page3 plink" href="#">Backstage</a>
</div>
EDIT:
These are the DIV's being shown and hidden:
<div id="page1">
<?php include_once("page1.php");?>
</div>
<div id="page2">
<?php include_once("page2.php");?>
</div>
<div id="page3">
<?php include_once("page3.php");?>
</div>
Is there a simple way to achieve this without regular expression matching?
$(function(){
var pages = $('div[id^=page]');
$("a.plink").click(function() {
var dis = $(this).attr("class").replace(' plink', '');
pages.hide().filter('#' + dis).show();
return false;
});
});
This should be
$("." + dis).show();
for class and in your example there are all classes.
As you mentioned simple way so it could be
$("a.plink").click(function() {
$(".plink").hide();
$(this).show();
return false;
});
According to your question after edit
$("a.plink").click(function() {
$('div[id^="page"]').not('#page-links').hide();
pid=$(this).attr('class').split(' ')[0];
$('#'+pid).show();
return false;
});
Here is a fiddle.
The JavaScript code is not correct. With the "#" you select ids from the html-element.
As you have only classes, the right way is to do it with "."
So this would be correct:
$(function(){
$("a.plink").click(function() {
var dis = $(this).attr("class");
$(".page1,.page2,.page3").hide();
$("." + dis).show();
return false;
});
});
I didn't test it, but I think you have to change something with the var dis.
If you click on .page1, the variable dis would contain "page1 plink".
$("." + dis).show();
would be
$(".page1 plink").show();
So I recommend to split the two classes, as it should be like
$(".page1 .plink").show();
You are trying to associate functionality of a click by appending classes. It would make more sense to put id of the div you want to show in the href
html:
<div id="page-links">
<a class="plink" href="#page1">About</a>
<a class="plink" href="#page2">History</a>
<a class=" plink" href="#page3">Backstage</a>
</div>
<div id="page1">
Content 1
</div>
<div id="page2">
Content 2
</div>
<div id="page3">
Content 3
</div>
javascript:
jQuery(function ($) {
var pages = [];
function showPage(page) {
var i;
for(i = 0; i < pages.length; i++)
{
if(page === pages[i]) {
$(pages[i]).show();
} else {
$(pages[i]).hide();
}
}
}
// Store each href in a pages array and add handlers
$('.plink').each( function() {
var page = $(this).attr('href');
pages.push(page);
$(this).attr('href', '#');
$(this).click(function () {
showPage(page);
});
});
// show the first page
if(pages.length > 0) {
showPage(pages[0]);
}
});
Example:
http://jsfiddle.net/38qLB/
And just so I don't avoid the actual question, which is how do you select a class from a multi class element, you should follow this example of splitting up the class name Get class list for element with jQuery if you truly insist on using classes to make your link/div association
You don't really want to exclude the plink class, because that will bring you confusion and trouble when you need to add another class. Instead you want to extract just the pageX class:
// Regex for extracting pageXX
var reg = /^(.*\s)?(page\d+)([^\d].*)?$/;
dis = reg.exec(dis)[2];
I haven't testet this 100%, but put these two lines in right after var dis = $(this).attr("class"); and you should hopefully be good to go.
i down't know if i get your question right
to get all classes with class plink u can use
var klasses $("a.plink");
now u can loop true the items
var yourClasses = Array();
for(var klass in klasses)
{
var word = klass.attr('class').replace(" plink", "");
yourClasses.push(word);
}
now you have all the classes wich have the class plink
hope this was where u where looking for
If I was just doing a minor tweak to fix your existing structure I would do something like this:
$(document).ready(function() {
$('a.plink').click(function() {
var id = $.trim(this.className.replace('plink', ''));
/*adding a "page" class to each of the page divs makes hiding the visible one a bit easier*/
$('div.page').hide();
/*otherwise use the version from sheikh*/
//$('div[id^="page"]').not('#page-links').hide();
$('div#' + id).show();
});
});
The main change I would recommend to your existing markup would be to add a common "page" class to each of the page divs. Here is a fiddle
If I was starting on this from scratch I would probably take a slightly different approach in which I define an "active" class and toggle which elements have it rather than using show/hide on the divs. And that would end up looking something like this:
Markup:
<div id="page-links">
<a class="plink active" href="#page1">About</a>
<a class="plink" href="#page2">History</a>
<a class="plink" href="#page3">Backstage</a>
</div>
<div id="page1" class='page active'> </div>
<div id="page2" class='page'> </div>
<div id="page3" class='page'> </div>
CSS:
div.page
{
height: 300px;
display:none;
}
div.page.active
{
display:block;
}
a.plink
{
padding-left:5px;
padding-right:5px;
}
a.plink.active
{
background-color:#ddd;
}
div#page1
{
background-color:blue;
}
div#page2
{
background-color:green;
}
div#page3
{
background-color:red;
}
Script:
$(document).ready(function() {
$('a.plink').click(function() {
var id = $(this).attr('href');
$('.active').removeClass('active');
$(this).addClass('active');
$('div' + id).addClass('active');
});
});
Or the fiddle here.
Oh and to answer the title question rather than just the end behavior described...
var classes = this.className.split(' ');
var id;
for (var i = 0; i < classes.length; i++) {
if(classes[i].substring(4) === classes[i].replace('page', '')) {
id = classes[i];
break;
}
}
should end up with id containing the "page#" value associated with the link that was clicked regardless of its position in the list of classes.
Is there a built in method or defacto default plugin that will let you automatically assign an unique ID to an element in jQuery, or do you need to implement something like this yourself? I'm looking for the jQuery equivalent to Prototype's identify method
Here's an example. I have some HTML structure on a page that looks like this
<span id="prefix_1">foo bar</span>
...
<div id="foo">
<span></span>
<span></span>
<span></span>
</div>
I want to assign each of the spans an ID that will be unique to the page. So after calling something like this
$('#foo span').identify('prefix'); //fake code, no such method
The rendered DOM would look something like this
<span id="prefix_1">foo bar</span>
...
<div id="foo">
<span id="prefix_2"></span>
<span id="prefix_3"></span>
<span id="prefix_4"></span>
</div>
Is there anything official-ish/robust for jQuery, or is this something most jQuery developers roll on their own?
jQuery.fn.identify = function(prefix) {
var i = 0;
return this.each(function() {
if(this.id) return;
do {
i++;
var id = prefix + '_' + i;
} while($('#' + id).length > 0);
$(this).attr('id', id);
});
};
$('span').identify('test');
Tested this on:
<span id='test_2'></span>
<span>test1</span>
<span>test2</span>
<span>test3</span>
Turned it to:
<span id="test_2"></span>
<span id="test_1">test1</span>
<span id="test_3">test2</span>
<span id="test_4">test3</span>
Not that I know of, but you could do this yourself by adding the id attribute and supplying a GUID.
To add the attribute:
$(foo).attr( "id", createGuid() );
For the createGuid() implementation, see this question.
Note that you could easily turn this into a jQuery plug-in so that this function (you could even name it identify()) is available on any $-expression.
Based on Paolo's solution:
jQuery.fn.identify = function(prefix) {
var i = 0;
return this.each(function() {
if($(this).attr('id')) return;
do {
i++;
var id = prefix + '_' + i;
} while($('#' + id).length > 0);
$(this).attr('id', id);
});
};
$('span').identify('test');
A small change that will avoid to re-count already used ids.
I'd modify the given function slightly and make it:
jQuery.fn.identify = function(prefix) {
var i = 0;
return this.each(function() {
if($(this).attr('id')) return;
do {
i++;
var id = prefix + '_' + i;
} while(document.getElementById(id) != null);
$(this).attr('id', id);
});
};
ID's could contain special characters that would require escaping in order to work properly with jQuery's CSS selector engine--like ".". So instead of finding them and escaping them, it's simpler and faster to replace it with the document method.
Maybe try
$("#foo span").each(function(){
$(this).attr("id", "prefix_" + $(this).parent().index($(this)));
});