My old code looked like this:
function unhide(rad) {
var id = "answer" + rad.id.replace("-", "");
var answer = document.getElementById(id);
if (answer) {
var current = document.getElementById(currentShown);
if (current) current.className = "hidden";
currentShown = id;
answer.className = "unhidden";
}
}
When my radio button was clicked:
<input class="editable" type="radio" name="q1" id="q1-a" onclick="unhide(this); scoreIncrement(this);"/>John
It would unhide this div:
<div id="answerq1a" class="hidden">
<p>Your answer is correct, John is 6ft2.</p>
</div>
But now, my radio button must look like this:
<input class="editable" type="radio" name="q1" id="untitled-region-1" onclick="unhide(this); scoreIncrement(this);"/>John
and my div that I want to unhide has the same id, but as they are unique, it replaces the 1 with the next number up. In my case it is 4 id's down so the id would be "untitled-region-5" for the new id, as follows:
<div id="untitled-region-5" class="hidden">
<p>Your answer is correct, John is 6ft2.</p>
</div>
So how can I change this code, to grab the new id "untitled-region-5" and minus 4 from it to fix it to the radio button with the new id's?
function unhide(rad) {
var id = "answer" + rad.id.replace("-", "");
var answer = document.getElementById(id);
if (answer) {
var current = document.getElementById(currentShown);
if (current) current.className = "hidden";
currentShown = id;
answer.className = "unhidden";
}
}
I am going along this sort of track:
function unhide2(rad) {
var id = $("div").attr('id').replace(/untitled-region-/, 'untitled-region-');
var untitled-region = document.getElementById(id);
if (untitled-region) {
var current = document.getElementById(currentShown);
if (current) current.className = "hidden";
currentShown = id;
untitled-region.className = "unhidden";
}
}
But I don't know how to replace the last digit on the id with "digit-4".
You've tagged this with jQuery, so I'll give you the jQuery answer.
The right way to solve this is not to mash about with id's, but to link the radio, and it's associated div some other way, and IMO the best way is using a data- attribute.
<input class="editable" type="radio"
name="q1" id="q1-a" data-answerId="untitled-region-5"/>John
Then your javascript becomes easy-as:
$('.editable').click(function(){
$('#' + currentShown).removeClass('unhidden').addClass('hidden');
var answerId = $(this).data('answerId');
$('#' + answerId).removeClass('hidden').addClass('unhidden');
});
Although I urge you to do away with the unhidden, hidden confusion and just use .show() and .hide()!
Related
Here is the section which is confusing me:
<script type="text/javascript">
//declaring veriables
var inputField = document.getElementById("input");
var addBtn = document.getElementById("addBtn");
var html = "";
var x = 0;
addBtn.addEventListener('click', function(){
var text = inputField.value;
addToList(text);
})
//adds items to list
function addToList(text){
html += "<li id=(x+=1)><h4><input type='checkbox' id=(x+=1) onclick= 'clearspecifieditems()'>"+text+"</h4></li>";
document.getElementById("myList").innerHTML = html;
inputField.value = "";
}
//clears items
function clearspecifieditems(itemid)
{
//delete selected item
};
So the goal here is to create a to-do list (I'm new to coding). The addToList(text) function is supposed to create a new list item and assign a sequential ID to it. However, I cannot seem to figure out how to have it generate the ID. In addition, clearspecifieditems(itemid) is supposed to get the IDs of all the list items that are checked, and clear all of them.
For the first part of your question either use string concatenation similar to how you added the text variable...
function addToList(text) {
const id = x + 1;
html += '<li id="' + id + '"><h4><input type="checkbox" id="' + id + '">' + text + '</h4></li>';
// ..
}
...or use a template literal:
function addToList(text) {
const id = x + 1;
html += `<li id="${id}"><h4><input type="checkbox" id="${id}" />${text}</h4></li>`;
// ..
}
HOWEVER, for the second part, how to clear checked boxes:
I purposely left the onclick out of the above code because it sounds as if you need a separate button to clear the checkboxes:
// Grab the button and add an click listener to it
// to call `clearSpecifiedItems`
const button = document.querySelector('.clear');
button.addEventListener('click', clearSpecifiedItems, false);
function clearSpecifiedItems() {
// Select all the checked checkboxes using their class
const selected = document.querySelectorAll('.test:checked');
// Set their checked property to false (or null)
selected.forEach(input => input.checked = false);
}
<input class="test" type="checkbox" />
<input class="test" type="checkbox" />
<input class="test" type="checkbox" />
<input class="test" type="checkbox" />
<button class="clear">Clear</button>
Notice that none of these inputs have IDs. I've used a class to pick up the elements instead. So unless you're using the ids for anything else it makes the first part of your code redundant. Just use a CSS selector to grab the elements you need and then process them. No IDs required!
I can see what you're going for. You are almost there. Just a little bit of syntactical error, and a bit of a logical one.
You see, when you increment x two times, You will have a different id for the <li> and the <input>. What I suggest is you increment the x beforehand and then use it.
You can do it like this:
function addToList(text){
x++;
html += "<li id="+ x +"><h4><input type='checkbox' id="+ x +" onclick= 'clearspecifieditems()'>"+text+"</h4></li>";
document.getElementById("myList").innerHTML = html;
inputField.value = "";
}
or this (ES6)
function addToList(text){
x++;
html += `<li id=${x}><h4><input type='checkbox' id=${x} onclick= 'clearspecifieditems()'>${text}</h4></li>`;
document.getElementById("myList").innerHTML = html;
inputField.value = "";
}
Is it absolutely necessary that you must only increment? Can the ID's be truly unique? I suggest you use UUID in that case
Your second question is how to make clearspecifieditems work. Here's what you can do. You can pass the context, or simply the checkbox that was clicked and then get it's ID easily..
So you would define your function something like this:
function clearspecifieditems(element){
//delete selected item
console.log(element.id); // this would give you the ID of the selected checkbox and then you can do whatever with it
};
and slightly modify your function call on the click event
html += "<li id="+ x +"><h4><input type='checkbox' id="+ x +" onclick= 'clearspecifieditems(this)'>"+text+"</h4></li>";
Note this this part.
More more information, See this
Just use string interpolation to reference the x variable and increment it by one every time you add a new item as follows:
/* JavaScript */
var inputField = document.getElementById("input");
var addBtn = document.getElementById("addBtn");
var output = document.getElementById("output");
var html = "";
var x = 0;
function addToList(text) {
output.innerHTML += `<li id=id${x}><h4><input type='checkbox' id=${x}>This list item has an id: id${x}"</h4></li>`;
inputField.value = "";
x++;
}
addBtn.addEventListener('click', function(){
var text = inputField.value;
addToList(text);
})
<!-- HTML -->
<input type="text" id="input" />
<button id="addBtn">Add Items</button>
<div id="output"></div>
And for removing checked elements, simply add another button, say removeBtn and then add a click listener to the button that invokes the clearspecifieditems().
Inside the function, assign a variable to a list of all the checkboxes, loop through the variable using forEach and remove any checkbox that is not checked like this:
function clearspecifieditems() {
var check = document.querySelectorAll('[id^="id"]');
check.forEach(checkBox => {
if(checkBox.children[0].children[0].checked){
checkBox.remove();
}
});
}
removeBtn.addEventListener('click', clearspecifieditems);
#output {list-style: none;}
/* <input type="text" id="input" />
<button id="addBtn">Add Items</button> */
<ul id="output">
<li id="id0"><h4><input type="checkbox" id="input0">This list item has an id: id0"</h4></li>
<li id="id1"><h4><input type="checkbox" id="input1">This list item has an id: id1"</h4></li>
<li id="id2"><h4><input type="checkbox" id="input2">This list item has an id: id2"</h4></li>
<li id="id3"><h4><input type="checkbox" id="input3">This list item has an id: id3"</h4></li>
</ul>
<hr>
<button id="removeBtn">Remove</button>
You're sending X as 1. You should do like this :
var input = document.getElementById("input");
var div = document.getElementById("div");
var button = document.getElementById("addbutton");
var id = 0;
button.onclick = function() {
text = input.value;
addtask(text)
}
function addtask(text) {
var element = document.createElement("li");
element.setAttribute("id", id)
var deleteE = document.createElement("input");
deleteE.setAttribute("type", "checkbox");
deleteE.setAttribute("onclick", "deleteX(" + id + ")");
var node = document.createTextNode(text);
element.appendChild(deleteE);
element.appendChild(node);
div.appendChild(element);
id += 1;
}
function deleteX(id) {
document.getElementById(id).style.visibility = "hidden";
}
<input id="input"> <button id="addbutton"> add </button>
<div id="div"></br> </div>
Attempting my first Javascript project, playing around with DOM to make a To-Do List.
After adding an item, how do i get the 'Remove' button to function and remove the item + the remove button.
Furthermore, after a new entry is made, the list item still stays in the input field after being added. How can it be made to be blank after each list item.
And yes i know my code is kinda messy and there is most likely an easier way to create it but I understand it like this for now.
Any help is greatly appreciated. Thanks
JSFiddle Link : http://jsfiddle.net/Renay/g79ssyqv/3/
<p id="addTask"> <b><u> Tasks </u></b> </p>
<input type='text' id='inputTask'/>
<input type='button' onclick='addText()' value='Add To List'/>
function addText(){
var input = document.getElementById('inputTask').value;
var node=document.createElement("p");
var textnode=document.createTextNode(input);
node.appendChild(textnode);
document.getElementById('addTask').appendChild(node);
var removeTask = document.createElement('input');
removeTask.setAttribute('type', 'button');
removeTask.setAttribute("value", "Remove");
removeTask.setAttribute("id", "removeButton");
node.appendChild(removeTask);
}
You can simply assign event:
removeTask.addEventListener('click', function(e) {
node.parentNode.removeChild(node);
});
http://jsfiddle.net/g79ssyqv/6/
Edited the Fiddle... just try this
FiddleLink (Should work now, button and p-tag will be removed)
HTML
<p id="addTask"> <b><u> Tasks </u></b> </p>
<input type='text' id='inputTask'/>
<input type='button' onclick='addText()' value='Add To List'/>
JS
var row = 0;
function addText(){
var input = document.getElementById('inputTask').value;
if(input != "")
{
var node=document.createElement("p");
var textnode=document.createTextNode(input);
node.appendChild(textnode);
node.setAttribute("id","contentP"+row);
document.getElementById('addTask').appendChild(node);
var removeTask = document.createElement('input');
removeTask.setAttribute('type', 'button');
removeTask.setAttribute("value", "Remove");
removeTask.setAttribute("id", "removeButton");
removeTask.setAttribute("onClick", "deleterow("+ row +");");
node.appendChild(removeTask);
row++;
}
else
{
alert("Please insert a value!");
}
}
function deleterow(ID)
{
document.getElementById('contentP'+ID).remove();
}
Greetings from Vienna
Use this
// +your code
.....
node.appendChild(removeTask);
// + modify
removeTask.onclick = function(e){
var dom = this;
var p_dom = this.parentNode;
console.log(p_dom);
var parent_node = p_dom.parentNode;
parent_node.removeChild(p_dom);
}
Right now, I am storing two forms full of radiobuttons in separate div tags.
I need to be able to compare the checked radiobuttons from the left and right div tag.
Right now, I have this code to look for the checked values in the right and left div tags, however; it's checking the left div tag radiobutton values twice.
$('#btn').click(function() {
$("#right input[type='radio']:checked").each(function() {
var idVal = $(this).attr("id");
var rightcity = ($("label[for='"+idVal+"']").text());
console.log(rightcity);
$('#rightcity').text(rightcity);
});
$("#left input[type='radio']:checked").each(function() {
var idVal = $(this).attr("id");
var leftcity = ($("label[for='"+idVal+"']").text());
console.log(leftcity);
$('#leftcity').text(leftcity);
});
});
Any idea on how to specifically run this query for the right div tag values as well?
1st : if radios with same group in left/right . no need to loop through
2nd you can try this
$('#btn').click(function() {
var rightId = $("#right input[type='radio']:checked").attr("id");
var leftId = $("#left input[type='radio']:checked").attr("id");
var rightcity = $("label[for='"+rightId+"']").text();
var leftcity = $("label[for='"+leftId+"']").text();
console.log(rightcity);
$('#rightcity').text(rightcity);
console.log(leftcity);
$('#leftcity').text(leftcity);
});
maybe you don't need to get ids .. if your html
<label></label>
<input type="radio"/>
you can directly use .prev() instead of getting ids
var rightcity = $("#right input[type='radio']:checked").prev('label').text();
var leftcity = $("#left input[type='radio']:checked").prev('label').text();
and if its
<input type="radio"/>
<label></label>
use .next()
var rightcity = $("#right input[type='radio']:checked").next('label').text();
var leftcity = $("#left input[type='radio']:checked").next('label').text();
and about (be able to compare the checked radiobuttons from the left and right div tag)
var rightValue = $("#right input[type='radio']:checked").val();
var leftValue = $("#left input[type='radio']:checked").val();
So, I have the following jquery code that clones an element when the input value in a certain field increases.
$(document).ready(function(){
$("#nmovimentos").change(function () {
var direction = this.defaultValue < this.value
this.defaultValue = this.value;
if (direction)
{
var $div = $('div[id^="novomov"]:last');
var num = parseInt( $div.prop("id").match(/\d+/g), 10 ) +1;
var $clone = $div.clone().prop('id', 'novomov'+ num)
$clone.insertAfter('[id^="novomov"]:last');
}
else $('[id^="novomov"]:last').remove();
});
});
However, it clones a div that contains part of a form with lots of input fields.
<div id="novomov1" class="novomov">
<table id="tab">
<tr name="linear1" id="linear1">
<td>
Cardinalidade:<input type="text" name="card1" id="card1" value=""><br>
Angulo 1:<input type="text" name="param1" id="angulo1" value=""><br>
Angulo 2:<input type="text" name="param2" id="angulo2" value=""><br>
Tamanho:<input type="text" name="param3" id="tamanho1" value=""><br>
Descricao:<input type="text" name="descricao1" id="descricao1" value=""><br>
Tempo:<input type="text" name="tempo1" id="tempo1" value=""><br>
</td></tr></table></div>
I need to change the names of all the cloned div's descendents, in order to pass these paramaters to a data base. I thought of incrementing the names by 1, using the var num in the jquery function. However I'm I little lost.. so, any clues on how to do that? thank you very much!
Code changed to retrieve all the inputs inside the cloned div and change its name/id.
<script>
$(document).ready(function(){
$("#nmovimentos").change(function () {
var direction = this.defaultValue < this.value
this.defaultValue = this.value;
if (direction)
{
var $div = $('div[id^="novomov"]:last');
var num = parseInt( $div.prop("id").match(/\d+/g), 10 ) +1;
var $clone = $div.clone().prop('id', 'novomov'+ num)
$clone.insertAfter('[id^="novomov"]:last');
// get all the inputs inside the clone
var inputs = $clone.find('input');
// for each input change its name/id appending the num value
$.each(inputs, function(index, elem){
var jElem = $(elem); // jQuery element
var name = jElem.prop('name');
// remove the number
name = name.replace(/\d+/g, '');
name += num;
jElem.prop('id', name);
jElem.prop('name', name);
});
}
else $('[id^="novomov"]:last').remove();
});
});
</script>
Instead of parsing the id of the element to get the number you should use the data attribute. Also since you are using jQuery you can use .last() to get the last element with that id. Hope this helps.
$('#nmovimentos').on('change', function () {
var direction = this.defaultValue < this.value,
$last = $('#novomov').last(),
$clone,
num;
this.defaultValue = this.value;
if (direction) {
// add id in a data attribute instead of parsing the id
num = parseInt($last.data('id'), 10) + 1;
// set clone id data attribute to have the latest number
$clone = $last.clone().data('id', num);
// add clone after the last div
$last.after($clone);
} else {
$last.remove();
}
});
I need to have buttons for moving up and down table rows with input's inside.
On move I need to guarantee that the input's name's and id's are changed
regarding to their new position
I've tried around on JSFiddle but couldn't get it to work: http://jsfiddle.net/vaDkF/1194/
For example I've the first row is moved down there are four changes:
<input type="text" id="id_1" name="id_1"/>
<input type="text" id="test_1" name="test_1"/>
needs to become
<input type="text" id="id_2" name="id_2"/>
<input type="text" id="test_2" name="test_2"/>
but the values need's to stay the same just need the id/name to change.
This is just a test example, in production environment I have like 20 inputs
per row.
Hope someone can help.
Try this : after rearranging the rows, call a function which will reassigne id and name to the input fields
$(document).ready(function(){
$(".up,.down").click(function(){
var row = $(this).parents("tr:first");
if ($(this).is(".up")) {
row.insertBefore(row.prev());
} else {
row.insertAfter(row.next());
}
reAssignIdAndName();
});
reAssignIdAndName = function(){
$('table tr').each(function(index){
$(this).find('td:eq(2) input').each(function(){
//id of input element
var id = $(this).attr('id');
//get index of underscrore
var underScoreIndex = id.indexOf('_');
//take id till underscore and append your index+1 value
id = id.substring(0,underScoreIndex+1)+(parseInt(index)+1);
//assigne new id and name
$(this).attr('id',id);
$(this).attr('name',id);
});
});
};
});
Demo
This works and reAssign the position only for the 2 rows that moved :
jQuery(document).ready(function($){
$(".up,.down").click(function(){
var $this = $(this),
row = $this.parents("tr:first");
if ($this.is(".up")) {
if (row.parent().find("tr:first").get(0) !== row.get(0)) {
reAssignPosition(row.prev().find('input'));
row.insertBefore(row.prev());
reAssignPosition(row.find('input'), true);
}
} else {
if (row.parent().find("tr:last").get(0) !== row.get(0)) {
reAssignPosition(row.next().find('input'), true);
row.insertAfter(row.next());
reAssignPosition(row.find('input'));
}
}
});
function reAssignPosition($elt, up) {
var $row = $elt.parents("tr:first"),
oldPosition = parseInt($row.find('input').attr('id').replace(/(id|test)_/, '')),
newPosition, newId, newName, input = $row.find('input');
if (up) newPosition = oldPosition - 1;
else newPosition = oldPosition + 1;
$elt.each(function() {
this.id = this.id.replace(/(id|test)_(.*)/, "$1_" + (newPosition));
this.name = this.name.replace(/(id|test)_(.*)/, "$1_" + (newPosition));
});
}
});
Some refactoring can be done, I am sure, though.