I need help with this. I need to make the value in the other place change all the time while user session is active. How can I get the value from a span and make other value in a data change?
Look at there!
1 <div class="pt-uea-container">
2 <span class="pt-uea-currency pt-uea-currency-before"> € </span>
3 <input type="text" class="pt-field pt-uea-custom-amount" autocomplete="off" name="pt_items[1][amount]" id="pt_uea_custom_amount_1" value="199" placeholder="" data-parsley-errors-container="#pt_uea_custom_amount_errors_1">
4 <input type="hidden" class="pt-field pt-uea-custom-amount-formatted" name="pt_items[1][amount]" value="199" data-pt-price="199">
5 <input type="hidden" name="pt_items[1][label]" value="Amount:">
6 <input type="hidden" name="pt_items[1][tax_percentage]" value="0">
7 <input type="hidden" name="pt_items[1][type]" value="open">
8 <div id="pt_uea_custom_amount_errors_1"></div>
9 <span class="form-price-value">85</span>
10 </div>
The value in row 9 needs to constantly change values in row 3 and 4 on the same session. Don't mind the value in row 6.
Let me know how I can get this done. Or maybe a different approach?
Greetings!
========
So this is what I got for now from you guys:
jQuery(document).ready(function($) {
var checkViewport = setInterval(function() {
var spanVal = $('.form-price-value').text();
$('#pt_uea_custom_amount_1').val(spanVal);
$('#pt_uea_custom_amount_formatted_1').val(spanVal);
$('#pt_uea_custom_amount_formatted_1').attr('data-pt-price', spanVal);
}, 1000);
});
This code works, but it only affects my needs when I put my mouse in pt-field pt-uea-custom-amount and add a space in it. Then it does apply to the page source. But this is not correct. The source needs to get changed too without touching that class or a space or something!
You can easily do this with the help of jQuery.
With the help of jQuery I would do like this.
Understanding what input field needs to be tracked for changes. I will give all this field a class (track-me).
In the document ready, I will look for changes for that tracked field.
On change of that field I will get the value and put in other input fields (class copy-to - or you can do whatever you like).
See an example below,
HTML
<form>
<div class="">
<input type="text" class="track-me" value=""/>
</div>
<div class="">
<input type="text" class="copy-to" value=""/>
</div>
<div class="">
<input type="text" class="copy-to" value=""/>
</div>
<div class="">
<input type="text" class="copy-to" value=""/>
</div>
<div class="">
<div class="">Please type anything in the first input box</div>
</div>
</form>
jQuery
$(document).ready(function(){
$('.track-me').change(function (){
$('.copy-to').val($(this).val())
});
});
I made comments in the above jQuery code so you can understand. Also, I have made a fiddle so you can play and have a look. In this fiddle, I am using Bootstrap4 just for the purpose of styling, you don't have to worry about that.
Link to fiddle
https://jsfiddle.net/anjanasilva/r21u4fmh/21/
I hope this helps. Feel free to ask me any questions if you have. Cheers.
This is not an ideal solution. I'm not sure there is a verified way of listening for when the innerHTML of a span element changes. This sort of stuff is usually based on user interaction, and the value of the span will be modified by your page. The best solution would be to use the same method that updates the span element to update the values of you hidden input fields.
However, I've placed an interval that will run every second, that takes the text value of the span element and gives it to the values of the 2 input fields:
function start() {
setInterval(function() {
document.getElementById("pt_uea_custom_amount_1").value = document.getElementById("price_value").innerHTML;
document.getElementById("pt_uea_custom_amount_2").value = document.getElementById("price_value").innerHTML;
}, 1000);
}
window.onload = start();
<div class="pt-uea-container">
<span class="pt-uea-currency pt-uea-currency-before"> € </span>
<input type="text" class="pt-field pt-uea-custom-amount" autocomplete="off" name="pt_items[1][amount]" id="pt_uea_custom_amount_1" value="199" placeholder="" data-parsley-errors-container="#pt_uea_custom_amount_errors_1">
<input type="hidden" class="pt-field pt-uea-custom-amount-formatted" name="pt_items[1][amount]" value="199" data-pt-price="199" id="pt_uea_custom_amount_2">
<input type="hidden" name="pt_items[1][label]" value="Amount:">
<input type="hidden" name="pt_items[1][tax_percentage]" value="0">
<input type="hidden" name="pt_items[1][type]" value="open">
<div id="pt_uea_custom_amount_errors_1"></div>
<span id="price_value" class="form-price-value">85</span>
</div>
MutationObserver should work here..
const formValuePrice = document.querySelector( '.form-price-value' );
const inputText = document.querySelector( 'input[type="text"]' );
// timer to change values
window.setInterval( () => {
formValuePrice.textContent = Math.round( Math.random() * 100 );
}, 1000 );
// mutation observer
const observer = new MutationObserver( ( mutationsList ) => {
inputText.value = formValuePrice.textContent;
} );
observer.observe( formValuePrice, { childList: true } );
https://codepen.io/anon/pen/LgWXrz?editors=1111
try this, simple using jquery, you can check in inspect element for value attribute data-pt-price
Update: you can using jquery event .on() like change, click, keyup or else to Attach an event handler function for one or more events to the selected elements,
you can read the doc here.
here the updated code
$(function() {
var spanVal = $('#price_value').text();
$('#pt_uea_custom_amount_1').val(spanVal);
$('#pt_uea_custom_amount_formatted_1').val(spanVal);
$('#pt_uea_custom_amount_formatted_1').attr('data-pt-price', spanVal);
$('#pt_uea_custom_amount_1').on('change click keyup', function() {
$('#pt_uea_custom_amount_formatted_1').val($(this).val());
$('#price_value').text($(this).val());
$('#pt_uea_custom_amount_formatted_1').attr('data-pt-price', $(this).val());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="pt-uea-container">
<span class="pt-uea-currency pt-uea-currency-before"> € </span>
<input type="text" class="pt-field pt-uea-custom-amount" autocomplete="off" name="pt_items[1][amount]" id="pt_uea_custom_amount_1" value="199" placeholder="" data-parsley-errors-container="#pt_uea_custom_amount_errors_1">
<input type="hidden" class="pt-field pt-uea-custom-amount-formatted" name="pt_items[1][amount]" value="199" data-pt-price="199" id="pt_uea_custom_amount_2">
<input type="hidden" name="pt_items[1][label]" value="Amount:">
<input type="hidden" name="pt_items[1][tax_percentage]" value="0">
<input type="hidden" name="pt_items[1][type]" value="open">
<div id="pt_uea_custom_amount_errors_1"></div>
<span id="price_value" class="form-price-value">85</span>
</div>
Related
I am having some problems regarding the jquery event handler function. I couldn't understand how can I set it in the correct way.
I will explain my problem, I have three checkboxes: 3D, TRI-Planar, and MPR. And when users check the 3D option the following two checkboxes appear Volume and Sur. Furthermore, when the user clicks the vol checkbox, some options toggle. And when the user unclicks the vol disappear and again if they click them then there will be two options of same. How can I solve it?
Below I have provided a minimal example which I used first without using a class like desire_viewer and method_selection. If you click 3D then vol and sur options toggle and if you click vol options then another options toggle but when u unclick it then it disappears and then click it again then two same options appear. I think there is something wrong with the code.
I expect the output to be like this: If the user clicks 3D options then it should toggle Volume and Surface options and again if the user clicks on the volume checkbox then volume options should toggle vice-verse with the surface. When the user unchecks any checkbox then its process should stop. For example, at first, the user clicked 3D > VOL and then 3D > sur, in this case, the first step should be stopped when the sur checkbox is clicked. I mean like logic 0 and 1. If the user clicks Tri-Planar then it's 1 and its option should toggle and again if the user unchecks it which is 0 then it's processed and should be stopped. So, in the next step user can play with MPR or other checkboxes.
ID_3D_render_selection = "#v1"
ID_tri_planar = "#v2"
ID_mpr_selection = "#v3"
ID_vol_selection = "#r1"
ID_sur_selection = "#r2"
$(ID_3D_render_selection).change(function() {
$('#select_render_method').slideToggle("slow");
$(ID_vol_selection).change(function() {
$('#VOL_OPTIONS').slideToggle("slow");
var vol_arr = []
var vol_arr2 = []
$( "#btn1" ).change(function() {
var vol_myFile = $('#btn1').prop('files');
vol_arr.push(vol_myFile)
});
<!--//////////////////////////////////////-->
$(document).ready(function() {
var vol_opacity = $('<input class=vol_set_opacity id="setScalarOpacityUnitDistance0" type="range" min="0" max="100" step="0.5" value="3">').appendTo('#set_opacity_distance_bm_Color');
var vol_distance = $('<input class=vol_set_distance id="setSampleDistance0" type="range" min="0.1" max="10" step="0.1" value="0.4">').appendTo('#set_opacity_distance_bm_Color');
var vol_blending = $('<select class=vol_blending_mode id=blendMode0 >').appendTo('#set_opacity_distance_bm_Color');
vol_blending.append($("<option>").attr('value',"0").text("Composite"));
var sel = $('<select class=colors_channels >').appendTo('#set_opacity_distance_bm_Color');
sel.append($("<option>").attr('value',"Reds").text("Reds"));
sel.append($("<option>").attr('value',"Blues").text("Blues"));
sel.append($("<option>").attr('value',"Greens").text("Greens"));
$( "#f" ).change(function() {
$('.vol_set_opacity').remove();
$('.vol_set_distance').remove();
$('.vol_blending_mode').remove();
$('.colors_channels').remove();
for(i=0; i<$('#f').val(); i++) {
var vol_opacity = $('<input class=vol_set_opacity id="setScalarOpacityUnitDistance'+ i +'"'+ ' type="range" min="0" max="100" step="0.5" value="3">').appendTo('#set_opacity_distance_bm_Color');
var vol_distance = $('<input class=vol_set_distance id="setSampleDistance'+ i + '"' + 'type="range" min="0.1" max="10" step="0.1" value="0.4">').appendTo('#set_opacity_distance_bm_Color');
var vol_blending = $('<select class=vol_blending_mode id="blendMode'+ i +'"'+ ' >').appendTo('#set_opacity_distance_bm_Color');
vol_blending.append($("<option>").attr('value',"0").text("Composite"));
var sel = $('<select class=colors_channels >').appendTo('#set_opacity_distance_bm_Color');
sel.append($("<option>").attr('value',"Reds").text("Reds"));
sel.append($("<option>").attr('value',"Blues").text("Blues"));
sel.append($("<option>").attr('value',"Greens").text("Greens"));
}
})
});
<!--//////////////////////////////////////-->
$( "#btn2" ).click(function() {
var vol_Picked_color = $(".colors_channels");
for(var i = 0; i < vol_Picked_color.length; i++){
vol_arr2.push($(vol_Picked_color[i]).val() );
}
console.log(vol_arr2)
if (vol_arr.length==vol_arr2.length){
vol_processFile(vol_arr, vol_arr2)
} else {
alert("Please check the number of input vs the number of channels ")
}
});
});
});
var tri_arr =[]
$(ID_tri_planar).click(function() {
$('#TRI_PLANAR_OPTIONS').slideToggle("slow");
});
$( "#btn1" ).change(function() {
var tri_myFile = $('#btn1').prop('files');
tri_arr.push(tri_myFile)
});
$( "#btn2" ).click(function() {
tri_processFile(tri_arr)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="{% static '/js/jquery-3.6.0.min.js' %}"></script>
<div >
<input class="desire_viewer" type="checkbox" name="Viewers" id="v1" value="3D"><label for="v1">3D</label>
<input class="desire_viewer" type="checkbox" name="Viewers" id="v2" value="TRI-Planar"><label for="v2">TRI-Planar</label>
<input class="desire_viewer" type="checkbox" name="Viewers" id="v3" value="MPR"><label for="v3">MPR</label>
</div>
<div id="select_render_method" class="section_header_2" style="display:none;">
<input class="method_selection" type="checkbox" name="Render" id="r1" value="Vol" ><label for="r1">Vol</label>
<input class="method_selection" type="checkbox" name="Render" id="r2" value="Sur" ><label for="r2">Sur</label>
</div>
<div id="divInput" class="section_internal_layout_card_middle_body_title_4" >
<table>
<tbody>
<td>Select the number of inputs:</td>
<td>
<input min=1 max=10 type="number" id="f" value="1" style="width: 43px; height: 25px;">
</td>
</tbody>
</table>
<div>
<input name="inputFile" type="file" multiple id="btn1" style="margin-left: 1px; margin-top: 30px; padding: 0px; border: none; z-index: 1;">
</div>
<div>
<button name="render" id="btn2" style="margin-top: 0px; margin-left:304px; width: 96px; font-size: 14pt; border: none; z-index: 1; margin-bottom: 7px;"> Render </button>
</div>
</div>
<div id="VOL_OPTIONS" class="section_header_5" style="display:none;">
<div id="set_opacity_distance_bm_Color" class="section_internal_layout_card_middle_body_title_5">
<p><b>Scalar Opacity</b>&ensp<b>SampleDistance</b><b>Blending</b><b>Color</b></p>
</div>
</div>
<div id="SUR_OPTIONS" class="section_header_6" style="display:none;">
<div id="set_iso_Color" class="section_internal_layout_card_middle_body_title_55">
<p><b>Scalar Opacity</b><b>Iso value</b><b>Color</b> </p>
</div>
</div>
<div id="TRI_PLANAR_OPTIONS" class="section_header_7" style="display:none;">
<table>
<tbody>
<tr>
<td>XY</td>
<td>
<input class="XY" type="range" min="0" max="119" step="1" value="0"> <!-- sliceI -->
</td>
</tr>
<tr>
<td>XZ</td>
<td>
<input class="XZ" type="range" min="0" max="119" step="1" value="0"> <!-- sliceJ -->
</td>
</tr>
<tr>
<td>YZ</td>
<td>
<input class="YZ" type="range" min="0" max="119" step="1" value="0"> <!-- sliceK -->
</td>
</tr>
<tr>
<td>Color level</td>
<td>
<input class="colorLevel" type="range" min="0" max="255" step="1" value="0">
</td>
</tr>
<tr>
<td>ColorWindow</td>
<td>
<input class="colorWindow" type="range" min="0" max="255" step="1" value="0">
</td>
</tr>
</tbody>
</table>
</div>
<div id="MPR_OPTIONS" class="section_header_8" style="height:412px; display:none;">
<table><tbody><tr> // do some stuff </tr></tbody></table>
</div>
UPDATE:
OP has edited their question significantly and much of my original answer now makes no sense. Here's a new answer for the current code.
Leaving my original answer below for reference.
The main problem in the new code is that your volume toggle actions are not balanced - the untick action does not do the reverse of the tick action.
When you tick the volume checkbox, you add some HTML to the page, display it, and set up some new change handlers;
When you untick that same checkbox, you add the same HTML again, hide it, and add another set of identical change handlers on top of the first set;
So you can see that if you tick to volume checkbox, untick it, and then tick it again, you will see 2x your HTML on the page.
The other major problem is what I described in my original answer below as "problem 2" - you are adding event handlers inside event handlers. In the example tick/untick/tick example of the volume checkbox above, you will end up with 2x handlers for #f, and 2x handlers for #btn1. If, for eg, you click #btn1, that code will now run 2x, simultaneously. This gets very messy very quickly, and will cause all kinds of problems.
Here's updated, working code, with comments.
Note I have simplified the code a lot by removing lots of stuff which is not relevant to the current problem. Your question summaries the key problem:
... and when the user unclicks the vol disappear and again if they click them then there will be two options of same. How can I solve it?
Ticking and unticking the volume checkbox shows 2x duplicate options. That's the problem we're tying to solve. Everything else here is not relevant, and we can remove it. It is much simpler - for you too! - to find and fix the problem when you focus on just the part that is not working. This is what the minimal in MVCE refers to.
// Document ready event handler should never be nested inside other handlers.
$(document).ready(function() {
// Volume-related variables we need to be able to access later
var vol_opacity, vol_distance, vol_blending, sel;
// Click and change events are technically the same for checkboxes, but still be,
// consistent - use change here, not a mix of change and click as your code had.
// https://stackoverflow.com/questions/11205957/jquery-difference-between-change-and-click-event-of-checkbox
$('#v1').change(function() {
$('#select_render_method').slideToggle("slow");
});
$("#v2").change(function() {
$('#TRI_PLANAR_OPTIONS').slideToggle("slow");
});
// Do not nest event handlers inside each other - move this handler outside other
// change handlers
$('#r1').change(function() {
// We are toggling elements on and off here. If you are ADDing the HTML when
// the checkbox is ticked, it means you have to REMOVE that HTML when it is
// unticked. Is it really necessary? Modifying the DOM like this is slow and
// inefficient, what about just toggling visibility, like you do with
// slideToggle() for other options?
// Anyway - assuming you want to add/remove it, let's do it like this:
if ($(this).is(':checked')) {
addVolumeStuff();
} else {
deleteVolumeStuff();
}
// I moved this toggle below the code above - .appendTo is synchronous, so
// wait until the HTML updates are done before displaying them.
$('#VOL_OPTIONS').slideToggle("slow");
});
/**
* Add some HTML when the vol checkbox is ticked
*/
function addVolumeStuff() {
vol_opacity = $('<input class=vol_set_opacity id="setScalarOpacityUnitDistance0" type="range" min="0" max="100" step="0.5" value="3">').appendTo('#set_opacity_distance_bm_Color');
vol_distance = $('<input class=vol_set_distance id="setSampleDistance0" type="range" min="0.1" max="10" step="0.1" value="0.4">').appendTo('#set_opacity_distance_bm_Color');
vol_blending = $('<select class=vol_blending_mode id=blendMode0 >').appendTo('#set_opacity_distance_bm_Color');
vol_blending.append($("<option>").attr('value',"0").text("Composite"));
sel = $('<select class=colors_channels >').appendTo('#set_opacity_distance_bm_Color');
sel.append($("<option>").attr('value',"Reds").text("Reds"));
sel.append($("<option>").attr('value',"Blues").text("Blues"));
sel.append($("<option>").attr('value',"Greens").text("Greens"));
}
/**
* Delete the volume controls when vol checkbox is unticked
*/
function deleteVolumeStuff() {
vol_opacity.remove();
vol_distance.remove();
vol_blending.remove();
sel.remove();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input class="desire_viewer" type="checkbox" name="Viewers" id="v1" value="3D">3D
<input class="desire_viewer" type="checkbox" name="Viewers" id="v2" value="TRI-Planar">TRI-Planar
<input class="desire_viewer" type="checkbox" name="Viewers" id="v3" value="MPR">MPR
</div>
<div id="select_render_method" class="section_header_2" style="display:none;">
<input class="method_selection" type="checkbox" name="Render" id="r1" value="Vol" >Vol
<input class="method_selection" type="checkbox" name="Render" id="r2" value="Sur" >Sur
</div>
<div>
<input min=1 max=10 type="number" id="f" value="1">
<div>
<input name="inputFile" type="file" multiple id="btn1">
</div>
<div>
<button name="render" id="btn2">Render</button>
</div>
</div>
<div id="VOL_OPTIONS" style="display:none;">
<div id="set_opacity_distance_bm_Color">
<p><b>Scalar Opacity</b> <b>SampleDistance</b> <b>Blending</b> <b>Color</b></p>
</div>
</div>
<div id="SUR_OPTIONS" style="display:none;">
<div id="set_iso_Color">
<p><b>Scalar Opacity</b> <b>Iso value</b> <b>Color</b></p>
</div>
</div>
<div id="TRI_PLANAR_OPTIONS" style="display:none;">
<table>
<tbody>
<tr>
<td>XY</td>
<td>
<input class="XY" type="range" min="0" max="119" step="1" value="0">
</td>
</tr>
<tr>
<td>... etc ...</td>
<td> </td>
</tr>
</tbody>
</table>
</div>
Original answer
Problem 1:
var value = $("input[name='Viewers']:checked").val();
The selector will match all 3 of your checkboxes. But what will the .val() of 3 elements look like? Quoting the docs for .val():
Get the current value of the first element in the set of matched elements.
So you're only ever going to get one of your checkbox values, the first checked one. Try it:
$('.desire_viewer').on('click', function() {
console.log($('.desire_viewer:checked').val());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="desire_viewer" type="checkbox" name="Viewers" value="3D">3D
<input class="desire_viewer" type="checkbox" name="Viewers" value="TRI-Planar">TRI-Planar
<input class="desire_viewer" type="checkbox" name="Viewers" value="MPR">MPR
So how do you check if a particular checkbox is checked? As you can imagine this is a pretty common problem and there are a lot of duplicates here, eg:
Getting all selected checkboxes in an array
Get checkboxes (with the same name) as array
Send same name multiple checkbox values via ajax
You need to iterate over each of the inputs, like so:
$('.desire_viewer').on('click', function() {
console.log('These are now checked:');
$('.desire_viewer:checked').each(function(i) {
console.log(i, ':', $(this).val());
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="desire_viewer" type="checkbox" name="Viewers" value="3D">3D
<input class="desire_viewer" type="checkbox" name="Viewers" value="TRI-Planar">TRI-Planar
<input class="desire_viewer" type="checkbox" name="Viewers" value="MPR">MPR
Note that inside the loop, $(this) represents the current jQuery object in the loop.
So in your case, your code might look something like:
$('.desire_viewer').on('click', function() {
$('.desire_viewer:checked').each(function(i) {
var val = $(this).val();
if (value == "3D") {
// Do stuff ...
} else if (value == "TRI-Planar") {
// Do other stuff ...
} else if (value == "MPR") {
// Do other different stuff ...
}
});
});
Problem 2:
$( "#btn1" ).change(function() {
This adds an event handler to your button. From this point on, any time that button is changed this handler will notice, and that function code will fire.
That's fine and will work. The problem is where it is added - when a checkbox is clicked. If the user decides they made a mistake and UNticks the TRI-Planar checkbox, guess what happens? Another identical event handler will be added to the button. And the best part? They will both fire! The handler function, whatever it is, will run 2x, in parallel. They don't overwrite each other, they all stack up, and they all run.
The (simplest) solution is to add event handlers independent of user interaction or other changes on the page, so they can only be bound once. If the code that runs is somehow dependent on where/when it would be triggered, set that up in the handler. Eg if this button change should only do something if TRI-Planar is checked, have the button event handler check if that is true before doing anything. Eg:
$("#btn1").change(function() {
// Maybe this should only happen if a certain checkbox is checked
$('.desire_viewer:checked').each(function(i) {
var val = $(this).val();
if (value == "TRI-Planar") {
// Do stuff
}
});
});
// Rest of your code - handlers are independent of user interaction and
// will only be bound once.
$('.desire_viewer').on('click', function() {
// ...
Note another option is to add handlers wherever you like, and use .off() to remove them, so you can dynamically add/remove them throughout your code. For simple applications I don't think this extra complexity is necessary.
There are lots of questions here about this too:
Is it correct to put an event inside an event?
jQuery click events firing multiple times
why is jQuery click event firing multiple times
Minor suggestion:
It looks like this is part of a bigger applicaton, and it looks like you're trying to reduce code repetition with variables like ID_desire_viewer = '.desire_viewer' etc. That's a good start but since those represent jQuery selectors, you may as well go just a tiny bit further and cache the actual selector.
Every time you do something like $(ID_desire_viewer) jQuery scans the whole DOM again to find matches. For small applications/pages you probably won't notice the performance hit doing that, but it is good practice to avoid it in case your app grows, and just in terms of read- and maintain-ability, DRY, etc.
To avoid that, save the results of the first search by doing:
let $viewers = $('.desire_viewer');
// Then you can do:
$viewers.on('click', function() { ...
Some references about that:
Does jQuery do any kind of caching of "selectors"?
Store jquery selector in variable
Try this
$('input["type=checkbox"]').attr("checked",'false');
i hope it was useful !
I have a form that has multiple inputs. One input is where user can input an ID. I need to verify the ID is unique. I want to call a JavaScript function for a onchange event. However, I can't get it to trigger. I have a console.log but it never hits when I make a change in the input so I am doing something wrong.
This is the function I am trying to call on the on change
function checkUniqueID() {
console.log("here");
var $counter = 0;
var tag = document.forms["userform"]["new_id"].value;
while ($counter < $totalItems) {
}
};
<div class="six wide field">
<label for="ID">ID</label>
<input type="text" id="new" name="new_id" placeholder="ID" onchange="checkUniqueID()">
</div>
I can't even get the console.log ("here") to trigger
The onchange HTML attribute triggers when the input loses focus.
So, if you correctly have your input#new_id inside a form like this:
<form name="userform">
<div class="six wide field">
<label for="ID">ID</label>
<input type="text" id="new" name="new" placeholder="ID">
</div>
</form>
Adding an eventListener in your script file would be enough.
document.userform.new_id.onchange=function(){
alert("ID changed to: "+this.value);
};
With jQuery would be as easy as:
$("#new").change(function(){
alert("ID changed to: "+$(this).value;
}
Here is a working fiddle:
https://jsfiddle.net/edbL3kgp/
This is my first post on this site so hopefully you will go easy on me. I'm trying to create an HTML / PHP form and use a small piece of Javascript to add additional rows to a table when a button is clicked and increment the ID for the two fields.
The button works in adding the rows however it doesn't seem to increment the ID, just use the same ID as the previous row. Hopefully someone could help?
$(window).load(function(){
var table = $('#productanddates')[0];
var newIDSuffix = 2;
$(table).delegate('#button2', 'click', function () {
var thisRow = $(this).closest('tr')[0];
var cloned = $(thisRow).clone();
cloned.find('input, select').each(function () {
var id = $(this).attr('id');
id = id.substring(0, id.length - 1) + newIDSuffix;
$(this).attr('id', id);
});
cloned.insertAfter(thisRow).find('input:date').val('');
newIDSuffix++;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="blue-bar ta-l">
<div class="container">
<h1>Submit Your Insurance Renewal Date(s)</h1>
</div>
</div>
<div class="grey-bar">
<div class="container">
<div class="rounded-box">
<div>
<label for="name">Name</label>
<input type="text" id="name" name="name" autocomplete="off" required />
</div>
<div>
<label for="name">Renewal Dates</label>
</div>
<table width="100%" border="0" cellspacing="0" cellpadding="5" id="productanddates" class="border">
<tr>
<td>
<select name="insurance_type1" id="insurance_type1">
<option></option>
<option>Car</option>
<option>Home</option>
<option>Van</option>
<option>Business</option>
<option>GAP</option>
<option>Travel</option>
</select>
</td>
<td>
<input type="date" name="renewal_date1" id="renewal_date1" />
</td>
<td>
<input type="button" name="button2" id="button2" value="+" />
</td>
</tr>
</table>
<div>
<label for="telephone_number">Contact Number</label>
<input type="tel" id="telephone_number" name="telephone_number" pattern="\d{11}" autocomplete="off" required />
</div>
<div>
<label for="email">Email Address</label>
<input type="email" id="email" name="email" autocomplete="off" required />
</div>
<div>
<input name="submit" type="submit" value="Submit" class="btn">
</div>
</div>
cloned.insertAfter(thisRow).find('input:date').val('');
This line isn't correct. It will throw an invalid selector error.
You need to change it to:
cloned.insertAfter(thisRow).find('input[type="date"]').val('');
jQuery actually does support the :INPUT-TYPE format in selectors, but not the new HTML5 input types (yet): so using input[type="date"] here is the correct way for now to select an element with an HTML5 type. Please notice the quotes around the value. If you want to select an attribute with a certain value.
A selector overview of css selectors here: W3schools.
Because this line is throwing an error your newIDSuffix never gets updated, because the script halts at the line before that because of the script error.
#Charlietfl raises a valid point about learning more about classes and DOM traversal. However that will not fix this code. Or explain why your code isn't working. Nevertheless it's a good tip.
I've gone ahead an taken a stab at a cleaner version of what I think that you are trying to accomplish. I'll walk through the major updates:
Updated the button id and name from "button2" to "button1" - I assumed that you would want to keep the indices in sync across the inputs in each row.
Changing $(window).load(function() { to $("document").ready(function() { - While either will work, the former will wait until all images have finished loading, while the latter while fire once the DOM has completed building. Unless you REALLY want the images to load first, I'd recommend $("document").ready(), for faster triggering of the code.
Removing the [0] references - the primary reason to use [0] after a jQuery selector collection is to reference the DOM version of the selected jQuery element, in order to us a "vanilla" JavaScript method on it. In all cases, you were re-rwapping the variables in $(...), which just converted the DOM element back into a jQuery object, so that extra step was not needed.
Changed the .delegate() method to .on() - as Howard Renollet noted, that is the correct method to use for modern versions of jQuery. Note that the "event" and "target" parameters have swapped places in on, from where they were in delegate.
Changed the event target from #button2 to :button - this will make sure that all of the buttons in the new rows will also allow you to add additional rows, not just the first one.
Switched the clone target from the clicked row to the last row in the table - this will help keep your row numbering consistant and in ascending order. The cloned row will always be the last one, regardless of which one was clicked, and the new row will always be placed at the end, after it.
Changed the indexing to use the last row's index as the base for the new row and use a regular expression to determine it - with the table being ordered now, you can always count on the last row to have the highest index. By using the regular expression /^(.+)(\d+)$/i, you can split up the index value into "everything before the index" and "the index (i.e., on or more numbers, at the end of the value)". Then, you simply increment the index by 1 and reattach it, for the new value. Using the regex approach also allows you to easily adapt, it there ever get to be more than 9 rows (i.e., double-digit indices).
Updated both the id and name attributes for each input - I assumed that you would want the id and name attributes to be the same for each individual element, based on the initial row, and, you were only updating the id in your code, which would have caused problems when sending the data.
Changed $("input:date") to $("input[type='date']) - as Mouser pointed out, this was really the core reason why your code was failing, initially. All of the other changes will help you avoid additional issues in the future or were simply "code quality"-related changes.
So . . . those were the major updates. :) Let me know if I misunderstood what you were trying to do or if you have any questions.
$("document").ready(function() {
$('#productanddates').on('click', ':button', function () {
var lastRow = $(this).closest('table').find("tr:last-child");
var cloned = lastRow.clone();
cloned.find('input, select').each(function () {
var id = $(this).attr('id');
var regIdMatch = /^(.+)(\d+)$/;
var aIdParts = id.match(regIdMatch);
var newId = aIdParts[1] + (parseInt(aIdParts[2], 10) + 1);
$(this).attr('id', newId);
$(this).attr('name', newId);
});
cloned.find("input[type='date']").val('');
cloned.insertAfter(lastRow);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="blue-bar ta-l">
<div class="container">
<h1>Submit Your Insurance Renewal Date(s)</h1>
</div>
</div>
<div class="grey-bar">
<div class="container">
<div class="rounded-box">
<div>
<label for="name">Name</label>
<input type="text" id="name" name="name" autocomplete="off" required />
</div>
<div>
<label for="name">Renewal Dates</label>
</div>
<table width="100%" border="0" cellspacing="0" cellpadding="5" id="productanddates" class="border">
<tr>
<td>
<select name="insurance_type1" id="insurance_type1">
<option></option>
<option>Car</option>
<option>Home</option>
<option>Van</option>
<option>Business</option>
<option>GAP</option>
<option>Travel</option>
</select>
</td>
<td>
<input type="date" name="renewal_date1" id="renewal_date1" />
</td>
<td>
<input type="button" name="button1" id="button1" value="+" />
</td>
</tr>
</table>
<div>
<label for="telephone_number">Contact Number</label>
<input type="tel" id="telephone_number" name="telephone_number" pattern="\d{11}" autocomplete="off" required />
</div>
<div>
<label for="email">Email Address</label>
<input type="email" id="email" name="email" autocomplete="off" required />
</div>
<div>
<input name="submit" type="submit" value="Submit" class="btn">
</div>
</div>
cloned.insertAfter(thisRow).find('input[type="date"]').val('');
Hi all I have a form in which I dynamically add in a new row consisting of a text box and check button on button press. However I need some sort of way to know which checkbuttons were pressed in the post data and therefore need a value field consisting of an ID on each of the the check buttons, code is seen below:
<div id='1'>
<div class="template">
<div>
<label class="right inline">Response:</label>
</div>
<div>
<input type="text" name="responseText[]" value="" maxlength="400" />
</div>
<div>
<input type="radio" name="responseRadio[]" value="" />
</div>
</div>
<div>
<input type="button" name="addNewRow" value="Add Row" />
</div>
</div>
JS to add new row:
var $template = $('.template');
$('input[type=button]').click(function() {
$template.clone().insertAfter($template);
});
can anyone suggest a good way to help me know in the post data which text field, links to which check button, and to know if it was pressed?
at the moment if you were to add 3 rows and check row 3 I have no way of identifying that row three was the button pressed - This is my issue
after you cloned it, change the name so you know about this input
also it's good to have a counter for naming:
like : 'somename[myInput' + counter + ']'
update:
var counter = 0;
var $template = $('.template');
$('input[type=button]').click(function() {
counter++;
$template.clone().attr('name' , 'somename[myInput' + counter + ']').insertAfter($template);
});
now you have array named:somename which you can have a loop over its content on your form handler.
I want to be able to add new sections (via the 'add' link) and remove them (via the 'x' button) like seen in the image.
The HTML for the image:
<fieldset>
<legend>Legend</legend>
<div id="section0">
<input type="text" name="text1" value="Text1" />
<input type="text" name="text2" value="Text2" size='40' />
<input type="button" value="x" style="width: 26px" /><br />
</div>
add<br />
</fieldset>
I guess I could add new sections as needed (i.e. section1, section2) and delete those sections according to which button was pressed. There would be a javascript function that would inject sections in the DOM everytime the 'add' link was clicked and another for deleting a section everytime the 'x' button was clicked.
Since I have so little experience in HTML and Javascript I have no idea if this is a good/bad solution. So, my question is exactly that: Is this the right way to do it or is there a simpler/better one? Thanks.
P.S.: Feel free to answer with some sample code
Here's one way to do it:
<script type="text/javascript">
function newrow() {
document.getElementById("customTable").innerHTML += "<tr><td><input type='text'></td><td><input type='text'></td><td><button onclick='del(this)'>X</button></td></tr>";
}
function del(field) {
field.parentNode.parentNode.outerHTML = "";
}
</script>
<body onload="newrow()">
<fieldset>
<legend>Legend</legend>
<table>
<tbody id="customTable">
</tbody>
</table>
<button onclick="newrow()">Add</button>
</fieldset>
</body>
You could add IDs to them if you wanted, or you could call them by their position document.getElementsByTagName("input")[x].value The inputs would start at 0, so the left one is 0, right is 1, add row: left is 2, right is 3, etc.
If you delete one, the sequence isn't messed up (it re-evaluates each time), which is better than hard-coded IDs.
I just answered a nearly identical question only a few minutes ago here using jQuery: https://stackoverflow.com/a/10038635/816620 if you want to see how it worked there.
If you want plain javascript, that can be done like this.
HTML:
<div id="section0">
<input type="text" name="text1" value="Text1" />
<input type="text" name="text2" value="Text2" size='40' />
<input type="button" value="x" style="width: 26px" /><br />
</div>
add<br />
Javascript:
function addSection(where) {
var main = document.getElementById("section0");
var cntr = (main.datacntr || 0) + 1;
main.datacntr = cntr;
var clone = main.cloneNode(true);
clone.id = "section" + cntr;
where.parentNode.insertBefore(clone, where);
}
Working demo: http://jsfiddle.net/jfriend00/TaNFz/
http://pastebin.com/QBMEJ2pq is a slightly longer but robust answer.