Tom Hollander's blog

patterns, practices and pontification

Integrate Lync into your intranet sites using the NameCtrl plug-in

Integrate Lync into your intranet sites using the NameCtrl plug-in

Rate This
  • Comments 3

Introduction

If you’re a regular user of both SharePoint and Lync, you’ve probably seen that SharePoint integrates with Lync by showing users’ presence on the page, and giving you a nice hover dialog allowing you to collaborate with them. But did you know that you can add the same capabilities to your own intranet sites? And did you know it can work on Firefox and Chrome as well as in Internet Explorer? Even if you knew it was possible, chances are you haven’t found it easy, since the documentation is frankly pretty awful.

clip_image001

Now before I go any further, yes this approach relies on plug-ins, and yes we all know that isn’t the way of the future. Very soon it will become much easier to integrate Lync presence into web apps using the new Unified Communications Web API (UCWA) which will ship as an update to Lync Server 2013. However even with that coming, there is still value in client-side plug-ins, and the integration with the Lync client you get with the plug-in approach does provide a very nice experience.

You can download a working sample showing everything I discuss in the post here. Important: I’ve made this available as a downloadable HTML file instead of hosting it on a web server as it won’t work in the Internet zone anyway. However after downloading you’ll need to right-click the file, choose Properties and Unblock before your browser will launch the plug-ins and scripts.

It’s not the most beautiful web code you’ll come across (nor has it been extensively tested) but I wanted to show all of the key concepts in one file without any unnecessary complexity.

Prerequisites

There are a few things required for this approach to work. If you can’t rely on all of these, make sure you do defensive coding to fall back gracefully when the plug-in isn’t available.

  • Your users will need Lync installed and be signed in
  • The NameCtrl plug-in must be properly registered. This should happen automatically when Lync is installed.
  • Your users will need to be using a supported web browser. I don’t know the official support matrix, but with Lync 2013 installed and the site coded correctly it works with Internet Explorer, Firefox and Chrome on Windows. I don’t know if it works on non-IE browsers with versions prior to Lync 2013 (let me know!).
  • Your web site must be in Internet Explorer’s Intranet or Trusted Sites security zone (even if being accessed from a different browser). This may sound like a big restriction, but in practice you’ll probably only want to do this on intranet sites anyway.

Initialising the Plug-In

The NameCtrl plug-in exposes the same API to all browsers, but the way you initialise it is different on different browsers.

On Internet Explorer, you need to create an ActiveX object of the type NameCtrl of the class “Name.NameCtrl”:

nameCtrl = new ActiveXObject("Name.NameCtrl");

On Chrome and Firefox you need an <object> tag to initialise the plug-in:

<object id="application/x-sharepoint-uc" type="application/x-sharepoint-uc" width="0" height="0" style="visibility: hidden;"></object>

My demo code (based on a simplified version of what ships with SharePoint 2013) to initialise using the correct approach based on the browser is as follows:

var nameCtrl = null;

$(document).ready(function () {

    try {
        if (window.ActiveXObject) {
            nameCtrl = new ActiveXObject("Name.NameCtrl");

        } else {
            nameCtrl = CreateNPApiOnWindowsPlugin("application/x-sharepoint-uc");
        }
        attachLyncPresenceChangeEvent();
    }
    catch (ex) { }
});


function IsSupportedNPApiBrowserOnWin() {
    return true; // SharePoint does this: IsSupportedChromeOnWin() || IsSupportedFirefoxOnWin()
}

function IsNPAPIOnWinPluginInstalled(a) {
    return Boolean(navigator.mimeTypes) && navigator.mimeTypes[a] && navigator.mimeTypes[a].enabledPlugin
}

function CreateNPApiOnWindowsPlugin(b) {
    var c = null;
    if (IsSupportedNPApiBrowserOnWin())
        try {
            c = document.getElementById(b);
            if (!Boolean(c) && IsNPAPIOnWinPluginInstalled(b)) {
                var a = document.createElement("object");
                a.id = b;
                a.type = b;
                a.width = "0";
                a.height = "0";
                a.style.setProperty("visibility", "hidden", "");
                document.body.appendChild(a);
                c = document.getElementById(b)
            }
        } catch (d) {
            c = null
        }
    return c
}

Subscribing to Presence Updates

Once you’ve initialised your plug-in, you can use it to check the presence for any number of users. Doing this properly takes a few steps:

  • Subscribe to the plug-in’s OnStatusChange event
  • Call the plug-in’s GetStatus method for each user whose presence you are interested in
  • In the OnStatusChange event, update your UI (for example to change the presence icon or colour) based on the reported user’s new presence.

There are a few tricks here which I figured out the hard way:

  • When you call GetStatus the first time, you probably won’t get the user’s actual presence back. Really this method is used to tell the plug-in you want to subscribe to a user. The correct presence value will be returned asynchronously in the OnStatusChange event handler.
  • The GetStatus method takes two parameters. The first is the SIP address (typically the same as their email address) of the user you are subscribing to. The documentation says that the second parameter is “a string that identifies the HTML <DIV> tag to update with the correct pawn icon”. I’ve never got this to work, and in any event I prefer to control my own UI rather than have the plug-in decide how it should look. In my tests, you can use any value for this string in Internet Explorer however it won’t work in Chrome or Firefox if you use an empty string (but other random strings worked fine).
  • The OnStatusChange event handler gives you three parameters. The docs say (accurately enough): “The first parameter is the sign-in name of the user, the second parameter is the new status, and the third parameter is the same ID that is passed to the GetStatus method.” The presence value returned in the second parameter is numeric; the docs have a partial list but see my code snippet below for some other values that may be returned.

So, with that out of the way, here’s my code to subscribe to users’ presence and update the UI (using CSS classes) when their presence changes:

function addUser() {
    var userName = $('#userName').val();
    var userElementId = getId(userName);
    $('<div/>', {
        text: userName,
        id: userElementId,
        class: 'user',
        onmouseover: "showLyncPresencePopup('" + userName + "', this)",
        onmouseout: "hideLyncPresencePopup()",
    }).appendTo('#users');

    if (nameCtrl) {
        nameCtrl.GetStatus(userName, 'users');
    }
    $('#userName').val('');
}

function getLyncPresenceString(status) {

    switch (status) {
        case 0:
            return 'available';
            break;
        case 1:
            return 'offline';
            break;
        case 2:
        case 4:
        case 16:
            return 'away';
            break;
        case 3:
        case 5:
            return 'inacall';
            break;
        case 6:
        case 7:
        case 8:
        case 10:
            return 'busy';
            break;
        case 9:
        case 15:
            return 'donotdisturb';
            break;
        default:
            return '';
    }
}

function attachLyncPresenceChangeEvent() {
    if (!nameCtrl) {
        return;
    }
    nameCtrl.OnStatusChange = onLyncPresenceStatusChange;
}

function onLyncPresenceStatusChange(userName, status, id) {
    var presenceClass = getLyncPresenceString(status);

    var userElementId = getId(userName);
    var userElement = $('#' + userElementId);
    removePresenceClasses(userElement);
    userElement.addClass(presenceClass);

}

function removePresenceClasses(jqueryObj) {
    jqueryObj.removeClass('available');
    jqueryObj.removeClass('offline');
    jqueryObj.removeClass('away');
    jqueryObj.removeClass('busy');
    jqueryObj.removeClass('donotdisturb');
    jqueryObj.removeClass('inacall');
}

function getId(userName) {
    return userName.replace('@', '_').replace('.', '_');
}

Showing and Hiding the Lync contact card

One final thing you can do with the plug-in is have it show a Lync contact card for a given user. This is useful as the contact card shows additional information about a user (full name, location, phone number, org chart, etc), and also allows you to interact them using any Lync modality (IM, phone, video, etc).

Showing and hiding the contact card is pretty straightforward: the ShowOOUI method shows it, and the HideOOUI method hides it. You just need to wire it up to an appropriate event (typically onmouseover and onmouseout respectively).

The trick is getting it to display in the right place. Without going into all of the details, here is some code which I’ve found to work pretty well:

function showLyncPresencePopup(userName, target) {
    if (!nameCtrl) {
        return;
    }

    var eLeft = $(target).offset().left;
    var x = eLeft - $(window).scrollLeft();

    var eTop = $(target).offset().top;
    var y = eTop - $(window).scrollTop();

    nameCtrl.ShowOOUI(userName, 0, x, y);
}

function hideLyncPresencePopup() {
    if (!nameCtrl) {
        return;
    }
    nameCtrl.HideOOUI();
}

Conclusion

So there you have it. If your organisation uses Lync, hopefully you’ve noticed how awesome it is. But it’s even awesomer (yes, I know that isn’t a word) if you can launch it exactly when you need it, which is often when using some intranet site or line-of-business application which tells you which people you need to communicate with. Even as we slowly move toward a plug-in-free world, it’s important to keep in mind what’s possible with the technology you already have deployed, and use it to create the best experiences you can.

  • Great! Thanks a lot!

    I have the same opinion as you do about using NameCtrl (+ plug-in) for now.

    UCWA might be solution for later when most customers start using Lync 2013, but with UCWA we will have to develop not only the control presence bubble but also UI for the contact card and that is changing with every Lync/Office release.

    I think that the best solution would be drag-and-drop HTML presence control but ...Maybe with Lync 16.

    I tested your plug-in sample on IE9, IE10(desktop mode), Firefox, Chrome and Safari and it works!

    On Firefox you have to hover over to get the presence state updated.

    It doesn’t work though on IE10 immersive mode - are you aware of that?

    Regards,

    Sanja

  • Hi Sanja -

    Thanks for doing some extra testing for me (I don't have Safari installed). In Firefox (19.0.1) I'm getting presence updates without needing to hover, so I'm not sure what's happening with you.

    IE10 does not run plug-ins in immersive mode (nor does Safari on iOS) so this solution will not work there. UCWA is probably going to be your best bet to target those platforms.

    Tom

  • Hi Tom,

    Thank you for your prompt reply.

    Once I updated Firefox to the version 19 presence state is immediately updated, no need to hover over.

    I have Office/Lync Client 2013 and Lync Server 2010 and your NameCtrl plug-in works fine on Firefox, Chrome, Safari and Internet Explorer 9 and 10 (desktop mode) both on Windows 7 and 8.

    On the machines with Office/Lync Client 2010 it doesn’t work for any other browser than Internet Explorer.

    Regards,

    Sanja

Page 1 of 1 (3 items)