multiple span calls of javascript value - javascript

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>

Related

How to get innerHTML value using only class?

I have a code similar to following:
<span class="subg">100</span>
<span class="subg">10000</span>
<span class="subg">1000000</span>
I want to access the inner value of any span using jQuery selectors. So for example if I want to get value of span having value 10000, I do following:
$('.subg:contains("10000")').text()
This works fine, but if I want to get value 100, then this approach is not correct as I want to get the first span value but since all 3 spans contain 100, all three will be matched.
Another approach I tried is this:
$('.subg[innerHTML="100"]')
But this doesn't seem to work, as innerHTML is not an attribute of span.
I don't know the order of spans.
Restrictions:
I cannot use loop.
I cannot give id.
I cannot change span to some other type.
I don't think you can do this via class. You'll need to filter out the elements that match instead.
function getText(n) {
return $('.subg').filter(function (i, v) {
return $(v).text() === n;
});
}
getText('100').css('color', 'red');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="subg">100</span>
<span class="subg">10000</span>
<span class="subg">1000000</span>
Use filter to get targeted span value:
var result = $(".subg").filter(function() { return ($(this).text() === '1000000') }); // Change value to get desire result
console.log(result.text());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="subg">100</span>
<span class="subg">10000</span>
<span class="subg">1000000</span>
UPDATED : I used filter to match what you want
$(".subg").filter(function() {
return $(this).text() === "100";
}).css("color", "red");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="subg">10000</span>
<span class="subg">1000000</span>
<span class="subg">100</span>

How to use 1 id for everything instead of 3 (for the following code)

I have the following html (it's a card) where a class is added to change the look of it:
<div class="card-small-half" id="card-1">
<a href="components/">
<div class="action-bar">
<p>Add Page</p>
<i class="material-icons">add</i>
</div>
</a>
</div>
and a switch made with a label that checks and unchecks an input type checkbox:
<div class="switch-wrapper" id="switch-wrapper-1">
<input type="checkbox" id="input-1" class="display-none">
<label class="switch" for="input-1"></label>
<p id="switch-caption-1">Visible</p>
</div>
With the following Javascript I add a class called "card-disabled" to the card:
window.onload = function () {
function check() {
if (document.getElementById("input-1").checked) {
document.getElementById("switch-caption-1").textContent = "Disabled";
$('#card-1').addClass('card-disabled');
} else {
document.getElementById("switch-caption-1").textContent = "Visible";
$('#card-1').removeClass('card-disabled');
}
}
document.getElementById('input-1').onchange = check;
check();
}
I know in css you can call id's or classes like so:
#switch-wrapper-1 input { /* styles */ }
or
#switch-wrapper-1 p { /* styles */ }
How can I do this with javascript, so I don't have to use an id for every element and instead use a global id for every wrapper.
EDIT:
The wrapper and input id's are unique! I want to call the paragraph inside the unique wrapper element something like this:
document.getElementById("switch-wrapper-1 p").textContent = "Disabled";
The 'p' here means paragraph
Is this possible and if so: how?
Query Selector is your friend here. You can use CSS selectors to retrieve DOM elements. In your case this call would return the first paragraph child in the #switch-wrapper-1 element.
var node = document.querySelector('#switch-wrapper-1 p');
If you also use jQuery, then as suggested in comments, you can simply use the $ function.
var $node = $('#switch-wrapper-1 p');
To select an individual element inside of an element with a specific ID using Javascript you can do:
document.getElementById('hello').getElementsByTagName('input')[0];
So in your example it would be:
document.getElementById('switch-wrapper-1').getElementsByTagName('input')[0].onchange = check;
The [0] is used because getElementsByTagName returns an array of all the child elements inside the parent element with the specified tag. Note that you will have to keep the unique ID on the input field if you want the for attribute on the label to function correctly.

get index of class element with inline onclick - pure js no jQuery

so i have some class-elements:
<span class="show" onclick="show()">show</span>
<span class="show" onclick="show()">show</span>
<span class="show" onclick="show()">show</span>
when i click one of these elements i need the index for some reason. i know how to use jQuery, but thats not what i am asking for, here.
my js function should look something like this:
function show() {
var index = document.getElementsByClassName('show')[??];
alert(index);
}
How is that possible with pure javascript? NOTE: i have to stick with the onclick="show()" that cannot be changed.
i hope someone can help, thanks in advance :)
Just get the array of all the elements and find the current element who received the click
function show(el) {
var els = Array.prototype.slice.call( document.getElementsByClassName('show'), 0 );
console.log(els.indexOf(event.currentTarget));
}
<span class="show" onclick="show(this)">span 1</span>
<span class="show" onclick="show(this)">span 2</span>
<span class="show" onclick="show(this)">span 3</span>
You can try something like this:
Use addEventListener to bind event handlers. This will allow you to use this.
If you still need index of element, you can either loop over elements or convert NodeList into array and then use Array.indexOf
Sample
Onclick
function show(self){
var spans = document.querySelectorAll('.show');
console.log(Array.from(spans).indexOf(self))
}
<span class="show" onclick="show(this)">show</span>
<span class="show" onclick="show(this)">show</span>
<span class="show" onclick="show(this)">show</span>
addEventListener
function show(){
var spans = document.querySelectorAll('.show');
console.log(Array.from(spans).indexOf(this))
}
function registerEvent(){
var spans = document.querySelectorAll('.show');
for(var i = 0; i< spans.length; i++){
spans[i].addEventListener("click", show)
}
}
registerEvent();
<span class="show" >show</span>
<span class="show" >show</span>
<span class="show" >show</span>
If you absolutely insist on using the onclick attribute (even though you don't really need to):
// get live collection so you only need to call this once
var liveCollection = document.getElementsByClassName('show');
function show(event) {
// convert liveCollection to array for `.indexOf()`
// either ES6
var shows = [...liveCollection];
// or ES5
var shows = Array.prototype.slice.call(liveCollection);
var index = shows.indexOf(event.currentTarget);
alert(index);
}
.show {
cursor: pointer;
}
<span class="show" onclick="show(event)">show</span>
<span class="show" onclick="show(event)">show</span>
<span class="show" onclick="show(event)">show</span>
However, I would rather recommend you use delegated events to handle dynamically added elements, as using the onclick attribute is considered bad practice, but don't just take my word for it.
// see below for how to select the best container
var container = document.body;
// single event listener for all dynamically added elements
container.addEventListener('click', function (event) {
if (event.target.classList.contains('show')) {
show.call(event.target, event);
}
});
// get live collection so you only need to call this once
var liveCollection = container.getElementsByClassName('show');
function show(event) {
// convert liveCollection to array for `.indexOf()`
// either ES6
var shows = [...liveCollection];
// or ES5
var shows = Array.prototype.slice.call(liveCollection);
// this === event.target
var index = shows.indexOf(this);
alert(index);
}
.show {
cursor: pointer;
}
<span class="show">show</span>
<span class="show">show</span>
<span class="show">show</span>
The nice thing about delegated event handling is you don't need an onclick attribute to handle dynamically added elements, so this will work best for your particular usage.
It is recommended, but not necessary, that the event listener for the delegated events is attached to the most immediate container of all the dynamically added elements, so that the click event doesn't have to bubble up all the way to the document.body. This makes the handling more efficient.
If you're JUST looking for the index, you can pass that to the show() method.
<span class="show" onclick="show(0)">show</span>
<span class="show" onclick="show(1)">show</span>
<span class="show" onclick="show(2)">show</span>

jQuery get element attribute from nested element

I'm in a situation as follows:
<span class="inputgrp">
<span class="additem">
</span>
</span>
<input type="text" avl="abc">
I'm trying to get the value of the attribute avl from the input with a click event on class="inputgrp"
I have tried with:
$(".additem").click(function () {
var v = $(this).parent().find("input:text").attr("avl")
})
and
$(".inputgrp").click(function () {
var v = $(this).prev("span").next("input:text").attr("avl")
})
But without success. Would appreciate some guide as I have no clue what I am dong wrong.
$(".inputgrp").click(function() {
alert($(this).next("input:text").attr("data-avl"))
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="inputgrp">
<span class="additem">
1
</span>
</span>
<input type="text" data-avl="abc">
Use data attribute since avl is not a valid attribute
use .next() since input is next to the click element
.find searches for children of the current element. The input is not a child but a sibling of .inputgrp
$('.inputgrp').on('click',function() {
var v = $(this).siblings('input[data-avl]').attr('data-avl');
});
Use data-avl as an attribute to make it valid.
Use the .sibling() function to select any of the siblings
If the input element is always going to be the next element, use the .next() function
use a data-avl="" attribute on your html input element and in jQuery use .data('avl') to get the value of the attribute
$(".inputgrp").click(function() {
alert($(this).next("input:text").data("avl"));
})

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

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

Categories

Resources