window.print() problems in Dynamics CRM 2011 forms - dynamics-crm

We've been implementing a Dynamics CRM 2011 solution where one of the requirements was to print out a bespoke-styled form containing sub-grids and charts. The short story is that clicking on a "print" link (which calls the window.print() method) throws up a series of JavaScript errors. These, however, are non-fatal and clicking through each will allow the form to be printed OK.
Line: 73
Char: 24234
Error: The value of the property 'isNull' is null or undefined, not a Function object.
URL: https:://aks7.crm4.dynamics.com/_static/_forms/controls/img.lu.htc?ver=-115872263
(note that the double colon above was intentional!)
One of our early thoughts was that the problem was down to unsupported customisations, so as a test I created a new entity with a basic form. On the ribbon I added a print button which calls the window.print() method. The result is exactly the same. I've also replicated the issue on CRM Online.
The upshot is that either using window.print() is unsupported, or we've found a bug or both. Is there a solution to this?

I suspect that it's unsupported since the native print functionality renders a different page before sending to print (suggesting that this is a workaround for some feature of their .htc files).
Can you not take the same approach? The stub URL for the "Print Preview" is at .../_forms/print/print.aspx?allsubgridspages=true&formid=<form-guid>&id=%7b<record-guid>%7d&objectType=<object-type-code>. You could wrap this is a HTML web resource and call the CRM print button function from your HTML holding frame.

Instead of using the window.print, you have to automate the print preview.
I use this, but it's unsupported:
parent.document.getElementById('Mscrm.Jewel-Default').children[0].click();
parent.document.getElementById('Mscrm.Jewel.PrintPreview-Menu16').click();
http://blog.customereffective.com/blog/2011/08/printing-in-crm-2011.html

Related

Programmatically determine if Sagepay card details form is incomplete

I'm looking for some help with regards to the drop-in checkout integration.
https://developer-eu.elavon.com/docs/opayo/integrate-our-drop-checkout
In particular I'm following ‘custom flow’ example - see first code example for the Custom Flow section. https://developer-eu.elavon.com/docs/opayo/spec/api-reference#section/Custom-flow
In summary how can I programmatically determine if the sagepay 'card details' form which is injected into the sp-container (hosted in an iframe) is not valid for submission/tokenisation, when a call ‘tokenise’ link is used?
For example when the user has not completed all the required fields; Name, Card Number, Expiry or CVC.
I'm following the flow calling sagepayCheckout.tokenise() when the user clicks our 'Complete Payment' button (referred to as the tokenise link in the custom flow example).
NB: Implementation is part of a SPA app in my particular case I'm not submitting the (outer) form rather handling things using javascipt and calling the tokenise method.
Normally the onTokenise call back method is called on success or when wrong card details have been entered or merchantKey has expired. But when the injected sagepay form fails its own validity the onTokenise call back is never called.
NB: Due to browser security I can't check the state of the fields inside the iframe.
Ok some good points to note:
The sagepay form does feedback to the user about errors that required fields need to be completed.
And sagepayCheckout.tokenise() doesn't try to submit my (outer) form when these errors exist.
But there doesn't seem to be a programmatic way to know if the required fields need to be complete (or the onTokenise call back wont be called).
The main reason I need to know when the form is incompleted or tokenise has failed would be to re-enable our 'Complete Payment' button. Currently our button is disabled as soon as the user clicks it to prevent multiple clicks.
I am having this exact same problem. The only way I have been able to think of to get around this is to use the message event listener on the window. The sagepay.js library registers a 'message' event on the window object probably when the sagepayCheckout method is called.
Side note: this method is also poorly implemented as anything else that uses the window message event will cause the sagpay.js library to throw errors.
I think the only purpose of sagepay.js' message event hander is to resize the iframe window when its content changes. If you were to assume the content of the iframe will only change when validation fails you might be able use that to reset the state of your 'Complete Payment' button.
I would also suggest making a complaint to Opayo. This library is clunky and in desperate need of improvement.

Click-To-Call feature for Dynamics CRM (like Lync/Skype)

Advance warning: Im an absolute newbie to Dynamics CRM!
Intention
I want to have a feature like Lync/Skype integration but use my own URL. (Click on any telephone number inside CRM and call it).
For eg. assuming I have a web service which can initiate a call per URL: http://telephony.com/call?nr=012345678. Now, whenever a CRM user clicks onto a telephone number field (in forms and views) inside the CRM my web service should be called instead of Skype/Lync.
In fact I'm trying to reproduce sth. like the InGenius Connecter.
Attempts
I already tried to inject a JS web resource to a specific formular (in my case it was the default contact form) and override the Mscrm.ReadFormUtilities.openPhoneClient callback (which seems to handle the Lync/Skype integration).
function load() {
// override integrated CTC (Lync/Skype)
Mscrm.ReadFormUtilities.openPhoneClient = function (telephoneNr) {
// redirect user to my web service
window.location.replace("http://telephony.com/call?nr="+telephoneNr);
return;
}
}
Found this method at: Disable Lync completely
This does work well in forms of Dynamics 2015 (my custom link pops up instead of Skype/Lync). However, this does only work on entity forms since I can't inject web resources into an entity view.
My other ideas how to implement such a feature are:
Inject global JS resource which disables Lync/Skype and encapsulate every telephone number with link to my custom URL.
Extend/Manipulate Lync/Skype integration to use my custom URL instead of Lync/Skype.
Write plugin which encapsulate telephone numbers server side.
Question
Since I have a grasp understanding of Dynamics and no experience in plugin/resource development, I'm left a bit confused with these questions.
Is it possible to achieve any of the three ideas above ?
If not, any idea how InGenius solved this problem ?
Do you have any other idea/resources about this topic ?
Currently I found two options available to achieve a custom CTC feature. (Both has the downside of not being officialy supported by the dynamics crm.)
Global Ribbon
Pretty simple: Add a Click-To-Call button to global ribbon which is only enabled on specific grids when one row is selected.
This button refers to an JS-Action which retrieves the telephone number via ODATA and then launches the dial process.
Global Ribbon CustomRule injection
Add a global button to ribbon which refers to a JS resource per <CustomRule>. The JScript then unbinds all actions from links with .ms-crm-Phone classes and replaces its href-attribute.
This would be useful if one want to override the integrated "Skype / Lync - Click to Dial" feature with his own logic.
I didn't test this method until now, so I can't guarentee it's working !
Note: I will include example scripts as soon I got the time.

Working with Quick View Forms

Has anyone had any success working with the Quick View forms and JavaScript in CRM 2013?
I'm attempting to get a value from the related entity. That value is on the quick view form. Inspection of the DOM means I can get to it via unsupported means...
document.getElementById("cardPatient_cardPatient_contact_birthdate").innerText
but I'd rather not.
All the information is there. I wonder if there's a way to get to it via supported methods. I'm currently hitting the OData service for the birthdate but it just strikes me as a waste when it's there already.
If you use OData call you already use supported way.
Quick forms attributes are accessible by calling getAttribute() from the control, as described here: http://msdn.microsoft.com/en-us/library/gg334266.aspx. Here's the example given on the page:
var quickViewMobilePhoneControl = Xrm.Page.getControl("contactQuickForm_contactQuickForm_contact_mobilephone");
if (quickViewMobilePhoneControl.getAttribute().getValue() == null)
{
quickViewMobilePhoneControl.setVisible(false);
}

Up to date, working Google apps-script example integrated with spreadsheet?

I'm trying to build some kind of GUI on top of/embedded into a google spreadsheet.
I've been crawling through the docs, and sadly, hitting a wall.
I DID find the sample video, at
http://www.youtube.com/watch?v=5VmEPo6Rkq4
Unfortunately, it seems out of date and broken :( Some of the calls are no longer valid.
And, while I think I figured that part out, I cant get the callback handler to be recognized.
It gives me a runtime error of
"Error encountered: Script function not found:
function respondToSubmit(e) {
/* full body of function here*/
}"
The odd thing is, for supposedly not finding it, it does a good job of printing out the whole function body.
It doesnt seem to be an error inside the function itself, because when I make it an EMPTY function, it still gives the same error :(
Could someone please point me to a simple, working example of how to add a UI alongside a google spreadsheet, or equivalent?
Please note that I dont need a general-purpose, standalone application(I think).
I'm just trying to embed some GUI type functions, in one very specific google spreadsheet that I have.
There are examples of simple Spreadsheet UIs using three different approaches in the
Dialogs and Sidebars in Google Apps documentation. They all work today. The third approach, Custom Dialogs, can be implemented using UiService or HtmlService, but that page only shows an example using HtmlService.

Kendo UI Grid/DataSource - Global Error Handling?

I've currently inherited an application which has numerous Kendo grids (and other controls) throughout, and I'm trying to fix an error which keeps cropping up now and again - specifically when the user is no longer authenticated.
I know what the solution is for a single instance of the control - return a flag to indicate authentication failed, and then detect this in the error handler and perform the authentication.
The problem is am I really going to have to handle this for every instance of a Kendo control I have? Is there not a global error handler I can hook into? Either for the data source itself (as I know this is used for all Kendo control data loading), or for the Grid specificially. I don't mind either way - just which one is a hook.
This would be a more straighforward short term solution than refactoring everything to specific error handlers, etc.
I assume you can attach a global error handler to $.ajax, which is used by the DataSource, you can check how to do it here:
http://api.jquery.com/category/ajax/global-ajax-event-handlers/
Or, you can take advanttage of that the configuration that is done in the DataSource is passed directly to the $.ajax:
http://docs.kendoui.com/api/framework/datasource#configuration-transport.read-ObjectStringFunction
For reference, someone from Telerik has provided a solution using just the DataSource. I haven't tested it, but I prefer the accepted answer above as it hooked into all Ajax on the site - not just ones that utilise the Kendo DataSource.
http://www.kendoui.com/forums/mvc/grid/global-error-handler-for-numerous-grids.aspx

Resources