Is there a way to determine from JavaScript if a page contains a scriptmanager, an updatepanel or if the __doPostBack is called from an update panel or is a partialpostback?
When one update panel is called, then there are two functions that trigger from javascript side. Inside this functions you can also get the Ids of the panel that trigger this update. If there is a full post back outside of an update panel, then you need to capture the submit of the form.
Here are the code that triggered when an update panel is going to upadte, together with the functions that show the update panel ids that make the trigger.
<script>
if(window.Sys && Sys.WebForms && Sys.WebForms.PageRequestManager)
{
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
}
else
{
// no ScriptManager found
}
function InitializeRequest(sender, args)
{
// get the array of update panels id
var UpdPanelsIds = args.get_updatePanelsToUpdate();
// get the Post ID
args.get_postBackElement().id;
}
function EndRequest(sender, args) {
}
</script>
'Dan Davies Brackett' Correct describe how you can know if the ScriptManager exist.
If I understand correctly, there are two questions here:
(1) how do I tell in JavaScript whether a ScriptManager exists on a page?
If the server-side page contains a ScriptManager, there will be a PageRequestManager available on the client. You can discover whether it exists with:
var haveScriptManager = window.Sys && Sys.WebForms && Sys.WebForms.PageRequestManager;
(2) how do I tell whether __doPostBack is synchronous?
Once you have a handle to the local PageRequestManager, you can hook the event that fires before every postback and check whether it's synchronous or asynchronous. Again, the documentation for the PageRequestManager will give you all the details of how to do that.
Emit the scriptManager clientID to some clientside javascript, then look for it on the page (document.getElementById(emittedClientID)
You can rename __doPostBack with... __NewDoPostBack = __doPostBack, then create a new function such as...
__doPostBack = function(whatever arguments __NewDoPostBack takes){
alert("We're doing a post back");
__NewDoPostBack(whatever arguments __NewDoPostBack takes)
}
Related
We recently discovered that Chrome no longer supports window.showModalDialog which is problematic because our enterprise application uses this method.
There is, apparently, a short term workaround that allows you to restore showModalDialog but it involves modifying the registry which is too complicated (and risky) four our average user. Therefore I'm not a big fan of this workaround.
The long term solution is obviously to remove all calls to this obsolete method and replace them with a convenient jQuery plugin (such as VistaPrint's Skinny Modal Dialog plugin, for example. Other suggestions are welcome by the way).
The typical scenario we use the modal dialog is to ask the user for Yes/No confirmation before executing an action that cannot be undone, ask the user to agree to terms and condition before proceeding, etc. Typically the onclick event on the "Yes" or "Ok" button in the modal dialog looks like this:
window.returnValue = true;
window.close();
Similarly, the "Cancel" or "No" button looks like this:
window.returnValue = false;
window.close();
The fact that we can return a value from the dialog is very convenient because it allows the "parent" window to be notified whether the user has clicked the "Ok" or the "Cancel" button like so:
var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
... proceed ...
}
The last thing I'm going to mention about the showModalDialog is that it works great even when the document displayed in the dialog is from a different domain. It's very common for us to have our javascript running from http://the-client.com but the "Terms of Service" web page is from http://the-enterprise-vendor.com
I need a temporary solution that I can deploy ASAP while we work on the long term solution. Here are my criteria:
minimal code change in existing JavaScript
the pop up window must be able to return a value to the "parent". Typically this value is a Boolean but it could be any simple type (e.g.: string, int, etc.)
solution must work even if the URL of the content is from different domain
Here's what I have so far:
1) Add the following method in my JavaScript:
function OpenDialog(url, width, height, callback)
{
var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
var timer = setInterval(function ()
{
if (win.closed)
{
clearInterval(timer);
var returnValue = win.returnValue;
callback(returnValue);
}
}, 500);
}
As you can see in this method, I try to make the pop up window look as similar to a dialog as possible by hiding the menu and the toolbar, I setup a time every 500 milliseconds to check if the window has been closed by the user and if so, get the 'returnValue' and invoke a callback.
2) replace all calls to showModalDialog with the following:
OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
if (termsOfServiceAccepted)
{
... proceed ....
}
});
The fourth parameter to the method is the callback where I check if the user has clicked the "Ok" button before allowing her to proceed.
I know it's a long question but basically it boils down to:
What do you think of the solution I propose?
In particular, do you think I'll be able to get a returnValue from a window that was opened with window.open?
Any other alternative you can suggest?
I have two ideas that could help you but the first one is tied to CORS, so you won't be able to use it from different domains at least you can access both services and configure them.
FIRST IDEA:
The first one is related to this native api. You could create on the parent window a global function like this:
window.callback = function (result) {
//Code
}
As you can see it receives a result argument which can hold the boolean value you need. The you could open the popup using the same old window.open(url) function. The popup's onlick event handler could look like this:
function() {
//Do whatever you want.
window.opener.callback(true); //or false
}
SECOND IDEA: Solves the problem
The other idea I got is to use this other native api to trigger an event on the parent window when the popup resolves (better known as cross-document messaging). So you could do this from the parent window:
window.onmessage = function (e) {
if (e.data) {
//Code for true
} else {
//Code for false
}
};
By this way you are listening to any posted message on this window, and checking if the data attached to the message is true (the user clicks ok in the popup) or false (the user clicks cancel in the popup).
In the popup you should post a message to the parent window attaching a true or a false value when corresponds:
window.opener.postMessage(true, '*'); //or false
I think that this solution perfectly fits your needs.
EDIT
I have wrote that the second solution was also tied to CORS but digging deeper
I realized that cross-document messaging isn't tied to CORS
I am writing javascript code to change the form of a entity in Dynamics CRM based on the value of a field on each form.
To change the form, the user has to change the value of the field.
Then during the onChange event, my js comes in, triggers saving, has to wait for the result and then change the form. (If you save and change at the same time, there is still a window shown asking the user to confirm leaving unsaved changes)
Now there should be a way to do that:
Xrm.Page.data.save(saveOptions).then(successCallback, errorCallback)
as it is described on msdn:
Saves the record asynchronously with the option to set callback functions to be executed after the save operation is completed.
I am using it as such:
var campaignType = Xrm.Page.getAttribute('typecode').getValue();
if (xxx.Forms.hasOwnProperty(campaignType)) {
Xrm.Page.data.save().then(function () { xxx.redirectToForm(xxx.Forms[campaignType]); }, null);
But the form change is still triggered immediately during the save.
What am I doing wrong?
I faced a similar problem while trying to update the process bar.
Xrm.Page.data.save().then
(function () {
window.location.reload(true);
},
function () {
windows.alert("broken");
}
);
I strongly suggest you to try to apply the logic on a vanilla CRM, for me what was breaking the logic was a third party component called N52 Rules, their code was interfering with the callback forcing the refresh of the page before the save event. Your code seems correct.
Hey the Save and Refresh Calls are Asynchronous! that is why it hits the success handler immediately.
What you can try is using SDK.REST.js file for CRM
function updateFunction(entityId) {
var campaignType = Xrm.Page.getAttribute('typecode').getValue();
if (xxx.Forms.hasOwnProperty(campaignType)) {
var entity= {};
entity.typecode= campaignType;
SDK.REST.updateRecord(
entityId,
entity,
entityName, //"Account"
function () {
writeMessage("The record changes were saved");
xxx.redirectToForm(xxx.Forms[campaignType]);
},
null
);
}
}
https://msdn.microsoft.com/en-us/library/gg334427(v=crm.7).aspx
Here you can call updateFunction given above onChange and in the onSuccess handler you can try calling the form you want to call. I haven't tried it the way you want, but let me know if it works.
check this link out as well
https://msdn.microsoft.com/en-us/library/gg334720.aspx#BKMK_entityOnSave
We recently discovered that Chrome no longer supports window.showModalDialog which is problematic because our enterprise application uses this method.
There is, apparently, a short term workaround that allows you to restore showModalDialog but it involves modifying the registry which is too complicated (and risky) four our average user. Therefore I'm not a big fan of this workaround.
The long term solution is obviously to remove all calls to this obsolete method and replace them with a convenient jQuery plugin (such as VistaPrint's Skinny Modal Dialog plugin, for example. Other suggestions are welcome by the way).
The typical scenario we use the modal dialog is to ask the user for Yes/No confirmation before executing an action that cannot be undone, ask the user to agree to terms and condition before proceeding, etc. Typically the onclick event on the "Yes" or "Ok" button in the modal dialog looks like this:
window.returnValue = true;
window.close();
Similarly, the "Cancel" or "No" button looks like this:
window.returnValue = false;
window.close();
The fact that we can return a value from the dialog is very convenient because it allows the "parent" window to be notified whether the user has clicked the "Ok" or the "Cancel" button like so:
var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
... proceed ...
}
The last thing I'm going to mention about the showModalDialog is that it works great even when the document displayed in the dialog is from a different domain. It's very common for us to have our javascript running from http://the-client.com but the "Terms of Service" web page is from http://the-enterprise-vendor.com
I need a temporary solution that I can deploy ASAP while we work on the long term solution. Here are my criteria:
minimal code change in existing JavaScript
the pop up window must be able to return a value to the "parent". Typically this value is a Boolean but it could be any simple type (e.g.: string, int, etc.)
solution must work even if the URL of the content is from different domain
Here's what I have so far:
1) Add the following method in my JavaScript:
function OpenDialog(url, width, height, callback)
{
var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
var timer = setInterval(function ()
{
if (win.closed)
{
clearInterval(timer);
var returnValue = win.returnValue;
callback(returnValue);
}
}, 500);
}
As you can see in this method, I try to make the pop up window look as similar to a dialog as possible by hiding the menu and the toolbar, I setup a time every 500 milliseconds to check if the window has been closed by the user and if so, get the 'returnValue' and invoke a callback.
2) replace all calls to showModalDialog with the following:
OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
if (termsOfServiceAccepted)
{
... proceed ....
}
});
The fourth parameter to the method is the callback where I check if the user has clicked the "Ok" button before allowing her to proceed.
I know it's a long question but basically it boils down to:
What do you think of the solution I propose?
In particular, do you think I'll be able to get a returnValue from a window that was opened with window.open?
Any other alternative you can suggest?
I have two ideas that could help you but the first one is tied to CORS, so you won't be able to use it from different domains at least you can access both services and configure them.
FIRST IDEA:
The first one is related to this native api. You could create on the parent window a global function like this:
window.callback = function (result) {
//Code
}
As you can see it receives a result argument which can hold the boolean value you need. The you could open the popup using the same old window.open(url) function. The popup's onlick event handler could look like this:
function() {
//Do whatever you want.
window.opener.callback(true); //or false
}
SECOND IDEA: Solves the problem
The other idea I got is to use this other native api to trigger an event on the parent window when the popup resolves (better known as cross-document messaging). So you could do this from the parent window:
window.onmessage = function (e) {
if (e.data) {
//Code for true
} else {
//Code for false
}
};
By this way you are listening to any posted message on this window, and checking if the data attached to the message is true (the user clicks ok in the popup) or false (the user clicks cancel in the popup).
In the popup you should post a message to the parent window attaching a true or a false value when corresponds:
window.opener.postMessage(true, '*'); //or false
I think that this solution perfectly fits your needs.
EDIT
I have wrote that the second solution was also tied to CORS but digging deeper
I realized that cross-document messaging isn't tied to CORS
In .NET 2.0, I have several client side validators ala the .NET validator controls. These run fine when I click a button...until I add my own javascript function to this button. Instead of running in addtion to the validators, it seems to prevent them from running at all.
To be clear, the validator controls are basic required field validators, and here is the javascript I added:
<script language="javascript">
function yaya()
{
var chkAmount = document.frmSearchFor.txtCheckAmount.value;
var amtApplied = document.frmSearchFor.lblAmountApplied.value;
if (amtApplied < chkAmount)
{
return confirm('Continue?');
}
}
</script>
And it's tied to the button like this...
OnClientClick="return yaya();
those are probably not the ID's being rendered to your page. Try this:
function yaya()
{
var checkAmount = parseFloat(document.getElementById("<%=txtCheckAmount.ClientID %>").value);
var amoutApplied = parseFloat(document.getElementById("<%=lblAmountApplied.ClientID %>").text);
if (amoutApplied < checkAmount)
{
return confirm('Continue?');
}
}
And try attaching it like this:
OnClientClick="javascript:yaya();";
Client-side validation is done via javascript just like your client click. When you specify the client-side event, I'm guessing there's nowhere for the validation code to attach. You may need to modify either the validation code to call your function, or your function to call the validation code. Probably the latter is easier. Instead of assigning OnClientClick at design time, add a client script that stores the current click handler function, creates a function that runs your code and then runs the stored handler function, and attaches that new function as the click handler.
<script>
var baseHandler = myElement.onclick;
myElement.onClick = function() {
// run your code here
baseHandler();
}
</script>
issue is that you are specifying a return in your OnClientClick attribute. when the page renders, it comes out like this
<input ... onclick="return yaya();WebForm_DoPostBackWithOptions...
after yaya completes, the onclick function concludes and I believe it's shutting down any further action that would normally happen before the form is submitted. it's kind of ugly but you can get around this by only having a return when your function evaluates to false:
OnClientClick="if (!yaya()) { return false; }"
for this to work you should also include return true; at the end of your function in case the conditions for the if check are not met.
you may also be having issues with references to elements as Hunter mentions but you're not providing your markup to verify that.
I have a Flex application which allows the user to edit a cloud-based document. (Think SlideRocket.) When the user tries to navigate away or close the browser window, I'd like to show them an are-you-sure dialog iff they have unsaved changes.
I'm using the following custom class, which I found at Flash player notified on browser close or change page (as3). I don't think it is the problem.
package
{
import flash.external.ExternalInterface;
public class ExternalInterfaceUtil
{
public static function addExternalEventListener(qualifiedEventName:String, callback:Function, callBackAlias:String):void
{
// 1. Expose the callback function via the callBackAlias
ExternalInterface.addCallback( callBackAlias, callback );
// 2. Build javascript to execute
var jsExecuteCallBack:String = "document.getElementsByName('"+ExternalInterface.objectID+"')[0]."+callBackAlias+"()";
var jsBindEvent:String = "function(){"+qualifiedEventName+"= function(){"+jsExecuteCallBack+"};}";
// 3. Execute the composed javascript to perform the binding of the external event to the specified callBack function
ExternalInterface.call(jsBindEvent);
}
}
}
In my applicationComplete function, I add an event listener to the javascript window.onbeforeunload event, as follows:
ExternalInterfaceUtil.addExternalEventListener("window.onbeforeunload", requestUnloadConfirmation, "unloadConfirmation");
The Actionscript function requestUnloadConfirmation (below) is successfully called when the user tries to close the browser window. However, it does not prevent the browser from closing. (In Chrome, the browser closes and the Actionscript function is called subsequently. In Firefox, the browser stays open for the duration of the function but then closes.)
private function requestUnloadConfirmation():String {
if (changedSinceSave)
return "There are unsaved changes. Are you sure you want to leave without saving?";
else
return null;
}
Behavior is identical in both debug and release builds, and on the production server as well as the local machine.
Any help would be greatly appreciated,
Dave
Right now, when the JavaScript event is fired, it is set to call your function in your AS3 code, which it does. The JavaScript function, however, is not returning the value that your AS3 function returns. To get this behaviour, add 'return' to the JavaScript event-handling function created in addExternalEventListener like so:
var jsBindEvent:String = "function(){"+qualifiedEventName+"= function(){return "+jsExecuteCallBack+"};}";
Since the event handler should return a true or false value, your requestUnloadConfirmation function should have a return type of Boolean and return false to cancel the event, and true otherwise. Use the following to get a confirmation dialog box:
private function requestUnloadConfirmation():Boolean {
if (changedSinceSave)
return ExternalInterface.call("confirm", "There are unsaved changes. Are you sure you want to leave without saving?");
else
return false;
}
UPDATE:
It turns out that returning a string to window.onbeforeunload causes a confirmation dialog box to be shown automatically. The ExternalInterface.call to confirm causes a second dialog box to show; it is redundant. The only change required in the AS3 code is to add the "return" in the generated JavaScript.
In a regular html/javascript web-app you would use the window.onbeforeunload event to do this.
https://web.archive.org/web/20211028110528/http://www.4guysfromrolla.com/demos/OnBeforeUnloadDemo1.htm
Perhaps you can use this event, and check some value of your flex app to determine if you should ask the user (not familiar with flex...)?
I had to run some modifications in the above code to make it work.
The problem was due to the fact that the function which handles the event window.onbeforeunload, should not return any value to avoid popup confirmation and should return text value when a popup confirmation is in-order
Here are my changes:
private function requestUnloadConfirmation():String {
if (changedSinceSave){
return "There are unsaved changes. Are you sure you want to leave without saving?";
}
return null;
}
And a little change in embedded JS
var jsBindEvent:String = "function(){"+qualifiedEventName+"= function(){ if ("+jsExecuteCallBack+") return "+jsExecuteCallBack+"};}";