My JS is as follows:
$(document).ready(function(){
$('#data1').change(function(){
title = $('#title1').val();
url = $('#url1').val();
$.post('library/edit.php',{title:title, url:url},function(res){
alert ("updated !");
});
});
});
and my HMTL-markup:
<div id="data1">
<input name="title1" type="text" id="title1" />
<input name="url1" type="text" id="url1" />
</div>
I wrote that code to call to a PHP file on change of textbox.
that code works as expected.
But now I've added more textboxes as follows:
<div id="div1"><input name="title1" type="text" id="title1" />
<input name="url1" type="text" id="url1" /></div>
<div id="div2"><input name="title2" type="text" id="title2" />
<input name="url2" type="text" id="url2" /></div>
<div id="div3"><input name="title3" type="text" id="title3" />
<input name="url3" type="text" id="url3" /></div>
Now I want the same functionality so that any of these textboxes works like title1 in my earlier code. So if input#title-3 is changed I want the change to be uploaded via POST to my PHP-script.
Important: The number of boxes are dynamic.
$(document).ready(function(){
$('#data1').on('change','[id^=title],[id^=url]',function(){
var index = $(this).attr('id').replace('title',"").replace('url',"");
var title = $("#title" + index).val();
var url = $("#url" + index).val();
var hid = $("#hid" + index).val();
// you can put in here in sequence all the fields you have
$.post('library/edit.php',{title:title, url:url, hid : hid},function(res){
alert ("updated !");
});
});
});
so by this answer if any text box whoes id starts with title changes.
the function passed in will be invoked.
indezx variable will store the index of the group of the elements that are changing. and then is being callculated by removing title from title1 or title2
I think the answer you have it right here:
I wrote that code to call to php file on change of textbox.
That script (jQuery I guess) it must be associatte with the $('#xxx1').onchange() right? (or similar)
If you modify the function, add a class to the input field (also in the php) and each time you call the function, start listening again.. I think you can call any function you may want.
Example (guessing your code)
HTML
<div id="data1" class="dynamicDiv">
<input name="title1" type="text" id="title1" />
<input name="url1" type="text" id="url1" />
</div>
jQuery
// enable the function on document ready
$(document).ready(function(){
startListening('.dynamicDiv');
});
// each time an ajax call is completed,
// run the function again to map new objects
$(document).ajaxComplete(function(){
startListening('.dynamicDiv');
});
// and finally the function
function startListening(obj){
$(obj).onchange(function(){
// ajax call
// function call
// or whatever...
});
}
PHP
// some code....
// some code....
// remember here to add "dynamicDiv" as a class in the object
return object;
Since your elements are dynamically generated you need to use event delegation, then you can use [id^="value"] to select the appropriate elements based on the first part of their id attribute
$(document).ready(function(){
$(document).on('change','[id^="data"]',function(){
var title = $(this).find('[id^="title"]').val();
var url = $(this).find('[id^="url"]').val();
var hidden = $(this).find('[id^="hid"]').val();
$.post('library/edit.php',{title:title, url:url, hid:hidden},function(res){
alert ("updated !");
});
});
});
Note: I suggest you bind to the closest parent of your data divs that is present at page load instead of binding to the document
Related
I have many pair of text fields and submit button, with id to submit button and class to text field as same but different for each pair. So I want to pass the value entered in text field after button click to ajax function.
function update_rate(id){
// var price = document.getElementsByClassName(id)[0].innerHTML;
var price = document.getElementsByClassName(id);
console.log(price);
$.ajax({
type: "POST",
url: "update_rate.php", // Name of the php files
data: {subcategory : id , price: price},
success: function(res)
{
// console.log(html);
alert(res);
}
});
}
first pair:
<div class="form-group">
<input type="text" class="form-control" name="a" placeholder="Your task rate excl. taxes">
</div>
<button type="submit" id="a" onclick="update_rate(this.id)" class="btn btn-primary">Update</button>
<div class="form-group">
<input type="text" class="form-control" name="b" placeholder="Your task rate excl. taxes">
</div>
<button type="submit" id="b" onclick="update_rate(this.id)" class="btn btn-primary">Update</button>
But I can't get the value of text field into variable.
This can and should be done in a different and more simple manner. Connecting the buttons with their text fields by id and class is not a scalable solution and requires constant updating of the code to keep all the naming in sync. Just get the value of the text field that comes just prior to the button. This will be easier if you modify your HTML structure so that the text field and the button are in the same div together.
Don't use inline event handlers, instead separate your event handling
code into JavaScript.
Set up just a single event handler at a higher DOM element and handle
it when it bubbles up to that element. This is called Event
Delegation.
Use data-* attributes to store custom data in elements.
Also, don't use .getElementsByClassName() in 2020. Instead,
use .querySelector.
See comments below.
// Do your event handling in JavaScript, not with inline HTML event handling attributes
// Also, set up just one handler at a parent level of the items that might trigger
// the event (event delegation).
$(".wrapper").on("click", update_rate);
function update_rate(event){
// See if it was a submit button that got clicked
if(event.target.classList.contains("btn")){
// A submit button was pressed.
// Locate the nearest ancestor element that has the form-group class
// (event.target references the actual element that triggered the event).
let formGroup = event.target.closest(".form-group");
// and then, from there, find the first input (which is the one you want).
var input = formGroup.querySelector("input");
// The following code is already added to the success handler below and
// that's where it should be. It's only added here to be able to see the
// effect since the AJAX call won't run in Stack Overflow. The next 3 lines
// should be removed when used for real.
input.classList.add("hidden");
formGroup.querySelector("button").classList.add("hidden");
formGroup.querySelector("span").classList.remove("hidden");
console.log(input.value);
$.ajax({
type: "POST",
url: "update_rate.php", // Name of the php files
// Use the dataset API to extract the custom attribute on the input
data: {subcategory : input.dataset.category , price: input.value},
success: function(res){
alert(res);
// Hide the input and the button and show the updated message
input.classList.add("hidden");
formGroup.querySelector("button").classList.add("hidden");
formGroup.querySelector("span").classList.remove("hidden");
}
});
}
}
.hidden { display:none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="form-group">
<input type="text" class="form-control" data-category="a" placeholder="Your task rate excl. taxes">
<button type="submit" class="btn btn-primary">Update</button>
<span class="hidden">Updated</span>
</div>
<div class="form-group">
<input type="text" class="form-control" data-category="b" placeholder="Your task rate excl. taxes">
<button type="submit" class="btn btn-primary">Update</button>
<span class="hidden">Updated</span>
</div>
</div>
In the end, you have no id or unique class names to have to match up against each other, your HTML is more simplified, and you only have one event handler to set up.
Several things
var price = document.getElementsByClassName(id);
is plural and you need the value, so
var price = document.getElementsByClassName(id)[0].value; if you must
BUT it is not a class. It is a name
var price = document.getElementsName(id)[0].value; if you must
but if you have jQuery, why not use it?
Here I take the button ID and find the input by name
I also change to type="button" - you do not want to submit when you use Ajax
$(function() { // on page load
$("#container").on("click","[type=button]",function() { // click on type="button" you can use a Class here too
const id = $(this).attr("id");
const price = $("[name="+id+"]").val(); // get the input by name
console.log(id, price)
if (price) {
$.ajax({
type: "POST",
url: "update_rate.php", // Name of the php files
data: {
subcategory: id,
price: price
},
success: function(res) {
// console.log(html);
alert(res);
}
});
}
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
first pair:
<div class="form-group">
<input type="text" class="form-control" name="a" placeholder="Your task rate excl. taxes">
</div>
<button type="button" id="a" class="btn btn-primary">Update</button>
<div class="form-group">
<input type="text" class="form-control" name="b" placeholder="Your task rate excl. taxes">
</div>
<button type="button" id="b" class="btn btn-primary">Update</button>
</div>
As you're already passing the id in the function, using jQuery, you can do something like:
var selector = 'input[name="' + id + '"]' // Compose the selector string for jQuery
var value = $(selector).val() // Get input value
I'm building a multipage form. On a few of the form's pages, I have questions that allow the user to add inputs dynamically if they need to add a job, or an award, etcetera. Here's what I'd like to do/what I have done so far.
What I Want to Do:
As the user adds fields dynamically, I want to validate those fields to make sure they have been filled in, and they are not just trying to move to the next page of the form with empty inputs.
After all the fields are successfully validated, a "Next" button at the bottom of the page, which up until this point was disabled, will become reenabled.
What I know How To Do
With some help, I've been able to workout a validation pattern for the inputs that are not dynamically added (such as First Name, Last Name) and I can extend this same logic to the first set of inputs that are not added dynamically. I have also worked out how to re-enable the "Next" button once all fields are good.
What I do Not Know How To Do
How do I write a function that extends the logic of the simple validation test to also check for dynamically added iterations.
http://codepen.io/theodore_steiner/pen/gwKAQX
var i = 0;
function addJob()
{
//if(i <= 1)
//{
i++;
var div = document.createElement("div");
div.innerHTML = '<input type="text" class="three-lines" placeholder="School Board" name="schoolBoard_'+i+'"> <input type="text" class="three-lines" placeholder="Position" name="position_'+i+'"> <input type="date" class="three-lines" name="years_'+i+'"> <input type="button" value="-" onclick="removeJob(this)">';
document.getElementById("employmentHistory").appendChild(div);
//}
}
function removeJob(div)
{
document.getElementById("employmentHistory").removeChild(div.parentNode);
i--;
};
function checkPage2()
{
var schoolBoard_1 = document.getElementById("schoolBoard_1").value;
if(!schoolBoard_1.match(/^[a-zA-Z]*$/))
{
console.log("something is wrong");
}
else
{
console.log("Working");
}
};
<div id="page2-content">
<div class="input-group" id="previousTeachingExperience">
<p class="subtitleDirection">Please list in chronological order, beginning with your most recent, any and all full-time or part-time teaching positions you have held.</p>
<div class="clearFix"></div>
<label id="teachingExpierience">Teaching Experience *</label>
<div id="employmentHistory">
<input type="text" class="three-lines" name="schoolBoard_1" id="schoolBoard_1" placeholder="School Board" onblur="this.placeholder='School Board'" onfocus="this.placeholder=''" onkeyup="checkPage2()" />
<input type="text" class="three-lines" name="position_1" placeholder="Position" onblur="this.placeholder='Position'" onfocus="this.placeholder=''" onkeyup="checkPage2()" />
<input type="date" class="three-lines" name="years_1" />
<input type="button" name="myButton" onclick="addJob()" value="+" />
</div>
</div><!--end of previousTeachingExperience Div -->
Instead of trying to validate each individual input element, I would recommend trying to validate them all at once. I believe that is what your checkPage2 function is doing.
You can add the onBlur event handler or the onKeyUp event handler you are currently using to all added inputs to run your form wide validation. This has the effect of checking each individual form element if it is valid so you know for sure you can enable the submit button.
Lastly, when removeJob is called, you should also run the form wide validation. It would look something like this:
function addJob()
{
i++;
var div = document.createElement("div");
div.innerHTML = '<input type="text" class="three-lines" placeholder="School Board" name="schoolBoard_'+i+'" onkeyup="checkPage2()"> <input type="text" class="three-lines" placeholder="Position" name="position_'+i+'" onkeyup="checkPage2()"> <input type="date" class="three-lines" name="years_'+i+'" onkeyup="checkPage2()"> <input type="button" value="-" onclick="removeJob(this)">';
document.getElementById("employmentHistory").appendChild(div);
}
function removeJob(div)
{
document.getElementById("employmentHistory").removeChild(div.parentNode);
i--;
checkPage2();
};
For every element that you make with document.createElement(...), you can bind to the onchange event of the input element, and then perform your validation.
Here's an updated version of your CodePen.
For example:
HTML
<div id="container">
</div>
Javascript
var container = document.getElementById("container");
var inputElement = document.createElement("input");
inputElement.type = "text";
inputElement.onchange = function(e){
console.log("Do validation!");
};
container.appendChild(inputElement);
In this case I'm directly creating the input element so I have access to its onchange property, but you can easily also create a wrapping div and append the inputElement to that.
Note: Depending on the freqency in which you want the validation to fire, you could bind to the keyup event instead, which fires every time the user releases a key while typing in the box, IE:
inputElement.addEventListener("keyup", function(e){
console.log("Do validation!");
});
I have dynamically created check boxes on my page and assigned each of them an unique id like 'renameteam1', 'renameteam2' etc.. I am trying to run a function when one of these gets checked. The function will then allow the user to enter a corresponding field that was previously readonly.
I have tried the following but it doesn't seem to be working.
var a=0;
$('input[type=checkbox]').change(function () {
for (var i=0;i<rows3;i++){
a=a+1;
var id= '#renameteam'+a;
if ($(id).is(":checked")) {
$('#newname'+a).removeProp('readonly');
}
}
//Here do the stuff you want to do when 'unchecked'
});
Any Suggestions?
This is how I would do it
//delegate the event so you can call this on document ready and it will still be bound to any dynamically created elements
$(document).on('change', 'input[type=checkbox]', function() {
var checkbox = $(this),
otherInput = $('#' + checkbox.data('id'));
otherInput.prop('readonly', !checkbox.is(':checked'));
if (!checkbox.is(':checked')) {
// do stuff here when checkbox isn't checked - not sure if you still want this bit but it is as per your comments in the code above
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" name="checkbox" value="" id="renameteam1" data-id="newname1" />
<!-- use a data attribute to target the id of the input you want to make readonly -->
<input type="textbox" name="textbox" value="" id="newname1" readonly />
If you don't want to use a data attribute, you could do this:
//delegate the event so you can call this on document ready and it will still be bound to any dynamically created elements
$(document).on('change', 'input[type=checkbox]', function() {
var checkbox = $(this),
otherInput = $('#newname' + this.id.replace('renameteam', ''));
otherInput.prop('readonly', !checkbox.is(':checked'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" name="checkbox" value="" id="renameteam1" />
<!-- use a data attribute to target the id of the input you want to make readonly -->
<input type="textbox" name="textbox" value="" id="newname1" readonly />
Try using an on click instead of on change for checkboxes and radio buttons.
i have this html form
<form action="" method="post" name="login_form">
Email : <input type="text" id="email2" name="email" /><br />
<span id="passwordT" >Password : </span>
<input type="password" name="password" id="password2"/><br />
<input type="button" id="submit_botton" value="Login" />
<div><input id="forgot" type="button" value="Forgot your Password?" /></div>
</form>
and the javascript here
var forgot = $('#forgot');
var forgot2 = $('#forgot2');
forgot.click(function() {
$('#password2').hide();
$('span#passwordT').hide();
$('input#submit_botton').prop('value', 'Reset Passowrd');
$('input#forgot').replaceWith('<input id="forgot2" type="button" value="Login here" />');
});
$('input#forgot2').click(function() { // this function didnt want to work
$('input#forgot2').prop('value', 'Forgot your Password?');
$('#password2').show();
$('span#passwordT').show();
$('input#submit_botton').prop('value', 'Login');
});
HERE JS-DEMO
what i want is :
when i click on second function i will get back the buttons as they were in first time.
I tried to make this second function inside the first but what i got is the function works but only one time , i mean if i click again to reset password will not work.
thanks for the help.
Your problem is that you're trying to attach an event handler to an element that doesn't exist yet. That's not possible with direct event handlers. Use delegated events instead.
$(document).on('click','#forgot2', function(){ ... });
document can be replaced with any #forgot2 container that exists at binding time.
As a side note, take into account that when you use selectors by id (e.g #forgot2) it's not necessary to add anything else since an id identify one and just one element (repeated ids are not allowed). So this selector input#forgot2 is not wrong but more complex than necessary.
I have a simple form with 2 input fields and one button. When the button is clicked, the value of the 2 input fields should be sent to the AJAX function to be handled in a servlet. For some reason, the servlet is not being reached. Can anyone see why? I have an almost identical method working with a different form, and I can't see why this one isn't working.
Here is the HTML form code:
<div id="addCourses" class="hidden" align="center" >
<form id="addCourse" name="addCourse">
<input type="text" id="courseID" name="courseID" value="courseID" size="40" /><br />
<textarea rows="5" cols="33" id="courseDesc" name="courseDesc">Description</textarea><br />
<input type="button" value="Add Course" onclick="addCourse(this.courseID.value, this.courseDesc.value);"/>
</form>
</div>
Here is the Script function:
<script type ="text/javascript">
function addCourse(id, descr)
{
var fluffy;
fluffy=new XMLHttpRequest();
fluffy.onreadystatechange=function()
{
if (fluffy.readyState==4 && fluffy.status==200)
{
//do something here
}
};
fluffy.open("GET","ajaxServlet?courseID="+id+"&courseDescription="+descr,true);
fluffy.send();
}
</script>
Because this is the button and not the form
so
this.courseID.value
this.courseDesc.value
returns an error.
You should use
this.form.courseID.value
this.form.courseDesc.value
Second problem is you have a name clash. The form and function are named addCourse. It will lead to problems. Rename one of them to be different.
Running Example
When you use this, as in onclick="addCourse(this.courseID.value, this.courseDesc.value);", I think that would refer to the input element, and therefore the values aren't being passed correctly.
Bind your event handlers in javascript, where they should be, and you can avoid the issue entirely.
HTML:
<input type="text" id="courseID" name="courseID" value="courseID" size="40" /><br />
<textarea rows="5" cols="33" id="courseDesc" name="courseDesc">Description</textarea><br />
<input type="button" id="addCourse" value="Add Course"/>
JS:
document.getElementById('addCourse').onclick = function () {
var fluffy = new XMLHttpRequest();
var id = document.getElementById('courseID').value;
var descr = document.getElementById('courseDesc').value;
fluffy.onreadystatechange=function() {
if (fluffy.readyState==4 && fluffy.status==200) {
//do something here
}
};
fluffy.open("GET","ajaxServlet?courseID="+id+"&courseDescription="+descr,true);
fluffy.send();
};
As epascarello pointed out, you need to change the ID of your form as having two elements with the same ID is not allowed and will cause unpredictable javascript behavior.
Try a fluffy.close; after the if ready state expression.