How to refresh DOM with newly created elements - javascript

I know this question was asked several times, but couldn't get the answer that works for me so here I am with my case.
I'm trying to make a jQuery plug-in that's add contact form to a certain page(It's not like there is no such a plug-ins but let's say I do this just for educational reasons). It is searching for <div id="add_contacts"></div> and creates the form in this div.
jQuery
$(document).ready(function(){
$('#add_contacts').append('<div class="contact-from"></div>');
$('<form></form>',{id:'new_contact'}).appendTo('.contact-form');
$('<div>',{class:'contact_user_name'}).appendTo('#new_contact');
var name_field = $('<input>',{
name:"contact_broker_fullname",
id:"contact_user_name",
}).appendTo('.contact_user_name');
var input_button = $('<input>',{
name:"submit",
type:"submit",
value:"Send"
}).appendTo('#new_contact');
var full_name=name_filed.val();//I'm not sure that this should be here at all.
input_button.on('click',function(){
ajax_send_contact(full_name);
return false;
});
});
And here is the ajax_send_contact(full_name) function:
$.ajax({
url:'../some.php',
type:'post',
data:{name:full_name},
success: function (response){
if (response) {
$('#success').append('<span>All right.</span>');
}
else{
$('#errors').append('<span>Something went wrong.</span>');
}
},
error: function () {
$('#errors').append('<span>ERROR!</span>');
}
});
I've read that when adding dynamically element to HTML they're not included into the DOM, so how can i operate with them. How i can get the value of the input so once the user click the Submit button the value is sent to ajax function. And I'm not asking only for this particular case but for the whole logic as I'm missing something quite important.
Thank you.

I don't know where you read this but it's not true.
Adding elements to your page is DOM manipulation.
In fact there is a lot of DOM manipulation in your ready function.
DOM manipulations are costly, try to reduce them by grouping operations :
var formHtml = '';
formHtml += '<div class="contact-form">';
formHtml += '<form id="new_contact">';
formHtml += '<div class="contact_user_name">';
formHtml += '<input type="text" name="contact_broker_fullname" id="contact_user_name">';
formHtml += '</div>';
formHtml += '<input type="submit" name="submit" value="send">';
formHtml += '</form>';
formHtml += '</div>';
$('#add_contacts').append(formHtml); // Only 1 DOM manip.
There are errors in your code :
$('#add_contacts').append('<div class="contact-from"></div>');
...
var name_field = $('<input>',{
And then :
$('<form></form>',{id:'new_contact'}).appendTo('.contact-form');
...
var full_name=name_filed.val();
'contact-from' then 'contact-form'.
'name_field' then 'name_filed'.
In your code, you get the value of your input#contact_user_name right after you created the form,
that is to say before the user had any chance to input something in it.
You have to do this in your click handler.

Pretty simple, set the data with the value of the field right before firing the request:
data: { name: $('.contact_user_name input').val() }
And you can remove var full_name=name_filed.val(), it would only get the value the field had at the moment it was created, and apparently that variable wouldn't be in scope when you actually need it.
The rest of your code looks okay.

Related

Unable to get element id dynamically in javascript

I have a list of students that I am looping through and adding to my page. Each student has a unique ID, and when getStudentInfo is invoked, it does something with the id. The problem is that whichever student I click, I get back the same id, belonging to student1.
Where am I going wrong?
foreach ($students as $student) {
echo '<tr>';
echo '<td>
'.$student[student_permalink].'
<input type="submit"
value="info"
onclick="getStudentInfo()"
class="student-name-btn"
id="'.$student[student_permalink].'"
/>
</td>';
}
js:
function getStudentInfo() {
var studentLink = $('.student-name-btn').attr('id');
console.log(studentLink);
}
Your code is selecting all the buttons on the page with that class and than reads the id of the first one in the list. You are not limiting it to the one that was clicked.
What most people would do is add events with jQuery and not inline.
//needs to be loaded after the element or document ready
$(".student-name-btn").on("click", function() {
console.log(this.id);
});
For yours to work, you would need to pass a reference to the button that was clicked.
onclick="getStudentInfo(this)"
and than change it to use the node passed in
function getStudentInfo(btn) {
var studentLink = $(btn).attr('id');
console.log(studentLink);
}
You can pass the reference to the element being clicked on the onclick event
foreach ($students as $student) {
echo '<tr>';
echo '<td>
'.$student[student_permalink].'
<input type="submit"
value="info"
onclick="getStudentInfo(this)" // << added this which refers to the input
class="student-name-btn"
id="'.$student[student_permalink].'"
/>
</td>';
}
And then use that to fetch the id in the js
function getStudentInfo(el) {
var studentLink = $(el).attr('id');
console.log(studentLink);
}
Don't use inline events - there's no need to clutter up the HTML with that. You have a common class on your element, so just make a jQuery handler and use an instance of this
$('.student-name-btn').click(function() {
var id = this.id;
});
Like #epascarello alluded to, you are not selecting the button that was actually clicked. What you should do is have your event handling in your JS, not in the HTML so you can see better how it works and use the this keyword within the closure to reference the clicked button.
$(document).on('click', '.student-name-btn', function(evt) {
// Prevent default if trying to do your own logic
evt.preventDefault();
// Need to use the "this" keyword to reference the clicked element
var studentId = $(this).attr('id');
console.log(studentId);
});
You can do this without inline JavaScript and since you're using jQuery drop the onClick() and the form element:
echo '<tr>';
echo '<td id="'.$student['student_permalink'].'" >
'.$student['student_permalink'].'
</td>';
You also need to quote the identifier in the array variable, 'student_permalink'.
The jQuery will be this:
$('td').click(function() {
var studentLink = this.id;
console.log(studentLink);
});

How can I retrieve input values from elements added after page load?

I'm working with Zend Framework 1.12 and I've need to be able to dynamically add and delete fields from a sub-form, in this case we're associating hyperlinks to a parent "promotion".
I haven't found a way to accomplish dynamically adding and removing elements via Zend, and the rare tutorial I've found that claimed to do this are half a decade old and aren't working when I attempt them.
So what I am doing is storing the links I need to work with in a Zend Hidden input field and then dealing with the JSON data after I submit. Not very efficient, but it's the only thing I've gotten to work so far.
Below is the section of the code I'm working with:
Assume a form like:
<form action="/promos/edit/promo_id/15" method="POST" id="form_edit">
<!-- input is Zend_Form_Element_Hidden -->
<input type="hidden" id="link_array" value="{ contains the JSON string }"/>
<button id="add_link">Add Link</button>
</form>
The purpose is that every time the Add Link button is pressed, the form adds fields to allow the user to input new hyperlinks that will be associated with the specific items.
Here's the function:
// add links
$('#add_link').click(
function(e) {
e.preventDefault();
link = '<div class="p_link new_link">' +
'<div class="element_wrap">' +
'<label for="link_name" class="form_label optional">Text: </label>' +
'<input type="text" id="new_link_name" name="link_name"/>' +
'</div>' +
'<div class="element_wrap">' +
'<label for="link_http" class="form_label optional">http://</label>' +
'<input type="text" id="new_link_http" name="link_http"/>' +
'</div>' +
'<div class="element_wrap">' +
'<button class="submit delete_link">Delete</button>' +
'</div>' +
'</div>';
$('#add_link').prev().after(link);
}
);
Now, what I need to do is on submit, for every new_link class element, to take the links name and http reference and place it in a json object. Here's the code as I have it so far (I know I don't have both input fields represented at this point):
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = document.getElementsByClassName('new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).children('#new_link_name').text();
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
My problem is that: var new_links = document.getElementsByClassName('new_link'); will collect all the newly added new_link elements, but it does not pull in any value that has been input into the text fields.
I need to know how I can apparently bind any input I make to the input field's value attribute, because right now anything I type into these new elements are tossed out and the field appears empty when it's anything but.
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = $('.new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).find('input').val(); // you need input values! This line //is changed...
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
JSFIDDLE: http://jsfiddle.net/DZuLJ/
EDit: You can't have multiple IDS (make class for each input, and target class, if you want link names and http's)

dynamic button does not call javascript function?

I have a button wich im dynamically adding to my page like this.
if (adminInd =='X'){
var adminDiv = $(
'<label id=Delegatelbl>Miscellaneous label prototyping.:</label>'+
'</br></br>'+
'<div style="padding-right:152px;"> '+
'<form action="userfop.jsp" id="userForm" >'+
'<label for="tuid">TU-ID:</label>'+
'<input type="text" name="tuid" id="tuid" maxlength="9"/>'+
'<button type="button" id="RoleChanger" style="cursor:pointer" class="ab_submit" onclick="validateTuid()"> Change Role </button>'+
'</form>'+
'</div>');
adminDiv.insertBefore('#FormDiv');
}
as you can see from the button tag im trying to call a javascript function and
i just about tried everything and the function does not trigger. What im i doing wrong. I've been trouble shooting this for 2 hours now with no success.
here is the function I dont see what I'm doing wrong. Someone please point me in the right direction.
function validateTuid(){
var textTuid = document.getElementById(tuid).value
$.ajax({ type: "POST",
url: "dbfunctions.jsp",
data: {TYPE:"V", tuidval:textTuid }}).done(function( msg )
{
alert("Data Saved: " + $.trim(msg));
if (msg != null || msg != ''){userForm.submit()}
return "N";
});
You should delegate the click event, you can use on() method, try the following:
$(document).on('click', "#RoleChanger", validateTuid)
Maybe have a look at http://api.jquery.com/live/. Also, instead of hardcoding onClick in the button bind a listener to it instead.

How can I add efficiently add many fields to a form I create in JavaScript?

I've got a new page new form, and I want to hook-up to some existing server-side stuff. Right now I have this code that works, but it's sort of clunky:
// make a form
var OrderStatusSearchQueryForm = document.createElement("form");
// make first input
var Operation = document.createElement("input");
Operation.name="Operation";
Operation.value="Search";
OrderStatusSearchQueryForm.appendChild(Operation);
// make second input
var SearchFieldValue = document.createElement("input");
SearchFieldValue.name="SearchFieldValue";
SearchFieldValue.value=document.formonpage.searchString.value
OrderStatusSearchQueryForm.appendChild(SearchFieldValue);
// not shown, many more inputs like the above
// set a few important values from the form on the page
OrderStatusSearchQueryForm.submit();
I was wondering if I could write a function that would just take the a few parameters and do the same thing. The function would allow me to replace the above with this:
var OrderStatusSearchQueryForm = document.createElement("form");
stakmagic("Operation", "Search", OrderStatusSearchQueryForm);
stakmagic("SearchFieldValue", document.formonpage.searchString.value, OrderStatusSearchQueryForm);
OrderStatusSearchQueryForm.submit();
I'm not sure what you are asking. You may have answered your own question. But if you're wanting the function, here you go:
function stakmagic(name, value, form) {
var Input = document.createElement("input");
Input.name = name;
Input.value = value;
form.appendChild(Input);
}
var inps = "<input name='xx' value='xx' /><input name='xx' value='xx' /> .......etc";
<form>
<div id='mydiv'></div>
</form>
document.getElementByID('mydiv').innerHTML( inps );
This will create all of the elements simultaneously.
Obviously you could use functions, but why not let the HTML parser create the DOM for you, it's actually significantly faster than creating it yourself.
var html = '<form id="myform">' +
'<input name="Operation" value="Search" />' +
'<input name="SearchFieldValue" value="' +
document.formonpage.searchString.value +
'" /></form>';
document.getElementById("form-container").innerHTML = html;
document.getElementById("myform").submit();
Obviously even this is not optimal, as you have a bunch of hard coded html in your javascript. But
that problem was with your original javascript as well. Currently the cleanest and easiest way to do this is
javascript templates. You will be able to maintain the HTML just like it was regular HTML and use very little code to do the same thing.

jquery: "Exception thrown and not caught" in IE8, but works in other browsers

My code works fine in other browsers, but in IE8 I get "error on page" - and when I click that it says:
"Exception thrown and not caught Line: 16 Char: 15120 Code: 0
URI: http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"
I tried linking to jquery.js (rather than jquery.min.js) and to 1.5.1/jquery.min.js,
but problem still remains.
Can someone correct/improve my code for me, or guide me as to where to look. Thanks
<script type="text/javascript">
function fbFetch()
{
var token = "<<tag_removed>>&expires_in=0";
//Set Url of JSON data from the facebook graph api. make sure callback is set with a '?' to overcome the cross domain problems with JSON
var url = "https://graph.facebook.com/<<ID_REMOVED>>?&callback=?&access_token=" + token;
//Use jQuery getJSON method to fetch the data from the url and then create our unordered list with the relevant data.
$.getJSON(url, function(json)
{
json.data = json.data.reverse(); // need to reverse it as FB outputs it as earliest last!
var html = "<div class='facebook'>";
//loop through and within data array's retrieve the message variable.
$.each(json.data, function(i, fb)
{
html += "<div class='n' >" + fb.name;
html += "<div class='t'>" + (dateFormat(fb.start_time, "ddd, mmm dS, yyyy")) + " at " + (dateFormat(fb.start_time, "h:MMtt")) + "</div >";
html += "<div class='l'>" + fb.location + "</div >";
html += '<div class="i"><a target="_blank" title="opens in NEW window" href="https://www.facebook.com/pages/<<id_removed>>#!/event.php?eid=' + fb.id + '" >more info...</a></div>';
html += "</div >";
}
);
html += "</div>";
//A little animation once fetched
$('.facebookfeed').animate({opacity: 0}, 500, function(){
$('.facebookfeed').html(html);
});
$('.facebookfeed').animate({opacity: 1}, 500);
});
};
Does the code do the job in IE8 or does it break? The reason I ask is because if it works as expected you could just wrap it in a try{ } catch{ \\do nothing } block and put it down to another thing IE is rubbish at.
You may be better off creating an object for the creation of the facebook div. Something like...
var html = $('<div />');
html.attr('class', 'facebook');
Then in your each loop you can do this...
$('<div />').attr('class', 'n').append(fb.name).appendTo(html);
$('<div />').attr('class', 't').append etc...
Then append html to the facebookfeed object
Doing this may remove the scope for error when using single quotes and double quotes when joining strings together, which in turn may solve your issue in IE8
$('.facebookfeed').fadeOut(500, function(){
$(this).append(html).fadeIn(500);
});
Hope this helps!
UPDATE
The append method is used to add stuff to a jquery object. For more info see here
So to surround the div's as you mentioned in the comments you would do something like this...
var nDiv = $('<div />').attr('class', 'n').append(fb.name);
$('<div />').attr('class', 't').append(fb.somethingElse).appendTo(nDiv);
// etc
And then you would need to append that to the html div like so...
html.append(nDiv);
So that would give you
<div class="facebook">
<div class="n">
value of fb.name
<div class="t">
value of fb.somethingElse
</div>
</div>
</div>
So what you have done is created a new jquery object and appended to that, then appended that to the html object which you have then appended to the facebookfeed div. Confusing huh?!

Categories

Resources