what i need to do is, when the user clicks a certain div/image, to navigate to a different page. i use struts2 on backend.
so far, i have found 2 approaches, which produce the same effect (navigating to the other page):
create an s:url tag with my action. add the div an onclick attribute, with the url as the parameter. in the javascript function, call window.open(url)
create a form with the action. with jquery, call document.forms[].submit();
what i want to know is what is the difference between these two approaches. i am mostly interested in differences in terms of what happens inside struts, or in terms of dialog between browser and server, or what happens to the session
one difference (which i am not interested in) is that window.open also accepts parameters to open in a new window, and resize that window. i want to open the new action in the same window
a second difference (which is indeed more interesting) is that forms allow to use either POST or GET protocol. as for window.open, i am not sure which protocol is used
window.open opens a new window
window.location changes the location of the current page
forms[n].submit() submits the nth form to the server.
The window functions issue a GET request where you can add URL parameters if you need to send info to the server. There is a limitation to the number of characters you can send in a URL and it's usually not a good idea to send passwords in a GET request.
When you POST a form the parameters are in the message and not in the URL, thus they do not show up in the browser history nor are they affected by the url length limitation.
If your not sending data to the server for processing and you need to just navigate on an image click you should wrap it in an anchor tag
<img src=""/>
Related
I have a form that has a number of dependent parameters fields. That is, changing one parameters field value may cause a server request to repopulate the other parameter fields. After the user sets all of the fields they will press a button and launch in a popup window a new form running the report they specified.
To get the URL for this window I need to make one final call to the server which will return the formatted URL (using GET). So the resultant flow on button click is:
Gather values from fields
Call web service to construct URL. (I will use a promise)
Launch open.window with new URL
The first 2 steps are straight-forward, but I am unsure on how to handle the window.open from the controller. Any thoughts or ideas?
P.S.
I thought about using a directive to overwrite the link URL as values changes, but having to go back to server to construct the URL after each parameter changed seems like way too much processing.
Sorry for wasting people's time. The answer is $window.open() from the controller.
I am making a simple web app that opens a url on entering a query. I am using the bottle framework in Python. The problem I am facing is as follows:
I have two URL handlers, one for / and other for /process. When the user enters a query through a form on /, the form action goes to /process which then processes the query and opens a particular url using window.open(url, "_self"). Now when the user hits the back button in the browser, /process is called again with the same query, which then again loads the same url. Instead of this, I want it to go / when the back button is pressed. How can I do this? Thanks.
EDIT : I did not notice this before but the above undesired behavior is found in Firefox but not in Chrome.
You can use the window.history object to manipulate and replace the history or, instead of using window.open(url, "_self"), replace the location
example:
window.location.replace(url);
Check some documentation and this answer
In Javascript, how do I "clear" the back (history -1)?
Another solution could be to intercept when the user is going to go back. Check this answer to have some examples:
Intercepting call to the back button in my AJAX application: I don't want it to do anything!
Don't redirect using window.open, or any kind of client-side JavaScript.
Have the HTTP response to the request for /process be a 302 Found HTTP status with a Location header.
See also The Post/Redirect/Get Pattern.
I've a link on my webpage, say 'about'. Clicking on it loads a particular div without refreshing the whole page using jquery .load(). This does not change the URL string in the browser address bar.
The same page can be accessed by going to www.mydomain.com/?page=about.
So what I want to do is, when the user clicks on the 'about' link, the pages will be loaded as it is (using jquery), but I want to change the URL string in the browser address bar also so that someone can actually copy or bookmark the exact page.
Is it possible to do so??
You have two possibilites to tackle this problem:
In newer browsers you can make use of the HTML5 history API, which lets change part of the URL, also the query string (and path afaik).
In browsers which don't support this, you can only change the fragment identifier # without reloading the page (via the location object). That means you have to change the URL to e.g.
www.mydomain.com/#!page=about
#! is a convention from Google to make Ajax sites crawlable. As the fragment identifier is not sent to the server, you have to detect it with JavaScript and load the corresponding data from the server.
There are jQuery plugins that help you to handler this.
I would look for a good plugin makes use of the history API if available and falls back to the hash based solution.
As written in my comment, you can also find more information here:
How to change browser address bar without reloading page, especially #ThiefMaster's answer.
Yes, I've done it by doing
location.hash = 'foo';
There's other attributes of location you can change, not sure what it's called for '?', probably query-string, get, or soemthing like that.
Internet Explorer (with default settings, which I generally assume will be in effect on the desktops of the Great Unwashed) seems to dislike the idea of accepting attachment content in an HTTP response if the corresponding request wasn't made directly from a user action (like a "click" handler, or a native form submit). There are probably more details and nuances, but that's the basic behavior that's frustrating me.
It seems to me that this situation is common: the user interface in front of some downloadable content — say, a prepared PDF report — allows for some options and inputs to be used in the creation of the content. Now, as with all forms that allow the user to stipulate how an application does something, it's possible that the input will be erroneous. Not always, but sometimes.
Thus there's a dilemma. If the client tries to do something fancy, like run an AJAX transaction to let the server vet the form contents, and then resubmit to get the download, IE won't like that. It won't like it because the actual HTTP transaction that carries the attachment back will happen not in the original user-action event handler, but in the AJAX completion callback. Worse, since the IE security bar seems to think that the solution to all one's problems is to simply reload the outer page from its original URL, its invitation to the user to go ahead and download the suspicious content won't even work.
The other option is to just have the form fire away. The server checks the parameters, and if there's anything wrong it responds with the form-container page, peppered appropriately with error messages. If the form contents are OK, it generates the content and ships it back in the HTTP response as an attached file. In this case (I think), IE is happy because the content was apparently directly requested by the user (which is, by the way, a ridiculously flimsy way to tell good content from bad content). This is great, but the problem now is that the client environment (that is, the code on my page) can't tell that the download worked, so the form is still just sitting there. If my form is in some sort of dialog, then I really need to close that up when the operation is complete — really, that's one of the motivations for doing it the AJAX way.
It seems to me that the only thing to do is equip the form dialogs with messaging that says something like, "Close this when your download begins." That really seems lame to me because it's an example of a "please push this button for me" interface: ideally, my own code should be able to push the buutton when it's appropriate. A key thing that I don't know is whether there's any way for client code to detect that form submission has resulted in an attachment download. I've never heard of a way to detect that, but that'd break the impasse for me.
I take it you're submitting the form with a different target window; hence the form staying in place.
There are several options.
Keep the submit button disabled and do ongoing validation in the background, polling the form for changes to fields and then firing off the validation request for a field as it changes. When the form is in a valid state, enable the button; when it isn't, disable the button. This isn't perfect, as there will tend to be a delay, but it may be good enough for whatever you're doing.
Do basic validation that doesn't require round-trips to the server in a handler for the form's submit event, then submit the form and remove it (or possibly just hide it). If the further validation on the server detects a problem, it can return a page that uses JavaScript to tell the original window to re-display the form.
Use a session cookie and a unique form ID (the current time from new Date().getTime() would do); when the form is submitted, disable its submit button but keep it visible until the response comes back. Make the response set a session cookie with that ID indicating success/failure. Have the window containing the form poll for the cookie every second or so and act on the result when it sees it. (I've never done this last one; not immediately seeing why it wouldn't work.)
I expect there are about a dozen other ways to skin this cat, but those are three that came to mind.
(Edit) If you're not submitting to a different target, you might want to go ahead and do that -- to a hidden iframe on the same page. That (possibly combined with the above or other answers) might help you get the user experience you're looking for.
There's a whole number of really good reasons IE does this, and I'm sure it's not something anyone would argue with - so the main objective is to get around it somehow to make things better for your users.
Sometimes its worth re-thinking how things are done. Perhaps disable the button, use javascript to check when all the fields are filled out, and fire off an ajax request once they are. If the ajax was successful, enable the button. This is but one suggestion, I'm sure there will be more...
Edit: more...
Do simple submission (non-AJAX), and if the checks fail, send a page back rather than an attachment. The page sent back could contain all the information originally submitted (plus whatever error message to the user) so the user doesn't need to fill out the entire form again. And I'm also sure there will be more ideas...
Edit: more...
I'm sure you've seen this type of thing before - and yes, it is an extra click (not ideal, but not hard).... an "if your download fails, click here" -> in this case, do it as you want to do it, but add a new link/button to the page when the AJAX returns, so if the download failed, they can submit the already validated form from a "direct user action". And I'm sure I'll think of more (or someone else will).....
I have been fighting a similar issue for a while. In my case, posting to a hidden iframe didn't work if my web app was embedded in an iframe on another site (third party cookie issues) unless our site was added to the Trusted Sites list.
I have found that I could break up the download into POST and GET sequence. The post returns a short lived GUID that can be used in a GET request to initiate the download. The POST can do the form validation as well as return the GUID in a successful response. Once the client has the GUID, you can set the src property of a hidden iframe element to the download URL. The browser sees the 'Content-Disposition': 'attachement' header and gives the user a download ribbon to download the file.
So far it appears to work in all the latest browsers. Unfortunately it requires you to modify you server side API for downloading the file.
So I have two documents dA and dB hosted on two different servers sA and sB respectively.
Document dA has some JS which opens up an iframe src'ing document dB, with a form on it. when the form in document dB is submitted to a form-handler on server sB, I want the iframe on page dA to close.
I hope that was clear enough. Is there a way to do this?
Thanks!
-Mala
UPDATE: I have no control over dA or sA except via inserted javascript
This isn't supposed to be possible due to browser/JavaScript security sandbox policy. That being said, it is possible to step outside of those limitations with a bit of hackery. There are a variety of methods, some involving Flash.
I would recommend against doing this if possible, but if you must, I'd recommend the DNS approach referred to here:
http://www.alexpooley.com/2007/08/07/how-to-cross-domain-javascript/
Key Excerpt:
Say domain D wants to
connect to domain E. In a nutshell,
the trick is to use DNS to point a
sub-domain of D, D_s, to E’s server.
In doing so, D_s takes on the
characteristics of E, while also being
accessible to D.
Assume that I create page A, that lies withing a frame that covers the entire page.
Let A link to yourbank.com, and you click on that link. Now if I could use javascript that modifies the content of the frame (banking site), I would be able to quite easily read the password you are using and store it in a cookie, send it to my server, etc.
That is the reason you cannot modify the content in another frame, whose content is NOT from the same domain. However, if they ARE from the same domain, you should be able to modify it as you see fit (both pages must be on your server).
You should be able to access the iframe with this code:
window["iframe_name"].document.body
If you just want the top-level to close, you can just call something like this:
window.top.location = "http://www.example.com/dC.html";
This will close out dA and sent the user to dC.html instead. dC.html can have the JS you want to run (for example, to close the window) in the onload handler.
Other people explained security implications. But the question is legitimate, there are use cases for that, and it is possible in some scenarios to do what you want.
W3C defines a property on document called domain, which is used to check security permissions. This property can be manipulated cooperatively by both documents, so they can access each other in some cases.
The governing document is DOM Level 1 Spec. Look at the description of document. As you can see this property is defined there and … it is read-only. In reality all browsers allow to modify it:
Mozilla's document.domain description.
Microsoft's domain property description.
Modifications cannot be arbitrary. Usually only super-domains are allowed. It means that you can make two documents served by different server to access each other, as long as they have a common super-domain.
So if you want two pages to communicate, you need to add a small one-liner, which should be run on page load. Something like that should do the trick:
document.domain = "yourdomain.com";
Now you can serve them from different subdomains without losing their accessibility.
Obviously you should watch for timing issues. They can be avoided if you establish a notification protocol of some sort. For example, one page (the master) sets its domain, and loads another page (the server). When the server is operational, it changes its domain and accesses the master triggering some function.
A mechanism to do so would be capable of a cross-site scripting attack (since you could do more than just remove a benign bit of page content).
A safe approach would limit to just the iframe document emptying/hiding itself, but if the iframe containing it is fixed size, you will just end up with a blank spot on the page.
If you don't have control over dA or Sa this isn't possible because of browser security restrictions. Even the Flash methods require access to both servers.
This is a bit convoluted but may be more legitimate than a straight XSS solution:
You have no control over server A other than writing javascript to document A. But you are opening an iframe within document A, which suggests that you only have write-access to document A. This a bit confusing. Are you writing the js to document A or injecting it somehow?
Either way, here is what I dreamed up. It won't work if you have no access to the server which hosts the page which has the iframe.
The user hits submit on the form within the iframe. The form, once completed, most likely changes something on the server hosting that form. So you have an AJAX function on Document A which asks a server-side script to check if the form has been submitted yet. If it has, the script returns a "submitted" value to the AJAX function, which triggers another js function to close the iframe.
The above requires a few things:
The iframe needs to be on a page hosted on a server where you can write an additional server-side script (this avoids the cross-domain issue, since the AJAX is pointing to the same directory, in theory).
The server within the iframe must have some url that can be requested which will return some kind of confirmation that the form has been submitted.
The "check-for-submitted" script needs to know both the above-mentioned URL and what to look for upon loading said URL.
If you have all of the above, the ajax function calls the server-script, the server-script uses cURL to go the URL that reflects if the form is done, the server-script looks for the "form has been submitted" indicators, and, depending on what it finds, returns an answer of "not submitted" or "submitted" to the ajax function.
For example, maybe the form is for user registration. If your outer document knows what username will be entered into the form, the server-side script can go to http://example.org/username and if it comes up with "user not found" you know the form has yet to be submitted.
Anything that goes beyond what is possible in the above example is probably outside of what is safe and secure anyway. While it would be very convenient to have the iframe close automatically when the user has submitted it, consider the possibility that I have sent you an email saying your bank account needs looking at. The email has a link to a page I have made which has an iframe of your bank's site set to fill the entire viewable part of my page. You log in as normal, because you are very trusting. If I had access to the fact that you hit submit on the page, that would imply I also had access to what you submitted or at the very least the URL that the iframe redirected to (which could have a session ID in or all sorts of other data the bank shouldn't include in a URL).
I don't mean to sound preachy at all. You should just consider that in order to know about one event, you often are given access to other data that you ought not have.
I think a slightly less elegant solution to your problem would be to have a link above the iframe that says "Finished" or "Close" that kills the iframe when the user is done with the form. This would not only close the iframe when the user has submitted the form, but also give them a chance to to say "oops! I don't want to fill out this form anyway. Nevermind!" Right now with your desired automatic solution, there is no way to get rid of the iframe unless the user hits submit.
Thank you everybody for your answers. I found a solution that works:
On my server, I tell the form to redirect to the url that created the iframe.
On the site containing the iframe, I add a setInterval function to poll for the current location of the iframe.
Due to JS sandboxing, this poll does not work while the url is foreign (i.e. before my form is submitted). However, once the url is local (i.e. identical to that of the calling page), the url is readable, and the function closes the iframe. This works as soon as the iframe is redirected, I don't even need to wait for the additional pageload.
Thank you very much Greg for helping me :)