Chrome Submit form and navigate window in Rails? - javascript

So I have an app that submits a form to an external cart using Javascript (target is blank) then I want the window to navigate to a Rails controller to create a small tracker model, controller as such:
def add_to_cart
#product = Product.find(params[:id])
#product.cart_trackers.create
redirect_to :back
end
And the Javascript (in a link_to, onclick helper):
document.forms['addCart#{product.id}'].submit();
window.location.href=\"/products/add_to_cart/#{product.id}\";
return false;
And this works wonderfully in Firefox and Internet Explorer, but Google Chrome throws a fit about so much navigation. I realize AJAX could be a worthy solution, but due to the environment this app runs under (which is a clustercrap of Prototype, Jquery, iFrames, and includes) I'd like to avoid it if possible. Chrome's response is to actually run the window.location... code and skip the form submitting. Without one or the other lines of code, Chrome will perform the single action just fine.
So, what would be the proper way of writing this out? Or should I give in and just wrangle in some AJAX?

Try using AJAX-but-not-really-AJAX. Submit the form using whatever AJAX submitter you want (e.g., $.ajax), but don't do anything with the response (i.e., no callback). That way the data gets POSTed and maybe the browser won't be upset that you're asking it to visit two urls back-to-back.

Related

IsPostBack sometimes doesn't work in asp.net webforms [duplicate]

The best explanation I've found for a postBack is from Wiki.
a postback is an HTTP POST to the same page that the form is on.
While the article does explain how a second page was needed in ASP, but no longer needed in ASP.NET, it doesn't give much detail or background. I am looking for a freakin' tome of information on PostBacks. Much like the simple question of "how can I clean a house" can be addressed by this 900 page book. I don't need 900 pages worth, but details please. I found a nice little tutorial for ASP.NET life cycle, but it seriously glosses over postbacks (amongst other things).
I am looking to the developers who have been around before .NET and really don't take these kinds of things for granted. Books and hyperlinks are reasonable answers or additions to your answer.
So far I've seen the right answer alluded to repeatedly, and almost everyone has come shy of what I consider subjectively to be the mark.
Let's start with the basics:
An HTTP request can be any of the HTTP verbs, but the two that people use most are GET and POST. Well, those are the two a programmer uses most frequently. The others all have some purpose, if they're implemented on the server. When you send information to the server, you can do so either through the use of the URL (to request a page) or within the body of the request (POST, PUT, DELETE, for instance).
Now you'll remark (I'm sure) that the URL in a GET request often contains data, and this is true, but according to W3C, you should not use GET to alter state, and yet we do often. It's sort of a hack that we all agree is an actual use, and not a hack. Whether that makes it a hack or an actual implementation detail I leave up to you.
So when you send the body of the POST (skipping the others for now, you can figure it out from here) with the form elements, you're sending back certain elements. How those elements are defined is up to you and to the environment you're working in. You could post to a server with a JSON element in the body, or with XML, or with form fields. Generally we do posts from a FORM element in the body of the HTML.
Now everyone says, "oh, a postback is a subsequent request to a page." But, that's not true. A postback is when you send data via POST -> back to the server. I say this because the difference between a GET request and a POST request is if data is included in the body (and the verb used, but the client usually knows how to deal with that). You could postback to the page on the first time the page is visited, and in fact ASP.NET has tools for doing that in the library. You could certainly have a desktop client POST data to a server (think Twitter) without showing any webpage at all from the server (ok, so twitter is probably not the best concept to use for an example here, but I want to illustrate that you can use a client that doesn't show the webpage, so no request is necessary).
So really what you should read there in "postback" is "I'm POSTing data BACK to the server for processing". It's presumed that you retrieved the page initially with a GET to show the user the <form> element that has <input> fields for them to interact with, and that at the end you're sending data back. But I hope you can see that it doesn't have to be in that order.
So here's something else to consider:
What if you gave the user a page with a bunch of <input>s and no <form> but instead, had a button wired up in javascript to concat all those <input>s with &value-n= and send them as a GET? Does the same thing, but violates that concept of only using GET for requests. (possibly) ensuing discussion encourages me to reinforce that GET should have no side effects (no updating values)
It's how come you can send someone a link to a google search, for instance. So we don't ALWAYS have to POST BACK to the server to get data.
Hope this helps.
Cheers
See ASP.NET Page Life Cycle Overview on MSDN for a good general introduction about what happens when a requests hits the server.
A PostBack is any request for a page that is not the first request. A PostBack will always be in response to a user action (triggered most commonly by a Button, AutoPostBack control or Ajax).
POSTBACK: Part of ASP.NET's contrived technique for hiding the true stateless nature of the web/HTTP behind a stateful facade. This results in complex code (IsPostback, ...), a hard to understand page lifecycle, many different events, ... and numerous problems (ViewState size, web-farm stickyness, state servers, browser warnings (not using PRG pattern), ...)
See ASP.NET MVC instead.
A post back is round trip from the client (Browser) to the server and then back to the client.
This enables you page to go through the asp engine on the server and any dynamic content to be updated.
here is a nice explanation
ASP.Net uses a new concept (well, new compared to asp... it's antiquated now) of ViewState to maintain the state of your asp.net controls. What does this mean? In a nutshell, if you type something into a textbox or select a dropdown from a dropdownlist, it will remember the values when you click on a button. Old asp would force you to write code to remember these values.
This is useful when if a user encounters an error. Instead of the programmer having to deal with remembering to re-populate each web control, the asp.net viewstate does this for you automatically. It's also useful because now the code behind can access the values of these controls on your asp.net web form with intellisense.
As for posting to the same page, yes, a "submit" button will post to an event handler on the code behind of the page. It's up to the event handler in the code behind to redirect to a different page if needs be (or serve up an error message to your page or whatever else you might need to do).
The Wikipedia definition of postback is pretty good, but I'd add the following:
A postback is a subsequent HTTP POST to the same page that the form is on.
If I have a page with a form on it and, rather than having my Submit button redirect the browser to another page that will process the form, instead have the Submit button refresh the current page (and perform some specific steps to validate/save the page, presumably), then that Submit button is said to have posted back to the current page.
Postbacks can be either full (refresh the entire page) or partial (in a case where AJAX is employed). A partial page postback will re-render only a part of the page (like a single drop-down list, a table, etc.).
In the old HTML, the only way to make something updated on the webpage is to resend a new webpage to the client browser. That's what ASP used to do, you have to do this thing call a "PostBack" to send an updated page to the client.
In ASP .NET, you don't have to resend the entire webpage. You can now use AJAX, or other ASP.NET controls such that you don't have to resend the entire webpage.
If you visit some old website, you would notice that once you click something, the entire page has to be refresh, this is the old ASP. In most of the modern website, you will notice your browser doesn't have to refresh the entire page, it only updates the part of the content that needs to be updated. For example, in Stackoverflow, you see the page update only the content, not the entire webpage.
Simply put this by a little code. Hope it is helpful to you.
When you firstly request the page url. you can view the source code of it in most browser. Below is a sample of it .
The essential of Post Back is actually call the __doPostBack which submit all the form data got from your firstly requested back to the server. (__EVENTTARGET contains the id of the control.)
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
NHibernate Demo
</title>
<script language="javascript" type="text/javascript">
function dopost() {
__doPostBack('LinkButton1', '');
}
</script>
</head>
<body>
<h1>NHibernate Demo</h1>
<form name="ctl01" method="post" action="Default.aspx" id="ctl01">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTMxNzcwNTYyMWRkKHoXAC3dty39nROvcj1ZHqZ5FYY=" />
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['ctl01'];
if (!theForm) {
theForm = document.ctl01;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
<div>
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="B2D7F301" />
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAwKZx5vTCgKM54rGBgLM9PumD20dn9KQguomfpAOdTG0r9Psa7al" />
</div>
<a id="LinkButton1" href="javascript:__doPostBack('LinkButton1','')">LinkButton</a>
<input type="button" value="testPostBack" id="testpostback" onclick="dopost();" />
</form>
</body>
</html>
Postback is a request during which ASP restores values of controls' properties from view state.

Form values getting lost in IE8 but Firefox, IE9 works

I ran into a scenario where I was thrown an unexpected behavior only in IE8 browser. IE9 and Firefox browsers work fine. The behavior went like:
User populated a form
On purpose - user leaves a mandatory field blanked
User clicked "Submit button" and browser sent a POST request
Expected behavior - error message is thrown along with data that was already provided. Only mandatory field should be left blanked as we did not provide anything in step 2. But instead I'm getting an error message with previous data lost i.e. form empty.
And note this only happens in IE8. Any suggestions?
I am going to answer this questions myself. So, here's what happened in my scenario. It was a double click problem. But I only clicked the button once. Then how did that happen? Some programmer who worked on this project was handling a form submit where he did another submit using JavaScript. But then how did this work in Firefox or IE9+?
I used Fiddler to go deep into this - I noticed in IE8 browser two requests are sent to the server. But IE9 and Firefox correctly handles this scenario (i.e. learns about double click) and sends only 1 POST request instead of 2.
Technologies used: Spring Framework 2.0, JSP, HTML, JavaScript
Why data is lost has also to do with Server - Spring modifies the session attributes (to be specific it's a formObject which is temporarily removed and re-added) while processing requests. When there's another request at the same time it goes through another pipeline (handleInvalidSubmit) which ends up creating a new formObject and thus destroying old data.
Hope this will help others :)

Submit Old Google Form then redirect to another page

I am utilizing a Google Form on a webpage. I copied the source code from the form directly onto my page so that I can modify some of the HTML instead of using an iframe. Then instead of taking the user to the google docs response page I would like to redirect them to another page.
The trouble that I am running into is with the page redirect. I was able to get this working properly in Chrome and Firefox with this:
<form target="GoogleResponse" action="https://docs.google.com/spreadsheet/
formResponse?formkey=xxxxxxxxxxxxxxxxxxxxxxxxxx&ifq;" onsubmit="
window.location = 'targetPage.html';" method="POST" id="ss-form">
IE and Safari both did the redirect automatically and the response never got written to the Google Form. If I drop the redirect, the action works perfectly in both and the response is recorded in the Google spreadsheet.
So I attempted to pull the action out and instead did it everything in onsubmit instead, like so:
<form target="GoogleResponse" onsubmit="this.action = https://docs.google.com
/spreadsheet/formResponse?formkey=xxxxxxxxxxxxxxxxxxxxxxxxxx&ifq';
window.location = 'targetPage.html';" method="POST" id="ss-form">
Same problem as before, IE and Safari both redirect, and nothing is written to the Google spreadsheet. And once again, if I remove the redirect the response gets recorded in all browsers. I can also do other stuff like throw in an alert after the action, and everything continues to work fine. The only time I see the issue is with the redirect.
So at this point the only thing I can figure is that their is some sort of conflict between the redirect and the action. I have pretty limited working knowledge of javascript and forms so any help or recommendations would be greatly appreciated!
Sounds like the browsers have not complete the form submission before handling the redirect. onsubmit happens before the submission itself so you can not handle the issue there.
Use the onload function of the target iframe for the redirect.
This has been asked in similar manner:
Old Google Form redirect after submission
Take a good look at the answer. The onload function of the iframe will handle the redirect, so the redirect will not happen until the submission is complete and a response has been given from google. So when the hidden response from google is loaded we fire a redirect. This is async functionality between the client and server. We are waiting for the server to handle the data before redirecting.
Extended note: You could try putting the redirect within a setTimeout function. This would delay the execution of the redirect, allowing the server to handle the submission first. But setTimeout requires a fixed amount of time, so if the data handling is not synchronous (ie. asynchronous) setTimeout will not work as it may fire to early or too late. Asynchronous data handling applies when the data processing requires an undetermined amount of time (such as http requests).

MVC3, switching between Views in the same page

I am working on a MVC project that is supposed to have one page only, with two zones. On one zone I have a Google Map with markers, and the second zone is populated with the selected marker's details.
The details view has a button that when clicked should change the entire view into edit mode without refreshing the page or redirecting it. I have used two views, for details and edit and with the help of ajaxForm function I am switching back and forth between these two views. I'm adding the ajaxForm on documentready for edit view.
<script type="text/javascript">
// wait for the DOM to be loaded
$(document).ready(function() {
// bind 'myForm' and provide a simple callback function
$('#currentDiv').ajaxForm(function(data) {
$('#currentDiv').html(data);
});
});
</script>
The problem appears when on server-side an error appears while trying to save data from edit view and I want to return to the same edit view with the errors displayed. The ajaxForm handler is not added any more and even if the new values that will try to be saved are ok, the detail view is loaded in another page.
Unfortunately, the use of ajaxForm creates some other problems because I don't have control over the cases when the ajax call fails.
Any ideas on how could I fix this? Is it some other solution to switch between those two views without using ajaxForm and without refreshing the page?
I think there are a couple of different questions that you are asking.
First off, you add jquery handlers to deal with the case when you get a 500 type error from the server.
Something like the following. I suggest taking a look at the docs for more info.
$(document).ajaxError(function(event,jqXHR,ajaxSettings,thrownError){
if (jqXHR.status != 0){
window.location = <error page>
}
}
The second problem seems to stem around error handling of known errors (say invalid input). In this case I suggest the following workflow.
1) User clicks on edit button, taken to edit screen
2) User enters in data, use client side validation to do initial check
3) User submits, user is then taken to the view screen and is shown a
success or error message.
The server response could look like:
public ActionResult Edit(EditModel model){
if (!ModelState.IsValid)
{
return Json(new {successful = false, message = "Failed.."});
}
...
}
On the client side, your form callback should now handle the message and the fact it was successful or not. In my implementation, I used knockoutjs to create a "message" area that I could update and clear. (I created templates, etc).
Remember to use client side validation for the easy field validation stuff.... This will save a trip back to the server.
Yours could be quite simple, by popping up the message returned from the server.
Lastly, document ready only fires when the original document is done loading, never again for an ajax call (at least that is my understanding). Just put that code that is the document.ready at the bottom of the edit page. It will fire after the html it is targeting has already been rendered.
Hope that helps!
I have begun to move away from the asp.net views available in ASP.Net MVC due to some incompatibilities and/or unnecessary complexities when trying to achieve functionalities expected of AJAX enabled sites of the day.
I would recommend moving towards a design where you use "dumb" HTML files, use jQuery to download them using AJAX and drop them into a container (personally I use a div) and then use another AJAX call to gather the data from a controller. There are a number of advantages to this approach:
It establishes a real (not fake) separation between client side and server side code.
Html files can be cached on the client cutting down on the amount of data transmitted.
Binding of the Html elements becomes a client side task achieved using jQuery offloading processing cycles from the server.
Controllers essentially become collections of web methods which means they can be untilized by iPhone and Android apps making mobile deployment easier.
I realize this probably isn't the exact answer you're looking for and this may not be an option for you but my hope is that it will help someone at some point make a decision to move away from mixing HTML and server side code.

Rails: Is this the proper way to return an AJAX dialog loaded from the server?

My target result is when a user clicks a link, to have that pop up an overlay that contains a new page loaded from the server with AJAX.
The way I'm doing this is using Prototype Overlay (I'm using Prototype for AJAX) to create the dialog, and after the dialog is created, I'm calling:
new Ajax.Updater("div_inside_the_dialog",
"url_for_the_content",
{method: 'get', requestHeaders:{Accept:'text/javascript'}});
I also added into my url_for_the_content controller:
respond_to do |format|
format.js
format.html
end
So when the link is clicked, it creates a dialog, my controller for url_for_the_content, which sees that I'm making a JavaScript request, and returns some stuff to display inside the dialog.
It works okay, but it strikes me as very odd that I had to manually code that I'm looking for a JavaScript return in the request header, and then what I return isn't actually JavaScript, it's just a bunch of html for the dialog.
On the other hand, I don't want to create a special controller method just for this, because it's not really its own action conceptually since it's displaying the same thing as an existing action, just formatted differently. Also, I'd have to disable layouts for it, and I would never want users to be able to visit it directly, not inside an AJAX dialog.
Can anyone provide any feedback on how I'm approaching this whole process, on any part of what I'm doing?
I am not too familiar with the way you are calling the Ajax updated but I prefer simply rendering forms via Ajax, which should also make it clearly why you would manually be coding in a request for a Javascript return in your request header. The way I usually do it is save a js.erb file in the views folder corresponding to your controller name. So in Views/(Controller_Name)/ I have a file called (Action_Name).js.erb which would look something as follows:
$("div_to_update").update("<%= escape_javascript(render('updateform')) %>")
Simply doing that will allow you to call any form that you want with AJAX. Similarly something like this allows you to simply update whatever content you need to in whichever way necessary. Hope this helps

Categories