I'm making a multi-language registration site. I need to detect if an element has a class="lng" which indicates that it will be displayed or hidden, depending on the language selected. (this part already works).
Additionally I need to detect which other class the element with the lng class has. So if the combination of classes is lng and en it will display the content in english language and hide all the other elements with the lng class which do not have an en class next to it (`class="lng" class="ru").
I can refactor the html elements so that it has class="lng en" if that would have make it easier...
HTML - language selection
<input type="image" id="slo" onclick="setLanguage('sl')">
<input type="image" id="ang" onclick="setLanguage('en')">
<input type="image" id="hrv" onclick="setLanguage('hr')">
<input type="image" id="rus" onclick="setLanguage('ru')">
HTML example - only one should be displayed, depending on the language selected:
<span class="lng" class="sl" class="radioS">Spol: </span>
<span class="lng" class="en" class="radioS">Gender: </span>
<span class="lng" class="hr" class="radioS">Spolov: </span>
<span class="lng" class="ru" class="radioS">секс: </span>
Javascript
function setLanguage(language) {
var lngs;
var i;
lngs = document.getElementsByClassName("lng");
console.log(lngs);
for (var i=0;i<lngs.length;i++){
if (lngs[i].classList.contains(language) !== language) {
lngs[i].style.display="none";
} else {
lngs[i].style.display="inline-block";
}
}
}
At the begining make them all invisible then iterate through all inputs and check if the class includes your language:
const lngs = document.getElementsByClassName("lng");
function init() {
for (var i = 0; i < lngs.length; i++) {
lngs[i].style.display = "none";
}
}
init();
function setLanguage(language) {
debugger
for (var i = 0; i < lngs.length; i++) {
if (lngs[i].className.includes(language)) {
lngs[i].style.display = "block";
} else {
lngs[i].style.display = "none";
}
}
}
<input type="image" id="slo" onclick="setLanguage('sl')">
<input type="image" id="ang" onclick="setLanguage('en')">
<input type="image" id="hrv" onclick="setLanguage('hr')">
<input type="image" id="rus" onclick="setLanguage('ru')">
<span class="lng sl radioS">Spol: </span>
<span class="lng en radioS">Gender: </span>
<span class="lng hr radioS">Spolov: </span>
<span class="lng ru radioS">секс: </span>
function setLanguage(language) {
// var 1
document
.getElementsByClassName("lng")
.forEach(lang => lang.classList.remove('visible'));
// var 2
document
.getElementByClassName('visible')
.forEach(el => el.classList.remove('visible'));
// show target lang
document.getElementById(language).classList.add('visible');
}
.lng {
display: none;
}
.visible {
display: block;
}
simply u can use radio buttons if it is checked that particular matching language will be displayed and others will be hidden.
$(document).ready(function() {
$("input").change(function() {
var len = document.getElementsByTagName("input");
for (var i = 0; i < len.length; i++) {
if (len[i].checked == 1) {
$(".lng." + len[i].id).show();
} else {
$(".lng." + len[i].id).hide();
}
}
});
});
.lng {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<input type="radio" id="sl" value="sl" name="lang"> sl
<input type="radio" id="en" value="sl" name="lang"> en
<input type="radio" id="hr" value="sl" name="lang"> hr
<input type="radio" id="ru" value="sl" name="lang"> ru
<br>
<span class="lng sl">Spol: </span>
<span class="lng en" class="en">Gender: </span>
<span class="lng hr" class="hr">Spolov: </span>
<span class="lng ru" class="ru">секс: </span>
Related
there is an onchange event on the input and want it to change the value of the spans with the class of "number" whenever it changes so there here is the HTML :
function myFunction() {
var x = document.getElementById("myText").value
document.querySelectorAll(".number").innerText = x
}
<div class="uper-container">
<p>Metric/Imperial unit conversion</p>
<!-- *********************************************************************************************** -->
<!-- this input will change the value of 6's span below with the class of "number" -->
<!-- ********************************************************************************************** -->
<input type="text" id="myText" placeholder="number here" value="20" onchange="myFunction()">
</div>
<div class="lower-container">
<p>Length(Meter/Feet)</p>
<p>
<span class="number"></span> meters = <span class="d"></span>feet |
<span class="number"></span> feet = <span class="d"></span>meters
</p>
<p>Volume(Liters/Gallons)
<</p>
<p>
<span class="number"></span> liter = <span class="d"></span>gallon |
<span class="number"></span> gallon = <span class="d"></span>liter
</p>
<p>Mass(Kilograms/Pounds)</p>
<p>
<span class="number"></span> kilogram = <span class="d"></span>pound |
<span class="number"></span> pound = <span class="d"></span>kilogram
</p>
</div>
so how to make spans with the class="number" have the same value as input id="myText"?
and one thing to mention is that I use scrimba editor.
Unlike jQuery, Vanilla JS will not execute innerText to every node returned by querySelectorAll with an inline call. You would need to loop through them.
The code below should work:
function myFunction() {
var x = document.getElementById("myText").value;
var spans = document.querySelectorAll(".number");
for (let i = 0; i < spans.length; i++) {
spans[i].innerText = x;
}
}
You can also use the for-of loop.
function myFunction() {
const x = document.getElementById("myText").value;
const numberElements = document.querySelectorAll(".number");
for (let element of numberElements) {
element.innerText = x;
}
}
When I click on the checkbox at the top, it puts a '0' in the total box, so I know that it is connected correctly, however I think there is a problem in the logic in the loop. One of the elements in html looks like this.
const form = document.getElementById('bookingForm');
const total = document.getElementById('total');
const checkboxes = document.querySelectorAll('input[data-price][type=checkbox]');
const cbamount = checkboxes.length;
document.getElementsByName('event[]')[0].onclick = function() {
totalPrice()
};
function totalPrice() {
let totalprice = 0;
for (let i = 0; i < cbamount; i++) {
const box = checkboxes[i];
if (box.checked) {
box.dataset.price = totalprice + box.dataset.price;
} //if
} //for
document.getElementsByName("total")[0].value = totalprice;
}
<span class="eventTitle">Carmen </span>
<span class="eventStartDate">2020</span>
<span class="eventEndDate">2020</span>
<span class="catDesc">T</span>
<span class="venueName">Mill </span>
<span class="eventPrice">3</span>
<span class="chosen"><input type="checkbox" name="event[]" value="11" data-price="35.00"></span>
<section id="Cost">
<h3>Total</h3>
Total <input type="text" name="total" size="20" readonly="">
</section>
You have no total in the code you provided.
I would personally use ID when only having one element and if more, use relative addressing and/or delegation
const form = document.getElementById('booking');
const total = document.getElementById('total');
document.getElementById("booking").addEventListener("click", function(e) {
if (e.target.name === "event[]") {
let totalprice = 0;
[...document.querySelectorAll('input[data-price][type=checkbox]')].forEach(function(box) {
if (box.checked) {
totalprice += +box.dataset.price;
} //if
})
document.querySelector("[name=total]").value = totalprice.toFixed(2);
}
})
<form id="booking" method="get">
<section id="book">
<h2>Select Events</h2>
<div class="item">
<span class="eventTitle">Carmen </span>
<span class="eventStartDate">2020</span>
<span class="eventEndDate">2020</span>
<span class="catDesc">T</span>
<span class="venueName">Mill </span>
<span class="eventPrice">3</span>
<span class="chosen"><input name="event[]" type="checkbox" value="11" data-price="35.00"></span>
</div>
<div class="item">
<span class="eventTitle">Ash</span>
<span class="eventStartDate">202</span>
<span class="eventEnd">2020-12-31</span>
<span class="catD">Exhib</span>
<span class="venueNa">The Biy</span>
<span class="eventPr">0.00</span>
<span class="chosen"><input type="checkbox" name="event[]" value="17" data-price="10.00"></span>
</div>
</section>
<section id="Cost">
<h3>Total</h3>
Total <input type="text" name="total" size="20" readonly="">
</section>
</form>
I have a list set up that throws two lists when content is put into a textbox, one list for a priority to-do list, and the other to delete unwanted content.
function chapter05() {
var uplist = document.getElementsByClassName('ch5')[0];
btn_colors = {
'hi': 'hiP',
'med': 'medP',
'low': 'lowP'
}
radios = document.getElementsByName('rgPrior');
for (var i = 0, length = radios.length; i < length; i++) {
if (radios[i].checked) {
btn_selected_color = (btn_colors[radios[i].value]);
break;
}
}
var todo = document.getElementById('txtAdd').value;
var entry = document.createElement('li');
entry.className = btn_selected_color;
entry.appendChild(document.createTextNode(todo));
uplist.appendChild(entry);
var botlist = document.getElementsByClassName('ch5')[1];
var todo = document.getElementById('txtAdd').value;
var entry = document.createElement('li');
var radio = document.createElement("input");
radio.type = "radio";
radio.name = radio;
radio.value = radio;
entry.appendChild(document.createTextNode("Delete this item: " + todo + " "));
entry.appendChild(radio);
botlist.appendChild(entry);
document.getElementById('txtAdd').value = " ";
}
function chapter05_del() {
}
.hiP {
color: red;
}
.medP {
color: blue;
}
.lowP {
color: green;
}
.ch5 {
padding-left: 30px;
}
<p style="">A to-do list</p>
<ol class="ch5"></ol>
<p> </p>
<p>
<label for="txtAdd">New thing to do:</label>
<input name="txtAdd" type="text" id="txtAdd" size="50" maxlength="50" />
</p>
<p>Set Priority</p>
<p>
<label>
<input type="radio" name="rgPrior" value="hi" id="rgPrior_0"/>High
</label>
<br/>
<label>
<input type="radio" name="rgPrior" value="med" id="rgPrior_1"/>Meduim
</label>
<br/>
<label>
<input type="radio" name="rgPrior" value="low" id="rgPrior_2"/>Low
</label>
<br/>
</p>
<p> </p>
<p>
<input type="button" name="btnAdd" id="btnAdd" value="Add a value" onClick="chapter05()" />
</p>
<br />
<p>Delete Items</p>
<ol class="ch5"></ol>
<p>
<input type="button" name="btnDel" id="btnDel" value="Delete an item" onClick="chapter05_del()" />
</p>
</article>
The first button is to input the data onto the page (add content to the lists) the second is to delete content.
I have the first part working the way I want it, so that when something is put into the text area and a priority radio button is clicked, it adds to a generated list both in the to-do list and the delete list, and the delete list creates a radio button next to the item.
Now, what I've been trying to accomplish is that in the chapter05_del() function, if a radio button in the delete list of the chapter05() function is clicked, it removes the corresponding items from both the to-do list, and the delete list.
TL;DR Once the user has chosen the element to delete, remove them from both lists.
You can find the updated code below. Comments in the code.
In chapter05, I have modified the below two lines to give a name and value to radio element created:
radio.name = "delete";
radio.value = todo;
function chapter05() {
var uplist = document.getElementsByClassName('ch5')[0];
btn_colors = {
'hi': 'hiP',
'med': 'medP',
'low': 'lowP'
}
radios = document.getElementsByName('rgPrior');
for (var i = 0, length = radios.length; i < length; i++) {
if (radios[i].checked) {
btn_selected_color = (btn_colors[radios[i].value]);
break;
}
}
var todo = document.getElementById('txtAdd').value;
var entry = document.createElement('li');
entry.className = btn_selected_color;
entry.appendChild(document.createTextNode(todo));
uplist.appendChild(entry);
var botlist = document.getElementsByClassName('ch5')[1];
var todo = document.getElementById('txtAdd').value;
var entry = document.createElement('li');
var radio = document.createElement("input");
radio.type = "radio";
radio.name = "delete";
radio.value = todo;
entry.appendChild(document.createTextNode("Delete this item: " + todo + " "));
entry.appendChild(radio);
botlist.appendChild(entry);
document.getElementById('txtAdd').value = " ";
}
function chapter05_del() {
var botlist = document.querySelectorAll('.ch5')[1];
var li = botlist.querySelectorAll("li input[type='radio']:checked");
if (li.length > 0) { //If user selected a radio button
var valToDelete = li[0].value; //Get radion button value
li[0].parentNode.parentNode.removeChild(li[0].parentNode); //Remove the todo item from delete list
var toplist = document.querySelectorAll('.ch5')[0]; //Get handle to top to-do
//Get handle to all li and loop
[].slice.call(toplist.querySelectorAll("li")).map(function (el){
if (el.innerText.trim() === valToDelete.trim()) el.parentNode.removeChild(el);
})
}
}
.hiP {
color: red;
}
.medP {
color: blue;
}
.lowP {
color: green;
}
.ch5 {
padding-left: 30px;
}
<p style="">A to-do list</p>
<ol class="ch5"></ol>
<p> </p>
<p>
<label for="txtAdd">New thing to do:</label>
<input name="txtAdd" type="text" id="txtAdd" size="50" maxlength="50" />
</p>
<p>Set Priority</p>
<p>
<label>
<input type="radio" name="rgPrior" value="hi" id="rgPrior_0"/>High
</label>
<br/>
<label>
<input type="radio" name="rgPrior" value="med" id="rgPrior_1"/>Meduim
</label>
<br/>
<label>
<input type="radio" name="rgPrior" value="low" id="rgPrior_2"/>Low
</label>
<br/>
</p>
<p> </p>
<p>
<input type="button" name="btnAdd" id="btnAdd" value="Add a value" onClick="chapter05()" />
</p>
<br />
<p>Delete Items</p>
<ol class="ch5"></ol>
<p>
<input type="button" name="btnDel" id="btnDel" value="Delete an item" onClick="chapter05_del()" />
</p>
I'm trying to sum the value of an input text changing dynamically with a radio that also changes dynamically. I'm doing something right but also something wrong because it doesn't sum when I want. The sum should show everytime the input text changes and not randomly disappear then you click a radio, just sum them.
the fiddle http://jsfiddle.net/7tFhx/
and the code
<form id="myForm" accept-charset="UTF-8">
<button type="button" class="btn-tt btn-primary btn-lg" disabled>1. Elige el color</button></br>
<label>
<input class="calc" id="fb1" type="radio" name="fb" value="10">
<img src="img/01.jpg"/>
</label>
<label>
<input class="calc" id="fb2" type="radio" name="fb" value="15">
<img src="img/02.jpg"/>
</label>
</br>
</br>
<button type="button" class="btn-tt btn-primary btn-lg" disabled>2. Elige las medidas</button></br>
<div class="row">
<div class="col-xs-2">
ancho (cm.)
<input id="ancho" type="text" class="form-control" placeholder="100">
</div>
<div class="col-xs-2">
alto (cm.)
<input id="alto" type="text" class="form-control" placeholder="100">
</div>
<div class="col-xs-2">
cantidad
<input id="cantidad" type="text" class="form-control" placeholder="1">
</div>
</div>
</br>
<button type="button" class="btn-tt btn-primary btn-lg" disabled>3. Posición mecanismo</button></br>
<label>
<input class="calc" id="fb3" type="radio" name="fb1" value="20">
<img src="img/01.jpg"/>
</label>
<label>
<input class="calc" id="fb4" type="radio" name="fb1" value="35">
<img src="img/02.jpg"/>
</label>
<div>
Total: <span id="price">0</span>€
</div>
</form>
js:
$(function(){
var mecanismoMedida = ['100','200'];
var mecanismoPrecio = ['50','80'];
$('#ancho').on('input',function(){
var j = 1, i = 0;
value = parseInt(($("#ancho").val() / 8) + 1);
for(i = 0; i < mecanismoMedida.length; i++){
if($("#ancho").val() >= mecanismoMedida[i] && $("#ancho").val() <
mecanismoMedida[j]){
value += mecanismoPrecio[i];
break;
} else {
j++;
}
}
$("#price").text(this.value + value);
});
$('#myForm input[type="radio"]').on('change', function () {
var sum = 0;
$("#myForm").find("input[type='radio']:checked").each(function () {
sum += parseInt(this.value);
});
$("#price").text(sum);
});
});
If it's a simple sum you're after, you can simply run an update code on the keyup and change events of all input elements:
$("input").change(function(){update();}).keyup(function(){update();});
To update them, first you need to check and see which one of the two radio buttons are checked and get its value:
function update(){
var p = 0;
for(var i = 0; i < $(".calc").val(); i++)
{
if($($(".calc")[i]).prop("checked") == true)
{
p += parseInt($($(".calc")[i]).val());
}
}
After that, simply parse the values of the textboxes to integers and add them to the value of the radio button. I created a custom function to do this, because if the boxes are empty, parsing them returns NaN:
p = parseInt(p);
p += parseInt(val2($("#ancho")));
p += parseInt(val2($("#alto")));
p += parseInt(val2($("#cantidad")));
p = parseInt(p);
$("#price").html(p);
}
function val2(elm){
if(isNaN(parseInt($(elm).val())))
return 0;
else
return parseInt($(elm).val());
}
JSFiddle
i have an .each() loop doing something on all matching elements. but i also have a way to add those elements.... i'm trying to get livequery to realize that a new element has been added and run it through the same each loop.
here's a general setup:
http://jsfiddle.net/CUURF/1/
basically, how do i use livequery and each together?
ultimately it is so that i can dynamically add tinymce editor textboxes in metaboxes, but i am fairly certain the problem is that my IDs aren't autoincremting on the add/clone, since the new element isn't in the DOM for the each loop.
edit- i think the biggest thing is that i need the index counter that comes standard w/ .each to work w/ livequery?
edit- here's the code from wpalchemy for looping/cloning
/* <![CDATA[ */
jQuery(function($)
{
$(document).click(function(e)
{
var elem = $(e.target);
if (elem.attr('class') && elem.filter('[class*=dodelete]').length)
{
e.preventDefault();
var p = elem.parents('.postbox'); /*wp*/
var the_name = elem.attr('class').match(/dodelete-([a-zA-Z0-9_-]*)/i);
the_name = (the_name && the_name[1]) ? the_name[1] : null ;
/* todo: expose and allow editing of this message */
if (confirm('This action can not be undone, are you sure?'))
{
if (the_name)
{
$('.wpa_group-'+ the_name, p).not('.tocopy').remove();
}
else
{
elem.parents('.wpa_group').remove();
}
the_name = elem.parents('.wpa_group').attr('class').match(/wpa_group-([a-zA-Z0-9_-]*)/i)[1];
checkLoopLimit(the_name);
$.wpalchemy.trigger('wpa_delete');
}
}
});
$('[class*=docopy-]').click(function(e)
{
e.preventDefault();
var p = $(this).parents('.postbox'); /*wp*/
var the_name = $(this).attr('class').match(/docopy-([a-zA-Z0-9_-]*)/i)[1];
var the_group = $('.wpa_group-'+ the_name +':first.tocopy', p);
var the_clone = the_group.clone().removeClass('tocopy');
var the_props = ['name', 'id', 'for'];
the_group.find('input, textarea, select, button, label').each(function(i,elem)
{
for (var j = 0; j < the_props.length; j++)
{
var the_prop = $(elem).attr(the_props[j]);
if (the_prop)
{
var the_match = the_prop.match(/\[(\d+)\]/i);
if (the_match)
{
the_prop = the_prop.replace(the_match[0],'['+(+the_match[1]+1)+']');
$(elem).attr(the_props[j], the_prop);
}
}
}
});
if ($(this).hasClass('ontop'))
{
$('.wpa_group-'+ the_name +':first', p).before(the_clone);
}
else
{
the_group.before(the_clone);
}
checkLoopLimit(the_name);
$.wpalchemy.trigger('wpa_copy', [the_clone]);
});
function checkLoopLimit(name)
{
var elem = $('.docopy-' + name);
var the_match = $('.wpa_loop-' + name).attr('class').match(/wpa_loop_limit-([0-9]*)/i);
if (the_match)
{
var the_limit = the_match[1];
if ($('.wpa_group-' + name).not('.wpa_group.tocopy').length >= the_limit)
{
elem.hide();
}
else
{
elem.show();
}
}
}
/* do an initial limit check, show or hide buttons */
$('[class*=docopy-]').each(function()
{
var the_name = $(this).attr('class').match(/docopy-([a-zA-Z0-9_-]*)/i)[1];
checkLoopLimit(the_name);
});
});
/* ]]> */
</script>
and the markup for inside my metabox:
<div id="testimonials">
<h2>Testimonials</h2>
<a style="float:right; margin:0 10px;" href="#" class="dodelete-testimonials button"><span class="icon delete"></span>Remove All</a>
<div id="wpa_loop-testimonials" class="wpa_loop wpa_loop-testimonials"><div class="wpa_group wpa_group-testimonials first">
<span class="icon delete"></span>Remove
<div class="slide_preview">
<div class="preview_wrap">
<img class="preview" src="" alt="preview" />
</div>
<input type="hidden" name="_sidebar_meta[testimonials][0][testimonial_image]" value="" class="img_src" />
<input type="hidden" name="_sidebar_meta[testimonials][0][slide_image_alt]" value="" class="img_alt" />
<button class="upload_image_button button" type="button"><span class="icon upload"></span>Change Photo</button>
</div>
<div class="slide_text">
<label>About Testimonial</label>
<div class="customEditor minimal">
<textarea rows="5" cols="50" name="_sidebar_meta[testimonials][0][testimonial_desc]">I realized it was ME causing all the problems</textarea>
</div>
</div>
</div> <div class="wpa_group wpa_group-testimonials last tocopy">
<h3 class="slide">Testimonial Name:
<input type="text" name="_sidebar_meta[testimonials][1][testimonial_name]" value="" />
</h3>
<span class="icon delete"></span>Remove
<div class="slide_preview">
<div class="preview_wrap">
<img class="preview" src="http://localhost/multi/wp-content/themes/callingintheone/functions/WPAlchemy/images/default_preview.png" alt="_sidebar_meta[testimonials][1][testimonial_image] Preview" />
</div>
<input type="hidden" name="_sidebar_meta[testimonials][1][testimonial_image]" value="" class="img_src" />
<input type="hidden" name="_sidebar_meta[testimonials][1][slide_image_alt]" value="" class="img_alt" />
<button class="upload_image_button button" type="button"><span class="icon upload"></span>Upload Photo</button>
</div>
<div class="slide_text">
<label>About Testimonial</label>
<div class="customEditor minimal">
<textarea rows="5" cols="50" name="_sidebar_meta[testimonials][1][testimonial_desc]"></textarea>
</div>
</div>
</div></div>
<p style="margin-bottom:15px; padding-top:5px;"><span class="icon add"></span>Add Testimonial</p>
</div>
the .tocopy class gets shifted by the alchemy code to a new hidden (by CSS) and last element
Your problem was that each was not executing with the clik. And after that there was nothing to make it run.
fixed code
Answer: http://jsfiddle.net/morrison/CUURF/6/
Notes:
Does not use livequery. There's no need to in this instance.
Keeps track of existing editors in an array. This is faster than cycling through the DOM every time you want an editor. DOM stuff is slow, arrays are fast. This also gives you easy access to any or all of the editors for other things you might do.
Doesn't cycle when a new editor is created. It simply modifies the new editor to have an id of the last one plus 1. This is a huge performance boost.