API Version: 6.4

Using the Addressbook

Downloads

Explained

This sample is intended to be similar to the Contact samples, except that using the addressbook is a little more complex. This is because:
  • Contacts only represent IPCortex Communication System (CS) users
  • Addressbook entries can represent several data types
    • Contact
    • Addressbook number (eg. external number)
    • Park orbits
    • XMPP chat contacts
  • Addressbook entries can be dynamically added and removed
The Address class provides a common interface to all of the above: indicating whether each record is 'chattable' or 'callable', and masking the details of the devices that the address comprises. In keeping with this, there is a single BLF state (whether the contact is in a call) representing all of the devices
Loading the addressbook causes additional system load, so is an optional feature. It is called by using:
IPCortex.PBX.getAddressbook(callback);
It can be used in two ways. With no callback provided, it will return a Promise which will resolve with the current addressbook as an Array, and will not be updated.
If a callback is provided, it will be called with two Arrays of 'added' and 'removed'. The initial response will be a full addressbook returned in 'added' and an empty list in 'removed'. The callback can be called repeatedly by the API if it detects an addressbook change, and will send only new items in 'added' or removed items in 'removed'.
To keep this sample slightly more simple, the Promise variant is used.
In this sample, once the API is initialised we use getAddressbook() and display the results by simply injecting them into a list tag as list items. Note the use of Address.sortFn() to help sort the result into alphabetical order.
function runApp() {
    /* Inject the list of contacts into the page */
    var listElement = document.getElementById('list');
    IPCortex.PBX.getAddressbook().then(function(addressbook) {
        /* use the provided sort-helper to order the addressbook */
        console.log(TAG, "Addressbook loaded");
        addressbook.sort(function(a,b) {return a.sortFn(b);});

        /* Insert into page */
        addressbook.forEach(function (address) {
            var addressElement = document.createElement('li');
            addressElement.innerHTML = '<a href="#">' +
                        '<i class="material-icons notcallable">phone_missed</i> ' +
                        '<i class="material-icons notchattable">chat_bubble_outline</i> ' +
                        '<i class="material-icons">call_end</i> ' +
                        address.name +
                        '</a>';
            listElement.appendChild(addressElement);
            var icons = addressElement.getElementsByTagName('i');
            address.addListener('update', function (a) {
                /* Each time this address entry is updated, this method will be called.
                 * the icons variable is scoped locally, so will remain in scope
                 * meaning that this callback will have access to the right icons to
                 * update.
                 */
                processAddress(a, icons);
            });
            processAddress(address, icons);
        });
    }).catch(function(e) {
        console.log(TAG, "Error fetching addressbook", e);
    });
}
Once each addresss is added to the list, its icon is set with processAddress() (below), and an update listener registered. The processAddress() function is designed to both set the initial state of the addressbook icons and to update it if anything changes. In this case, we update:
  • Callable state (from address.canCall)
  • Chattable state (from address.canChat)
  • BLF State (from address.blf)
function processAddress(a, icons) {
        /* prepare a list of icon names for the states: idle, busy, ringing, busy+ringing */
        var states = ["call_end", "phone", "ring_volume", "phone"];

        /* Initial setup or update calls this function */
        if ( a.canCall ) {
                icons[0].className = 'material-icons callable';
                icons[0].innerHTML = 'phone';
        } else {
                icons[0].className = 'material-icons notcallable';
                icons[0].innerHTML = 'phone_missed';
        }
        if ( a.canChat ) {
                icons[1].className = 'material-icons chattable';
                icons[1].innerHTML = 'chat_bubble';
        } else {
                icons[1].className = 'material-icons notchattable';
                icons[1].innerHTML = 'chat_bubble_outline';
        }
        icons[2].innerHTML = states[a.blf];
}