Javascript OnPageUnload - on "leave page" must call additional method - javascript

This is the problem: my web application (php) has a wizard feature which gathers customer's data page by page, and stores it in session. If customer tries to navigate away from the page before they have completed the wizard, I would like to display a massage to the effect of "You will lose your data". If the customer chooses to navigate away, the session data should be wiped.
I know that I can intercept this action by binding onpageunload event, but is there a way to then make another call, e.g. ajaxClearWizard() if the customer says "yes"?
PS I can see that, perhaps session shouldn't be used here, but I'm using an existing library, and although this wizard-data-persistence used to be a required feature the business now requires it to be removed :(
Any ideas, alternatives?
Thanks in advance!

window.onbeforeunload = function () {
return 'Your content has not been properly saved yet!';
};
This will make the browser display a confirmation box in middle with above content.

Related

Is there a way to send POST data to another form and return the result of that form?

I need to send form data to another page that will allow the user to do something in a form and return the result of that form back to the original page? Is this possible? I know it's not ideal, but the issue is that I need to make a "drop-in" solution that does not need to be integrated with other code. I know it's a very specific request and scenario.
I know how to send POST data that doesn't require any user input on the processing page. i.e. I can send POST data to 'calculate.php' which will do the math and send it back, but if I need additional user input on 'calculate.php', how can I still send it back?
An example of expected results would be:
Page #1: User enters a number and presses submit to go to next page.
Page #2: User enters a second number and presses submit to finish.
Back to Page #1: User receives sum of both numbers.
Obviously, this is a really redundant thing to do, but I'm trying to simplify the problem as much as possible.
EDIT: There a few restrictions I forgot to add.
Page #1 is not my application, I am developing Page #2 as a "drop-in" solution for Page #1. Essentially, I can only use Page #1 to call Page #2 and receive a response from it. The problem is that I need to be able to allow for user input on Page #2.
I know I can post to Page #2 and then post to Page #1 again, but what if I need to maintain the state of Page #1. For example, if there's an open Web Socket connection.
Please note, I understand that this may be impossible or extremely difficult, but if I don't ask I'll never know right?
You want it with PHP or any other language. If you are running Php on server side then you can use Global variables like $_GET and $_POST.
Page #1: Use Post/Get method to send data to second page.
Page #2: Receive all fields' values using Globe variables ($_GET and $_POST). You can use these values as default values of form fields. Now submit this data to page 1 using post or get method.
Back to Page #1: Here you will receive the data of first page from second page and newly posted data from page 2
Either of these should work:
Never leave the page - use AJAX / XMLHttpRequest to call out to other pages to process chunks of data
Do everything on page 1 using "postbacks" -- the form targets are the same page, there is a state variable like "stage=1", and you use JavaScript to add set hidden variables for any additional state that's needed.
... PHP state validation and processing for the different stages ...
... one or more blocks of HTML for the page (PHP if / else can be used to choose between multiple page views) ...
Edit for added restrictions:
Have page 2 use postbacks or AJAX to collect the additional information
I figured out a few ways to do it.
Update a Database (or Data Store of some sort, depends on security needs) and have Page #1 listen for events from a separate page (on the same server as the database). Very similar to the way PayPal's Instant Payment Notification (IPN) works. I was actually able to set up server sent events with it as well.
Essentially, Page #1 sends data to Page #2 where the user will perform the function and then Page #2 will send POST data to a listener somewhere (either on the same server or Page #1's server), the listener will update a database and Page #1 will be listening or pulling to an event handler that will send an update once the database updates.
Use JavaScript Child/Parent Window functions. This is okay if Page #1 and Page #2 are on the same server, but can get messy and browsers have a lot of restrictions and it varies depending on browser.
Page #1 will open Page #2 in a child window, after the user performs a function, Page #2 will call a function that accepts the result data on Page #1.

Need to prompt user for text during NetSuite Workflow

Business logic: when an Approver rejects an expense report, an e-mail must be sent to the creator. This e-mail must contain the reason for rejection.
Existing setup: A multi-state workflow has already been set up, that sends the expense report through two separate approvals. Each Approver can approve or reject the workflow. Rejecting the workflow sends it back to the submission state for correction by the creator. My task is to acquire the rejection text and create the outgoing e-mail.
Obvious solutions rejected:
Send Email workflow action-- this WF action allows only boilerplate e-mails to be sent (with some parameterization). Nothing can be customized from the user's perspective.
Workflow Action Script-- this script context does not allow the use of JavaScript dialog presentations, such as window.confirm() or window.prompt(). There are popup parallels in the workflow action palette, but only for confirm() or alert()-- no prompt(). Unfortunately the technical requirements and restrictions for Workflow Action scripts are horribly documented, so this result was learned only after spending a few days researching and writing the script.
Add a tracking field on the expense report that must be filled in before the report can be Rejected. However, this requires unlocking the record, an issue for Audit concerns. It also must be made visible and hidden for appropriate states, and can be adjacent to only one set of action buttons.
The new state is not an end-state, so e-mail generation is not automatic as it is for end-states. We just want similar functionality.
The only other possiblity I see is to target a new page, such as a Suitelet. However, I only need a single string from the user. A Suitelet seems overkill, plus it makes the workflow more complicated to go back to the correct report.
Any insight or ideas that anyone might have would be most helpful.
Well, I've tried several other solutions and none of these seem to work:
Redirect (via nlapiSetRedirectURL() in a WFA script) on state Exit trigger to a Suitelet that takes the parameters passed from the workflow where the user enters the rejection text; then redirect to the expense report. This fails because the report state does not actually change.
Do the same thing, but from the Entry trigger of the new state. Requires some more detailed parameter handling but this also does not work. Apparently redirecting from any part of the UI experience cancels the workflow transition.
Setting the "User Interface" context on the workflow action also does not work; the redirection still kills the transition.
The nlapiTriggerWorkflow() function also does not seem to have an effect, even when the UI context is set on the action. No errors or debug text generated.
The user may just have to accept manual behaviors like, adding a note and sending a canned e-mail. This appears to be a major feature hole, either deliberate or not. Note that there is a Confirm and a Show Message action, but no Prompt. So why not? No details, just deal with it I guess.
Final solution:
A separate workflow state where a script runs. A new button on the workflow redirects to this new state.
A workflow action script in these special state(s) that has parameter settings that are changed depending on where they are in the workflow. This script redirects to the suitelet (next), which interrupts the workflow transition and keeps the item in the same state.
A suitelet that takes the user text in a textarea, and a non-submit action button. Don't want to use a submit button, because that reloads the same page, creating an extra step.
A client script that takes parameters from the suitelet button event, creates the e-mail, and redirects back to the original record (that is in the same workflow state as before).
Of course this is inelegant. The user must press a button to create the e-mail, and a separate button to transition to the correct state. It fulfills the user's needs, but it requires them to remember to press one button to create the e-mail reason text, and another button to actually reject the record.
The need for this convoluted solution is because of all the roadblocks in NetSuite design:
Can't prompt for text from a server-side WF action script. We can confirm() giving a Y/N (Ok / Cancel) answer, but somehow string returns are not allowed.
Can't complete a transition if a WF action script redirects to another page.
Suitelet submit buttons reload the same page, so we need a client script to do the final e-mail creation work.
Feature hole much?
There is a limitation on the workflow that it cannot accept input from the user. Hence, we need to go ahead with a customized solution for this scenario. I have implemented this in multiple NetSuite projects. Here is the solution which works
(1) Have a workflow action script which would call the suitelet. Please see script sample below for workflow action script
define(['N/record','N/runtime','N/redirect'],
function (record,runtime,redirect){
function callSuitelet(context)
{
try {
var currentRecord = context.newRecord;
var vendorId = currentRecord.id;
var vendorNumber = currentRecord.getValue('entityid');
redirect.toSuitelet({
scriptId: 'customscript_call_rejection_reason',
deploymentId: 'customdeploy_call_rejection_reason',
parameters: {'recid':vendorId,'vbTransactionNo':vendorNumber, trantype: context.newRecord.type}
});
}
catch (err) {
log.error("Error while calling Suitelet", err);
throw err;
}
}
return {
onAction: callSuitelet
};
});
(2) Have a suiteLet designed to capture the "Rejection Reason"
(a) Add a field on the suitelet form labelled as "Rejection Reason" (FieldType.TEXTAREA)
(b) Add a "Submit" button which will add the data to the transaction record
(c) Redirect the suitelet back to the transaction record once "submit" button is clicked
This should solve the problem stated above

With the Javascript event onbeforeunload, is it possible to do anything other than an alert dialog?

In all of the sample code I have seen, it appears that the only function of onbeforeunload is to serve up an alert dialog box prior to the person leaving the page. Is that the only thing that can be triggered by the event or is it possible to do something else, like an unobtrusive function that sends off partial form data?
I am trying to capture abandoned shopping carts in Yahoo! Small Business and unfortunately I do not have access to any server side scripting, so I'm forced to work client-side only.
I was also thinking of doing an ajax posting of data after the email field was changed, and then comparing the list of all forms partially submitted against completed carts to determine which were incomplete.
You can save the partial form data in localStorage. Then, when another page is loaded, you could check for the presence of that data and AJAX it to the server, deleting it from localStorage on success. Or you might be able to just use that data in JavaScript, without involving the server, but that depends on your setup.
<body onbeforeunload="return ('You will lose all your data')" onunload="alert('You have gone away!')">
</body>
Onbeforeunload uses for alert box. Onunload for anything else.
You can technically fire off an ajax event, but there is no guarantee that it will complete before the page is actually reloaded.

Can I Send an Email using ONLY Javascript Without Having to Click The Send Button on the Email Client?

I created a form in HTML and when the submit button is clicked the onclick event calls the following function:
function ProcessSubmition(){
var stringEmailBody=BuildEmailBody();
var stringTo=document.getElementById("SubmittersEmail").value;
var stringSubject = "My Subject Text";
window.location.href = "mailto:"+stringTo+"?subject="+stringSubject+"&body="+stringEmailBody;
}
There are two requirements to my project:
No PHP is allowed on our server.
The person filling out the form must not be able to edit the data which contains a calculate price.
The Problem:
When the function launches, the mail client window appears and displays the message constructed by the function and the user must click the "Send" button in the mail client window.
Unfortunately before the user clicks send, they can simply change the calculated price to a lower dollar amount which obviously is unacceptable.
Is there any way to hide the mail client window and auto-sent? Alternately is there any other method I could use to solve the problem?
Thank you for any help you can give me.
Short answer: No
The JavaScript code that runs in the context of a browser is client-side code that can be manipulated by the end-users. For that reason, you should never rely on client-side code to perform any sensitive operations.
Basically, you will need some server-side support to do what you are tyring to achieve or it will never be secure. Now, if it's dangerous for you that the users can tamper with your code, it would also be dangerous for them if your code could perform tasks such as sending e-mails on their behalf without any form of approval.
Even if you could talk directly to the mail client like you asked and make the email being sent automatically, there's nothing that would prevent users from editing the JavaScript source that generates the message and change the message content.
Alternative? If you will never be able to use any server-side technology, Maybe you could simply send the form details by e-mail and do the pricing calculations in another process afterwards.

What are techniques to get around the IE file download security rules?

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.

Categories

Resources