Event delegation in Firefox after Ajax - ajax

Below is example html, script and php to submit and reload two forms via jquery ajax. In the real application, the same forms will not be reloaded but a series of forms will be loaded after each is submitted.
In chrome, IE and safari; clicking submit results in the intended ajax request. The server responds as intended. Results (showing post variables for conformation) and new forms are loaded into the page as intended. Those new forms can then be submitted and all is good.
In firefox; everything works as intended until you try to submit the forms that were loaded via ajax. They will not submit. The original forms do work. It is only the ones added via ajax that don't submit.
I am guessing that this is an "event delegation" issue with the way firefox updates the DOM after the ajax. I have read the documentation at http://api.jquery.com/on/ and other places but I am at a loss...
Any help or suggestions would be greatly appreciated! My goal is to get this functional in the latest versions of chrome, IE, safari and firefox.
html page with script
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Example Ajax Form Submit</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<div id="results"></div>
<div id="forms">
<div>
<table width="100%" cellspacing="0" cellpadding="0" class="ui-widget">
<form>
<tr>
<td width="100"></td><td width="300"></td><td></td>
</tr>
<tr>
<td class=""colspan="3"><h1>Form 1</h1></td>
</tr>
<tr>
<td>Input 1A</td><td colspan="2"><input type="text" name="1A" /></td>
</tr>
<tr>
<td colspan="3"><input type="hidden" name="1B" value="Form 1 was submitted" /></td>
</tr>
<tr>
<td colspan="3"><button type="submit" >Click Me!</button><input type="submit" value="Submit Form 1" /></td>
</tr>
</form>
</table>
</div>
<div>
<table width="100%" cellspacing="0" cellpadding="0" class="ui-widget">
<form>
<tr>
<td width="100"></td><td width="300"></td><td></td>
</tr>
<tr>
<td class=""colspan="3"><h1>Form 2</h1></td>
</tr>
<tr>
<td>Input 2A</td><td colspan="2"><input type="text" name="2A" /></td>
</tr>
<tr>
<td colspan="3"><input type="hidden" name="2B" value="Form 2 was submitted" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Submit Form 2" /></td>
</tr>
</form>
</table>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$("#forms").on("submit", "form", function(e) {
e.preventDefault();
$.ajax({
url: "testAjax.php",
type: "POST",
cache: false,
data: $(this).serializeArray(),
success: function(jsonData) {
htmlData = jQuery.parseJSON(jsonData);
$.each(htmlData, function(id, data){
$("#"+id).html(data);
});
},
error: function(jqXHR, textStatus, errorThrown){
$("#results").html("<p>Somthing went wrong!</p>");
}
});
});
});
</script>
</body>
</html>
testAjax.php
<?php
$htmlOutput['forms'] =
'<div>
<table width="100%" cellspacing="0" cellpadding="0" class="ui-widget">
<form id="login" method="post" enctype="multipart/form-data" target="_self" action="_self">
<tr>
<td width="100"></td><td width="300"></td><td></td>
</tr>
<tr>
<td class=""colspan="3"><h1>Form 1</h1></td>
</tr>
<tr>
<td>Input 1A</td><td colspan="2"><input type="text" name="1A" /></td>
</tr>
<tr>
<td colspan="3"><input type="hidden" name="1B" value="Form 1 was submitted" /></td>
</tr>
<tr>
<td colspan="3"><button type="submit" >Click Me!</button><input type="submit" value="Submit Form 1" /></td>
</tr>
</form>
</table>
</div>
<div>
<table width="100%" cellspacing="0" cellpadding="0" class="ui-widget">
<form>
<tr>
<td width="100"></td><td width="300"></td><td></td>
</tr>
<tr>
<td class=""colspan="3"><h1>Form 2</h1></td>
</tr>
<tr>
<td>Input 2A</td><td colspan="2"><input type="text" name="2A" /></td>
</tr>
<tr>
<td colspan="3"><input type="hidden" name="2B" value="Form 2 was submitted" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Submit Form 2" /></td>
</tr>
</form>
</table>
</div>';
$htmlOutput['results'] =
'<p>Form 1:<br> 1A = ' . $_POST['1A'] . '<br>1B = ' . $_POST['1B'] . '</p>' .
'<p>Form 2:<br> 2A = ' . $_POST['2A'] . '<br>2B = ' . $_POST['2B'] . '</p>';
echo json_encode($htmlOutput);
?>

Open Firebug DOM inspector and verify that your form indeed loaded. I am pretty sure you are not allowed to nest form element directly under table element, and FF is likely simply dropping it.
In general issues like this one are always due to broken HTML. Verify that your HTML is correct. Verify that loaded DOM is what you expect it to be.
Here is how your HTML is being parsed. As expected form has been mangled.

Related

Bootstrap Modal window and Thymeleaf

I have a project with Spring Mvc and I want to use Bootstrap modal windows and Thymeleaf. I hava a view students.jsp witch get list of students from model when I make loop without Thymeleaf everything work ok.
I use JS. But when I use Thymeleaf model windows didn't work ok.
<table class="table table-hover">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
<tr id="user-${user.id}" th:each="user: ${students}">
<td th:text="${user.id}" />
<td th:text="${user.firstName}" />
<td th:text="${user.lastName}" />
<td>
<button type="button" class="btn btn-primary editButton"
data-toggle="modal" data-target="#myModal" data-user-id="${user.id}">Edit</button>
</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
$("#myModal").on('show.bs.modal', function(e) {
var userId = $(e.relatedTarget).data('user-id');
var cols = $('#user-' + userId + ' td');
var firstName = $(cols[0]).text();
var lastName = $(cols[1]).text();
var email = $(cols[2]).text();
$('#firstNameInput').val(firstName);
$('#lastNameInput').val(lastName);
$('#emailInput').val(email);
});
$("#myModal").on('hidden.bs.modal', function() {
var form = $(this).find('form');
form[0].reset();
});
</script>
It doesn't get data from list. I don't know how to solve this problem. Please help me :)
There's a small problem with data-user-id attribute in your "Edit" button.
Instead of:
data-user-id="${user.id}"
...you should have:
th:data-user-id="${user.id}"
...so that the attribute is processed by Thymeleaf and ${user.id} actually replaced with expected value.
<tr th:each="user: ${students}" th:id="'user-' + ${user.id}">
<td th:text="${user.id}" />
<td th:text="${user.firstName}" />
<td th:text="${user.lastName}" />
<td th:text="${user.email}" />
<td>
<button type="button" class="btn btn-primary editButton"
data-toggle="modal" data-target="#myModal"
th:data-user-id="${user.id}">Edit</button>
</td>
</tr>

How to send this post without the submit

How to send this post without the submit?
I need that as I point to the this html page the form is posted without any button submission.
I am not so expert then please the example should be as simple as possible.
Many thanks for your help.
This is my Post base code:
<html>
<hr>
<b>Send sms text</b>
<br>
<br>
<form method=POST action="http://111.111.111.111:1111/smssend.cgi">
<table>
<tr>
<td> Destination number </td>
<td><input type=text name=num value="+39111111111" </td>
</tr>
<tr>
<td> Message text </td>
<td> <textarea name=text value="My message"></textarea></td>
</tr>
<tr>
<td> Password </td>
<td> <input type=text name=Pwd value="SMSxxx"></td>
</tr>
</table>
<input type=submit value=Send>
</form>
<hr>
</html>
Try the following code:
<html>
<head>
<script type="text/javascript">
function send() {
document.getElementById('myForm').submit();
}
</script>
</head>
<body>
<hr>
<b>Send sms text</b>
<br>
<br>
<form id="myForm" method=POST action="http://111.111.111.111:1111/smssend.cgi">
<table>
<tr>
<td>Destination number</td>
<td><input type=text name=num value="+39111111111"></td>
</tr>
<tr>
<td>Message text</td>
<td><textarea name=text value="My message"></textarea></td>
</tr>
<tr>
<td>Password</td>
<td><input type=text name=Pwd value="SMSxxx"></td>
</tr>
</table>
<input type=button value=Send onclick="send();">
</form>
<hr>
</body>
</html>

Content Wont Scroll With Footer And Header Fixed

I have set both the header and the footer to fixed but still cannot get the content to adjust in IPhone.
Here is my layout code
<body>
<div data-role="page" #(Page.Id == null ? string.Empty : "id=" + Page.Id) data-fullscreen="false">
#* #RenderSection("MoreCode", false)*#
#if (IsSectionDefined("Header"))
{
<div data-role="header" data-position="fixed">
#RenderSection("Header", false)
</div><!-- /header -->
}
<div data-role="content">
#RenderBody()
</div><!-- /content -->
<div data-role="footer" data-tap-toggle="false" data-position="fixed">
<div class="center-wrapper">
<table border="0">
<tr>
<td>
<label for="basic">
Place Of Interest
</label>
</td>
</tr>
<tr>
<td>
<table border="0">
<tr>
<td>
Terms of Use
</td>
<td>
<label for="basic">
|
</label>
</td>
<td>
Privacy Policy
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</body>
Here is my View
<h3 style='color:#4FA600; font-weight:bold;'>#ViewBag.Number</h3>
<table border="1" width="100%">
<tr>
<td align="center" valign=middle style=' font-weight:bold; color:#FFFFFF; background:#4FA600; '>
<label for="basic">Available Documents</label>
</td>
</tr>
<tr>
<td>
<table width="100%" height="100%">
<tr>
<td align="left" valign="middle" style=' font-weight:bold;'>
Type
</td>
<td align="center" valign="middle" style=' font-weight:bold;'>
Description
</td>
</tr>
#{
foreach(var row in Model)
{
<tr>
<td align="left" valign="middle">
#row.DocType
</td>
<td align="center" valign="middle">
#row.Description
</td>
</tr>
}
}
</table>
</td>
</tr>
</table>
Isnt jquerymobile suppose to manually adjust? It renders fine in firefox. What can I do to make the content fully display?
\The issue was I had this in my css:
[data-role=page]{height: 100% !important; position:relative !important;}
I got this code from use theme roller not sure why this messed it up. Maybe someone can clarify would be appreciated

How to display the similar information in every view?

I would like to display the information about user's registration state. It should be displayed on every view, but i consider, that writting this code for about 20 times is a bad idea. By the way, this is the code, it works, i guarantee that:
View/RegistrationInfo:
<table width="95%" border="0" cols="2">
<tr>
<td width="50%" height="124"><h2><strong>Simple Blog </strong></h2></td>
<td width="50%" height="124">
#if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account"))
{
<table width="95%" height="86" border="0">
<tr>
<td width="50%" valign="middle">Hello, #System.Web.HttpContext.Current.User.Identity.Name</td>
<td width="50%" valign="middle" align = "right"><input type="submit" value="Exit" /></td>
</tr>
</table>
}
}
else
{
using (Html.BeginForm("LogIn", "Home"))
{
<table width="95%" height="86" border="0">
<tr>
<td width="45%" valign="bottom">Login:</td>
<td width="45%" valign="bottom">Password:</td>
<td width="10%"></td>
</tr>
<tr>
<td width="45%">
<p>
<input type="text" name="login" />
</p>
</td>
<td width="45%">
<p>
<input type="password" name="password" />
</p>
</td>
<td width="10%" align="left">
<input type="submit" value="Enter" />
</td>
</tr>
<tr>
<td width="45%" valign="top">
#Html.ActionLink("Register", "Register", "Account")
</td>
</tr>
</table>
}
}
</td>
</tr>
</table>
<hr align="left" width="100%" size="2" />
As you can see, this view doesn't require to be strongly typed... and i don't know, should I modify any controllers (because, all information is stored in HTML Context), and how. I tried to call
#Html.RenderAction("RegistrationInfo", "Home");
or
#Html.RenderPartial("RegistrationInfo", "Home");
and every time i receive compile error with message about invalid parametres
While Darin's answer perfectly covers your question, I would point out that registration information seems like it's part of your layout more (master page for the .aspx-inclined) than an actual action.
So what I would do (and indeed, do do) is put it either in the header part of your layout in the top right or under your side menu or something, and let the layout handle all the details of rendering it (with a conditional around it to hide it when you're not logged in, so you don't see it on the login screen).
The following should work:
#Html.Partial("~/Views/Home/RegistrationInfo.cshtml")
Or if you are inside a view of the Home controller simply:
#Html.Partial("RegistrationInfo")
Or if you put this partial in ~/Views/Shared/RegistrationInfo.cshtml you will be able to reference with the shorthand syntax.

Coldfusion forms and image upload with cffile

I'm learning some Coldfusion, and I'm having trouble with this small form based application I'm building for a coworker.
Here is the first page: http://pastebin.com/aLPYHPsF
As you can see, what I want to do is get the user input and take that input and output it to html. The text stuff works fine, but I can't get the image to upload! What I want to do is have the user click upload, get a confirmation, then click submit and they are sent to the generated html (cfm) page. On the page is a resized version of the image they uploaded.
Please tell me what I'm doing wrong! Right now when "upload" is clicked, the form just dumps.
It's because of you forgot to assign enctype="multipart/form-data" to your first cfform. I've edited some of your coding. Check it out.
<cfset strPath = ExpandPath( "./" ) />
<cfset strPath = GetDirectoryFromPath(GetCurrentTemplatePath()) />
<table width="100%">
<tr>
<td align="center">
<cfform name="ecaform" action="ecagenerator.cfm" enctype="multipart/form-data">
<table style="font-family: arial; font-size: 9pt">
<tr><td height="30px" align="center" colspan="2" style="background-color: #020058; color: #FFFFFF; font-family: arial;">
<b>ECA Newsletter Creation Form</b>
</td>
</tr>
<tr><td height="20"></td></tr>
<tr>
<td>Earned from:</td>
<td>
<cfinput
type="radio"
name="earnedfrom"
value="UC">
UC
<cfinput
type="radio"
name="earnedfrom"
value="ECA">
ECA
</td>
</tr>
<tr>
<td>First Name:</td>
<td>
<cfinput
name="firstname">
</td>
</tr>
<tr>
<td>Last Name:</td>
<td>
<cfinput
name="lastname">
</td>
</tr>
<tr>
<td>Instructor's Name:</td>
<td>
<cfinput
name="instructorname">
</td>
</tr>
<tr>
<td>Date (MM/DD/YYYY):</td>
<td>
<cfinput
name="date">
</td>
</tr>
<tr>
<td>Sex:</td>
<td>
<cfinput
type="radio"
name="sex"
value="male">
Male
<cfinput
type="radio"
name="sex"
value="female">
Female
</td>
</tr>
<tr>
<td>Certificate Type:</td>
<td>
<cfinput
type="radio"
name="certtype"
value="Private">
Private
<cfinput
type="radio"
name="certtype"
value="Recreational">
Recreational
<cfinput
type="radio"
name="certtype"
value="Commercial">
Commercial
</td>
</tr>
</table>
<table style="font-family: arial; font-size: 9pt; margin-top: 20 px;">
<tr>
<td>
Upload the photo:
</td>
</tr>
<tr>
<td>
<cfif isDefined("form.fileUpload")>
<cffile action="upload"
fileField="fileUpload"
destination="#strPath#"
accept="image/*">
<cfimage action="resize"
width="200"
height="200"
source="#strPath##file.serverfile#"
destination="#strPath##file.serverfile#"
overwrite="yes">
<img src="<cfoutput>#file.serverfile#</cfoutput>">
</cfif>
</td>
</tr>
<tr>
<td>
<form enctype="multipart/form-data"
method="post">
<input type="file"
name="fileUpload" /><br /><br />
<input type="submit"
value="Submit"
action="ecagenerator.cfm" />
</form>
</td>
</tr>
</table>
<table style="margin-top: 20px;">
<tr>
<td>
<cfinput
type="submit"
name="Submit"
value="Submit">
</td>
</tr>
</table>
</cfform>
</td>
</tr>
</table>
You might want to look into using <cfdiv> for the image upload section. Basically you want the form for image uploading be inside the <cfdiv>, so that the form is submitted through ajax. Have the image form action post to a previewImage.cfm that uses <cffileupload>, validate with isImageFile() if it is an image file, then use <cfimage> to resize it and display a thumbnail (may use action="writetobrowser"). The easiest way to associate the uploaded image with the parent form would be storing the file path in Session I guess, if you don't want to code up extra Javascript.

Resources