Welcome to devspade...

You have reached the personal website/blog of Brendan Caffrey. Here I will post updates about software and projects I am working on.

Any questions? Please do not hesitate to contact me.

What follows are posts | thoughts | ideas | etcetera. Enjoy.

I’ve started playing with Rails.  So far it looks really great.  I get it.  I do.  The concept of Convention over Configuration – it makes a ton of sense.  Here’s where you lose me Rails:  how can I install/set up/get to ‘Hello World’?

I want to code.  I don’t want to configure right?  Ok, let’s say you’re new to .Net.  What do you do?

  1. Download Visual Studio Express.
  2. File->New Project
  3. Write some code – Response.Write(“Hello World”);
  4. Hit F5
  5. Rejoice!

5 steps.  One of those steps involves hitting a single button and another involves rejoicing.

Now let’s say you’re like me and you want to write a small Hello World Ruby on Rails app using the latest version of Ruby and the latest version of Rails.

Here is what you’ll need to do.  Bit tricky.  Doable yes, but someone (not it!) needs to write a nice wrapped up Windows MSI for this:

  1. Install Ruby from http://rubyforge.org/frs/?group_id=167 (version 1.92-p136 as of this writing). Version is crazy important in rails.  Make sure you tick the box that adds Ruby to your PATH.
  2. Download and install Ruby gems, it’s like apt-get (or er, windows update?). It’s a package manager that lets you download stuff and keep it up to date.
    • Get it here: http://rubyforge.org/frs/?group_id=126 (version 1.5.2 as of this writing)
    • Extract it
    • Figure out where you extracted it.  Open a cmd prompt by going to Start->Run and typing ‘cmd’ and navigate to that directory by typing cd c:\downloads\ruby-gems or whatever  your folder is
    • once you are properly in the folder run ruby setup.rb
  3. Now gem is installed so we can install rails. At the cmd prompt run gem install rails. Pretty easy huh?
  4. Install the Sqlite gem (required to run your first rails ‘hello world’ app, even if you don’t want to use a database at all). For some reason there’s an issue with this on Windows. But it’s pretty easy to get going:
    • At the cmd prompt run gem install sqlite3
    • After the command completes, grab this zip: http://www.sqlite.org/sqlitedll-3_7_3.zip
    • Get the extracted files an place them in your /ruby/bin/ directory where you installed ruby in step 1.
  5. Now we’re ready to create our first app.  At your trusty cmd prompt run rails new /path/to/your/app
  6. Start your rails server by running cd /path/to/your/app followed by rails server. Now you can browse to http://localhost:3000 to see the default rails application
  7. Now Ruby on Rails is fully installed!  Rejoi-er-what about ‘Hello World’?  Ah yes, we still have not written a single line of code.  Well, here’s where Rails shines a bit.  Go back to your trusty cmd prompt and run rails generate controller Greetings hello This will actually generate a controller called ‘Greetings’ with an action/view called ‘hello’.
  8. For this simple example go to /path/to/your/app in Windows Explorer.  Find the /app/controllers sub-directory.  In there you should see your Controller – greetings_controller.rb.  Edit the file in your favorite Ruby on Rails editor to look like this:
    class GreetingsController < ApplicationController
      def hello
    	@message = "Hellow world!"
      end
    end
  9. Now, let's edit our view. Back to the /app/views/greetings/ folder we'll see hello.html.erb. We can edit that to resemble:
    <h1>Greetings#hello</h1>
    <p><%= @message %></p>
  10. Now, at last we can navigate to http://localhost:3000/greetings/hello

So now that I've been up and running with Rails almost a week I still think the setup was far and away the most challenging/least documented part.  Which is what this post will hopefully solve for someone else down the line.  Unfortunately, Rails changes so quickly that this will likely be out of date quite soon.

Ah, yes and lest we forget:

11.  Rejoice

January 2, 2011 | In: Bespin, JavaScript, Skywriter

Writing in the Sky

The folks over at Mozilla Labs have some interesting projects going on.  One I’ve been playing with recently is Skywriter [originally named Bespin, and kudos to you if you got the reference without clicking the link].  The basic premise: it’s an IDE like editor you can add to your web applications.

The effect is pretty impressive so far and they’re not even at version 1.0.  Out of the box it provides a rich looking text editor.  It’s plugin framework provides the ability to extend it even further.

So what’s the negative?  Well the plugin gallery only has 24 plugins as of this writing and most of them are syntax highlighters which is cool but a bit limited.  It uses some advanced HTML5 canvas as well as web workers.  So browser support is relatively limited.  The latest versions of Chrome, Firefox and Safari will be fine.  But if your users have IE or older browsers you had better make sure your app degrades gracefully.

There’s some great docs on the labs site but I  found that when I downloaded the demos they didn’t work right out of the box on my machine because the references to the Javascript files were messed up.

Now that we’ve covered the overview let’s dive in – make sure you’re using one of the supported browsers or the demo’s won’t work.

Semantics

They’ve renamed the project Skywriter – but every file is still called Bespin – for the purpose of this writing I’ll use Bespin.

The Download

The first thing you’ll want to do is download the latest version from the labs site – https://mozillalabs.com/skywriter/.

Once you’ve downloaded and unzipped everything you’ll notice there are quite a few files and directories.  Many of those files are there so you could build your own version of Bespin, plugins you could build into your custom Bespin ,the obligatory docs directory and a directory name prebuilt.

Prebuilt, as the name might indicate, is an already compiled and ready to embed version of Bespin.

Let’s focus on that for now and we’ll worry about building our own Bespin in a future post.

Embedding Bespin in Your Web Page

To make this as generic as possible I am going to demonstrate how to embed a Bespin editor in a page and handle the value on a form submit.  I’ll use straight HTML and Javascript for the demo but of course you can use this in .Net/Java/Php/Ruby etc.

Step 1 – Put the files where they need to be:

From the downloaded Prebuilt directory grab the BespinEmbeded.css,  BespinEmbdedded.js, BespinWorker.js, BespinMain.js and the resources directory and copy them to your project/site folder.

Step 2 – Add the proper references to the <head></head> portion of your page:

You need two lines in the header of your page.  Mine look like the following:

<link id="bespin_base" href="script/bespin"/>
<script type="text/javascript" src="script/bespin/BespinEmbedded.js"></script>

The bespin_base link tag needs to point to the directory where you pasted your bespin files in step 1.  Similarly your script tag includes the BespinEmbedded.js file from step 1.

Step 3 – Add the bespin css class to a div on your page The key here is to make sure you give your div height and width.  The editor needs a known height and width to draw itself.  In my example below I’ve put height and width inline for demonstration purposes

<div id="bespin_editor" class="bespin" style="height:400px; width: 90%"></div>

And, well, that’s it really. You now have a slick looking HTML5 based editor right on your page.  Now we can start using what Bespin brings to the table.  For example, to add HTML syntax highlighting we can add a property to our div:

<div id="bespin_editor" class="bespin" style="height:400px; width: 90%" data-bespinoptions='{"syntax": "html"}'></div>

How to Handle the Editor Value in a Form Post

So now you have a great editor on your page and you want to post your form somewhere to save the data.  The trick I have used is to copy the editor value to a hidden input field.  This way you can treat the value like any of your other form fields – remember your editor is just a div and will not post.

So here’s a little Javascript to do just that:

function UpdateBespinValue(){
  var edit = document.getElementById("bespin_editor");
  var env = edit.bespin;
  var editor = env.editor;
  var hidden = document.getElementById("bespin_value");
  hidden.value = editor.value;
  alert(hidden.value);
}

Next steps:

  • Check out the working demo
  • Download the working demo
  • September 24, 2010 | In: .Net, C#

    Enumerating the Enumerations

    One of the things I find myself using more and more in .Net is the good old Enum.  Very often there are a list of choices for a UI or options for things like object states or statuses that we need to represent in code.  The most readable way to do that is using an Enum. 

    Which is better?

    Constants:

            static void Login()
            {
                switch (status)
                {
                    case "New":
                        Console.Write("Welcoome to our site.");
                        break;
                    case "Active":
                        Console.WriteLine("Welcome back.");
                        break;
                    case "Inactive":
                        Console.WriteLine("Your account is inactive.  Please contact tech support.");
                        break;
                    default:
                        Console.WriteLine("Invalid user and/or password.");
                        break;
    
                }

    Or Enums:

            static void Login()
            {
                switch (status)
                {
                    case UserStatus.New:
                        Console.Write("Welcoome to our site.");
                        break;
                    case UserStatus.Active:
                        Console.WriteLine("Welcome back.");
                        break;
                    case UserStatus.Inactive:
                        Console.WriteLine("Your account is inactive.  Please contact tech support.");
                        break;
                    default:
                        Console.WriteLine("Invalid user and/or password.");
                        break;
    
                }
            }

     

    Advantages of Enums:

    -  When compared to using string constants there is a peformance advantage.  Enums are value types, created on the stack and not the heap.  Translation – it uses fewer resources than strings which are stored on the heap.  Is the advantage significant? No probably not, but it does exist.

    - Intellisense.  Using Enums provides full intellisense support in Visual Studio for your types, categories, colors, statuses, etc.  Don’t underestimate the value of this.

    -Compile time versus runtime checking of values.  At compile you’ll know if the values are valid.  No typos, or at least the risk is greatly reduced, with Enums.

    -Readability.  Great read here about not using "magic numbers" – use Enums instead!!

    [Place holder for snarky conclusion sentence.] Enjoy!

    So you did it.  You drank the MS Kool Aid and decided to go full bore and implement the Asp.Net Membership Provider.

    As with any out of the box solution like the membership provider there are alot of pro’s.  It gives you quite a bit out of the box:

    • Ready made db for storing users, passwords, roles and more
    • Login controls, forgot my password control, etc
    • Lots of API classes to wrap users, roles, etc right out of the box
    • Highly configurable

    Sounds great right?  Now say you’re like alot of developers I know and you have one database for development, possibly localhost.  You probably also have a staging or QA environment where your testers can create 100 users and try to break everything.  Then you have production – the real deal.

    You’ve decided to use the Sql Membership Provider, you right all your code hitting your localhost db.  Everything runs perfect.  All your unit tests pass.  (You’re writing unit tests right?)  Now the move to QA.  Well step 1 is to create the Membership database on QA.  Ok, let’s a assume you can do this or can get a DBA to do this.

    Now what?  All your connection strings point to localhost.  You look at your web.config and ugh – it looks like this:

    <connectionStrings>
      <add name="MySqlConnection"   connectionString="Data Source=localhost;  Initial Catalog=aspnetdb;Integrated Security=SSPI;" />
    </connectionStrings>
    <system.web>
    ...
      <membership defaultProvider="SqlProvider">
        <providers>
          <clear />
          <add
            name="SqlProvider"
            type="System.Web.Security.SqlMembershipProvider"
            connectionStringName="MySqlConnection"
            applicationName="MyApplication"
            enablePasswordRetrieval="false"
            enablePasswordReset="true"
            requiresQuestionAndAnswer="true"
            requiresUniqueEmail="true"
            passwordFormat="Hashed" />
        </providers>
      </membership>

    Ok, cool, I’ll just add a connection string for QA.  Wait, what’s this membership section?  You’re kidding right?  I can only have one connection string for my membership provider?  In short, the answer is yes, you can only have one.

    So what’s the fix?

    The solution is what I like to call complicated simple.  In theory it seems complicated.  In execution it’s actually pretty simple.  You can create your own membership provider and fix the little “bug”.

    Create my own?  But doesn’t that defeat the whole purpose?  not exactly, you create your own, but inherit from all of Microsoft’s classes and only override one very small bit of functionality – the connection string implementation.

    Your new Membership Provider:

    public class MembershipProvider:SqlMembershipProvider
    {
    public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
     {
      base.Initialize(name, config);  
    
      // Update the private connection string field in the base class.
       var connectionString = IAmInQABool ? QAString : DevString;
     // Set private property of Membership provider.
      var connectionStringField = GetType().BaseType.GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
     connectionStringField.SetValue(this, connectionString);
     	}
        }

    Note: For the line where I set the connections string you’ll want to implement your own logic here.  Likely some sort of code to determine what system you’re running on and then grabbing the write connection string from your config file.

    That’s it.  You’ve created your own Membership Provider.  Now all your really did was take everything MS was giving you by default and use a little reflection to override the connection string.  You new provider will work just like the old.  You can still use the login controls and all that good stuff.

    The only last bit of config you’ll need is to update your web.config to not use the default membership provider but yours instead:

    <membership defaultProvider="MembershipProvider">
    	<providers>
    	<clear/>
    	<add name="MembershipProvider" type="MyFullNamespace.MembershipProvider, MyProject"          connectionStringName="ApplicationServices" enablePasswordRetrieval="true"          enablePasswordReset="true" requiresQuestionAndAnswer="false"          requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5"          minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0"          passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/>
    	</providers>
    </membership>
    <profile>
    	<providers>
    	<clear/>
    	<add name="MembershipProvider" type="MyFullNamespace.MembershipProvider, ResellerDashboard"          connectionStringName="ApplicationServices" applicationName="/"/>
    	</providers>
    </profile>

    That’s all there is to it.  Would love to hear if anyone reads this post and implements this solution.

    June 13, 2010 | In: meta

    New look, new feel, new stuff

    I currently drive a blue Honda CRV.  When I first started looking at  buying the car I knew CRV’s were popular.  But to be honest I didn’t notice that many on the road.  And most of the ones I had seen were black or red.  Well of course after having the car for a few months now all I see on the road are blue Honda CRVs.  I can’t go to the mall or the supermarket without almost getting in the wrong car when leaving.  I still love the car.  But I guess I’m not as unique and creative as I thought I was.

    For a few months now I’ve had some ideas for posts on this site.  Every time I started writing I would get frustrated.  I was disappointed with the look/feel of devspade.  I built version 1 using Blog Engine.  I converted a Word Press theme – Inove – to work with Blog Engine.  Much like my CRV, it seems like I have been cruising the internet and am running across a ton of blogs running the Inove theme.

    I kept tweaking and tinkering with small parts of the design.  What ended up happening was I would not write a new post but would end up giving up.

    I’m turning the page.  I found the current design on design disease.  I contemplated converting it to Blog Engine but decided instead to move to Wordpress (more on that in a future post).

    So for now – new look, new feel, new stuff.

    So I haven’t posted here in a bit.  For a variety of reasons.  One of them has been my struggles with BlogEngine which I think I am just now starting to really get down.

    My most recent struggle has been with code syntax highlighting.  If you are a developer and you’re going to blog you will inevitably need to put some code on your blog.  So this was my project – make the code pretty.

    My thoughts on syntax highlighting is keep it simple.  My requirements:

    • The code should look somewhat like code you might see in an IDE or Notepad++ type product.
    • You should be able to copy it to your clipboard very easily

    Solution 1

    So I use BlogEngine, I also mostly use Windows Live Writer for the actual “writing” part so here was my first approach:

    Step 1: Google “blogengine Code syntax highlighting”.

    Step 2:  Do whatever the first link tells me.

    Step 3:  Profit.

    Somewhere along the way I got lost.  I stumbled upon this plugin.  It seemed to be perfect BlogEngine (check), (Live Writer) check and pretty code (check).  Well I found some issues.  It seemed very brittle.  Sometimes I’d edit a post and the code blocks would lose line breaks.  or I’d re-open the post using Live Writer and it would break the code blocks again.

    Solution 2

    So in short solution 1 was no good.  I mean I should have smelled that out from the beginning.  Really, I need C# code just to format some code in an HTML page?  I needed a better solution.  More importantly, I need to change my approach.

    Step 1:  Find the best code syntax highlighter there is.  If I want to put code in an HTML page what should I use?  After some research there are definitely split opinions but goolge-code-prettify is certainly amongst the best so I went with that.

    Step 2:  Has anyone put that to use in BlogEngine before?  How?  Sure enough naspinksi has : http://naspinski.net/post/How-to-use-Google-Code-Prettify-with-BlogEngineNet.aspx.

    Followed those steps almost to the letter and it worked.  (Well I also had to rip out the old Syntax Highlighter Extension code which was tedious and annoying but whatever.)

    Step 3:  Modified my theme style sheet to format the pre tag a bit:

    pre{background:#F4F5F7;      padding:8px 12px 8px 36px;      overflow: scroll; }

    Step 4:  Download and install the Windows Live Writer plugin for google-code-prettify.

    Step 5:  Profit.  (Well, we’re still working on this one.)

    Lesson Learned:

    When you have a problem.  Solve that problem.  Don’t create artificial requirements that will ultimately alter the final solution.  The reality is if naspinksi hadn’t posted about how to incorporate google-code-prettify into BlogEngine I could have figure that out.  Heck, I probably could even write the Live Writer plugin if so inclined.  Those issues were more about the toolset I was using then the original problem I set out to solve.

    My problem was that I needed to format my code samples in the most robust and lightweight method possible.  And now, I’m kind of doing that.

    I came across this question on StackOverflow the other day.  And my first reaction was huh?  My second was, of course!  Brilliant!

    One of the keys to writing effective jQuery is being able to write effective selectors.  It’s really one of those things that you just get better at with experience.  But what happens when you have some common set of selectors you find your self always writing.  Well, you can extend jQuery using custom selectors.

    A simple example:

    Problem:

    You often do form validation in jQuery and you always need to identify empty fields on a form.  Your simple form:

    
    
    
        
        
    
    
    

    Some Form

    Thing 1 Thing 2 Thing 3

    Solution:

    You could write some simple validation function that might look like this:

    function ValidateForm() {
     $('span.validation_error').remove();
     $(':text').each(function() {
        if ($(this).val() == '') {
         $(this).after('*');
        }
      })
    }

    That would work sufficiently.  But wouldn’t it be nicer and more readable to be able to write:

    function ValidateForm() {
     $('span.validation_error').remove();
     $(':textEmpty').each(function() {
      $(this).after('*');
       })
    }

    Unfortunately there is no :textEmpty selector.  But no problem, we’ll just create one:

    $(document).ready(function() {
        $.extend($.expr[':'], {
            textEmpty: function(el) {
                var $el = $(el);
                return ($el.val() == "") && ($el.attr("type") == "text");
            }
        });
    });
    
    function ValidateForm() {
        $('span.validation_error').remove();
        $(':textEmpty').each(function() {
           $(this).after('*');
        })
    }

    Summary:

    As you can see it’s relatively trivial to extend jQuery’s selectors.  Of course you don’t need to have your custom selectors defined in the $(document).ready().  You could just as easily create your own file with all your most commonly used selectors in it.

    And to say this is just the tip of this iceberg is an understatement.  James Padolsey has a great listing of different ways to extend jQuery selectors.

    If you’ve done any good amount of work using the Microsoft CRM Web Service you have most certainly been told on one occasion or another that the “Server is unable to process request”. 

    What does this even mean?  Is the server down?  Does my user not have enough permission?  Did I send the right request?  At some point Microsoft could replace that message with “Uh, somethin’ ain’t right boss”.  That would be equally informative and infinitely more amusing.

    But there is hope.  If you examine the exception you’ll notice it’s a Soap Exception.  We can examine the SoapException.Detail.OuterXML to see more information – messages like “Invalid user” or “The attribute ‘xxxxx’ does not exist on account”.

    The obligatory code sample:

    try {
       CrmService s = GetMyService();
       s.Execute(SomeRequest);
    }
    catch (System.Web.Protocols.SoapException soap_ex)
    {
      Console.WriteLine(soap_ex.Detail.OuterXML);
    }
    catch(System.Exception ex)
    {
      Console.WriteLine(ex.Message);
    }

    I basically divide my work with Microosft CRM into two eras – the first era I call trial and error.  The second I call SoapException.Detail.  Let’s just say the second era was far more productive.

    The Problem

    When my company first looked at Microsoft CRM a few years ago there were two immediate questions.

    1. (From the higher ups) How can we brand Microsoft CRM, so that our users know it as Company ABC CRM?
    2. (From the tech folks)  Can you please give me back the 100 + pixels of screen real estate at the top of the screen?

    As you can see Microsoft is nice enough to insert a massive Microsoft Dynamics CRM logo which takes up a good 15% of your screen real estate and of course kills any chance of branding Microsoft CRM.  Not to mention the fact that the title of every page begins with “Microsoft Dynamics CRM”.

    Solution

    But what can you do?  It’s their sandbox right?  You have to play by their rules.  Well, kind of.  If you followed my previous post, I talked about how we can insert jQuery and our own custom JavaScript file right into Microsoft CRM.  Well, here’s a good example of what this opens up for us.

    In our inserted JavaScript file we could have something like this:

    $(document).ready(function() {    UpdateHeader();});
    
    function UpdateHeader(){    $("FRAMESET").each(function() {    if ($(this).attr("rows") == "112,*") {    $(this).attr("rows", "80,*");    }    });
    
        $("#tdLogoMastHeadBar").css("background-image", "url()").css("font-weight", "bold").height("20px");    if ($("#tdLogoMastHeadBar").html()) {    $("#tdLogoMastHeadBar").html($("#tdLogoMastHeadBar").html().replace("
    ", "&nbsp;")); } $(".ms-crm-MastHead-SignIn-Org").css("margin-left", "7px").css("margin-right","7px").text(""); $("#leftContextTD").height("20px").next("td"); $(".ms-crm-ContextHeader-Title").css("padding-top", "5px"); if(document.title == "Microsoft Dynamics CRM"){ document.title = "ABC Company CRM"; } }

    In this snippet we do 3 basic things:

    1. We find the frame set with the header in it and reduce the rows.  Make it smaller.  Reclaim the real estate.
    2. We clear out the background images, remove some <BR> tags, adjust some margins.  Basically clean up the header to make it more like something we like.
    3. Finally, remove MS’s title in favor of our own.

    And the results will be something like this:


    Summary

    Here we saw an example of how we can use some inserted JavaScript to change the look/feel of Microsoft CRM to fit our needs.  As usual things like this come with the same disclaimer I had on my previous post and of course my overall blog disclaimer.  Good luck!

    If you’ve done any decent amount of customization work with Microsoft CRM (version 3.0 or 4.0) you have probably had to remember all the JavaScript you tried so hard to forget.  Maybe you’re trying to do some advanced form validation or want to do some advanced CSS manipulation.  These things are not very simple and writing dozens and dozens of lines of document.getElementById() can get really irritating.

    But this problem has already been solved now hasn’t it?  We can write rich unobtrusive JavaScript easily using any of the latest JavaScript libraries (see jQuery, MooTools, Scriptaculous, etc).

    How We Do It

    The code is actually pretty simple.  I’ll demonstrate using jQuery here but really you can do this with any of the popular libraries.

    First, download jQuery from http://www.jquery.com.  Or, choose one of the jQuery CDN’s – including Microsoft’s newest one which supports SSL.  If you are downloading the file, place it on your Microsoft CRM server in the ISV directory (e.g. /ISV/MyCompany/jQuery.js).

    Next you’ll need this basic function:

    function load_script (url)
     {
        var x = new ActiveXObject("Msxml2.XMLHTTP");
        x.open('GET', url, false); x.send('');
        eval(x.responseText);
        var s = x.responseText.split(/\n/);
        var r = /^function\s*([a-z_]+)/i; 
    
          for (var i = 0; i < s.length; i++)
          {
              var m = r.exec(s[i]);
              if (m != null)
                  window[m[1]] = eval(m[1]);
          }
      } 

    This will take a script URL and parse out the functions and insert them into your page.  This will allow us to make a call like this to inject jQuery right into Microsoft CRM:

    load_script("/ISV/MyCompany/scripts/jquery-1.3.1.min.js");

    You can paste the function and then put this line in your form load and then use jQuery calls the rest of the way.

    Take It To The Next Level

    One of my biggest frustrations when I got started with Microsft CRM was this concept of pasting my code into some window on their app and hitting “publish”.  As a developer, this was very far from ideal.  Additionally, the only places I could put code was OnLoad and OnSave on Entity Forms.  Well what if I needed more than that?

    So here’s the approach I took.  [Big Disclaimer Here :: Note this is an unsupported Microsoft CRM customization.  Microsoft will potentially break this in updates/upgrades.  They probably will not help you if it breaks your stuff.  They will not talk to you at parties.  It will be awkward.  You have been warned.]

    In version 4.0 of Microsoft CRM there is a file – /_static/common/scripts/Global.js/  This file is loaded in some 90% of their pages.  So I opened the file and pasted the following at the vey very bottom of the file (be careful not to touch anything else in here – see aforementioned disclaimer).  Note there is an equivalent file in 3.0 as well.

    /* Begin Custom Code  */
    
    function load_script (url)
     {
        var x = new ActiveXObject("Msxml2.XMLHTTP");
        x.open('GET', url, false); x.send('');
        eval(x.responseText);
        var s = x.responseText.split(/\n/);
        var r = /^function\s*([a-z_]+)/i; 
    
          for (var i = 0; i < s.length; i++)
          {
              var m = r.exec(s[i]);
              if (m != null)
                  window[m[1]] = eval(m[1]);
          }
      } 
    
        load_script("/ISV/MyCompany/scripts/jquery-1.3.1.min.js");
        load_script("/ISV/MyCompany/scripts/crm_scripts.js");
    
    /* End Custom Code  */

    You probably recognize our load_script function and the call to load jQuery.  The final call loads my own js file into every page.  Now I have a single (or many if your prefer) source controlled file, that I can publish, that has all my custom JavaScript.  The benefits:

    1. File is under source control, allows for easy diffs.
    2. Easy to deploy, do not need to republish MS CRM forms.
    3. Can use custom js now outside of the forms, pretty much anywhere in crm.

     

    In future posts I’ll explore some of the doors this opens and just where we can really take this.