Essentially what I need is to run some JavaScript after a record has been saved. This will pick up a guid from a field which has been populated by a plugin. My code looks like;
Xrm.Page.data.entity.save();
var newguid = Xrm.Page.getAttribute("new_copyguid").getValue();
Xrm.Utility.openEntityForm("new_myentity", newguid);
The problem is the code runs past the call to save() and continues executing before a plugin has populated the "new_copyguid" field. Is there a way to wait for the plugin to complete before continuing with the javascript? I have tried AddOnSave() without success. Any javascript callback seems to execute before the plugin finishes as well. The plugin is set to run synchronously.
I am performing this javascript from a button on the form. The button sets a field value and then saves the record, triggering the plugin. The button is a "Copy Entity" button which creates a clone. I need to open this new record in the browser.
I have read that this does not work either, as it happens before the save;
Xrm.Page.data.refresh(save).then(successCallback, errorCallback);
Any pointers would be great!
I think you'll have to run your logic in the OnLoad section. The save should force a refresh and your onload logic will run again. You'll need to do some check to see if the modified on date is within a certain time frame.
Other option is you perform the update manually through a rest call or Soap call, then you can read the value from the plugin in another call.
You can just wait for some seconds by putting this code.
function YourFunction()
{
Xrm.Page.data.entity.save();
OpenForm();
}
Its a new function.
function OpenForm()
{
setTimeout(function () {
var newguid = Xrm.Page.getAttribute("new_copyguid").getValue();
Xrm.Utility.openEntityForm("new_myentity", newguid);
}, 3000);
}
Try this:
function onPageLoad() {
var formType = Xrm.Page.ui.getFormType();
if (formType == 0 || formType == 1) { // 0 = Undefined, 1 = Create
// If form is in Create Mode then
if (Xrm.Page.data != null && Xrm.Page.data.entity != null) {
Xrm.Page.data.entity.addOnSave(onSaveDoThis);
}
}
}
function onSaveDoThis() {
setTimeout(onFormSaveSuccess, 300);
}
function onFormSaveSuccess() {
var newguid = Xrm.Page.getAttribute("new_copyguid").getValue();
if (newguid == "") {
onSaveDoThis();
} else {
// Don't need to trigger the function onSaveDoThis anymore
Xrm.Page.data.entity.removeOnSave(onSaveDoThis);
Xrm.Utility.openEntityForm("new_myentity", newguid);
}
}
Try this:
function OpenForm()
{
setTimeout(function () {
var newguid = Xrm.Page.getAttribute("new_copyguid").getValue();
Xrm.Utility.openEntityForm("new_myentity", newguid);
}, 3000);
}
Related
I want to automate clicking the agree button to Google's cookie policies.
(I clean cookies after closing a tab, and I don't want to create a google account, so I get asked every time I use google)
There is a div element with the ID "introAgreeButton" that I'm trying to access with my script:
<div role="button" id="introAgreeButton" [...]></div>
However, document.getElementById('introAgreeButton') always returns null.
My first thought was that the element wasn't loaded by the time my function was executed. But it doesn't work if I execute it on window.onload, or even if I run it in a loop until the element is definitely there:
window.onload = function() {
var x = document.getElementById('introAgreeButton')
console.log(x)
}
Output:
null
function loop() {
var x = document.getElementById('introAgreeButton')
if (x) {
console.log('success')
} else {
loop()
}
}
Output:
null
null
null
...
Can be tested on https://www.google.com/search?hl=en&q=test
Anyone have an idea why this is and how to solve it?
Edit: I execute the script via the browser extension TamperMonkey
You can use setInterval to check if element is rendered in DOM like this :
document.addEventListener('DOMContentLoaded', function () {
var intervalID = null;
function checkElementInDOM () {
var element = document.getElementById('introAgreeButton');
if (element) {
clearInterval(intervalID);
// DO YOUR STUFF HERE ...
}
}
intervalID = setInterval(checkElementInDOM, 100);
});
To be used intelligently, however, so as not to have a setInterval which works continuously. Maybe think about adding a maximum number of attempts.
Here's the problem. I'm making a callback to the server that receives an MVC partial page. It's been working great, it calls the success function and all that. However, I'm calling a function after which iterates through specific elements:
$(".tool-fields.in div.collapse, .common-fields div.collapse").each(...)
Inside this, I'm checking for a specific attribute (custom one using data-) which is also working great; however; the iterator never finishes. No error messages are given, the program doesn't hold up. It just quits.
Here's the function with the iterator
function HideShow() {
$(".tool-fields.in div.collapse, .common-fields div.collapse").each(function () {
if (IsDataYesNoHide(this)) {
$(this).collapse("show");
}
else
$(this).collapse("hide");
});
alert("test");
}
Here's the function called in that, "IsDataYesNoHide":
function IsDataYesNoHide(element) {
var $element = $(element);
var datayesnohide = $element.attr("data-yes-no-hide");
if (datayesnohide !== undefined) {
var array = datayesnohide.split(";");
var returnAnswer = true;
for (var i in array) {
var answer = array[i].split("=")[1];
returnAnswer = returnAnswer && (answer.toLowerCase() === "true");
}
return returnAnswer;
}
else {
return false;
}
}
This is the way the attribute appears
data-yes-no-hide="pKanban_Val=true;pTwoBoxSystem_Val=true;"
EDIT: Per request, here is the jquery $.post
$.post(path + conPath + '/GrabDetails', $.param({ data: dataArr }, true), function (data) {
ToggleLoader(false); //Page load finished so the spinner should stop
if (data !== "") { //if we got anything back of if there wasn't a ghost record
$container.find(".container").first().append(data); //add the content
var $changes = $("#Changes"); //grab the changes
var $details = $("#details"); //grab the current
SplitPage($container, $details, $changes); //Just CSS changes
MoveApproveReject($changes); //Moves buttons to the left of the screen
MarkAsDifferent($changes, $details) //Adds the data- attribute and colors differences
}
else {
$(".Details .modal-content").removeClass("extra-wide"); //Normal page
$(".Details input[type=radio]").each(function () {
CheckOptionalFields(this);
});
}
HideShow(); //Hide or show fields by business logic
});
For a while, I thought the jquery collapse was breaking, but putting the simple alert('test') showed me what was happening. It just was never finishing.
Are there specific lengths of time a callback function can be called from a jquery postback? I'm loading everything in modal views which would indicate "oh maybe jquery is included twice", but I've already had that problem for other things and have made sure that it only ever includes once. As in the include is only once in the entire app and the layout is only applied to the main page.
I'm open to any possibilities.
Thanks!
~Brandon
Found the problem. I had a variable that was sometimes being set as undefined cause it to silently crash. I have no idea why there was no error message.
I am stuck on getting a timeout working. I already have a working code but it seems to me the wrong way to do it.
Working code but probably not the best:
/* Autosave */
// On load we hide all autosave messages.
$('.jform_params_autosave-cg').hide();
// Below is the function that handles the autosave.
$.fn.autoSave = function(){
// We remove the autosave message from it's place defined by the xml and add it to the system message container.
var autosavemessage = $('.jform_params_autosave-cg');
autosavemessage.detach();
autosavemessage.appendTo('#system-message-container');
// Now we show the message.
$('.jform_params_autosave-cg').show();
// Here we save the extension.
Joomla.submitbutton('module.apply');
}
// On change of the below elements we run the autosave.
//------------------------------------------//
// DUPLICATE AUTOSAVE FUNCTION BELOW
//------------------------------------------//
// Autosave: Theme Selection
$("#jform_params_theme_selection").change(function() {
$.fn.autoSave();
});
// Autosave: Add Content
$("a.group-add.btn.btn-mini.button.btn-success").click(function() {
setTimeout(
function()
{
$.fn.autoSave();
}, 5000);
});
The Function:
$.fn.autoSave = function(){
// We remove the autosave message from it's place defined by the xml and add it to the system message container.
var autosavemessage = $('.jform_params_autosave-cg');
autosavemessage.detach();
autosavemessage.appendTo('#system-message-container');
// Now we show the message.
$('.jform_params_autosave-cg').show();
// Here we save the extension.
Joomla.submitbutton('module.apply');
}
The Function Call
$("#jform_params_theme_selection").change(function() {
$.fn.autoSave();
});
The Function Call with Timeout
$("a.group-add.btn.btn-mini.button.btn-success").click(function() {
setTimeout(
function()
{
$.fn.autoSave();
}, 5000);
});
What do I want to achieve
Make the Timeout inside the function.
Define the timeout when calling the function.
With defining I mean calling it something like $.fn.autoSave(5000); or $.fn.autoSave().timeout(500);
I have been trying to get a working code but so far no luck. Will keep updating this post whenever I get more success or details to add.
Thanks everyone for helping.
Any link to existing SO questions will also be appreciated as I might be googling for the wrong key words.
Here it is the modified version of your function. Now it has optional timeout parameter. You can use it like
$('selector').autoSave(5000) or $('selector').autoSave()
$.fn.autoSave = function(timeout) {
function doIt() {
// We remove the autosave message from it's place defined by the xml and add it to the system message container.
var autosavemessage = $('.jform_params_autosave-cg');
autosavemessage.detach();
autosavemessage.appendTo('#system-message-container');
// Now we show the message.
$('.jform_params_autosave-cg').show();
// Here we save the extension.
Joomla.submitbutton('module.apply');
return this;
}
timeout = Number(timeout) || 0;
var f = doIt.bind(this);
if(timeout < 0) return f();
setTimeout(f, timeout);
return this;
}
Here is a quick example that should (but it doesn't work for some reason).
function clearSave()
{
var c = confirm("Are you sure you want to reset the current game?");
if (c==true)
{
localStorage.setItem("saved","false");
location.reload();
}
}
function save()
{
localStorage.setItem("saved","true");
setTimeout(save,1000);
}
function load()
{
if (localStorage.getItem("saved") == "true")
{
alert("Game Loaded");
}
else {
save();
}
}
When the page loads the load function is called. And when the user clicks a button to reset stuff the clearSave function is called.
But after the page is reloaded after the clearSave function is called the alert shows, meaning that the "saved" item is set to "true" somehow.
Any clues?
setTimeout(save,1000);
The above code is causing the error, you need to use some other strategy based on your needs
function save()
{
localStorage.setItem("saved","true");
//Below line needs to be updated
setTimeout(save,1000);
}
Problem: I have a asp.net button and on click of that I am displaying another window using window.open() at the client side using <script></script>
"I actually, need a popup (alert message) to be displayed on my parent page where my button is located once the user closes the child window."
Couple of things I tried are as follows:
I tried using setTimeOut() to have a time out for some milliseconds. This does not work as the control is not waiting until the time out is complete. It just proceeds to execute next set of code.
I tried using setInterval() but for some reason it is not working for me. Below is the code snippet of that:
$(document).ready(function () {
$('#<%=btnClick.ClientID%>').bind('click', function () {
var newWindow = window.open("http://www.google.com/", "google", 'resizable=1,width=900,height=800,scrollbars=1', '_blank');
newWindow.moveTo(0, 0);
var test = setInterval(function (e) {
if (newWindow.closed) {
alert("HEYY");
clearInterval(test);
__doPostBack("<%= btnClick.UniqueID %>", "");
}
else {
e.preventDefault();
}
}, 5000);
});
});
.
I also tried making an ajax call to open the new window and make it async : false, it again did not help me.
Bring your window and timer variable out of scope of the event handler. You need to do a polling i.e. periodically keep on checking if the windows has been closed. Using setInterval to do a polling will do the job.
var newWin, pollTimer;
$('#btnId').bind('click', function () {
newWin = window.open("...", "...", "");
pollTimer = window.setInterval(function() {
if (newWin.closed) {
window.clearInterval(pollTimer);
callCodeWhenPopupCloses();
}
}, 5000);
});
function callCodeWhenPopupCloses() {
alert("Popup closed.");
...
}