I have the following div collection in my HTML. It's designed to dynamically replicate according to user interaction.
<div class="bill-item">
<!-- Section for a single item -->
<div class="bill-item-img">
<!-- Section for Item pic -->
</div>
<div class="bill-item-description">
<!-- Section for Item description and pricing -->
<div class="bill-item-name">
<p class="bill-item-name-left">Normal Cofee</p><p class="bill-item-name-right">170.00</p>
<div class="clear"></div>
</div>
<div class="bill-item-price">
<span>170.00 USD</span>
</div>
<div class="bill-item-amount">
<span>2</span>
</div>
</div>
<div class="bill-amount-selection">
<!-- Section where the increment & decrement of item amount goes -->
<a class="amount-increase" href="#"></a>
<a class="amount-decrease" href="#"></a>
</div>
</div>
This is the HTML Rendered image of the elements.
I've written the following script to increase the bill-item-amount span value.
$(".amount-increase").click(function(){
x+=1;
$(".bill-item-amount span").html(x);
});
$(".amount-decrease").click(function(){
if(!x<=0){
x-=1;
$(".bill-item-amount span").html(x);
}
});
This works great but, it updates the value of both the span elements. what I want is to catch the event of the clicked element (which I do now) and increase the span value of the respective span. How can I filter out which span to update using javascript.?
Something like $(this).parents('.bill-item').find('.bill-item-amount span') should select the right element.
Inside your callback this is assigned to the eventSource.
You should walk the dom tree from the clicked element up until you reach the .bill-item element and the go down to the .bill-item-amount span node
$(".amount-increase").click(function(){
var $span = $(this).parent().parent().find(".bill-item-amount span");
var x = $span.html();
x+=1;
$span.html(x);
});
$(".amount-decrease").click(function(){
var $span = $(this).parent().parent().find(".bill-item-amount span");
var x = $span.html();
if(!x<=0){
x-=1;
$span.html(x);
}
});
Hi dimal update your code:
$(".amount-increase").click(function(){
x+=1;
$(".bill-item-amount").html(x);
});
$(".amount-decrease").click(function(){
if(!x<=0){
x-=1;
$(".bill-item-amount").html(x);
}
});
dont add span inside the selector [ it changes entire span values]
$(".amount-increase").click(function(){
x+=1;
$("use ur increase span id here").html(x); //
});
$(".amount-decrease").click(function(){
if(!x<=0){
x-=1;
$("use ur decrease span id here").html(x);
}
});
Inside each function the selector $(".bill-item-amount span") will find all the <span> amounts in the document. You can walk the DOM to find the correct <span> using jQuery or plain JavaScript. You seem to be using jQuery functions so my answer also uses jQuery.
The following code combines the two actions into a single function that increases or decreases the amount based on the class name of the <a> clicked. I also added a return false so that the browser will not follow the href="#" on the anchor.
$('.bill-amount-selection').on('click', 'a', function(){
var change = this.className == 'amount-increase' ? 1 : -1
var $amount = $(this).closest('.bill-item').find('.bill-item-amount span')
var amount = parseInt($amount.html(), 10) + change
$amount.html(amount < 0 ? 0 : amount)
return false
});
The use of .on() means that jQuery v1.7+ is required. I can supply a compatible function with lower jQuery versions if necessary.
Related
So I've got this slider, and I want to hide its controls if it only has one element inside it.
Markup:
<div class="grid carousel-controls">
<span class="control prev"></span>
<span class="control next"></span>
</div>
<div class="carousel">
<img src="//placecage.com/440/660"/>
</div>
jQuery:
$(function(){
var count = $('.carousel').children().length;
if (count < 2) {
$('.carousel-controls').hide();
}
});
Any takers? ❤️
Edit: Worth adding that it's inside a tab nav, wherein the other carousel has > 2 children, in which case I obviously want the controls to be visible.
You are looking for $.each():
$(function(){
$('.carousel').each(function(i, c){
var count = $(c).children().length;
// if the .carousel-controls is a children of .carousel
if (count < 3)
$(c).find('.carousel-controls').hide();
// if the .carousel-controls is a siblings of .carousel
if (count < 2)
$(c).siblings('.carousel-controls').hide();
// comment out the inappropriate syntax above.
});
});
find() is relative to .carousel and depends where .carousel-controls is placed. If .carousel-controls is inside .carousel, it would also be consider a children of .carousel so you need to count less than 3.
I can give you an idea.
Assumption: only one tab will be active at a time
find carousel-controls of active tab only. and then you can controls hide them based on logic.
$('a[data-toggle="tab"]').on('shown', function (e) {
// access carousel here then you can find children here using $(this);
// your logic goes here.
});
This piece of code is for reference only.
I Have the following in my HTML:
<div class="item" id="item_1">
Content
</div>
<div class="item" id="item_2">
Content
</div>
<div class="item" id="item_3">
Content
</div>
<!--CONTENT BLOCK 1-->
<div class="item w100" id="content_1">
Story
</div>
<!--/CONTENT BLOCK 1-->
<div class="item" id="item_4">
Content
</div>
<div class="item" id="item_5">
Content
</div>
<!--CONTENT BLOCK 2-->
<div class="item w100" id="content_2">
Story
</div>
<!--/CONTENT BLOCK 2-->
<div class="item" id="item_6">
Content
</div>
<!--CONTENT BLOCK 3-->
<div class="item w100" id="content_3">
Story
</div>
<!--/CONTENT BLOCK 3-->
The content blocks are hidden, only visible when an item is clicked.
I had this working fine as an unresponsive layout but now I've made the website responsive and the javascript needs to function slightly differently as each item width is different (it's a boxed grid layout).
This is the javascript:
// Open Link in Content Block
jQuery(document).ready(function($){
$('.contentLink').click(function(event){
var itemID=$(event.target).closest(".storyLink").attr("id");
showBlock(itemID);
document.location.hash = itemID;
return false;
});
});
function showBlock(targetID){ //load content and open dialog
var $url = "ss_storyboard/"+targetID+".html";
if (targetID == 'Sarah')
{
loadStory("#content_1", 500, targetID);
}
else if ((targetID == 'item_1') || (targetID == 'item_2') || (targetID == 'item_3'))
{
loadStory("#content_2", 1700, targetID);
}
else if (targetID == 'item_4' || targetID == 'item_5')
{
loadStory("#content_3", 2200, targetID);
}
else if (targetID == 'item_6' || targetID == 'item_7')
{
loadStory("#content_4", 2750, targetID);
}
else{
return false;
}
I was thinking I could do something like this:
jQuery(document).ready(function($){
$('.contentLink').click(function(event){
var itemID=$(event.target).closest(".storyLink").attr("id");
var contentID= $(event.target).next(".w100").attr("id");
showBlock(itemID, contentID);
document.location.hash = itemID;
return false;
});
});
But jquery's .next() only works within the content set. Is there a way to find find the next class the comes after a clicked class in a document??
Another way I though I could do this is to detect where the line break of the items ends (ie. when the items wrap to a new line), and append the content block in dynamically after this....I'm just not sure how to go about calculating where the break would be. All the item widths use percentages that differ for a number of media queries matching the different screen widths.
Final answer
Measure available area
function measureWidths(){
var container = document.getElementById("container"),
containerRectObject = container.getBoundingClientRect(),
containerRight = 0;
containerRight = containerRectObject.right;
return containerRight;
}
Go trought each storyLink and certain data-attribute if it's last of row.
This uses containerRight -value from previous function.
$(".storylink").each(function(key, value) {
$(this).append("<h2>Storylink no: " + key + "</h2>");
$(this).attr("data-open", "false");
$(this).attr("data-target", "content-" + key).append("<em>My data-target is 'content-" + key + "'</em>");
storyLinkRectObject = this.getBoundingClientRect();
storyLinkRight = storyLinkRectObject.right;
if(storyLinkRight == containerRight){
$(this).attr("data-row",dataRow);
$(this).attr("data-endOfRow",dataRow);
dataRow++;
}else{
$(this).attr("data-row",dataRow);
}
});
On click, dynamically move contentBlock after last storylink on the row.
//Destroy previous content of dynamicContentBlock
$(".dynamicContentBlock").html("");
$(".dynamicContentBlock").append(storyContent);
console.log(currentRow);
$(".dynamicContentBlock").insertAfter($("*[data-endOfRow='"+currentRow+"']"));
$(".dynamicContentBlock").show("slow");
Check the whole code HERE
I improved my answer based on your comment. Now the code checks if window width is small or not and if it's small (mobile), it does the following.
toggle clicked .storyLink larger (optional)
get wanted .storyBlock, based on assigned data-attributes (new)
use insertAfter() -jQuery method to move selected .storyBlock-node
after clicked .storyLink (new)
show wanted content(your code)
Notice:
I added some custom data-attributes on .storyLinks, .storyblocks
and to .story-elements. (only to first set of links)
I added .story for each .storyLink just to make things more clear to myself. Stories are now shown based on class "open".
CodePen
You can find code here
OLD ANSWER
If I understood you right, then this might help you.
Assigining data-targets (or similar), you can easily detect what content block to show on click.
I used .toggle() -jQuery method, but if you don't want to hide content block on second click, then you can just use .show() instead.
Hope this helps!
CodePen
I have three content boxes that i want to show and hide using controls.
The HTML is as follows:
<div id="leermat1">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
<div id="leermat2">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
<div id="leermat3">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
I have the two anchors pag-next and pag-prev that will control which of the content divs should be visible at any given point:
I want to write jquery such as, when #leermat1 'pag-next' is clicked, it hides #leermat1 and shows #leermat2. Then when #leermat1 is hidden and #leermat2 shows, when '.pag-next' is clicked, it hides #leermat2, and shows #leermat3.
Also the 'pag-prev' should work the same way.
I started with the following but dont know where to go from here.
$(document).ready(function() {
$('.pag-next').on('click',function() {
$('#leermat1').addClass('hide');
$('#leermat2').addClass('show');
});
});
One more thing is that the '.pag-next' should stop functioning after it has shown #leermat3.
You need this
$('[class^=pag-]').click(function() {
var elem = $('[id^=leermat]').filter(":visible"); // take the visible element
var num = Number(elem[0].id.match(/\d+$/)[0]); // take the number from it
var step = $(this).is('.pag-next') ? 1 : -1; // ternary operator
$('#leermat'+ (num + step)).show(); // show next or back
elem.hide(); // hide the visible element
});
Looks like in your anchor tag you have not given it a class.
Next
You then go on in your JQuery code to add a click function to a class which does not exist.
$('.pag-next').on('click',function()
Try adding class="pag-next" to your anchor tag.
This is what worked for me through a little trial and error. Although I am not sure if this is the most efficient solution.
$('#leermat1 .pag-next').on('click',function(){
$('#leermat1').addClass('hide');
$('#leermat1').removeClass('show');
$('#leermat3').addClass('hide');
$('#leermat3').remove('show');
$('#leermat2').addClass('show');
});
$('#leermat2 .pag-next').on('click',function(){
$('#leermat1').removeClass('show');
$('#leermat2').addClass('hide');
$('#leermat2').removeClass('show');
$('#leermat3').addClass('show');
});
$('#leermat2 .pag-prev').on('click',function(){
$('#leermat2').addClass('hide');
$('#leermat2').removeClass('show');
$('#leermat1').addClass('show');
$('#leermat3').removeClass('show');
});
$('#leermat3 .pag-prev').on('click',function(){
$('#leermat3').addClass('hide');
$('#leermat2').addClass('show');
$('#leermat1').addClass('hide');
$('#leermat3').removeClass('show');
$('#leermat1').removeClass('show');
});
I'm pretty sure I'm close but I don't know what I'm missing:
var newId = 1;
$("#trigger").click(function(){
$("#new-div").attr('id', 'new-div' +newId++).clone().appendTo("#myDiv");
});
I set breakpoints: I can see the counter auto-incrementing, but the cloned div does not appear where it should. I get no errors. HTML for this:
<div id="secret-div" style="display: none;">
<div>This is new div number </div>
</div>
<p><a id="trigger" href="javascript:void(0);">Please, add an element</a></p>
<div id="myDiv"></div>
The issue is that you're changing the ID of your element before cloning and appending, resulting in 2 elements with the same ID, breaking your selector and code.
Fixed Live Demo
HTML:
<div id="secret-div" style="display:none;">
<div>This is new div number <span class="spnNewDivNumber"></span></div>
</div>
<p><a id="trigger" href="javascript:void(0);">Please, add an element</a></p>
<div id="myDiv"></div>
JavaScript:
var newId = 1;
$("#trigger").click(function() {
var $newSecretDiv = $("#secret-div").clone().attr('id', 'new-div' + newId++);
$newSecretDiv.show().appendTo("#myDiv");
$newSecretDiv.find('.spnNewDivNumber').text(newId - 1);
});
Your current code is applying the new id before the clone, which means it's changing the id of the existing div. This in turn means that the next time the click handler is called, there won't be a div matching the selector '#new-div'.
Try applying the id after either the clone, or after inserting it into the DOM:
var newId = 1;
$("#trigger").click(function(){
$("#new-div").clone().attr('id', 'new-div' +newId++).appendTo("#myDiv");
});
OR
var newId = 1;
$("#trigger").click(function(){
$("#new-div").clone().appendTo("#myDiv").attr('id', 'new-div' +newId++);
});
You are attempting to clone the #new-div unless your current div is named 'new-div'. Also you are changing the id of the original div rather than creating a new one with the generated id.
I have 4 divs in a container. I want to display the html of the container which contains the divs in the textarea. I'm able to do this. The issue is, i don't want to get all the html of the container. I don't want to get #iv #three. I want to copy all the html of the container except div #three. I could use $('#three').remove() but i don't want to remove the div, I just don't want to copy it's html value to textarea. Check jsfiddle http://jsfiddle.net/rzfPP/
<div id="container">
<div id="one">test 1 </div>
<div id="two">test 2 </div>
<div id="three">test 3 </div>
<div id="four">test 4 </div>
</div>
<textarea id="save"></textarea>
var x = $('#container').html();
$('#save').val(x);
Try this
$("#container").clone().find("#three").remove().end().html();
http://jsfiddle.net/rzfPP/21/
/*
var x = $('#container').html();
$('#save').val(x);
*/
var lol = $('#container').clone()
$(lol).find('#three').remove();
$('#save').val(lol.html());
$('#container').clone().find('#three').remove().end().html();
Technically this is illegal since you are duplicating IDs, but it works fine.
http://jsfiddle.net/rzfPP/33/
Edit: Someone beat me to it :( Oh well.
var text = "";
$('#container div').each( function() {
if ( this.id != "three" ) {
text += $(this).html();
}
});
$('#save').val( text );
http://jsfiddle.net/rzfPP/31/
Basically you check the divs inside #container one by one, and check their id. If it's one you want, add their html to a string. Then at the end give that string as your textarea value.