Adding Chrome to browser identification list for Microsoft Ajax

Microsoft Ajax library can identify browser type and version for Firefox, Internet Explorer and Safari. Chrome is missing from this list and it seems Microsoft added Chrome to “init.js” but did not extend Microsoft Ajax. However, as Microsoft Ajax is not limited to SharePoint, you can add Chrome by adding the following code in another JavaScript file (be sure you load the file after Microsoft Ajax is loaded).

(function () {

    function execute() {
        Sys.Browser.Chrome = {};
        var a = navigator.userAgent.toLowerCase();
        if (a.toLowerCase().indexOf("chrome") != -1) {
            Sys.Browser.agent = Sys.Browser.Chrome;
            Sys.Browser.version = parseInt(a.substring(a.indexOf("chrome/") + 7));
        }
    }

    if (typeof (Sys) !== "undefined" && typeof (Sys.Browser) !== "undefined") {
        execute();
    }

})();

And now you can easily identify is browser is Chrome and what version is used.

// Check if browser is Chrome
if (Sys.Browser.agent === Sys.Browser.Chrome) {
    // Alert current Chrome version
    alert(Sys.Browser.agent);
}
Advertisements

Send email using SharePoint API

I see all over examples about how to send emails using SharePoint API. I am not going to reinvent the code, but I am just organizing it into a little bit more object orientated way. And again, Microsoft Ajax library is here to help us. As always, first step is to create the namespace where you want to place the objects.

Type.registerNamespace('Shp.Utility');

Once I done it, I need to create an object containing email properties.

Shp.Utility.EmailProperties = function (to, from, subject, body) {
    /// <summary>Create an instance of Shp.Utility.EmailProperties
    /// <param name="to" type="String" mayBeNull="false" optional="false">To</param>
    /// <param name="from" type="String" mayBeNull="false" optional="false">From</param>
    /// <param name="subject" type="String" mayBeNull="false" optional="false">Email Subject</param>
    /// <param name="body" type="String" mayBeNull="false" optional="false">Email Body</param>
    var e = Function.validateParameters(arguments, [{ name: 'to', type: Array, elementType: String, elementMayBeNull: false, optional: false, mayBeNull: false },
                                                    { name: 'from', type: String, optional: false, mayBeNull: false },
                                                    { name: 'subject', type: String, optional: false, mayBeNull: false },
                                                    { name: 'body', type: String, optional: false, mayBeNull: false }], true);
    if (e) throw e;

    this.to = to;
    this.from = from;
    this.subject = subject;
    this.body = body;
    this.cc = [];
    this.bcc = [];
}

Shp.Utility.EmailProperties.prototype = {


    add_cc: function (cc) {
        /// <signature>
        ///     <summary>Add CC to email properties</summary>
        ///     <param name="cc" type="String" mayBeNull="false" optional="false">CC</param>
        ///     <returns type="Shp.Utility.EmailProperties"></returns>
        /// </signature>
        /// <signature>
        ///     <summary>Add CC to email properties</summary>
        ///      <param name="cc" type="Array" elementType="String" elementMayBeNull="false" mayBeNull="false" optional="false">CC</param>
        ///      <returns type="Shp.Utility.EmailProperties"></</returns>
        /// </signature>
        var e1 = Function.validateParameters(arguments, [{ name: 'cc', type: String, optional: false, mayBeNull: false }], true);
        var e2 = Function.validateParameters(arguments, [{ name: 'cc', type: Array, elementType: String, elementMayBeNull: false, optional: false, mayBeNull: false }], true);
        if (e1 != null && e2 != null) throw e1 || e2;

        var instance = this;
        if (e1 == null)
            instance.cc.push(cc);
        if (e2 == null)
            instance.cc = Array.clone(cc);

        return instance;
    },

    add_bcc: function (bcc) {
        /// <signature>
        ///     <summary>Add CC to email properties</summary>
        ///     <param name="bcc" type="String" mayBeNull="false" optional="false">CC</param>
        ///     <returnts type="Shp.Utility.EmailProperties" />
        /// </signature>
        /// <signature>
        ///     <summary>Add CC to email properties</summary>
        ///     <param name="bcc" type="Array" elementType="String" elementMayBeNull="false" mayBeNull="false" optional="false">CC</param>
        ///     <returnts type="Shp.Utility.EmailProperties" />
        /// </signature>
        var e1 = Function.validateParameters(arguments, [{ name: 'bcc', type: String, optional: false, mayBeNull: false }], true);
        var e2 = Function.validateParameters(arguments, [{ name: 'bcc', type: Array, elementType: String, elementMayBeNull: false, optional: false, mayBeNull: false }], true);
        if (e1 != null && e2 != null) throw e1 || e2;

        var instance = this;
        if (e1 == null)
            instance.bcc.push(bcc);
        if (e2 == null)
            instance.bcc = Array.clone(bcc);

        return instance;

    },

    GenerateRequestBody: function () {
        /// <summary>Generate Ajax request body</summary>
        var instance = this;
        var request = {
            'properties': {
                '__metadata': { 'type': 'SP.Utilities.EmailProperties' },
                'From': instance.from,
                'To': { 'results': instance.to },
                'CC': { 'results': instance.cc },
                'BCC': { 'results': instance.bcc },
                'Body': instance.body,
                'Subject': instance.subject
            }
        }
        return JSON.stringify(request);
    }

}

Shp.Utility.EmailProperties.registerClass('Shp.Utility.EmailProperties');

Here is actually the point where the code is simplified. Creating email properties object makes you write less code in the Ajax call. Generate request body method is using all necessary properties of the object to create string representation of JSON object to be used as the request body.

var from = 'someone@domain.com';
var body = 'Email body'; // Pay attention, you might need to encode it
var subject = 'Email subject';
var to = ['person1@domain.com', 'person2@domain.com'];

// Create email properties object
var emailProperties = new Shp.Utility.EmailProperties(to, from, subject, body);

// Add CC and BCC
emailProperties.add_cc(['person3@domain.com', 'person4@domain.com']);
emailProperties.add_bcc(['person3@domain.com', 'person4@domain.com']);

// Forgot to add someone, no worries 
// Passing a string instead of array of strings makes the method not to act like a setter. Instead is adding email to CC or BCC field.
emailProperties.add_cc('forgotten@domain.com');
emailProperties.add_bcc('forgotten@domain.com');

Now, as we have the object containing the email properties, is time to handle the Ajax call.


Shp.Utility.Email = function () {
    /// <summary>Shp.Utility.Email static class</summary>
    throw 'You cannot initialize an instance of Shp.Utility.Email static class';
}


Shp.Utility.Email.SendEmail = function (emailProperties, success, fail) {
    /// <summary>Send an email using SharePoint API</summary>
    /// <param name="emailProperties" type="Shp.Utility.EmailProperties" optional="false" mayBeNull="false">Email Properties</param>
    /// <param name="success" type="Function" optional="false" mayBeNull="false">Success</param>
    /// <param name="fail" type="Function" optional="true" mayBeNull="false">Fail</param>
    var e = Function.validateParameters(arguments, [{ name: 'emailProperties', type: Shp.Utility.EmailProperties, optional: false, mayBeNull: false },
                                                    { name: 'success', type: Function, optional: false, mayBeNull: false },
                                                    { name: 'fail', type: Function, optional: true, mayBeNull: false }], true);
    if (e) throw e;


    Shp.Utility.Email._SendEmail(emailProperties, success, fail || function (errCode, errText) {
        alert('Send email Ajax call failed with error code ' + errCode + ':' + errText);
    });
}

Shp.Utility.Email._SendEmail = function (emailProperties, success, fail) {
    var ajax = new Sys.Net.WebRequest();
    ajax.set_url(_spPageContextInfo.webServerRelativeUrl + '/_api/SP.Utilities.Utility.SendEmail');
    ajax.set_httpVerb('POST');
    ajax.set_body(emailProperties.GenerateRequestBody());
    ajax.get_headers()['Accept'] = 'application/json;odata=verbose';
    ajax.get_headers()['Content-Type'] = 'application/json;odata=verbose';
    ajax.get_headers()['X-RequestDigest'] = $get('__REQUESTDIGEST').value;

    ajax.add_completed(function (executor, eventArgs) {
        if (executor.get_statusCode() >= 200 && executor.get_statusCode() < 300 && executor.get_responseAvailable() === true) {
            success(executor.get_responseData());
        }
        else {
            alert('Ajax failed with error code ' + executor.get_statusCode() + ':' + executor.get_responseData());
        }
    });

    ajax.invoke();
}

Shp.Utility.Email.registerClass('Shp.Utility.Email');

This class is very simple. It contains a method called “SendEmail” which accepts 3 arguments:

  • Email properties, which is the object created before
  • A function to be executed if Ajax is successfully, which accept obtained data from server as parameter.
  • A function to be executed if Ajax fails. This function accepts error code and error text as parameters, but is not mandatory. If not specified, an alert containing this information is shown.

As an example, check the code below.

Shp.Utility.Email.SendEmail(emailProperties, function (data) {
    // Do something with data
});

There one important thing I need to mention. It seems you can send emails only to the users registered to the SharePoint. If not registered, the user won’t receive emails, but the email doesn’t fail as the rest of registered users will receive it.

There is always a way to improve the code and if you have suggestions, please let me know. 🙂