Tag Archives: javascript

Capturing a signature in a CRM form using html5

Scenario:

“I have a touchscreen.  I want to capture a signature in a Dynamics CRM form.  If the signature hasn’t been saved, then I want to allow a user to provide their signature.  The next time the record is loaded, after the signature has been saved, I want to load an imagine of the signature to prevent ‘resigning’.”

This is a relatively simple thing with Dynamics CRM thanks to web resources and Xrm.Page.  The general concept is to embed an html web resource in the form that captures the signature using the html5 canvas (preferably using an existing control vs. low level canvas programming).  Before saving, you want to copy the data from the canvas control into a Multiple Lines of Text type hidden field on the form so the data is stored when the record is saved.  Finally, when the web resource is loaded, you want to check if the field has data in it.  If so, you can assume a signature was previously recorded and just show the data as an image. 

Here’s the entire source code for a basic implementation:

1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title>Signature</title> 5 <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.1.min.js"></script> 6 <script src="scripts/jSignature.min.js"></script><!-- download from http://willowsystems.github.io/jSignature/#/about/ --> 7 </head> 8 <body> 9 <img id="sigImage" alt="This is an image of the persons signature." style="display:none"/> 10 <div id="sigPanel" style="display:none"> 11 <div id="signature"></div> 12 <button id="clear">Clear</button> 13 </div> 14 <script type="text/javascript"> 15 $(function () { 16 var sigImage = $("#sigImage"); 17 var sigPanel = $("#sigPanel"); 18 var sig = $("#signature"); 19 20 var Xrm = window.parent.Xrm; 21 var sigBase64Attribute = Xrm.Page.getAttribute("msftpoc_esigbase64"); //replace this with your hidden "multiple lines of text" field with a max length of 1,048,576 22 var sigBase64Value = sigBase64Attribute.getValue(); 23 24 sig.bind("change", function (e) { 25 sigBase64Attribute.setValue(sig.jSignature("getData")); 26 }); 27 28 29 if (sigBase64Value != null) { 30 sigImage.css("display", "inline"); 31 sigImage.attr("src", sigBase64Value); 32 } else { 33 sigPanel.css("display", "inline"); 34 sig.jSignature(); 35 $("#clear").click(function() { 36 sig.jSignature("clear"); 37 }); 38 } 39 }); 40 </script> 41 </body> 42 </html> 43

All you have to do is add this web resource to your form (make sure you read instructions in the comments) and update the code to reference your field name.  A few things to note:

  • There are many controls out there, but I chose http://willowsystems.github.io/jSignature/#/about/.  It met all my requirements.  Feel free to use another.
  • The hidden field on the form for my entity is called msftpoc_esigbase64 and uses the Multiple Lines of Text type of Dynamics CRM.  Make sure to change the code to match your field name.
  • For simplicity, I chose to use the default data format of the jSignature control which is a base64 encoded string (hence my field name).  Since base64 encoded strings can be big, I set the max length field to 1,048,576 which is the largest Dynamics CRM allows.  The jSignature control supports other formats.  You could clearly improve on performance of this sample by using one of the smaller string formats.
  • My code doesn’t handle save/autosave side effects.  I simply copy the signature date to the hidden field using the change event of the jSignature control.   A more robust implementation would perhaps wire up to Xrm.Page.data.entity.addOnSave() and intelligently determine whether to copy the data into the field based on save state.  You might also want to consider switching to the image after as successful OnSave with signature if that makes the most sense for your requirements.  I’ll leave that up to you as an exercise for improvement.

Here are a couple screenshots for a quick visualization.

Before Save (signature capable canvas with clear button):

image

After Save (fixed image of signature):

image

@devkeydet

Debugging CRM web resources without ever deploying them

UPDATE: The steps explained below don’t work with CRM 2013.  However, Scott has a blog post which shows you how to get it working again:

http://develop1.net/public/post/Fiddler2-The-tool-that-gives-you-Superpowers-Part-2.aspx

One of my last posts was sharing how I use Visual Studio to debug CRM web resources:

http://blogs.msdn.com/b/devkeydet/archive/2013/06/19/eureka-f5-debugging-of-crm-javascript-web-resources.aspx

This approach was one of those discoveries that makes us developer types get a little excited because it allows us to do something we do repeatedly in a much more efficient fashion.  I just came across another one of those EUREKA moments thanks to Scott Durow (@scottdurow) and some his promising new http://www.sparklexrm.com project. 

BTW, Scott’s the man behind Ribbon Workbench for Dynamics CRM.  It’s the best Ribbon editor out there in my opinion.  I digress…

I was reading through http://www.sparklexrm.com/s/Tutorials/SetUpNewProject.html and discovered a little gift from Scott at the end of the walkthrough.  Steps 9-14 explain how to use www.fiddler2.com to let you debug changes to web resources without ever having to deploy them to Dynamics CRM.  How?  Steps 9-14 explain it.

Combine this with my post on F5 debugging from Visual Studio and you nearly have web resource developer productivity nirvana.  I just tried combining the two approaches.  It works beautifully!  I was able to make changes to JavaScript, hit F5, debug right in Visual Studio, and repeat over and over again.  I did this all without ever having to deploy the JavaScript file to the server.  Because of it, I was able to iterate on my changes in a fraction of the time CRM developer typically spend.  Try it yourself!

@devkeydet

EUREKA: F5 debugging of CRM JavaScript web resources

Scenario:

“Internet Explorer F12 JavaScript debugger is great, but I use Visual Studio.  I want to be able to set breakpoints in my JavaScript web resources which I author in Visual Studio, then hit F5 on the keyboard or Debug->Start Debugging from the menu or the Play Button on my toolbar just like I do with all other types of development in Visual Studio.  Visual Studio should then launch the right CRM url, attach its JavaScript debugger, and my breakpoints should be hit.”

This is the #1 piece of feedback I hear from the customers/partners/ISVs with whom I work.  I’ve always told people it’s not possible.  I just realized how wrong I am.  Given that I’ve used every version Visual Studio since it was first released, I am a little embarrassed to say I just had this “A HA!” moment.  Better late than neverSmile

As I mentioned in this post, I have stopped using the Developer Toolkit for Microsoft Dynamics CRM for web resource authoring in favor of the CRM 2011 Web Resource Linker/Publisher.  Note, I still use the developer toolkit for plugin / workflow activity authoring.  As I state in the post about the web resource linker tool, since it allows you to keep all of your web resources in a standard web project in VS, you get all the benefits of web project capabilities including other addons that work with web projects.  It’s this premise which brought me to my “A HA!” moment.  Below is a video walkthrough of getting this scenario working:

 

You can install the jQuery Code Snippets from:

http://visualstudiogallery.msdn.microsoft.com/577b9c03-71fb-417b-bcbb-94b6d3d326b8

@devkeydet

TOOL HIGHLIGHT: CRM 2011 Web Resource Linker/Publisher

I’ve blogged previously about why I like the approach CRM Solution Manager uses for authoring web resources in Visual Studio.  While I think CRM Solution Manager is a fantastic tool, there are ways to get some of the benefits of it’s approach to web resource authoring with a couple other free Visual Studio addins.  The first tool is CRM 2011 Web Resource Linker/Publisher.  This tool provides the ability to map a file in a Visual Studio project to a web resource in CRM.  Because of this, I can organize my scripts in a folder structure which aligns with the relative path naming convention that’s recommended in the CRM SDK.  See http://msdn.microsoft.com/en-us/library/gg309536.aspx for more details.  In the picture below, I just started with an empty web app and added the dkdt_ structure below:

image

Then, I simply link/publish the files:

image

Here’s an example of what initial linking looks like:

image

Notice that you can also create a new web resource right from the linker dialog.  Once you’ve linked the files, you can do things like multi-select in Solution Explorer and deploy/publish just the files you care about:

image

But wait, there’s more.  Since this is just a standard web app project, I can take advantage of all the goodness that Visual Studio 2012 has to offer.  For example, I can use NuGet to add the CRM 2011 Client Side VSDoc to get JavaScript Intellisense for Xrm.Page and simply drag and drop the file from Solution Explorer to the open JavaScript file that needs Intellisense and Visual Studio takes care of adding the reference:

image

I can also take advantage of addins which are designed to work with web projects such as Web Essentials 2012.  One example is the JavaScript Minification feature:

image

…which will give me a production optimized version of my JavaScript file.  Because these are just files, I can just relink if I want to test the minified version.  To hit home the “because they are just files” point, I’ll give you another example.  I’ve grown fond of TypeScript.  There’s even an Xrm.Page TypeScript definition file.  Because TypeScript ultimately produces JavaScript files, those files can simply be linked/published.  I think you are starting to see the “it just works” pattern here.

So, for me, I’ve stopped using the Developer Toolkit for Microsoft Dynamics CRM to Create and Deploy Web Resources because many of these things I talk about don’t work with the supplied template.  Furthermore, the Developer Toolkit forces you to deploy all of your web resources every time and it doesn’t publish.  You have to do that manually.  I’ve found the approach I lay out in this post to be the most productive way of using Visual Studio to develop web resources.  However, I still use the Developer Toolkit to Create and Deploy Plug-ins and Create and Deploy Workflow Libraries.

HTH

@devkeydet

Improving perceived performance in a CRM form

In general web development, there are useful patterns to improving the perceived performance in a web page.  A great example is this blog post:

http://blog.michaelckennedy.net/2012/11/13/improve-perceived-performance-of-asp-net-mvc-websites-with-async-partialviews/

Once you understand the core concepts of the post (even tough it’s about ASP.NET MVC), you should be able apply similar patterns with CRM Web Resources.  You can achieve the same thing by breaking up your UI pieces into separate web resources and laying them out on the form appropriately.  Or you can have separate div tags in your web resource for each thing that needs to be loaded discretely.  Often times, in CRM, people want to have the similar spinning loading indicator while the initialization of the web resource is happening.  I’ve put together a little sample of how I do it.  I’ve packaged it up as a managed solution you can download and review:

http://sdrv.ms/14dZNvi

Here’s a quick video of it in action:

All I did was add the dkdt_/simulateslowload.htm web resource to the form.

Basically, what happens is when the web resource loads it has the real content hidden.  I simulate an asynchronous web service call using setTimeout with a delay of 3 seconds.  The idea is that the real content gets fully generated after the web service call is complete.  Therefore, a delay.  While we’re waiting, I show a loading animation via an overlaid IFrame.  Once the 3 seconds are over, I hide the animation and show the content.

@devkeydet

CRM Online & Windows Azure: Improving the SSO experience

This is supposed to be one of a series of CRM Online & Windows Azure posts for which I have been building some samples.  While I really wanted to make this the second or third post, someone needed the explanation sooner, so this will be somewhat of a tease to the overall series.

Scenario:

I’ve already configured SSO across Windows Azure & CRM Online.  When I try to integrate an Azure hosted page into the CRM UI, I get the following errors:

This content cannot be displayed in a frame

To help protect the security of information you enter into this website, the publisher of this content does not allow it to be displayed in a frame.

This video walks you through why you get the error and how to work around it with a better user experience.

Here’s the code for the two helper pages…

ssoinitiator.htm (CRM Web Resource)

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

    <head>

        <title></title>

        <meta http-equiv="refresh" content="5">

        <script type="text/javascript">
   1:  

   2:             function getQuerystring(key, default_) {

   3:                 if (default_ == null) default_ = "";

   4:                 key = key.replace(/[[]/, "\[").replace(/[]]/, "\]");

   5:                 var regex = new RegExp("[\?&]" + key + "=([^&#]*)");

   6:                 var qs = regex.exec(window.location.href);

   7:                 if (qs == null)

   8:                     return default_;

   9:                 else

  10:                     return qs[1];

  11:             }

  12:  

  13:             function redirectToIntendedPage() {

  14:                 window.location = decodeURIComponent(getQuerystring("data"));

  15:             }

  16:  

  17:             function bodyOnload() {

  18:                 if (document.cookie.indexOf("AZURE_SSO_COMPLETE=") != -1) {

  19:                     redirectToIntendedPage();

  20:                 } else {

  21:                     var message = document.getElementById("message");

  22:                     message.style.visibility = "visible";

  23:  

  24:                     if (document.cookie.indexOf("AZURE_SSO_INITIATED=") == -1) {

  25:                         document.cookie = "AZURE_SSO_INITIATED=true";

  26:                         window.open("https://crmazrfedtest.cloudapp.net/SSOHelper.htm");//replace with your azure hosted version

  27:                     } else {

  28:                         document.cookie = "AZURE_SSO_COMPLETE=true";

  29:                         redirectToIntendedPage();

  30:                     }

  31:                 }

  32:             }

  33:         

</script>

    </head>

    <body onload="bodyOnload() ">

        <div id="message" style="visibility:hidden">

            <h1>Initiating Single Sign On...</h1>

            <p>This page will refresh shortly.</p>

        </div>

    </body>

</html>

SSOHelper.htm (Azure hosted)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

    <head>

        <title>SSO Helper</title>

        <script type="text/javascript">
   1:  

   2:             function bodyOnload() {

   3:                 window.close();

   4:             }

   5:         

</script>

        <meta http-equiv="expires" content="-1" />

        <meta http-equiv="pragma" content="no-cache" />

    </head>

    <body onload="bodyOnload()">

        <div>

            <h1>Single Sign On Complete</h1>

            <p>Please close this window.</p>

        </div>

    </body>

</html>

@devkeydet

Enable IE10 spell check in a CRM 2011 form

UPDATE: Yes, I am shamelessly promoting IE10 in this post, but this will work in any browser CRM that supports the spellcheck attribute.

Now that Polaris/UR12 is out, CRM works with browsers like IE10 and others that support the spellcheck attribute of the <input/> and <textarea/> tags.  According to Spellchecking in IE10, “Spellchecking is active by default on <textarea> and contenteditable elements, and off by default for text boxes.”

As you might expect, the Multiple Lines of Text fields on the form are rendered using <textarea/> tags.  Therefore, the spelling error suggestions will be shown.  However, Single Line of Text fields are rendered using <input/> tags.  Therefore the spelling won’t be checked.  I tested this out with IE10 installed on Windows Server 2008 R2. 

clip_image002

Notice the first attempt has no red error indicator underlining the misspelled text and the second one does.  Fingers crossed that there will be an option in a future release of Dynamics CRM to control configuring spellcheck for form controls.  In the interim, you can apply an OBVIOUSLY UNSUPPORTED, but relatively harmless workaround if you really want your textboxes to be enabled for IE10 spell checking.  Here’s how:

-Reference jQuery in the form

-Reference a JavaScript file in the form that contains the following function and call it on form load:

function enableSpellcheck(){

$(“:text”).attr(“spellcheck”,true);

}

After applying this, you will see that the text in your textboxes are being checked for spelling errors:

clip_image002[5]

Why is this unsupported?  Because the CRM 2011 SDK clearly states here that “HTML DOM manipulation is not supported” when the CRM product owns the HTML.  Yes, it’s supported for your web resources because you own that html.  The CRM product owns it’s HTML and can never guarantee your code won’t break if you do some wacky DOM manipulation of it’s HTML.

Because of this, I tend to stay away from sharing unsupported hacks.  However, this one seems to follow my unsupported hacks rule of thumb.  I always ask myself, “what are the potential side effects?”  Most of the time, the potential side effects (say after a service update / update rollup) are too risky.  In this case, the risk is low but technically unsupported nonetheless.  It’s your call.

I tested this out with IE10 installed on Windows Server 2008 R2.  You can download IE10 for Windows 7 SP1 / Windows Server 2008 R2 SP1 which you can download in preview form http://ie.microsoft.com/testdrive/info/downloads/Default.html.

 

@devkeydet