How to set up x-bees contacts page on a website

This Guide explains how to set up x-bees contacts page using a script, with an example available at https://www.wildix.com/contacts/.

Created: September 2024

Permalink: https://wildix.atlassian.net/wiki/x/VAbOAQ

Requirements

  • jQuery
  • Web skills: Basic knowledge of HTML, CSS and JavaScript to implement and customize the contact cards 

Setup steps

Step 1. Insert x-bees script

  • Insert x-bees script globally on your website or on a specific page where you want to display contact cards: 

     Click here to expand...
    <script>
    (function ($) {
    jQuery.fn.kiteContact = function (options) {
    
    var _extensions = {};
    
    var kiteUrl = 'https://kite.wildix.com';
    var xbeesUrl = 'https://x-bees.biz';
    
    var settings = {
    statusImages: {
    'online': 'https://www.wildix.com/wp-content/uploads/2022/10/online-1.webp', 
    'offline': 'https://www.wildix.com/wp-content/uploads/2022/10/offline.jpeg',
    'talking': 'https://www.wildix.com/wp-content/uploads/2022/10/talking.webp',
    'ringing': 'https://www.wildix.com/wp-content/uploads/2022/10/ringing-now.webp',
    'away': 'https://www.wildix.com/wp-content/uploads/2022/10/away.webp',
    'away-offline': 'https://www.wildix.com/wp-content/uploads/2022/10/awayoffline.jpeg',
    'dnd': 'https://www.wildix.com/wp-content/uploads/2022/10/dnd.webp',
    'dnd-offline': 'https://www.wildix.com/wp-content/uploads/2022/10/dndoffline.webp'
    }, 
    updateInterval: 1000 * 10
    };
    
    
    var methods = {
    _timeout: {},
    _timeoutCounter: {},
    
    _updatePresence: function (serial) {
    if (this._timeoutCounter[serial] == undefined) {
    this._timeoutCounter[serial] = 0;
    }
    
    if (!this._timeoutCounter[serial]) {
    $.ajax({
    url: kiteUrl + '/' + serial + '/' + _extensions[serial] + '/api/presence',
    type: 'GET',
    cache: false,
    dataType: 'jsonp',
    timeout: 10 * 1000,
    success: jQuery.proxy(this._onAjaxSuccess, this, serial),
    error: jQuery.proxy(this._onAjaxError, this, serial),
    complete: jQuery.proxy(this._onAjaxComplete, this, serial)
    });
    }
    },
    
    _popitup: function (mypage, w, h, pos, myname, infocus) {
    if (w != parseInt(w) || w <= 0) w = $width;
    if (h != parseInt(h) || h <= 0) h = $height;
    if (myname == null) {
    myname = "swin"
    }
    ;
    var myleft = 0;
    var mytop = 0;
    if (myleft == 0 && mytop == 0 && pos != "random") {
    pos = "center"
    }
    ;
    if (pos == "random") {
    myleft = (screen.width) ? Math.floor(Math.random() * (screen.width - w)) : 100;
    mytop = (screen.height) ? Math.floor(Math.random() * ((screen.height - h) - 75)) : 100;
    }
    if (pos == "center") {
    myleft = (screen.width) ? (screen.width - w) / 2 : 100;
    mytop = (screen.height) ? (screen.height - h) / 2 : 100;
    }
    settings = "width=" + w + ",height=" + h + ",top=" + mytop + ",left=" + myleft + ",scrollbars=no,location=yes,directories=no,status=no,menubar=no,toolbar=no,resizable=no";
    swin = window.open(mypage, myname, settings);
    if (infocus == null || infocus == "front") {
    swin.focus()
    }
    ;
    return false;
    },
    
    _onAjaxSuccess: function (serial, data, textStatus, jqXHR) {
    var self = this;
    if (data.type == "result") {
    $.each(_extensions[serial], function (index, extension) {
    var presence = {};
    var file = 'offline.jpeg';
    
    if (data && data.result) {
    if (data.result.hasOwnProperty(extension)) {
    // multiple presences
    file = self._getPresenceImage(data.result[extension]);
    } else if (data.result.hasOwnProperty('online')) {
    // one presence
    file = self._getPresenceImage(data.result);
    }
    }
    
    $('.contact[serial="' + serial + '"][extension="' + extension + '"] .presence').attr('src', file);
    });
    
    } else {
    console.log('Error (' + serial + '): ' + data.reason);
    this._resetPresence(serial);
    }
    this._timeoutCounter[serial] = 0;
    },
    
    _onAjaxError: function (serial, jqXHR, textStatus, errorThrown) {
    console.log("Error: " + textStatus + ' ' + errorThrown, serial);
    if (textStatus == 'timeout') {
    if (this._timeoutCounter[serial] == 2) {
    this._resetPresence(serial);
    }
    this._timeoutCounter[serial]++;
    } else {
    this._timeoutCounter[serial] = 0;
    this._resetPresence(serial);
    }
    },
    
    _onAjaxComplete: function (serial, jqXHR, textStatus) {
    
    if (this._timeout && this._timeout[serial]) {
    clearTimeout(this._timeout[serial]);
    }
    this._timeout[serial] = setTimeout(this._updatePresence.bind(this, serial), settings.updateInterval);
    },
    
    
    _getPresenceImage: function (presence) {
    var status = 'offline';
    if (presence) {
    var online = presence['online'];
    var show = presence['show'];
    var deviceShow = presence['device_show'];
    
    if (deviceShow == 'talking' || deviceShow == 'tr') {
    status = 'talking';
    } else if (deviceShow == 'ringing') {
    status = 'ringing';
    } else if (show == 'away') {
    status = online ? 'away' : 'away-offline';
    } else if (show == 'dnd') {
    status = online ? 'dnd' : 'dnd-offline';
    } else {
    status = online ? 'online' : 'offline';
    }
    }
    return settings.statusImages[status];
    },
    
    _resetPresence: function (serial) {
    $.each(_extensions[serial], function (index, extension) {
    $('.contact[serial="' + serial + '"][extension="' + extension + '"] .presence').attr('src', settings.statusImages['offline']);
    
    });
    },
    
    
    _onOpenKite: function (e) {
    var contact = $(e.currentTarget).closest('.contact');
    var serial = contact.attr('serial');
    var extension = contact.attr('extension');
    var email = contact.attr('email');
    var kiteid = contact.attr('kiteid');
    console.log(kiteid);
    console.log(typeof kiteid);
    
    if (typeof kiteid !== 'undefined') {
    var url = xbeesUrl + '/kite/' + kiteid;
    } else {
    var url = xbeesUrl + '/kite/' + email;
    }
    
    
    this._popitup(url, 600, 500, 'center', 'Kite', 'front');
    }
    }
    
    this.each(function () {
    if (this.used) {
    return;
    }
    if (options) {
    $.extend(true, settings.statusImages, options.statusImages);
    }
    
    var extension = $(this).attr('extension');
    var serial = $(this).attr('serial');
    
    //Serial can be both serial or subdomain for pbx
    if (extension && extension != '' && serial) {
    $(this).find('.avatar img').attr('src', kiteUrl + '/' + serial + '/' + extension + '/api/avatar');
    
    if (_extensions[serial] == undefined) {
    _extensions[serial] = [];
    }
    _extensions[serial].push(extension);
    this.used = true;
    }
    
    $(this).find('.call a').click(jQuery.proxy(methods._onOpenKite, methods));
    $(this).find('.avatar a').click(jQuery.proxy(methods._onOpenKite, methods));
    });
    
    $.each(_extensions, function (serial, extensions) {
    methods._updatePresence(serial);
    });
    };
    })(jQuery);
    
    jQuery(window).on('load', function () {
    jQuery('.contact').kiteContact();
    });
    </script>
    

Step 2. Customize contact cards

  • To create a custom contact card design, use contact, avatar, call, presence classes:

    <div class="contact" extension="0000" serial="pbxname" email="test@email.com">
    <div class="avatar"> <a href="javascript:void(0)"><img alt="avatar" 
    src="/default-avatar.png" /></a></div>
    <div class="call"><a href="javascript:void(0)">call</a></div>
    <img class="presence" src="images/presence/offline.jpg" align="middle" /></div>
  • Make sure to set the appropriate values to show contact details: 

    extension="0000"
    serial="pbxname"
    email="test@email.com"

Step 3. Link your local presence images

  • To display the contact's presence (online/ offline etc), make sure you replace the URLs in the script with your local files: 

    'online': '/online-1.webp',
    'offline': '/offline.jpeg',
    'talking': '/talking.webp',
    'ringing': '/ringing-now.webp',
    'away': '/away.webp',
    'away-offline': '/awayoffline.jpeg',
    'dnd': '/dnd.webp',
    'dnd-offline': '/dndoffline.webp'