Creating widget in ExtJs 6

By | September 14, 2015

Introduction

This post is about creating widget in ExtJs 6. We will create a VOIP controls widget. It will have buttons for starting a Phone call, Audio, Video, Screen sharing and Terminating session.

This ExtJs widget will demonstrate having multiple states icons. We will have a disabled, On/Off or Connected/disconnected states. This widget will also encapsulate functionality to change its internal buttons state. The VOIP control widget will have five custom buttons.

Create custom button widget in ExtJs

We will start with creating a custom widget button. The code to create custom button is given below: –

Ext.define('ExtjsDemo.view.ux.button.ChatButton', {
    extend: 'Ext.button.Button',
    xtype: 'chatbutton',
    iconAlign: 'top',
    scale: 'small',
    iconCls: 'voip-control-icon',
    initComponent: function() {
        this.callParent();
        if (!this.disabled) {
            this.setIcon(this.iconNotSelected);
        }
        this.addIconStyles();
    },
    addIconStyles: function() {
        var id = this.getId();
        Ext.util.CSS.createStyleSheet(
          '#' + id + '.x-btn-pressed .x-btn-icon-el
            {background-image: url(' + this.iconSelected + ') !important;} '
          +
          '#' + id + '.x-btn-menu-active .x-btn-icon-el
            {background-image: url(' + this.iconSelected + ') !important;}'
        );
    }
});

The ChatButton is extended from Ext.button.Button class. Note this control xtype has been defined as “chatbutton“, it will be used for creating an instance of ChatButton type in other widgets or views as needed.

The ChatButton adds two additional styles when addIconStyles function is called on initComponent. When initComponent function is executed it looks for disabled attribute set for the button. If it is not a disabled button when created its icon is set to another attribute iconNotSelected.

Attributes like iconNotSelected, iconSelected, iconDisabled are workaround for setting icons for various states for a button. You will find these attributes definition further down in the post.

The CSS for the above custom button and VOIP control that we are building is given below.

.voip-control-icon {
	height: 27px !important;
	width: 27px !important;
}
a.x-btn.voipControl {
	border: 0 none;
	margin: 0px 0px;
	padding: 0;
}
.voipControl .x-btn-button {
	border-style: none;
	border-width: 0px;
 	border-color: white;
	border-radius: 1px;
	background-color: #FFF;
	height: 59px;
	min-height: 59px;
	min-width: 59px;
	width: 59px;
}
.voipControl .x-btn-icon-el {
	background-position: center;
	background-repeat: no-repeat;
	display: block;
	min-width: 59px;
}
.voipControl .x-btn-inner {
	background-position: center bottom;
	margin: 0;
	color: #000;
}
ChatButton

ChatButton button

Create composite ExtJs widget using custom button

The VoipControl extends from a Ext Panel. It creates a button panel to hold our custom created ChatButton widgets. The code to create VoipControl panel is given below: –

Ext.define('ExtjsDemo.view.contact.connect.VoipControl', {
    extend: 'Ext.panel.Panel',
    requires: ['ExtjsDemo.view.ux.button.ChatButton'],
    xtype: 'voipcontrol',
    id: 'voipControl',
    layout: {
        type: 'hbox',
        align: 'center',
        pack: 'center'
    },
    height: 60,
    width: '100%',
    border: true,
    defaults: {
        width: '60px',
        height: '60px',
        cls: 'voipControl'
    },
    setVoipCall: function(pressed, changeButtonState) {
        var voipButton = this.down('#voipCallButton');
        var muteButton = this.down('#muteButton');
        var videoButton = this.down('#videoButton');
        if (changeButtonState) {
    		voipButton.setPressed(pressed);
    	}
        if (pressed) {
            muteButton.setPressed(false)
               .setDisabled(false)
               .setIcon(muteButton.iconNotSelected);
            videoButton.setPressed(false)
               .setDisabled(false)
               .setIcon(videoButton.iconNotSelected);
        } else {
            muteButton.setPressed(false)
              .setDisabled(true)
              .setIcon(muteButton.iconDisabled);
            videoButton.setPressed(false)
              .setDisabled(true)
              .setIcon(videoButton.iconDisabled);
        }
    },
    setScreenShare: function(pressed) {
        var screenShareButton = this.down('#screenShareButton');
        if (pressed) {
            screenShareButton.setPressed(true);
        } else {
            screenShareButton.setPressed(false);
        }
    },
    items: [{
        xtype: 'chatbutton',
        text: 'Phone',
        name: 'voipCallButton',
        id: 'voipCallButton',
        icon: 'resources/images/btn-phone-off.png',
        iconSelected: 'resources/images/btn-phone-on.png',
        iconNotSelected: 'resources/images/btn-phone-off.png',
        tooltip: 'Phone call',
        enableToggle: true,
        toggleHandler: 'onVoipCallButtonClick'
    }, {
        xtype: 'chatbutton',
        text: 'Audio',
        name: 'muteButton',
        id: 'muteButton',
        icon: 'resources/images/btn-mic-disabled.png',
        iconSelected: 'resources/images/btn-mic-off.png',
        iconNotSelected: 'resources/images/btn-mic-on.png',
        iconDisabled: 'resources/images/btn-mic-disabled.png',
        tooltip: 'Audio ON/OFF',
        disabled: true,
        enableToggle: true,
        toggleHandler: 'onMuteButtonClick'
    }, {
        xtype: 'chatbutton',
        text: 'Video',
        name: 'videoButton',
        id: 'videoButton',
        icon: 'resources/images/btn-camera-disabled.png',
        iconSelected: 'resources/images/btn-camera-on.png',
        iconNotSelected: 'resources/images/btn-camera-off.png',
        iconDisabled: 'resources/images/btn-camera-disabled.png',
        tooltip: 'Video ON/OFF',
        disabled: true,
        enableToggle: true,
        toggleHandler: 'onVideoButtonClick'
    }, {
        xtype: 'chatbutton',
        text: 'Share',
        name: 'screenShareButton',
        id: 'screenShareButton',
        icon: 'resources/images/btn-screenshare-disabled.png',
        iconSelected: 'resources/images/btn-screenshare-on.png',
        iconNotSelected: 'resources/images/btn-screenshare-off.png',
        tooltip: 'Screen share ON/OFF',
        disabled: false,
        enableToggle: true,
        toggleHandler: 'onScreenShareButtonClick'
    }, {
        xtype: 'button',
        text: 'End',
        name: 'terminateSessionButton',
        id: 'terminateSessionButton',
        icon: 'resources/images/btn-close-chat.png',
        iconAlign: 'top',
        iconCls: 'voip-control-icon',
        scale: 'small',
        tooltip: 'Terminate current session',
        handler: 'onTerminateSessionButtonClick'
    }]
});

VoipControl is a composite control built using ChatButtons, the code describe these buttons as voipCallButton, muteButton, videoButton, screenShareButton, terminateSessionButton. This control is built for a custom chat which allows user to connect on VOIP calls with screen share sessions. All the buttons except End has toggle enabled.

The implementation is out of scope for this post and will be added sometime later. It uses WebRtc and a third party platform for collaboration.

If you look into declaration of each of the ChatButtons described in VoipControl, you will find additional attributes like iconSelected, iconNotSelected, iconDisabled. These attributes have Url to different icons and are declared with controls where required.

There are two functions also defined in this control. These functions are primarily changing state of ChatButtons that are declared in the composite control.

Initial connection state of buttons

Default state on chat start

Default state on chat start

When the chat session starts Phone button should be enabled with disconnect state (Red phone icon), Audio, Video should be disabled, Screen share should be enabled but nothing is shared (Red icon), lastly the End button (X button) is enabled for closing chat session.

Chat in connected state with VOIP call enabled

When phone button is clicked it changes state for Audio/Video buttons. On successful connection of VOIP call phone icon changes to its selected icon from not selected one. It also changes state of Audio/Video icons from disabled to enabled and their initial icon are Audio is selected or enabled, Video is not enabled (Not selected).

VOIP call in progress

VOIP call in progress

VOIP call in progress with video

Once VOIP call is in progress you can enable disable video by clicking video button. Clicking this button calls its handler to add or remove video on its toggle state. Toggle state can be determined by another parameter which provides a boolean for button is pressed or not. VoipControl state when video is enabled is given below. Same is when you can have Sharing enabled.

VOIP call with Video

VOIP call with Video

Screen share enabled

Screen share enabled

There is not much of explanation required for the two functions in the VoipControl code. These functions are performing change of state for other controls in the composite control.

Let me know if you need details on using this control in other ExtJs views.