I have written an event handler on change of stage in BPF in Opportunity Entity:
var checkForAccountApproved = function (executionContext) {
var formContext = executionContext.getFormContext();
formContext.data.process.addOnStageChange(function (stageContext) {
var stageName = stageContext.getEventArgs().getStage().getName().toString();
if (some conditions) {
formContext.data.process.movePrevious();
}
else {
currentActiveStage.setValue(stageName);
formContext.data.entity.save();
}
});
};
Basically, on clicking next, I need to check if some conditions are not satisfied, then only, the next stage should be active, else, the current stage should be active.
If the conditions are not satisfied, i.e. the stage change happens, I will store the value of the current active stage in a field. If I am explicitly calling save, the event handler is again triggered.
Why is it so?
Probably a late answer but ...
don't use formContext.data.process.movePrevious() to cancel your stage change, as this will try to move the stage back and re-execute your pre-stage change ( this will probably keep looping till you get back to the first stage).. Instead use the below which cancels the stage change and stays at the current stage
executionContext.getEventArgs().preventDefault();
I'm trying to use the $(window).on('beforeunload', function(){}); and editor.session.getUndoManager().isClean(); in the ace editor to check if the user made changes to a document but didn't click the submit button but for some reason it doesn't work Here's the code:
editor.on('change', function(Isclean ) {
var Isclean = editor.session.getUndoManager().isClean();
});
var submitting = false;
$(window).on('beforeunload', function(){
if (submitting == false && Isclean == false) {
return "You have made some changes in the editor.";
};
});
But for whatever reason Isclean always returns a boolean of true.
There are a couple of problems with the code. In your 'change' event handler, the function argument and the local variable are both called Isclean.
Secondly, the Isclean variable is not visible to your 'beforeunload' event handler.
In order to accomplish this task I did:
$(window).bind("load", function() {
editor.session.getUndoManager().markClean();
});
I was pre-loading some Json into the editor so unless i called editor.session.getUndoManager().markClean(); as the last thing to load (and it HAS to be the last thing to load), it would always boolean to false.
I tried using a hack described in various locations which uses:
document.body.onfocus = checkOnCancel();
An example:
var fileSelectEle = document.getElementById('fileinput');
fileSelectEle.onclick = charge;
function charge()
{
document.body.onfocus = checkOnCancel;
}
function checkOnCancel()
{
alert("FileName:" + fileSelectEle.value + "; Length: " + fileSelectEle.value.length);
if(fileSelectEle.value.length == 0) alert('You clicked cancel!')
else alert('You selected a file!');
document.body.onfocus = null;
}
Is there something wrong here? Because fileSelectedEle.value always returns the previous execution value and NOT the one selected by the user.
Is this the expected behavior of input file? How to resolve this to read the actual file selected?
http://jsfiddle.net/smV9c/2/
You can reproduce the error by:
Step 1: SelectFile - some select some file (and notice the output)
Step 2: SelectFile - press cancel (and notice the output)
One solution is to use the onchange event of the input.
var fileSelectEle = document.getElementById('fileinput');
fileSelectEle.onchange = function ()
{
if(fileSelectEle.value.length == 0) {
alert('You clicked cancel - ' + "FileName:" + fileSelectEle.value + "; Length: " + fileSelectEle.value.length);
} else {
alert('You selected a file - ' + "FileName:" + fileSelectEle.value + "; Length: " + fileSelectEle.value.length);
}
}
This responds correctly to changes in the selected filename, as you can test here: http://jsfiddle.net/munderwood/6h2r7/1/
The only potential difference in behaviour from the way you were trying to do it, is that if you cancel right away, or twice in a row, or select the same file twice in a row, then the event won't fire. However, every time the filename actually changes, you'll detect it correctly.
I don't know for sure why your original attempt didn't work, although my best guess is that it's a timing issue with the onfocus event firing asynchronously, and before the input control's properties have finished updating.
UPDATE: To determine what the user has selected every time they close the file dialog, even if nothing has changed, the timing issue can be skirted by adding a brief delay between receiving focus again, and checking the value of the file input. Instead of calling checkOnCancel immediately upon receiving focus, the following version of charge causes it to be called a tenth of a second later.
function charge() {
document.body.onfocus = function () { setTimeout(checkOnCancel, 100); };
}
Here's a working version: http://jsfiddle.net/munderwood/6h2r7/2/.
You can hook into the window.focus event which gets fired when they cancel window's file select box. Then check to see if it actually has a file selected.
//This code works in chrome for file selection try it
<--write this line in HTML code-->
<input type='file' id='theFile' onclick="initialize()" />
var theFile = document.getElementById('theFile');
function initialize() {
document.body.onfocus = checkIt;
console.log('initializing');
}
function checkIt() {
setTimeout(function() {
theFile = document.getElementById('theFile');
if (theFile.value.length) {
alert('Files Loaded');
} else {
alert('Cancel clicked');
}
document.body.onfocus = null;
console.log('checked');
}, 500);
}
It gets tricky to handle all of the various ways that a user can cancel file input.
On most browsers, the file picker immediately opens and takes the user out of the browser. We can use the window.focus event to detect when they come back without selecting anything to detect cancellation
On ios browsers, the user first sees an ios modal that lets them pick between camera -vs- gallery. User's can cancel from here by clicking away from the modal. So, we can use the window.touchend to detect this
there are likely other browsers and cases that act differently on cancellation, that this hasn't caught yet, too
Implementation wise, you can use addEventListener to make sure that you dont replace other event listeners that may already be on the window - and to easily clean up the event listener after it fires. For example:
window.addEventListener('focus', () => console.log('no file selected'), { once: true });
Here is an example of how you can use this to get images programatically, handling the considerations listed above (typescript):
/**
* opens the user OS's native file picker, returning the selected images. gracefully handles cancellation
*/
export const getImageFilesFromUser = async ({ multiple = true }: { multiple?: boolean } = {}) =>
new Promise<File[]>((resolve) => {
// define the input element that we'll use to trigger the input ui
const fileInput = document.createElement('input');
fileInput.setAttribute('style', 'visibility: hidden'); // make the input invisible
let inputIsAttached = false;
const addInputToDom = () => {
document.body.appendChild(fileInput); // required for IOS to actually fire the onchange event; https://stackoverflow.com/questions/47664777/javascript-file-input-onchange-not-working-ios-safari-only
inputIsAttached = true;
};
const removeInputFromDom = () => {
if (inputIsAttached) document.body.removeChild(fileInput);
inputIsAttached = false;
};
// define what type of files we want the user to pick
fileInput.type = 'file';
fileInput.multiple = multiple;
fileInput.accept = 'image/*';
// add our event listeners to handle selection and canceling
const onCancelListener = async () => {
await sleep(50); // wait a beat, so that if onchange is firing simultaneously, it takes precedent
resolve([]);
removeInputFromDom();
};
fileInput.onchange = (event: any) => {
window.removeEventListener('focus', onCancelListener); // remove the event listener since we dont need it anymore, to cleanup resources
window.removeEventListener('touchend', onCancelListener); // remove the event listener since we dont need it anymore, to cleanup resources
resolve([...(event.target!.files as FileList)]); // and resolve the files that the user picked
removeInputFromDom();
};
window.addEventListener('focus', onCancelListener, { once: true }); // detect when the window is refocused without file being selected first, which is a sign that user canceled (e.g., user left window into the file system's file picker)
window.addEventListener('touchend', onCancelListener, { once: true }); // detect when the window is touched without a file being selected, which is a sign that user canceled (e.g., user did not leave window - but instead canceled the modal that lets you choose where to get photo from on ios)
// and trigger the file selection ui
addInputToDom();
fileInput.click();
});
Is there something wrong here? Because fileSelectedEle.value always returns the previous execution value and NOT the one selected by the user. Is this the expected behavior of input file? How to resolve this to read the actual file selected?
There's nothing wrong, this is expected behaviour. If the user cancels the file selection process, then it's as if they never started it. So the previous value is left in place.
I have a contact form that sends a value to a hidden input on successful completion of the sendmail function. I want to detect this value change and then use it to apply a class to a div/paragraph.
I asked a similar question recently and I'm aware that this requires the script to continually check the doc after DOM is loaded but even after adding .change() it just doesn't seem to want to add the class.
Here's the jQuery:
$(document).ready(function() {
$("#acf_success_sent").change(function(){
if ($("#acf_success_sent").val() == "1"){
$("#acf_verified").addClass('gone');
}
});
});
any help would be great. here's a link to a test version of form in case you're interested, everything works except the verified symbol doesn't disappear after a successful send http://seeshell.me/forms/contact.php
There'll be no "change" event fired when code updates the value of your <input> element, so the handler you've registered won't run. What you could do however is fire "change" from a watchdog:
var watchdog = setInterval(function() {
if ($('#acf_success_sent').val() !== originalValue)
$('#acf_success_sent').trigger('change');
}, 100);
How you set up "originalValue" depends on your application. You could, for example, keep a separate ".data()" value, and watch for whenever your saved value differs from the current "value" attribute. Or you could keep the value in a closure variable:
var watchdog = (function() {
var $acfSuccessSent = $('#acf_success_sent'), cachedValue = $acfSuccessSent.val();
return function() {
if (cachedValue !== $acfSuccessSent.val())
$acfSuccessSent.trigger('change');
};
})();
Hi I have a long form that is split into a wizard. To prevent the user from hitting browser back button and losing data I have the following:
window.onbeforeunload = function() {
return "Hitting back will cause you to lose all form data.";
};
How would I insert a flag and apply to the last step so the form can be submitted properly?
Thanks,
You can set a variable on the last step to true and check against it, like this:
var okToSubmit = false;
window.onbeforeunload = function() {
if(!okToSubmit) return "Hitting back will cause you to lose all form data.";
};
//set okToSubmit = true; on the last step
Without your current code I can't say exactly where to insert this, but wherever your script moves to the last step, add a okToSubmit = true; in there.