Three-way toggling of two states (Javascript or jQuery) - javascript

I am working on a page that will show prices in a choice of currencies (euros, pounds or dollars). My aim is to display the price in euros first, keeping the pound and dollar prices hidden.
<button id="mybutton">Change Currency</button>
<p id="euro" class="shown">Euro</p>
<p id="pound" class="hidden">Pound</p>
<p id="dollar" class="hidden">Dollar</p>
When the button is clicked, I need the three ids to cycle through the three states shown/hidden/hidden, hidden/shown/hidden and hidden/hidden/shown.
So far I have made it work with two ids (not difficult!).
$('#mybutton').click(function()
{
$('#euro').toggleClass('hidden','shown'),
$('#pound').toggleClass('hidden','shown');
});
I'm at a loss to see how to extend this to the third id. Any ideas gratefully received.

I just wanted to point out you may be confused on how toggleClass works. The second parameter is never a string like a class. Instead, it's a boolean. I've gotten rid of the "shown" class (things are shown by default) and used a boolean for the second argument:
i=0;
$('#mybutton').click(function(){
i++;
$('#euro').toggleClass('hidden', i%3!==0),
$('#pound').toggleClass('hidden',i%3!==1);
$('#dollar').toggleClass('hidden',i%3!==2);
});
All this does is remove the hidden class when the cycling matches (i%3===0) and add it (hide those elements) otherwise.
If you did want to toggle between multiple classes, I believe the first argument should be a space separated list of classes.
http://jsfiddle.net/NWj5w/
http://api.jquery.com/toggleClass/

Supposing you don't use those class elsewhere, you could do
var i = 0, divs = $('.hidden, .shown');
$('#mybutton').click(function() {
$('.shown').removeClass('shown').addclass('hidden');
i = (i+1) % divs.length;
divs.eq(i).removeClass('hidden').addclass('shown');
});
Supposing you use those classes elsewhere, I'd recommend you to change your HTML to add a specific classs and to do
var i = 0, divs = $('.specificClass');
$('#mybutton').click(function() {
$('.shown').removeClass('shown').addclass('hidden');
i = (i+1) % divs.length;
divs.eq(i).removeClass('hidden').addclass('shown');
});
Note that I find usually simpler to change only one class, that is to give all the elements the same "specific" class and to just add or remove the "hidden" class.

My final solution is based on Jere's answer above, but is a little more complicated. As well as showing a price in one currency and hiding the other's, I also need to indicate which currency is being displayed and which others are available. Therefore my html ends up like this:
<span class="euro_h activ">Euro</span>
<span class="pound_h activ inactiv">Pound</span>
<span class="dollar_h activ inactiv">Dollar</span>
<span id="change" style="cursor:pointer">Change Currency</span>
<br>
<br>
<span class="euro shown">€ 100</span>
<span class="pound hidden">£ 80</span>
<span class="dollar hidden">$ 140</span>
The CSS is:
.activ {color:#ff0000}
.inactiv {color:#CCCCCC}
.shown {display:inline}
.hidden {display:none}
The javascript is:
i=0;
$('#change').click(function(){
i++;
$('.euro').toggleClass('hidden', i%3!==0);
$('.pound').toggleClass('hidden',i%3!==1);
$('.dollar').toggleClass('hidden',i%3!==2);
$('.euro_h').toggleClass('inactiv', i%3!==0);
$('.pound_h').toggleClass('inactiv',i%3!==1);
$('.dollar_h').toggleClass('inactiv',i%3!==2);
});
Doubling up the lines seems a bit messy but it works and my efforts at something more streamlined didn't. So .....

HTML
<button id="mybutton">Change Currency</button>
<p id="euro" class="unit shown">Euro</p>
<p id="pound" class="unit hidden">Pound</p>
<p id="dollar" class="unit hidden">Dollar</p>
JavaScript
$("#mybutton").on("click", function() {
var btns = $(".unit");
var active = btns.filter(".shown").removeClass("shown").next();
active = (active.length) ? active : btns.eq(0)
active.addClass("shown");
});
Fiddle
http://jsfiddle.net/g6EM5/

Another working example:
HTML:
<button id="mybutton">Change Currency</button>
<p class="currency euro">Euro</p>
<p class="currency pound">Pound</p>
<p class="currency dollar">Dollar</p>
JS:
$('#mybutton').click(function() {
for (var i = 0; i < currencies.length; i++) {
i == shown ? currencies[i].show() : currencies[i].hide();
}
shown = (shown+1)%3;
});
Fiddle

Related

JavaScript possible to select all elements with classname that starts with (...)? [duplicate]

I'm trying to only show certain divs. The way I have decided to do this is to first hide all elements that start with "page" and then only show the correct divs. Here's my (simplified) code:
<form>
<input type="text" onfocus="showfields(1);">
<input type="text" onfocus="showfields(2);">
</form>
<div class="page1 row">Some content</div>
<div class="page1 row">Some content</div>
<div class="page2 row">Some content</div>
<div class="page2 row">Some content</div>
<script>
function showfields(page){
//hide all items that have a class starting with page*
var patt1 = /^page/;
var items = document.getElementsByClassName(patt1);
console.log(items);
for(var i = 0; i < items.length; i++){
items[i].style.display = "none";
}
//now show all items that have class 'page'+page
var item = document.getElementsByClassName('page' + page);
item.style.display = '';
}
</script>
When I console.log(items); I get a blank array. I'm pretty sure the regexp is right (get all items starting with 'page').
The code I'm using is old school JS, but I'm not adverse to using jQuery. Also if there is a solution that doesn't use regexp, that's fine too as I'm new to using regexp's.
getElementsByClassName only matches on classes, not bits of classes. You can't pass a regular expression to it (well, you can, but it will be type converted to a string, which is unhelpful).
The best approach is to use multiple classes…
<div class="page page1">
i.e. This div is a page, it is also a page1.
Then you can simply document.getElementsByClassName('page').
Failing that, you can look to querySelector and a substring matching attribute selector:
document.querySelectorAll("[class^=page]")
… but that will only work if pageSomething is the first listed class name in the class attribute.
document.querySelectorAll("[class*=page]")
… but that will match class attributes which mention "page" and not just those with classes which start with "page" (i.e. it will match class="not-page".
That said, you could use the last approach and then loop over .classList to confirm if the element should match.
var potentials = document.querySelectorAll("[class*=page]");
console.log(potentials.length);
elementLoop:
for (var i = 0; i < potentials.length; i++) {
var potential = potentials[i];
console.log(potential);
classLoop:
for (var j = 0; j < potential.classList.length; j++) {
if (potential.classList[j].match(/^page/)) {
console.log("yes");
potential.style.background = "green";
continue elementLoop;
}
}
console.log("no");
potential.style.background = "red";
}
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
Previous answers contain parts of the correct one, but none really gives it.
To do this, you need to combine two selectors in a single query, using the comma , separator.
The first part would be [class^="page"], which will find all the elements whose class attribute begins with page, this selector is thus not viable for elements with multiple classes, but this can be fixed by [class*=" page"] which will find all the elements whose class attribute have somewhere the string " page" (note the space at the beginning).
By combining both selectors, we have our classStartsWith selector:
document.querySelectorAll('[class^="page"],[class*=" page"]')
.forEach(el => el.style.backgroundColor = "green");
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
You can use jQuery solution..
var $divs = $('div[class^="page"]');
This will get all the divs which start with classname page
$(document).ready(function () {
$("[class^=page]").show();
$("[class^=page]").hide();
});
Use this to show hide div's with specific css class it will show/hide all div's with css class mention.

dynamically insert div after row containing floating divs jquery [duplicate]

I have a number of divs floating in several rows. The divs contain text-previews and a link to slide down the full content (see http://jsfiddle.net/yDcKu/ for an example).
What happens now: When you slide down the content-div it opens right after the connected preview.
What I want to happen: Open the content-div after the last div in the row.
I assume the could be done by:
1. find out which div is the last one in the row of the activated preview,
2. add an id to this div and
3. append the content-div to this div.
I have a solution for steps 2 und 3 using jQuery but no guess how to do the first step.
I can manage to get the document width and the x- and y-value of each div but I have no idea how to find out which div has the highest x- as well the highest y-value and as well is in the row of the activated preview-div.
Any idea anyone? Thanks
Here is an example that does what you want. I simplified your code, so you don't have to manually ID every entry and preview.
http://jsfiddle.net/jqmPc/1/
It's a little complicated. Let me know if you have questions.
Basically, when the window is resized, the script goes through and finds the first preview in each row by finding the preview with the same left offset as the very first one. It then adds a class last to the entry before (previous row) and class first to this preview. I do css clear: left on both of these so that everything wraps normally when the entries open.
I made your code generic, without IDs:
<div class="preview">
<p>Some preview text <a class="trigger" href="#">…</a></p>
</div>
<div class="entry">
<div class="close_button">
<a class="close" href="#">×</a>
</div>
<p>Some content text.</p>
</div>
This makes you not have to write the same code over and over.
The open/close script:
$('.trigger').click(function() {
$('.openEntry').slideUp(800); // Close the open entry
var preview = $(this).closest('.preview'); // Grab the parent of the link
// Now, clone the entry and stick it after the "last" item on this row:
preview.next('.entry').clone().addClass('openEntry').insertAfter(preview.nextAll('.last:first')).slideDown(800);
});
// Use "on()" here, because the "openEntry" is dynamically added
// (and it's good practice anyway)
$('body').on('click', '.close', function() {
// Close and remove the cloned entry
$('.openEntry').slideUp(800).remove();
});
This could be simplified a bit I'm sure, especially if you were willing to reformat your html a little more, by putting the entry inside of the preview element (but still hidden). Here is a slightly simpler version, with the html rearranged:
http://jsfiddle.net/jqmPc/2/
(I also color the first and last element on the line so you can see what is going on)
You could just get the last div in the array after calling getElementsByTagName.
var divArray = wrapperDiv.getElementsByTagName("div");
if(divArray.length > 0)
var lastDiv = divArray[divArray.length-1];
else
console.log("Empty!");
i am not able to correctly understand your question, but if you want to find out last div element in the document then you can do something like this
$("div:last")
so this will give you last div of the document
Reference:
http://api.jquery.com/last-selector/
$([1,2]).each(function(idx,el) {
$("#entry" + el).hide().insertAfter("div.entry:last");
$("#trigger" + el).click(function() {
$("#entry" + el).slideDown('800');
});
$("#close" + el).click(function() {
$("#entry" + el).slideUp('800');
});
});​
http://jsfiddle.net/yDcKu/11/
I got same problem as yours, and I have been redirected to this question. But I think the answer is too complicated to my need. So I made my own way. Supposedly, you get your div list from a JSON, you can do this:
product[0] = {id: "name1", text: "text1"}
product[1] = {id: "name2", text: "text2"}
product[2] = {id: "name3", text: "text3"}
private getLastElement(id, products) {
const getTop = (id) => $("#" + id).position().top;
let itemPos = getTop(id);
let itemIndex = products.map(x => x.id).indexOf(id);
let lastID = itemIndex;
while (lastID < products.length - 1) {
if (getTop(products[lastID + 1].id) > itemPos) break;
lastID++;
}
return products[lastID].id;
}
But you can also find out by gathering all id inside your wrapper.
It works by scanning next id's row position, and return the last id of the same row.
I was looking for the same but on a single element to add style on first and last elements. #Jeff B answer helped me so alter and use it for me on one element. So the search phrase 'Get the last div in a row of floating divs' and someone looking for the same, this code may helpful:
Fiddle: https://jsfiddle.net/kunjsharma/qze8n97x/2/
JS:
$(function() {
$(window).on('resize', function() {
var startPosX = $('.preview:first').position().left;
$('.preview').removeClass("first last");
$('.preview').each(function() {
if ($(this).position().left == startPosX) {
$(this).addClass("first");
$(this).prevAll('.preview:first').addClass("last");
}
});
$('.preview:last').addClass("last");
});
$(window).trigger('resize');
});
CSS:
.preview {
float: left;
}
HTML:
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>

multiple span calls of javascript value

In my header I have
function addusr() {
document.getElementById("usrout").innerHTML = document.getElementById("usrin").value;}
and in my text I have
code-bla bla bla<span id="usrout"></span> bla!! It works!
but if I try to call <span id="usrout"></span> again on the same page at a different location, none of the others appear.
Example:
text <span id="usrout"></span> more text, code... another <span id="usrout"></span>...
...
..
...
another <span id="usrout"></span> ...
Only the first one appears, why is this? How can I fix it?
An ID needs to be unique. You might want to consider classes instead.
When you’ve assigned classes to the HTML elements, your JavaScript code may look like this:
function addusr () {
var usrin = document.getElementById("usrin").value,
usrout = document.getElementsByClassName("usrout");
Array.prototype.forEach.call(usrout, function (el) {
el.innerHTML = usrin;
});
}
Explanation:
Instead of getElementById, we’re using getElementsByClassName which returns an array of elements having that particular classname. Thus a loop is required to set the innerHTML property of each retrieved element.
First of all, using same ID in more than one element is WRONG and against RFC.
You should make it a CLASS, not ID, and then...
document.querySelector(".usrout").innerHTML = ...
Every single element needs a unique ID.
For example
<span id="usrout1"></span>
<span id="usrout2"></span>
Alternatively, you could use classes as mentioned already
<span class="green"></span>
<span class="green"></span>
Then use a CSS selector such as document.getElementByClass
Element IDs must be unique, so getElementById will only ever return (at most) one element.
You need to use a different search, perhaps querySelectorAll, to get all the applicable elements. You can then loop through them, and set the necessary comment.
For example:
function addusr() {
var inputValue = document.getElementById("usrin").value;
var outputs = document.querySelectorAll("span.usrout");
for (var i = 0; i < outputs.length; ++i) {
outputs[i].textContent = inputValue;
}
}
<input id="usrin" type="text" />
<button type="button" onclick="addusr();">Update</button>
<span class="usrout"></span>
<span class="usrout"></span>
<span class="usrout"></span>
<span class="usrout"></span>
<span class="usrout"></span>
<span class="usrout"></span>

filter out which span to update

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.

Get the last div in a row of floating divs

I have a number of divs floating in several rows. The divs contain text-previews and a link to slide down the full content (see http://jsfiddle.net/yDcKu/ for an example).
What happens now: When you slide down the content-div it opens right after the connected preview.
What I want to happen: Open the content-div after the last div in the row.
I assume the could be done by:
1. find out which div is the last one in the row of the activated preview,
2. add an id to this div and
3. append the content-div to this div.
I have a solution for steps 2 und 3 using jQuery but no guess how to do the first step.
I can manage to get the document width and the x- and y-value of each div but I have no idea how to find out which div has the highest x- as well the highest y-value and as well is in the row of the activated preview-div.
Any idea anyone? Thanks
Here is an example that does what you want. I simplified your code, so you don't have to manually ID every entry and preview.
http://jsfiddle.net/jqmPc/1/
It's a little complicated. Let me know if you have questions.
Basically, when the window is resized, the script goes through and finds the first preview in each row by finding the preview with the same left offset as the very first one. It then adds a class last to the entry before (previous row) and class first to this preview. I do css clear: left on both of these so that everything wraps normally when the entries open.
I made your code generic, without IDs:
<div class="preview">
<p>Some preview text <a class="trigger" href="#">…</a></p>
</div>
<div class="entry">
<div class="close_button">
<a class="close" href="#">×</a>
</div>
<p>Some content text.</p>
</div>
This makes you not have to write the same code over and over.
The open/close script:
$('.trigger').click(function() {
$('.openEntry').slideUp(800); // Close the open entry
var preview = $(this).closest('.preview'); // Grab the parent of the link
// Now, clone the entry and stick it after the "last" item on this row:
preview.next('.entry').clone().addClass('openEntry').insertAfter(preview.nextAll('.last:first')).slideDown(800);
});
// Use "on()" here, because the "openEntry" is dynamically added
// (and it's good practice anyway)
$('body').on('click', '.close', function() {
// Close and remove the cloned entry
$('.openEntry').slideUp(800).remove();
});
This could be simplified a bit I'm sure, especially if you were willing to reformat your html a little more, by putting the entry inside of the preview element (but still hidden). Here is a slightly simpler version, with the html rearranged:
http://jsfiddle.net/jqmPc/2/
(I also color the first and last element on the line so you can see what is going on)
You could just get the last div in the array after calling getElementsByTagName.
var divArray = wrapperDiv.getElementsByTagName("div");
if(divArray.length > 0)
var lastDiv = divArray[divArray.length-1];
else
console.log("Empty!");
i am not able to correctly understand your question, but if you want to find out last div element in the document then you can do something like this
$("div:last")
so this will give you last div of the document
Reference:
http://api.jquery.com/last-selector/
$([1,2]).each(function(idx,el) {
$("#entry" + el).hide().insertAfter("div.entry:last");
$("#trigger" + el).click(function() {
$("#entry" + el).slideDown('800');
});
$("#close" + el).click(function() {
$("#entry" + el).slideUp('800');
});
});​
http://jsfiddle.net/yDcKu/11/
I got same problem as yours, and I have been redirected to this question. But I think the answer is too complicated to my need. So I made my own way. Supposedly, you get your div list from a JSON, you can do this:
product[0] = {id: "name1", text: "text1"}
product[1] = {id: "name2", text: "text2"}
product[2] = {id: "name3", text: "text3"}
private getLastElement(id, products) {
const getTop = (id) => $("#" + id).position().top;
let itemPos = getTop(id);
let itemIndex = products.map(x => x.id).indexOf(id);
let lastID = itemIndex;
while (lastID < products.length - 1) {
if (getTop(products[lastID + 1].id) > itemPos) break;
lastID++;
}
return products[lastID].id;
}
But you can also find out by gathering all id inside your wrapper.
It works by scanning next id's row position, and return the last id of the same row.
I was looking for the same but on a single element to add style on first and last elements. #Jeff B answer helped me so alter and use it for me on one element. So the search phrase 'Get the last div in a row of floating divs' and someone looking for the same, this code may helpful:
Fiddle: https://jsfiddle.net/kunjsharma/qze8n97x/2/
JS:
$(function() {
$(window).on('resize', function() {
var startPosX = $('.preview:first').position().left;
$('.preview').removeClass("first last");
$('.preview').each(function() {
if ($(this).position().left == startPosX) {
$(this).addClass("first");
$(this).prevAll('.preview:first').addClass("last");
}
});
$('.preview:last').addClass("last");
});
$(window).trigger('resize');
});
CSS:
.preview {
float: left;
}
HTML:
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>

Categories

Resources