I have a php table created by a mysqli query where I want users to be able to update the date values of a text cell. For other formatting reasons, I have chosen not to use the date input.
My script works for other forms with an id that does not include brackets and changes the form value immediately and correctly. However, when I apply the onchange function to the table cell, it seems the brackets in the id may be holding me up. I can see in the console that I am calling the correct bracketed id, however, nothing else happens.
Here is my cell:
<td>
<input type='text' class='form-control form-control-sm'
id='tbl_date01[".$tbl_ID."]' name='tbl_date01[".$tbl_ID."]'
value='".$tbl_date01."' onchange=\"dateChange()\" required />
</td>
Here is my script:
function dateChange(){
var id = (event.target.id);
var y = document.getElementById(id).value;
if(y === '?'){
$("#"+id).val(new Date().toJSON().slice(0,10).substring(5,7) + '/' + new Date().toJSON().slice(0,10).substring(8,10) + '/' + new Date().toJSON().slice(0,10).substring(0,4));
return;
};
};
Related
My starting html looks like this:
<label> Names: </label><br>
<input type="text" class="form-control name" placeholder="name1" id="name1" name ="name1"><br>
and i have a variable that captures the html:
var html = "<label> Names: </label><br><input type=\"text\" class=\"form-control name\" placeholder=\"name1\" id=\"name1\" name =\"name1\"><br>"
Then I have an onchange operator that performs a couple functions when the first row has text in it. the .onchange is picked up fine the first time and the subsequent functions are run. I end up with an additional row:
for (n = 1; n < inputLength+1 ; ++n) {
var test2 = document.getElementById(dude+n);
test2.onchange = forFunction
}
function forFunction() {
for (m = 1; m < inputLength+1 ; ++m) {
var test = document.getElementById(dude+m)
if (test.value != "") {
var txt = "<input type=\"text\" class=\"form-control name\" placeholder="+dude+(m+1)+" id="+dude+(m+1)+" name="+dude+(m+1)+"><br>";
document.getElementById('group_names').innerHTML = updateHTML(txt);
//function updateHTML(txt)
}
}
}
var html = "<label> Names: </label><br><input type=\"text\" class=\"form-control name\" placeholder=\"name1\" id=\"name1\" name =\"name1\"><br>"
function updateHTML(txt) {
html = html + txt;
return html;
}
The issue is that after all that completes i end up with two input rows as desired: name1 and name2. However, when i enter text in those fields for a second time, the .onchange is not picked up. but the elements are there in the html when i inspect and view the html.
Also, when i
console.log(inputFormDiv.getElementsByTagName('input').length);
the length of the inputs increases from 1 to 2 after i first run functions (upon the first time i change the value in my input field) so that is getting recognized correctly, just not the .onchange.
thoughts?
The onchange will only work if added to the attribute on the html and the user clicks out of a textbox e.g:
<input onchange="forFunction()" type="text" class="form-control name" placeholder="name1" id="name1" name ="name1">
To add the onchange event in JavaScript code. Add the change event to the addEventListener e.g:
var test2 = document.getElementById(dude+n);
test2.addEventListener('change', forFunction, false)
However if you want the event to fire whilst the user is types a key then use the keypress event. e.g:
var test2 = document.getElementById(dude+n);
test2.addEventListener('keypress', forFunction, false
A basic example: https://jsfiddle.net/xrL6y012/1/
Instead of .innerHTML = html + text do .insertAdjacentHTML('beforeend', text), that way you keep the original html (and events binding).
Edit: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
I had the same problem, it seems like modifying the HTML will never work, regardless of how you do it (.innerHTML or .insertAdjacentHTML()).
The only way that worked for me is to append a child instead of editing the HTML, like so:
const span = document.createElement('span');
span.innerHTML = 'text and <b> html stuff </b>';
initialElement.appendChild(span);
And if you actually need to insert just pure text, then this works:
initialElement.append('just text');
Hope that helps.
step 1: I have a form where input fields will be generated dynamically by innerHTML.
var d = document.getElementById("d1p_1");
d.innerHTML += "<input class='add' name='field_" + i + "' type='text'>";
step 2: now I would like to echo a php variable of each value to each dynamically generated input field. Something like:
d.innerHTML += "<input class='add' name='field_" + i + "' type='text' value='"<?php echo $field_" + i + "; ?>" + "'>
How can I archieve that?
Thanks in advance.
To give further information:
This is for a form where an user can add fields, depending from how many fields he needs and will be adding. Now it could be that an user adds more fields than he usually needs and enters data somewhere between field_1 and field_280. To catch the field_x where he entered data I need to echo the value of that input field.
$field_1 = value of field_1 if given;
...
$field_280 = value of field_280 if given;
The innerHTML will add the input fields dynamically by a counter for i. So I dont know what input will be given on which field. Thats why I need to generate the PHP echo part dynamical as well. Like:
<?php echo $field_" + i + "; ?>
The whole process:
form -> contains first just one input field (user will make some inputs) -> by clicking a button there will be added further input fields (1 click 1 field and user does not need to fill in data before he can add another fields) -> now imagine that a user will add 3 fields and has given input on first and third input field -> name="field_1" and name="field_3" ->
the name of each input field is generated by i++ -> the value is empty otherwise the form will be posted -> now the user will submit the form.
this means the value to echo would be $field_3 = (isset($_POST['field_3'])) ? $_POST['field_3']; : ''; -> this variable exist for all i so each variable is set in the php part before BUT to catch the right input name="field_i" with $field_i and to echo this match is the problem.
So by clicking submit the page would be reloaded and instead of only just one input field like from before now would be there 2 input fields. first would be name="field_1" and the second would be name="field_3" because user has left out input name="field_2" before. So name="field_3" needs to echo the right value depending from a dynamically generated name="field_"+ i +"what means that when the name tag is generated dynamically the php tag needs also to be generated dynamically to match each other.
i is a JavaScript variable so including it in a php declaration is giving you problems
You may implement your string concatenation out of the php code as follows
<?php
$field_="stavo";
?>
<script type="text/javascript">
var i=10;
var d = document.getElementById("d1p_1");
d.innerHTML+= "<input class='add' name='field_" + i + "' type='text'>";
d.innerHTML += "<input class='add' name='field_" + i + "' type='text' value='<?php echo $field_; ?>"+i+"'>";
</script>
Of course you must be having this in your Html
<div id="d1p_1"></div>
in my form, the user can click a button to create input fields. Inside each of the created input fields, they can click the "add media links" button to create another input field underneath. They can add as many media links as they please or none at all. The first set of input fields are also sortable. I have the user interface working, I'm just wondering how to go about processing it.
right now, I am basically grabbing all of the values entered from the first set of input fields (aka "thestepvalues" in the code) and then grabbing all of the values entered from the second set of input values (aka "links" in the code) and then URL enconding it and serializing it to send to the my process.php file. The code is below:
$("#new_post").submit(function(e){
e.preventDefault();
//enter each of the values for 'the step' input field into an array
var thestepvalues = $("input[name='thestep\\[\\]']")
.map(function(){return $(this).val();}).get();
//enter each of the values for each 'links' input field into an array
var linkvalues = $("input[name='link\\[\\]']")
.map(function(){return $(this).val();}).get();
//this will basically convert everything entered into the steps as well as the links fields
//into URL appropriate strings to pass on to the process.php file
var i, string="";
for(i=0;i<thestepvalues.length; i++){
string += "thesteps[]=" + encodeURI(thestepvalues[i]) + "&";
}
for(i=0;i<linkvalues.length; i++){
string += "links[]=" + encodeURI(linkvalues[i]) + "&";
}
//send the data from the string (both kinds of input fields) as well as any
//other input fields (that aren't dynamic) from the form
$.post("process.php", string + $("#new_post").serialize(),
function(data){
if(data.email_check == 'invalid'){
$("#message_post").html("<div class='errorMessage'>Sorry " + data.name + ", " + data.email + " is NOT a valid e-mail address. Try again.</div>");
} else {
$("#message_post").html("<div class='successMessage'>" + data.email + " is a valid e-mail address. Thank you, " + data.name + ".</div>");
}
}, "json");
});
For a sample of data entered into the form, how do I go about indicating which link belongs to the parent input field? Baring in mind the parent input fields are sortable jquery ui elements.
here's a sample set of data entered, as you can tell I have no way of knowing which input field the child links belong to:
[thesteps] => Array
(
[0] => This is really the second input field, but dragged up to the first position.
[1] => This is the second input field, but used to be in the first position.
[2] => this is the third input field
)
[links] => Array
(
[0] => this is the first (child) link for the first position.
[1] => this is actually the (child) link for the third field!
)
Any help would be greatly appreciated, thanks in advance
-- 24x7
You could use HTML5 custom data attributes, setting the value of each linked set to be the same number.
For example:
<input id="1" data-newinput-id="1" />
<input id="2" data-newinput-id="1" />
<input id="3" data-newinput-id="2" />
<input id="4" data-newinput-id="2" />
Even if the inputs are re-arranged, you can match them up by getting the attribute values in jQuery like so:
var id = $(this).attr("data-newinput-id"); // 1
I am building a form using a js+html and I ran into a problem. There's a part of my form where user should be able to click on a textfield and pick a date & time from a calendar(anytime.js by MAM3), and since my form(partial code) is built this way:
third_list = "<table class='table'>";
if (radio_array[genIndex] == reserve) {
third_list += "<tr><td id='Date:'><label><span id='Date'>Date:</span><input type='text' id='Date' name='_date' size='20' onfocus='showMessage()'/></label></td>";
third_list += "<td id='Time:'><label><span id='Time'>Time:</span><input type='text' id='Time' name='_time' size='20' /></label></td>";
document.getElementById("third").innerHTML = third_list;
l3_value = "";
return;
}
and by putting this to the html:
<script type="text/javascript">
AnyTime.widget
( "Date",
{ format: "%m/%d/%Z" }
);
AnyTime.widget
( "Time",
{ format: "%h:%i:%p" }
);
</script>
it does not pop-up a calendar.
Side notes: I have included all of the required js&css files and tried to see if it works on a seperate text field out from js, and it works. I think the reason it doesnt work is it is controlled by js, so the anytime.js does not see it as a html name field.
SN2: onfocus='showMessage()' in my js is to show a message when a user clicks on a text field.
How do I make it work?
A couple of issues:
First, you have more than one element with the id values Date and Time. id values must be unique in the document. I expect the script isn't getting the element it expects and is failing to init. The documentation for AnyTime seems to suggest it uses the first argument you give AnyTime.widget as an id and expects to get an input field. In your case, it usually won't on most browsers, because when faced with an invalid structure featuring duplicate ids, most browsers will return the first one when you ask for "the" element with that id, which in your case is a span rather than an input field.
Your Date elements:
<span id='Date'>Date:</span><input type='text' id='Date' ... />
<!-- ^--- one ^--- two -->
The Time is the same sort of problem.
Separately from that, I suspect you need to ensure that the elements exist when you call AnyTime.widget. I don't know where you have that script tag that calls it, but what you need to do is make this calls after you've executed the line
document.getElementById("third").innerHTML = third_list;
...so that the elements in question exist in the DOM. So for instance:
third_list = "<table class='table'>";
if (radio_array[genIndex] == reserve) {
third_list += "<tr><td id='Date:'><label><span id='Date'>Date:</span><input type='text' id='Date' name='_date' size='20' onfocus='showMessage()'/></label></td>";
third_list += "<td id='Time:'><label><span id='Time'>Time:</span><input type='text' id='Time' name='_time' size='20' /></label></td>";
document.getElementById("third").innerHTML = third_list;
l3_value = "";
setUpWidgets();
return;
}
// ...elsewhere in the same scope or a containing scope:
function setUpWidgets() {
AnyTime.widget
( "Date",
{ format: "%m/%d/%Z" }
);
AnyTime.widget
( "Time",
{ format: "%h:%i:%p" }
);
}
That creates a function, which you call when the elements are there.
Side note: You also have an id that looks like this:
<td id='Date:'>
Although that's a valid id in HTML5, it wasn't valid in HTML4 and isn't valid in CSS. So if you try to use that id in a CSS-style selector (for instance, with jQuery), you'll probably run into trouble.
I am using ASP.Net MVC along with Jquery to create a page which contains a contact details section which will allow the user to enter different contact details:
<div id='ContactDetails'>
<div class='ContactDetailsEntry'>
<select id="venue_ContactLink_ContactDatas[0]_Type" name="venue.ContactLink.ContactDatas[0].Type">
<option>Email</option>
<option>Phone</option>
<option>Fax</option>
</select>
<input id="venue_ContactLink_ContactDatas[0]_Data" name="venue.ContactLink.ContactDatas[0].Data" type="text" value="" />
</div>
</div>
<p>
<input type="submit" name="SubmitButton" value="AddContact" id='addContact' />
</p>
Pressing the button is supposed to add a templated version of the ContactDetailsEntry classed div to the page. However I also need to ensure that the index of each id is incremented.
I have managed to do this with the following function which is triggered on the click of the button:
function addContactDetails() {
var len = $('#ContactDetails').length;
var content = "<div class='ContactDetailsEntry'>";
content += "<select id='venue_ContactLink_ContactDatas[" + len + "]_Type' name='venue.ContactLink.ContactDatas[" + len + "].Type'><option>Email</option>";
content += "<option>Phone</option>";
content += "<option>Fax</option>";
content += "</select>";
content += "<input id='venue_ContactLink_ContactDatas[" + len + "]_Data' name='venue.ContactLink.ContactDatas[" + len + "].Data' type='text' value='' />";
content += "</div>";
$('#ContactDetails').append(content);
}
This works fine, however if I change the html, I need to change it in two places.
I have considered using clone() to do this but have three problems:
EDIT: I have found answers to questions as shown below:
(is a general problem which I cannot find an answer to) how do I create a selector for the ids which include angled brackets, since jquery uses these for a attribute selector.
EDIT: Answer use \ to escape the brackets i.e. $('#id\\[0\\]')
how do I change the ids within the tree.
EDIT: I have created a function as follows:
function updateAttributes(clone, count) {
var f = clone.find('*').andSelf();
f.each(function (i) {
var s = $(this).attr("id");
if (s != null && s != "") {
s = s.replace(/([^\[]+)\[0\]/, "$1[" + count + "]");
$(this).attr("id", s);
}
});
This appears to work when called with the cloned set and the count of existing versions of that set. It is not ideal as I need to perform the same for name and for attributes. I shall continue to work on this and add an answer when I have one. I'd appreciate any further comments on how I might improve this to be generic for all tags and attributes which asp.net MVC might create.
how do I clone from a template i.e. not from an active fieldset which has data already entered, or return fields to their default values on the cloned set.
You could just name the input field the same for all entries, make the select an input combo and give that a consistent name, so revising your code:
<div id='ContactDetails'>
<div class='ContactDetailsEntry'>
<select id="venue_ContactLink_ContactDatas_Type" name="venue_ContactLink_ContactDatas_Type"><option>Email</option>
<option>Phone</option>
<option>Fax</option>
</select>
<input id="venue_ContactLink_ContactDatas_Data" name="venue_ContactLink_ContactDatas_Data" type="text" value="" />
</div>
</div>
<p>
<input type="submit" name="SubmitButton" value="AddContact" id='addContact'/>
</p>
I'd probably use the Javascript to create the first entry on page ready and then there's only 1 place to revise the HTML.
When you submit, you get two arrays name "venue_ContactLink_ContactDatas_Type" and "venue_ContactLink_ContactDatas_Data" with matching indicies for the contact pairs, i.e.
venue_ContactLink_ContactDatas_Type[0], venue_ContactLink_ContactDatas_Data[0]
venue_ContactLink_ContactDatas_Type[1], venue_ContactLink_ContactDatas_Data[1]
...
venue_ContactLink_ContactDatas_Type[*n*], venue_ContactLink_ContactDatas_Data[*n*]
Hope that's clear.
So, I have a solution which works in my case, but would need some adjustment if other element types are included, or if other attributes are set by with an index included.
I'll answer my questions in turn:
To select an element which includes square brackets in it's attributes escape the square brackets using double back slashes as follows: var clone = $("#contactFields\[0\]").clone();
& 3. Changing the ids in the tree I have implemented with the following function, where clone is the variable clone (in 1) and count is the count of cloned statements.
function updateAttributes(clone, count) {
var attribute = ['id', 'for', 'name'];
var f = clone.find('*').andSelf();
f.each(function(i){
var tag = $(this);
$.each(attribute, function(i, val){
var s = tag.attr(val);
if (s!=null&& s!="")
{
s = s.replace(/([^\[]+)\[0\]/, "$1["+count+"]");
tag.attr(val, s);
}
});
if ($(this)[0].nodeName == 'SELECT')
{ $(this).val(0);}
else
{
$(this).val("");
}
});
}
This may not be the most efficient way or the best, but it does work in my cases I have used it in. The attributes array could be extended if required, and further elements would need to be included in the defaulting action at the end, e.g. for checkboxes.