Replace all XX attributes to numeric ID with jQuery - javascript

I'm trying to clone a div element by clicking on an a element. And when that div cloned, all XX attributes change to it's numeric ID.
For example:
for="gr_name_XX" to for="gr_name_1"
name="grfield[XX][name]" to name="grfield[1][name]"
id="gr_name_XX" to id="gr_name_1"
I'm trying to do that, but only the div element's ID attribute doing this function and change to numeric ID. Sorry, I'm novice in javascript and jQuery coding. It's my code:
var elementCounter = 0;
jQuery(document).ready(function() {
jQuery("#add-new-game").click(function() {
var elementRow = jQuery("#placeholder-item").clone();
var newId = "gr-item-" + elementCounter;
elementRow.attr("id", newId);
elementRow.show();
// Where I have problem!!
elementRow.each(function() {
elementRow.html().replace(/XX/g, elementCounter);
});
var removeLink = jQuery("a", elementRow).click(function() {
removeElement(elementRow);
return false;
});
elementCounter++;
jQuery("input[name=element-max-id]").val(elementCounter);
jQuery(".add-and-remove-items").append(elementRow);
return false;
});
});
function removeElement(element) {
jQuery(element).remove();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sortable-items add-and-remove-items settings-items gr-items"></div>
<input type="hidden" name="element-max-id" />
Add new
<div class="sortable-item add-and-remove-item settings-item gr-item front-page-element" id="placeholder-item" style="display: none;">
<label for="gr_name_XX" style="width: 90px; display: inline-block;">Name: </label>
<input type="text" name="grfield[XX][name]" class="regular-text" id="gr_name_XX" value="" />
<label for="gr_genre_XX" style="width: 90px; display: inline-block;">Genre: </label>
<input type="text" name="grfield[XX][genre]" class="regular-text" id="gr_genre_XX" value="" />
<br>
<label for="gr_backg_XX" style="width: 90px; display: inline-block;">Background: </label>
<input type="text" name="grfield[XX][backg]" class="regular-text" id="gr_backg_XX" value="" />
<label for="gr_date_XX" style="width: 90px; display: inline-block;">Date: </label>
<input type="text" name="grfield[XX][date]" class="regular-text" id="gr_date_XX" value="" />
<label for="gr_nc_XX"><input type="checkbox" name="grfield[XX][nc]" id="gr_nc_XX" value="1" /> String date</label>
Remove<br>
</div>
What am I doing wrong? Thanks...

You don't need to use each and also .html() only returns the markup content. For updating, you need to do .html(YOUR-UPDATE-CODE),
change,
// Where I have problem!!
elementRow.each(function() {
elementRow.html().replace(/XX/g, elementCounter);
});
To
elementRow.html(elementRow.html().replace(/XX/g, elementCounter));
Demo:
var elementCounter = 0;
jQuery(document).ready(function() {
jQuery("#add-new-game").click(function() {
var elementRow = jQuery("#placeholder-item").clone();
var newId = "gr-item-" + elementCounter;
elementRow.attr("id", newId);
elementRow.show();
elementRow.html(elementRow.html().replace(/XX/g, elementCounter));
var removeLink = jQuery("a", elementRow).click(function() {
removeElement(elementRow);
return false;
});
elementCounter++;
jQuery("input[name=element-max-id]").val(elementCounter);
jQuery(".add-and-remove-items").append(elementRow);
return false;
});
});
function removeElement(element) {
jQuery(element).remove();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sortable-items add-and-remove-items settings-items gr-items"></div>
<input type="hidden" name="element-max-id" />
Add new
<div class="sortable-item add-and-remove-item settings-item gr-item front-page-element" id="placeholder-item" style="display: none;">
<label for="gr_name_XX" style="width: 90px; display: inline-block;">Name: </label>
<input type="text" name="grfield[XX][name]" class="regular-text" id="gr_name_XX" value="" />
<label for="gr_genre_XX" style="width: 90px; display: inline-block;">Genre: </label>
<input type="text" name="grfield[XX][genre]" class="regular-text" id="gr_genre_XX" value="" />
<br>
<label for="gr_backg_XX" style="width: 90px; display: inline-block;">Background: </label>
<input type="text" name="grfield[XX][backg]" class="regular-text" id="gr_backg_XX" value="" />
<label for="gr_date_XX" style="width: 90px; display: inline-block;">Date: </label>
<input type="text" name="grfield[XX][date]" class="regular-text" id="gr_date_XX" value="" />
<label for="gr_nc_XX"><input type="checkbox" name="grfield[XX][nc]" id="gr_nc_XX" value="1" /> String date</label>
Remove<br>
</div>

What you are going to do is first get and loop the children of your elementRow then loop through each attribute of that child:
// get and loop through each children
$(elementRow).children().each(function () {
var child = $(this)[0];
// loop through each attribute
for (var i = 0; i < child.attributes.length; i++)
{
var attributeVal = child.attributes[i].value;
// check if attribute value contains XX
if (attributeVal.indexOf("XX") != -1)
{
// replace it
child.attributes[i].value = attributeVal.replace(/XX/g, elementCounter)
}
}
});
$(this)[0] is a way of getting the original javascript HTML object reference instead of getting jQuery object.
.attributes is a property of JS HTML Object and does not exist in jQuery HTML object.
working fiddle based on your example
hope that helps.

Related

JavaScript function not working as desired

I'm working with HTML, JavaScript and CSS. The function objective is to create a border-radius attribute in a div element(id="surface"), and assign the value typed in inputs texts(class="chars_1") to it.
HTML
<div id="container">
<div class="input_wrapper" id="input_wrapper_tl">
<input type="text" id="input_tl" class="chars_1" value="0" onkeypress="changeSize()">
</div>
<div class="input_wrapper" id="input_wrapper_tr">
<input type="text" id="input_tr" class="chars_1" value="0" onkeypress="changeSize()">
</div>
<div class="input_wrapper" id="input_wrapper_br">
<input type="text" id="input_br" class="chars_1" value="0" onkeypress="changeSize()">
</div>
<div class="input_wrapper" id="input_wrapper_bl">
<input type="text" id="input_bl" class="chars_1" value="0" onkeypress="changeSize()">
</div>
<div id="surface">
<textarea id="code" readonly="readonly"></textarea>
<div id="options">
<input type="checkbox" checked="true" id="opt_webkit">
<label for="opt_webkit"> Webkit</label>
<input type="checkbox" checked="true" id="opt_gecko">
<label for="opt_gecko"> Gecko</label>
<input type="checkbox" checked="true" id="opt_css3">
<label for="opt_css3"> CSS3</label>
</div>
</div>
JavaScript Function
function changeSize(){
var surface = document.getElementById("surface");
var inputs = document.getElementsByClassName("chars_1");
var total = 0;
for(var x = 0; x == 3; x++){
total += Number(inputs[x].value);
}
surface.style.borderRadius = String(total)+"px";
}
First I selected both elements and assigned it to these 2 variable "surface" and "inputs". "total" being used in the "for structure" to go through every input element and select every value, and afterward convert to Number to the "total" variable.
The idea is to assign to the border-radius attribute the total variable value, which will be converted to a string so it can be recognized as a value.
Have a border
Fix the for loop for (var x = 0; x < inputs.length; x++) {
Here is an upgraded version
const changeSize = (e) => {
const tgt = e.target; // which input
if (tgt.classList.contains("chars_1")) { // ah, one of those
let total = [...document.querySelectorAll(".chars_1")].reduce(
(sum, input) => {
const val = input.value;
sum += val.trim() === "" || isNaN(val) ? 0 : +val; // only add if a number
return sum;
}, 0);
console.log(String(total) + "px")
document.getElementById("surface").style.borderRadius = String(total) + "px";
}
};
window.addEventListener("load", () => { // when page loads
document.getElementById("container").addEventListener("input", changeSize);
});
#surface {
border: 3px solid black;
}
<div id="container">
<div class="input_wrapper" id="input_wrapper_tl">
<input type="text" id="input_tl" class="chars_1" value="0">
</div>
<div class="input_wrapper" id="input_wrapper_tr">
<input type="text" id="input_tr" class="chars_1" value="0">
</div>
<div class="input_wrapper" id="input_wrapper_br">
<input type="text" id="input_br" class="chars_1" value="0">
</div>
<div class="input_wrapper " id="input_wrapper_bl ">
<input type="text" id="input_bl " class="chars_1" value="0">
</div>
<div id="surface">
<textarea id="code" readonly="readonly"></textarea>
<div id="options">
<input type="checkbox" checked="true" id="opt_webkit">
<label for="opt_webkit"> Webkit</label>
<input type="checkbox" checked="true" id="opt_gecko">
<label for="opt_gecko"> Gecko</label>
<input type="checkbox" checked="true" id="opt_css3">
<label for="opt_css3"> CSS3</label>
</div>
</div>
for(var x = 0; x == 3; x++)
that loop doesn't even execute,
change x==3 on x<3 or whatever you want to achive.
And I guess you must have border to change it's radious

Change div color by finding input background-color

How do I change the JavaScript code to find the input label's HTML background-color instead of having to manually insert the color into the JavaScript like in this snippet?
function ChangeColor(color) {
var clrDiv = document.getElementsByClassName("colorDiv")[0];
clrDiv.style.backgroundColor = color;
}
document.getElementById("select1").onclick = function() {
ChangeColor("red");
}
document.getElementById("select2").onclick = function() {
ChangeColor("green");
}
document.getElementById("select3").onclick = function() {
ChangeColor("blue");
}
.colorDiv {
width: 50px;
height: 50px;
}
<section>
<input id="select1" name="test" type="radio" />
<label style="background-color:red;" for="select1">Red</label>
<input id="select2" name="test" type="radio" />
<label style="background-color:green;" for="select2">Green</label>
<input id="select3" name="test" type="radio" />
<label style="background-color:blue;" for="select3">Blue</label>
</section>
<footer>
<div class="colorDiv"></div>
</footer>
Is this what you are looking for? Instead of a color, I pass the id of the select, find the label for the input, and then use that label's background color to set the div background color.
If you are alright using jquery this could be greatly simplified.
function findLableForControl(el) {
var idVal = el.id;
labels = document.getElementsByTagName('label');
for( var i = 0; i < labels.length; i++ ) {
if (labels[i].htmlFor == idVal)
return labels[i];
}
}
function ChangeColor(color) {
var clrDiv = document.getElementsByClassName("colorDiv")[0];
clrDiv.style.backgroundColor = findLableForControl(document.getElementById(color)).style.backgroundColor;;
}
document.getElementById("select1").onclick = function() { ChangeColor("select1"); }
document.getElementById("select2").onclick = function() { ChangeColor("select2"); }
document.getElementById("select3").onclick = function() { ChangeColor("select3"); }
.colorDiv{
width:50px;
height:50px;
}
<section>
<input id="select1" name="test" type="radio" />
<label style="background-color:red;" for="select1">Red</label>
<input id="select2" name="test" type="radio" />
<label style="background-color:green;" for="select2">Green</label>
<input id="select3" name="test" type="radio" />
<label style="background-color:blue;" for="select3">Blue</label>
</section>
<footer>
<div class="colorDiv"></div>
</footer>
You can make your code much simpler by following a few easy steps:
Assign the ChangeColor function directly to the onclick, no need for an intermediary anonymous function and no need to pass anything.
In the ChangeColor function, use this to access the element that raised the event (i.e. the input that you clicked on).
Use the querySelector function to select the associated label by its for attribute.
function ChangeColor() {
var clrDiv = document.getElementsByClassName("colorDiv")[0];
clrDiv.style.backgroundColor = document.querySelector("label[for=" + this.id + "]").style.backgroundColor;
}
document.getElementById("select1").onclick = ChangeColor;
document.getElementById("select2").onclick = ChangeColor;
document.getElementById("select3").onclick = ChangeColor;
.colorDiv {
width: 50px;
height: 50px;
}
<section>
<input id="select1" name="test" type="radio" />
<label style="background-color:red;" for="select1">Red</label>
<input id="select2" name="test" type="radio" />
<label style="background-color:green;" for="select2">Green</label>
<input id="select3" name="test" type="radio" />
<label style="background-color:blue;" for="select3">Blue</label>
</section>
<footer>
<div class="colorDiv"></div>
</footer>

Second text field should be inactive while clicking on 1st text field's radio button

I have two text fields with radio buttons.
When I click on 1st button that text field should be active and other text field should be inactive.
But, When I click on 2nd button both text fields are in active mode.
I need only one field should be active on clicking button and other should be in inactive mode.
I have this HTML code
<form name="myform" action="">
<input type="radio" id="yourBox" value="text1" style="margin-left: 15px; margin-right: 5px;" />
<input type="text" `enter code here`id="yourText" disabled="disabled" style="margin-left: 15px; width: 349px;" />
<input type="radio" id="yourBox1" value="text2" style="margin-left: 30px;margin-right: 5px;" />
<input type="text" id="id2" disabled="disabled" style="margin-left: 15px; width: 352px;" />
</form>
Ξ‘nd my JavaScript code:
<script>
document.getElementById('yourBox').onchange = function() {
document.getElementById('yourText').disabled = !this.checked;
};
document.getElementById('yourBox1').onchange = function() {
document.getElementById('id2').disabled = !this.checked;
};
</script>
First of all, you have typo in your code. Second, you should improve the code for efficiency, but this is out of the scope of what you are asking. Here is a working code modified from your original post:
<form name="myform" action="">
<input type="radio" id="yourBox" value="text1" style="margin-left: 15px; margin-right: 5px;" />
<input type="text" value="enter code here" id="yourText" disabled="disabled" style="margin-left: 15px; width: 349px;" /><br/>
<input type="radio" id="yourBox1" value="text2" style="margin-left: 30px;margin-right: 5px;" />
<input type="text" id="id2" disabled="disabled" style="margin-left: 15px; width: 352px;" />
</form>
<script>
var yourBox = document.getElementById('yourBox');
var yourBox1 = document.getElementById('yourBox1');
yourBox.onchange = function() {
yourBox1.checked = !this.checked;
document.getElementById('yourText').disabled = !this.checked;
document.getElementById('id2').disabled = this.checked;
};
yourBox1.onchange = function() {
yourBox.checked = !this.checked;
document.getElementById('id2').disabled = !this.checked;
document.getElementById('yourText').disabled = this.checked;
};
</script>
Here is a JSFiddle: http://jsfiddle.net/swfh0qo5/
Check following way you can do it. You have to give name property to input radio button So if one select then another get de-selected.
HTML:
<input type="radio" id="yourBox" name="test" value="text1" style="margin-left: 15px; margin-right: 5px;" />
<input type="radio" id="yourBox1" name="test" value="text2" style="margin-left: 30px;margin-right: 5px;" />
JS:
<script>
document.getElementById('yourBox').onchange = function() {
document.getElementById('yourText').disabled = !this.checked;
document.getElementById('id2').disabled = this.checked;
};
document.getElementById('yourBox1').onchange = function() {
document.getElementById('id2').disabled = !this.checked;
document.getElementById('yourText').disabled = this.checked;
};
</script>
Fiddle
try this simply with Jquery
$("#c1").on("change", function() {
if ($("#c1:checked").length > 0) {
$("#t1").removeAttr("disabled");
$("#t2").attr("disabled", true);
} else {
$("#t1").attr("disabled", true);
}
})
$("#c2").on("change", function() {
if ($("#c2:checked").length > 0) {
$("#t2").removeAttr("disabled");
$("#t1").attr("disabled", true);
} else {
$("#t2").attr("disabled", true);
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="checkbox" id="c1">button1</input>
<input type="checkbox" id="c2" text="button2">button2</input>
<input type="text" id="t1" disabled placeholder="text1" />
<input type="text" id="t2" disabled placeholder="text2" />

How to show form fields on keyup

I've been working on this for weeks now and I can't seem to get the hang of this. I'm trying to show the hidden fields only when the previous fields are entered. Here's my example code:
HTML
<form>
<div id="group1">
<label>Field 1:</label>
<input type="text" class="field1" />
<br/>
<label>Field 2:</label>
<input type="text" class="field2" />
<br/>
<label>Field 3:</label>
<input type="text" class="field3" />
<br/>
</div>
<div id="group2">
<label>Field 4:</label>
<input type="text" class="field4" />
<br/>
<label>Field 5:</label>
<input type="text" class="field5" />
<br/>
<label>Field 6:</label>
<input type="text" class="field6" />
<br/>
</div>
<div id="group3">
<label>Field 7:</label>
<input type="text" class="field7" />
<br/>
<label>Field 8:</label>
<input type="text" class="field8" />
<br/>
<label>Field 9:</label>
<input type="text" class="field9" />
<br/>
<input type="submit" value="Submit">
</div>
</form>
CSS
#group2 {
visibility: hidden;
}
#group3 {
visibility: hidden;
}
Script
$(document).ready(function () {
$('#group1').find('input[type="text"]').keyup(function () {
CheckSubmit();
});
function CheckSubmit() {
var x = true;
$('#group1').find('input[type="text"]').keyup(function () {
if ($(this).val().length === 0) {
x = false;
return;
}
});
if (x) {
$('#group2').css('visibility', 'visible');
$('#group3').css('visibility', 'visible');
} else {
$('#group2').css('visibility', 'hidden');
$('#group3').css('visibility', 'hidden');
}
CheckSubmit();
});
I'm not sure what I'm doing wrong here. Can someone please assist?
I changed your code a bit. I stored the relevant selectors in variables, so you don't need to do a lot of re-querying every time something changes.
Here's the updated code:
JavaScript
var inputs = $('#group1').find('input[type="text"]');
var hidden = $('#group2, #group3');
inputs.keyup(function() {
var test = true;
inputs.each(function(key, value) {
if (!$(this).val().length) {
test = false;
return false;
}
});
hidden.css('visibility', ( test ? 'visible' : 'hidden' ) );
});
Demo
Try before buy
You can make this more dynamic by checking the inputs in the current div and if they all have a value, then show the next div (if there is one).
If they clear a value, then hide all the later divs.
$(document).ready(function() {
// you can restrict this to inputs in a specific div or just any input
$('#group1 input').on('keyup', function () {
var parentDiv = $(this).closest('div')
var hasValues = parentDiv.find('input').filter(function() {
return this.value == '';
}).length == 0;
if(hasValues) {
//parentDiv.next().css('visibility', 'visible'); // show just the next section
parentDiv.nextAll().css('visibility', 'visible'); // show all later sections
} else {
parentDiv.nextAll().css('visibility', 'hidden');
}
});
});
DEMO
I made a quick pen with a solution. It may not be the prettiest but it get's it done. Basically on every keyup event I check #group1's children for their value length and if they all have a length that's more than 0 I change a flag in an array. If all 3 flags are true I show #group2.
Here's the pen
$('#group2').hide();
$('#group3').hide();
$('#group1').keyup(function() {
var flags = {
0: false,
1: false,
2: false
}
$('#group1 > input').each(function(i, ele) {
if(ele.value.length !== 0)
{
flags[i] = true;
}
});
if(flags[0] && flags[1] && flags[2])
{
$('#group2').show();
}
});
$('#group2').keyup(function() {
var flags = {
0: false,
1: false,
2: false
}
$('#group2 > input').each(function(i, ele) {
if(ele.value.length !== 0)
{
flags[i] = true;
}
});
if(flags[0] && flags[1] && flags[2])
{
$('#group3').show();
}
});
Hope it helps :D
If I understand your question well, you want to show the fields in #group2/-3 if all the fields in the previous fields have a value. Using a few data-*-attributes (see MDN), you can create a handler like this (if you prefer: jsFiddle, containing a more complete example):
$('[data-nextgroup] [type=text]').on('keyup', function (e){
var fieldgroup = $(this.getAttribute('data-group'))
,fields = fieldgroup.find('[type=text]')
,canshow = fields.length ===
fields.filter( function (i,el) { return el.value.length; } ).length;
void( canshow && $(fieldgroup.attr('data-nextgroup')).fadeIn() );
});
[data-hidden] {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="group1" data-nextgroup="#group2">
<label>Field 1:</label>
<input type="text" class="field1" data-group="#group1"/>
<br/>
<label>Field 2:</label>
<input type="text" class="field2" data-group="#group1"/>
<br/>
<label>Field 3:</label>
<input type="text" class="field3" data-group="#group1"/>
<br/>
</div>
<div id="group2" data-nextgroup="#group3" data-hidden>
<label>Field 4:</label>
<input type="text" class="field4" data-group="#group2"/>
<br/>
<label>Field 5:</label>
<input type="text" class="field5" data-group="#group2"/>
<br/>
<label>Field 6:</label>
<input type="text" class="field6" data-group="#group2"/>
<br/>
</div>
<div id="group3" data-groups data-hidden>
<label>Field 7:</label>
<input type="text" class="field7" />
<br/>
<label>Field 8:</label>
<input type="text" class="field8" />
<br/>
<label>Field 8:</label>
<input type="text" class="field9" />
<br/>
<input type="submit" value="Submit">
</div>

Check if input text is filled and display different divs

I have 3 input text and I want to display a div if one over 3 is filled, a different div if 2 input over 3 are filled and so on. How can I do it with javascript?
<input type="text" id="text1" name="text1" />
<input type="text" id="text2" name="text2" />
<input type="text" id="text3" name="text3" />
I tried this but it doesn't work
function display() {
if ($('#text').val() != '') {
document.getElementById('green').style.display = 'block';
}   
}
CSS
#a, #b, #c {
visibility:hidden;
}
HTML
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>
JavaScript
var istext1filled = document.querySelector('input#text1').value.length>0;
var istext2filled = document.querySelector('input#text2').value.length>0;
var istext3filled = document.querySelector('input#text3').value.length>0;
if(istext1filled) {
document.querySelector('div#a').style.visibility = 'visible';
}
if(istext2filled) {
document.querySelector('div#b').style.visibility = 'visible';
}
if(istext3filled) {
document.querySelector('div#c').style.visibility = 'visible';
}
I think there's a misunderstanding here. #Domenico asked
I have 3 input text and I want to display a div if one over 3 is filled, a different div if 2 input over 3 are filled and so on.
If I am not misunderstanding his statement: I think he is talking about the number of inputs that were filled and not necessarily the particular input that was filled.
Hence JSFiddle:
#div_1, #div_2, #div_3{
display: none;
}
<input type="text" id="text_1" name="text1" value="" />
<input type="text" id="text_2" name="text2" value=""/>
<input type="text" id="text_3" name="text3" value="" />
<div id="div_1">Only ONE input is filled</div>
<div id="div_2">Only TWO inputs are filled</div>
<div id="div_3">All THREE inputs are filled</div>
$(document).ready(function() {
$("input[id*='text']").blur(function() {
var counter=0;
$("input[id*='text']").each(function(ind, val){
if($(val).val().trim()!==""){
counter++;
}
});
$("#div_1, #div_2, #div_3").hide();
$("#div_"+counter).show();
});
});
But if you want it the other way round, here is the solution too:
#div_1, #div_2, #div_3{
display: none;
}
<input type="text" id="text_1" name="text1" value="" />
<input type="text" id="text_2" name="text2" value=""/>
<input type="text" id="text_3" name="text3" value="" />
<div id="div_1">Input ONE is filled</div>
<div id="div_2">Input TWO is filled</div>
<div id="div_3">Input THREE is filled</div>
$(document).ready(function() {
$("input[id*='text']").blur(function() {
$("#div_1, #div_2, #div_3").hide();
$("input[id*='text']").each(function(ind, val) {
if ($(val).val().trim() !== "") {
console.log("div_"+$(val).prop("id").split("_")[1])
$("#div_"+$(val).prop("id").split("_")[1]).show();
}
});
});
});

Categories