Intercept a dynamic added form submission - javascript

Normal form submission intercept can be found. But, my class is different. The form is dynamically added after calling a function. Then, the form submission cannot be captured.
How to capture the form submission like this? Better to use Jquery but altering the dynamic added form attributes is acceptable.
The following is the example.
Here is how I capture the form submission.
$(function() {
$(".formClass").submit(function(e) {
e.preventDefault();
var actionurl = e.currentTarget.action;
alert(actionurl);
});
});
Here is how forms are added after calling the function - eObj.getFormElement()
(function($){
function(eObj) {
var selector = "#abc";
//Call the function to get the form elements
eObj.getFormElement(langObj, function(err, x) {
var elem = "<ul>";
for (var i=0; i<x.length; i++) {
var formId = elementId + "_sform_" + i;
elem = elem + "<li class='product_" + i + "'>"
for (var key in x[i]) {
elem = elem + "<div class='price'>" + curMap[curKey] + x[i][key].price + "</div>";
elem = elem + "<div class='s'><form id='" + formId +"' class='formClass' method='post' action='" + x[i][key].url + "'>"
+ "<input class='s_btn' type='submit' value='" + submitLabel + "'>"
+ "</form></div>";
}
elem = elem + "</li>";
}
elem = elem + "</ul>";
//Append the form to the div after we create the forms
$(selector).append(elem);
});
}})(jQuery);

Since You can't set events for non-existing elements You need to set events for element existing.
In this case you can use document to get the event.
http://jsfiddle.net/h189o3xc/
here is a sample code.
$(document).on("submit",function(e){
if($(e.target).hasClass("formClass")){
e.preventDefault();
console.log("you can catch the event!");
//and do whatever you want.
}
});
set a event for document and whenever any submit event happens, check whether it's your target form or not. then do whatever you want if it's your target form.
EDITED
as #charlietfl mentioned,You can use extra on function's parameter instead of if statement.
the code would be something like..
$(document).on("submit",".formClass",function(e){
e.preventDefault();
console.log("you can catch the event!");
//and do whatever you want.
});
http://jsfiddle.net/h189o3xc/2/

Related

Nestable.js issue with callback updating textarea

I'm having an issue with nestable.js and maybe I'm using the callback incorrectly. Below is my current code and I'm loading the JSON from the php variable $primary_menu_json that is passed into the function. It creates the menu with no issues and I can move my menu elements around that are created from the JSON no problem, but it's not updating my hidden textarea (#nestableOutput) on the callback.
The way I understand the callback from the documentation is it's fired when elements are reordered or nested. In my mind this would be the place to update the hidden textarea when an element is dropped. Maybe I am wrong in this thinking. Any help?
$(document).ready(function () {
function nestableJSON(jsonArray, root) {
if (typeof root === 'undefined') {
root = $('body');
}
var $div = $('<div id="nestable02a" class="dd" data-plugin="nestable"><ol class="dd-list dd3-list"></ol></div>');
root.append($div);
for(var i = 0; i < jsonArray.length; i++) {
var $li = $("<li class='dd-item dd-item-alt' id='item-" + jsonArray[i].id + "' data-id='" + jsonArray[i].id + "' data-title='" + jsonArray[i].title + "'><div class='dd-handle'></div><div class='dd-content'>" + jsonArray[i].title + "<span class='float-right wb-trash'></span></div></li>");
root.find('ol.dd-list:first').append($li);
if (typeof jsonArray[i].children !== 'undefined') {
nestableJSON(jsonArray[i].children, $li);
}
}
$('#nestable02a').nestable({
group: 1,
maxDepth: 3,
callback: function(e){
var list = e.length ? e : $(e.target);
$('#nestableOutput').text(window.JSON.stringify(list.nestable('serialize')));
console.log('json updated');
}
});
}
nestableJSON(<?php echo $primary_menu_json; ?>);
});

Adding paramaters for an onclick function inside an element

Hey guys I'm having an issue with the syntax of providing a parameter for a function that I call on an onclick event inside a div.
I can get the function open_email() to call but not when I add a parameter since the parameter I am looking to add is obtained from another form element and I'm not sure how to type it properly.
Below is my code. Please let me know if you know how it should be written. I'm currently getting nothing to happen unless I keep the parameters (arguments) blank.
To clarify, I need to know how to add emails[index].id as an argument for the function below that is called open_email(). What is the proper syntax? I tried : open_email(emails[index].id) and open_email("emails[index].id")
for (index = 0; index < emails.length; index++) {
if (emails[index].read == false) {
element.innerHTML += '<div class="emails unread" onclick="open_email();">' + "From:" + JSON.stringify(emails[index].sender) +
"<p class='subject'>" + "Subject: " + JSON.stringify(emails[index].subject) + "</p>" + JSON.stringify(emails[index].timestamp) + '</div>';
} else {
element.innerHTML += '<div class="emails">' + "From:" + JSON.stringify(emails[index].sender) +
"<p>" + "Subject: " + JSON.stringify(emails[index].subject) + "</p>" + JSON.stringify(emails[index].timestamp) + '</div>';
}
Yes, you can. You need to send an arrow function there. Try to click on the text "Initial Content".
I do not have your open_email function, so I made up one as an example.
Basically, onclick will execute () => open_email(emailIndexId):
<div id="text">Initial Content</div>
<script>
textDiv = document.getElementById('text');
const open_email = id => {
textDiv.innerText = "Sent email to " + id;
}
const emailIndexId = 33;
textDiv.onclick = () => open_email(emailIndexId) // IMPORTANT
</script>

Why is this JavaScript parameter getting lost?

In this function, the value parameter is being passed down to fill in my URL. This works perfectly.
function showResults(results) {
var html = '';
$.each(results, function(index,value) {
html += '<li><img src="' + value.snippet.thumbnails.medium.url + '">' + value.snippet.title + '(More from ' + value.snippet.channelTitle + ')</li>';
});
$('#results').html(html);
}
In this nearly identical function, the value param loses its value. I can't see how. It's difficult to debug why this is happening because console.log() just returns "ReferenceError: $ is not defined" no matter what I check (it returns this in the first section too, which works well).
function showResults(results) {
var html = '';
$.each(results, function(index,value) {
html += '<li><img src="' + value.snippet.thumbnails.medium.url + '">' + value.snippet.title + ') </li>';
});
$('#results').html(html);
$('#results li a').click(function(){
playVid($(this).attr(value.id.videoId));
});
}
function playVid(vidID) {
var embedVid = 'https://www.youtube.com/embed/'+vidID+'?autoplay=1';
document.getElementById('player').src = embedVid;
}
Here I'm trying to push the value param (in the url again) to an iframe with id="player". The iframe receives an invalid param and the video won't play. Meanwhile the video plays in the first example. Where does value get lost?
value only exists within the scope of the each loop. So, first fix your reference error, and then I suggest the following changes in that second example:
1) Update the href with the videoId value in the each loop like in the first example:
<a href="https://www.youtube.com/watch?v=' + value.id.videoId + '">
2) And then launch the player with that value:
$('#results li a').click(function(e) {
e.preventDefault();
playVid($(this).attr('href'));
});

How to change a javascript function's parameter from callback function

I have an HTML input element generated by the server and it looks like this:
HERE IS THE SERVER SIDE
"<input id='" + cRoadList.getRoadListNumber() + ",start_km' style='' type=\"text\" value='"+ cRoadList.getStartKm() + "' onkeypress='handleRoadListDataUpdate(\""+cRoadList.getStartKm()+"\")'
As you see the attrbutes of the input element are generated dynamically but that is not the case so let's simplify it by putting some static data like this:
"<input id='myID' style='' type=\"text\" value='100' onkeypress='handleRoadListDataUpdate(\"100\")'
The most important part of this HTML input element is the onkeypress event which calls the function handleRoadListDataUpdate
HERE IS THE CLIENT PART
function handleRoadListDataUpdate(oValue) // The function accpets the old value of the *input* element
{
var event = handleRoadListDataUpdate.caller.arguments[0] || window.event ;
var keyPressed = event.keyCode;
if(keyPressed == 13)
{
var roadListNumber = event.target.id.split(",")[0];
var inputId = event.target.id.split(",")[1];
var nValue = event.target.value;
if(nValue != oValue)
{
var userAction = confirm("Are you sure you want to change this value?\nPrevious value: " + oValue + "\nNew value: " + nValue);
if(userAction == true)
{
var url = "/GBS/RoadListController";
var params = "type=updateRoadList&roadListNumber=" + roadListNumber + "&updateData="+inputId + "&newValue="+ nValue;
dhtmlxAjax.post(url,params,function(loader)
{
var xmlDoc = loader.xmlDoc.responseXML;
var sqlResponse = xmlDoc.documentElement.getElementsByTagName("response");
var result = sqlResponse[0].getAttribute("value");
if(result == "sql_error")
{
alert("The operation could not be completed because of an network error!");
event.target.value = oValue;
}
else if(result == "sql_success")
{
alert("The operation completed successfully!");
//Change the parameter oValue of the parent function
}
});
}
else
{
event.target.value = oValue;
}
}
}
}
Basically this function is about updating (using ajax) the database with the new value the user enters inside the input element and press key Enter. If the parameter oValue is different than the parameter in the input element an ajax request is made so the database can be updated with the new value.
When the operation completes we have the new value in the input element (which is entered by the user) but the problem is that if he press Enter again the function get executed AGAIN because its parameter oValue is not changed with the new value.
So my very question is:
How to change the handleRoadListDataUpdate() function's parameter oValue to become the same as nValue so if the user press Enter by accident the function does not execute the ajax part again?
P.S.
Please no jQuery code! Only pure javaScript!

Things are happening outside my for loop before its done (javascript)

I'm sure I've seen this before and know the answer to it but after 12 hours... my mind is complete mush.
I have a for loop in which I am trying to concatenate onto a string so that AFTER I can complete the string (thus completing a nice little table) that I had hoped to then insert into my html and show the user.
However, the things at the end of my function (after my for loop) are getting called before the for loop ever does....
function getEntries() {
$('#entryTotalsDiv').html('<img src="images/ajax-loader.gif" /> ... retrieving form totals.');
var entryTotalsTable = "<table id='entryTable' class='display' style='border:1px;'><thead><tr><th>Form Name</th><th>Hash</th><th>Entries</th></tr></thead>" +
"<tbody>"
//Get rows ONE at a time.
var countNumber = 1;
for (var frm = 0; frm < numberOfForms; frm++) {
$.post('ajax/getEntries.aspx',
{
'formNumber': frm
},
function (data) {
entryTotalsTable += "<tr><td>" + data[0].formName + "</td><td>" + data[0].formHash + "</td><td>" + data[0].formEntryCount + "</td></tr>";
//Now go and update the Form Retrieval div -- add 1 to the frm Number
$('#formNamesDiv').html(countNumber + ' of ' + numberOfForms + ' retrieved.');
countNumber++;
});
}
entryTotalsTable += "</tbody></table>";
$('#entriesDiv').html(entryTotalsTable);
//Now bind the table to the DataTables JQ script
$('#entryTable').dataTable();
$('#entryTable').show('slow');
}
If you notice, I wanted to close up the Table html at the end, but this gets called before my for loop is finished, thus screwing up my string...
?
entryTotalsTable += "</tbody></table>";
$('#entriesDiv').html(entryTotalsTable);
//Now bind the table to the DataTables JQ script
$('#entryTable').dataTable();
$('#entryTable').show('slow');
}
A solution could be to save every response in an array and test in every callback whether the current count is equal to the total count. Something like:
var countNumber = 1,
allData = [];
function runWhenFinished() {
if(countNumber === numberOfForms) {
var entryTotalsTable = "<table id='entryTable' class='display' style='border:1px;'><thead><tr><th>Form Name</th><th>Hash</th><th>Entries</th></tr></thead>" + "<tbody>";
for(var i = 0, l = allData.length; i < l; i++) {
entryTotalsTable += "<tr><td>" + allData[i].formName + "</td><td>" + allData[i].formHash + "</td><td>" + allData[i].formEntryCount + "</td></tr>";
}
entryTotalsTable += "</tbody></table>";
$('#entriesDiv').html(entryTotalsTable);
//Now bind the table to the DataTables JQ script
$('#entryTable').dataTable();
$('#entryTable').show('slow');
}
}
for(var frm = 0; frm < numberOfForms; frm++) {
(function(frm) {
$.post('ajax/getEntries.aspx',{'formNumber': frm}, function (data) {
allData[frm] = data[0];
countNumber++;
$('#formNamesDiv').html(countNumber + ' of ' + numberOfForms + ' retrieved.');
runWhenFinished();
});
}(frm));
}
I'm sure this can still be improved, but you get the idea.
If you really make 70 requests then you might want to rethink your strategy anyway. 70 simultaneous requests is a lot.
E.g. you could make one request and prove the minimum and maximum number of that should be retrieved / updated / whatever the method is doing.
$.post is asynchronous, meaning that it's firing off all the requests in the loop as fast as it can, and then exiting the loop. It doesn't wait for a response. When the response comes back, your row function is then called... but by then, all the posts have been sent on their way.
See the answers to this question here...
How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?
You'll need to change from $.post to $.ajax

Categories

Resources