Source: widgets/login/inputfield.js

define('application/widgets/login/inputfield', [
    'rofl/widgets/container',
    'rofl/widgets/input/text',
    'application/widgets/login/password',
    'rofl/widgets/label',
    'rofl/lib/utils',
    'application/events/textvalidatedevent'
], function (
    Container,
    TextInput,
    PasswordInput,
    Label,
    Utils,
    TextValidatedEvent
) {
    'use strict';

    var TYPES = {
            PASSWORD: 'password',
            TEXT: 'text'
        },
        InputField;

    InputField = Container.extend({

        /**
         * Initialises the inputfield widget.
         *
         * @param {Object} config - The configuration.
         * @param {string} config.title - The input title.
         * @param {string} config.type - The input type. TYPES.PASSWORD or TYPES.TEXT.
         * @param {Object} [config.opts] - The options. Optional.
         */
        init: function init (config) {
            var opts = config.opts || {};

            init.base.call(this);

            this._config = config;
            this._validateLength = opts.validateLength;
            this._maxLength = opts.maxLength;
            this._build(config);

            this.addClass('inputfield');
            this._onTextChangeBound = Utils.bind(this._onTextChange, this);
        },

        /**
         * Builds the widget.
         *
         * @param {Object} config - The configuration.
         * @param {string} config.title - The input title.
         * @param {string} config.type - The input type. TYPES.PASSWORD or TYPES.TEXT.
         * @param {Object} [config.opts] - The options. Optional.
         * @private
         */
        _build: function (config) {
            this._buildTitle(config.title || '');
            this._buildInput(config);
            this._buildCursor();
            this._buildCheckmark();
            this._buildFocusBar();
        },

        /**
         * Builds the title.
         *
         * @param {string} text - The text to set.
         * @private
         */
        _buildTitle: function (text) {
            var title = this._title = new Label({ text: text, classNames: ['title'] });

            this.appendChildWidget(title);
        },

        /**
         * Builds the input.
         *
         * @param {Object} config - The configuration.
         * @param {string} config.title - The input title.
         * @param {string} config.type - The input type. TYPES.PASSWORD or TYPES.TEXT.
         * @param {Object} [config.opts] - The options. Optional.
         * @private
         */
        _buildInput: function (config) {
            var type = config.type || TYPES.TEXT,
                input;

            if (type === TYPES.TEXT) {
                input = new TextInput(config.opts);
            } else {
                input = new PasswordInput(config.opts);
            }

            this._input = input;
            input.isFocusable = Utils.bind(this._isInputFocusable, this);

            this.appendChildWidget(input);
        },

        /**
         * Builds a checkmark label.
         *
         * @private
         */
        _buildCheckmark: function () {
            var label = this._checkmark = new Label({ text: 'q', classNames: ['checkmark', 'icon'] });

            this.appendChildWidget(label);
        },

        /**
         * Builds a checkmark label.
         *
         * @private
         */
        _buildCursor: function () {
            var label = this._cursor = new Label({ text: '|', classNames: ['cursor'] });

            this.appendChildWidget(label);
        },

        /**
         * Builds the focus bar.
         *
         * @private
         */
        _buildFocusBar: function () {
            var focusBar = this._focusBar = new Container();

            focusBar.addClass('focusbar');

            this.appendChildWidget(focusBar);
        },

        /**
         * Sets the keyboard to the input.
         *
         * @param {Object} keyboard - The keyboard.
         */
        setKeyboard: function (keyboard) {
            this._input.setKeyboard(keyboard);

            keyboard.addEventListener('textchange', this._onTextChangeBound);
        },

        /**
         * Determines if the input should be validated.
         *
         * @returns {boolean} - True if should be validated.
         * @private
         */
        _shouldValidate: function () {
            return this._validateLength;
        },

        /**
         * TextChange event.
         *
         * @param {Object} e - The event data.
         * @private
         */
        _onTextChange: function (e) {
            var cursor = this._cursor;

            if (e.text.length > 0) {

                cursor.setStyleTo('position', 'none');
                cursor.setStyleTo('left', 'auto');
                cursor.setStyleTo('direction', 'rtl');
            } else if (e.text.length === 0) {
                cursor.setStyleTo('position', 'absolute');
                cursor.setStyleTo('left', '0');
                cursor.setStyleTo('direction', 'ltr');
            }

            if (this._shouldValidate() && e.text.length === this._maxLength) {

                this._checkmark.setStyleTo('display', 'block');
                this.getFocusBar().removeClass('redfocus');

                this.bubbleEvent(new TextValidatedEvent());

            } else {

                this._checkmark.setStyleTo('display', 'none');
            }
        },

        /**
         * Returns false to disable focus on input fields.
         *
         * @returns {boolean} - Focusable. False.
         * @private
         */
        _isInputFocusable: function () {
            return false;
        },

        /**
         * Returns value of the input.
         *
         * @returns {string} - Value of the inupt.
         */
        getValue: function () {
             return this._input.getValue();
        },

        /**
         * Returns cursor.
         *
         * @returns {Object} - Cursor object.
         */
        getCursor: function () {
            return this._cursor;
        },

        /**
         * Returns cursor.
         *
         * @returns {Object} - Cursor object.
         */
        getFocusBar: function () {
            return this._focusBar;
        },

        /**
         * Shows and hides cursor based on timeout.
         */
        showCursorBlink: function () {
            var cursor = this._cursor;

            clearInterval(this._blinkInterval);

            this._blinkInterval = setInterval(function () {

                if (cursor.hasClass('visible')) {
                    cursor.removeClass('visible');
                } else {
                    cursor.addClass('visible');
                }
            }, 500);
        },

        /**
         * Clears timeouts and intervals.
         */
        stopCursorBlink: function () {

            clearInterval(this._blinkInterval);

            this._cursor.removeClass('visible');
        },

         /**
         * Animates focusbar based on timeout.
         */
        animateFocusBar: function () {
            var self = this;

            this._animateTimeout = setTimeout(function () {
                self.getFocusBar().setStyleTo('background-position', 'left bottom');
            }, 800);
        },

        /**
         * Stops the focusbar animation.
         */
        stopFocusbarAnimation: function () {

            clearTimeout(this._animateTimeout);
        }

    });

    InputField.TYPES = TYPES;

    return InputField;
});