top

Creating New UI Components

Published 2014-10-28 | (Compatible with SDK 3.5,4.5,5.0,5.1 and 2012,2013,2014 models)

This tutorial describes the use of the UI Widgets system for developing UI widgets from scratch. A Label widget and an IconLabel on top of it are created.

** This class will not be supported in 2015.

   All functionalities of AppsFramework are more improved, integrating with CAPH. Therefore Appsframework is not supported since 2015 Smart TV. To use functionalities of Appsframework, refer to here.

Prerequisites

To create applications that run on a TV screen, you need:

  • Samsung TV connected to the Internet
  • SDK or a text editor for creating HTML, JavaScript and CSS files (using Samsung Smart TV SDK is recommended)

Development environment

The UI Widgets system is based on Templates plugin that requires jQuery 1.4.3 or above.

The JavaScript files should be loaded in the following order:

  1. jQuery library
  2. jQuery Templates plugin
  3. API
  4. User files

Use Samsung Smart TV SDK to create the application. You can also use the emulator provided with the SDK to debug and test the application before uploading it in your TV. Later, you can run the application on a TV; see Testing Your Application on a TV. Note that applications may perform better on the TV than on the emulator. You can find general instructions for creating applications in Implementing Your Application Code.

Label Widget

Label is a simple text element with no HTML markup and the text of the Label can be changed. This task describes the implementation of a Label widget. In the task, the example code is first presented, and then explained line by line.

Label Stub

Define the Label in the Ex namespace. It is assumed that Ex namespace is already defined. Using namespaces makes the code clean and less buggy.

1
2
3
4
5
6
7
(function (sf) {
    Ex.Label = sf.ui.widgetFactory({
        widgetName: "exLabel"
    }); // Ex.Label()
    sf.ui.bridge("exLabel", Ex.Label);
    sf.ui.addSelector("exLabel");
}(sf));

The explanation of the code is as follows:

Lines 2-4 Defines the Ex.Label class. The base class is sf.ui.Widget (by default). An argument is passed (literal object) to the factory function. The aim is to fill this object with code describing the Label functionality.
Line 5

Defines the jQuery plugin function, exLabel. Label can now be instantiated in two ways - as a JavaScript object and as a jQuery plugin as shown below.

var label1 = new Ex.Label({ // JavaScript object
    // ...
}, $("#label1")),

label2 = $("#label2").exLabel({ // jQuery plugin
    // ...
});
Line 6

Defines the jQuery custom selector. All the instances of Label widget can be selected using the following code.

var labelInstances = $(":exLabel");

The Ex.Label now has the same functionality as sf.ui.Widget. The following sections describe the customization of Ex.Label.

Base Customization

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Ex.Label = sf.ui.widgetFactory({
    baseCssClass: "ex-label",
    eventNamespace: "exlabel",
    options: {
        textCssClass: "",
        text: "Label"
    },
    templates: {
        text: '<span class="${baseCssClass}-text ${textCssClass}">${text}</span>'
    },
    widgetName: "exLabel"
}); // Ex.Label()

The explanation of the code is as follows:

Line 2 Defines the base CSS class that will be added to each Label.
Line 3 eventNamespace is the namespace suffix added to each event triggered by Label (See event.namespace in jQuery documentation). The convention is to use the lower case of widgetName.
Lines 4-7 Label “public” options that can be read and/or written. The options object is the “public state” of the Label instance.
Lines 8-10 Templates describing how Widget (or its parts) will be rendered.
Line 11 widgetName should be unique for each UI Widget class. It is recommended to use the same string as widgetName, jQuery plugin name in sf.ui.bridge function, and selector in sf.ui.addSelector function.

Create and Destroy

To add create and destroy functionality for the Label instance, add the following code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Ex.Label = sf.ui.widgetFactory({
    ...

    _create: function () {
        this._super();
        this.view.text = $.tmpl(this.templates.text, {
            baseCssClass: this.baseCssClass,
            textCssClass: this.options.textCssClass,
            text: this.options.text
        });
        this.widget().append(this.view.text);
    }, // _create()

    _destroy: function () {
        this.view.text.remove();
    } // destroy()
}); // Ex.Label()

The explanation of the code is as follows:

Lines 4-12 The _create function is called once, when the widget instance is created.
Line 5 Calls the _create function from the base class (sf.ui.Widget). this._super() is the alias for the same function in the base class.
Lines 6-10 Creates a text element and stores it in the view object for future use.
Line 11 Adds text element to DOM.
Lines 14-16 The _destroy function is called when the widget instance is destroyed. Removes whatever was added in the _create function. The this._super() function need not be called as it is empty in the sf.ui.Widget class.

Base Functionality

To add the setter part of option function to cover base functionality of sf.ui.Widget class, add the following function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Ex.Label = sf.ui.widgetFactory({
    ...

    _setOption: function (name, value) {
        switch (name) {
            case 'textCssClass':
                this.setTextCssClass(value);
                break;

            case 'text':
                this.setText(value);
                break;

            default:
                this._super(name, value);
        } // switch(name)
    } // _setOption()
}); // Ex.Label()

The explanation of the code is as follows:

Lines 4-12 _setOption is the setter part of option function.
Lines 6, 10 Write code for actions for the case statements.
Line 14 The default action of the base class.

Additional Functionality

To define the getText, setText, and setTextCssClass functions, add the following code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Ex.Label = sf.ui.widgetFactory({
    ...

    getText: function () {
        return this.options.text;
    }, // getText()

    setText: function (value) {
        value = value || "";
        this.view.text.text(value);
        this.options.text = value;
        return this;
    }, // setText()

    setTextCssClass: function (value) {
        value = value || "";
        if (this.options.textCssClass) {
            this.view.text.removeClass(this.options.textCssClass);
        }
        if (value) {
            this.view.text.addClass(value);
        }
        this.options.textCssClass = value;
        return this;
    } // setTextCssClass()
}); // Ex.Label()

The explanation of the code is as follows:

Lines 4-6 getText is a simple getter function.
Lines 8-13 setText changes the state and view of the Label instance.
Line 9 Validates the value.
Line 10 Updates the text element.
Line 11 Updates the text property.
Lines 15-25 setTextCssClass changes the state and view of the Label instance.
Line 16 Validates the value.
Lines 17-22 Updates the text element.
Line 23 Updates the textCssClass property.

CSS Classes for Label Widget

2 CSS classes are defined.

.ex-label {
    font: bold 12px/16px Verdana;
    height: 16px;
}

.ex-label .ex-label-text {}

The Label widget implementation is now completed.

Label Examples

Example 1: Various Label instances

For this example, an additional CSS class is defined.

Example code 1

.red-label {
    color: #f00;
}
$("#label1").exLabel();
$("#label2").exLabel({
    text: "I am a Label"
});
$("#label3").exLabel({
    text: "I am the Red Label",
    textCssClass: "red-label"
});

Figure. Result

Example 2: Create and Destroy

Example code 2

// Create
$("#label4").exLabel({
    text: "Here I am!"
});

// Destroy
$("#label4").exLabel("destroy");

Example 3: Change Label Properties

Example code 1

// Makes Label instance
$("#label5").exLabel({
    text: "Play with me!"
});

Result 1

Play with me

Example code 2

// Sets text
$("#label5").exLabel("setText", "Text was changed 0 time");
// Sets text ("option" function)
$("#label5").exLabel("option", "text", "Text was changed 0 time");

Figure. Result 2

Example code 3

// Gets text
alert($("#label5").exLabel("getText"));

This message shows in the log window when it is executed in SDK.

Figure. Result 3

Example code 4

// Makes red label
$("#label5").exLabel("setTextCssClass", "red-label");

Result 4

Text was changed 0 time

Example code 5

// Makes normal label
$("#label5").exLabel("setTextCssClass", "");

IconLabel widget

IconLabel is a combination of text and icon. The icon is placed on the left or on the right side of the text. The icon is an image of size 16 x 16 pixels.

This task describes the implementation of a IconLabel widget. It is built on top of the this document.

The additional functionality implemented is the icon of the IconLabel, the image and the alignment of which can be changed. In the task, the example code is first presented, and then explained line by line.

IconLabel Stub

Define IconLabel in the Ex namespace. It is assumed that the Ex namespace is already defined.

1
2
3
4
5
6
7
(function (sf) {
    Ex.IconLabel = sf.ui.widgetFactory(Ex.Label, {
        widgetName: "exIconLabel"
    }); // Ex.IconLabel()
    sf.ui.bridge("exIconLabel", Ex.IconLabel);
    sf.ui.addSelector("exIconLabel");
}(sf));

The explanation of the code is as follows:

Lines 2-4 Defines the Ex.IconLabel class. The base class for this is is Ex.Label. 2 arguments are passed to the factory function. The first is the base class constructor function, Ex.Label, and the second is a literal object. The aim is to fill this object with code describing the IconLabel functionality.
Line 5

Defines the jQuery plugin function, exIconLabel. IconLabel can now be instantiated in 2 ways - as a JavaScript object and as a jQuery plugin as shown in the code below:

var iconlabel1 = new Ex.IconLabel({        // JavaScript object
    // ...
}, $("#iconlabel1")),

iconlabel2 = $("#iconlabel2").exIconLabel({ // jQuery plugin
    // ...
});
Line 6

Defines the jQuery custom selector. All instances of IconLabel widget can be selected using the following code.

var iconLabelInstances = $(":exIconLabel");

Base Customization

IconLabel is derived from Label, so it it possible to use the functionality previously defined.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Ex.IconLabel = sf.ui.widgetFactory(Ex.Label, {
    eventNamespace: "exiconlabel",
    options: {
        text: "Label with Icon",
        icon: "",
        iconAlign: "left"
    },
    templates: {
        icon: '<span class="${baseCssClass}-icon ${baseCssClass}-icon-${iconAlign}    ${icon}" />'
    },
    widgetName: "exIconLabel"
}); // Ex.Label()

The explanation of the code is as follows:

Line 2 Defines the different eventNamespace.
Lines 3-7 IconLabel “public” options that can be read and/or written.
Line 4 Overrides the text property.
Lines 5-6 Defines the new properties.
Lines 8-10 Defines additional template for the icon element.
Line 11 Unique widgetName.

Base CSS class is the same as in Label.

Create and Destroy

To create and destroy the IconLabel, add the following functions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 Ex.IconLabel = sf.ui.widgetFactory(Ex.Label, {
     //...

     _create: function () {
         this._super();
             this.options.iconAlign = this._getValidIconAlign(this.options.iconAlign);
             this.view.icon = $.tmpl(this.templates.icon, {
                 baseCssClass: this.baseCssClass,
                 iconAlign: this.options.iconAlign,
                 icon: this.options.icon
             });
             this.widget().prepend(this.view.icon);
     }, // _create()

     _destroy: function () {
         this.view.icon.remove();
         this._super();
     }, // destroy()

     _isValidIconAlign: function (value) {
         return value === "left" || value === "right";
     }, // _isValidIconAlign()

     _getValidIconAlign: function (value) {
         value = ("" + value).toLowerCase();
         return this._isValidIconAlign(value) ? value : "left";
     } // _getValidIconAlign()
 }); // Ex.Label()

The explanation of the code is as follows:

Lines 4-13 The _create function is called once, when the widget instance is created.
Line 5 Calls the _create function from the base class (Ex.Label).
Line 6 Validates the iconAlign property.
Lines 7-11 Creates the icon element and stores it in the view object for future use.
Line 12 Adds the icon element to DOM.
Lines 15-18 The _destroy function is called when the widget instance is destroyed.
Line 16 Removes the icon element.
Line 17 Calls the _destroy function from base class (Ex.Label).
Lines 20-27 Helper functions to validate the iconAlign property

Destroy the instance element in the reverse order of creation.

Base Functionality

To add the setter part of the option function of Ex.Label class, add the following function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Ex.IconLabel = sf.ui.widgetFactory(Ex.Label, {
    //...
    _setOption: function (name, value) {
    switch (name) {
        case 'icon':
            this.setIcon(value);
            break;

        case 'iconAlign':
            this.setIconAlign(value);
            break;

        default:
            this._super(name, value);
        } // switch(name)
    } // _setOption()
}); // Ex.Label()

The explanation of the code is as follows:

Lines 4-16 _setOption is the setter part of the option function.
Lines 6, 10 Implement actions for the case conditions.
Line 14 The default action.

Additional Functionality

To define the getIcon, setIcon and setIconAlign functions, add the following code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Ex.IconLabel = sf.ui.widgetFactory(Ex.Label, {
    //...

    getIcon: function () {
        return this.options.icon;
    }, // getIcon()

    setIcon: function (value) {
        value = value || "";
        if (this.options.icon) {
            this.view.icon.removeClass(this.options.icon);
        }
        if (value) {
            this.view.icon.addClass(value);
        }
        this.options.icon = value;
        return this;
    }, // setIcon()

    setIconAlign: function (value) {
        value = ("" + value).toLowerCase();
        if (this._isValidIconAlign(value)) {
            this.view.icon.removeClass(this.baseCssClass + "-icon-" + this.options.iconAlign);
            this.options.iconAlign = value;
            this.view.icon.addClass(this.baseCssClass + "-icon-" + this.options.iconAlign);
        }
        return this;
    } // setIconAlign()
}); // Ex.Label()

The explanation of the code is as follows:

Lines 4-6 getIcon is a simple getter function.
Lines 8-18 setIcon changes the state and view of the IconLabel instance.
Line 9 Validates the value.
Lines 10-15 Updates the icon element.
Line 16 Updates the icon property.
Lines 20-28 setIconAlign changes the state and view of the IconLabel instance.
Line 21 Converts the value.
Lines 22-26 If value is valid, update icon element and iconAlign property.

CSS Classes for IconLabel

Define 3 additional CSS classes.

.ex-label .ex-label-icon {
    display: block;
    width: 16px;
    height: 16px;
    background-repeat: no-repeat;
    background-position: 0 0;
}

.ex-label .ex-label-icon-left {
    float: left;
    margin-right: 4px;
}

.ex-label .ex-label-icon-right {
    float: right;
    margin-left: 4px;
}

The implementation of the IconLabel widget is now completed.

IconLabel Examples

Example 1: Various IconLabel Instances

For this example, an additional CSS class is defined.

.book {
    background-image: url("img/book.png");
}

.bomb {
    background-image: url("img/bomb.png");
}

.brick {
    background-image: url("img/brick.png");
}

Example code

$("#iconlabel1").exIconLabel();
$("#iconlabel2").exIconLabel({
    icon: "book"
});

$("#iconlabel3").exIconLabel({
    text: "BOOOMMMM!!!",
    textCssClass: "red-label",
    iconAlign: "right",
    icon: "bomb"
});

$("#iconlabel4").exIconLabel({
    text: "Another brick in the wall",
    icon: "brick"
});

Figure. Result

Example 2: Create and Destroy

Example code

// Create
$("#iconlabel5").exIconLabel({
    text: "Here I am!",
    icon: "book"
});

// Destroy
$("#iconlabel5").exIconLabel("destroy");

Figure. Result

Example 3: Change Label Properties

Example code

// Make IconLabel instance
$("#iconlabel6").exIconLabel({
    text: "Play with me!"
});

// Set text
$("#iconlabel6").exIconLabel("setText", "Your text...");

// Get text
alert($("#iconlabel6").exIconLabel("getText"));

// Set book icon
$("#iconlabel6").exIconLabel("setIcon", "book");

// Set bomb icon
$("#iconlabel6").exIconLabel("option", {
    icon: "bomb",
    text: "Booommmm!!!",
    textCssClass: "red-label"
});

// Set brick icon
$("#iconlabel6").exIconLabel("setIcon", "brick");

// Get icon
alert($("#iconlabel6").exIconLabel("getIcon"));

// Make me red
$("#iconlabel6").exIconLabel("setTextCssClass", "red-label");

// Make me normal
$("#iconlabel6").exIconLabel("setTextCssClass", "");

// Left icon
$("#iconlabel6").exIconLabel("setIconAlign", "left");

// Right icon
$("#iconlabel6").exIconLabel("setIconAlign", "right");