Thursday, June 12, 2014

Identify MS CRM 2013 Environment by different colors

 NOTE: THIS IS TOTALLY UNSUPPORTED MS CRM 2013 CUSTOMIZATION.  BEFORE DOING THESE CHANGES, PLEASE TAKE COPY OF FILES, MENTIONED IN THIS ARTICLE.

Change Microsoft Dynamics CRM text with company name
JavaScript File:  /_controls/NavBar/NavBar.css.aspx
·         Open CSS file
·         Look for  .navigationControl
·         Set background-color to color you like.
·         Save Changes
·         Clear Browser cache
·         Your new text will be shown. 

Before

After


Change "Microsoft Dynamics CRM" text For MS CRM 2013

NOTE: THIS IS TOTALLY UNSUPPORTED MS CRM 2013 CUSTOMIZATION.  BEFORE DOING THESE CHANGES, PLEASE TAKE COPY OF FILES, MENTIONED IN THIS ARTICLE.


Change Microsoft Dynamics CRM text with company name
JavaScript File:  /_static/_controls/NavBar/NavBar.js
·         Open JS file
·         Look for  Span id “navTabLogoTextId

span id="navTabLogoTextId" class="navTabLogoText">Your Custom Text  /span

·         This span is in two functions, replace in both
Mscrm.TabLogoImageBuilder.prototype
Mscrm.TabLogoButtonBuilder.prototype
·         Save Changes
·         Clear Browser cache / restart IIS

·         Your new text will be shown. 

Before 


After


Wednesday, June 11, 2014

Mask Phone number, Date fields in CRM

NOTE: THIS IS UNSUPPORTED CRM 2013 CUSTOMIZATION.

For Complete code check https://maskedinputcrm2013.codeplex.com

To provide masking for input fields in CRM form we can use jQuery masked input plugin.
 Using this plugin we can easily add masking for not only phone number, fax, date fields but also we can add masking for like SSN number, driving license number etc.
Also when adding this masking, this plugin is already taking care of inputs validation like phone number should contain only numbers.
 We can add our own formats also using this plugin. For more details about this plugin, Check  http://digitalbush.com/projects/masked-input-plugin/
For CRM implementation
·         Download minified masked input plugin file from https://raw.github.com/digitalBush/jquery.maskedinput/1.3.1/dist/jquery.maskedinput.min.js
·         Add this JS file to CRM web resources.
·         Create new JavaScript web resource and add following code in that file
var CustomMaskScript = {
    MaskInputField: function (fieldName, format) {       
        var control = Xrm.Page.getControl(fieldName);
        if (control != null && control.getControlType() == 'standard') {
            control.setFocus();
            if (Xrm.Page.getAttribute(fieldName).getAttributeType() == 'datetime') {
                var input = $("#" + fieldName + "_i").find("input");
                if (input != null)
                    input.mask(format);
            } else
                $("#" + fieldName + "_i").mask(format);
        }
    },
};


·         Now add both file in entity form library where you want to use masking

  •   Call MaskInputField function on load of Form with attribute name and Format as parameters.

'new_birthdate','99/99/9999'
·         Save and publish customization.
·         And maked input is ready to use

Above example is for manual masking for fields which we can to add masking.

If by default we want to add masking for all phones and date attributes on Form then use following script

var DefaultMask = {
    MASK_date: '99/99/9999',
    MASK_Phone: '(999) 999-9999',

    MaskDatePhoneInput: function () {
        var PageAttributes = Xrm.Page.data.entity.attributes.get();
        var fieldName = '';
        var Format = '';
        for (var i in PageAttributes) {
            var control = PageAttributes[i].controls.get(0);
            fieldName = PageAttributes[i].getName();
            Format = PageAttributes[i].getFormat();
            if (Format == 'phone' || Format == 'date') {
                control.setFocus();
                if (PageAttributes[i].getAttributeType() == 'datetime') {
                    var input = $("#" + fieldName + "_i").find("input");
                    if (input != null)
                        input.mask(ContactDefaultMask.MASK_date);
                } else
                    $("#" + fieldName + "_i").mask(ContactDefaultMask.MASK_Phone);
            }
        }
    },
}
Add this in JS web resources and call function on load.  This will add masking for all phone number and date fields on Form.

Here are some examples of masking 
·         Date
Without Mask:

With Mask

Mask Format:  99/99/9999

·         Phone number
Without Mask:


With Mask


Mask Format:  (999) 999-9999

·         Phone number with Extension
Without Mask:


With Mask


Mask Format:  (999) 999-9999? X99999

·         Social Security Number
Without Mask:


With Mask


Mask Format:  999-99-9999

·         Custom (e.g. Wisconsin Driving license)
Without Mask:


With Mask


Mask Format:  a-9999999999


For Complete code check https://maskedinputcrm2013.codeplex.com



Wednesday, May 14, 2014

Address autocomplete for CRM 2013

Google is providing free services for address lookup using Google Places.
We can implement address lookup using google places into CRM 2013.
NOTE: THIS IS UNSUPPORTED CRM 2013 CUSTOMIZATION.

For Code check https://addressautolookup.codeplex.com

To implement address lookup in CRM 2013, we need to add two JavaScript files into CRM.
And need to call “PopulateAddresses” function on load event.
Here are step by step details
  •  Create First JavaScript web resource with name “GoogleJsapi.js”

You will find this script by browsing http://www.google.com/jsapi
Copy script to our GoogleJsapi.js file.
  • Create another JavaScript web resource with name “GoogleAddressAutocomplete.js”

This is custom script we have to create. To add autocomplete functionality for CRM attributes.
function PopulateAddresses() {

    //If google library not loaded then settime
    if (google == null) {
        google.load("maps", "3", { other_params: "libraries=places&sensor=false", "callback": PopulateAddresses });
        setTimeout(PopulateAddresses, 2000);
        return;
    }
    //If google library loaded but google maps libray not loaded then add those and settime to recall same function again
    if (google != null && google.maps == null) {
        google.load("maps", "3", { other_params: "libraries=places&sensor=false", "callback": PopulateAddresses });
        setTimeout(PopulateAddresses, 2000);
        return;
    }
    //if google map places is undefined then recall function after some time..
    if (google.maps.places == null) {
        setTimeout(PopulateAddresses, 2000);
        return;
    }

    //Get input control for Google places  
    var autocomplete;         
    var control = Xrm.Page.getAttribute('address1_composite').controls.get(0);
    if (control != null) {
        control.setFocus();
        //var input = $("#" + attributeName + "_i")
        var input = $("#address1_composite_compositionLinkControl_address1_line1_i");

        /*Sometimes google places list is not showing thats why need to add this style*/
        var pacContainerInitialized = false;
        input.keypress(function () {
            if (!pacContainerInitialized) {
                $('.pac-container').css('z-index', '9999');
                pacContainerInitialized = true;
            }
        });

        //add input to google autocomplete
        autocomplete = new google.maps.places.Autocomplete(document.getElementById('address1_composite_compositionLinkControl_address1_line1_i'));
    }

   
    /* Set up event listener for place selection */
    google.maps.event.addListener(autocomplete, 'place_changed', function () {
        /* Get place details */
        var place = autocomplete.getPlace();
        if (!place.geometry) {
            return;
        }
        /* Loop through the address components for the selected place and fill
         the corresponding input fields in CRM */

        var houseNumber, StreetName, city, state, Zip, Country;

        for (i = 0; i < place.address_components.length; i++) {

            var type = place.address_components[i].types[0];
            if (type == 'street_number') {
                houseNumber = place.address_components[i].long_name + "";
            }
            if (type == 'route') {
                StreetName = place.address_components[i].long_name;
            }
            if (type == 'locality' || type == 'administrative_area_level_3') {
                city = place.address_components[i].long_name;
            }
            if (type == 'postal_code') {
                Zip = place.address_components[i].long_name;
            }
            if (type == 'administrative_area_level_1') {
                state = place.address_components[i].short_name;
            }
            if (type == 'country') {
                Country = place.address_components[i].long_name;
            }
        }
            Xrm.Page.getAttribute('address1_line1').setValue(houseNumber);
            Xrm.Page.getAttribute('address1_line2').setValue(StreetName);
            Xrm.Page.getAttribute('address1_city').setValue(city);
            Xrm.Page.getAttribute('address1_postalcode').setValue(Zip);
            Xrm.Page.getAttribute('address1_stateorprovince').setValue(state);
            Xrm.Page.getAttribute('address1_country').setValue(Country);
    });

}
  •        Add both Scripts to CRM address ( Account/contact/ lead) entity.
  •  Add onload event
  • Call PopulateAddresses function. 





  • For google autocomplete HTMLInput type element is required.

But in CRM 2013 we will not get directly HTMLInput element for any attribute directly.
CRM 2013 is uing inline input element, so when we click on any attribute on form then dynamically input field is generated and displayed on Form.
For this we can us control.setFocus();  CRM function. When focus is set on field then we will get input element as “attributename_i”
var control = Xrm.Page.getAttribute('address1_composite').controls.get(0);
    if (control != null) {
        control.setFocus();
        //var input = $("#" + attributeName + "_i")
        var input = $("#address1_composite_compositionLinkControl_address1_line1_i");

 and then call google autocomplete
autocomplete = new google.maps.places.Autocomplete(document.getElementById('address1_composite_compositionLinkControl_address1_line1_i'));

  • Save Customization
  • Publish your customization.
  •  Now open any account/ contact or lead form
  • Click on Address Composite control


I



  • Start typing in Street1 field, because we added google place autocomplete on this field

address1_composite_compositionLinkControl_address1_line1_i

I



  • Select required address
  • The selected address will be populated in address fields




For more information on GOOGLE places



Tuesday, February 25, 2014

Total record count in MS CRM grid

By default CRM is not giving total number of records for entity in grid. If there are more than 5000 records, then CRM will display 5000+ records and when you navigate through 5000+ then count is changing per page size.
If want to show count of total number of records in grid, then need to modify database values.
Steps:
1.       Open MSCRM_CONFIG database in SQL server management studio

select * from DeploymentProperties where ColumnName ='TotalRecordCountLimit'

2.       In this table IntColumn default value is 5000.
3.       Update IntColumn value to -1

Update DeploymentProperties Set IntColumn=-1 Where ColumnName = 'TotalRecordCountLimit'

4.       When using -1, then CRM will take count of all records.
5.       If don’t want all records, but want say 15000 records count then update IntColumn value to number of record count want.
6.       Reset IIS.

7.       Try now.. 

Before



After